summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEvan Martin <martine@danga.com>2011-09-06 21:01:17 (GMT)
committerEvan Martin <martine@danga.com>2011-09-06 21:01:17 (GMT)
commit2e8d3c48c4a53b8f567b1a4c3b6aae85f11b5e2e (patch)
tree765baf723a3e42a130d3c76197f6504f66832ca2
parent46d1b2cef311e4f58807727339dbe1a41b5df554 (diff)
parent85740c2ddbb2aa0d523c997187442385a191fb64 (diff)
downloadNinja-2e8d3c48c4a53b8f567b1a4c3b6aae85f11b5e2e.zip
Ninja-2e8d3c48c4a53b8f567b1a4c3b6aae85f11b5e2e.tar.gz
Ninja-2e8d3c48c4a53b8f567b1a4c3b6aae85f11b5e2e.tar.bz2
Merge pull request #91 from pcc/reload-manifest
Support for rebuilding and reloading manifest files
-rw-r--r--doc/manual.asciidoc4
-rw-r--r--src/build_log.h1
-rw-r--r--src/ninja.cc29
3 files changed, 34 insertions, 0 deletions
diff --git a/doc/manual.asciidoc b/doc/manual.asciidoc
index 86afc09..9506f0c 100644
--- a/doc/manual.asciidoc
+++ b/doc/manual.asciidoc
@@ -256,6 +256,10 @@ statement to the rule (for example, if the rule needs "the file
extension of the first input"), pass that through as an extra
variable, like how `cflags` is passed above.
+If the top-level Ninja file is specified as an output of any build
+statement and it is out of date, Ninja will rebuild and reload it
+before building the targets requested by the user.
+
The `phony` rule
~~~~~~~~~~~~~~~~
diff --git a/src/build_log.h b/src/build_log.h
index 81a745f..f45cbde 100644
--- a/src/build_log.h
+++ b/src/build_log.h
@@ -32,6 +32,7 @@ struct Edge;
/// from it
struct BuildLog {
BuildLog();
+ ~BuildLog() { Close(); }
void SetConfig(BuildConfig* config) { config_ = config; }
bool OpenForWrite(const string& path, string* err);
diff --git a/src/ninja.cc b/src/ninja.cc
index 8f972f3..cdaab3a 100644
--- a/src/ninja.cc
+++ b/src/ninja.cc
@@ -109,6 +109,21 @@ struct RealFileReader : public ManifestParser::FileReader {
}
};
+bool RebuildManifest(State* state, const BuildConfig& config,
+ const char* input_file, string* err) {
+ string path = input_file;
+ CanonicalizePath(&path);
+ Node* node = state->LookupNode(path);
+ if (!node)
+ return false;
+
+ Builder manifest_builder(state, config);
+ if (!manifest_builder.AddTarget(node, err))
+ return false;
+
+ return manifest_builder.Build(err);
+}
+
bool CollectTargetsFromArgs(State* state, int argc, char* argv[],
vector<Node*>* targets, string* err) {
if (argc == 0) {
@@ -398,6 +413,9 @@ int main(int argc, char** argv) {
}
}
+ bool rebuilt_manifest = false;
+
+reload:
State state;
RealFileReader file_reader;
ManifestParser parser(&state, &file_reader);
@@ -450,6 +468,17 @@ int main(int argc, char** argv) {
return 1;
}
+ if (!rebuilt_manifest) { // Don't get caught in an infinite loop by a rebuild
+ // target that is never up to date.
+ if (RebuildManifest(&state, config, input_file, &err)) {
+ rebuilt_manifest = true;
+ goto reload;
+ } else if (!err.empty()) {
+ Error("rebuilding '%s': %s", input_file, err.c_str());
+ return 1;
+ }
+ }
+
vector<Node*> targets;
if (!CollectTargetsFromArgs(&state, argc, argv, &targets, &err)) {
Error("%s", err.c_str());