diff options
author | Marc Chevrier <marc.chevrier@gmail.com> | 2023-04-19 14:01:10 (GMT) |
---|---|---|
committer | Marc Chevrier <marc.chevrier@gmail.com> | 2023-05-03 15:08:07 (GMT) |
commit | 375e6fdbbe398921de321216125765ba1917a325 (patch) | |
tree | 43d934f18f4d28a82d5264a0d0fb0301bc0bf7d9 /Source | |
parent | 24a3e5cda049138ca178216e0d7b02262e4035ed (diff) | |
download | CMake-375e6fdbbe398921de321216125765ba1917a325.zip CMake-375e6fdbbe398921de321216125765ba1917a325.tar.gz CMake-375e6fdbbe398921de321216125765ba1917a325.tar.bz2 |
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.cxx | 24 | ||||
-rw-r--r-- | Source/cmGccDepfileLexerHelper.cxx | 6 | ||||
-rw-r--r-- | Source/cmGeneratorTarget.cxx | 24 | ||||
-rw-r--r-- | Source/cmGeneratorTarget.h | 3 | ||||
-rw-r--r-- | Source/cmGlobalGenerator.h | 2 | ||||
-rw-r--r-- | Source/cmGlobalNinjaGenerator.h | 2 | ||||
-rw-r--r-- | Source/cmGlobalUnixMakefileGenerator3.h | 6 | ||||
-rw-r--r-- | Source/cmLocalGenerator.cxx | 38 | ||||
-rw-r--r-- | Source/cmLocalGenerator.h | 6 | ||||
-rw-r--r-- | Source/cmLocalNinjaGenerator.cxx | 8 | ||||
-rw-r--r-- | Source/cmLocalNinjaGenerator.h | 3 | ||||
-rw-r--r-- | Source/cmLocalUnixMakefileGenerator3.cxx | 18 | ||||
-rw-r--r-- | Source/cmLocalUnixMakefileGenerator3.h | 3 | ||||
-rw-r--r-- | Source/cmMakefileExecutableTargetGenerator.cxx | 2 | ||||
-rw-r--r-- | Source/cmMakefileLibraryTargetGenerator.cxx | 3 | ||||
-rw-r--r-- | Source/cmMakefileTargetGenerator.cxx | 29 | ||||
-rw-r--r-- | Source/cmMakefileTargetGenerator.h | 2 | ||||
-rw-r--r-- | Source/cmNinjaNormalTargetGenerator.cxx | 15 |
18 files changed, 182 insertions, 12 deletions
diff --git a/Source/cmDependsCompiler.cxx b/Source/cmDependsCompiler.cxx index 0cc4946..c8061c3 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 34c8824..87377de 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 1c37e52..8ac19fc 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 87227fd..9008286 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 dde3648..79fe52c 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 bd54168..bfbe57f 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 214ba2a..760679a 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 64f0246..b02fa62 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 ea60a4e..3ad52c4 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 2e837bb..82d5a60 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 347aaa0..0bc462b 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 028066e..9f3894a 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 78aa7f9..7d5a922 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 3caabde..be8318c 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 691edf4..0ebbe4d 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 a0a7324..97e3fad 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 98c3a0e..ef7a60f 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 ee4fa90..9903d63 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); |