Add support of "LINKER:" prefix for CMAKE_<TYPE>_LINKER_FLAGS variable

The following variables now support the LINKER: prefix:
* CMAKE_<TYPE>_LINKER_FLAGS
* CMAKE_<TYPE>_LINKER_FLAGS_<CONFIG>

Fixes: #26171
This commit is contained in:
Marc Chevrier 2024-10-04 18:07:39 +02:00
parent 384dbef61e
commit 35350c419d
38 changed files with 328 additions and 66 deletions

View File

@ -336,6 +336,10 @@ Other Behavior Settings
The current settings of :policy:`CMP0065` and :policy:`CMP0083` are propagated
through to the generated test project.
.. versionadded:: 3.32
The current setting of :policy:`CMP0181` policy is propagated through to the
generated test project.
Set variable :variable:`CMAKE_TRY_COMPILE_CONFIGURATION` to choose a build
configuration:

View File

@ -51,6 +51,14 @@ The :variable:`CMAKE_MINIMUM_REQUIRED_VERSION` variable may also be used
to determine whether to report an error on use of deprecated macros or
functions.
Policies Introduced by CMake 3.32
=================================
.. toctree::
:maxdepth: 1
CMP0181: Link command-line fragment variables are parsed and re-quoted. </policy/CMP0181>
Policies Introduced by CMake 3.31
=================================

41
Help/policy/CMP0181.rst Normal file
View File

@ -0,0 +1,41 @@
CMP0181
-------
.. versionadded:: 3.32
The :variable:`CMAKE_EXE_LINKER_FLAGS`,
:variable:`CMAKE_EXE_LINKER_FLAGS_<CONFIG>`,
:variable:`CMAKE_SHARED_LINKER_FLAGS`,
:variable:`CMAKE_SHARED_LINKER_FLAGS_<CONFIG>`,
:variable:`CMAKE_MODULE_LINKER_FLAGS`,
and :variable:`CMAKE_MODULE_LINKER_FLAGS_<CONFIG>` variables are parsed and
re-quoted and support the ``LINKER:`` prefix.
CMake 3.31 and below use the content of these variables as is.
CMake 3.32 and above parse the content of these variables and manage the
escaping of special characters. Moreover, the ``LINKER:`` prefix is now
recognized and expanded.
The ``OLD`` behavior of this policy is to consume the content of the
:variable:`CMAKE_EXE_LINKER_FLAGS`,
:variable:`CMAKE_EXE_LINKER_FLAGS_<CONFIG>`,
:variable:`CMAKE_SHARED_LINKER_FLAGS`,
:variable:`CMAKE_SHARED_LINKER_FLAGS_<CONFIG>`,
:variable:`CMAKE_MODULE_LINKER_FLAGS`,
and :variable:`CMAKE_MODULE_LINKER_FLAGS_<CONFIG>` variables as is.
The ``NEW`` behavior of this policy is to parse and re-quote the content of the
:variable:`CMAKE_EXE_LINKER_FLAGS`,
:variable:`CMAKE_EXE_LINKER_FLAGS_<CONFIG>`,
:variable:`CMAKE_SHARED_LINKER_FLAGS`,
:variable:`CMAKE_SHARED_LINKER_FLAGS_<CONFIG>`,
:variable:`CMAKE_MODULE_LINKER_FLAGS`,
and :variable:`CMAKE_MODULE_LINKER_FLAGS_<CONFIG>` variables as well as to
expand the ``LINKER:`` prefix.
.. |INTRODUCED_IN_CMAKE_VERSION| replace:: 3.32
.. |WARNS_OR_DOES_NOT_WARN| replace:: does *not* warn
.. include:: STANDARD_ADVICE.txt
.. include:: DEPRECATED.txt

View File

@ -0,0 +1,13 @@
CMAKE_TYPE_LINKER_FLAGS-LINKER-prefix-support
---------------------------------------------
* The :variable:`CMAKE_EXE_LINKER_FLAGS`,
:variable:`CMAKE_EXE_LINKER_FLAGS_<CONFIG>`,
:variable:`CMAKE_SHARED_LINKER_FLAGS`,
:variable:`CMAKE_SHARED_LINKER_FLAGS_<CONFIG>`,
:variable:`CMAKE_MODULE_LINKER_FLAGS`,
and :variable:`CMAKE_MODULE_LINKER_FLAGS_<CONFIG>` variables learned to
support the ``LINKER:`` prefix.
This support implies to parse and re-quote the content of these variables.
This parsing is controlled by :policy:`CMP0181` policy.

