Skip to content

Commit

Permalink
v1.4.0
Browse files Browse the repository at this point in the history
  • Loading branch information
evmar committed Sep 12, 2013
2 parents 045d008 + 6f7ea46 commit 63d5b10
Show file tree
Hide file tree
Showing 31 changed files with 813 additions and 215 deletions.
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,16 @@ TAGS
/doc/manual.html
/doc/doxygen
/gtest-1.6.0
*.patch

# Eclipse project files
.project
.cproject

# SublimeText project files
*.sublime-project
*.sublime-workspace

# Ninja output
.ninja_deps
.ninja_log
18 changes: 14 additions & 4 deletions RELEASING
Original file line number Diff line number Diff line change
@@ -1,12 +1,22 @@
Notes to myself on all the steps to make for a Ninja release.

Push new release branch:
1. update src/version.cc with new version (with ".git")
2. git checkout release; git merge master
3. fix version number in src/version.cc (it will likely conflict in the above)
4. fix version in doc/manual.asciidoc
5. rebuild manual, put in place on website
6. commit, tag, push (don't forget to push --tags)
7. construct release notes from prior notes
5. commit, tag, push (don't forget to push --tags)
6. construct release notes from prior notes
credits: git shortlog -s --no-merges REV..
8. update home page mention of latest version.

Release on github:
1. (haven't tried this yet)
https://github.com/blog/1547-release-your-software

Make announcement on mailing list:
1. copy old mail

Update website:
(note to self: website is now in github.com/martine/martine.github.io)
1. rebuild manual, put in place on website
2. update home page mention of latest version.
6 changes: 3 additions & 3 deletions bootstrap.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
help='target platform (' + '/'.join(platform_helper.platforms()) + ')',
choices=platform_helper.platforms())
parser.add_option('--force-pselect', action='store_true',
help="ppoll() is used by default on Linux and OpenBSD, but older versions might need to use pselect instead",)
help="ppoll() is used by default on Linux, OpenBSD and Bitrig, but older versions might need to use pselect instead",)
(options, conf_args) = parser.parse_args()


Expand All @@ -53,7 +53,7 @@ def run(*args, **kwargs):
# g++ call as well as in the later configure.py.
cflags = os.environ.get('CFLAGS', '').split()
ldflags = os.environ.get('LDFLAGS', '').split()
if platform.is_freebsd() or platform.is_openbsd():
if platform.is_freebsd() or platform.is_openbsd() or platform.is_bitrig():
cflags.append('-I/usr/local/include')
ldflags.append('-L/usr/local/lib')

Expand Down Expand Up @@ -109,7 +109,7 @@ def run(*args, **kwargs):
cflags.append('-D_WIN32_WINNT=0x0501')
if options.x64:
cflags.append('-m64')
if (platform.is_linux() or platform.is_openbsd()) and not options.force_pselect:
if (platform.is_linux() or platform.is_openbsd() or platform.is_bitrig()) and not options.force_pselect:
cflags.append('-DUSE_PPOLL')
if options.force_pselect:
conf_args.append("--force-pselect")
Expand Down
6 changes: 3 additions & 3 deletions configure.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
help='use EXE as the Python interpreter',
default=os.path.basename(sys.executable))
parser.add_option('--force-pselect', action='store_true',
help="ppoll() is used by default on Linux and OpenBSD, but older versions might need to use pselect instead",)
help="ppoll() is used by default where available, but some platforms may need to use pselect instead",)
(options, args) = parser.parse_args()
if args:
print('ERROR: extra unparsed command-line arguments:', args)
Expand Down Expand Up @@ -165,7 +165,7 @@ def binary(name):
cflags.append('-fno-omit-frame-pointer')
libs.extend(['-Wl,--no-as-needed', '-lprofiler'])

if (platform.is_linux() or platform.is_openbsd()) and not options.force_pselect:
if (platform.is_linux() or platform.is_openbsd() or platform.is_bitrig()) and not options.force_pselect:
cflags.append('-DUSE_PPOLL')

