Swift: Honor CMAKE_EXE_LINKER_FLAGS when CMP0157 is NEW

Since commit 56e5cea600 (Swift: Support module libraries with
command-line build systems, 2024-03-23, v3.30.0-rc1~245^2) we pass
`CMAKE_SHARED_LINKER_FLAGS` when linking Swift shared libraries if
CMP0157 is NEW.  For consistency, pass `CMAKE_EXE_LINKER_FLAGS` when
linking executables.  Add policy CMP0214 for compatibility.

Fixes: #26154
This commit is contained in:
Fabrice de Gans
2026-04-15 13:01:37 +02:00
committed by Brad King
parent 53d49e5aa4
commit 15a6d96359
13 changed files with 120 additions and 3 deletions

View File

@@ -100,6 +100,7 @@ Policies Introduced by CMake 4.4
.. toctree::
:maxdepth: 1
CMP0214: Honor CMAKE_EXE_LINKER_FLAGS for Swift executable targets. </policy/CMP0214>
CMP0213: file(ARCHIVE_{CREATE,EXTRACT}) encode archive paths as UTF-8 by default. </policy/CMP0213>
CMP0212: add_custom_command DEPENDS does not strip .exe suffixes. </policy/CMP0212>
CMP0211: A file may belong to at most one file set in a target. </policy/CMP0211>

33
Help/policy/CMP0214.rst Normal file
View File

@@ -0,0 +1,33 @@
CMP0214
-------
.. versionadded:: 4.4
Honor ``CMAKE_EXE_LINKER_FLAGS`` for Swift executable targets.
CMake 3.29 introduced :policy:`CMP0157`, which provides an abstraction
for selecting the Swift compilation mode. In CMake 3.30,
:variable:`CMAKE_SHARED_LINKER_FLAGS` was accidentally honored for
Swift shared library targets when :policy:`CMP0157` is ``NEW``, but
the change went unnoticed and was not documented. The corresponding
change was not made for Swift executable targets, leaving linker flag
handling inconsistent between Swift executables and Swift shared
libraries in CMake 3.30 through 4.3.
CMake 4.4 and above prefer to honor :variable:`CMAKE_EXE_LINKER_FLAGS`
for Swift executable targets when :policy:`CMP0157` is set to ``NEW``,
restoring consistency with Swift shared library targets. This policy
provides compatibility for projects that have not been updated to
expect ``CMAKE_EXE_LINKER_FLAGS`` to be honored for Swift executables.
The ``OLD`` behavior for this policy is to not honor
:variable:`CMAKE_EXE_LINKER_FLAGS` for Swift executable targets.
The ``NEW`` behavior for this policy is to honor
:variable:`CMAKE_EXE_LINKER_FLAGS` for Swift executable targets
when :policy:`CMP0157` is set to ``NEW``.
.. |INTRODUCED_IN_CMAKE_VERSION| replace:: 4.4
.. |WARNS_OR_DOES_NOT_WARN| replace:: does *not* warn
.. include:: include/STANDARD_ADVICE.rst
.. include:: include/DEPRECATED.rst

View File

