summaryrefslogtreecommitdiffstats
path: root/Source
diff options
context:
space:
mode:
authorMarc Chevrier <marc.chevrier@gmail.com>2020-12-04 17:35:04 (GMT)
committerMarc Chevrier <marc.chevrier@gmail.com>2020-12-23 14:47:46 (GMT)
commitcfd8a5ac1f443725342517ddbaee51692d8d0324 (patch)
treebf2224cb9c6b6ba1a7aed1eb2fbcaf31799cbc17 /Source
parenta526f71266c2fed017c65a3d90b63286221476c0 (diff)
downloadCMake-cfd8a5ac1f443725342517ddbaee51692d8d0324.zip
CMake-cfd8a5ac1f443725342517ddbaee51692d8d0324.tar.gz
CMake-cfd8a5ac1f443725342517ddbaee51692d8d0324.tar.bz2
Makefiles: Add support of DEPFILE for add_custom_command
Issue: #20286 Fixes: #21415
Diffstat (limited to 'Source')
-rw-r--r--Source/cmAddCustomCommandCommand.cxx6
-rw-r--r--Source/cmDependsCompiler.cxx133
-rw-r--r--Source/cmGlobalUnixMakefileGenerator3.h6
-rw-r--r--Source/cmLocalUnixMakefileGenerator3.cxx39
-rw-r--r--Source/cmMakefileTargetGenerator.cxx19
-rw-r--r--Source/cmMakefileUtilityTargetGenerator.cxx39
-rw-r--r--Source/cmcmd.cxx2
7 files changed, 182 insertions, 62 deletions
diff --git a/Source/cmAddCustomCommandCommand.cxx b/Source/cmAddCustomCommandCommand.cxx
index ccd7255..ff2cc3e 100644
--- a/Source/cmAddCustomCommandCommand.cxx
+++ b/Source/cmAddCustomCommandCommand.cxx
@@ -296,6 +296,12 @@ bool cmAddCustomCommandCommand(std::vector<std::string> const& args,
status.SetError("given APPEND option with no OUTPUT.");
return false;
}
+ if (!implicit_depends.empty() && !depfile.empty() &&
+ mf.GetGlobalGenerator()->GetName() != "Ninja") {
+ // Makefiles generators does not support both at the same time
+ status.SetError("IMPLICIT_DEPENDS and DEPFILE can not both be specified.");
+ return false;
+ }
// Check for an append request.
if (append) {
diff --git a/Source/cmDependsCompiler.cxx b/Source/cmDependsCompiler.cxx
index f6e5af8..beb080f 100644
--- a/Source/cmDependsCompiler.cxx
+++ b/Source/cmDependsCompiler.cxx
@@ -19,6 +19,7 @@
#include "cmFileTime.h"
#include "cmGccDepfileReader.h"
+#include "cmGccDepfileReaderTypes.h"
#include "cmGlobalUnixMakefileGenerator3.h"
#include "cmLocalUnixMakefileGenerator3.h"
#include "cmStringAlgorithms.h"
@@ -86,7 +87,7 @@ bool cmDependsCompiler::CheckDependencies(
if (!forceReadDeps) {
depFileTime.Load(depFile);
}
- if (forceReadDeps || depFileTime.Newer(internalDepFileTime)) {
+ if (forceReadDeps || depFileTime.Compare(internalDepFileTime) >= 0) {
status = false;
if (this->Verbose) {
cmSystemTools::Stdout(cmStrCat("Dependencies file \"", depFile,
@@ -95,59 +96,92 @@ bool cmDependsCompiler::CheckDependencies(
}
std::vector<std::string> depends;
- if (format == "msvc"_s) {
- cmsys::ifstream fin(depFile.c_str());
- if (!fin) {
- continue;
+ if (format == "custom"_s) {
+ std::string prefix;
+ if (this->LocalGenerator->GetCurrentBinaryDirectory() !=
+ this->LocalGenerator->GetBinaryDirectory()) {
+ prefix =
+ cmStrCat(this->LocalGenerator->MaybeConvertToRelativePath(
+ this->LocalGenerator->GetBinaryDirectory(),
+ this->LocalGenerator->GetCurrentBinaryDirectory()),
+ '/');
}
- std::string line;
- if (!isValidPath) {
- // insert source as first dependency
- depends.push_back(source);
- }
- while (cmSystemTools::GetLineFromStream(fin, line)) {
- depends.emplace_back(std::move(line));
- }
- } else {
- auto deps = cmReadGccDepfile(depFile.c_str());
+ auto deps = cmReadGccDepfile(depFile.c_str(), prefix);
if (!deps) {
continue;
}
- // dependencies generated by the compiler contains only one target
- depends = std::move(deps->front().paths);
- if (depends.empty()) {
- // unexpectedly empty, ignore it and continue
- continue;
- }
-
- // depending of the effective format of the dependencies file generated
- // by the compiler, the target can be wrongly identified as a
- // dependency so remove it from the list
- if (depends.front() == target) {
- depends.erase(depends.begin());
+ for (auto& entry : *deps) {
+ depends = std::move(entry.paths);
+ if (isValidPath) {
+ cm::erase_if(depends, isValidPath);
+ }
+ // copy depends for each target, except first one, which can be
+ // moved
+ for (auto index = entry.rules.size() - 1; index > 0; --index) {
+ dependencies[entry.rules[index]] = depends;
+ }
+ dependencies[entry.rules.front()] = std::move(depends);
}
+ } else {
+ if (format == "msvc"_s) {
+ cmsys::ifstream fin(depFile.c_str());
+ if (!fin) {
+ continue;
+ }
- // ensure source file is the first dependency
- if (depends.front() != source) {
- cm::erase(depends, source);
+ std::string line;
if (!isValidPath) {
- depends.insert(depends.begin(), source);
+ // insert source as first dependency
+ depends.push_back(source);
+ }
+ while (cmSystemTools::GetLineFromStream(fin, line)) {
+ depends.emplace_back(std::move(line));
+ }
+ } else if (format == "gcc"_s) {
+ auto deps = cmReadGccDepfile(depFile.c_str());
+ if (!deps) {
+ continue;
}
- } else if (isValidPath) {
- // remove first dependency because it must not be filtered out
- depends.erase(depends.begin());
+
+ // dependencies generated by the compiler contains only one target
+ depends = std::move(deps->front().paths);
+ if (depends.empty()) {
+ // unexpectedly empty, ignore it and continue
+ continue;
+ }
+
+ // depending of the effective format of the dependencies file
+ // generated by the compiler, the target can be wrongly identified
+ // as a dependency so remove it from the list
+ if (depends.front() == target) {
+ depends.erase(depends.begin());
+ }
+
+ // ensure source file is the first dependency
+ if (depends.front() != source) {
+ cm::erase(depends, source);
+ if (!isValidPath) {
+ depends.insert(depends.begin(), source);
+ }
+ } else if (isValidPath) {
+ // remove first dependency because it must not be filtered out
+ depends.erase(depends.begin());
+ }
+ } else {
+ // unknown format, ignore it
+ continue;
}
- }
- if (isValidPath) {
- cm::erase_if(depends, isValidPath);
- // insert source as first dependency
- depends.insert(depends.begin(), source);
- }
+ if (isValidPath) {
+ cm::erase_if(depends, isValidPath);
+ // insert source as first dependency
+ depends.insert(depends.begin(), source);
+ }
- dependencies[target] = std::move(depends);
+ dependencies[target] = std::move(depends);
+ }
}
}
@@ -168,6 +202,8 @@ void cmDependsCompiler::WriteDependencies(
// external dependencies file
for (auto& node : makeDependencies) {
+ auto target = LocalGenerator->ConvertToMakefilePath(
+ this->LocalGenerator->MaybeConvertToRelativePath(binDir, node.first));
auto& deps = node.second;
std::transform(
deps.cbegin(), deps.cend(), deps.begin(),
@@ -176,13 +212,16 @@ void cmDependsCompiler::WriteDependencies(
this->LocalGenerator->MaybeConvertToRelativePath(binDir, dep));
});
- makeDepends << this->LocalGenerator->ConvertToMakefilePath(node.first)
- << ": " << deps.front();
- // first dependency is the source, remove it because should not be declared
- // as phony target
- deps.erase(deps.begin());
+ bool first_dep = true;
+ makeDepends << target << ": ";
for (const auto& dep : deps) {
- makeDepends << ' ' << lineContinue << " " << dep;
+ if (first_dep) {
+ first_dep = false;
+ makeDepends << dep;
+ } else {
+ makeDepends << ' ' << lineContinue << " " << dep;
+ }
+
phonyTargets.emplace(dep.data(), dep.length());
}
makeDepends << std::endl << std::endl;
diff --git a/Source/cmGlobalUnixMakefileGenerator3.h b/Source/cmGlobalUnixMakefileGenerator3.h
index 6459771..09679a7 100644
--- a/Source/cmGlobalUnixMakefileGenerator3.h
+++ b/Source/cmGlobalUnixMakefileGenerator3.h
@@ -93,6 +93,12 @@ public:
*/
static bool SupportsPlatform() { return false; }
+ /**
+ * Utilized to determine if this generator
+ * supports DEPFILE option.
+ */
+ bool SupportsCustomCommandDepfile() const override { return true; }
+
/** Get the documentation entry for this generator. */
static void GetDocumentation(cmDocumentationEntry& entry);
diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx
index 08cefb7..358df9d 100644
--- a/Source/cmLocalUnixMakefileGenerator3.cxx
+++ b/Source/cmLocalUnixMakefileGenerator3.cxx
@@ -13,6 +13,7 @@
#include <cm/string_view>
#include <cm/vector>
#include <cmext/algorithm>
+#include <cmext/string_view>
#include "cmsys/FStream.hxx"
#include "cmsys/Terminal.h"
@@ -1435,7 +1436,7 @@ bool cmLocalUnixMakefileGenerator3::UpdateDependencies(
this->Makefile->GetSafeDefinition("CMAKE_DEPENDS_DEPENDENCY_FILES");
if (!depends.empty()) {
// dependencies are managed by compiler
- auto depFiles = cmExpandedList(depends);
+ auto depFiles = cmExpandedList(depends, true);
std::string const internalDepFile =
targetDir + "/compiler_depend.internal";
std::string const depFile = targetDir + "/compiler_depend.make";
@@ -1998,18 +1999,32 @@ void cmLocalUnixMakefileGenerator3::WriteDependLanguageInfo(
cmakefileStream << "\n# The set of dependency files which are needed:\n";
cmakefileStream << "set(CMAKE_DEPENDS_DEPENDENCY_FILES\n";
for (auto const& compilerLang : compilerLangs) {
- auto depFormat = this->Makefile->GetSafeDefinition(
- cmStrCat("CMAKE_", compilerLang.first, "_DEPFILE_FORMAT"));
auto const& compilerPairs = compilerLang.second;
- for (auto const& compilerPair : compilerPairs) {
- for (auto const& src : compilerPair.second) {
- cmakefileStream << " \"" << src << "\" \""
- << this->MaybeConvertToRelativePath(
- this->GetBinaryDirectory(), compilerPair.first)
- << "\" \"" << depFormat << "\" \""
- << this->MaybeConvertToRelativePath(
- this->GetBinaryDirectory(), compilerPair.first)
- << ".d\"\n";
+ if (compilerLang.first == "CUSTOM"_s) {
+ for (auto const& compilerPair : compilerPairs) {
+ for (auto const& src : compilerPair.second) {
+ cmakefileStream << R"( "" ")"
+ << this->MaybeConvertToRelativePath(
+ this->GetBinaryDirectory(), compilerPair.first)
+ << R"(" "custom" ")"
+ << this->MaybeConvertToRelativePath(
+ this->GetBinaryDirectory(), src)
+ << "\"\n";
+ }
+ }
+ } else {
+ auto depFormat = this->Makefile->GetSafeDefinition(
+ cmStrCat("CMAKE_", compilerLang.first, "_DEPFILE_FORMAT"));
+ for (auto const& compilerPair : compilerPairs) {
+ for (auto const& src : compilerPair.second) {
+ cmakefileStream << " \"" << src << "\" \""
+ << this->MaybeConvertToRelativePath(
+ this->GetBinaryDirectory(), compilerPair.first)
+ << "\" \"" << depFormat << "\" \""
+ << this->MaybeConvertToRelativePath(
+ this->GetBinaryDirectory(), compilerPair.first)
+ << ".d\"\n";
+ }
}
}
}
diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx
index 1f23424..70a0393 100644
--- a/Source/cmMakefileTargetGenerator.cxx
+++ b/Source/cmMakefileTargetGenerator.cxx
@@ -1617,6 +1617,16 @@ void cmMakefileTargetGenerator::GenerateCustomRuleFile(
std::vector<std::string> depends;
this->LocalGenerator->AppendCustomDepend(depends, ccg);
+ if (!ccg.GetCC().GetDepfile().empty()) {
+ // Add dependency over timestamp file for dependencies management
+ auto dependTimestamp = cmSystemTools::ConvertToOutputPath(
+ this->LocalGenerator->MaybeConvertToRelativePath(
+ this->LocalGenerator->GetBinaryDirectory(),
+ cmStrCat(this->TargetBuildDirectoryFull, "/compiler_depend.ts")));
+
+ depends.push_back(dependTimestamp);
+ }
+
// Write the rule.
const std::vector<std::string>& outputs = ccg.GetOutputs();
bool symbolic = this->WriteMakeRule(*this->BuildFileStream, nullptr, outputs,
@@ -1653,6 +1663,15 @@ void cmMakefileTargetGenerator::GenerateCustomRuleFile(
objFullPath, srcFullPath);
}
+ // Setup implicit depend for depfile if any
+ if (!ccg.GetCC().GetDepfile().empty()) {
+ std::string objFullPath = cmSystemTools::CollapseFullPath(
+ outputs[0], this->LocalGenerator->GetCurrentBinaryDirectory());
+ this->LocalGenerator->AddImplicitDepends(
+ this->GeneratorTarget, "CUSTOM", objFullPath, ccg.GetFullDepfile(),
+ cmDependencyScannerKind::Compiler);
+ }
+
this->CustomCommandOutputs.insert(outputs.begin(), outputs.end());
}
diff --git a/Source/cmMakefileUtilityTargetGenerator.cxx b/Source/cmMakefileUtilityTargetGenerator.cxx
index 6c18e48..a885b17 100644
--- a/Source/cmMakefileUtilityTargetGenerator.cxx
+++ b/Source/cmMakefileUtilityTargetGenerator.cxx
@@ -15,6 +15,7 @@
#include "cmLocalUnixMakefileGenerator3.h"
#include "cmMakefile.h"
#include "cmOSXBundleGenerator.h"
+#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
cmMakefileUtilityTargetGenerator::cmMakefileUtilityTargetGenerator(
@@ -36,10 +37,42 @@ void cmMakefileUtilityTargetGenerator::WriteRuleFiles()
*this->BuildFileStream << "# Utility rule file for "
<< this->GeneratorTarget->GetName() << ".\n\n";
+ const char* root = (this->Makefile->IsOn("CMAKE_MAKE_INCLUDE_FROM_ROOT")
+ ? "$(CMAKE_BINARY_DIR)/"
+ : "");
+
+ // Include the dependencies for the target.
+ std::string dependFile =
+ cmStrCat(this->TargetBuildDirectoryFull, "/compiler_depend.make");
+ *this->BuildFileStream
+ << "# Include any custom commands dependencies for this target.\n"
+ << this->GlobalGenerator->IncludeDirective << " " << root
+ << cmSystemTools::ConvertToOutputPath(
+ this->LocalGenerator->MaybeConvertToRelativePath(
+ this->LocalGenerator->GetBinaryDirectory(), dependFile))
+ << "\n\n";
+ if (!cmSystemTools::FileExists(dependFile)) {
+ // Write an empty dependency file.
+ cmGeneratedFileStream depFileStream(
+ dependFile, false, this->GlobalGenerator->GetMakefileEncoding());
+ depFileStream << "# Empty custom commands generated dependencies file for "
+ << this->GeneratorTarget->GetName() << ".\n"
+ << "# This may be replaced when dependencies are built.\n";
+ }
+
+ std::string dependTimestamp =
+ cmStrCat(this->TargetBuildDirectoryFull, "/compiler_depend.ts");
+ if (!cmSystemTools::FileExists(dependTimestamp)) {
+ // Write a dependency timestamp file.
+ cmGeneratedFileStream depFileStream(
+ dependTimestamp, false, this->GlobalGenerator->GetMakefileEncoding());
+ depFileStream << "# CMAKE generated file: DO NOT EDIT!\n"
+ << "# Timestamp file for custom commands dependencies "
+ "management for "
+ << this->GeneratorTarget->GetName() << ".\n";
+ }
+
if (!this->NoRuleMessages) {
- const char* root = (this->Makefile->IsOn("CMAKE_MAKE_INCLUDE_FROM_ROOT")
- ? "$(CMAKE_BINARY_DIR)/"
- : "");
// Include the progress variables for the target.
*this->BuildFileStream
<< "# Include the progress variables for this target.\n"
diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx
index b8464f2..73fbfb6 100644
--- a/Source/cmcmd.cxx
+++ b/Source/cmcmd.cxx
@@ -1272,6 +1272,8 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string> const& args,
cmStateSnapshot snapshot = cm.GetCurrentSnapshot();
snapshot.GetDirectory().SetCurrentBinary(startOutDir);
snapshot.GetDirectory().SetCurrentSource(startDir);
+ snapshot.GetDirectory().SetRelativePathTopSource(homeDir.c_str());
+ snapshot.GetDirectory().SetRelativePathTopBinary(homeOutDir.c_str());
cmMakefile mf(cm.GetGlobalGenerator(), snapshot);
auto lgd = cm.GetGlobalGenerator()->CreateLocalGenerator(&mf);