summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Help/manual/cmake-properties.7.rst1
-rw-r--r--Help/manual/cmake-variables.7.rst3
-rw-r--r--Help/prop_tgt/LINKER_TYPE.rst26
-rw-r--r--Help/release/dev/Linker-user-selection.rst6
-rw-r--r--Help/variable/CMAKE_LANG_USING_LINKER_MODE.rst15
-rw-r--r--Help/variable/CMAKE_LANG_USING_LINKER_TYPE.rst30
-rw-r--r--Help/variable/CMAKE_LINKER_TYPE.rst18
-rw-r--r--Help/variable/LINKER_PREDEFINED_TYPES.txt57
-rw-r--r--Modules/CMakeASMCompiler.cmake.in2
-rw-r--r--Modules/CMakeCCompiler.cmake.in2
-rw-r--r--Modules/CMakeCUDACompiler.cmake.in2
-rw-r--r--Modules/CMakeCXXCompiler.cmake.in2
-rw-r--r--Modules/CMakeFindBinUtils.cmake11
-rw-r--r--Modules/CMakeHIPCompiler.cmake.in2
-rw-r--r--Modules/CMakeOBJCCompiler.cmake.in2
-rw-r--r--Modules/CMakeOBJCXXCompiler.cmake.in2
-rw-r--r--Modules/Platform/Apple-Clang.cmake7
-rw-r--r--Modules/Platform/Apple-GNU.cmake3
-rw-r--r--Modules/Platform/Linux-Clang-CUDA.cmake2
-rw-r--r--Modules/Platform/Linux-GNU.cmake7
-rw-r--r--Modules/Platform/Linux-NVIDIA-CUDA.cmake7
-rw-r--r--Modules/Platform/Windows-Clang.cmake10
-rw-r--r--Modules/Platform/Windows-GNU.cmake5
-rw-r--r--Modules/Platform/Windows-MSVC.cmake6
-rw-r--r--Modules/Platform/Windows-NVIDIA-CUDA.cmake6
-rw-r--r--Source/cmCoreTryCompile.cxx16
-rw-r--r--Source/cmGeneratorExpressionDAGChecker.cxx5
-rw-r--r--Source/cmGeneratorTarget.cxx69
-rw-r--r--Source/cmGeneratorTarget.h7
-rw-r--r--Source/cmGhsMultiTargetGenerator.cxx13
-rw-r--r--Source/cmGlobalXCodeGenerator.cxx3
-rw-r--r--Source/cmLocalGenerator.cxx45
-rw-r--r--Source/cmLocalGenerator.h3
-rw-r--r--Source/cmLocalVisualStudio7Generator.cxx21
-rw-r--r--Source/cmMakefileExecutableTargetGenerator.cxx3
-rw-r--r--Source/cmMakefileLibraryTargetGenerator.cxx3
-rw-r--r--Source/cmMakefileTargetGenerator.cxx2
-rw-r--r--Source/cmNinjaNormalTargetGenerator.cxx8
-rw-r--r--Source/cmRulePlaceholderExpander.cxx25
-rw-r--r--Source/cmRulePlaceholderExpander.h1
-rw-r--r--Source/cmTarget.cxx1
-rw-r--r--Source/cmVisualStudio10TargetGenerator.cxx10
-rw-r--r--Tests/RunCMake/CMakeLists.txt8
-rw-r--r--Tests/RunCMake/LinkerSelection/AppleClassic.cmake7
-rw-r--r--Tests/RunCMake/LinkerSelection/CMakeLists.txt3
-rw-r--r--Tests/RunCMake/LinkerSelection/CustomLinkerType-build-check.cmake2
-rw-r--r--Tests/RunCMake/LinkerSelection/CustomLinkerType.cmake36
-rw-r--r--Tests/RunCMake/LinkerSelection/InvalidLinkerType-result.txt1
-rw-r--r--Tests/RunCMake/LinkerSelection/InvalidLinkerType-stderr.txt3
-rw-r--r--Tests/RunCMake/LinkerSelection/InvalidLinkerType.cmake5
-rw-r--r--Tests/RunCMake/LinkerSelection/LinkerType-validation.cmake9
-rw-r--r--Tests/RunCMake/LinkerSelection/RunCMakeTest.cmake44
-rw-r--r--Tests/RunCMake/LinkerSelection/UnsupportedLinkerType-result.txt1
-rw-r--r--Tests/RunCMake/LinkerSelection/UnsupportedLinkerType-stderr.txt3
-rw-r--r--Tests/RunCMake/LinkerSelection/UnsupportedLinkerType.cmake5
-rw-r--r--Tests/RunCMake/LinkerSelection/ValidLinkerType-build-check.cmake2
-rw-r--r--Tests/RunCMake/LinkerSelection/ValidLinkerType.cmake32
-rw-r--r--Tests/RunCMake/LinkerSelection/main.c4
-rw-r--r--Tests/RunCMake/LinkerSelection/main.cu5
59 files changed, 623 insertions, 16 deletions
diff --git a/Help/manual/cmake-properties.7.rst b/Help/manual/cmake-properties.7.rst
index fa1d297..55054f5 100644
--- a/Help/manual/cmake-properties.7.rst
+++ b/Help/manual/cmake-properties.7.rst
@@ -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
diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst
index d9df773..9320ffa 100644
--- a/Help/manual/cmake-variables.7.rst
+++ b/Help/manual/cmake-variables.7.rst
@@ -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
diff --git a/Help/prop_tgt/LINKER_TYPE.rst b/Help/prop_tgt/LINKER_TYPE.rst
new file mode 100644
index 0000000..90a663d
--- /dev/null
+++ b/Help/prop_tgt/LINKER_TYPE.rst
@@ -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
diff --git a/Help/release/dev/Linker-user-selection.rst b/Help/release/dev/Linker-user-selection.rst
new file mode 100644
index 0000000..ed78099
--- /dev/null
+++ b/Help/release/dev/Linker-user-selection.rst
@@ -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.
diff --git a/Help/variable/CMAKE_LANG_USING_LINKER_MODE.rst b/Help/variable/CMAKE_LANG_USING_LINKER_MODE.rst
new file mode 100644
index 0000000..c9b6779
--- /dev/null
+++ b/Help/variable/CMAKE_LANG_USING_LINKER_MODE.rst
@@ -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.
diff --git a/Help/variable/CMAKE_LANG_USING_LINKER_TYPE.rst b/Help/variable/CMAKE_LANG_USING_LINKER_TYPE.rst
new file mode 100644
index 0000000..e4d9fa6
--- /dev/null
+++ b/Help/variable/CMAKE_LANG_USING_LINKER_TYPE.rst
@@ -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)
diff --git a/Help/variable/CMAKE_LINKER_TYPE.rst b/Help/variable/CMAKE_LINKER_TYPE.rst
new file mode 100644
index 0000000..17ea947
--- /dev/null
+++ b/Help/variable/CMAKE_LINKER_TYPE.rst
@@ -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
diff --git a/Help/variable/LINKER_PREDEFINED_TYPES.txt b/Help/variable/LINKER_PREDEFINED_TYPES.txt
new file mode 100644
index 0000000..50dc3df
--- /dev/null
+++ b/Help/variable/LINKER_PREDEFINED_TYPES.txt
@@ -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.
diff --git a/Modules/CMakeASMCompiler.cmake.in b/Modules/CMakeASMCompiler.cmake.in
index 1efd9f5..fab366a 100644
--- a/Modules/CMakeASMCompiler.cmake.in
+++ b/Modules/CMakeASMCompiler.cmake.in
@@ -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)
diff --git a/Modules/CMakeCCompiler.cmake.in b/Modules/CMakeCCompiler.cmake.in
index 2f0b774..01185a3 100644
--- a/Modules/CMakeCCompiler.cmake.in
+++ b/Modules/CMakeCCompiler.cmake.in
@@ -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@)
diff --git a/Modules/CMakeCUDACompiler.cmake.in b/Modules/CMakeCUDACompiler.cmake.in
index 3c28c28..3bc21fb 100644
--- a/Modules/CMakeCUDACompiler.cmake.in
+++ b/Modules/CMakeCUDACompiler.cmake.in
@@ -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@")
diff --git a/Modules/CMakeCXXCompiler.cmake.in b/Modules/CMakeCXXCompiler.cmake.in
index 8b6f82b..fbc1540 100644
--- a/Modules/CMakeCXXCompiler.cmake.in
+++ b/Modules/CMakeCXXCompiler.cmake.in
@@ -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@)
diff --git a/Modules/CMakeFindBinUtils.cmake b/Modules/CMakeFindBinUtils.cmake
index e12b175..cf270c0 100644
--- a/Modules/CMakeFindBinUtils.cmake
+++ b/Modules/CMakeFindBinUtils.cmake
@@ -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")
diff --git a/Modules/CMakeHIPCompiler.cmake.in b/Modules/CMakeHIPCompiler.cmake.in
index 6d5e62a..0c06c3b 100644
--- a/Modules/CMakeHIPCompiler.cmake.in
+++ b/Modules/CMakeHIPCompiler.cmake.in
@@ -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@")
diff --git a/Modules/CMakeOBJCCompiler.cmake.in b/Modules/CMakeOBJCCompiler.cmake.in
index de73645..95e52bf 100644
--- a/Modules/CMakeOBJCCompiler.cmake.in
+++ b/Modules/CMakeOBJCCompiler.cmake.in
@@ -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@)
diff --git a/Modules/CMakeOBJCXXCompiler.cmake.in b/Modules/CMakeOBJCXXCompiler.cmake.in
index 94d24ff..87aca96 100644
--- a/Modules/CMakeOBJCXXCompiler.cmake.in
+++ b/Modules/CMakeOBJCXXCompiler.cmake.in
@@ -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@)
diff --git a/Modules/Platform/Apple-Clang.cmake b/Modules/Platform/Apple-Clang.cmake
index 57b3910..5fe4300 100644
--- a/Modules/Platform/Apple-Clang.cmake
+++ b/Modules/Platform/Apple-Clang.cmake
@@ -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")
diff --git a/Modules/Platform/Apple-GNU.cmake b/Modules/Platform/Apple-GNU.cmake
index 823c790..15f6a71 100644
--- a/Modules/Platform/Apple-GNU.cmake
+++ b/Modules/Platform/Apple-GNU.cmake
@@ -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)
diff --git a/Modules/Platform/Linux-Clang-CUDA.cmake b/Modules/Platform/Linux-Clang-CUDA.cmake
new file mode 100644
index 0000000..4a9337e
--- /dev/null
+++ b/Modules/Platform/Linux-Clang-CUDA.cmake
@@ -0,0 +1,2 @@
+include(Platform/Linux-GNU)
+__linux_compiler_gnu(CUDA)
diff --git a/Modules/Platform/Linux-GNU.cmake b/Modules/Platform/Linux-GNU.cmake
index 6878254..b8ce521 100644
--- a/Modules/Platform/Linux-GNU.cmake
+++ b/Modules/Platform/Linux-GNU.cmake
@@ -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()
diff --git a/Modules/Platform/Linux-NVIDIA-CUDA.cmake b/Modules/Platform/Linux-NVIDIA-CUDA.cmake
new file mode 100644
index 0000000..4b416de
--- /dev/null
+++ b/Modules/Platform/Linux-NVIDIA-CUDA.cmake
@@ -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")
diff --git a/Modules/Platform/Windows-Clang.cmake b/Modules/Platform/Windows-Clang.cmake
index 33d271d..a03fc9e 100644
--- a/Modules/Platform/Windows-Clang.cmake
+++ b/Modules/Platform/Windows-Clang.cmake
@@ -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")
diff --git a/Modules/Platform/Windows-GNU.cmake b/Modules/Platform/Windows-GNU.cmake
index 412af6b..ac990d5 100644
--- a/Modules/Platform/Windows-GNU.cmake
+++ b/Modules/Platform/Windows-GNU.cmake
@@ -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 "")
diff --git a/Modules/Platform/Windows-MSVC.cmake b/Modules/Platform/Windows-MSVC.cmake
index 829ab9b..1fbf0cc 100644
--- a/Modules/Platform/Windows-MSVC.cmake
+++ b/Modules/Platform/Windows-MSVC.cmake
@@ -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)
diff --git a/Modules/Platform/Windows-NVIDIA-CUDA.cmake b/Modules/Platform/Windows-NVIDIA-CUDA.cmake
index 326e715..6489841 100644
--- a/Modules/Platform/Windows-NVIDIA-CUDA.cmake
+++ b/Modules/Platform/Windows-NVIDIA-CUDA.cmake
@@ -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)
diff --git a/Source/cmCoreTryCompile.cxx b/Source/cmCoreTryCompile.cxx
index 7e19812..69d5ffc 100644
--- a/Source/cmCoreTryCompile.cxx
+++ b/Source/cmCoreTryCompile.cxx
@@ -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
diff --git a/Source/cmGeneratorExpressionDAGChecker.cxx b/Source/cmGeneratorExpressionDAGChecker.cxx
index d51dbd0..4e46df7 100644
--- a/Source/cmGeneratorExpressionDAGChecker.cxx
+++ b/Source/cmGeneratorExpressionDAGChecker.cxx
@@ -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
diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx
index 2ea18bd..f7a6a4e 100644
--- a/Source/cmGeneratorTarget.cxx
+++ b/Source/cmGeneratorTarget.cxx
@@ -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
{
diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h
index bf49914..a32c5d8 100644
--- a/Source/cmGeneratorTarget.h
+++ b/Source/cmGeneratorTarget.h
@@ -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;
diff --git a/Source/cmGhsMultiTargetGenerator.cxx b/Source/cmGhsMultiTargetGenerator.cxx
index 95e2187..940f49d 100644
--- a/Source/cmGhsMultiTargetGenerator.cxx
+++ b/Source/cmGhsMultiTargetGenerator.cxx
@@ -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(), '/',
diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx
index 5076e6c..9f6786e 100644
--- a/Source/cmGlobalXCodeGenerator.cxx
+++ b/Source/cmGlobalXCodeGenerator.cxx
@@ -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,
diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index fe8d502..76e36ab 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -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,
diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h
index a920cfe..a61def9 100644
--- a/Source/cmLocalGenerator.h
+++ b/Source/cmLocalGenerator.h
@@ -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);
diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx
index 7b02c56..3f3779a 100644
--- a/Source/cmLocalVisualStudio7Generator.cxx
+++ b/Source/cmLocalVisualStudio7Generator.cxx
@@ -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
diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx
index 4a2b9e8..96a0d5c 100644
--- a/Source/cmMakefileExecutableTargetGenerator.cxx
+++ b/Source/cmMakefileExecutableTargetGenerator.cxx
@@ -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();
diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx
index fc3caa1..0429155 100644
--- a/Source/cmMakefileLibraryTargetGenerator.cxx
+++ b/Source/cmMakefileLibraryTargetGenerator.cxx
@@ -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();
diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx
index 0c2a719..343f6b8 100644
--- a/Source/cmMakefileTargetGenerator.cxx
+++ b/Source/cmMakefileTargetGenerator.cxx
@@ -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(
diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx
index 48c30b6..5e7bb6e 100644
--- a/Source/cmNinjaNormalTargetGenerator.cxx
+++ b/Source/cmNinjaNormalTargetGenerator.cxx
@@ -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";
diff --git a/Source/cmRulePlaceholderExpander.cxx b/Source/cmRulePlaceholderExpander.cxx
index 638bb42..a8c81d0 100644
--- a/Source/cmRulePlaceholderExpander.cxx
+++ b/Source/cmRulePlaceholderExpander.cxx
@@ -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;
}
diff --git a/Source/cmRulePlaceholderExpander.h b/Source/cmRulePlaceholderExpander.h
index 5d1f199..225abd4 100644
--- a/Source/cmRulePlaceholderExpander.h
+++ b/Source/cmRulePlaceholderExpander.h
@@ -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;
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index abbf29e..d93f658 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -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 },
diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx
index ce94fe1..84f808d 100644
--- a/Source/cmVisualStudio10TargetGenerator.cxx
+++ b/Source/cmVisualStudio10TargetGenerator.cxx
@@ -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, '/');
diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt
index 4387c5b..4f80015 100644
--- a/Tests/RunCMake/CMakeLists.txt
+++ b/Tests/RunCMake/CMakeLists.txt
@@ -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)
diff --git a/Tests/RunCMake/LinkerSelection/AppleClassic.cmake b/Tests/RunCMake/LinkerSelection/AppleClassic.cmake
new file mode 100644
index 0000000..62a12ad
--- /dev/null
+++ b/Tests/RunCMake/LinkerSelection/AppleClassic.cmake
@@ -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)
diff --git a/Tests/RunCMake/LinkerSelection/CMakeLists.txt b/Tests/RunCMake/LinkerSelection/CMakeLists.txt
new file mode 100644
index 0000000..6a9ce76
--- /dev/null
+++ b/Tests/RunCMake/LinkerSelection/CMakeLists.txt
@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 3.28)
+project(${RunCMake_TEST} NONE)
+include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/LinkerSelection/CustomLinkerType-build-check.cmake b/Tests/RunCMake/LinkerSelection/CustomLinkerType-build-check.cmake
new file mode 100644
index 0000000..235c38e
--- /dev/null
+++ b/Tests/RunCMake/LinkerSelection/CustomLinkerType-build-check.cmake
@@ -0,0 +1,2 @@
+
+include("${CMAKE_CURRENT_LIST_DIR}/LinkerType-validation.cmake")
diff --git a/Tests/RunCMake/LinkerSelection/CustomLinkerType.cmake b/Tests/RunCMake/LinkerSelection/CustomLinkerType.cmake
new file mode 100644
index 0000000..4bf98b0
--- /dev/null
+++ b/Tests/RunCMake/LinkerSelection/CustomLinkerType.cmake
@@ -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")
diff --git a/Tests/RunCMake/LinkerSelection/InvalidLinkerType-result.txt b/Tests/RunCMake/LinkerSelection/InvalidLinkerType-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/LinkerSelection/InvalidLinkerType-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/LinkerSelection/InvalidLinkerType-stderr.txt b/Tests/RunCMake/LinkerSelection/InvalidLinkerType-stderr.txt
new file mode 100644
index 0000000..11aea7a
--- /dev/null
+++ b/Tests/RunCMake/LinkerSelection/InvalidLinkerType-stderr.txt
@@ -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\?
diff --git a/Tests/RunCMake/LinkerSelection/InvalidLinkerType.cmake b/Tests/RunCMake/LinkerSelection/InvalidLinkerType.cmake
new file mode 100644
index 0000000..bbe398c
--- /dev/null
+++ b/Tests/RunCMake/LinkerSelection/InvalidLinkerType.cmake
@@ -0,0 +1,5 @@
+
+enable_language(C)
+
+set(CMAKE_LINKER_TYPE FOO)
+add_executable(main main.c)
diff --git a/Tests/RunCMake/LinkerSelection/LinkerType-validation.cmake b/Tests/RunCMake/LinkerSelection/LinkerType-validation.cmake
new file mode 100644
index 0000000..3f82479
--- /dev/null
+++ b/Tests/RunCMake/LinkerSelection/LinkerType-validation.cmake
@@ -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()
diff --git a/Tests/RunCMake/LinkerSelection/RunCMakeTest.cmake b/Tests/RunCMake/LinkerSelection/RunCMakeTest.cmake
new file mode 100644
index 0000000..cae4ca4
--- /dev/null
+++ b/Tests/RunCMake/LinkerSelection/RunCMakeTest.cmake
@@ -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()
diff --git a/Tests/RunCMake/LinkerSelection/UnsupportedLinkerType-result.txt b/Tests/RunCMake/LinkerSelection/UnsupportedLinkerType-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/LinkerSelection/UnsupportedLinkerType-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/LinkerSelection/UnsupportedLinkerType-stderr.txt b/Tests/RunCMake/LinkerSelection/UnsupportedLinkerType-stderr.txt
new file mode 100644
index 0000000..6473451
--- /dev/null
+++ b/Tests/RunCMake/LinkerSelection/UnsupportedLinkerType-stderr.txt
@@ -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.
diff --git a/Tests/RunCMake/LinkerSelection/UnsupportedLinkerType.cmake b/Tests/RunCMake/LinkerSelection/UnsupportedLinkerType.cmake
new file mode 100644
index 0000000..1b0703c
--- /dev/null
+++ b/Tests/RunCMake/LinkerSelection/UnsupportedLinkerType.cmake
@@ -0,0 +1,5 @@
+
+enable_language(C)
+
+set(CMAKE_LINKER_TYPE LDD)
+add_executable(main main.c)
diff --git a/Tests/RunCMake/LinkerSelection/ValidLinkerType-build-check.cmake b/Tests/RunCMake/LinkerSelection/ValidLinkerType-build-check.cmake
new file mode 100644
index 0000000..235c38e
--- /dev/null
+++ b/Tests/RunCMake/LinkerSelection/ValidLinkerType-build-check.cmake
@@ -0,0 +1,2 @@
+
+include("${CMAKE_CURRENT_LIST_DIR}/LinkerType-validation.cmake")
diff --git a/Tests/RunCMake/LinkerSelection/ValidLinkerType.cmake b/Tests/RunCMake/LinkerSelection/ValidLinkerType.cmake
new file mode 100644
index 0000000..a685ac1
--- /dev/null
+++ b/Tests/RunCMake/LinkerSelection/ValidLinkerType.cmake
@@ -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")
diff --git a/Tests/RunCMake/LinkerSelection/main.c b/Tests/RunCMake/LinkerSelection/main.c
new file mode 100644
index 0000000..8488f4e
--- /dev/null
+++ b/Tests/RunCMake/LinkerSelection/main.c
@@ -0,0 +1,4 @@
+int main(void)
+{
+ return 0;
+}
diff --git a/Tests/RunCMake/LinkerSelection/main.cu b/Tests/RunCMake/LinkerSelection/main.cu
new file mode 100644
index 0000000..766b775
--- /dev/null
+++ b/Tests/RunCMake/LinkerSelection/main.cu
@@ -0,0 +1,5 @@
+
+int main()
+{
+ return 0;
+}