@@ -1562,7 +1562,9 @@ void cmLocalGenerator::GetTargetFlags(
}
} break;
case cmStateEnums::EXECUTABLE: {
if (linkLanguage != "Swift") {
if (linkLanguage != "Swift" ||
(this->IsSplitSwiftBuild() &&
target->GetPolicyStatusCMP0214() == cmPolicies::NEW)) {
std::string exeFlags;
this->AddTargetTypeLinkerFlags(exeFlags, target, linkLanguage, config);
if (!exeFlags.empty()) {

View File

@@ -639,7 +639,10 @@ class cmMakefile;
SELECT(POLICY, CMP0213, \
"file(ARCHIVE_{CREATE,EXTRACT}) encode archive paths as UTF-8 by " \
"default.", \
4, 4, 0, WARN)
4, 4, 0, WARN) \
SELECT(POLICY, CMP0214, \
"Honor CMAKE_EXE_LINKER_FLAGS for Swift executable targets.", 4, 4, \
0, WARN)
#define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1)
#define CM_FOR_EACH_POLICY_ID(POLICY) \
@@ -695,7 +698,8 @@ class cmMakefile;
F(CMP0204) \
F(CMP0209) \
F(CMP0210) \
F(CMP0211)
F(CMP0211) \
F(CMP0214)
#define CM_FOR_EACH_CUSTOM_COMMAND_POLICY(F) \
F(CMP0116) \

View File

@@ -0,0 +1,18 @@
if(RunCMake_GENERATOR_IS_MULTI_CONFIG)
set(path "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/impl-Debug.ninja")
else()
set(path "${RunCMake_TEST_BINARY_DIR}/build.ninja")
endif()
file(READ "${path}" build_ninja)
# With CMP0157 OLD (no split build), CMAKE_SHARED_LINKER_FLAGS should NOT be
# passed to Swift shared libraries.
if(build_ninja MATCHES "Swift_SHARED_LIBRARY_LINKER[^\n]*(\n [^\n]+)*\n LINK_FLAGS = [^\n]*-foo")
string(APPEND RunCMake_TEST_FAILED "Build file:\n ${path}\nunexpectedly has -foo in LINK_FLAGS for Swift shared library\n")
endif()
# With CMP0157 OLD (no split build), CMAKE_EXE_LINKER_FLAGS should NOT be
# passed to Swift executables even with CMP0214 NEW.
if(build_ninja MATCHES "Swift_EXECUTABLE_LINKER[^\n]*(\n [^\n]+)*\n LINK_FLAGS = [^\n]*-foo")
string(APPEND RunCMake_TEST_FAILED "Build file:\n ${path}\nunexpectedly has -foo in LINK_FLAGS for Swift executable\n")
endif()

View File

@@ -0,0 +1,4 @@
cmake_minimum_required(VERSION 4.3)
cmake_policy(SET CMP0157 OLD)
cmake_policy(SET CMP0214 NEW)
include(LinkerFlags-common.cmake)

View File

@@ -0,0 +1,17 @@
if(RunCMake_GENERATOR_IS_MULTI_CONFIG)
set(path "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/impl-Debug.ninja")
else()
set(path "${RunCMake_TEST_BINARY_DIR}/build.ninja")
endif()
file(READ "${path}" build_ninja)
# With CMP0157 NEW (split build), CMAKE_SHARED_LINKER_FLAGS should be passed
# to Swift shared libraries regardless of CMP0214.
if(NOT build_ninja MATCHES "Swift_SHARED_LIBRARY_LINKER[^\n]*(\n [^\n]+)*\n LINK_FLAGS = [^\n]*-foo")
string(APPEND RunCMake_TEST_FAILED "Build file:\n ${path}\ndoes not have -foo in LINK_FLAGS for Swift shared library\n")
endif()
# With CMP0214 NEW, CMAKE_EXE_LINKER_FLAGS should be passed to Swift executables.
if(NOT build_ninja MATCHES "Swift_EXECUTABLE_LINKER[^\n]*(\n [^\n]+)*\n LINK_FLAGS = [^\n]*-foo")
string(APPEND RunCMake_TEST_FAILED "Build file:\n ${path}\ndoes not have -foo in LINK_FLAGS for Swift executable\n")
endif()

View File

@@ -0,0 +1,4 @@
cmake_minimum_required(VERSION 4.3)
cmake_policy(SET CMP0157 NEW)
cmake_policy(SET CMP0214 NEW)
include(LinkerFlags-common.cmake)

View File

@@ -0,0 +1,17 @@
if(RunCMake_GENERATOR_IS_MULTI_CONFIG)
set(path "${RunCMake_TEST_BINARY_DIR}/CMakeFiles/impl-Debug.ninja")
else()
set(path "${RunCMake_TEST_BINARY_DIR}/build.ninja")
endif()
file(READ "${path}" build_ninja)
# With CMP0157 NEW (split build), CMAKE_SHARED_LINKER_FLAGS should still be
# passed to Swift shared libraries even with CMP0214 OLD.
if(NOT build_ninja MATCHES "Swift_SHARED_LIBRARY_LINKER[^\n]*(\n [^\n]+)*\n LINK_FLAGS = [^\n]*-foo")
string(APPEND RunCMake_TEST_FAILED "Build file:\n ${path}\ndoes not have -foo in LINK_FLAGS for Swift shared library\n")
endif()
# With CMP0214 OLD, CMAKE_EXE_LINKER_FLAGS should NOT be passed to Swift executables.
if(build_ninja MATCHES "Swift_EXECUTABLE_LINKER[^\n]*(\n [^\n]+)*\n LINK_FLAGS = [^\n]*-foo")
string(APPEND RunCMake_TEST_FAILED "Build file:\n ${path}\nunexpectedly has -foo in LINK_FLAGS for Swift executable\n")
endif()

View File

@@ -0,0 +1,4 @@
cmake_minimum_required(VERSION 4.3)
cmake_policy(SET CMP0157 NEW)
cmake_policy(SET CMP0214 OLD)
include(LinkerFlags-common.cmake)

View File

@@ -0,0 +1,8 @@
enable_language(Swift)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -foo")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -foo")
add_library(L SHARED L.swift)
add_executable(E E.swift)
target_link_libraries(E PRIVATE L)

View File

@@ -161,4 +161,8 @@ if(RunCMake_GENERATOR MATCHES "Ninja")
set(RunCMake_TEST_NO_CLEAN 1)
run_cmake_command(SwiftLibraryModuleCommand-check ${CMAKE_COMMAND} --build . -- -n -v)
endblock()
run_cmake(CMP0214-NEW)
run_cmake(CMP0214-OLD)
run_cmake(CMP0214-NEW-CMP0157-OLD)
endif()

View File

@@ -55,6 +55,7 @@
\* CMP0209
\* CMP0210
\* CMP0211
\* CMP0214
Call Stack \(most recent call first\):
CMakeLists\.txt:3 \(include\)