From 85740c2ddbb2aa0d523c997187442385a191fb64 Mon Sep 17 00:00:00 2001 From: Peter Collingbourne Date: Sat, 27 Aug 2011 02:25:57 +0100 Subject: Support for rebuilding and reloading manifest files This introduces support for rebuilding the top-level manifest file using a provided build statement, and reloading it before building the user-requested targets. --- doc/manual.asciidoc | 4 ++++ src/build_log.h | 1 + src/ninja.cc | 29 +++++++++++++++++++++++++++++ 3 files changed, 34 insertions(+) diff --git a/doc/manual.asciidoc b/doc/manual.asciidoc index 112aac5..8ab2195 100644 --- a/doc/manual.asciidoc +++ b/doc/manual.asciidoc @@ -253,6 +253,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* 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 targets; if (!CollectTargetsFromArgs(&state, argc, argv, &targets, &err)) { Error("%s", err.c_str()); -- cgit v0.12