mirror of
https://github.com/Kitware/CMake.git
synced 2026-04-24 07:08:38 -05:00
Link step: use linker dependency linker file
Based on work done by @ben.boeckel (!8051) Fixes: #22217
This commit is contained in:
@@ -479,6 +479,7 @@ Variables that Control the Build
|
||||
/variable/CMAKE_LIBRARY_PATH_FLAG
|
||||
/variable/CMAKE_LINK_DEF_FILE_FLAG
|
||||
/variable/CMAKE_LINK_DEPENDS_NO_SHARED
|
||||
/variable/CMAKE_LINK_DEPENDS_USE_LINKER
|
||||
/variable/CMAKE_LINK_GROUP_USING_FEATURE
|
||||
/variable/CMAKE_LINK_GROUP_USING_FEATURE_SUPPORTED
|
||||
/variable/CMAKE_LINK_INTERFACE_LIBRARIES
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
use-linker-depfile
|
||||
------------------
|
||||
|
||||
* GNU (and GNU-compatible) linkers gained support for a ``--dependency-file``
|
||||
flag in GNU Binutils 2.35 and LLVM's LLD 12.0.0. The
|
||||
:ref:`Makefile <Makefile Generators>` and :ref:`Ninja <Ninja Generators>`
|
||||
generators will now add these flags so that files read by the linker will
|
||||
cause a relink if they change (typically modified timestamps).
|
||||
|
||||
This feature can be controlled by the variable
|
||||
:variable:`CMAKE_LINK_DEPENDS_USE_LINKER`.
|
||||
@@ -0,0 +1,12 @@
|
||||
CMAKE_LINK_DEPENDS_USE_LINKER
|
||||
-----------------------------
|
||||
|
||||
.. versionadded:: 3.27
|
||||
|
||||
For the :ref:`Makefile <Makefile Generators>` and
|
||||
:ref:`Ninja <Ninja Generators>` generators, link dependencies are now, for a
|
||||
selection of linkers, generated by the linker itself. By defining this
|
||||
variable with value ``FALSE``, you can deactivate this feature.
|
||||
|
||||
This feature is also deactivated if the :prop_tgt:`LINK_DEPENDS_NO_SHARED`
|
||||
target property is true.
|
||||
@@ -17,5 +17,6 @@ set(CMAKE_ASM@ASM_DIALECT@_COMPILER_ENV_VAR "@_CMAKE_ASM_COMPILER_ENV_VAR@")
|
||||
|
||||
set(CMAKE_ASM@ASM_DIALECT@_IGNORE_EXTENSIONS h;H;o;O;obj;OBJ;def;DEF;rc;RC)
|
||||
set(CMAKE_ASM@ASM_DIALECT@_LINKER_PREFERENCE 0)
|
||||
set(CMAKE_ASM@ASM_DIALECT@_LINKER_DEPFILE_SUPPORTED "@CMAKE_ASM_LINKER_DEPFILE_SUPPORTED@")
|
||||
|
||||
@CMAKE_ASM_COMPILER_CUSTOM_CODE@
|
||||
|
||||
@@ -39,6 +39,7 @@ set(CMAKE_C_COMPILER_ID_RUN 1)
|
||||
set(CMAKE_C_SOURCE_FILE_EXTENSIONS c;m)
|
||||
set(CMAKE_C_IGNORE_EXTENSIONS h;H;o;O;obj;OBJ;def;DEF;rc;RC)
|
||||
set(CMAKE_C_LINKER_PREFERENCE 10)
|
||||
set(CMAKE_C_LINKER_DEPFILE_SUPPORTED "@CMAKE_C_LINKER_DEPFILE_SUPPORTED@")
|
||||
|
||||
# Save compiler ABI information.
|
||||
set(CMAKE_C_SIZEOF_DATA_PTR "@CMAKE_C_SIZEOF_DATA_PTR@")
|
||||
|
||||
@@ -30,6 +30,7 @@ set(CMAKE_CUDA_COMPILER_ID_RUN 1)
|
||||
set(CMAKE_CUDA_SOURCE_FILE_EXTENSIONS cu)
|
||||
set(CMAKE_CUDA_LINKER_PREFERENCE 15)
|
||||
set(CMAKE_CUDA_LINKER_PREFERENCE_PROPAGATES 1)
|
||||
set(CMAKE_CUDA_LINKER_DEPFILE_SUPPORTED "@CMAKE_CUDA_LINKER_DEPFILE_SUPPORTED@")
|
||||
|
||||
set(CMAKE_CUDA_SIZEOF_DATA_PTR "@CMAKE_CUDA_SIZEOF_DATA_PTR@")
|
||||
set(CMAKE_CUDA_COMPILER_ABI "@CMAKE_CUDA_COMPILER_ABI@")
|
||||
|
||||
@@ -50,6 +50,7 @@ endforeach()
|
||||
|
||||
set(CMAKE_CXX_LINKER_PREFERENCE 30)
|
||||
set(CMAKE_CXX_LINKER_PREFERENCE_PROPAGATES 1)
|
||||
set(CMAKE_CXX_LINKER_DEPFILE_SUPPORTED "@CMAKE_CXX_LINKER_DEPFILE_SUPPORTED@")
|
||||
|
||||
# Save compiler ABI information.
|
||||
set(CMAKE_CXX_SIZEOF_DATA_PTR "@CMAKE_CXX_SIZEOF_DATA_PTR@")
|
||||
|
||||
@@ -29,6 +29,7 @@ set(CMAKE_Fortran_COMPILER_ID_RUN 1)
|
||||
set(CMAKE_Fortran_SOURCE_FILE_EXTENSIONS f;F;fpp;FPP;f77;F77;f90;F90;for;For;FOR;f95;F95;f03;F03;f08;F08@CMAKE_Fortran_VENDOR_SOURCE_FILE_EXTENSIONS@)
|
||||
set(CMAKE_Fortran_IGNORE_EXTENSIONS h;H;o;O;obj;OBJ;def;DEF;rc;RC)
|
||||
set(CMAKE_Fortran_LINKER_PREFERENCE 20)
|
||||
set(CMAKE_Fortran_LINKER_DEPFILE_SUPPORTED "@CMAKE_Fortran_LINKER_DEPFILE_SUPPORTED@")
|
||||
if(UNIX)
|
||||
set(CMAKE_Fortran_OUTPUT_EXTENSION .o)
|
||||
else()
|
||||
|
||||
@@ -26,6 +26,7 @@ set(CMAKE_HIP_COMPILER_ID_RUN 1)
|
||||
set(CMAKE_HIP_SOURCE_FILE_EXTENSIONS hip)
|
||||
set(CMAKE_HIP_LINKER_PREFERENCE 90)
|
||||
set(CMAKE_HIP_LINKER_PREFERENCE_PROPAGATES 1)
|
||||
set(CMAKE_HIP_LINKER_DEPFILE_SUPPORTED "@CMAKE_HIP_LINKER_DEPFILE_SUPPORTED@")
|
||||
|
||||
set(CMAKE_HIP_SIZEOF_DATA_PTR "@CMAKE_HIP_SIZEOF_DATA_PTR@")
|
||||
set(CMAKE_HIP_COMPILER_ABI "@CMAKE_HIP_COMPILER_ABI@")
|
||||
|
||||
@@ -37,6 +37,7 @@ set(CMAKE_OBJC_COMPILER_ID_RUN 1)
|
||||
set(CMAKE_OBJC_SOURCE_FILE_EXTENSIONS m)
|
||||
set(CMAKE_OBJC_IGNORE_EXTENSIONS h;H;o;O)
|
||||
set(CMAKE_OBJC_LINKER_PREFERENCE 5)
|
||||
set(CMAKE_OBJC_LINKER_DEPFILE_SUPPORTED "@CMAKE_OBJC_LINKER_DEPFILE_SUPPORTED@")
|
||||
|
||||
foreach (lang C CXX OBJCXX)
|
||||
foreach(extension IN LISTS CMAKE_OBJC_SOURCE_FILE_EXTENSIONS)
|
||||
|
||||
@@ -54,6 +54,7 @@ endforeach()
|
||||
|
||||
set(CMAKE_OBJCXX_LINKER_PREFERENCE 25)
|
||||
set(CMAKE_OBJCXX_LINKER_PREFERENCE_PROPAGATES 1)
|
||||
set(CMAKE_OBJCXX_LINKER_DEPFILE_SUPPORTED "@CMAKE_OBJCXX_LINKER_DEPFILE_SUPPORTED@")
|
||||
|
||||
# Save compiler ABI information.
|
||||
set(CMAKE_OBJCXX_SIZEOF_DATA_PTR "@CMAKE_OBJCXX_SIZEOF_DATA_PTR@")
|
||||
|
||||
@@ -1,4 +1,13 @@
|
||||
include(Compiler/Clang)
|
||||
|
||||
#
|
||||
# For now, deactivate globally linker dependency file support because
|
||||
# HIP compiler is based on Clang which provides support of other languages
|
||||
#
|
||||
foreach (lang IN ITEMS "C" "CXX" "OBJC" "OBJCXX" "Fortran" "ASM")
|
||||
set(CMAKE_${lang}_LINKER_DEPFILE_SUPPORTED FALSE)
|
||||
endforeach()
|
||||
|
||||
__compiler_clang(HIP)
|
||||
__compiler_clang_cxx_standards(HIP)
|
||||
|
||||
|
||||
@@ -52,6 +52,44 @@ macro(__compiler_gnu lang)
|
||||
set(CMAKE_DEPFILE_FLAGS_${lang} "-MD -MT <DEP_TARGET> -MF <DEP_FILE>")
|
||||
endif()
|
||||
|
||||
# define flags for linker depfile generation
|
||||
if (NOT DEFINED CMAKE_${lang}_LINKER_DEPFILE_SUPPORTED)
|
||||
## Ensure ninja tool is recent enough...
|
||||
if(CMAKE_GENERATOR MATCHES "^Ninja")
|
||||
# Ninja 1.10 or upper is required
|
||||
execute_process(COMMAND "${CMAKE_MAKE_PROGRAM}" --version
|
||||
OUTPUT_VARIABLE _ninja_version
|
||||
ERROR_VARIABLE _ninja_version)
|
||||
if (_ninja_version MATCHES "[0-9]+(\\.[0-9]+)*")
|
||||
set (_ninja_version "${CMAKE_MATCH_0}")
|
||||
endif()
|
||||
if (_ninja_version VERSION_LESS "1.10")
|
||||
set(CMAKE_${lang}_LINKER_DEPFILE_SUPPORTED FALSE)
|
||||
endif()
|
||||
unset(_ninja_version)
|
||||
endif()
|
||||
|
||||
if (NOT DEFINED CMAKE_${lang}_LINKER_DEPFILE_SUPPORTED)
|
||||
## check if this feature is supported by the linker
|
||||
execute_process(COMMAND "${CMAKE_LINKER}" --help
|
||||
OUTPUT_VARIABLE _linker_capabilities
|
||||
ERROR_VARIABLE _linker_capabilities)
|
||||
if(_linker_capabilities MATCHES "--dependency-file")
|
||||
set(CMAKE_${lang}_LINKER_DEPFILE_SUPPORTED TRUE)
|
||||
else()
|
||||
set(CMAKE_${lang}_LINKER_DEPFILE_SUPPORTED FALSE)
|
||||
endif()
|
||||
unset(_linker_capabilities)
|
||||
endif()
|
||||
endif()
|
||||
if (CMAKE_${lang}_LINKER_DEPFILE_SUPPORTED)
|
||||
set(CMAKE_${lang}_LINKER_DEPFILE_FLAGS "LINKER:--dependency-file,<DEP_FILE>")
|
||||
set(CMAKE_${lang}_LINKER_DEPFILE_FORMAT gcc)
|
||||
set(CMAKE_${lang}_LINK_DEPENDS_USE_LINKER TRUE)
|
||||
else()
|
||||
unset(CMAKE_${lang}_LINK_DEPENDS_USE_LINKER)
|
||||
endif()
|
||||
|
||||
# Initial configuration flags.
|
||||
string(APPEND CMAKE_${lang}_FLAGS_INIT " ")
|
||||
string(APPEND CMAKE_${lang}_FLAGS_DEBUG_INIT " -g")
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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()) {
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -236,6 +236,8 @@ public:
|
||||
return cmDepfileFormat::GccDepfile;
|
||||
}
|
||||
|
||||
bool SupportsLinkerDependencyFile() const override { return true; }
|
||||
|
||||
virtual cmGeneratedFileStream* GetImplFileStream(
|
||||
const std::string& /*config*/) const
|
||||
{
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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"));
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -70,6 +70,8 @@ void cmMakefileExecutableTargetGenerator::WriteRuleFiles()
|
||||
this->WriteExecutableRule(true);
|
||||
}
|
||||
|
||||
this->WriteTargetLinkDependRules();
|
||||
|
||||
// Write clean target
|
||||
this->WriteTargetCleanRules();
|
||||
|
||||
|
||||
@@ -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()) {
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -1,26 +1,26 @@
|
||||
--RULES--
|
||||
main.o
|
||||
--DEPENDENCIES--
|
||||
main.cpp
|
||||
/usr/include/features.h
|
||||
/usr/include/stdc-predef.h
|
||||
/usr/include/stdio.h
|
||||
/usr/include/x86_64-linux-gnu/bits/libc-header-start.h
|
||||
/usr/include/features.h
|
||||
/usr/include/x86_64-linux-gnu/sys/cdefs.h
|
||||
/usr/include/x86_64-linux-gnu/bits/wordsize.h
|
||||
/usr/include/x86_64-linux-gnu/bits/long-double.h
|
||||
/usr/include/x86_64-linux-gnu/gnu/stubs.h
|
||||
/usr/include/x86_64-linux-gnu/gnu/stubs-64.h
|
||||
/usr/lib/gcc/x86_64-linux-gnu/8/include/stddef.h
|
||||
/usr/lib/gcc/x86_64-linux-gnu/8/include/stdarg.h
|
||||
/usr/include/x86_64-linux-gnu/bits/types.h
|
||||
/usr/include/x86_64-linux-gnu/bits/typesizes.h
|
||||
/usr/include/x86_64-linux-gnu/bits/types/__fpos_t.h
|
||||
/usr/include/x86_64-linux-gnu/bits/types/__mbstate_t.h
|
||||
/usr/include/x86_64-linux-gnu/bits/types/__fpos64_t.h
|
||||
/usr/include/x86_64-linux-gnu/bits/types/__FILE.h
|
||||
/usr/include/x86_64-linux-gnu/bits/types/FILE.h
|
||||
/usr/include/x86_64-linux-gnu/bits/types/struct_FILE.h
|
||||
/usr/include/x86_64-linux-gnu/bits/types/cookie_io_functions_t.h
|
||||
/usr/include/x86_64-linux-gnu/bits/stdio_lim.h
|
||||
/usr/include/x86_64-linux-gnu/bits/sys_errlist.h
|
||||
/usr/include/x86_64-linux-gnu/bits/types.h
|
||||
/usr/include/x86_64-linux-gnu/bits/types/FILE.h
|
||||
/usr/include/x86_64-linux-gnu/bits/types/__FILE.h
|
||||
/usr/include/x86_64-linux-gnu/bits/types/__fpos64_t.h
|
||||
/usr/include/x86_64-linux-gnu/bits/types/__fpos_t.h
|
||||
/usr/include/x86_64-linux-gnu/bits/types/__mbstate_t.h
|
||||
/usr/include/x86_64-linux-gnu/bits/types/cookie_io_functions_t.h
|
||||
/usr/include/x86_64-linux-gnu/bits/types/struct_FILE.h
|
||||
/usr/include/x86_64-linux-gnu/bits/typesizes.h
|
||||
/usr/include/x86_64-linux-gnu/bits/wordsize.h
|
||||
/usr/include/x86_64-linux-gnu/gnu/stubs-64.h
|
||||
/usr/include/x86_64-linux-gnu/gnu/stubs.h
|
||||
/usr/include/x86_64-linux-gnu/sys/cdefs.h
|
||||
/usr/lib/gcc/x86_64-linux-gnu/8/include/stdarg.h
|
||||
/usr/lib/gcc/x86_64-linux-gnu/8/include/stddef.h
|
||||
main.cpp
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
--RULES--
|
||||
main.o
|
||||
--DEPENDENCIES--
|
||||
main.cpp
|
||||
foo#bar.h
|
||||
foo\#bar.h
|
||||
foo bar.h
|
||||
foo#bar.h
|
||||
foo$bar.h
|
||||
foo\ bar.h
|
||||
foo\#bar.h
|
||||
foo\\ bar.h
|
||||
foo\\\\
|
||||
foo$bar.h
|
||||
main.cpp
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
|
||||
enable_language(C)
|
||||
|
||||
include("${CMAKE_BINARY_DIR}/../LinkDependsExternalLibrary-build/ExternalLibrary-debug.cmake")
|
||||
cmake_path(GET EXTERNAL_LIBRARY PARENT_PATH EXTERNAL_DIR)
|
||||
|
||||
add_library(LinkDependsLib SHARED "${CMAKE_CURRENT_BINARY_DIR}/lib_depends.c")
|
||||
target_link_directories(LinkDependsLib PRIVATE "${EXTERNAL_DIR}")
|
||||
target_link_libraries(LinkDependsLib PRIVATE External)
|
||||
|
||||
add_executable(LinkDependsExe "${CMAKE_CURRENT_BINARY_DIR}/exe_depends.c")
|
||||
target_link_directories(LinkDependsExe PRIVATE "${EXTERNAL_DIR}")
|
||||
target_link_libraries(LinkDependsExe PRIVATE External)
|
||||
|
||||
|
||||
file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/check-$<LOWER_CASE:$<CONFIG>>.cmake"
|
||||
CONTENT "
|
||||
set(check_pairs
|
||||
\"$<TARGET_FILE:LinkDependsLib>|${EXTERNAL_LIBRARY}\"
|
||||
\"$<TARGET_FILE:LinkDependsExe>|${EXTERNAL_LIBRARY}\"
|
||||
)
|
||||
")
|
||||
@@ -0,0 +1,23 @@
|
||||
|
||||
file(WRITE "${RunCMake_TEST_BINARY_DIR}/lib_depends.c" [[
|
||||
|
||||
extern void external(void);
|
||||
|
||||
void lib_depends(void)
|
||||
{
|
||||
external();
|
||||
}
|
||||
]])
|
||||
|
||||
|
||||
file(WRITE "${RunCMake_TEST_BINARY_DIR}/exe_depends.c" [[
|
||||
|
||||
extern void external(void);
|
||||
|
||||
int main(void)
|
||||
{
|
||||
external();
|
||||
|
||||
return 0;
|
||||
}
|
||||
]])
|
||||
@@ -0,0 +1,4 @@
|
||||
|
||||
include ("${RunCMake_TEST_BINARY_DIR}/../LinkDependsExternalLibrary-build/ExternalLibrary-debug.cmake")
|
||||
|
||||
file(TOUCH "${EXTERNAL_LIBRARY}")
|
||||
@@ -0,0 +1,11 @@
|
||||
|
||||
enable_language(C)
|
||||
|
||||
file(WRITE "${CMAKE_BINARY_DIR}/LinkDependsUseLinker.cmake"
|
||||
"set(CMAKE_C_LINK_DEPENDS_USE_LINKER \"${CMAKE_C_LINK_DEPENDS_USE_LINKER}\")\n")
|
||||
|
||||
|
||||
file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/check-$<LOWER_CASE:$<CONFIG>>.cmake"
|
||||
CONTENT "
|
||||
# no required actions
|
||||
")
|
||||
@@ -0,0 +1,13 @@
|
||||
|
||||
enable_language(C)
|
||||
|
||||
add_library(External SHARED "${CMAKE_CURRENT_BINARY_DIR}/external.c")
|
||||
|
||||
file(GENERATE OUTPUT "${CMAKE_BINARY_DIR}/ExternalLibrary-$<LOWER_CASE:$<CONFIG>>.cmake"
|
||||
CONTENT "set(EXTERNAL_LIBRARY \"$<TARGET_LINKER_FILE:External>\")\n")
|
||||
|
||||
|
||||
file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/check-$<LOWER_CASE:$<CONFIG>>.cmake"
|
||||
CONTENT "
|
||||
# no required actions
|
||||
")
|
||||
@@ -0,0 +1,11 @@
|
||||
|
||||
file(WRITE "${RunCMake_TEST_BINARY_DIR}/external.c" [[
|
||||
|
||||
|
||||
#if defined(_WIN32)
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
void external(void)
|
||||
{
|
||||
}
|
||||
]])
|
||||
@@ -194,3 +194,15 @@ if(RunCMake_GENERATOR MATCHES "^Visual Studio 9 " OR
|
||||
endif()
|
||||
run_BuildDepends(CustomCommandUnityBuild)
|
||||
unset(run_BuildDepends_skip_step_2)
|
||||
|
||||
#if (RunCMake_GENERATOR MATCHES "Make|Ninja" AND CMAKE_C_LINK_DEPENDS_USE_LINKER)
|
||||
if (RunCMake_GENERATOR MATCHES "Make|Ninja")
|
||||
set(run_BuildDepends_skip_step_2 1)
|
||||
run_BuildDepends(LinkDependsCheck)
|
||||
include("${RunCMake_BINARY_DIR}/LinkDependsCheck-build/LinkDependsUseLinker.cmake")
|
||||
if (CMAKE_C_LINK_DEPENDS_USE_LINKER)
|
||||
run_BuildDepends(LinkDependsExternalLibrary)
|
||||
unset(run_BuildDepends_skip_step_2)
|
||||
run_BuildDepends(LinkDepends)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@@ -295,6 +295,7 @@ endif()
|
||||
add_RunCMake_test(BuildDepends
|
||||
-DMSVC_VERSION=${MSVC_VERSION}
|
||||
-DCMAKE_C_COMPILER_ID=${CMAKE_C_COMPILER_ID}
|
||||
-DCMAKE_C_LINK_DEPENDS_USE_COMPILER=${CMAKE_C_LINK_DEPENDS_USE_COMPILER}
|
||||
-DCMake_TEST_BuildDepends_GNU_AS=${CMake_TEST_BuildDepends_GNU_AS}
|
||||
)
|
||||
if(UNIX AND "${CMAKE_GENERATOR}" MATCHES "Unix Makefiles|Ninja")
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
subdir/out1 \
|
||||
/home/build/out2: \
|
||||
subdir/in1 \
|
||||
/home/build/in2
|
||||
/home/build/in2 \
|
||||
subdir/in1
|
||||
subdir/out3 \
|
||||
/home/build/out4: \
|
||||
subdir/in3 \
|
||||
/home/build/in4
|
||||
/home/build/in4 \
|
||||
subdir/in3
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
subdir/out1 \
|
||||
C:/build/out2: \
|
||||
subdir/in1 \
|
||||
C:/build/in2
|
||||
C:/build/in2 \
|
||||
subdir/in1
|
||||
subdir/out3 \
|
||||
C:/build/out4: \
|
||||
subdir/in3 \
|
||||
C:/build/in4
|
||||
C:/build/in4 \
|
||||
subdir/in3
|
||||
|
||||
Reference in New Issue
Block a user