From 144a24dcdcbb075d60d31171e0bda0654e613287 Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 19 Sep 2016 15:49:13 -0400 Subject: [PATCH 1/2] cmGlobalNinjaGenerator: Teach WriteBuild about implicit outputs Ninja 1.7 introduced support for implicit outputs on build statements. Teach WriteBuild to generate the corresponding syntax. Leave it up to callers to decide whether implicit outputs are supported by the Ninja version in use. For now simply update all call sites to pass an empty list of implicit outputs. --- Source/cmGlobalNinjaGenerator.cxx | 27 ++++++++++++++++++------- Source/cmGlobalNinjaGenerator.h | 1 + Source/cmNinjaNormalTargetGenerator.cxx | 9 ++++++--- Source/cmNinjaTargetGenerator.cxx | 5 +++-- 4 files changed, 30 insertions(+), 12 deletions(-) diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx index bd65366da..c74baa180 100644 --- a/Source/cmGlobalNinjaGenerator.cxx +++ b/Source/cmGlobalNinjaGenerator.cxx @@ -140,10 +140,10 @@ std::string cmGlobalNinjaGenerator::EncodeDepfileSpace(const std::string& path) void cmGlobalNinjaGenerator::WriteBuild( std::ostream& os, const std::string& comment, const std::string& rule, - const cmNinjaDeps& outputs, const cmNinjaDeps& explicitDeps, - const cmNinjaDeps& implicitDeps, const cmNinjaDeps& orderOnlyDeps, - const cmNinjaVars& variables, const std::string& rspfile, int cmdLineLimit, - bool* usedResponseFile) + const cmNinjaDeps& outputs, const cmNinjaDeps& implicitOuts, + const cmNinjaDeps& explicitDeps, const cmNinjaDeps& implicitDeps, + const cmNinjaDeps& orderOnlyDeps, const cmNinjaVars& variables, + const std::string& rspfile, int cmdLineLimit, bool* usedResponseFile) { // Make sure there is a rule. if (rule.empty()) { @@ -204,6 +204,13 @@ void cmGlobalNinjaGenerator::WriteBuild( this->CombinedBuildOutputs.insert(EncodePath(*i)); } } + if (!implicitOuts.empty()) { + build += " |"; + for (cmNinjaDeps::const_iterator i = implicitOuts.begin(); + i != implicitOuts.end(); ++i) { + build += " " + EncodeIdent(EncodePath(*i), os); + } + } build += ":"; // Write the rule. @@ -244,7 +251,8 @@ void cmGlobalNinjaGenerator::WritePhonyBuild( const cmNinjaDeps& explicitDeps, const cmNinjaDeps& implicitDeps, const cmNinjaDeps& orderOnlyDeps, const cmNinjaVars& variables) { - this->WriteBuild(os, comment, "phony", outputs, explicitDeps, implicitDeps, + this->WriteBuild(os, comment, "phony", outputs, + /*implicitOuts=*/cmNinjaDeps(), explicitDeps, implicitDeps, orderOnlyDeps, variables); } @@ -288,7 +296,8 @@ void cmGlobalNinjaGenerator::WriteCustomCommandBuild( vars["depfile"] = depfile; } this->WriteBuild(*this->BuildFileStream, comment, "CUSTOM_COMMAND", outputs, - deps, cmNinjaDeps(), orderOnly, vars); + /*implicitOuts=*/cmNinjaDeps(), deps, cmNinjaDeps(), + orderOnly, vars); if (this->ComputingUnknownDependencies) { // we need to track every dependency that comes in, since we are trying @@ -330,7 +339,8 @@ void cmGlobalNinjaGenerator::WriteMacOSXContentBuild(const std::string& input, cmNinjaVars vars; this->WriteBuild(*this->BuildFileStream, "", "COPY_OSX_CONTENT", outputs, - deps, cmNinjaDeps(), cmNinjaDeps(), cmNinjaVars()); + /*implicitOuts=*/cmNinjaDeps(), deps, cmNinjaDeps(), + cmNinjaDeps(), cmNinjaVars()); } void cmGlobalNinjaGenerator::WriteRule( @@ -1271,6 +1281,7 @@ void cmGlobalNinjaGenerator::WriteTargetRebuildManifest(std::ostream& os) this->WriteBuild(os, "Re-run CMake if any of its inputs changed.", "RERUN_CMAKE", /*outputs=*/cmNinjaDeps(1, ninjaBuildFile), + /*implicitOuts=*/cmNinjaDeps(), /*explicitDeps=*/cmNinjaDeps(), implicitDeps, /*orderOnlyDeps=*/cmNinjaDeps(), variables); @@ -1308,6 +1319,7 @@ void cmGlobalNinjaGenerator::WriteTargetClean(std::ostream& os) /*generator=*/false); WriteBuild(os, "Clean all the built files.", "CLEAN", /*outputs=*/cmNinjaDeps(1, this->NinjaOutputPath("clean")), + /*implicitOuts=*/cmNinjaDeps(), /*explicitDeps=*/cmNinjaDeps(), /*implicitDeps=*/cmNinjaDeps(), /*orderOnlyDeps=*/cmNinjaDeps(), @@ -1327,6 +1339,7 @@ void cmGlobalNinjaGenerator::WriteTargetHelp(std::ostream& os) /*generator=*/false); WriteBuild(os, "Print all primary targets available.", "HELP", /*outputs=*/cmNinjaDeps(1, this->NinjaOutputPath("help")), + /*implicitOuts=*/cmNinjaDeps(), /*explicitDeps=*/cmNinjaDeps(), /*implicitDeps=*/cmNinjaDeps(), /*orderOnlyDeps=*/cmNinjaDeps(), diff --git a/Source/cmGlobalNinjaGenerator.h b/Source/cmGlobalNinjaGenerator.h index a0fad644b..d8eddd012 100644 --- a/Source/cmGlobalNinjaGenerator.h +++ b/Source/cmGlobalNinjaGenerator.h @@ -106,6 +106,7 @@ public: */ void WriteBuild(std::ostream& os, const std::string& comment, const std::string& rule, const cmNinjaDeps& outputs, + const cmNinjaDeps& implicitOuts, const cmNinjaDeps& explicitDeps, const cmNinjaDeps& implicitDeps, const cmNinjaDeps& orderOnlyDeps, diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx index f87a7883d..dbd84cb2b 100644 --- a/Source/cmNinjaNormalTargetGenerator.cxx +++ b/Source/cmNinjaNormalTargetGenerator.cxx @@ -691,7 +691,8 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() // Write the build statement for this target. bool usedResponseFile = false; globalGen.WriteBuild(this->GetBuildFileStream(), comment.str(), - this->LanguageLinkerRule(), outputs, explicitDeps, + this->LanguageLinkerRule(), outputs, + /*implicitOuts=*/cmNinjaDeps(), explicitDeps, implicitDeps, orderOnlyDeps, vars, rspfile, commandLineLengthLimit, &usedResponseFile); this->WriteLinkRule(usedResponseFile); @@ -702,7 +703,8 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() this->GetBuildFileStream(), "Create executable symlink " + targetOutput, "CMAKE_SYMLINK_EXECUTABLE", cmNinjaDeps(1, targetOutput), - cmNinjaDeps(1, targetOutputReal), emptyDeps, emptyDeps, symlinkVars); + /*implicitOuts=*/cmNinjaDeps(), cmNinjaDeps(1, targetOutputReal), + emptyDeps, emptyDeps, symlinkVars); } else { cmNinjaDeps symlinks; std::string const soName = @@ -717,7 +719,8 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() symlinks.push_back(targetOutput); globalGen.WriteBuild( this->GetBuildFileStream(), "Create library symlink " + targetOutput, - "CMAKE_SYMLINK_LIBRARY", symlinks, cmNinjaDeps(1, targetOutputReal), + "CMAKE_SYMLINK_LIBRARY", symlinks, + /*implicitOuts=*/cmNinjaDeps(), cmNinjaDeps(1, targetOutputReal), emptyDeps, emptyDeps, symlinkVars); } } diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index 6ac59d576..fb09bfe25 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -607,8 +607,9 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( std::string const rspfile = objectFileName + ".rsp"; this->GetGlobalGenerator()->WriteBuild( - this->GetBuildFileStream(), comment, rule, outputs, explicitDeps, - implicitDeps, orderOnlyDeps, vars, rspfile, commandLineLengthLimit); + this->GetBuildFileStream(), comment, rule, outputs, + /*implicitOuts=*/cmNinjaDeps(), explicitDeps, implicitDeps, orderOnlyDeps, + vars, rspfile, commandLineLengthLimit); if (const char* objectOutputs = source->GetProperty("OBJECT_OUTPUTS")) { std::vector outputList; From 501f9c93671cdbed546bb92382240cc704cf6e6a Mon Sep 17 00:00:00 2001 From: Brad King Date: Mon, 19 Sep 2016 16:27:21 -0400 Subject: [PATCH 2/2] cmGlobalNinjaGenerator: Add API to check for implicit outputs support Ninja 1.7 introduced support for implicit outputs on build statements. Add an internal API to check whether the Ninja version in use for the build supports this feature. --- Source/cmGlobalNinjaGenerator.cxx | 7 +++++++ Source/cmGlobalNinjaGenerator.h | 2 ++ 2 files changed, 9 insertions(+) diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx index c74baa180..b9136219f 100644 --- a/Source/cmGlobalNinjaGenerator.cxx +++ b/Source/cmGlobalNinjaGenerator.cxx @@ -1306,6 +1306,13 @@ bool cmGlobalNinjaGenerator::SupportsConsolePool() const RequiredNinjaVersionForConsolePool().c_str()); } +bool cmGlobalNinjaGenerator::SupportsImplicitOuts() const +{ + return !cmSystemTools::VersionCompare( + cmSystemTools::OP_LESS, this->NinjaVersion.c_str(), + this->RequiredNinjaVersionForImplicitOuts().c_str()); +} + void cmGlobalNinjaGenerator::WriteTargetClean(std::ostream& os) { WriteRule(*this->RulesFileStream, "CLEAN", ninjaCmd() + " -t clean", diff --git a/Source/cmGlobalNinjaGenerator.h b/Source/cmGlobalNinjaGenerator.h index d8eddd012..02016859d 100644 --- a/Source/cmGlobalNinjaGenerator.h +++ b/Source/cmGlobalNinjaGenerator.h @@ -339,7 +339,9 @@ public: // Ninja generator uses 'deps' and 'msvc_deps_prefix' introduced in 1.3 static std::string RequiredNinjaVersion() { return "1.3"; } static std::string RequiredNinjaVersionForConsolePool() { return "1.5"; } + static std::string RequiredNinjaVersionForImplicitOuts() { return "1.7"; } bool SupportsConsolePool() const; + bool SupportsImplicitOuts() const; std::string NinjaOutputPath(std::string const& path); bool HasOutputPathPrefix() const { return !this->OutputPathPrefix.empty(); }