mirror of
https://github.com/Kitware/CMake.git
synced 2026-01-09 15:20:56 -06:00
Linking: Preserve nested LINKER: prefixes as written
Previously LINKER:,-Xlinker and -Wl, options nested inside LINKER: prefixes would be transformed to separate prefixed options. This is confusing and undocumented behavior, instead preserve these as written. Fixes: #26298
This commit is contained in:
@@ -7,6 +7,7 @@
|
||||
#include "cmConfigure.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
@@ -91,10 +92,16 @@ void processOptions(cmGeneratorTarget const* tgt,
|
||||
}
|
||||
}
|
||||
|
||||
enum class NestedLinkerFlags
|
||||
{
|
||||
PreserveAsSpelled,
|
||||
Normalize,
|
||||
};
|
||||
|
||||
std::vector<BT<std::string>> wrapOptions(
|
||||
std::vector<std::string>& options, const cmListFileBacktrace& bt,
|
||||
const std::vector<std::string>& wrapperFlag, const std::string& wrapperSep,
|
||||
bool concatFlagAndArgs)
|
||||
bool concatFlagAndArgs, NestedLinkerFlags nestedLinkerFlags)
|
||||
{
|
||||
std::vector<BT<std::string>> result;
|
||||
|
||||
@@ -148,6 +155,11 @@ std::vector<BT<std::string>> wrapOptions(
|
||||
}
|
||||
};
|
||||
|
||||
if (nestedLinkerFlags == NestedLinkerFlags::PreserveAsSpelled) {
|
||||
insertWrapped(options);
|
||||
return result;
|
||||
}
|
||||
|
||||
for (std::vector<std::string>::size_type index = 0; index < options.size();
|
||||
index++) {
|
||||
if (cmHasLiteralPrefix(options[index], "LINKER:")) {
|
||||
@@ -488,8 +500,9 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetLinkOptions(
|
||||
// host link options must be wrapped
|
||||
std::vector<std::string> options;
|
||||
cmSystemTools::ParseUnixCommandLine(it->Value.c_str(), options);
|
||||
auto hostOptions = wrapOptions(options, it->Backtrace, wrapperFlag,
|
||||
wrapperSep, concatFlagAndArgs);
|
||||
auto hostOptions =
|
||||
wrapOptions(options, it->Backtrace, wrapperFlag, wrapperSep,
|
||||
concatFlagAndArgs, NestedLinkerFlags::Normalize);
|
||||
it = result.erase(it);
|
||||
// some compilers (like gcc 4.8 or Intel 19.0 or XLC 16) do not respect
|
||||
// C++11 standard: 'std::vector::insert()' do not returns an iterator,
|
||||
@@ -538,12 +551,11 @@ std::vector<BT<std::string>>& cmGeneratorTarget::ResolveLinkerWrapper(
|
||||
const std::string SHELL{ "SHELL:" };
|
||||
const std::string LINKER_SHELL = LINKER + SHELL;
|
||||
|
||||
std::vector<BT<std::string>>::iterator entry;
|
||||
while ((entry = std::find_if(result.begin(), result.end(),
|
||||
[&LINKER](BT<std::string> const& item) -> bool {
|
||||
return item.Value.compare(0, LINKER.length(),
|
||||
LINKER) == 0;
|
||||
})) != result.end()) {
|
||||
for (auto entry = result.begin(); entry != result.end(); ++entry) {
|
||||
if (entry->Value.compare(0, LINKER.length(), LINKER) != 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string value = std::move(entry->Value);
|
||||
cmListFileBacktrace bt = std::move(entry->Backtrace);
|
||||
entry = result.erase(entry);
|
||||
@@ -573,15 +585,19 @@ std::vector<BT<std::string>>& cmGeneratorTarget::ResolveLinkerWrapper(
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<BT<std::string>> options = wrapOptions(
|
||||
linkerOptions, bt, wrapperFlag, wrapperSep, concatFlagAndArgs);
|
||||
// Very old versions of the C++ standard library return void for insert, so
|
||||
// can't use it to get the new iterator
|
||||
const auto index = entry - result.begin();
|
||||
std::vector<BT<std::string>> options =
|
||||
wrapOptions(linkerOptions, bt, wrapperFlag, wrapperSep,
|
||||
concatFlagAndArgs, NestedLinkerFlags::PreserveAsSpelled);
|
||||
if (joinItems) {
|
||||
result.insert(entry,
|
||||
cmJoin(cmRange<decltype(options.cbegin())>(
|
||||
options.cbegin(), options.cend()),
|
||||
" "_s));
|
||||
result.insert(
|
||||
entry, cmJoin(cmMakeRange(options.begin(), options.end()), " "_s));
|
||||
entry = std::next(result.begin(), index);
|
||||
} else {
|
||||
result.insert(entry, options.begin(), options.end());
|
||||
entry = std::next(result.begin(), index + options.size() - 1);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
|
||||
set(reference_file "LINKER.txt")
|
||||
include ("${CMAKE_CURRENT_LIST_DIR}/LINKER_expansion-validation.cmake")
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
|
||||
set(reference_file "LINKER_NESTED.txt")
|
||||
set(linker_prefix_expected YES)
|
||||
include ("${CMAKE_CURRENT_LIST_DIR}/LINKER_expansion-validation.cmake")
|
||||
@@ -0,0 +1,4 @@
|
||||
|
||||
set(reference_file "LINKER_NESTED_SHELL.txt")
|
||||
set(linker_prefix_expected YES)
|
||||
include ("${CMAKE_CURRENT_LIST_DIR}/LINKER_expansion-validation.cmake")
|
||||
@@ -1,2 +1,3 @@
|
||||
|
||||
set(reference_file "LINKER.txt")
|
||||
include ("${CMAKE_CURRENT_LIST_DIR}/LINKER_expansion-validation.cmake")
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
|
||||
if (actual_stdout MATCHES "LINKER:")
|
||||
if (actual_stdout MATCHES "LINKER:" AND NOT linker_prefix_expected)
|
||||
set (RunCMake_TEST_FAILED "LINKER: prefix was not expanded.")
|
||||
return()
|
||||
endif()
|
||||
|
||||
if (NOT EXISTS "${RunCMake_TEST_BINARY_DIR}/LINKER.txt")
|
||||
set (RunCMake_TEST_FAILED "${RunCMake_TEST_BINARY_DIR}/LINKER.txt: Reference file not found.")
|
||||
if (NOT EXISTS "${RunCMake_TEST_BINARY_DIR}/${reference_file}")
|
||||
set (RunCMake_TEST_FAILED "${RunCMake_TEST_BINARY_DIR}/${reference_file}: Reference file not found.")
|
||||
return()
|
||||
endif()
|
||||
file(READ "${RunCMake_TEST_BINARY_DIR}/LINKER.txt" linker_flag)
|
||||
file(READ "${RunCMake_TEST_BINARY_DIR}/${reference_file}" linker_flag)
|
||||
|
||||
if (NOT actual_stdout MATCHES "${linker_flag}")
|
||||
set (RunCMake_TEST_FAILED "LINKER: was not expanded correctly.")
|
||||
|
||||
@@ -31,6 +31,14 @@ target_link_options(linker PRIVATE "LINKER:-foo,bar")
|
||||
add_test_library(linker_shell)
|
||||
target_link_options(linker_shell PRIVATE "LINKER:SHELL:-foo bar")
|
||||
|
||||
# Nested LINKER: prefixes should be preserved as written, only the outermost LINKER: prefix removed
|
||||
add_test_library(linker_nested)
|
||||
target_link_options(linker_nested PRIVATE "LINKER:LINKER:-foo,-Xlinker=bar,-Xlinker,--baz,-Wl,/qux")
|
||||
|
||||
# Same with LINKER:SHELL:
|
||||
add_test_library(linker_nested_shell SHARED LinkOptionsLib.c)
|
||||
target_link_options(linker_nested_shell PRIVATE "LINKER:SHELL:LINKER:-foo -Xlinker=bar -Xlinker --baz -Wl,/qux")
|
||||
|
||||
# generate reference for LINKER flag
|
||||
if (CMAKE_C_LINKER_WRAPPER_FLAG)
|
||||
set(linker_flag ${CMAKE_C_LINKER_WRAPPER_FLAG})
|
||||
@@ -43,12 +51,22 @@ if (CMAKE_C_LINKER_WRAPPER_FLAG)
|
||||
list (JOIN linker_flag " " linker_flag)
|
||||
if (CMAKE_C_LINKER_WRAPPER_FLAG_SEP)
|
||||
set(linker_sep "${CMAKE_C_LINKER_WRAPPER_FLAG_SEP}")
|
||||
|
||||
set(linker_flag_nested "${linker_flag}${linker_space}LINKER:-foo${linker_sep}-Xlinker=bar${linker_sep}-Xlinker${linker_sep}--baz${linker_sep}-Wl${linker_sep}/qux")
|
||||
set(linker_flag_nested_shell "${linker_flag}${linker_space}LINKER:-foo${linker_sep}-Xlinker=bar${linker_sep}-Xlinker${linker_sep}--baz${linker_sep}-Wl,/qux")
|
||||
string (APPEND linker_flag "${linker_space}" "-foo${linker_sep}bar")
|
||||
else()
|
||||
set(linker_prefix "${linker_flag}${linker_space}")
|
||||
|
||||
set(linker_flag_nested "${linker_prefix}LINKER:-foo ${linker_prefix}-Xlinker=bar ${linker_prefix}-Xlinker ${linker_prefix}--baz ${linker_prefix}-Wl ${linker_prefix}/qux")
|
||||
set(linker_flag_nested_shell "${linker_prefix}LINKER:-foo ${linker_prefix}-Xlinker=bar ${linker_prefix}-Xlinker ${linker_prefix}--baz ${linker_prefix}-Wl,/qux")
|
||||
set (linker_flag "${linker_prefix}-foo ${linker_prefix}bar")
|
||||
endif()
|
||||
else()
|
||||
set(linker_flag_nested "LINKER:-foo -Xlinker=bar -Xlinker --baz -Wl /qux")
|
||||
set(linker_flag_nested_shell "LINKER:-foo -Xlinker=bar -Xlinker --baz -Wl,/qux")
|
||||
set(linker_flag "-foo bar")
|
||||
endif()
|
||||
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/LINKER.txt" "${linker_flag}")
|
||||
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/LINKER_NESTED.txt" "${linker_flag_nested}")
|
||||
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/LINKER_NESTED_SHELL.txt" "${linker_flag_nested_shell}")
|
||||
|
||||
@@ -76,6 +76,8 @@ if(RunCMake_GENERATOR MATCHES "(Ninja|Makefile)")
|
||||
|
||||
run_cmake_target(LINKER_expansion LINKER linker)
|
||||
run_cmake_target(LINKER_expansion LINKER_SHELL linker_shell)
|
||||
run_cmake_target(LINKER_expansion LINKER_NESTED linker_nested)
|
||||
run_cmake_target(LINKER_expansion LINKER_NESTED_SHELL linker_nested_shell)
|
||||
endif()
|
||||
|
||||
run_cmake(empty_keyword_args)
|
||||
|
||||
Reference in New Issue
Block a user