mirror of
https://github.com/Kitware/CMake.git
synced 2025-10-20 04:24:36 +08:00
Add options to specify linker tool
Offer the capability, through variable `CMAKE_LINKER_TYPE`, as well as the target property `LINKER_TYPE` to specify which linker must be used. The implementation of this capability is specified by variables specific to the language and linker type: `CMAKE_<LANG>_USING_LINKER_<TYPE>`. Some definitions are provided as part of `CMake`. For example, to select the `LLVM` linker rather than the standard one, the type `LLD` should be specified through the variable `CMAKE_LINKER_TYPE`. And, on `Apple`, `Linux` and some environments on `Windows`, the variable `CMAKE_<LANG>_USING_LINKER_LLD` has value `-fuse-ld=lld`. And for `Windows` environments based on `MSVC`, where the linker is used directly, the tool `lld-link.exe` will be used rather than `link.exe`. Fixes: #19174, #24254, #24990
This commit is contained in:
@@ -336,6 +336,7 @@ Properties on Targets
|
||||
/prop_tgt/LINK_SEARCH_START_STATIC
|
||||
/prop_tgt/LINK_WHAT_YOU_USE
|
||||
/prop_tgt/LINKER_LANGUAGE
|
||||
/prop_tgt/LINKER_TYPE
|
||||
/prop_tgt/LOCATION
|
||||
/prop_tgt/LOCATION_CONFIG
|
||||
/prop_tgt/MACHO_COMPATIBILITY_VERSION
|
||||
|
@@ -474,6 +474,8 @@ Variables that Control the Build
|
||||
/variable/CMAKE_LANG_LINK_LIBRARY_USING_FEATURE_SUPPORTED
|
||||
/variable/CMAKE_LANG_LINK_WHAT_YOU_USE_FLAG
|
||||
/variable/CMAKE_LANG_LINKER_LAUNCHER
|
||||
/variable/CMAKE_LANG_USING_LINKER_MODE
|
||||
/variable/CMAKE_LANG_USING_LINKER_TYPE
|
||||
/variable/CMAKE_LANG_VISIBILITY_PRESET
|
||||
/variable/CMAKE_LIBRARY_OUTPUT_DIRECTORY
|
||||
/variable/CMAKE_LIBRARY_OUTPUT_DIRECTORY_CONFIG
|
||||
@@ -490,6 +492,7 @@ Variables that Control the Build
|
||||
/variable/CMAKE_LINK_LIBRARY_USING_FEATURE_SUPPORTED
|
||||
/variable/CMAKE_LINK_WHAT_YOU_USE
|
||||
/variable/CMAKE_LINK_WHAT_YOU_USE_CHECK
|
||||
/variable/CMAKE_LINKER_TYPE
|
||||
/variable/CMAKE_MACOSX_BUNDLE
|
||||
/variable/CMAKE_MACOSX_RPATH
|
||||
/variable/CMAKE_MAP_IMPORTED_CONFIG_CONFIG
|
||||
|
26
Help/prop_tgt/LINKER_TYPE.rst
Normal file
26
Help/prop_tgt/LINKER_TYPE.rst
Normal file
@@ -0,0 +1,26 @@
|
||||
LINKER_TYPE
|
||||
-----------
|
||||
|
||||
.. versionadded:: 3.29
|
||||
|
||||
Specify which linker will be used for the link step. The property value may use
|
||||
:manual:`generator expressions <cmake-generator-expressions(7)>`.
|
||||
|
||||
.. code-block:: cmake
|
||||
|
||||
add_library(lib1 SHARED ...)
|
||||
set_property(TARGET lib1 PROPERTY LINKER_TYPE LLD)
|
||||
|
||||
This specifies that ``lib1`` should use linker type ``LLD`` for the link step.
|
||||
The implementation details will be provided by the variable
|
||||
:variable:`CMAKE_<LANG>_USING_LINKER_<TYPE>` with ``<TYPE>`` having the value
|
||||
``LLD``.
|
||||
|
||||
This property is not supported on :generator:`Green Hills MULTI` and
|
||||
:generator:`Visual Studio 9 2008` generators.
|
||||
|
||||
.. note::
|
||||
It is assumed that the linker specified is fully compatible with the standard
|
||||
one. CMake will not do any options translation.
|
||||
|
||||
.. include:: ../variable/LINKER_PREDEFINED_TYPES.txt
|
6
Help/release/dev/Linker-user-selection.rst
Normal file
6
Help/release/dev/Linker-user-selection.rst
Normal file
@@ -0,0 +1,6 @@
|
||||
Linker-user-selection
|
||||
---------------------
|
||||
|
||||
* The linker tool can now be specified for a selection of compilers/platforms
|
||||
by setting :variable:`CMAKE_LINKER_TYPE` variable or :prop_tgt:`LINKER_TYPE`
|
||||
target property.
|
15
Help/variable/CMAKE_LANG_USING_LINKER_MODE.rst
Normal file
15
Help/variable/CMAKE_LANG_USING_LINKER_MODE.rst
Normal file
@@ -0,0 +1,15 @@
|
||||
CMAKE_<LANG>_USING_LINKER_MODE
|
||||
------------------------------
|
||||
|
||||
.. versionadded:: 3.29
|
||||
|
||||
This variable specify what is the type of data stored in variable
|
||||
:variable:`CMAKE_<LANG>_USING_LINKER_<TYPE>`. There are two possible values:
|
||||
|
||||
``FLAG``
|
||||
:variable:`CMAKE_<LANG>_USING_LINKER_<TYPE>` holds compiler flags. This is
|
||||
the default.
|
||||
|
||||
``TOOL``
|
||||
:variable:`CMAKE_<LANG>_USING_LINKER_<TYPE>` holds the path to the linker
|
||||
tool.
|
30
Help/variable/CMAKE_LANG_USING_LINKER_TYPE.rst
Normal file
30
Help/variable/CMAKE_LANG_USING_LINKER_TYPE.rst
Normal file
@@ -0,0 +1,30 @@
|
||||
CMAKE_<LANG>_USING_LINKER_<TYPE>
|
||||
--------------------------------
|
||||
|
||||
.. versionadded:: 3.29
|
||||
|
||||
This variable defines how to specify the linker for the link step for the type
|
||||
as specified by the variable :variable:`CMAKE_LINKER_TYPE` or the target
|
||||
property :prop_tgt:`LINKER_TYPE`. It can hold compiler flags for the link step
|
||||
or directly the linker tool. The type of data is given by the variable
|
||||
:variable:`CMAKE_<LANG>_USING_LINKER_MODE`.
|
||||
|
||||
For example, to specify the ``LLVM`` linker for ``GNU`` compilers, we have:
|
||||
|
||||
.. code-block:: cmake
|
||||
|
||||
set(CMAKE_C_USING_LINKER_LLD "-fuse-ld=lld")
|
||||
|
||||
Or on ``Windows`` platform, for ``Clang`` compilers simulating ``MSVC``, we
|
||||
have:
|
||||
|
||||
.. code-block:: cmake
|
||||
|
||||
set(CMAKE_C_USING_LINKER_LLD "-fuse-ld=lld-link")
|
||||
|
||||
And for the ``MSVC`` compiler, linker is directly used, so we have:
|
||||
|
||||
.. code-block:: cmake
|
||||
|
||||
set(CMAKE_C_USING_LINKER_LLD "/path/to/lld-link.exe")
|
||||
set(CMAKE_C_USING_LINKER_MODE TOOL)
|
18
Help/variable/CMAKE_LINKER_TYPE.rst
Normal file
18
Help/variable/CMAKE_LINKER_TYPE.rst
Normal file
@@ -0,0 +1,18 @@
|
||||
CMAKE_LINKER_TYPE
|
||||
-----------------
|
||||
|
||||
.. versionadded:: 3.29
|
||||
|
||||
Specify which linker will be used for the link step.
|
||||
|
||||
.. note::
|
||||
It is assumed that the linker specified is fully compatible with the standard
|
||||
one. CMake will not do any options translation.
|
||||
|
||||
This variable is used to initialize the :prop_tgt:`LINKER_TYPE` target
|
||||
property when they are created by calls to :command:`add_library` or
|
||||
:command:`add_executable` commands. It is meaningful only for targets having a
|
||||
link step. If set, its value is also used by the :command:`try_compile`
|
||||
command.
|
||||
|
||||
.. include:: LINKER_PREDEFINED_TYPES.txt
|
57
Help/variable/LINKER_PREDEFINED_TYPES.txt
Normal file
57
Help/variable/LINKER_PREDEFINED_TYPES.txt
Normal file
@@ -0,0 +1,57 @@
|
||||
Linker types are case-sensitive and may only contain letters, numbers and
|
||||
underscores. Linker types defined in all uppercase are reserved for CMake's own
|
||||
built-in types. The pre-defined linker types are:
|
||||
|
||||
``DEFAULT``
|
||||
This type corresponds to standard linking, essentially equivalent to
|
||||
not specifying :prop_tgt:`LINKER_TYPE` target property.
|
||||
|
||||
``SYSTEM``
|
||||
Use the standard linker delivered by the platform or the standard toolkit
|
||||
(for example, ``SYSTEM`` imply Microsoft linker for all ``MSVC`` compatible
|
||||
compilers). This type is supported for the following platforms/compilers:
|
||||
|
||||
* Linux, for ``GNU``, ``Clang`` and ``NVIDIA`` compilers.
|
||||
* All Apple variants for ``AppleClang``, ``Clang`` and ``GNU`` compilers.
|
||||
* Windows, for ``MSVC``, ``GNU``, ``Clang`` and ``NVIDIA`` compilers.
|
||||
|
||||
``LLD``
|
||||
Use the ``LLVM`` linker. This type is supported for the following
|
||||
platforms/compilers:
|
||||
|
||||
* Linux, for ``GNU``, ``Clang`` and ``NVIDIA`` compilers.
|
||||
* All Apple variants for ``Clang`` and ``AppleClang`` compilers.
|
||||
* Windows, for ``GNU``, ``Clang`` compilers with ``GNU`` front-end and
|
||||
``CLang``, ``MSVC`` and ``NVIDIA`` compilers with ``MSVC`` front-end.
|
||||
|
||||
``BFD``
|
||||
Use the ``GNU`` linker. This type is supported for the following
|
||||
platforms/compilers:
|
||||
|
||||
* Linux, for ``GNU``, ``Clang`` and ``NVIDIA`` compilers.
|
||||
* Windows, for ``GNU``, ``Clang`` compilers with ``GNU`` front-end.
|
||||
|
||||
``GOLD``
|
||||
Supported on Linux platform for ``GNU``, ``Clang`` and ``NVIDIA`` compilers.
|
||||
|
||||
``MOLD``
|
||||
Use the `mold linker <https://github.com/rui314/mold>`_. This type is
|
||||
supported on the following platforms:
|
||||
|
||||
* Linux platform for ``GNU``, ``Clang`` and ``NVIDIA`` compilers.
|
||||
* All Apple variants for ``Clang`` and ``AppleClang`` compilers as an
|
||||
alias to ``SOLD``.
|
||||
|
||||
``SOLD``
|
||||
Use the `sold linker <https://github.com/bluewhalesystems/sold>`_. This type
|
||||
is only supported on Apple platforms for ``Clang`` and ``AppleClang``
|
||||
compilers.
|
||||
|
||||
``APPLE_CLASSIC``
|
||||
Use the Apple linker in the classic behavior (i.e. before ``Xcode 15.0``).
|
||||
This type is only supported on Apple platforms for ``GNU``, ``Clang`` and
|
||||
``AppleClang`` compilers.
|
||||
|
||||
``MSVC``
|
||||
Use the Microsoft linker. This type is only supported on Windows
|
||||
platform for ``MSVC`` and ``Clang`` compiler with ``MSVC`` front-end.
|
@@ -5,6 +5,8 @@ set(CMAKE_ASM@ASM_DIALECT@_COMPILER_AR "@_CMAKE_ASM_COMPILER_AR@")
|
||||
set(CMAKE_RANLIB "@CMAKE_RANLIB@")
|
||||
set(CMAKE_ASM@ASM_DIALECT@_COMPILER_RANLIB "@_CMAKE_ASM_COMPILER_RANLIB@")
|
||||
set(CMAKE_LINKER "@CMAKE_LINKER@")
|
||||
set(CMAKE_LINKER_LINK "@CMAKE_LINKER_LINK@")
|
||||
set(CMAKE_LINKER_LLD "@CMAKE_LINKER_LLD@")
|
||||
set(CMAKE_MT "@CMAKE_MT@")
|
||||
set(CMAKE_TAPI "@CMAKE_TAPI@")
|
||||
set(CMAKE_ASM@ASM_DIALECT@_COMPILER_LOADED 1)
|
||||
|
@@ -26,6 +26,8 @@ set(CMAKE_C_COMPILER_AR "@CMAKE_C_COMPILER_AR@")
|
||||
set(CMAKE_RANLIB "@CMAKE_RANLIB@")
|
||||
set(CMAKE_C_COMPILER_RANLIB "@CMAKE_C_COMPILER_RANLIB@")
|
||||
set(CMAKE_LINKER "@CMAKE_LINKER@")
|
||||
set(CMAKE_LINKER_LINK "@CMAKE_LINKER_LINK@")
|
||||
set(CMAKE_LINKER_LLD "@CMAKE_LINKER_LLD@")
|
||||
set(CMAKE_MT "@CMAKE_MT@")
|
||||
set(CMAKE_TAPI "@CMAKE_TAPI@")
|
||||
set(CMAKE_COMPILER_IS_GNUCC @CMAKE_COMPILER_IS_GNUCC@)
|
||||
|
@@ -72,5 +72,7 @@ set(CMAKE_CUDA_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "@CMAKE_CUDA_IMPLICIT_LINK_FR
|
||||
@_SET_CMAKE_CUDA_RUNTIME_LIBRARY_DEFAULT@
|
||||
|
||||
set(CMAKE_LINKER "@CMAKE_LINKER@")
|
||||
set(CMAKE_LINKER_LINK "@CMAKE_LINKER_LINK@")
|
||||
set(CMAKE_LINKER_LLD "@CMAKE_LINKER_LLD@")
|
||||
set(CMAKE_AR "@CMAKE_AR@")
|
||||
set(CMAKE_MT "@CMAKE_MT@")
|
||||
|
@@ -27,6 +27,8 @@ set(CMAKE_CXX_COMPILER_AR "@CMAKE_CXX_COMPILER_AR@")
|
||||
set(CMAKE_RANLIB "@CMAKE_RANLIB@")
|
||||
set(CMAKE_CXX_COMPILER_RANLIB "@CMAKE_CXX_COMPILER_RANLIB@")
|
||||
set(CMAKE_LINKER "@CMAKE_LINKER@")
|
||||
set(CMAKE_LINKER_LINK "@CMAKE_LINKER_LINK@")
|
||||
set(CMAKE_LINKER_LLD "@CMAKE_LINKER_LLD@")
|
||||
set(CMAKE_MT "@CMAKE_MT@")
|
||||
set(CMAKE_TAPI "@CMAKE_TAPI@")
|
||||
set(CMAKE_COMPILER_IS_GNUCXX @CMAKE_COMPILER_IS_GNUCXX@)
|
||||
|
@@ -60,6 +60,13 @@ endfunction()
|
||||
__resolve_tool_path(CMAKE_LINKER "${_CMAKE_TOOLCHAIN_LOCATION}" "Default Linker")
|
||||
__resolve_tool_path(CMAKE_MT "${_CMAKE_TOOLCHAIN_LOCATION}" "Default Manifest Tool")
|
||||
|
||||
macro(__resolve_linker_path __linker_type __name __search_path __doc)
|
||||
if(NOT CMAKE_LINKER_${__linker_type})
|
||||
set( CMAKE_LINKER_${__linker_type} "${__name}")
|
||||
endif()
|
||||
__resolve_tool_path(CMAKE_LINKER_${__linker_type} "${__search_path}" "${__doc}")
|
||||
endmacro()
|
||||
|
||||
set(_CMAKE_TOOL_VARS "")
|
||||
|
||||
# if it's the MS C/CXX compiler, search for link
|
||||
@@ -93,6 +100,10 @@ if(("x${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_SIMULATE_ID}" STREQUAL "xMSVC" AND
|
||||
|
||||
list(APPEND _CMAKE_TOOL_VARS LINKER MT AR)
|
||||
|
||||
# look-up for possible usable linker
|
||||
__resolve_linker_path(LINK "link" "${_CMAKE_TOOLCHAIN_LOCATION}" "link Linker")
|
||||
__resolve_linker_path(LLD "lld-link" "${_CMAKE_TOOLCHAIN_LOCATION}" "lld-link Linker")
|
||||
|
||||
elseif("x${CMAKE_${_CMAKE_PROCESSING_LANGUAGE}_COMPILER_ID}" MATCHES "^x(Open)?Watcom$")
|
||||
set(_CMAKE_LINKER_NAMES "wlink")
|
||||
set(_CMAKE_AR_NAMES "wlib")
|
||||
|
@@ -74,5 +74,7 @@ set(CMAKE_HIP_COMPILER_AR "@CMAKE_HIP_COMPILER_AR@")
|
||||
set(CMAKE_RANLIB "@CMAKE_RANLIB@")
|
||||
set(CMAKE_HIP_COMPILER_RANLIB "@CMAKE_HIP_COMPILER_RANLIB@")
|
||||
set(CMAKE_LINKER "@CMAKE_LINKER@")
|
||||
set(CMAKE_LINKER_LINK "@CMAKE_LINKER_LINK@")
|
||||
set(CMAKE_LINKER_LLD "@CMAKE_LINKER_LLD@")
|
||||
set(CMAKE_MT "@CMAKE_MT@")
|
||||
set(CMAKE_TAPI "@CMAKE_TAPI@")
|
||||
|
@@ -24,6 +24,8 @@ set(CMAKE_OBJC_COMPILER_AR "@CMAKE_OBJC_COMPILER_AR@")
|
||||
set(CMAKE_RANLIB "@CMAKE_RANLIB@")
|
||||
set(CMAKE_OBJC_COMPILER_RANLIB "@CMAKE_OBJC_COMPILER_RANLIB@")
|
||||
set(CMAKE_LINKER "@CMAKE_LINKER@")
|
||||
set(CMAKE_LINKER_LINK "@CMAKE_LINKER_LINK@")
|
||||
set(CMAKE_LINKER_LLD "@CMAKE_LINKER_LLD@")
|
||||
set(CMAKE_MT "@CMAKE_MT@")
|
||||
set(CMAKE_TAPI "@CMAKE_TAPI@")
|
||||
set(CMAKE_COMPILER_IS_GNUOBJC @CMAKE_COMPILER_IS_GNUOBJC@)
|
||||
|
@@ -25,6 +25,8 @@ set(CMAKE_OBJCXX_COMPILER_AR "@CMAKE_OBJCXX_COMPILER_AR@")
|
||||
set(CMAKE_RANLIB "@CMAKE_RANLIB@")
|
||||
set(CMAKE_OBJCXX_COMPILER_RANLIB "@CMAKE_OBJCXX_COMPILER_RANLIB@")
|
||||
set(CMAKE_LINKER "@CMAKE_LINKER@")
|
||||
set(CMAKE_LINKER_LINK "@CMAKE_LINKER_LINK@")
|
||||
set(CMAKE_LINKER_LLD "@CMAKE_LINKER_LLD@")
|
||||
set(CMAKE_MT "@CMAKE_MT@")
|
||||
set(CMAKE_TAPI "@CMAKE_TAPI@")
|
||||
set(CMAKE_COMPILER_IS_GNUOBJCXX @CMAKE_COMPILER_IS_GNUOBJCXX@)
|
||||
|
@@ -18,6 +18,13 @@ macro(__apple_compiler_clang lang)
|
||||
set(CMAKE_${lang}_LINK_LIBRARY_USING_FRAMEWORK "-framework <LIBRARY>")
|
||||
set(CMAKE_${lang}_LINK_LIBRARY_USING_FRAMEWORK_SUPPORTED TRUE)
|
||||
|
||||
# linker selection
|
||||
set(CMAKE_${lang}_USING_LINKER_SYSTEM "-fuse-ld=ld")
|
||||
set(CMAKE_${lang}_USING_LINKER_APPLE_CLASSIC "-fuse-ld=ld" "LINKER:-ld_classic")
|
||||
set(CMAKE_${lang}_USING_LINKER_LLD "-fuse-ld=lld")
|
||||
set(CMAKE_${lang}_USING_LINKER_MOLD "-fuse-ld=mold")
|
||||
set(CMAKE_${lang}_USING_LINKER_SOLD "-fuse-ld=sold")
|
||||
|
||||
if(_CMAKE_OSX_SYSROOT_PATH MATCHES "/iPhoneOS")
|
||||
set(CMAKE_${lang}_OSX_DEPLOYMENT_TARGET_FLAG "-miphoneos-version-min=")
|
||||
elseif(_CMAKE_OSX_SYSROOT_PATH MATCHES "/iPhoneSimulator")
|
||||
|
@@ -17,6 +17,9 @@ macro(__apple_compiler_gnu lang)
|
||||
|
||||
set(CMAKE_${lang}_LINK_LIBRARY_USING_FRAMEWORK "-framework <LIBRARY>")
|
||||
set(CMAKE_${lang}_LINK_LIBRARY_USING_FRAMEWORK_SUPPORTED TRUE)
|
||||
|
||||
set(CMAKE_${lang}_USING_LINKER_SYSTEM "")
|
||||
set(CMAKE_${lang}_USING_LINKER_APPLE_CLASSIC "LINKER:-ld_classic")
|
||||
endmacro()
|
||||
|
||||
macro(cmake_gnu_set_sysroot_flag lang)
|
||||
|
2
Modules/Platform/Linux-Clang-CUDA.cmake
Normal file
2
Modules/Platform/Linux-Clang-CUDA.cmake
Normal file
@@ -0,0 +1,2 @@
|
||||
include(Platform/Linux-GNU)
|
||||
__linux_compiler_gnu(CUDA)
|
@@ -12,4 +12,11 @@ macro(__linux_compiler_gnu lang)
|
||||
# We pass this for historical reasons. Projects may have
|
||||
# executables that use dlopen but do not set ENABLE_EXPORTS.
|
||||
set(CMAKE_SHARED_LIBRARY_LINK_${lang}_FLAGS "-rdynamic")
|
||||
|
||||
# linker selection
|
||||
set(CMAKE_${lang}_USING_LINKER_SYSTEM "")
|
||||
set(CMAKE_${lang}_USING_LINKER_LLD "-fuse-ld=lld")
|
||||
set(CMAKE_${lang}_USING_LINKER_BFD "-fuse-ld=bfd")
|
||||
set(CMAKE_${lang}_USING_LINKER_GOLD "-fuse-ld=gold")
|
||||
set(CMAKE_${lang}_USING_LINKER_MOLD "-fuse-ld=mold")
|
||||
endmacro()
|
||||
|
7
Modules/Platform/Linux-NVIDIA-CUDA.cmake
Normal file
7
Modules/Platform/Linux-NVIDIA-CUDA.cmake
Normal file
@@ -0,0 +1,7 @@
|
||||
|
||||
# linker selection
|
||||
set(CMAKE_CUDA_USING_LINKER_SYSTEM "")
|
||||
set(CMAKE_CUDA_USING_LINKER_LLD "-fuse-ld=lld")
|
||||
set(CMAKE_CUDA_USING_LINKER_BFD "-fuse-ld=bfd")
|
||||
set(CMAKE_CUDA_USING_LINKER_GOLD "-fuse-ld=gold")
|
||||
set(CMAKE_CUDA_USING_LINKER_MOLD "-fuse-ld=mold")
|
@@ -53,6 +53,12 @@ macro(__windows_compiler_clang_gnu lang)
|
||||
set(CMAKE_${lang}_LINK_OPTIONS_NO_PIE "")
|
||||
set(CMAKE_SHARED_LIBRARY_${lang}_FLAGS "")
|
||||
|
||||
# linker selection
|
||||
set(CMAKE_${lang}_USING_LINKER_DEFAULT "-fuse-ld=lld-link")
|
||||
set(CMAKE_${lang}_USING_LINKER_SYSTEM "-fuse-ld=link")
|
||||
set(CMAKE_${lang}_USING_LINKER_LLD "-fuse-ld=lld-link")
|
||||
set(CMAKE_${lang}_USING_LINKER_MSVC "-fuse-ld=link")
|
||||
|
||||
set(CMAKE_${lang}_USE_RESPONSE_FILE_FOR_OBJECTS 1)
|
||||
set(CMAKE_${lang}_USE_RESPONSE_FILE_FOR_LIBRARIES 1)
|
||||
set(CMAKE_${lang}_USE_RESPONSE_FILE_FOR_INCLUDES 1)
|
||||
@@ -74,10 +80,10 @@ macro(__windows_compiler_clang_gnu lang)
|
||||
set(CMAKE_${lang}_ARCHIVE_APPEND "<CMAKE_AR> q <TARGET> <LINK_FLAGS> <OBJECTS>")
|
||||
set(CMAKE_${lang}_ARCHIVE_FINISH "<CMAKE_RANLIB> <TARGET>")
|
||||
set(CMAKE_${lang}_CREATE_SHARED_LIBRARY
|
||||
"<CMAKE_${lang}_COMPILER> -fuse-ld=lld-link -nostartfiles -nostdlib <CMAKE_SHARED_LIBRARY_${lang}_FLAGS> <LANGUAGE_COMPILE_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS> -o <TARGET> ${CMAKE_GNULD_IMAGE_VERSION} -Xlinker /MANIFEST:EMBED -Xlinker /implib:<TARGET_IMPLIB> -Xlinker /pdb:<TARGET_PDB> -Xlinker /version:<TARGET_VERSION_MAJOR>.<TARGET_VERSION_MINOR> <OBJECTS> <LINK_LIBRARIES> <MANIFESTS>")
|
||||
"<CMAKE_${lang}_COMPILER> -nostartfiles -nostdlib <CMAKE_SHARED_LIBRARY_${lang}_FLAGS> <LANGUAGE_COMPILE_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_${lang}_FLAGS> -o <TARGET> ${CMAKE_GNULD_IMAGE_VERSION} -Xlinker /MANIFEST:EMBED -Xlinker /implib:<TARGET_IMPLIB> -Xlinker /pdb:<TARGET_PDB> -Xlinker /version:<TARGET_VERSION_MAJOR>.<TARGET_VERSION_MINOR> <OBJECTS> <LINK_LIBRARIES> <MANIFESTS>")
|
||||
set(CMAKE_${lang}_CREATE_SHARED_MODULE ${CMAKE_${lang}_CREATE_SHARED_LIBRARY})
|
||||
set(CMAKE_${lang}_LINK_EXECUTABLE
|
||||
"<CMAKE_${lang}_COMPILER> -fuse-ld=lld-link -nostartfiles -nostdlib <FLAGS> <CMAKE_${lang}_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> -Xlinker /MANIFEST:EMBED -Xlinker /implib:<TARGET_IMPLIB> -Xlinker /pdb:<TARGET_PDB> -Xlinker /version:<TARGET_VERSION_MAJOR>.<TARGET_VERSION_MINOR> ${CMAKE_GNULD_IMAGE_VERSION} <LINK_LIBRARIES> <MANIFESTS>")
|
||||
"<CMAKE_${lang}_COMPILER> -nostartfiles -nostdlib <FLAGS> <CMAKE_${lang}_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> -Xlinker /MANIFEST:EMBED -Xlinker /implib:<TARGET_IMPLIB> -Xlinker /pdb:<TARGET_PDB> -Xlinker /version:<TARGET_VERSION_MAJOR>.<TARGET_VERSION_MINOR> ${CMAKE_GNULD_IMAGE_VERSION} <LINK_LIBRARIES> <MANIFESTS>")
|
||||
|
||||
set(CMAKE_${lang}_CREATE_WIN32_EXE "-Xlinker /subsystem:windows")
|
||||
set(CMAKE_${lang}_CREATE_CONSOLE_EXE "-Xlinker /subsystem:console")
|
||||
|
@@ -112,6 +112,11 @@ macro(__windows_compiler_gnu lang)
|
||||
set(CMAKE_${type}_LINK_DYNAMIC_${lang}_FLAGS "-Wl,-Bdynamic")
|
||||
endforeach()
|
||||
|
||||
# linker selection
|
||||
set(CMAKE_${lang}_USING_LINKER_SYSTEM "")
|
||||
set(CMAKE_${lang}_USING_LINKER_BFD "-fuse-ld=bfd")
|
||||
set(CMAKE_${lang}_USING_LINKER_LLD "-fuse-ld=lld")
|
||||
|
||||
# No -fPIC on Windows
|
||||
set(CMAKE_${lang}_COMPILE_OPTIONS_PIC "")
|
||||
set(CMAKE_${lang}_COMPILE_OPTIONS_PIE "")
|
||||
|
@@ -512,6 +512,12 @@ macro(__windows_compiler_msvc lang)
|
||||
set(CMAKE_DEPFILE_FLAGS_${lang} "/showIncludes")
|
||||
set(CMAKE_${lang}_DEPFILE_FORMAT msvc)
|
||||
endif()
|
||||
|
||||
# linker selection
|
||||
set(CMAKE_${lang}_USING_LINKER_SYSTEM "${CMAKE_LINKER_LINK}")
|
||||
set(CMAKE_${lang}_USING_LINKER_LLD "${CMAKE_LINKER_LLD}")
|
||||
set(CMAKE_${lang}_USING_LINKER_MSVC "${CMAKE_LINKER_LINK}")
|
||||
set(CMAKE_${lang}_USING_LINKER_MODE TOOL)
|
||||
endmacro()
|
||||
|
||||
macro(__windows_compiler_msvc_enable_rc flags)
|
||||
|
@@ -47,6 +47,12 @@ set(CMAKE_CUDA_DEVICE_LINK_EXECUTABLE
|
||||
"<CMAKE_CUDA_COMPILER> ${_CMAKE_CUDA_EXTRA_FLAGS} <LANGUAGE_COMPILE_FLAGS> <LINK_FLAGS> ${_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS} -shared -dlink <OBJECTS> -o <TARGET> <LINK_LIBRARIES> -Xcompiler=-Fd<TARGET_COMPILE_PDB>,-FS${__IMPLICIT_DLINK_FLAGS}")
|
||||
unset(__IMPLICIT_DLINK_FLAGS)
|
||||
|
||||
# linker selection
|
||||
set(CMAKE_CUDA_USING_LINKER_SYSTEM "${CMAKE_LINKER_LINK}")
|
||||
set(CMAKE_CUDA_USING_LINKER_LLD "${CMAKE_LINKER_LLD}")
|
||||
set(CMAKE_CUDA_USING_LINKER_MSVC "${CMAKE_LINKER_LINK}")
|
||||
set(CMAKE_CUDA_USING_LINKER_MODE TOOL)
|
||||
|
||||
string(REPLACE "/D" "-D" _PLATFORM_DEFINES_CUDA "${_PLATFORM_DEFINES}${_PLATFORM_DEFINES_CXX}")
|
||||
|
||||
if(CMAKE_MSVC_RUNTIME_LIBRARY_DEFAULT)
|
||||
|
@@ -14,6 +14,7 @@
|
||||
|
||||
#include "cmsys/Directory.hxx"
|
||||
#include "cmsys/FStream.hxx"
|
||||
#include "cmsys/RegularExpression.hxx"
|
||||
|
||||
#include "cmArgumentParser.h"
|
||||
#include "cmConfigureLog.h"
|
||||
@@ -83,6 +84,7 @@ std::string const kCMAKE_HIP_PLATFORM = "CMAKE_HIP_PLATFORM";
|
||||
std::string const kCMAKE_HIP_RUNTIME_LIBRARY = "CMAKE_HIP_RUNTIME_LIBRARY";
|
||||
std::string const kCMAKE_ISPC_INSTRUCTION_SETS = "CMAKE_ISPC_INSTRUCTION_SETS";
|
||||
std::string const kCMAKE_ISPC_HEADER_SUFFIX = "CMAKE_ISPC_HEADER_SUFFIX";
|
||||
std::string const kCMAKE_LINKER_TYPE = "CMAKE_LINKER_TYPE";
|
||||
std::string const kCMAKE_LINK_SEARCH_END_STATIC =
|
||||
"CMAKE_LINK_SEARCH_END_STATIC";
|
||||
std::string const kCMAKE_LINK_SEARCH_START_STATIC =
|
||||
@@ -1114,6 +1116,20 @@ cm::optional<cmTryCompileResult> cmCoreTryCompile::TryCompileCode(
|
||||
vars.insert(varList.begin(), varList.end());
|
||||
}
|
||||
|
||||
if (this->Makefile->GetDefinition(kCMAKE_LINKER_TYPE)) {
|
||||
// propagate various variables to support linker selection
|
||||
vars.insert(kCMAKE_LINKER_TYPE);
|
||||
auto defs = this->Makefile->GetDefinitions();
|
||||
cmsys::RegularExpression linkerTypeDef{
|
||||
"^CMAKE_[A-Za-z]+_USING_LINKER_"
|
||||
};
|
||||
for (auto const& def : defs) {
|
||||
if (linkerTypeDef.find(def)) {
|
||||
vars.insert(def);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this->Makefile->GetPolicyStatus(cmPolicies::CMP0083) ==
|
||||
cmPolicies::NEW) {
|
||||
// To ensure full support of PIE, propagate cache variables
|
||||
|
@@ -175,14 +175,15 @@ bool cmGeneratorExpressionDAGChecker::EvaluatingLinkExpression() const
|
||||
cm::string_view property(this->Top()->Property);
|
||||
|
||||
return property == "LINK_DIRECTORIES"_s || property == "LINK_OPTIONS"_s ||
|
||||
property == "LINK_DEPENDS"_s || property == "LINK_LIBRARY_OVERRIDE"_s;
|
||||
property == "LINK_DEPENDS"_s || property == "LINK_LIBRARY_OVERRIDE"_s ||
|
||||
property == "LINKER_TYPE"_s;
|
||||
}
|
||||
|
||||
bool cmGeneratorExpressionDAGChecker::EvaluatingLinkOptionsExpression() const
|
||||
{
|
||||
cm::string_view property(this->Top()->Property);
|
||||
|
||||
return property == "LINK_OPTIONS"_s;
|
||||
return property == "LINK_OPTIONS"_s || property == "LINKER_TYPE"_s;
|
||||
}
|
||||
|
||||
bool cmGeneratorExpressionDAGChecker::EvaluatingLinkerLauncher() const
|
||||
|
@@ -868,6 +868,31 @@ cmValue cmGeneratorTarget::GetFeature(const std::string& feature,
|
||||
return this->LocalGenerator->GetFeature(feature, config);
|
||||
}
|
||||
|
||||
std::string cmGeneratorTarget::GetLinkerTypeProperty(
|
||||
std::string const& lang, std::string const& config) const
|
||||
{
|
||||
std::string propName{ "LINKER_TYPE" };
|
||||
auto linkerType = this->GetProperty(propName);
|
||||
if (!linkerType.IsEmpty()) {
|
||||
cmGeneratorExpressionDAGChecker dagChecker(this, propName, nullptr,
|
||||
nullptr);
|
||||
auto ltype =
|
||||
cmGeneratorExpression::Evaluate(*linkerType, this->GetLocalGenerator(),
|
||||
config, this, &dagChecker, this, lang);
|
||||
if (this->IsDeviceLink()) {
|
||||
cmList list{ ltype };
|
||||
const auto DL_BEGIN = "<DEVICE_LINK>"_s;
|
||||
const auto DL_END = "</DEVICE_LINK>"_s;
|
||||
cm::erase_if(list, [&](const std::string& item) {
|
||||
return item == DL_BEGIN || item == DL_END;
|
||||
});
|
||||
return list.to_string();
|
||||
}
|
||||
return ltype;
|
||||
}
|
||||
return std::string{};
|
||||
}
|
||||
|
||||
const char* cmGeneratorTarget::GetLinkPIEProperty(
|
||||
const std::string& config) const
|
||||
{
|
||||
@@ -5515,6 +5540,50 @@ std::string cmGeneratorTarget::GetLinkerLanguage(
|
||||
return this->GetLinkClosure(config)->LinkerLanguage;
|
||||
}
|
||||
|
||||
std::string cmGeneratorTarget::GetLinkerTool(const std::string& config) const
|
||||
{
|
||||
return this->GetLinkerTool(this->GetLinkerLanguage(config), config);
|
||||
}
|
||||
|
||||
std::string cmGeneratorTarget::GetLinkerTool(const std::string& lang,
|
||||
const std::string& config) const
|
||||
{
|
||||
auto usingLinker =
|
||||
cmStrCat("CMAKE_", lang, "_USING_", this->IsDeviceLink() ? "DEVICE_" : "",
|
||||
"LINKER_");
|
||||
auto format = this->Makefile->GetDefinition(cmStrCat(usingLinker, "MODE"));
|
||||
if (!format || format != "TOOL"_s) {
|
||||
return this->Makefile->GetDefinition("CMAKE_LINKER");
|
||||
}
|
||||
|
||||
auto linkerType = this->GetLinkerTypeProperty(lang, config);
|
||||
if (linkerType.empty()) {
|
||||
linkerType = "DEFAULT";
|
||||
}
|
||||
usingLinker = cmStrCat(usingLinker, linkerType);
|
||||
auto linkerTool = this->Makefile->GetDefinition(usingLinker);
|
||||
|
||||
if (!linkerTool) {
|
||||
if (this->GetGlobalGenerator()->IsVisualStudio() &&
|
||||
linkerType == "DEFAULT"_s) {
|
||||
return std::string{};
|
||||
}
|
||||
|
||||
// fall-back to generic definition
|
||||
linkerTool = this->Makefile->GetDefinition("CMAKE_LINKER");
|
||||
|
||||
if (linkerType != "DEFAULT"_s) {
|
||||
this->LocalGenerator->IssueMessage(
|
||||
MessageType::FATAL_ERROR,
|
||||
cmStrCat("LINKER_TYPE '", linkerType,
|
||||
"' is unknown. Did you forgot to define '", usingLinker,
|
||||
"' variable?"));
|
||||
}
|
||||
}
|
||||
|
||||
return linkerTool;
|
||||
}
|
||||
|
||||
std::string cmGeneratorTarget::GetPDBOutputName(
|
||||
const std::string& config) const
|
||||
{
|
||||
|
@@ -205,6 +205,9 @@ public:
|
||||
cmValue GetFeature(const std::string& feature,
|
||||
const std::string& config) const;
|
||||
|
||||
std::string GetLinkerTypeProperty(std::string const& lang,
|
||||
std::string const& config) const;
|
||||
|
||||
const char* GetLinkPIEProperty(const std::string& config) const;
|
||||
|
||||
bool IsIPOEnabled(std::string const& lang, std::string const& config) const;
|
||||
@@ -788,6 +791,10 @@ public:
|
||||
|
||||
//! Return the preferred linker language for this target
|
||||
std::string GetLinkerLanguage(const std::string& config) const;
|
||||
//! Return the preferred linker tool for this target
|
||||
std::string GetLinkerTool(const std::string& config) const;
|
||||
std::string GetLinkerTool(const std::string& lang,
|
||||
const std::string& config) const;
|
||||
|
||||
/** Does this target have a GNU implib to convert to MS format? */
|
||||
bool HasImplibGNUtoMS(std::string const& config) const;
|
||||
|
@@ -116,6 +116,19 @@ void cmGhsMultiTargetGenerator::Generate()
|
||||
|
||||
void cmGhsMultiTargetGenerator::GenerateTarget()
|
||||
{
|
||||
if (this->GeneratorTarget->GetType() == cmStateEnums::EXECUTABLE &&
|
||||
!this->GeneratorTarget
|
||||
->GetLinkerTypeProperty(
|
||||
this->GeneratorTarget->GetLinkerLanguage(this->ConfigName),
|
||||
this->ConfigName)
|
||||
.empty()) {
|
||||
// Green Hill MULTI does not support this feature.
|
||||
cmSystemTools::Message(
|
||||
cmStrCat("'LINKER_TYPE' property, specified on target '",
|
||||
this->GeneratorTarget->GetName(),
|
||||
"', is not supported by this generator."));
|
||||
}
|
||||
|
||||
// Open the target file in copy-if-different mode.
|
||||
std::string fproj =
|
||||
cmStrCat(this->LocalGenerator->GetCurrentBinaryDirectory(), '/',
|
||||
|
@@ -2500,6 +2500,9 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
|
||||
this->CurrentLocalGenerator->GetStaticLibraryFlags(
|
||||
extraLinkOptions, configName, llang, gtgt);
|
||||
} else {
|
||||
this->CurrentLocalGenerator->AppendLinkerTypeFlags(extraLinkOptions, gtgt,
|
||||
configName, llang);
|
||||
|
||||
cmValue targetLinkFlags = gtgt->GetProperty("LINK_FLAGS");
|
||||
if (targetLinkFlags) {
|
||||
this->CurrentLocalGenerator->AppendFlags(extraLinkOptions,
|
||||
|
@@ -82,7 +82,6 @@ static auto ruleReplaceVars = { "CMAKE_${LANG}_COMPILER",
|
||||
"CMAKE_CURRENT_SOURCE_DIR",
|
||||
"CMAKE_CURRENT_BINARY_DIR",
|
||||
"CMAKE_RANLIB",
|
||||
"CMAKE_LINKER",
|
||||
"CMAKE_MT",
|
||||
"CMAKE_TAPI",
|
||||
"CMAKE_CUDA_HOST_COMPILER",
|
||||
@@ -1604,6 +1603,7 @@ void cmLocalGenerator::GetTargetFlags(
|
||||
}
|
||||
|
||||
std::string extraLinkFlags;
|
||||
this->AppendLinkerTypeFlags(extraLinkFlags, target, config, linkLanguage);
|
||||
this->AppendPositionIndependentLinkerFlags(extraLinkFlags, target, config,
|
||||
linkLanguage);
|
||||
this->AppendIPOLinkerFlags(extraLinkFlags, target, config, linkLanguage);
|
||||
@@ -3200,6 +3200,49 @@ void cmLocalGenerator::AddUnityBuild(cmGeneratorTarget* target)
|
||||
}
|
||||
}
|
||||
|
||||
void cmLocalGenerator::AppendLinkerTypeFlags(std::string& flags,
|
||||
cmGeneratorTarget* target,
|
||||
const std::string& config,
|
||||
const std::string& linkLanguage)
|
||||
{
|
||||
switch (target->GetType()) {
|
||||
case cmStateEnums::EXECUTABLE:
|
||||
case cmStateEnums::SHARED_LIBRARY:
|
||||
case cmStateEnums::MODULE_LIBRARY:
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
auto usingLinker =
|
||||
cmStrCat("CMAKE_", linkLanguage, "_USING_",
|
||||
target->IsDeviceLink() ? "DEVICE_" : "", "LINKER_");
|
||||
|
||||
auto format = this->Makefile->GetDefinition(cmStrCat(usingLinker, "MODE"));
|
||||
if (format && format != "FLAG"_s) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto linkerType = target->GetLinkerTypeProperty(linkLanguage, config);
|
||||
if (linkerType.empty()) {
|
||||
linkerType = "DEFAULT";
|
||||
}
|
||||
usingLinker = cmStrCat(usingLinker, linkerType);
|
||||
auto linkerTypeFlags = this->Makefile->GetDefinition(usingLinker);
|
||||
if (linkerTypeFlags) {
|
||||
if (!linkerTypeFlags.IsEmpty()) {
|
||||
auto linkerFlags = cmExpandListWithBacktrace(linkerTypeFlags);
|
||||
target->ResolveLinkerWrapper(linkerFlags, linkLanguage);
|
||||
this->AppendFlags(flags, linkerFlags);
|
||||
}
|
||||
} else if (linkerType != "DEFAULT"_s) {
|
||||
this->IssueMessage(MessageType::FATAL_ERROR,
|
||||
cmStrCat("LINKER_TYPE '", linkerType,
|
||||
"' is unknown. Did you forgot to define '",
|
||||
usingLinker, "' variable?"));
|
||||
}
|
||||
}
|
||||
|
||||
void cmLocalGenerator::AppendIPOLinkerFlags(std::string& flags,
|
||||
cmGeneratorTarget* target,
|
||||
const std::string& config,
|
||||
|
@@ -177,6 +177,9 @@ public:
|
||||
void AddPchDependencies(cmGeneratorTarget* target);
|
||||
void AddUnityBuild(cmGeneratorTarget* target);
|
||||
virtual void AddXCConfigSources(cmGeneratorTarget* /* target */) {}
|
||||
void AppendLinkerTypeFlags(std::string& flags, cmGeneratorTarget* target,
|
||||
const std::string& config,
|
||||
const std::string& linkLanguage);
|
||||
void AppendIPOLinkerFlags(std::string& flags, cmGeneratorTarget* target,
|
||||
const std::string& config,
|
||||
const std::string& lang);
|
||||
|
@@ -32,6 +32,7 @@
|
||||
#include "cmList.h"
|
||||
#include "cmListFileCache.h"
|
||||
#include "cmMakefile.h"
|
||||
#include "cmMessageType.h"
|
||||
#include "cmOutputConverter.h"
|
||||
#include "cmPolicies.h"
|
||||
#include "cmSourceFile.h"
|
||||
@@ -1085,6 +1086,16 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(
|
||||
cmComputeLinkInformation& cli = *pcli;
|
||||
std::string linkLanguage = cli.GetLinkLanguage();
|
||||
|
||||
if (!target->GetLinkerTypeProperty(linkLanguage, configName).empty()) {
|
||||
// Visual Studio 10 or upper is required for this feature
|
||||
this->GetCMakeInstance()->IssueMessage(
|
||||
MessageType::FATAL_ERROR,
|
||||
cmStrCat("'LINKER_TYPE' property, specified on target '",
|
||||
target->GetName(),
|
||||
"', is not supported by this generator."),
|
||||
target->GetBacktrace());
|
||||
}
|
||||
|
||||
// Compute the variable name to lookup standard libraries for this
|
||||
// language.
|
||||
std::string standardLibsVar =
|
||||
@@ -1161,6 +1172,16 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(
|
||||
cmComputeLinkInformation& cli = *pcli;
|
||||
std::string linkLanguage = cli.GetLinkLanguage();
|
||||
|
||||
if (!target->GetLinkerTypeProperty(linkLanguage, configName).empty()) {
|
||||
// Visual Studio 10 or upper is required for this feature
|
||||
this->GetCMakeInstance()->IssueMessage(
|
||||
MessageType::FATAL_ERROR,
|
||||
cmStrCat("'LINKER_TYPE' property, specified on target '",
|
||||
target->GetName(),
|
||||
"', is not supported by this generator."),
|
||||
target->GetBacktrace());
|
||||
}
|
||||
|
||||
bool isWin32Executable = target->IsWin32Executable(configName);
|
||||
|
||||
// Compute the variable name to lookup standard libraries for this
|
||||
|
@@ -344,6 +344,8 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
|
||||
return;
|
||||
}
|
||||
|
||||
auto linker = this->GeneratorTarget->GetLinkerTool(this->GetConfigName());
|
||||
|
||||
// Build list of dependencies.
|
||||
std::vector<std::string> depends;
|
||||
this->AppendLinkDepends(depends, linkLanguage);
|
||||
@@ -533,6 +535,7 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
|
||||
vars.CMTargetType =
|
||||
cmState::GetTargetTypeName(this->GeneratorTarget->GetType()).c_str();
|
||||
vars.Language = linkLanguage.c_str();
|
||||
vars.Linker = linker.c_str();
|
||||
vars.AIXExports = aixExports.c_str();
|
||||
vars.Objects = buildObjs.c_str();
|
||||
std::string objectDir = this->GeneratorTarget->GetSupportDirectory();
|
||||
|
@@ -441,6 +441,8 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
|
||||
return;
|
||||
}
|
||||
|
||||
auto linker = this->GeneratorTarget->GetLinkerTool(this->GetConfigName());
|
||||
|
||||
// Build list of dependencies.
|
||||
std::vector<std::string> depends;
|
||||
this->AppendLinkDepends(depends, linkLanguage);
|
||||
@@ -766,6 +768,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
|
||||
vars.CMTargetType =
|
||||
cmState::GetTargetTypeName(this->GeneratorTarget->GetType()).c_str();
|
||||
vars.Language = linkLanguage.c_str();
|
||||
vars.Linker = linker.c_str();
|
||||
vars.AIXExports = aixExports.c_str();
|
||||
vars.Objects = buildObjs.c_str();
|
||||
std::string objectDir = this->GeneratorTarget->GetSupportDirectory();
|
||||
|
@@ -153,6 +153,8 @@ void cmMakefileTargetGenerator::GetTargetLinkFlags(
|
||||
this->LocalGenerator->AppendCompileOptions(flags, opts);
|
||||
this->LocalGenerator->SetLinkScriptShell(false);
|
||||
|
||||
this->LocalGenerator->AppendLinkerTypeFlags(
|
||||
flags, this->GeneratorTarget, this->GetConfigName(), linkLanguage);
|
||||
this->LocalGenerator->AppendPositionIndependentLinkerFlags(
|
||||
flags, this->GeneratorTarget, this->GetConfigName(), linkLanguage);
|
||||
this->LocalGenerator->AppendDependencyInfoLinkerFlags(
|
||||
|
@@ -294,6 +294,9 @@ void cmNinjaNormalTargetGenerator::WriteNvidiaDeviceLinkRule(
|
||||
.c_str();
|
||||
|
||||
vars.Language = "CUDA";
|
||||
std::string linker =
|
||||
this->GetGeneratorTarget()->GetLinkerTool("CUDA", config);
|
||||
vars.Linker = linker.c_str();
|
||||
|
||||
// build response file name
|
||||
std::string responseFlag = this->GetMakefile()->GetSafeDefinition(
|
||||
@@ -400,6 +403,9 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkRules(
|
||||
vars.Fatbinary = "$FATBIN";
|
||||
vars.RegisterFile = "$REGISTER";
|
||||
vars.LinkFlags = "$LINK_FLAGS";
|
||||
std::string linker =
|
||||
this->GetGeneratorTarget()->GetLinkerTool("CUDA", config);
|
||||
vars.Linker = linker.c_str();
|
||||
|
||||
std::string flags = this->GetFlags("CUDA", config);
|
||||
vars.Flags = flags.c_str();
|
||||
@@ -441,6 +447,8 @@ void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile,
|
||||
vars.CMTargetName = this->GetGeneratorTarget()->GetName().c_str();
|
||||
vars.CMTargetType = cmState::GetTargetTypeName(targetType).c_str();
|
||||
|
||||
std::string linker = this->GetGeneratorTarget()->GetLinkerTool(config);
|
||||
vars.Linker = linker.c_str();
|
||||
std::string lang = this->TargetLinkLanguage(config);
|
||||
vars.Language = lang.c_str();
|
||||
vars.AIXExports = "$AIX_EXPORTS";
|
||||
|
@@ -27,6 +27,19 @@ std::string cmRulePlaceholderExpander::ExpandVariable(
|
||||
return this->ReplaceValues->LinkFlags;
|
||||
}
|
||||
}
|
||||
if (this->ReplaceValues->Linker) {
|
||||
if (variable == "CMAKE_LINKER") {
|
||||
auto result = this->OutputConverter->ConvertToOutputForExisting(
|
||||
this->ReplaceValues->Linker);
|
||||
if (this->ReplaceValues->Launcher) {
|
||||
// Add launcher as part of expansion so that it always appears
|
||||
// immediately before the command itself, regardless of whether the
|
||||
// overall rule template contains other content at the front.
|
||||
result = cmStrCat(this->ReplaceValues->Launcher, " ", result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
if (this->ReplaceValues->Manifests) {
|
||||
if (variable == "MANIFESTS") {
|
||||
return this->ReplaceValues->Manifests;
|
||||
@@ -325,17 +338,7 @@ std::string cmRulePlaceholderExpander::ExpandVariable(
|
||||
auto mapIt = this->VariableMappings.find(variable);
|
||||
if (mapIt != this->VariableMappings.end()) {
|
||||
if (variable.find("_FLAG") == std::string::npos) {
|
||||
std::string ret =
|
||||
this->OutputConverter->ConvertToOutputForExisting(mapIt->second);
|
||||
|
||||
if (this->ReplaceValues->Launcher && variable == "CMAKE_LINKER") {
|
||||
// Add launcher as part of expansion so that it always appears
|
||||
// immediately before the command itself, regardless of whether the
|
||||
// overall rule template contains other content at the front.
|
||||
ret = cmStrCat(this->ReplaceValues->Launcher, " ", ret);
|
||||
}
|
||||
|
||||
return ret;
|
||||
return this->OutputConverter->ConvertToOutputForExisting(mapIt->second);
|
||||
}
|
||||
return mapIt->second;
|
||||
}
|
||||
|
@@ -53,6 +53,7 @@ public:
|
||||
const char* SONameFlag = nullptr;
|
||||
const char* TargetSOName = nullptr;
|
||||
const char* TargetInstallNameDir = nullptr;
|
||||
const char* Linker = nullptr;
|
||||
const char* LinkFlags = nullptr;
|
||||
const char* Manifests = nullptr;
|
||||
const char* LanguageCompileFlags = nullptr;
|
||||
|
@@ -456,6 +456,7 @@ TargetProperty const StaticTargetProperties[] = {
|
||||
{ "AUTORCC_EXECUTABLE"_s, IC::CanCompileSources },
|
||||
|
||||
// Linking properties
|
||||
{ "LINKER_TYPE"_s, IC::CanCompileSources },
|
||||
{ "ENABLE_EXPORTS"_s, IC::TargetWithSymbolExports },
|
||||
{ "LINK_LIBRARIES_ONLY_TARGETS"_s, IC::NormalNonImportedTarget },
|
||||
{ "LINK_SEARCH_START_STATIC"_s, IC::CanCompileSources },
|
||||
|
@@ -2987,6 +2987,16 @@ void cmVisualStudio10TargetGenerator::WritePathAndIncrementalLinkOptions(
|
||||
e1.WritePlatformConfigTag(
|
||||
"IntDir", cond, R"($(Platform)\$(Configuration)\$(ProjectName)\)");
|
||||
} else {
|
||||
if (ttype == cmStateEnums::SHARED_LIBRARY ||
|
||||
ttype == cmStateEnums::MODULE_LIBRARY ||
|
||||
ttype == cmStateEnums::EXECUTABLE) {
|
||||
auto linker = this->GeneratorTarget->GetLinkerTool(config);
|
||||
if (!linker.empty()) {
|
||||
ConvertToWindowsSlash(linker);
|
||||
e1.WritePlatformConfigTag("LinkToolExe", cond, linker);
|
||||
}
|
||||
}
|
||||
|
||||
std::string intermediateDir = cmStrCat(
|
||||
this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget), '/',
|
||||
config, '/');
|
||||
|
@@ -737,6 +737,14 @@ if((CMAKE_C_COMPILER_ID STREQUAL "AppleClang"
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (CMAKE_SYSTEM_NAME MATCHES "(Linux|Darwin|Windows)"
|
||||
AND CMAKE_C_COMPILER_ID MATCHES "^(AppleClang|Clang|GNU|MSVC|NVIDIA)$"
|
||||
AND NOT CMAKE_GENERATOR STREQUAL "Green Hills MULTI")
|
||||
add_RunCMake_test(LinkerSelection -DCMake_TEST_CUDA=${CMake_TEST_CUDA}
|
||||
-DCMAKE_C_COMPILER_ID=${CMAKE_C_COMPILER_ID}
|
||||
-DCMAKE_C_COMPILER_VERSION=${CMAKE_C_COMPILER_VERSION})
|
||||
endif()
|
||||
|
||||
add_RunCMake_test(File_Archive)
|
||||
add_RunCMake_test(File_Configure)
|
||||
add_RunCMake_test(File_Generate)
|
||||
|
7
Tests/RunCMake/LinkerSelection/AppleClassic.cmake
Normal file
7
Tests/RunCMake/LinkerSelection/AppleClassic.cmake
Normal file
@@ -0,0 +1,7 @@
|
||||
|
||||
enable_language(C)
|
||||
|
||||
set(CMAKE_LINKER_TYPE APPLE_CLASSIC)
|
||||
|
||||
add_executable(main main.c)
|
||||
target_link_libraries(main PRIVATE m m)
|
3
Tests/RunCMake/LinkerSelection/CMakeLists.txt
Normal file
3
Tests/RunCMake/LinkerSelection/CMakeLists.txt
Normal file
@@ -0,0 +1,3 @@
|
||||
cmake_minimum_required(VERSION 3.28)
|
||||
project(${RunCMake_TEST} NONE)
|
||||
include(${RunCMake_TEST}.cmake)
|
@@ -0,0 +1,2 @@
|
||||
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/LinkerType-validation.cmake")
|
36
Tests/RunCMake/LinkerSelection/CustomLinkerType.cmake
Normal file
36
Tests/RunCMake/LinkerSelection/CustomLinkerType.cmake
Normal file
@@ -0,0 +1,36 @@
|
||||
|
||||
enable_language(C)
|
||||
|
||||
set(CMAKE_C_USING_LINKER_FOO_C "${CMAKE_C_USING_LINKER_LLD}")
|
||||
|
||||
add_executable(main main.c)
|
||||
set_property(TARGET main PROPERTY LINKER_TYPE "$<$<LINK_LANGUAGE:C>:FOO_C>$<$<LINK_LANGUAGE:CUDA>:FOO_CUDA>")
|
||||
|
||||
if(CMake_TEST_CUDA)
|
||||
enable_language(CUDA)
|
||||
|
||||
set(CMAKE_CUDA_USING_LINKER_FOO_CUDA "${CMAKE_CUDA_USING_LINKER_LLD}")
|
||||
|
||||
add_executable(mainCU main.cu)
|
||||
set_property(TARGET mainCU PROPERTY LINKER_TYPE "$<$<LINK_LANGUAGE:C>:FOO_C>$<$<LINK_LANGUAGE:CUDA>:FOO_CUDA>")
|
||||
endif()
|
||||
|
||||
#
|
||||
# Generate file for validation
|
||||
#
|
||||
if (CMAKE_C_USING_LINKER_MODE STREQUAL "TOOL")
|
||||
cmake_path(GET CMAKE_C_USING_LINKER_FOO_C FILENAME LINKER_TYPE_OPTION)
|
||||
else()
|
||||
set(LINKER_TYPE_OPTION "${CMAKE_C_USING_LINKER_FOO_C}")
|
||||
endif()
|
||||
if(CMake_TEST_CUDA)
|
||||
if (CMAKE_CUDA_USING_LINKER_MODE STREQUAL "TOOL")
|
||||
cmake_path(GET CMAKE_CUDA_USING_LINKER_FOO_CUDA FILENAME CUDA_LINKER)
|
||||
else()
|
||||
set(CUDA_LINKER "${CMAKE_CUDA_USING_LINKER_FOO_CUDA}")
|
||||
endif()
|
||||
string(APPEND LINKER_TYPE_OPTION "|${CUDA_LINKER}")
|
||||
endif()
|
||||
|
||||
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/LINKER_TYPE_OPTION.cmake"
|
||||
"set(LINKER_TYPE_OPTION \"${LINKER_TYPE_OPTION}\")\n")
|
@@ -0,0 +1 @@
|
||||
1
|
@@ -0,0 +1,3 @@
|
||||
CMake Error in CMakeLists.txt:
|
||||
LINKER_TYPE 'FOO' is unknown. Did you forgot to define
|
||||
'CMAKE_C_USING_LINKER_FOO' variable\?
|
5
Tests/RunCMake/LinkerSelection/InvalidLinkerType.cmake
Normal file
5
Tests/RunCMake/LinkerSelection/InvalidLinkerType.cmake
Normal file
@@ -0,0 +1,5 @@
|
||||
|
||||
enable_language(C)
|
||||
|
||||
set(CMAKE_LINKER_TYPE FOO)
|
||||
add_executable(main main.c)
|
@@ -0,0 +1,9 @@
|
||||
|
||||
include ("${RunCMake_TEST_BINARY_DIR}/LINKER_TYPE_OPTION.cmake")
|
||||
|
||||
# In some environment, `=` character is escaped
|
||||
string(REPLACE "=" "\\\\?=" LINKER_TYPE_OPTION "${LINKER_TYPE_OPTION}")
|
||||
|
||||
if (NOT actual_stdout MATCHES "${LINKER_TYPE_OPTION}")
|
||||
set (RunCMake_TEST_FAILED "Not found expected '${LINKER_TYPE_OPTION}'.")
|
||||
endif()
|
44
Tests/RunCMake/LinkerSelection/RunCMakeTest.cmake
Normal file
44
Tests/RunCMake/LinkerSelection/RunCMakeTest.cmake
Normal file
@@ -0,0 +1,44 @@
|
||||
include(RunCMake)
|
||||
|
||||
if (RunCMake_GENERATOR MATCHES "Visual Studio 9 2008")
|
||||
run_cmake(UnsupportedLinkerType)
|
||||
return()
|
||||
endif()
|
||||
|
||||
run_cmake(InvalidLinkerType)
|
||||
|
||||
# look-up for LLVM linker
|
||||
if (WIN32)
|
||||
set (LINKER_NAMES lld-link)
|
||||
else()
|
||||
set(LINKER_NAMES ld.lld ld64.lld)
|
||||
endif()
|
||||
find_program(LLD_LINKER NAMES ${LINKER_NAMES})
|
||||
|
||||
macro(run_cmake_and_build test)
|
||||
run_cmake_with_options(${test} -DCMake_TEST_CUDA=${CMake_TEST_CUDA})
|
||||
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${test}-build)
|
||||
set(RunCMake_TEST_NO_CLEAN 1)
|
||||
if(CMake_TEST_CUDA)
|
||||
string(APPEND "|${CMAKE_CUDA_USING_LINKER_LLD}")
|
||||
endif()
|
||||
run_cmake_command(${test}-build ${CMAKE_COMMAND} --build . --config Release --verbose ${ARGN})
|
||||
|
||||
unset(RunCMake_TEST_BINARY_DIR)
|
||||
unset(RunCMake_TEST_NO_CLEAN)
|
||||
endmacro()
|
||||
|
||||
if(LLD_LINKER)
|
||||
block(SCOPE_FOR VARIABLES)
|
||||
set(CMAKE_VERBOSE_MAKEFILE TRUE)
|
||||
set(CMAKE_C_USE_RESPONSE_FILE_FOR_LIBRARIES FALSE)
|
||||
set(CMAKE_CUDA_USE_RESPONSE_FILE_FOR_LIBRARIES FALSE)
|
||||
|
||||
run_cmake_and_build(ValidLinkerType)
|
||||
run_cmake_and_build(CustomLinkerType)
|
||||
endblock()
|
||||
endif()
|
||||
|
||||
if(CMAKE_C_COMPILER_ID STREQUAL "AppleClang" AND CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL "15.0")
|
||||
run_cmake_and_build(AppleClassic)
|
||||
endif()
|
@@ -0,0 +1 @@
|
||||
1
|
@@ -0,0 +1,3 @@
|
||||
CMake Error at UnsupportedLinkerType.cmake:[0-9]+ \(add_executable\):
|
||||
'LINKER_TYPE' property, specified on target 'main', is not supported by
|
||||
this generator.
|
@@ -0,0 +1,5 @@
|
||||
|
||||
enable_language(C)
|
||||
|
||||
set(CMAKE_LINKER_TYPE LDD)
|
||||
add_executable(main main.c)
|
@@ -0,0 +1,2 @@
|
||||
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/LinkerType-validation.cmake")
|
32
Tests/RunCMake/LinkerSelection/ValidLinkerType.cmake
Normal file
32
Tests/RunCMake/LinkerSelection/ValidLinkerType.cmake
Normal file
@@ -0,0 +1,32 @@
|
||||
|
||||
enable_language(C)
|
||||
|
||||
set(CMAKE_LINKER_TYPE LLD)
|
||||
|
||||
add_executable(main main.c)
|
||||
|
||||
if(CMake_TEST_CUDA)
|
||||
enable_language(CUDA)
|
||||
|
||||
add_executable(mainCU main.cu)
|
||||
endif()
|
||||
|
||||
#
|
||||
# Generate file for validation
|
||||
#
|
||||
if (CMAKE_C_USING_LINKER_MODE STREQUAL "TOOL")
|
||||
cmake_path(GET CMAKE_C_USING_LINKER_LLD FILENAME LINKER_TYPE_OPTION)
|
||||
else()
|
||||
set(LINKER_TYPE_OPTION "${CMAKE_C_USING_LINKER_LLD}")
|
||||
endif()
|
||||
if(CMake_TEST_CUDA)
|
||||
if (CMAKE_CUDA_USING_LINKER_MODE STREQUAL "TOOL")
|
||||
cmake_path(GET CMAKE_CUDA_USING_LINKER_LLD FILENAME CUDA_LINKER)
|
||||
else()
|
||||
set(CUDA_LINKER "${CMAKE_CUDA_USING_LINKER_LLD}")
|
||||
endif()
|
||||
string(APPEND LINKER_TYPE_OPTION "|${CUDA_LINKER}")
|
||||
endif()
|
||||
|
||||
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/LINKER_TYPE_OPTION.cmake"
|
||||
"set(LINKER_TYPE_OPTION \"${LINKER_TYPE_OPTION}\")\n")
|
4
Tests/RunCMake/LinkerSelection/main.c
Normal file
4
Tests/RunCMake/LinkerSelection/main.c
Normal file
@@ -0,0 +1,4 @@
|
||||
int main(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
5
Tests/RunCMake/LinkerSelection/main.cu
Normal file
5
Tests/RunCMake/LinkerSelection/main.cu
Normal file
@@ -0,0 +1,5 @@
|
||||
|
||||
int main()
|
||||
{
|
||||
return 0;
|
||||
}
|
Reference in New Issue
Block a user