1
0
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:
Marc Chevrier
2023-09-27 15:22:55 +02:00
parent ee5f31ba72
commit 96a953b1ed
59 changed files with 623 additions and 16 deletions

View File

@@ -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

View File

@@ -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

View 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

View 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.

View 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.

View 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)

View 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

View 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.

View File

@@ -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)

View File

@@ -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@)

View File

@@ -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@")

View File

@@ -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@)

View File

@@ -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")

View File

@@ -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@")

View File

@@ -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@)

View File

@@ -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@)

View File

@@ -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")

View File

@@ -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)

View File

@@ -0,0 +1,2 @@
include(Platform/Linux-GNU)
__linux_compiler_gnu(CUDA)

View File

@@ -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()

View 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")

View File

@@ -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")

View File

@@ -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 "")

View File

@@ -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)

View File

@@ -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)

View File

@@ -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

View File

@@ -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

View File

@@ -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
{

View File

@@ -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;

View File

@@ -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(), '/',

View File

@@ -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,

View File

@@ -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,

View File

@@ -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);

View File

@@ -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

View File

@@ -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();

View File

@@ -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();

View File

@@ -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(

View File

@@ -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";

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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 },

View File

@@ -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, '/');

View File

@@ -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)

View 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)

View File

@@ -0,0 +1,3 @@
cmake_minimum_required(VERSION 3.28)
project(${RunCMake_TEST} NONE)
include(${RunCMake_TEST}.cmake)

View File

@@ -0,0 +1,2 @@
include("${CMAKE_CURRENT_LIST_DIR}/LinkerType-validation.cmake")

View 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")

View File

@@ -0,0 +1 @@
1

View File

@@ -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\?

View File

@@ -0,0 +1,5 @@
enable_language(C)
set(CMAKE_LINKER_TYPE FOO)
add_executable(main main.c)

View File

@@ -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()

View 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()

View File

@@ -0,0 +1 @@
1

View File

@@ -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.

View File

@@ -0,0 +1,5 @@
enable_language(C)
set(CMAKE_LINKER_TYPE LDD)
add_executable(main main.c)

View File

@@ -0,0 +1,2 @@
include("${CMAKE_CURRENT_LIST_DIR}/LinkerType-validation.cmake")

View 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")

View File

@@ -0,0 +1,4 @@
int main(void)
{
return 0;
}

View File

@@ -0,0 +1,5 @@
int main()
{
return 0;
}