summaryrefslogtreecommitdiffstats
path: root/Source/cmLocalNinjaGenerator.cxx
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2021-05-19 14:21:11 (GMT)
committerBrad King <brad.king@kitware.com>2021-05-19 17:28:14 (GMT)
commit2725ecff38ccd25905a9bc968bfb1b2f0d09b34a (patch)
tree94dd74aa6b00b3bdddf90e64eace0d6aff7078e5 /Source/cmLocalNinjaGenerator.cxx
parentbc40cd7a4e107be68debb01760700850d4c1106c (diff)
downloadCMake-2725ecff38ccd25905a9bc968bfb1b2f0d09b34a.zip
CMake-2725ecff38ccd25905a9bc968bfb1b2f0d09b34a.tar.gz
CMake-2725ecff38ccd25905a9bc968bfb1b2f0d09b34a.tar.bz2
Ninja: Handle depfiles with absolute paths to generated files
Ninja treats every (normalized) path as its own node. It does not recognize `/abs/path/to/file` in a depfile as matching `path/to/file` even when `build.ninja` and the working directory are in `/abs/`. See Ninja Issue 1251. In cases where we pass absolute paths to the compiler, it will write a depfile containing absolute paths. If those files are generated in the build tree by custom commands, `build.ninja` references them by relative path in build statement outputs, so Ninja does not hook up the dependency and rebuild the project correctly. Add infrastructure to work around this problem by adding implicit outputs to custom command build statements that reference the main outputs by absolute path. Use a `${cmake_ninja_workdir}` placeholder to avoid repeating the base path. For example: build out.txt | ${cmake_ninja_workdir}out.txt: CUSTOM_COMMAND ... Ninja will create two nodes for the output file, one with a relative path and one with an absolute path. A depfile may then mention either form of the path and Ninja will hook up the dependency. Unfortunately Ninja will also stat the file twice. Issue: #13894 Fixes: #21865
Diffstat (limited to 'Source/cmLocalNinjaGenerator.cxx')
-rw-r--r--Source/cmLocalNinjaGenerator.cxx13
1 files changed, 13 insertions, 0 deletions
diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx
index 9eb3e46..fb6c730 100644
--- a/Source/cmLocalNinjaGenerator.cxx
+++ b/Source/cmLocalNinjaGenerator.cxx
@@ -263,6 +263,7 @@ void cmLocalNinjaGenerator::WriteBuildFileTop()
this->GetConfigNames().front());
}
this->WriteNinjaFilesInclusionCommon(this->GetCommonFileStream());
+ this->WriteNinjaWorkDir(this->GetCommonFileStream());
// For the rule file.
this->WriteProjectHeader(this->GetRulesFileStream());
@@ -364,6 +365,17 @@ void cmLocalNinjaGenerator::WriteNinjaFilesInclusionCommon(std::ostream& os)
os << "\n";
}
+void cmLocalNinjaGenerator::WriteNinjaWorkDir(std::ostream& os)
+{
+ cmGlobalNinjaGenerator::WriteDivider(os);
+ cmGlobalNinjaGenerator::WriteComment(
+ os, "Logical path to working directory; prefix for absolute paths.");
+ cmGlobalNinjaGenerator* ng = this->GetGlobalNinjaGenerator();
+ std::string ninja_workdir = this->GetBinaryDirectory();
+ ng->StripNinjaOutputPathPrefixAsSuffix(ninja_workdir); // Also appends '/'.
+ os << "cmake_ninja_workdir = " << ng->EncodePath(ninja_workdir) << "\n";
+}
+
void cmLocalNinjaGenerator::WriteProcessedMakefile(std::ostream& os)
{
cmGlobalNinjaGenerator::WriteDivider(os);
@@ -654,6 +666,7 @@ void cmLocalNinjaGenerator::WriteCustomCommandBuildStatement(
cmNinjaBuild build("phony");
build.Comment = cmStrCat("Phony custom command for ", mainOutput);
build.Outputs = std::move(ccOutputs.ExplicitOuts);
+ build.WorkDirOuts = std::move(ccOutputs.WorkDirOuts);
build.ExplicitDeps = std::move(ninjaDeps);
build.OrderOnlyDeps = orderOnlyDeps;
gg->WriteBuild(this->GetImplFileStream(fileConfig), build);