mirror of
https://github.com/Kitware/CMake.git
synced 2025-10-24 19:59:47 +08:00
target_link_libraries: Add support for the LINKER: prefix
It is now possible to use the `LINKER:` prefix in `LINK_LIBRARIES` and `INTERFACE_LINK_LIBRARIES` target properties. Fixes: #26318
This commit is contained in:
24
Help/command/LINK_LIBRARIES_LINKER.txt
Normal file
24
Help/command/LINK_LIBRARIES_LINKER.txt
Normal file
@@ -0,0 +1,24 @@
|
||||
Handling Compiler Driver Differences
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. versionadded:: 3.32
|
||||
|
||||
To pass options to the linker tool, each compiler driver has its own syntax.
|
||||
The ``LINKER:`` prefix and ``,`` separator can be used to specify, in a portable
|
||||
way, options to pass to the linker tool. ``LINKER:`` is replaced by the
|
||||
appropriate driver option and ``,`` by the appropriate driver separator.
|
||||
The driver prefix and driver separator are given by the values of the
|
||||
:variable:`CMAKE_<LANG>_LINKER_WRAPPER_FLAG` and
|
||||
:variable:`CMAKE_<LANG>_LINKER_WRAPPER_FLAG_SEP` variables.
|
||||
|
||||
For example, ``"LINKER:-z,defs"`` becomes ``-Xlinker -z -Xlinker defs`` for
|
||||
``Clang`` and ``-Wl,-z,defs`` for ``GNU GCC``.
|
||||
|
||||
The ``LINKER:`` prefix supports, as an alternative syntax, specification of
|
||||
arguments using the ``SHELL:`` prefix and space as separator. The previous
|
||||
example then becomes ``"LINKER:SHELL:-z defs"``.
|
||||
|
||||
.. note::
|
||||
|
||||
Specifying the ``SHELL:`` prefix anywhere other than at the beginning of the
|
||||
``LINKER:`` prefix is not supported.
|
||||
@@ -148,6 +148,8 @@ command lines.
|
||||
See the :manual:`cmake-buildsystem(7)` manual for more on defining
|
||||
buildsystem properties.
|
||||
|
||||
.. include:: ../command/LINK_LIBRARIES_LINKER.txt
|
||||
|
||||
Libraries for a Target and/or its Dependents
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
||||
@@ -32,6 +32,8 @@ direct link dependencies of a target's dependents by using the
|
||||
:prop_tgt:`INTERFACE_LINK_LIBRARIES_DIRECT` and
|
||||
:prop_tgt:`INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE` target properties.
|
||||
|
||||
.. include:: ../command/LINK_LIBRARIES_LINKER.txt
|
||||
|
||||
Creating Relocatable Packages
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
||||
@@ -8,3 +8,9 @@ INTERFACE_LINK_OPTIONS
|
||||
.. |PROPERTY_INTERFACE_NAME| replace:: ``INTERFACE_LINK_OPTIONS``
|
||||
.. |PROPERTY_LINK| replace:: :prop_tgt:`LINK_OPTIONS`
|
||||
.. include:: INTERFACE_BUILD_PROPERTY.txt
|
||||
|
||||
.. include:: ../command/DEVICE_LINK_OPTIONS.txt
|
||||
|
||||
.. include:: ../command/OPTIONS_SHELL.txt
|
||||
|
||||
.. include:: ../command/LINK_OPTIONS_LINKER.txt
|
||||
|
||||
@@ -33,3 +33,5 @@ See the :variable:`CMAKE_LINK_LIBRARIES_STRATEGY` variable and
|
||||
corresponding :prop_tgt:`LINK_LIBRARIES_STRATEGY` target property
|
||||
for details on how CMake orders direct link dependencies on linker
|
||||
command lines.
|
||||
|
||||
.. include:: ../command/LINK_LIBRARIES_LINKER.txt
|
||||
|
||||
5
Help/release/dev/target_link_libraries-LINKER-prefix.rst
Normal file
5
Help/release/dev/target_link_libraries-LINKER-prefix.rst
Normal file
@@ -0,0 +1,5 @@
|
||||
target_link_libraries-LINKER-prefix
|
||||
-----------------------------------
|
||||
|
||||
* The :command:`target_link_libraries` command gains the support of the
|
||||
``LINKER:`` prefix.
|
||||
@@ -1883,6 +1883,7 @@ void cmComputeLinkInformation::AddUserItem(LinkEntry const& entry,
|
||||
// foo ==> -lfoo
|
||||
// libfoo.a ==> -Wl,-Bstatic -lfoo
|
||||
|
||||
const cm::string_view LINKER{ "LINKER:" };
|
||||
BT<std::string> const& item = entry.Item;
|
||||
|
||||
if (item.Value[0] == '-' || item.Value[0] == '$' || item.Value[0] == '`') {
|
||||
@@ -1905,6 +1906,13 @@ void cmComputeLinkInformation::AddUserItem(LinkEntry const& entry,
|
||||
this->Items.emplace_back(item, ItemIsPath::No);
|
||||
return;
|
||||
}
|
||||
if (cmHasPrefix(item.Value, LINKER)) {
|
||||
std::vector<BT<std::string>> linkerFlag{ 1, item };
|
||||
this->Target->ResolveLinkerWrapper(linkerFlag, this->GetLinkLanguage(),
|
||||
true);
|
||||
this->Items.emplace_back(linkerFlag.front(), ItemIsPath::No);
|
||||
return;
|
||||
}
|
||||
|
||||
// Parse out the prefix, base, and suffix components of the
|
||||
// library name. If the name matches that of a shared or static
|
||||
|
||||
@@ -875,6 +875,7 @@ add_RunCMake_test(target_link_libraries-LINK_GROUP -DCMAKE_SYSTEM_NAME=${CMAKE_S
|
||||
-DCMAKE_IMPORT_LIBRARY_PREFIX=${CMAKE_IMPORT_LIBRARY_PREFIX}
|
||||
-DCMAKE_IMPORT_LIBRARY_SUFFIX=${CMAKE_IMPORT_LIBRARY_SUFFIX}
|
||||
-DCMAKE_LINK_LIBRARY_FLAG=${CMAKE_LINK_LIBRARY_FLAG})
|
||||
add_RunCMake_test(target_link_libraries-LINKER-prefix -DCMAKE_C_COMPILER_ID=${CMAKE_C_COMPILER_ID})
|
||||
add_RunCMake_test(add_link_options -DCMAKE_C_COMPILER_ID=${CMAKE_C_COMPILER_ID})
|
||||
add_RunCMake_test(target_link_options -DCMAKE_C_COMPILER_ID=${CMAKE_C_COMPILER_ID}
|
||||
-DCMake_TEST_CUDA=${CMake_TEST_CUDA})
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
cmake_minimum_required(VERSION 3.30...3.32)
|
||||
|
||||
project(${RunCMake_TEST} LANGUAGES NONE)
|
||||
|
||||
include(${RunCMake_TEST}.cmake)
|
||||
@@ -0,0 +1,3 @@
|
||||
|
||||
set(reference_file "LINKER.txt")
|
||||
include ("${CMAKE_CURRENT_LIST_DIR}/LINKER_expansion-validation.cmake")
|
||||
@@ -0,0 +1,3 @@
|
||||
|
||||
set(reference_file "LINKER.txt")
|
||||
include ("${CMAKE_CURRENT_LIST_DIR}/LINKER_expansion-validation.cmake")
|
||||
@@ -0,0 +1,3 @@
|
||||
|
||||
set(reference_file "LINKER.txt")
|
||||
include ("${CMAKE_CURRENT_LIST_DIR}/LINKER_expansion-validation.cmake")
|
||||
@@ -0,0 +1,15 @@
|
||||
|
||||
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}/${reference_file}")
|
||||
set (RunCMake_TEST_FAILED "${RunCMake_TEST_BINARY_DIR}/${reference_file}: Reference file not found.")
|
||||
return()
|
||||
endif()
|
||||
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.")
|
||||
endif()
|
||||
@@ -0,0 +1,63 @@
|
||||
|
||||
enable_language(C)
|
||||
|
||||
set(cfg_dir)
|
||||
get_property(_isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
|
||||
if(_isMultiConfig)
|
||||
set(cfg_dir /Debug)
|
||||
endif()
|
||||
set(DUMP_EXE "${CMAKE_CURRENT_BINARY_DIR}${cfg_dir}/dump${CMAKE_EXECUTABLE_SUFFIX}")
|
||||
|
||||
add_executable(dump dump.c)
|
||||
|
||||
# ensure no temp file nor response file will be used
|
||||
set(CMAKE_C_USE_RESPONSE_FILE_FOR_LIBRARIES 0)
|
||||
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 LAUNCH facility to dump linker command
|
||||
set_property(TARGET ${target_name} PROPERTY RULE_LAUNCH_LINK "\"${DUMP_EXE}\"")
|
||||
|
||||
add_dependencies(${target_name} dump)
|
||||
endfunction()
|
||||
|
||||
# Use LINKER alone
|
||||
add_test_library(linker)
|
||||
target_link_libraries(linker PRIVATE "LINKER:-foo,bar")
|
||||
|
||||
# Use LINKER with SHELL
|
||||
add_test_library(linker_shell)
|
||||
target_link_libraries(linker_shell PRIVATE "LINKER:SHELL:-foo bar")
|
||||
|
||||
# Propagate LINKER
|
||||
add_library(linker_interface INTERFACE)
|
||||
target_link_libraries(linker_interface INTERFACE "LINKER:-foo,bar")
|
||||
add_test_library(linker_consumer)
|
||||
target_link_libraries(linker_consumer PRIVATE linker_interface)
|
||||
|
||||
# generate reference for LINKER flag
|
||||
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}")
|
||||
@@ -0,0 +1,7 @@
|
||||
#if defined(_WIN32)
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
int flags_lib(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
|
||||
include(RunCMake)
|
||||
|
||||
macro(run_cmake_target test subtest target)
|
||||
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${test}-build)
|
||||
set(RunCMake_TEST_NO_CLEAN 1)
|
||||
run_cmake_command(${test}-${subtest} ${CMAKE_COMMAND} --build . --target ${target} ${ARGN})
|
||||
|
||||
unset(RunCMake_TEST_BINARY_DIR)
|
||||
unset(RunCMake_TEST_NO_CLEAN)
|
||||
endmacro()
|
||||
|
||||
|
||||
run_cmake(bad_SHELL_usage)
|
||||
|
||||
if(RunCMake_GENERATOR MATCHES "(Ninja|Makefile)")
|
||||
run_cmake(LINKER_expansion)
|
||||
|
||||
run_cmake_target(LINKER_expansion LINKER linker)
|
||||
run_cmake_target(LINKER_expansion LINKER_SHELL linker_shell)
|
||||
run_cmake_target(LINKER_expansion LINKER_CONSUMER linker_consumer)
|
||||
endif()
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1,4 @@
|
||||
CMake Error at bad_SHELL_usage.cmake:[0-9]+ \(add_library\):
|
||||
'SHELL:' prefix is not supported as part of 'LINKER:' arguments.
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists.txt:[0-9]+ \(include\)
|
||||
@@ -0,0 +1,5 @@
|
||||
|
||||
enable_language(C)
|
||||
|
||||
add_library(example SHARED LinkOptionsLib.c)
|
||||
target_link_libraries(example PRIVATE "LINKER:-foo,SHELL:-bar")
|
||||
13
Tests/RunCMake/target_link_libraries-LINKER-prefix/dump.c
Normal file
13
Tests/RunCMake/target_link_libraries-LINKER-prefix/dump.c
Normal file
@@ -0,0 +1,13 @@
|
||||
|
||||
#include "stdio.h"
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 1; i < argc; i++)
|
||||
printf("%s ", argv[i]);
|
||||
printf("\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user