Linker: Generate per-language link directory flags on Windows

IntelLLVM links through the compiler driver, so its link directory
flag is wrapped in `/Qoption,link,`.  MSVC and CUDA run `link.exe`
directly.  When both are used in one build tree, the IntelLLVM value
of `CMAKE_LIBRARY_PATH_FLAG` leaked onto `link.exe` command lines.
Setting `CMAKE_<LANG>_LIBRARY_PATH_FLAG` per language, as was done
for `CMAKE_<LANG>_LINK_DEF_FILE_FLAG`, gives each link line the
spelling its own linker understands.  The variable is now documented.

Fixes: #28116
This commit is contained in:
Daksh Mamodiya committed 2026-10-01 15:37:42 +05:30
1 parent ebef261ea1
commit 89e5c19c55
11 files changed
+60 -1

No files matched your search

+1
View File
@@ -518,6 +518,7 @@ Variables that Control the Build
/variable/CMAKE_LANG_CPPLINT
/variable/CMAKE_LANG_ICSTAT
/variable/CMAKE_LANG_INCLUDE_WHAT_YOU_USE
/variable/CMAKE_LANG_LIBRARY_PATH_FLAG
/variable/CMAKE_LANG_LINK_DEF_FILE_FLAG
/variable/CMAKE_LANG_LINK_GROUP_USING_FEATURE
/variable/CMAKE_LANG_LINK_GROUP_USING_FEATURE_SUPPORTED
@@ -0,0 +1,15 @@
CMAKE_<LANG>_LIBRARY_PATH_FLAG
------------------------------
.. versionadded:: 3.16
The flag to be used to add a library search path to the linker
for the toolchain of language ``<LANG>``.
CMake sets this variable automatically for some toolchains during
toolchain inspection by calls to the :command:`project` or
:command:`enable_language` commands.
If the :variable:`!CMAKE_<LANG>_LIBRARY_PATH_FLAG` variable
is defined, it takes precedence over the language-agnostic
:variable:`CMAKE_LIBRARY_PATH_FLAG` variable.
@@ -5,3 +5,6 @@ The flag to be used to add a library search path to a compiler.
The flag will be used to specify a library directory to the compiler.
On most compilers this is ``-L``.
If the per-language :variable:`CMAKE_<LANG>_LIBRARY_PATH_FLAG` variable
is defined, it takes precedence over :variable:`!CMAKE_LIBRARY_PATH_FLAG`.
+2 -1
View File
@@ -37,7 +37,8 @@ macro(__windows_compiler_intel lang)
set(CMAKE_${lang}_CREATE_CONSOLE_EXE "${CMAKE_${lang}_LINKER_WRAPPER_FLAG}/subsystem:console")
set(CMAKE_${lang}_LINK_DEF_FILE_FLAG "${CMAKE_${lang}_LINKER_WRAPPER_FLAG}/DEF:")
set(CMAKE_LINK_DEF_FILE_FLAG "${CMAKE_${lang}_LINK_DEF_FILE_FLAG}")
set(CMAKE_LIBRARY_PATH_FLAG "${CMAKE_${lang}_LINKER_WRAPPER_FLAG}/LIBPATH:")
set(CMAKE_${lang}_LIBRARY_PATH_FLAG "${CMAKE_${lang}_LINKER_WRAPPER_FLAG}/LIBPATH:")
set(CMAKE_LIBRARY_PATH_FLAG "${CMAKE_${lang}_LIBRARY_PATH_FLAG}")
set(CMAKE_${lang}_LINK_EXECUTABLE
"${_CMAKE_VS_LINK_EXE}<CMAKE_${lang}_COMPILER> ${CMAKE_CL_NOLOGO} <OBJECTS> ${CMAKE_START_TEMP_FILE} <LINK_FLAGS> <LINK_LIBRARIES> /link /out:<TARGET> /implib:<TARGET_IMPLIB> /pdb:<TARGET_PDB> /version:<TARGET_VERSION_MAJOR>.<TARGET_VERSION_MINOR>${_PLATFORM_LINK_FLAGS} ${CMAKE_END_TEMP_FILE}")
+1
View File
@@ -430,6 +430,7 @@ macro(__windows_compiler_msvc lang)
"<CMAKE_${lang}_COMPILER> ${CMAKE_START_TEMP_FILE} ${CMAKE_CL_NOLOGO}${_COMPILE_${lang}} <DEFINES> <INCLUDES> <FLAGS> /FoNUL /FAs /Fa<ASSEMBLY_SOURCE> /c <SOURCE>${CMAKE_END_TEMP_FILE}")
set(CMAKE_${lang}_LINK_DEF_FILE_FLAG "/DEF:")
set(CMAKE_${lang}_LIBRARY_PATH_FLAG "-LIBPATH:")
set(CMAKE_${lang}_USE_RESPONSE_FILE_FOR_OBJECTS 1)
set(CMAKE_${lang}_LINK_EXECUTABLE
"${_CMAKE_VS_LINK_EXE}<CMAKE_LINKER> ${CMAKE_CL_NOLOGO} <OBJECTS> ${CMAKE_START_TEMP_FILE} /out:<TARGET> /implib:<TARGET_IMPLIB> /pdb:<TARGET_PDB> /version:<TARGET_VERSION_MAJOR>.<TARGET_VERSION_MINOR>${_PLATFORM_LINK_FLAGS} <LINK_FLAGS> <LINK_LIBRARIES>${_CMAKE_FASTBUILD_MANIFESTS} ${CMAKE_END_TEMP_FILE}")
@@ -26,6 +26,7 @@ set(CMAKE_CUDA_SHARED_LIBRARY_COMPILE_DEFINITIONS "_WINDLL")
set(CMAKE_CUDA_CREATE_SHARED_MODULE ${CMAKE_CUDA_CREATE_SHARED_LIBRARY})
set(CMAKE_CUDA_CREATE_STATIC_LIBRARY "<CMAKE_AR> ${CMAKE_CL_NOLOGO}${_PLATFORM_ARCHIVE_FLAGS} <LINK_FLAGS> /out:<TARGET> <OBJECTS> ")
set(CMAKE_CUDA_LINKER_SUPPORTS_PDB ON)
set(CMAKE_CUDA_LIBRARY_PATH_FLAG "-LIBPATH:")
set(CMAKE_CUDA_LINK_EXECUTABLE
"${_CMAKE_VS_LINK_EXE}<CMAKE_LINKER> ${CMAKE_CL_NOLOGO} <OBJECTS> ${CMAKE_START_TEMP_FILE} /out:<TARGET> /implib:<TARGET_IMPLIB> /pdb:<TARGET_PDB> /version:<TARGET_VERSION_MAJOR>.<TARGET_VERSION_MINOR>${_PLATFORM_LINK_FLAGS} <LINK_FLAGS> <LINK_LIBRARIES>${__IMPLICIT_LINKS} ${CMAKE_END_TEMP_FILE}")
unset(_CMAKE_VS_LINK_DLL)
+1
View File
@@ -11,6 +11,7 @@ set(CudaOnly.CompileFlags_BUILD_OPTIONS -DCMake_TEST_CUDA_ARCH=${CMake_TEST_CUDA
add_cuda_test_macro(CudaOnly.CompileFlags CudaOnlyCompileFlags)
add_cuda_test_macro(CudaOnly.EnableStandard CudaOnlyEnableStandard)
add_cuda_test_macro(CudaOnly.ExportPTX CudaOnlyExportPTX)
add_cuda_test_macro(CudaOnly.LinkDirectory CudaOnlyLinkDirectory)
add_cuda_test_macro(CudaOnly.SharedRuntimePlusToolkit CudaOnlySharedRuntimePlusToolkit)
add_cuda_test_macro(CudaOnly.StaticRuntimePlusToolkit CudaOnlyStaticRuntimePlusToolkit)
if(NOT WIN32 AND CMake_TEST_CUDA STREQUAL "NVIDIA")
@@ -0,0 +1,20 @@
cmake_minimum_required(VERSION 3.18)
project(LinkDirectory CUDA)
if(MSVC)
# Simulate another language overriding the link directory flag.
# The generators prefer CMAKE_<LANG>_LIBRARY_PATH_FLAG.
set(CMAKE_LIBRARY_PATH_FLAG "bad-libpath-flag:")
endif()
add_library(CudaOnlyLinkDirectoryLib STATIC lib.cu)
set_target_properties(CudaOnlyLinkDirectoryLib PROPERTIES
OUTPUT_NAME LinkDirectoryLib
ARCHIVE_OUTPUT_DIRECTORY "$<1:${CMAKE_CURRENT_BINARY_DIR}/lib>"
)
# Link by name so the linker has to search the link directory.
add_executable(CudaOnlyLinkDirectory main.cu)
target_link_directories(CudaOnlyLinkDirectory PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/lib")
target_link_libraries(CudaOnlyLinkDirectory PRIVATE LinkDirectoryLib)
add_dependencies(CudaOnlyLinkDirectory CudaOnlyLinkDirectoryLib)
+4
View File
@@ -0,0 +1,4 @@
int linkdir_answer()
{
return 42;
}
+6
View File
@@ -0,0 +1,6 @@
int linkdir_answer();
int main()
{
return linkdir_answer() == 42 ? 0 : 1;
}
+6
View File
@@ -1,6 +1,12 @@
cmake_minimum_required(VERSION 3.10)
project(LinkDirectoryExternal C)
if(MSVC)
# Simulate another language overriding the link directory flag.
# The generators prefer CMAKE_<LANG>_LIBRARY_PATH_FLAG.
set(CMAKE_LIBRARY_PATH_FLAG "bad-libpath-flag:")
endif()
set(cfg_dir)
get_property(_isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)