Link step: use linker dependency linker file

Based on work done by @ben.boeckel (!8051)

Fixes: #22217
This commit is contained in:
Marc Chevrier
2023-04-19 16:01:10 +02:00
parent 24a3e5cda0
commit 375e6fdbbe
43 changed files with 387 additions and 41 deletions
+1
View File
@@ -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
+11
View File
@@ -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.
+1
View File
@@ -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@
+1
View File
@@ -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@")
+1
View File
@@ -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@")
+1
View File
@@ -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@")
+1
View File
@@ -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()
+1
View File
@@ -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@")
+1
View File
@@ -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)
+1
View File
@@ -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@")
+9
View File
@@ -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)
+38
View File
@@ -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")
+14 -10
View File
@@ -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);
+6
View File
@@ -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()) {
+24
View File
@@ -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();
+3
View File
@@ -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;
+2
View File
@@ -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. */
+2
View File
@@ -236,6 +236,8 @@ public:
return cmDepfileFormat::GccDepfile;
}
bool SupportsLinkerDependencyFile() const override { return true; }
virtual cmGeneratedFileStream* GetImplFileStream(
const std::string& /*config*/) const
{
+6
View File
@@ -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();
+38
View File
@@ -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)
+6
View File
@@ -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,
+8
View File
@@ -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(
+3
View File
@@ -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;
+18
View File
@@ -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"));
+3
View File
@@ -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()) {
+27 -2
View File
@@ -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());
+2
View File
@@ -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();
+15
View File
@@ -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()
+1
View File
@@ -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