View File

@ -4,3 +4,5 @@ CMAKE_EXE_LINKER_FLAGS
Linker flags to be used to create executables.
These flags will be used by the linker when creating an executable.
.. include:: ../variable/LINKER_FLAGS.txt

View File

@ -5,3 +5,5 @@ Flags to be used when linking an executable.
Same as ``CMAKE_C_FLAGS_*`` but used by the linker when creating
executables.
.. include:: ../variable/LINKER_FLAGS.txt

View File

@ -4,3 +4,5 @@ CMAKE_MODULE_LINKER_FLAGS
Linker flags to be used to create modules.
These flags will be used by the linker when creating a module.
.. include:: ../variable/LINKER_FLAGS.txt

View File

@ -4,3 +4,5 @@ CMAKE_MODULE_LINKER_FLAGS_<CONFIG>
Flags to be used when linking a module.
Same as ``CMAKE_C_FLAGS_*`` but used by the linker when creating modules.
.. include:: ../variable/LINKER_FLAGS.txt

View File

@ -4,3 +4,5 @@ CMAKE_SHARED_LINKER_FLAGS
Linker flags to be used to create shared libraries.
These flags will be used by the linker when creating a shared library.
.. include:: ../variable/LINKER_FLAGS.txt

View File

@ -5,3 +5,5 @@ Flags to be used when linking a shared library.
Same as ``CMAKE_C_FLAGS_*`` but used by the linker when creating shared
libraries.
.. include:: ../variable/LINKER_FLAGS.txt

View File

@ -0,0 +1,5 @@
.. include:: ../command/LINK_LIBRARIES_LINKER.txt
This support implies to parse and re-quote the content of the variable. See
policy :policy:`CMP0181`.

View File

