summaryrefslogtreecommitdiff
path: root/Source
diff options
context:
space:
mode:
authorMarc Chevrier <marc.chevrier@gmail.com>2023-04-19 16:01:10 +0200
committerMarc Chevrier <marc.chevrier@gmail.com>2023-05-03 17:08:07 +0200
commit375e6fdbbe398921de321216125765ba1917a325 (patch)
tree43d934f18f4d28a82d5264a0d0fb0301bc0bf7d9 /Source
parent24a3e5cda049138ca178216e0d7b02262e4035ed (diff)
downloadcmake-375e6fdbbe398921de321216125765ba1917a325.tar.gz
Link step: use linker dependency linker file
Based on work done by @ben.boeckel (!8051) Fixes: #22217
Diffstat (limited to 'Source')
-rw-r--r--Source/cmDependsCompiler.cxx24
-rw-r--r--Source/cmGccDepfileLexerHelper.cxx6
-rw-r--r--Source/cmGeneratorTarget.cxx24
-rw-r--r--Source/cmGeneratorTarget.h3
-rw-r--r--Source/cmGlobalGenerator.h2
-rw-r--r--Source/cmGlobalNinjaGenerator.h2
-rw-r--r--Source/cmGlobalUnixMakefileGenerator3.h6
-rw-r--r--Source/cmLocalGenerator.cxx38
-rw-r--r--Source/cmLocalGenerator.h6
-rw-r--r--Source/cmLocalNinjaGenerator.cxx8
-rw-r--r--Source/cmLocalNinjaGenerator.h3
-rw-r--r--Source/cmLocalUnixMakefileGenerator3.cxx18
-rw-r--r--Source/cmLocalUnixMakefileGenerator3.h3
-rw-r--r--Source/cmMakefileExecutableTargetGenerator.cxx2
-rw-r--r--Source/cmMakefileLibraryTargetGenerator.cxx3
-rw-r--r--Source/cmMakefileTargetGenerator.cxx29
-rw-r--r--Source/cmMakefileTargetGenerator.h2
-rw-r--r--Source/cmNinjaNormalTargetGenerator.cxx15
18 files changed, 182 insertions, 12 deletions
diff --git a/Source/cmDependsCompiler.cxx b/Source/cmDependsCompiler.cxx
index 0cc4946e48..c8061c36ee 100644
--- a/Source/cmDependsCompiler.cxx
+++ b/Source/cmDependsCompiler.cxx
@@ -128,7 +128,7 @@ bool cmDependsCompiler::CheckDependencies(
}
std::string line;
- if (!isValidPath) {
+ if (!isValidPath && !source.empty()) {
// insert source as first dependency
depends.push_back(source);
}
@@ -158,14 +158,16 @@ bool cmDependsCompiler::CheckDependencies(
}
// ensure source file is the first dependency
- if (depends.front() != source) {
- cm::erase(depends, source);
- if (!isValidPath) {
- depends.insert(depends.begin(), source);
+ if (!source.empty()) {
+ 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 if (isValidPath) {
- // remove first dependency because it must not be filtered out
- depends.erase(depends.begin());
}
} else {
// unknown format, ignore it
@@ -174,8 +176,10 @@ bool cmDependsCompiler::CheckDependencies(
if (isValidPath) {
cm::erase_if(depends, isValidPath);
- // insert source as first dependency
- depends.insert(depends.begin(), source);
+ if (!source.empty()) {
+ // insert source as first dependency
+ depends.insert(depends.begin(), source);
+ }
}
dependencies[target] = std::move(depends);
diff --git a/Source/cmGccDepfileLexerHelper.cxx b/Source/cmGccDepfileLexerHelper.cxx
index 34c88248a0..87377de401 100644
--- a/Source/cmGccDepfileLexerHelper.cxx
+++ b/Source/cmGccDepfileLexerHelper.cxx
@@ -2,6 +2,7 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmGccDepfileLexerHelper.h"
+#include <algorithm>
#include <cstdio>
#include <memory>
#include <string>
@@ -113,6 +114,11 @@ void cmGccDepfileLexerHelper::addToCurrentPath(const char* s)
void cmGccDepfileLexerHelper::sanitizeContent()
{
for (auto it = this->Content.begin(); it != this->Content.end();) {
+ // remove duplicate path entries
+ std::sort(it->paths.begin(), it->paths.end());
+ auto last = std::unique(it->paths.begin(), it->paths.end());
+ it->paths.erase(last, it->paths.end());
+
// Remove empty paths and normalize windows paths
for (auto pit = it->paths.begin(); pit != it->paths.end();) {
if (pit->empty()) {
diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx
index 1c37e52bee..8ac19fc37e 100644
--- a/Source/cmGeneratorTarget.cxx
+++ b/Source/cmGeneratorTarget.cxx
@@ -8518,6 +8518,30 @@ bool cmGeneratorTarget::IsLinkable() const
this->IsExecutableWithExports());
}
+bool cmGeneratorTarget::HasLinkDependencyFile(std::string const& config) const
+{
+ if (this->GetType() != cmStateEnums::EXECUTABLE &&
+ this->GetType() != cmStateEnums::SHARED_LIBRARY &&
+ this->GetType() != cmStateEnums::MODULE_LIBRARY) {
+ return false;
+ }
+
+ if (this->Target->GetProperty("LINK_DEPENDS_NO_SHARED").IsOn()) {
+ // Do not use the linker dependency file because it includes shared
+ // libraries as well
+ return false;
+ }
+
+ const std::string depsUseLinker{ "CMAKE_LINK_DEPENDS_USE_LINKER" };
+ auto linkLanguage = this->GetLinkerLanguage(config);
+ const std::string langDepsUseLinker{ cmStrCat("CMAKE_", linkLanguage,
+ "_LINK_DEPENDS_USE_LINKER") };
+
+ return (!this->Makefile->IsDefinitionSet(depsUseLinker) ||
+ this->Makefile->IsOn(depsUseLinker)) &&
+ this->Makefile->IsOn(langDepsUseLinker);
+}
+
bool cmGeneratorTarget::IsFrameworkOnApple() const
{
return this->Target->IsFrameworkOnApple();
diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h
index 87227fd29c..9008286a1a 100644
--- a/Source/cmGeneratorTarget.h
+++ b/Source/cmGeneratorTarget.h
@@ -805,6 +805,9 @@ public:
/** Return whether this target may be used to link another target. */
bool IsLinkable() const;
+ /** Return whether the link step generates a dependency file. */
+ bool HasLinkDependencyFile(std::string const& config) const;
+
/** Return whether this target is a shared library Framework on
Apple. */
bool IsFrameworkOnApple() const;
diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h
index dde364886e..79fe52c193 100644
--- a/Source/cmGlobalGenerator.h
+++ b/Source/cmGlobalGenerator.h
@@ -546,6 +546,8 @@ public:
return cm::nullopt;
}
+ virtual bool SupportsLinkerDependencyFile() const { return false; }
+
std::string GetSharedLibFlagsForLanguage(std::string const& lang) const;
/** Generate an <output>.rule file path for a given command output. */
diff --git a/Source/cmGlobalNinjaGenerator.h b/Source/cmGlobalNinjaGenerator.h
index bd541685c9..bfbe57f22b 100644
--- a/Source/cmGlobalNinjaGenerator.h
+++ b/Source/cmGlobalNinjaGenerator.h
@@ -236,6 +236,8 @@ public:
return cmDepfileFormat::GccDepfile;
}
+ bool SupportsLinkerDependencyFile() const override { return true; }
+
virtual cmGeneratedFileStream* GetImplFileStream(
const std::string& /*config*/) const
{
diff --git a/Source/cmGlobalUnixMakefileGenerator3.h b/Source/cmGlobalUnixMakefileGenerator3.h
index 214ba2af51..760679a051 100644
--- a/Source/cmGlobalUnixMakefileGenerator3.h
+++ b/Source/cmGlobalUnixMakefileGenerator3.h
@@ -99,6 +99,12 @@ public:
*/
bool SupportsCustomCommandDepfile() const override { return true; }
+ /**
+ * Utilized to determine if this generator
+ * supports linker dependency file.
+ */
+ bool SupportsLinkerDependencyFile() const override { return true; }
+
/** Get the documentation entry for this generator. */
static cmDocumentationEntry GetDocumentation();
diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index 64f0246e90..b02fa62487 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -1586,6 +1586,8 @@ void cmLocalGenerator::GetTargetFlags(
this->AppendPositionIndependentLinkerFlags(extraLinkFlags, target, config,
linkLanguage);
this->AppendIPOLinkerFlags(extraLinkFlags, target, config, linkLanguage);
+ this->AppendDependencyInfoLinkerFlags(extraLinkFlags, target, config,
+ linkLanguage);
this->AppendModuleDefinitionFlag(extraLinkFlags, target, linkLineComputer,
config);
@@ -3202,6 +3204,42 @@ void cmLocalGenerator::AppendPositionIndependentLinkerFlags(
}
}
+void cmLocalGenerator::AppendDependencyInfoLinkerFlags(
+ std::string& flags, cmGeneratorTarget* target, const std::string& config,
+ const std::string& linkLanguage)
+{
+ if (!this->GetGlobalGenerator()->SupportsLinkerDependencyFile() ||
+ !target->HasLinkDependencyFile(config)) {
+ return;
+ }
+
+ auto depFlag = *this->Makefile->GetDefinition(
+ cmStrCat("CMAKE_", linkLanguage, "_LINKER_DEPFILE_FLAGS"));
+ if (depFlag.empty()) {
+ return;
+ }
+
+ auto depFile = this->ConvertToOutputFormat(
+ this->MaybeRelativeToWorkDir(this->GetLinkDependencyFile(target, config)),
+ cmOutputConverter::SHELL);
+ std::unique_ptr<cmRulePlaceholderExpander> rulePlaceholderExpander(
+ this->CreateRulePlaceholderExpander());
+ cmRulePlaceholderExpander::RuleVariables linkDepsVariables;
+ linkDepsVariables.DependencyFile = depFile.c_str();
+ rulePlaceholderExpander->ExpandRuleVariables(this, depFlag,
+ linkDepsVariables);
+ auto depFlags = cmExpandListWithBacktrace(depFlag);
+ target->ResolveLinkerWrapper(depFlags, linkLanguage);
+
+ this->AppendFlags(flags, depFlags);
+}
+
+std::string cmLocalGenerator::GetLinkDependencyFile(
+ cmGeneratorTarget* /*target*/, const std::string& /*config*/) const
+{
+ return "link.d";
+}
+
void cmLocalGenerator::AppendModuleDefinitionFlag(
std::string& flags, cmGeneratorTarget const* target,
cmLinkLineComputer* linkLineComputer, std::string const& config)
diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h
index ea60a4ee35..3ad52c4256 100644
--- a/Source/cmLocalGenerator.h
+++ b/Source/cmLocalGenerator.h
@@ -183,6 +183,12 @@ public:
cmGeneratorTarget* target,
const std::string& config,
const std::string& lang);
+ void AppendDependencyInfoLinkerFlags(std::string& flags,
+ cmGeneratorTarget* target,
+ const std::string& config,
+ const std::string& lang);
+ virtual std::string GetLinkDependencyFile(cmGeneratorTarget* target,
+ const std::string& config) const;
void AppendModuleDefinitionFlag(std::string& flags,
cmGeneratorTarget const* target,
cmLinkLineComputer* linkLineComputer,
diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx
index 2e837bb30b..82d5a607b9 100644
--- a/Source/cmLocalNinjaGenerator.cxx
+++ b/Source/cmLocalNinjaGenerator.cxx
@@ -200,6 +200,14 @@ std::string cmLocalNinjaGenerator::MaybeRelativeToWorkDir(
this->MaybeRelativeToTopBinDir(path));
}
+std::string cmLocalNinjaGenerator::GetLinkDependencyFile(
+ cmGeneratorTarget* target, std::string const& config) const
+{
+ return cmStrCat(target->GetSupportDirectory(),
+ this->GetGlobalNinjaGenerator()->ConfigDirectory(config),
+ "/link.d");
+}
+
// Virtual protected methods.
std::string cmLocalNinjaGenerator::ConvertToIncludeReference(
diff --git a/Source/cmLocalNinjaGenerator.h b/Source/cmLocalNinjaGenerator.h
index 347aaa03bc..0bc462b038 100644
--- a/Source/cmLocalNinjaGenerator.h
+++ b/Source/cmLocalNinjaGenerator.h
@@ -94,6 +94,9 @@ public:
bool HasUniqueByproducts(std::vector<std::string> const& byproducts,
cmListFileBacktrace const& bt);
+ std::string GetLinkDependencyFile(cmGeneratorTarget* target,
+ std::string const& config) const override;
+
protected:
std::string ConvertToIncludeReference(
std::string const& path, cmOutputConverter::OutputFormat format) override;
diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx
index 028066ef90..9f3894adbd 100644
--- a/Source/cmLocalUnixMakefileGenerator3.cxx
+++ b/Source/cmLocalUnixMakefileGenerator3.cxx
@@ -239,6 +239,12 @@ void cmLocalUnixMakefileGenerator3::GetIndividualFileTargets(
}
}
+std::string cmLocalUnixMakefileGenerator3::GetLinkDependencyFile(
+ cmGeneratorTarget* target, std::string const& /*config*/) const
+{
+ return cmStrCat(target->GetSupportDirectory(), "/link.d");
+}
+
void cmLocalUnixMakefileGenerator3::WriteLocalMakefile()
{
// generate the includes
@@ -2008,6 +2014,18 @@ void cmLocalUnixMakefileGenerator3::WriteDependLanguageInfo(
<< this->MaybeRelativeToTopBinDir(src) << "\"\n";
}
}
+ } else if (compilerLang.first == "LINK"_s) {
+ auto depFormat = this->Makefile->GetDefinition(
+ cmStrCat("CMAKE_", target->GetLinkerLanguage(this->GetConfigName()),
+ "_LINKER_DEPFILE_FORMAT"));
+ for (auto const& compilerPair : compilerPairs) {
+ for (auto const& src : compilerPair.second) {
+ cmakefileStream << R"( "" ")"
+ << this->MaybeRelativeToTopBinDir(compilerPair.first)
+ << "\" \"" << depFormat << "\" \""
+ << this->MaybeRelativeToTopBinDir(src) << "\"\n";
+ }
+ }
} else {
auto depFormat = this->Makefile->GetSafeDefinition(
cmStrCat("CMAKE_", compilerLang.first, "_DEPFILE_FORMAT"));
diff --git a/Source/cmLocalUnixMakefileGenerator3.h b/Source/cmLocalUnixMakefileGenerator3.h
index 78aa7f9c2f..7d5a9224b4 100644
--- a/Source/cmLocalUnixMakefileGenerator3.h
+++ b/Source/cmLocalUnixMakefileGenerator3.h
@@ -191,6 +191,9 @@ public:
// Eclipse generator.
void GetIndividualFileTargets(std::vector<std::string>& targets);
+ std::string GetLinkDependencyFile(cmGeneratorTarget* target,
+ std::string const& config) const override;
+
protected:
void WriteLocalMakefile();
diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx
index 3caabde0bc..be8318cd12 100644
--- a/Source/cmMakefileExecutableTargetGenerator.cxx
+++ b/Source/cmMakefileExecutableTargetGenerator.cxx
@@ -70,6 +70,8 @@ void cmMakefileExecutableTargetGenerator::WriteRuleFiles()
this->WriteExecutableRule(true);
}
+ this->WriteTargetLinkDependRules();
+
// Write clean target
this->WriteTargetCleanRules();
diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx
index 691edf4c21..0ebbe4d190 100644
--- a/Source/cmMakefileLibraryTargetGenerator.cxx
+++ b/Source/cmMakefileLibraryTargetGenerator.cxx
@@ -62,6 +62,9 @@ void cmMakefileLibraryTargetGenerator::WriteRuleFiles()
// write in rules for object files and custom commands
this->WriteTargetBuildRules();
+ // Write in the rules for the link dependency file
+ this->WriteTargetLinkDependRules();
+
// write the link rules
// Write the rule for this target type.
switch (this->GeneratorTarget->GetType()) {
diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx
index a0a7324070..97e3fad85f 100644
--- a/Source/cmMakefileTargetGenerator.cxx
+++ b/Source/cmMakefileTargetGenerator.cxx
@@ -150,6 +150,8 @@ void cmMakefileTargetGenerator::GetTargetLinkFlags(
this->LocalGenerator->AppendPositionIndependentLinkerFlags(
flags, this->GeneratorTarget, this->GetConfigName(), linkLanguage);
+ this->LocalGenerator->AppendDependencyInfoLinkerFlags(
+ flags, this->GeneratorTarget, this->GetConfigName(), linkLanguage);
}
void cmMakefileTargetGenerator::CreateRuleFile()
@@ -414,8 +416,10 @@ void cmMakefileTargetGenerator::WriteCommonCodeRules()
this->GlobalGenerator->SupportsCompilerDependencies() &&
(!this->Makefile->IsDefinitionSet(depsUseCompiler) ||
this->Makefile->IsOn(depsUseCompiler));
+ bool linkerGenerateDeps =
+ this->GeneratorTarget->HasLinkDependencyFile(this->GetConfigName());
- if (compilerGenerateDeps || ccGenerateDeps) {
+ if (compilerGenerateDeps || linkerGenerateDeps || ccGenerateDeps) {
std::string compilerDependFile =
cmStrCat(this->TargetBuildDirectoryFull, "/compiler_depend.make");
*this->BuildFileStream << "# Include any dependencies generated by the "
@@ -1499,6 +1503,21 @@ bool cmMakefileTargetGenerator::WriteMakeRule(
return symbolic;
}
+void cmMakefileTargetGenerator::WriteTargetLinkDependRules()
+{
+ if (!this->GeneratorTarget->HasLinkDependencyFile(this->GetConfigName())) {
+ return;
+ }
+
+ auto depFile = this->LocalGenerator->GetLinkDependencyFile(
+ this->GeneratorTarget, this->GetConfigName());
+ this->CleanFiles.insert(depFile);
+ this->LocalGenerator->AddImplicitDepends(
+ this->GeneratorTarget, "LINK",
+ this->GeneratorTarget->GetFullPath(this->GetConfigName()), depFile,
+ cmDependencyScannerKind::Compiler);
+}
+
void cmMakefileTargetGenerator::WriteTargetDependRules()
{
// must write the targets depend info file
@@ -2052,8 +2071,14 @@ void cmMakefileTargetGenerator::AppendTargetDepends(
return;
}
- // Loop over all library dependencies.
const std::string& cfg = this->GetConfigName();
+
+ if (this->GeneratorTarget->HasLinkDependencyFile(cfg)) {
+ depends.push_back(
+ cmStrCat(this->TargetBuildDirectoryFull, "/compiler_depend.ts"));
+ }
+
+ // Loop over all library dependencies.
if (cmComputeLinkInformation* cli =
this->GeneratorTarget->GetLinkInformation(cfg)) {
cm::append(depends, cli->GetDepends());
diff --git a/Source/cmMakefileTargetGenerator.h b/Source/cmMakefileTargetGenerator.h
index 98c3a0e8db..ef7a60fa62 100644
--- a/Source/cmMakefileTargetGenerator.h
+++ b/Source/cmMakefileTargetGenerator.h
@@ -77,6 +77,8 @@ protected:
// write the clean rules for this target
void WriteTargetCleanRules();
+ // write the linker depend rules for this target
+ void WriteTargetLinkDependRules();
// write the depend rules for this target
void WriteTargetDependRules();
diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx
index ee4fa90043..9903d63614 100644
--- a/Source/cmNinjaNormalTargetGenerator.cxx
+++ b/Source/cmNinjaNormalTargetGenerator.cxx
@@ -417,6 +417,13 @@ void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile,
std::string cmakeVarLang =
cmStrCat("CMAKE_", this->TargetLinkLanguage(config));
+ if (this->GeneratorTarget->HasLinkDependencyFile(config)) {
+ auto DepFileFormat = this->GetMakefile()->GetDefinition(
+ cmStrCat(cmakeVarLang, "_LINKER_DEPFILE_FORMAT"));
+ rule.DepType = DepFileFormat;
+ rule.DepFile = "$DEP_FILE";
+ }
+
// build response file name
std::string cmakeLinkVar = cmakeVarLang + "_RESPONSE_FILE_LINK_FLAG";
cmValue flag = this->GetMakefile()->GetDefinition(cmakeLinkVar);
@@ -1134,6 +1141,14 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement(
cmNinjaBuild linkBuild(this->LanguageLinkerRule(config));
cmNinjaVars& vars = linkBuild.Variables;
+ if (this->GeneratorTarget->HasLinkDependencyFile(config)) {
+ vars["DEP_FILE"] = this->GetLocalGenerator()->ConvertToOutputFormat(
+ this->ConvertToNinjaPath(
+ this->GetLocalGenerator()->GetLinkDependencyFile(this->GeneratorTarget,
+ config)),
+ cmOutputConverter::SHELL);
+ }
+
// Compute the comment.
linkBuild.Comment =
cmStrCat("Link the ", this->GetVisibleTypeName(), ' ', targetOutputReal);