def shell_escape(str):
Expand Down Expand Up @@ -263,12 +263,12 @@ def has_re2c():
for name in ['build',
'build_log',
'clean',
'debug_flags',
'depfile_parser',
'deps_log',
'disk_interface',
'edit_distance',
'eval_env',
'explain',
'graph',
'graphviz',
'lexer',
Expand Down
8 changes: 6 additions & 2 deletions doc/manual.asciidoc
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Ninja
=====
Evan Martin <martine@danga.com>
v1.3.0, May 2013
v1.4.0, September 2013


Introduction
Expand Down Expand Up @@ -55,7 +55,7 @@ Here are the design goals of Ninja:
higher-level build systems have different opinions about how code
should be built; for example, should built objects live alongside
the sources or should all build output go into a separate directory?
Is there an "package" rule that builds a distributable package of
Is there a "package" rule that builds a distributable package of
the project? Sidestep these decisions by trying to allow either to
be implemented, rather than choosing, even if that results in
more verbosity.
Expand Down Expand Up @@ -589,6 +589,7 @@ rule cc
command = cl /showIncludes -c $in /Fo$out
----
[[ref_pool]]
Pools
~~~~~

Expand Down Expand Up @@ -669,6 +670,9 @@ A file is a series of declarations. A declaration can be one of:
+include _path_+. The difference between these is explained below
<<ref_scope,in the discussion about scoping>>.
6. A pool declaration, which looks like +pool _poolname_+. Pools are explained
<<ref_pool, in the section on pools>>.
Lexical syntax
~~~~~~~~~~~~~~

Expand Down
8 changes: 6 additions & 2 deletions platform_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

def platforms():
return ['linux', 'darwin', 'freebsd', 'openbsd', 'solaris', 'sunos5',
'mingw', 'msvc', 'gnukfreebsd8']
'mingw', 'msvc', 'gnukfreebsd8', 'bitrig']

class Platform( object ):
def __init__( self, platform):
Expand All @@ -41,7 +41,8 @@ def __init__( self, platform):
self._platform = 'mingw'
elif self._platform.startswith('win'):
self._platform = 'msvc'

elif self._platform.startswith('bitrig'):
self._platform = 'bitrig'

def platform(self):
return self._platform
Expand Down Expand Up @@ -69,3 +70,6 @@ def is_openbsd(self):

def is_sunos5(self):
return self._platform == 'sunos5'

def is_bitrig(self):
return self._platform == 'bitrig'
58 changes: 31 additions & 27 deletions src/build.cc
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#endif