@ -910,6 +910,14 @@ cm::optional<cmTryCompileResult> cmCoreTryCompile::TryCompileCode(
? "OLD"
: "NEW");
/* Set the appropriate policy information for the LINKER: prefix expansion
*/
fprintf(fout, "cmake_policy(SET CMP0181 %s)\n",
this->Makefile->GetPolicyStatus(cmPolicies::CMP0181) ==
cmPolicies::NEW
? "NEW"
: "OLD");
// Workaround for -Wl,-headerpad_max_install_names issue until we can avoid
// adding that flag in the platform and compiler language files
fprintf(fout,

View File

@ -2538,7 +2538,8 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
}
if (!extraLinkOptionsVar.empty()) {
this->CurrentLocalGenerator->AddConfigVariableFlags(
extraLinkOptions, extraLinkOptionsVar, configName);
extraLinkOptions, extraLinkOptionsVar, gtgt, cmBuildStep::Link, llang,
configName);
}
if (gtgt->GetType() == cmStateEnums::OBJECT_LIBRARY ||

View File

@ -1495,17 +1495,16 @@ void cmLocalGenerator::GetTargetFlags(
libraryLinkVariable = "CMAKE_MODULE_LINKER_FLAGS";
CM_FALLTHROUGH;
case cmStateEnums::SHARED_LIBRARY: {
std::string sharedLibFlags;
if (this->IsSplitSwiftBuild() || linkLanguage != "Swift") {
sharedLibFlags = cmStrCat(
this->Makefile->GetSafeDefinition(libraryLinkVariable), ' ');
if (!configUpper.empty()) {
std::string build = cmStrCat(libraryLinkVariable, '_', configUpper);
sharedLibFlags += this->Makefile->GetSafeDefinition(build);
sharedLibFlags += " ";
std::string libFlags;
this->AddConfigVariableFlags(libFlags, libraryLinkVariable, target,
cmBuildStep::Link, linkLanguage, config);
if (!libFlags.empty()) {
linkFlags.emplace_back(std::move(libFlags));
}
}
std::string sharedLibFlags;
cmValue targetLinkFlags = target->GetProperty("LINK_FLAGS");
if (targetLinkFlags) {
sharedLibFlags += *targetLinkFlags;
@ -1538,7 +1537,6 @@ void cmLocalGenerator::GetTargetFlags(
}
} break;
case cmStateEnums::EXECUTABLE: {
std::string exeFlags;
if (linkLanguage.empty()) {
cmSystemTools::Error(
"CMake can not determine linker language for target: " +
@ -1547,15 +1545,16 @@ void cmLocalGenerator::GetTargetFlags(
}
if (linkLanguage != "Swift") {
exeFlags = this->Makefile->GetSafeDefinition("CMAKE_EXE_LINKER_FLAGS");
exeFlags += " ";
if (!configUpper.empty()) {
exeFlags += this->Makefile->GetSafeDefinition(
cmStrCat("CMAKE_EXE_LINKER_FLAGS_", configUpper));
exeFlags += " ";
std::string exeFlags;
this->AddConfigVariableFlags(exeFlags, "CMAKE_EXE_LINKER_FLAGS",
target, cmBuildStep::Link, linkLanguage,
config);
if (!exeFlags.empty()) {
linkFlags.emplace_back(std::move(exeFlags));
}
}
std::string exeFlags;
if (target->IsWin32Executable(config)) {
exeFlags += this->Makefile->GetSafeDefinition(
cmStrCat("CMAKE_", linkLanguage, "_CREATE_WIN32_EXE"));
@ -2621,6 +2620,19 @@ void cmLocalGenerator::AddConfigVariableFlags(std::string& flags,
this->AppendFlags(flags, this->Makefile->GetSafeDefinition(flagsVar));
}
}
void cmLocalGenerator::AddConfigVariableFlags(std::string& flags,
const std::string& var,
cmGeneratorTarget const* target,
cmBuildStep compileOrLink,
const std::string& lang,
const std::string& config)
{
std::string newFlags;
this->AddConfigVariableFlags(newFlags, var, config);
if (!newFlags.empty()) {
this->AppendFlags(flags, newFlags, var, target, compileOrLink, lang);
}
}
void cmLocalGenerator::AppendFlags(std::string& flags,
const std::string& newFlags) const
@ -2651,6 +2663,59 @@ void cmLocalGenerator::AppendFlagEscape(std::string& flags,
this->EscapeForShell(rawFlag, false, false, false, this->IsNinjaMulti()));
}
void cmLocalGenerator::AppendFlags(std::string& flags,
std::string const& newFlags,
const std::string& name,
const cmGeneratorTarget* target,
cmBuildStep compileOrLink,
const std::string& language)
{
switch (target->GetPolicyStatusCMP0181()) {
case cmPolicies::WARN:
if (!this->Makefile->GetCMakeInstance()->GetIsInTryCompile() &&
this->Makefile->PolicyOptionalWarningEnabled(
"CMAKE_POLICY_WARNING_CMP0181")) {
this->Makefile->GetCMakeInstance()->IssueMessage(
MessageType::AUTHOR_WARNING,
cmStrCat(cmPolicies::GetPolicyWarning(cmPolicies::CMP0181),
"\nSince the policy is not set, the contents of variable '",
name,
"' will "
"be used as is."),
target->GetBacktrace());
}
CM_FALLTHROUGH;
case cmPolicies::OLD:
this->AppendFlags(flags, newFlags);
break;
case cmPolicies::REQUIRED_IF_USED:
case cmPolicies::REQUIRED_ALWAYS:
this->Makefile->GetCMakeInstance()->IssueMessage(
MessageType::FATAL_ERROR,
cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0181),
target->GetBacktrace());
CM_FALLTHROUGH;
case cmPolicies::NEW:
if (compileOrLink == cmBuildStep::Link) {
std::vector<std::string> options;
cmSystemTools::ParseUnixCommandLine(newFlags.c_str(), options);
this->SetLinkScriptShell(this->GlobalGenerator->GetUseLinkScript());
std::vector<BT<std::string>> optionsWithBT{ options.size() };
std::transform(options.cbegin(), options.cend(), optionsWithBT.begin(),
[](const std::string& item) -> BT<std::string> {
return BT<std::string>{ item };
});
target->ResolveLinkerWrapper(optionsWithBT, language);
for (const auto& item : optionsWithBT) {
this->AppendFlagEscape(flags, item.Value);
}
this->SetLinkScriptShell(false);
} else {
this->AppendFlags(flags, newFlags);
}
}
}
void cmLocalGenerator::AddISPCDependencies(cmGeneratorTarget* target)
{
std::vector<std::string> enabledLanguages =

View File

@ -174,6 +174,12 @@ public:
const std::string& lang);
void AddConfigVariableFlags(std::string& flags, const std::string& var,
const std::string& config);
// Handle prefixes processing (like LINKER:)
void AddConfigVariableFlags(std::string& flags, const std::string& var,
cmGeneratorTarget const* target,
cmBuildStep compileOrLink,
const std::string& lang,
const std::string& config);
void AddColorDiagnosticsFlags(std::string& flags, const std::string& lang);
//! Append flags to a string.
virtual void AppendFlags(std::string& flags,
@ -182,6 +188,13 @@ public:
const std::vector<BT<std::string>>& newFlags) const;
virtual void AppendFlagEscape(std::string& flags,
const std::string& rawFlag) const;
/**
* Append flags after parsing, prefixes processing (like LINKER:) and
* escaping
*/
void AppendFlags(std::string& flags, std::string const& newFlags,
const std::string& name, const cmGeneratorTarget* target,
cmBuildStep compileOrLink, const std::string& lang);
void AddISPCDependencies(cmGeneratorTarget* target);
void AddPchDependencies(cmGeneratorTarget* target);
void AddUnityBuild(cmGeneratorTarget* target);

View File

@ -664,7 +664,6 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(
}
std::string flags;
std::string langForClCompile;
if (target->GetType() <= cmStateEnums::OBJECT_LIBRARY) {
const std::string& linkLanguage =
(this->FortranProject ? std::string("Fortran")
: target->GetLinkerLanguage(configName));
@ -674,6 +673,7 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(
target->GetName()));
return;
}
if (target->GetType() <= cmStateEnums::OBJECT_LIBRARY) {
langForClCompile = linkLanguage;
if (langForClCompile == "C" || langForClCompile == "CXX" ||
langForClCompile == "Fortran") {
@ -957,26 +957,14 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(
}
this->OutputTargetRules(fout, configName, target, libName);
this->OutputBuildTool(fout, configName, target, targetOptions);
this->OutputBuildTool(fout, linkLanguage, configName, target, targetOptions);
this->OutputDeploymentDebuggerTool(fout, configName, target);
fout << "\t\t</Configuration>\n";
}
std::string cmLocalVisualStudio7Generator::GetBuildTypeLinkerFlags(
std::string const& rootLinkerFlags, const std::string& configName)
{
std::string configTypeUpper = cmSystemTools::UpperCase(configName);
std::string extraLinkOptionsBuildTypeDef =
cmStrCat(rootLinkerFlags, '_', configTypeUpper);
const std::string& extraLinkOptionsBuildType =
this->Makefile->GetRequiredDefinition(extraLinkOptionsBuildTypeDef);
return extraLinkOptionsBuildType;
}
void cmLocalVisualStudio7Generator::OutputBuildTool(
std::ostream& fout, const std::string& configName, cmGeneratorTarget* target,
std::ostream& fout, const std::string& linkLanguage,
const std::string& configName, cmGeneratorTarget* target,
const Options& targetOptions)
{
cmGlobalVisualStudio7Generator* gg =
@ -984,19 +972,19 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(
std::string temp;
std::string extraLinkOptions;
if (target->GetType() == cmStateEnums::EXECUTABLE) {
extraLinkOptions = cmStrCat(
this->Makefile->GetRequiredDefinition("CMAKE_EXE_LINKER_FLAGS"), ' ',
GetBuildTypeLinkerFlags("CMAKE_EXE_LINKER_FLAGS", configName));
this->AddConfigVariableFlags(extraLinkOptions, "CMAKE_EXE_LINKER_FLAGS",
target, cmBuildStep::Link, linkLanguage,
configName);
}
if (target->GetType() == cmStateEnums::SHARED_LIBRARY) {
extraLinkOptions = cmStrCat(
this->Makefile->GetRequiredDefinition("CMAKE_SHARED_LINKER_FLAGS"), ' ',
GetBuildTypeLinkerFlags("CMAKE_SHARED_LINKER_FLAGS", configName));
this->AddConfigVariableFlags(extraLinkOptions, "CMAKE_SHARED_LINKER_FLAGS",
target, cmBuildStep::Link, linkLanguage,
configName);
}
if (target->GetType() == cmStateEnums::MODULE_LIBRARY) {
extraLinkOptions = cmStrCat(
this->Makefile->GetRequiredDefinition("CMAKE_MODULE_LINKER_FLAGS"), ' ',
GetBuildTypeLinkerFlags("CMAKE_MODULE_LINKER_FLAGS", configName));
this->AddConfigVariableFlags(extraLinkOptions, "CMAKE_MODULE_LINKER_FLAGS",
target, cmBuildStep::Link, linkLanguage,
configName);
}
cmValue targetLinkFlags = target->GetProperty("LINK_FLAGS");
@ -1089,7 +1077,6 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(
return;
}
cmComputeLinkInformation& cli = *pcli;
std::string linkLanguage = cli.GetLinkLanguage();
if (!target->GetLinkerTypeProperty(linkLanguage, configName).empty()) {
// Visual Studio 10 or upper is required for this feature
@ -1173,7 +1160,6 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(
return;
}
cmComputeLinkInformation& cli = *pcli;
std::string linkLanguage = cli.GetLinkLanguage();
if (!target->GetLinkerTypeProperty(linkLanguage, configName).empty()) {
// Visual Studio 10 or upper is required for this feature

View File

@ -99,8 +99,6 @@ protected:
private:
using Options = cmVS7GeneratorOptions;
using FCInfo = cmLocalVisualStudio7GeneratorFCInfo;
std::string GetBuildTypeLinkerFlags(std::string const& rootLinkerFlags,
const std::string& configName);
void FixGlobalTargets();
void WriteVCProjHeader(std::ostream& fout, const std::string& libName,
cmGeneratorTarget* tgt,
@ -119,8 +117,9 @@ private:
void OutputTargetRules(std::ostream& fout, const std::string& configName,
cmGeneratorTarget* target,
const std::string& libName);
void OutputBuildTool(std::ostream& fout, const std::string& configName,
cmGeneratorTarget* t, const Options& targetOptions);
void OutputBuildTool(std::ostream& fout, const std::string& linkLanguage,
const std::string& configName, cmGeneratorTarget* t,
const Options& targetOptions);
void OutputDeploymentDebuggerTool(std::ostream& fout,
std::string const& config,
cmGeneratorTarget* target);

View File

@ -370,7 +370,8 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
// Add flags to create an executable.
this->LocalGenerator->AddConfigVariableFlags(
linkFlags, "CMAKE_EXE_LINKER_FLAGS", this->GetConfigName());
linkFlags, "CMAKE_EXE_LINKER_FLAGS", this->GeneratorTarget,
cmBuildStep::Link, linkLanguage, this->GetConfigName());
if (this->GeneratorTarget->IsWin32Executable(
this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"))) {

View File

@ -177,7 +177,8 @@ void cmMakefileLibraryTargetGenerator::WriteSharedLibraryRules(bool relink)
std::string extraFlags;
this->GetTargetLinkFlags(extraFlags, linkLanguage);
this->LocalGenerator->AddConfigVariableFlags(
extraFlags, "CMAKE_SHARED_LINKER_FLAGS", this->GetConfigName());
extraFlags, "CMAKE_SHARED_LINKER_FLAGS", this->GeneratorTarget,
cmBuildStep::Link, linkLanguage, this->GetConfigName());
std::unique_ptr<cmLinkLineComputer> linkLineComputer =
this->CreateLinkLineComputer(
@ -212,7 +213,8 @@ void cmMakefileLibraryTargetGenerator::WriteModuleLibraryRules(bool relink)
std::string extraFlags;
this->GetTargetLinkFlags(extraFlags, linkLanguage);
this->LocalGenerator->AddConfigVariableFlags(
extraFlags, "CMAKE_MODULE_LINKER_FLAGS", this->GetConfigName());
extraFlags, "CMAKE_MODULE_LINKER_FLAGS", this->GeneratorTarget,
cmBuildStep::Link, linkLanguage, this->GetConfigName());
std::unique_ptr<cmLinkLineComputer> linkLineComputer =
this->CreateLinkLineComputer(
@ -239,7 +241,8 @@ void cmMakefileLibraryTargetGenerator::WriteFrameworkRules(bool relink)
std::string extraFlags;
this->GetTargetLinkFlags(extraFlags, linkLanguage);
this->LocalGenerator->AddConfigVariableFlags(
extraFlags, "CMAKE_MACOSX_FRAMEWORK_LINKER_FLAGS", this->GetConfigName());
extraFlags, "CMAKE_MACOSX_FRAMEWORK_LINKER_FLAGS", this->GeneratorTarget,
cmBuildStep::Link, linkLanguage, this->GetConfigName());
this->WriteLibraryRules(linkRuleVar, extraFlags, relink);
}

View File

@ -552,7 +552,10 @@ class cmMakefile;
3, 31, 0, cmPolicies::WARN) \
SELECT(POLICY, CMP0180, \
"project() always sets <PROJECT-NAME>_* as normal variables.", 3, \
31, 0, cmPolicies::WARN)
31, 0, cmPolicies::WARN) \
SELECT(POLICY, CMP0181, \
"Link command-line fragment variables are parsed and re-quoted.", 3, \
32, 0, cmPolicies::WARN)
#define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1)
#define CM_FOR_EACH_POLICY_ID(POLICY) \
@ -597,7 +600,8 @@ class cmMakefile;
F(CMP0157) \
F(CMP0160) \
F(CMP0162) \
F(CMP0179)
F(CMP0179) \
F(CMP0181)
#define CM_FOR_EACH_CUSTOM_COMMAND_POLICY(F) \
F(CMP0116) \

View File

@ -4426,12 +4426,9 @@ bool cmVisualStudio10TargetGenerator::ComputeLinkOptions(
linkType = "EXE";
}
std::string flags;
std::string linkFlagVarBase = cmStrCat("CMAKE_", linkType, "_LINKER_FLAGS");
flags += ' ';
flags += this->Makefile->GetRequiredDefinition(linkFlagVarBase);
std::string linkFlagVar = cmStrCat(linkFlagVarBase, '_', CONFIG);
flags += ' ';
flags += this->Makefile->GetRequiredDefinition(linkFlagVar);
this->LocalGenerator->AddConfigVariableFlags(
flags, cmStrCat("CMAKE_", linkType, "_LINKER_FLAGS"),
this->GeneratorTarget, cmBuildStep::Link, linkLanguage, config);
cmValue targetLinkFlags = this->GeneratorTarget->GetProperty("LINK_FLAGS");
if (targetLinkFlags) {
flags += ' ';

View File

@ -44,6 +44,7 @@
\* CMP0160
\* CMP0162
\* CMP0179
\* CMP0181
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)

View File

@ -0,0 +1,3 @@
set(reference_file "LINKER.txt")
include ("${CMAKE_CURRENT_LIST_DIR}/LINKER_expansion-validation.cmake")

View File

@ -0,0 +1,3 @@
set(reference_file "LINKER.txt")
include ("${CMAKE_CURRENT_LIST_DIR}/LINKER_expansion-validation.cmake")

View File

@ -0,0 +1,3 @@
set(reference_file "LINKER.txt")
include ("${CMAKE_CURRENT_LIST_DIR}/LINKER_expansion-validation.cmake")

View File

@ -0,0 +1,2 @@
include ("${CMAKE_CURRENT_LIST_DIR}/LINKER_expansion2-CMP0181-OLD-validation.cmake")

View File

@ -0,0 +1,2 @@
include ("${CMAKE_CURRENT_LIST_DIR}/LINKER_expansion2-CMP0181-OLD-validation.cmake")

View File

@ -0,0 +1,2 @@
include ("${CMAKE_CURRENT_LIST_DIR}/LINKER_expansion2-CMP0181-OLD-validation.cmake")

View File

@ -0,0 +1,5 @@
if (NOT actual_stdout MATCHES "LINKER:-foo,bar")
set (RunCMake_TEST_FAILED "LINKER: prefix was expanded.")
return()
endif()

View File

@ -0,0 +1,56 @@
enable_language(C)
cmake_policy(SET CMP0181 ${CMP0181})
# ensure command line is always displayed and do not use any response file
set(CMAKE_VERBOSE_MAKEFILE TRUE)
if (CMAKE_GENERATOR MATCHES "Borland|NMake")
string(REPLACE "${CMAKE_START_TEMP_FILE}" "" CMAKE_C_LINK_EXECUTABLE "${CMAKE_C_LINK_EXECUTABLE}")
string(REPLACE "${CMAKE_END_TEMP_FILE}" "" CMAKE_C_LINK_EXECUTABLE "${CMAKE_C_LINK_EXECUTABLE}")
string(REPLACE "${CMAKE_START_TEMP_FILE}" "" CMAKE_C_CREATE_SHARED_LIBRARY "${CMAKE_C_CREATE_SHARED_LIBRARY}")
string(REPLACE "${CMAKE_END_TEMP_FILE}" "" CMAKE_C_CREATE_SHARED_LIBRARY "${CMAKE_C_CREATE_SHARED_LIBRARY}")
string(REPLACE "${CMAKE_START_TEMP_FILE}" "" CMAKE_C_CREATE_SHARED_MODULE "${CMAKE_C_CREATE_SHARED_MODULE}")
string(REPLACE "${CMAKE_END_TEMP_FILE}" "" CMAKE_C_CREATE_SHARED_MODULE "${CMAKE_C_CREATE_SHARED_MODULE}")
endif()
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} LINKER:-foo,bar")
add_executable(exe_linker_flags main.c)
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} LINKER:-foo,bar")
add_library(shared_linker_flags SHARED LinkOptionsLib.c)
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} LINKER:-foo,bar")
add_library(module_linker_flags MODULE LinkOptionsLib.c)
# generate reference for LINKER flag
if (CMP0181 STREQUAL "NEW")
if (CMAKE_C_LINKER_WRAPPER_FLAG)
set(linker_flag ${CMAKE_C_LINKER_WRAPPER_FLAG})
list(GET linker_flag -1 linker_space)
if (linker_space STREQUAL " ")
list(REMOVE_AT linker_flag -1)
else()
set(linker_space)
endif()
list (JOIN linker_flag " " linker_flag)
if (CMAKE_C_LINKER_WRAPPER_FLAG_SEP)
set(linker_sep "${CMAKE_C_LINKER_WRAPPER_FLAG_SEP}")
string (APPEND linker_flag "${linker_space}" "-foo${linker_sep}bar")
else()
set(linker_prefix "${linker_flag}${linker_space}")
set (linker_flag "${linker_prefix}-foo ${linker_prefix}bar")
endif()
else()
set(linker_flag "-foo bar")
endif()
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/LINKER.txt" "${linker_flag}")
endif()

View File

@ -20,3 +20,18 @@ if(RunCMake_GENERATOR MATCHES "(Ninja|Makefile)")
run_cmake_target(LINKER_expansion LINKER_SHELL linker_shell)
run_cmake_target(LINKER_expansion LINKER_CONSUMER linker_consumer)
endif()
# Some environments are excluded because they are not able to honor verbose mode
if (RunCMake_GENERATOR MATCHES "Makefiles|Ninja|Xcode|Visual Studio"
AND NOT CMAKE_C_COMPILER_ID STREQUAL "Intel")
set(RunCMake_TEST_OUTPUT_MERGE TRUE)
foreach(policy IN ITEMS OLD NEW)
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/LINKER_expansion2-CMP0181-${policy}-build)
run_cmake_with_options(LINKER_expansion2 -DCMP0181=${policy})
run_cmake_target(LINKER_expansion2-CMP0181-${policy} EXE_LINKER_FLAGS exe_linker_flags --verbose)
run_cmake_target(LINKER_expansion2-CMP0181-${policy} SHARED_LINKER_FLAGS shared_linker_flags --verbose)
run_cmake_target(LINKER_expansion2-CMP0181-${policy} MODULE_LINKER_FLAGS module_linker_flags --verbose)
endforeach()
endif()

View File

@ -0,0 +1,4 @@
int main(void)
{
return 0;
}