summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2024-09-25 12:58:00 (GMT)
committerKitware Robot <kwrobot@kitware.com>2024-09-25 12:58:26 (GMT)
commit506255b1f1ba2b7a7d4babce4b86d30238977d87 (patch)
tree8a1980362f3ea4d24b896021903da1aba2f9e44a
parent57480c767647601d6a1c541667d781838f56d8ae (diff)
parente3895f4a8bcce3d9caae7d0e5559e6f057725fad (diff)
downloadCMake-506255b1f1ba2b7a7d4babce4b86d30238977d87.zip
CMake-506255b1f1ba2b7a7d4babce4b86d30238977d87.tar.gz
CMake-506255b1f1ba2b7a7d4babce4b86d30238977d87.tar.bz2
Merge topic 'nested_linker_prefixes'
e3895f4a8b Linking: Preserve nested LINKER: prefixes as written 4185dfbe1b Tests/LINK_OPTIONS: extract common code in test (NFC) 54381b5a81 Linking: extract wrapping linker options to a lambda (NFC) Acked-by: Kitware Robot <kwrobot@kitware.com> Acked-by: buildbot <buildbot@kitware.com> Merge-request: !9823
-rw-r--r--Source/cmGeneratorTarget_Options.cxx118
-rw-r--r--Tests/RunCMake/target_link_options/LINKER_expansion-LINKER-check.cmake1
-rw-r--r--Tests/RunCMake/target_link_options/LINKER_expansion-LINKER_NESTED-check.cmake4
-rw-r--r--Tests/RunCMake/target_link_options/LINKER_expansion-LINKER_NESTED_SHELL-check.cmake4
-rw-r--r--Tests/RunCMake/target_link_options/LINKER_expansion-LINKER_SHELL-check.cmake1
-rw-r--r--Tests/RunCMake/target_link_options/LINKER_expansion-validation.cmake8
-rw-r--r--Tests/RunCMake/target_link_options/LINKER_expansion.cmake44
-rw-r--r--Tests/RunCMake/target_link_options/RunCMakeTest.cmake2
8 files changed, 115 insertions, 67 deletions
diff --git a/Source/cmGeneratorTarget_Options.cxx b/Source/cmGeneratorTarget_Options.cxx
index f77ef72..d8b3eb3 100644
--- a/Source/cmGeneratorTarget_Options.cxx
+++ b/Source/cmGeneratorTarget_Options.cxx
@@ -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;
@@ -111,6 +118,48 @@ std::vector<BT<std::string>> wrapOptions(
return result;
}
+ auto insertWrapped = [&](std::vector<std::string>& opts) {
+ if (!wrapperSep.empty()) {
+ if (concatFlagAndArgs) {
+ // insert flag elements except last one
+ for (auto i = wrapperFlag.begin(); i != wrapperFlag.end() - 1; ++i) {
+ result.emplace_back(*i, bt);
+ }
+ // concatenate last flag element and all list values
+ // in one option
+ result.emplace_back(wrapperFlag.back() + cmJoin(opts, wrapperSep), bt);
+ } else {
+ for (std::string const& i : wrapperFlag) {
+ result.emplace_back(i, bt);
+ }
+ // concatenate all list values in one option
+ result.emplace_back(cmJoin(opts, wrapperSep), bt);
+ }
+ } else {
+ // prefix each element of list with wrapper
+ if (concatFlagAndArgs) {
+ std::transform(opts.begin(), opts.end(), opts.begin(),
+ [&wrapperFlag](std::string const& o) -> std::string {
+ return wrapperFlag.back() + o;
+ });
+ }
+ for (std::string& o : opts) {
+ for (auto i = wrapperFlag.begin(),
+ e = concatFlagAndArgs ? wrapperFlag.end() - 1
+ : wrapperFlag.end();
+ i != e; ++i) {
+ result.emplace_back(*i, bt);
+ }
+ result.emplace_back(std::move(o), bt);
+ }
+ }
+ };
+
+ 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:")) {
@@ -154,40 +203,7 @@ std::vector<BT<std::string>> wrapOptions(
continue;
}
- if (!wrapperSep.empty()) {
- if (concatFlagAndArgs) {
- // insert flag elements except last one
- for (auto i = wrapperFlag.begin(); i != wrapperFlag.end() - 1; ++i) {
- result.emplace_back(*i, bt);
- }
- // concatenate last flag element and all list values
- // in one option
- result.emplace_back(wrapperFlag.back() + cmJoin(opts, wrapperSep), bt);
- } else {
- for (std::string const& i : wrapperFlag) {
- result.emplace_back(i, bt);
- }
- // concatenate all list values in one option
- result.emplace_back(cmJoin(opts, wrapperSep), bt);
- }
- } else {
- // prefix each element of list with wrapper
- if (concatFlagAndArgs) {
- std::transform(opts.begin(), opts.end(), opts.begin(),
- [&wrapperFlag](std::string const& o) -> std::string {
- return wrapperFlag.back() + o;
- });
- }
- for (std::string& o : opts) {
- for (auto i = wrapperFlag.begin(),
- e = concatFlagAndArgs ? wrapperFlag.end() - 1
- : wrapperFlag.end();
- i != e; ++i) {
- result.emplace_back(*i, bt);
- }
- result.emplace_back(std::move(o), bt);
- }
- }
+ insertWrapped(opts);
}
return result;
}
@@ -484,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,
@@ -534,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);
@@ -569,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;
diff --git a/Tests/RunCMake/target_link_options/LINKER_expansion-LINKER-check.cmake b/Tests/RunCMake/target_link_options/LINKER_expansion-LINKER-check.cmake
index d0ef8de..99f5aa3 100644
--- a/Tests/RunCMake/target_link_options/LINKER_expansion-LINKER-check.cmake
+++ b/Tests/RunCMake/target_link_options/LINKER_expansion-LINKER-check.cmake
@@ -1,2 +1,3 @@
+set(reference_file "LINKER.txt")
include ("${CMAKE_CURRENT_LIST_DIR}/LINKER_expansion-validation.cmake")
diff --git a/Tests/RunCMake/target_link_options/LINKER_expansion-LINKER_NESTED-check.cmake b/Tests/RunCMake/target_link_options/LINKER_expansion-LINKER_NESTED-check.cmake
new file mode 100644
index 0000000..522fe86
--- /dev/null
+++ b/Tests/RunCMake/target_link_options/LINKER_expansion-LINKER_NESTED-check.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")
diff --git a/Tests/RunCMake/target_link_options/LINKER_expansion-LINKER_NESTED_SHELL-check.cmake b/Tests/RunCMake/target_link_options/LINKER_expansion-LINKER_NESTED_SHELL-check.cmake
new file mode 100644
index 0000000..917455c
--- /dev/null
+++ b/Tests/RunCMake/target_link_options/LINKER_expansion-LINKER_NESTED_SHELL-check.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")
diff --git a/Tests/RunCMake/target_link_options/LINKER_expansion-LINKER_SHELL-check.cmake b/Tests/RunCMake/target_link_options/LINKER_expansion-LINKER_SHELL-check.cmake
index d0ef8de..99f5aa3 100644
--- a/Tests/RunCMake/target_link_options/LINKER_expansion-LINKER_SHELL-check.cmake
+++ b/Tests/RunCMake/target_link_options/LINKER_expansion-LINKER_SHELL-check.cmake
@@ -1,2 +1,3 @@
+set(reference_file "LINKER.txt")
include ("${CMAKE_CURRENT_LIST_DIR}/LINKER_expansion-validation.cmake")
diff --git a/Tests/RunCMake/target_link_options/LINKER_expansion-validation.cmake b/Tests/RunCMake/target_link_options/LINKER_expansion-validation.cmake
index 1af8f13..27adde6 100644
--- a/Tests/RunCMake/target_link_options/LINKER_expansion-validation.cmake
+++ b/Tests/RunCMake/target_link_options/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.")
diff --git a/Tests/RunCMake/target_link_options/LINKER_expansion.cmake b/Tests/RunCMake/target_link_options/LINKER_expansion.cmake
index f86d19f..2219218 100644
--- a/Tests/RunCMake/target_link_options/LINKER_expansion.cmake
+++ b/Tests/RunCMake/target_link_options/LINKER_expansion.cmake
@@ -14,26 +14,30 @@ add_executable(dump dump.c)
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}")
+function (add_test_library target_name)
+ add_library(${target_name} SHARED LinkOptionsLib.c)
-# Use LINKER alone
-add_library(linker SHARED LinkOptionsLib.c)
-target_link_options(linker PRIVATE "LINKER:-foo,bar")
+ # use LAUNCH facility to dump linker command
+ set_property(TARGET ${target_name} PROPERTY RULE_LAUNCH_LINK "\"${DUMP_EXE}\"")
-# use LAUNCH facility to dump linker command
-set_property(TARGET linker PROPERTY RULE_LAUNCH_LINK "\"${DUMP_EXE}\"")
-
-add_dependencies (linker dump)
+ add_dependencies(${target_name} dump)
+endfunction()
+# Use LINKER alone
+add_test_library(linker)
+target_link_options(linker PRIVATE "LINKER:-foo,bar")
# Use LINKER with SHELL
-add_library(linker_shell SHARED LinkOptionsLib.c)
+add_test_library(linker_shell)
target_link_options(linker_shell PRIVATE "LINKER:SHELL:-foo bar")
-# use LAUNCH facility to dump linker command
-set_property(TARGET linker_shell PROPERTY RULE_LAUNCH_LINK "\"${DUMP_EXE}\"")
-
-add_dependencies (linker_shell dump)
+# 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)
@@ -46,11 +50,23 @@ if (CMAKE_C_LINKER_WRAPPER_FLAG)
endif()
list (JOIN linker_flag " " linker_flag)
if (CMAKE_C_LINKER_WRAPPER_FLAG_SEP)
- string (APPEND linker_flag "${linker_space}" "-foo${CMAKE_C_LINKER_WRAPPER_FLAG_SEP}bar")
+ 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_flag "${linker_flag}${linker_space}-foo ${linker_flag}${linker_space}bar")
+ 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}")
diff --git a/Tests/RunCMake/target_link_options/RunCMakeTest.cmake b/Tests/RunCMake/target_link_options/RunCMakeTest.cmake
index ff0c5a8..5562c9e 100644
--- a/Tests/RunCMake/target_link_options/RunCMakeTest.cmake
+++ b/Tests/RunCMake/target_link_options/RunCMakeTest.cmake
@@ -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)