summaryrefslogtreecommitdiffstats
path: root/Source
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2015-03-20 20:43:21 (GMT)
committerBrad King <brad.king@kitware.com>2015-03-20 21:40:12 (GMT)
commitbd9c7f9b2c788f9bf69c2ce4eb93d27212a6dfaa (patch)
tree8b089b3e0b7a47ed5adfc0c7a1b3a9abc8a175b0 /Source
parented8e30b00d032594fbb67d62f8bd4319ae6e5907 (diff)
downloadCMake-bd9c7f9b2c788f9bf69c2ce4eb93d27212a6dfaa.zip
CMake-bd9c7f9b2c788f9bf69c2ce4eb93d27212a6dfaa.tar.gz
CMake-bd9c7f9b2c788f9bf69c2ce4eb93d27212a6dfaa.tar.bz2
Ninja: Add policy to require explicit custom command byproducts
Add policy CMP0058 to avoid generating 'phony' ninja rules for unknown custom command dependencies. This requires projects to specify their custom command byproducts explicitly. With this requirement we no longer have to assume that unknown custom command dependencies are generated and can instead simply assume they are source files expected to exist when the build starts. This is particularly important in in-source builds. It is also helpful for out-of-source builds to allow Ninja to diagnose missing files before running custom command rules that depend on them.
Diffstat (limited to 'Source')
-rw-r--r--Source/cmGlobalNinjaGenerator.cxx61
-rw-r--r--Source/cmGlobalNinjaGenerator.h5
-rw-r--r--Source/cmPolicies.cxx5
-rw-r--r--Source/cmPolicies.h1
4 files changed, 66 insertions, 6 deletions
diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx
index 6c612ab..f74f1e0 100644
--- a/Source/cmGlobalNinjaGenerator.cxx
+++ b/Source/cmGlobalNinjaGenerator.cxx
@@ -17,6 +17,7 @@
#include "cmLocalNinjaGenerator.h"
#include "cmMakefile.h"
#include "cmVersion.h"
+#include "cmAlgorithms.h"
#include <algorithm>
#include <assert.h>
@@ -183,7 +184,10 @@ void cmGlobalNinjaGenerator::WriteBuild(std::ostream& os,
i != outputs.end(); ++i)
{
build += " " + EncodeIdent(EncodePath(*i), os);
- this->CombinedBuildOutputs.insert( EncodePath(*i) );
+ if (this->ComputingUnknownDependencies)
+ {
+ this->CombinedBuildOutputs.insert( EncodePath(*i) );
+ }
}
build += ":";
@@ -281,11 +285,14 @@ cmGlobalNinjaGenerator::WriteCustomCommandBuild(const std::string& command,
orderOnly,
vars);
- //we need to track every dependency that comes in, since we are trying
- //to find dependencies that are side effects of build commands
- for(cmNinjaDeps::const_iterator i = deps.begin(); i != deps.end(); ++i)
+ if (this->ComputingUnknownDependencies)
{
- this->CombinedCustomCommandExplicitDependencies.insert( EncodePath(*i) );
+ //we need to track every dependency that comes in, since we are trying
+ //to find dependencies that are side effects of build commands
+ for(cmNinjaDeps::const_iterator i = deps.begin(); i != deps.end(); ++i)
+ {
+ this->CombinedCustomCommandExplicitDependencies.insert(EncodePath(*i));
+ }
}
}
@@ -477,6 +484,8 @@ cmGlobalNinjaGenerator::cmGlobalNinjaGenerator()
, CompileCommandsStream(0)
, Rules()
, AllDependencies()
+ , ComputingUnknownDependencies(false)
+ , PolicyCMP0058(cmPolicies::WARN)
{
// // Ninja is not ported to non-Unix OS yet.
// this->ForceUnixPaths = true;
@@ -510,6 +519,13 @@ void cmGlobalNinjaGenerator::Generate()
this->OpenBuildFileStream();
this->OpenRulesFileStream();
+ this->PolicyCMP0058 =
+ this->LocalGenerators[0]->GetMakefile()
+ ->GetPolicyStatus(cmPolicies::CMP0058);
+ this->ComputingUnknownDependencies =
+ (this->PolicyCMP0058 == cmPolicies::OLD ||
+ this->PolicyCMP0058 == cmPolicies::WARN);
+
this->cmGlobalGenerator::Generate();
this->WriteAssumedSourceDependencies();
@@ -955,6 +971,11 @@ void cmGlobalNinjaGenerator::WriteTargetAliases(std::ostream& os)
void cmGlobalNinjaGenerator::WriteUnknownExplicitDependencies(std::ostream& os)
{
+ if (!this->ComputingUnknownDependencies)
+ {
+ return;
+ }
+
// We need to collect the set of known build outputs.
// Start with those generated by WriteBuild calls.
// No other method needs this so we can take ownership
@@ -1047,9 +1068,11 @@ void cmGlobalNinjaGenerator::WriteUnknownExplicitDependencies(std::ostream& os)
knownDependencies.end(),
std::back_inserter(unknownExplicitDepends));
-
std::string const rootBuildDirectory =
this->GetCMakeInstance()->GetHomeOutputDirectory();
+ bool const inSourceBuild =
+ (rootBuildDirectory == this->GetCMakeInstance()->GetHomeDirectory());
+ std::vector<std::string> warnExplicitDepends;
for (std::vector<std::string>::const_iterator
i = unknownExplicitDepends.begin();
i != unknownExplicitDepends.end();
@@ -1067,8 +1090,34 @@ void cmGlobalNinjaGenerator::WriteUnknownExplicitDependencies(std::ostream& os)
"",
deps,
cmNinjaDeps());
+ if (this->PolicyCMP0058 == cmPolicies::WARN &&
+ !inSourceBuild && warnExplicitDepends.size() < 10)
+ {
+ warnExplicitDepends.push_back(*i);
+ }
}
}
+
+ if (!warnExplicitDepends.empty())
+ {
+ std::ostringstream w;
+ w <<
+ (this->GetCMakeInstance()->GetPolicies()->
+ GetPolicyWarning(cmPolicies::CMP0058)) << "\n"
+ "This project specifies custom command DEPENDS on files "
+ "in the build tree that are not specified as the OUTPUT or "
+ "BYPRODUCTS of any add_custom_command or add_custom_target:\n"
+ " " << cmJoin(warnExplicitDepends, "\n ") <<
+ "\n"
+ "For compatibility with versions of CMake that did not have "
+ "the BYPRODUCTS option, CMake is generating phony rules for "
+ "such files to convince 'ninja' to build."
+ "\n"
+ "Project authors should add the missing BYPRODUCTS or OUTPUT "
+ "options to the custom commands that produce these files."
+ ;
+ this->GetCMakeInstance()->IssueMessage(cmake::AUTHOR_WARNING, w.str());
+ }
}
void cmGlobalNinjaGenerator::WriteBuiltinTargets(std::ostream& os)
diff --git a/Source/cmGlobalNinjaGenerator.h b/Source/cmGlobalNinjaGenerator.h
index 3f6af6c..6aa76f9 100644
--- a/Source/cmGlobalNinjaGenerator.h
+++ b/Source/cmGlobalNinjaGenerator.h
@@ -368,6 +368,11 @@ private:
/// The set of custom command outputs we have seen.
std::set<std::string> CustomCommandOutputs;
+ /// Whether we are collecting known build outputs and needed
+ /// dependencies to determine unknown dependencies.
+ bool ComputingUnknownDependencies;
+ cmPolicies::PolicyStatus PolicyCMP0058;
+
/// The combined explicit dependencies of custom build commands
std::set<std::string> CombinedCustomCommandExplicitDependencies;
diff --git a/Source/cmPolicies.cxx b/Source/cmPolicies.cxx
index 720030b..592df8f 100644
--- a/Source/cmPolicies.cxx
+++ b/Source/cmPolicies.cxx
@@ -380,6 +380,11 @@ cmPolicies::cmPolicies()
CMP0057, "CMP0057",
"Disallow multiple MAIN_DEPENDENCY specifications for the same file.",
3,3,0, cmPolicies::WARN);
+
+ this->DefinePolicy(
+ CMP0058, "CMP0058",
+ "Ninja requires custom command byproducts to be explicit.",
+ 3,3,0, cmPolicies::WARN);
}
cmPolicies::~cmPolicies()
diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h
index 854b132..b18b337 100644
--- a/Source/cmPolicies.h
+++ b/Source/cmPolicies.h
@@ -115,6 +115,7 @@ public:
CMP0056, ///< Honor link flags in try_compile() source-file signature.
CMP0057, ///< Disallow multiple MAIN_DEPENDENCY specifications
/// for the same file.
+ CMP0058, ///< Ninja requires custom command byproducts to be explicit
/** \brief Always the last entry.
*