#include "build_log.h"
#include "debug_flags.h"
#include "depfile_parser.h"
#include "deps_log.h"
#include "disk_interface.h"
Expand Down Expand Up @@ -408,38 +409,32 @@ void Plan::CleanNode(DependencyScan* scan, Node* node) {
if (want_i == want_.end() || !want_i->second)
continue;

// Don't attempt to clean an edge if it failed to load deps.
if ((*ei)->deps_missing_)
continue;

// If all non-order-only inputs for this edge are now clean,
// we might have changed the dirty state of the outputs.
vector<Node*>::iterator
begin = (*ei)->inputs_.begin(),
end = (*ei)->inputs_.end() - (*ei)->order_only_deps_;
if (find_if(begin, end, mem_fun(&Node::dirty)) == end) {
// Recompute most_recent_input and command.
// Recompute most_recent_input.
Node* most_recent_input = NULL;
for (vector<Node*>::iterator ni = begin; ni != end; ++ni) {
if (!most_recent_input || (*ni)->mtime() > most_recent_input->mtime())
most_recent_input = *ni;
}
string command = (*ei)->EvaluateCommand(true);

// Now, recompute the dirty state of each output.
bool all_outputs_clean = true;
for (vector<Node*>::iterator ni = (*ei)->outputs_.begin();
ni != (*ei)->outputs_.end(); ++ni) {
if (!(*ni)->dirty())
continue;

if (scan->RecomputeOutputDirty(*ei, most_recent_input, 0,
command, *ni)) {
(*ni)->MarkDirty();
all_outputs_clean = false;
} else {

// Now, this edge is dirty if any of the outputs are dirty.
// If the edge isn't dirty, clean the outputs and mark the edge as not
// wanted.
if (!scan->RecomputeOutputsDirty(*ei, most_recent_input)) {
for (vector<Node*>::iterator ni = (*ei)->outputs_.begin();
ni != (*ei)->outputs_.end(); ++ni) {
CleanNode(scan, *ni);
}
}

// If we cleaned all outputs, mark the node as not wanted.
if (all_outputs_clean) {
want_i->second = false;
--wanted_edges_;
if (!(*ei)->is_phony())
Expand Down Expand Up @@ -641,7 +636,10 @@ bool Builder::Build(string* err) {
}

--pending_commands;
FinishCommand(&result);
if (!FinishCommand(&result, err)) {
status_->BuildFinished();
return false;
}

if (!result.success()) {
if (failures_allowed)
Expand Down Expand Up @@ -704,7 +702,7 @@ bool Builder::StartEdge(Edge* edge, string* err) {
return true;
}

void Builder::FinishCommand(CommandRunner::Result* result) {
bool Builder::FinishCommand(CommandRunner::Result* result, string* err) {
METRIC_RECORD("FinishCommand");

Edge* edge = result->edge;
Expand Down Expand Up @@ -733,7 +731,7 @@ void Builder::FinishCommand(CommandRunner::Result* result) {

// The rest of this function only applies to successful commands.
if (!result->success())
return;
return true;

// Restat the edge outputs, if necessary.
TimeStamp restat_mtime = 0;
Expand Down Expand Up @@ -763,7 +761,7 @@ void Builder::FinishCommand(CommandRunner::Result* result) {
}

string depfile = edge->GetBinding("depfile");
if (restat_mtime != 0 && !depfile.empty()) {
if (restat_mtime != 0 && deps_type.empty() && !depfile.empty()) {
TimeStamp depfile_mtime = disk_interface_->Stat(depfile);
if (depfile_mtime > restat_mtime)
restat_mtime = depfile_mtime;
Expand All @@ -779,21 +777,27 @@ void Builder::FinishCommand(CommandRunner::Result* result) {

// Delete any left over response file.
string rspfile = edge->GetBinding("rspfile");
if (!rspfile.empty())
if (!rspfile.empty() && !g_keep_rsp)
disk_interface_->RemoveFile(rspfile);

if (scan_.build_log()) {
scan_.build_log()->RecordCommand(edge, start_time, end_time,
restat_mtime);
if (!scan_.build_log()->RecordCommand(edge, start_time, end_time,
restat_mtime)) {
*err = string("Error writing to build log: ") + strerror(errno);
return false;
}
}

if (!deps_type.empty() && !config_.dry_run) {
assert(edge->outputs_.size() == 1 && "should have been rejected by parser");
Node* out = edge->outputs_[0];
TimeStamp deps_mtime = disk_interface_->Stat(out->path());
scan_.deps_log()->RecordDeps(out, deps_mtime, deps_nodes);
if (!scan_.deps_log()->RecordDeps(out, deps_mtime, deps_nodes)) {
*err = string("Error writing to deps log: ") + strerror(errno);
return false;
}
}

return true;
}

bool Builder::ExtractDeps(CommandRunner::Result* result,
Expand Down
7 changes: 5 additions & 2 deletions src/build.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ struct Plan {
Edge* FindWork();

/// Returns true if there's more work to be done.
bool more_to_do() const { return wanted_edges_; }
bool more_to_do() const { return wanted_edges_ > 0 && command_edges_ > 0; }

/// Dumps the current state of the plan.
void Dump();
Expand Down Expand Up @@ -163,7 +163,10 @@ struct Builder {
bool Build(string* err);

bool StartEdge(Edge* edge, string* err);
void FinishCommand(CommandRunner::Result* result);

/// Update status ninja logs following a command termination.
/// @return false if the build can not proceed further due to a fatal error.
bool FinishCommand(CommandRunner::Result* result, string* err);

/// Used for tests.
void SetBuildLog(BuildLog* log) {
Expand Down
Loading

0 comments on commit 63d5b10

Please sign in to comment.