mirror of
https://github.com/Kitware/CMake.git
synced 2026-01-11 16:32:14 -06:00
MSVC: Move link -machine flag out of CMAKE_*_LINKER_FLAGS
The `CMAKE_{EXE,SHARED,MODULE,STATIC}_LINKER_FLAGS` variables are
not language-specific, so multiple languages' toolchains may disagree
about if/how to pass the flag through a compiler driver to the linker.
Furthermore, carrying the flag in public-facing variables allows projects
or users to change it even though it is required. Add policy CMP0197
to remove the flag from the public-facing variables and generate it
automatically instead:
* For command-line generators, add the `-machine:` flag to the
linker and archiver rule variables.
* For Visual Studio generators, we do not need to explicitly add the
link `-machine:` flag. MSBuild automatically adds it, and the new
behavior actually removes a duplicate we generated previously.
Issue: #21934
This commit is contained in:
@@ -98,6 +98,7 @@ Policies Introduced by CMake 4.1
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
CMP0197: MSVC link -machine: flag is not in CMAKE_*_LINKER_FLAGS. </policy/CMP0197>
|
||||
CMP0196: The CMakeDetermineVSServicePack module is removed. </policy/CMP0196>
|
||||
CMP0195: Swift modules in build trees use the Swift module directory structure. </policy/CMP0195>
|
||||
CMP0194: MSVC is not an assembler for language ASM. </policy/CMP0194>
|
||||
|
||||
45
Help/policy/CMP0197.rst
Normal file
45
Help/policy/CMP0197.rst
Normal file
@@ -0,0 +1,45 @@
|
||||
CMP0197
|
||||
-------
|
||||
|
||||
.. versionadded:: 4.1
|
||||
|
||||
MSVC link ``-machine:`` flag is not in ``CMAKE_*_LINKER_FLAGS``.
|
||||
|
||||
When using MSVC-like compilers in CMake 4.0 and below, the linker's
|
||||
``-machine:`` flag is added via language-agnostic linker flag variables:
|
||||
|
||||
* :variable:`CMAKE_EXE_LINKER_FLAGS`
|
||||
* :variable:`CMAKE_SHARED_LINKER_FLAGS`
|
||||
* :variable:`CMAKE_MODULE_LINKER_FLAGS`
|
||||
* :variable:`CMAKE_STATIC_LINKER_FLAGS`
|
||||
|
||||
This is problematic when multiple languages' toolchains disagree about
|
||||
if/how to pass the flag through a compiler driver to the linker.
|
||||
Furthermore, carrying the flag in public-facing variables allows projects
|
||||
or users to change it even though it is required.
|
||||
|
||||
CMake 4.1 and above prefer to leave the ``-machine:`` flag out of
|
||||
``CMAKE_*_LINKER_FLAGS`` variables, and instead generate the link
|
||||
flag automatically where needed.
|
||||
|
||||
This policy provides compatibility with projects that have not been updated
|
||||
to expect the lack of the ``-machine:`` flags. The policy setting takes
|
||||
effect as of the first :command:`project` or :command:`enable_language`
|
||||
command that initializes the above-listed ``CMAKE_*_LINKER_FLAGS`` variables.
|
||||
|
||||
.. note::
|
||||
|
||||
Once the policy has taken effect at the top of a project for a given
|
||||
language, that choice must be used throughout the tree for that language.
|
||||
In projects that have nested projects in subdirectories, be sure to
|
||||
convert everything together.
|
||||
|
||||
The ``OLD`` behavior for this policy is to place the MSVC ``-machine:``
|
||||
flag in ``CMAKE_*_LINKER_FLAGS``. The ``NEW`` behavior for this policy
|
||||
is to *not* place the MSVC ``-machine:`` flag in ``CMAKE_*_LINKER_FLAGS``.
|
||||
|
||||
.. |INTRODUCED_IN_CMAKE_VERSION| replace:: 4.1
|
||||
.. |WARNS_OR_DOES_NOT_WARN| replace:: does *not* warn
|
||||
.. include:: include/STANDARD_ADVICE.rst
|
||||
|
||||
.. include:: include/DEPRECATED.rst
|
||||
5
Help/release/dev/msvc-link-machine.rst
Normal file
5
Help/release/dev/msvc-link-machine.rst
Normal file
@@ -0,0 +1,5 @@
|
||||
msvc-link-machine
|
||||
-----------------
|
||||
|
||||
* The MSVC link ``-machine:`` flag is no longer added to the
|
||||
``CMAKE_*_LINKER_FLAGS`` variables. See policy :policy:`CMP0197`.
|
||||
@@ -47,7 +47,7 @@ macro(__windows_compiler_intel lang)
|
||||
if (NOT "${lang}" STREQUAL "Fortran" OR CMAKE_${lang}_COMPILER_VERSION VERSION_GREATER_EQUAL 2022.1)
|
||||
# The Fortran driver does not support -fuse-ld=llvm-lib before compiler version 2022.1
|
||||
set(CMAKE_${lang}_CREATE_STATIC_LIBRARY
|
||||
"<CMAKE_${lang}_COMPILER> ${CMAKE_CL_NOLOGO} <CMAKE_${lang}_LINK_FLAGS> <OBJECTS> ${CMAKE_START_TEMP_FILE} -fuse-ld=llvm-lib -o <TARGET> <LINK_FLAGS> <LINK_LIBRARIES> ${CMAKE_END_TEMP_FILE}")
|
||||
"<CMAKE_${lang}_COMPILER> ${CMAKE_CL_NOLOGO}${_PLATFORM_ARCHIVE_FLAGS} <CMAKE_${lang}_LINK_FLAGS> <OBJECTS> ${CMAKE_START_TEMP_FILE} -fuse-ld=llvm-lib -o <TARGET> <LINK_FLAGS> <LINK_LIBRARIES> ${CMAKE_END_TEMP_FILE}")
|
||||
endif()
|
||||
|
||||
set(CMAKE_DEPFILE_FLAGS_${lang} "-QMD -QMT <DEP_TARGET> -QMF <DEP_FILE>")
|
||||
|
||||
@@ -276,7 +276,12 @@ unset(_GR)
|
||||
|
||||
set(CMAKE_CXX_STANDARD_LIBRARIES_INIT "${CMAKE_C_STANDARD_LIBRARIES_INIT}")
|
||||
|
||||
set(_machine "/machine")
|
||||
cmake_policy(GET CMP0197 CMAKE_MSVC_CMP0197)
|
||||
if(CMAKE_MSVC_CMP0197 STREQUAL "NEW")
|
||||
set(_machine "-machine")
|
||||
else()
|
||||
set(_machine "/machine")
|
||||
endif()
|
||||
|
||||
# executable linker flags
|
||||
set (CMAKE_LINK_DEF_FILE_FLAG "/DEF:")
|
||||
@@ -321,7 +326,9 @@ if(NOT WINDOWS_PHONE AND NOT WINDOWS_STORE AND NOT CMAKE_SYSTEM_NAME STREQUAL "W
|
||||
endif()
|
||||
|
||||
foreach(t EXE SHARED MODULE)
|
||||
string(APPEND CMAKE_${t}_LINKER_FLAGS_INIT " ${_MACHINE_ARCH_FLAG}")
|
||||
if(NOT CMAKE_MSVC_CMP0197 STREQUAL "NEW")
|
||||
string(APPEND CMAKE_${t}_LINKER_FLAGS_INIT " ${_MACHINE_ARCH_FLAG}")
|
||||
endif()
|
||||
if (CMAKE_COMPILER_SUPPORTS_PDBTYPE)
|
||||
string(APPEND CMAKE_${t}_LINKER_FLAGS_DEBUG_INIT " ${_Wl}/debug ${_Wl}/pdbtype:sept ${MSVC_INCREMENTAL_YES_FLAG}")
|
||||
string(APPEND CMAKE_${t}_LINKER_FLAGS_RELWITHDEBINFO_INIT " ${_Wl}/debug ${_Wl}/pdbtype:sept ${MSVC_INCREMENTAL_YES_FLAG}")
|
||||
@@ -340,11 +347,19 @@ if(CMAKE_SYSTEM_NAME STREQUAL "WindowsCE")
|
||||
elseif(CMAKE_SYSTEM_NAME STREQUAL "WindowsKernelModeDriver")
|
||||
string(APPEND _PLATFORM_LINK_FLAGS " -subsystem:native -kernel -MANIFEST:NO")
|
||||
endif()
|
||||
if(CMAKE_MSVC_CMP0197 STREQUAL "NEW")
|
||||
string(APPEND _PLATFORM_LINK_FLAGS " ${_MACHINE_ARCH_FLAG}")
|
||||
endif()
|
||||
|
||||
set(_PLATFORM_ARCHIVE_FLAGS "")
|
||||
if((_MSVC_C_ARCHITECTURE_FAMILY STREQUAL "ARM64EC") OR (_MSVC_CXX_ARCHITECTURE_FAMILY STREQUAL "ARM64EC"))
|
||||
set(_MACHINE_ARCH_FLAG " ${_Wl}${_machine}:ARM64X")
|
||||
endif()
|
||||
string(APPEND CMAKE_STATIC_LINKER_FLAGS_INIT " ${_MACHINE_ARCH_FLAG}")
|
||||
if(CMAKE_MSVC_CMP0197 STREQUAL "NEW")
|
||||
string(APPEND _PLATFORM_ARCHIVE_FLAGS " ${_MACHINE_ARCH_FLAG}")
|
||||
else()
|
||||
string(APPEND CMAKE_STATIC_LINKER_FLAGS_INIT " ${_MACHINE_ARCH_FLAG}")
|
||||
endif()
|
||||
unset(_MACHINE_ARCH_FLAG)
|
||||
unset(_machine)
|
||||
|
||||
@@ -388,7 +403,7 @@ macro(__windows_compiler_msvc lang)
|
||||
unset(_DLL_DRIVER)
|
||||
|
||||
set(CMAKE_${lang}_CREATE_SHARED_MODULE ${CMAKE_${lang}_CREATE_SHARED_LIBRARY})
|
||||
set(CMAKE_${lang}_CREATE_STATIC_LIBRARY "<CMAKE_AR> ${CMAKE_CL_NOLOGO} <LINK_FLAGS> /out:<TARGET> <OBJECTS> ")
|
||||
set(CMAKE_${lang}_CREATE_STATIC_LIBRARY "<CMAKE_AR> ${CMAKE_CL_NOLOGO}${_PLATFORM_ARCHIVE_FLAGS} <LINK_FLAGS> /out:<TARGET> <OBJECTS> ")
|
||||
|
||||
set(CMAKE_${lang}_COMPILE_OBJECT
|
||||
"<CMAKE_${lang}_COMPILER> ${CMAKE_START_TEMP_FILE} ${CMAKE_CL_NOLOGO}${_COMPILE_${lang}} <DEFINES> <INCLUDES> <FLAGS> /Fo<OBJECT> /Fd<TARGET_COMPILE_PDB>${_FS_${lang}} -c <SOURCE>${CMAKE_END_TEMP_FILE}")
|
||||
|
||||
@@ -17,7 +17,7 @@ set(CMAKE_CUDA_CREATE_SHARED_LIBRARY
|
||||
"${_CMAKE_VS_LINK_DLL}<CMAKE_LINKER> ${CMAKE_CL_NOLOGO} <OBJECTS> ${CMAKE_START_TEMP_FILE} /out:<TARGET> /implib:<TARGET_IMPLIB> /pdb:<TARGET_PDB> /dll /version:<TARGET_VERSION_MAJOR>.<TARGET_VERSION_MINOR>${_PLATFORM_LINK_FLAGS} <LINK_FLAGS> <LINK_LIBRARIES>${__IMPLICIT_LINKS} ${CMAKE_END_TEMP_FILE}")
|
||||
|
||||
set(CMAKE_CUDA_CREATE_SHARED_MODULE ${CMAKE_CUDA_CREATE_SHARED_LIBRARY})
|
||||
set(CMAKE_CUDA_CREATE_STATIC_LIBRARY "<CMAKE_AR> ${CMAKE_CL_NOLOGO} <LINK_FLAGS> /out:<TARGET> <OBJECTS> ")
|
||||
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_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}")
|
||||
|
||||
@@ -91,6 +91,7 @@ std::string const kCMAKE_MSVC_DEBUG_INFORMATION_FORMAT_DEFAULT =
|
||||
"CMAKE_MSVC_DEBUG_INFORMATION_FORMAT_DEFAULT";
|
||||
std::string const kCMAKE_MSVC_RUNTIME_CHECKS_DEFAULT =
|
||||
"CMAKE_MSVC_RUNTIME_CHECKS_DEFAULT";
|
||||
std::string const kCMAKE_MSVC_CMP0197 = "CMAKE_MSVC_CMP0197";
|
||||
|
||||
/* GHS Multi platform variables */
|
||||
std::set<std::string> const ghs_platform_vars{
|
||||
@@ -684,6 +685,12 @@ cm::optional<cmTryCompileResult> cmCoreTryCompile::TryCompileCode(
|
||||
fprintf(fout, "cmake_policy(SET CMP0128 OLD)\n");
|
||||
}
|
||||
|
||||
/* Set MSVC link -machine: policy to match outer project. */
|
||||
if (cmValue cmp0197 = this->Makefile->GetDefinition(kCMAKE_MSVC_CMP0197)) {
|
||||
fprintf(fout, "cmake_policy(SET CMP0197 %s)\n",
|
||||
*cmp0197 == "NEW"_s ? "NEW" : "OLD");
|
||||
}
|
||||
|
||||
std::string projectLangs;
|
||||
for (std::string const& li : testLangs) {
|
||||
projectLangs += cmStrCat(' ', li);
|
||||
|
||||
@@ -586,7 +586,10 @@ class cmMakefile;
|
||||
"Swift modules in build trees use the Swift module directory structure.", \
|
||||
4, 1, 0, WARN) \
|
||||
SELECT(POLICY, CMP0196, \
|
||||
"The CMakeDetermineVSServicePack module is removed.", 4, 1, 0, WARN)
|
||||
"The CMakeDetermineVSServicePack module is removed.", 4, 1, 0, WARN) \
|
||||
SELECT(POLICY, CMP0197, \
|
||||
"MSVC link -machine: flag is not in CMAKE_*_LINKER_FLAGS.", 4, 1, 0, \
|
||||
WARN)
|
||||
|
||||
#define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1)
|
||||
#define CM_FOR_EACH_POLICY_ID(POLICY) \
|
||||
|
||||
2
Tests/RunCMake/MSVCDefaultFlags/CMP0197-NEW-config.txt
Normal file
2
Tests/RunCMake/MSVCDefaultFlags/CMP0197-NEW-config.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
[ ,][/-][Mm][Aa][Cc][Hh][Ii][Nn][Ee]:[A-Za-z0-9_]+[ ]|[Vv][Cc](98|7)\\\\[Bb][Ii][Nn]\\\\[Ll][Ii][Nn][Kk]\.[Ee][Xx][Ee] [^
|
||||
]*@[^ ]+\\\\nm
|
||||
2
Tests/RunCMake/MSVCDefaultFlags/CMP0197-NEW.cmake
Normal file
2
Tests/RunCMake/MSVCDefaultFlags/CMP0197-NEW.cmake
Normal file
@@ -0,0 +1,2 @@
|
||||
cmake_policy(SET CMP0197 NEW)
|
||||
include(CMP0197-common.cmake)
|
||||
1
Tests/RunCMake/MSVCDefaultFlags/CMP0197-OLD-config.txt
Normal file
1
Tests/RunCMake/MSVCDefaultFlags/CMP0197-OLD-config.txt
Normal file
@@ -0,0 +1 @@
|
||||
[" ,]/[Mm][Aa][Cc][Hh][Ii][Nn][Ee]:[A-Za-z0-9_]+[ "]
|
||||
2
Tests/RunCMake/MSVCDefaultFlags/CMP0197-OLD.cmake
Normal file
2
Tests/RunCMake/MSVCDefaultFlags/CMP0197-OLD.cmake
Normal file
@@ -0,0 +1,2 @@
|
||||
cmake_policy(SET CMP0197 OLD)
|
||||
include(CMP0197-common.cmake)
|
||||
1
Tests/RunCMake/MSVCDefaultFlags/CMP0197-WARN-config.txt
Normal file
1
Tests/RunCMake/MSVCDefaultFlags/CMP0197-WARN-config.txt
Normal file
@@ -0,0 +1 @@
|
||||
[" ,]/[Mm][Aa][Cc][Hh][Ii][Nn][Ee]:[A-Za-z0-9_]+[ "]
|
||||
2
Tests/RunCMake/MSVCDefaultFlags/CMP0197-WARN.cmake
Normal file
2
Tests/RunCMake/MSVCDefaultFlags/CMP0197-WARN.cmake
Normal file
@@ -0,0 +1,2 @@
|
||||
|
||||
include(CMP0197-common.cmake)
|
||||
1
Tests/RunCMake/MSVCDefaultFlags/CMP0197-build-stdout.txt
Normal file
1
Tests/RunCMake/MSVCDefaultFlags/CMP0197-build-stdout.txt
Normal file
@@ -0,0 +1 @@
|
||||
[ ,][/-][Mm][Aa][Cc][Hh][Ii][Nn][Ee]:[A-Za-z0-9_]+[ ]
|
||||
20
Tests/RunCMake/MSVCDefaultFlags/CMP0197-common.cmake
Normal file
20
Tests/RunCMake/MSVCDefaultFlags/CMP0197-common.cmake
Normal file
@@ -0,0 +1,20 @@
|
||||
enable_language(C)
|
||||
|
||||
# Make sure the compile command is not hidden.
|
||||
string(REPLACE "${CMAKE_START_TEMP_FILE}" "" CMAKE_C_LINK_EXECUTABLE "${CMAKE_C_LINK_EXECUTABLE}")
|
||||
string(REPLACE "${CMAKE_END_TEMP_FILE}" "" CMAKE_C_LINK_EXECUTABLE "${CMAKE_C_LINK_EXECUTABLE}")
|
||||
|
||||
cmake_policy(GET CMP0197 cmp0197)
|
||||
foreach(t EXE SHARED MODULE STATIC)
|
||||
if(cmp0197 STREQUAL "NEW")
|
||||
if("${CMAKE_${t}_LINKER_FLAGS}" MATCHES "([/-][Mm][Aa][Cc][Hh][Ii][Nn][Ee]:)")
|
||||
message(SEND_ERROR "CMAKE_${t}_LINKER_FLAGS has '${CMAKE_MATCH_1}' under NEW behavior")
|
||||
endif()
|
||||
else()
|
||||
if(NOT " ${CMAKE_${t}_LINKER_FLAGS} " MATCHES "[ ,]/machine:[A-Za-z0-9_]+ ")
|
||||
message(SEND_ERROR "CMAKE_${t}_LINKER_FLAGS does not have '/machine:' under OLD behavior")
|
||||
endif()
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
add_executable(main main.c)
|
||||
@@ -3,3 +3,16 @@ include(RunCMake)
|
||||
run_cmake(CMP0092-WARN)
|
||||
run_cmake(CMP0092-OLD)
|
||||
run_cmake(CMP0092-NEW)
|
||||
|
||||
function(run_CMP0197 pol)
|
||||
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/CMP0197-${pol})
|
||||
run_cmake(CMP0197-${pol})
|
||||
set(RunCMake_TEST_NO_CLEAN 1)
|
||||
set(RunCMake_TEST_OUTPUT_MERGE 1)
|
||||
set(RunCMake-stdout-file "CMP0197-build-stdout.txt")
|
||||
run_cmake_command(CMP0197-${pol}-build ${CMAKE_COMMAND} --build . --config Debug --verbose)
|
||||
endfunction()
|
||||
|
||||
run_CMP0197(WARN)
|
||||
run_CMP0197(OLD)
|
||||
run_CMP0197(NEW)
|
||||
|
||||
4
Tests/RunCMake/MSVCDefaultFlags/main.c
Normal file
4
Tests/RunCMake/MSVCDefaultFlags/main.c
Normal file
@@ -0,0 +1,4 @@
|
||||
int main(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user