mirror of
https://gitlab.kitware.com/cmake/cmake.git
synced 2026-09-25 04:09:36 +03:00
CMP0215: Update NEW behavior to require CMP0157/CMP0195 to be NEW
Update CMP0215 to avoid attempting to iterate through the flags looking for `-emit-module-path` ins the user-specified flags. We don't do this anywhere else in the code. The existing implementation didn't handle correctly parsing the flag so `-I blah/my-emit-module-path/` and `-Xcc -emit-module-path ...` would both trigger it, result in the compiler not emitting any module. Furthermore, it didn't include the user-specified module path as part of the build graph resulting in an incorrect build graph that would never resolve. The only two appropriate layouts for the module are either the flat binary module file with the name `<module-name>.swiftmodule`, or the nested form with `<module-name>.swiftmodule/<module-triple>.swiftmodule`. The noted Swift-Syntax situation passes the explicit `-emit-module-path` to get to the latter form. This form is automatically emitted by CMake when CMP0195 is `NEW`, removing the need for the flag. The Swift project generally recommends the nested directory structure since it gathers all of the generated interface outputs from the compiler (textual swift interfaces, swiftdoc, sourceinfo, and the binary swiftmodule file) in a single place, and since it uses the module triple in the filename, cleanly allows fat mach-o binaries on Apple platforms. Fixes: #28021
This commit is contained in:
@@ -24,13 +24,15 @@ The :prop_tgt:`Swift_SEPARATE_MODULE_EMISSION` target property and
|
||||
corresponding :variable:`CMAKE_Swift_SEPARATE_MODULE_EMISSION` variable
|
||||
may be set to enable or disable the behavior on a per-target basis.
|
||||
|
||||
.. note::
|
||||
|
||||
Separate module emission takes effect only when policy :policy:`CMP0157`
|
||||
is set to ``NEW`` prior to the first :command:`project` or
|
||||
:command:`enable_language` command that enables the Swift language.
|
||||
The dedicated ``.swiftmodule`` edge is available only in the split
|
||||
Swift build model.
|
||||
The ``NEW`` behavior requires that policies :policy:`CMP0157` and
|
||||
:policy:`CMP0195` are also set to ``NEW``. :policy:`CMP0157` selects the
|
||||
split Swift build model that provides the dedicated ``.swiftmodule`` edge,
|
||||
and must be set prior to the first :command:`project` or
|
||||
:command:`enable_language` command that enables the Swift language.
|
||||
:policy:`CMP0195` places the module in the Swift module directory structure
|
||||
that the dedicated edge writes. If either policy is not ``NEW`` while
|
||||
``CMP0215`` is ``NEW``, CMake issues a fatal error when the Swift language
|
||||
is enabled.
|
||||
|
||||
.. |INTRODUCED_IN_CMAKE_VERSION| replace:: 4.4
|
||||
.. |WARNS_OR_DOES_NOT_WARN| replace:: does *not* warn
|
||||
|
||||
@@ -322,7 +322,9 @@ Swift
|
||||
:prop_tgt:`Swift_SEPARATE_MODULE_EMISSION` target property, initialized by
|
||||
the :variable:`CMAKE_Swift_SEPARATE_MODULE_EMISSION` variable, to control
|
||||
whether importable Swift targets emit ``.swiftmodule`` from a dedicated
|
||||
build edge. Policy :policy:`CMP0215` enables this by default.
|
||||
build edge. Policy :policy:`CMP0215` enables this by default. The
|
||||
behavior requires policies :policy:`CMP0157` and :policy:`CMP0195` to be
|
||||
set to ``NEW``.
|
||||
|
||||
* The default :prop_tgt:`Swift_MODULE_NAME` now replaces hyphens with
|
||||
underscores, since hyphens are not valid in Swift module identifiers.
|
||||
@@ -450,3 +452,9 @@ Changes made since CMake 4.4.0 include the following.
|
||||
* This version made no changes to documented features or interfaces.
|
||||
Some implementation updates were made to support ecosystem changes
|
||||
and/or fix regressions.
|
||||
|
||||
.. 4.4.3
|
||||
|
||||
* Swift policy :poilcy:`CMP0215`'s ``NEW`` behavior has been updated
|
||||
to require policies :policy:`CMP0157` and :policy:`CMP0195` to also
|
||||
be set to ``NEW``.
|
||||
|
||||
@@ -109,6 +109,47 @@ else()
|
||||
endif()
|
||||
unset(__SWIFT_COMP_MODE_CMP0157)
|
||||
|
||||
# Separate Swift module emission (see policy CMP0215) is available only in the
|
||||
# split build model selected by policy CMP0157, and it writes the module into
|
||||
# the Swift module directory structure selected by policy CMP0195. When
|
||||
# CMP0215 is NEW, require both to also be NEW. This is a Ninja-only feature,
|
||||
# so only enforce the requirement for Ninja generators.
|
||||
if(CMAKE_GENERATOR MATCHES "Ninja")
|
||||
cmake_policy(GET CMP0215 __SWIFT_SEPARATE_MODULE_CMP0215)
|
||||
if(__SWIFT_SEPARATE_MODULE_CMP0215 STREQUAL "NEW")
|
||||
set(__SWIFT_SEPARATE_MODULE_UNMET "")
|
||||
cmake_policy(GET CMP0157 __SWIFT_SEPARATE_MODULE_CMP0157)
|
||||
if(NOT __SWIFT_SEPARATE_MODULE_CMP0157 STREQUAL "NEW")
|
||||
list(APPEND __SWIFT_SEPARATE_MODULE_UNMET CMP0157)
|
||||
endif()
|
||||
cmake_policy(GET CMP0195 __SWIFT_SEPARATE_MODULE_CMP0195)
|
||||
if(NOT __SWIFT_SEPARATE_MODULE_CMP0195 STREQUAL "NEW")
|
||||
list(APPEND __SWIFT_SEPARATE_MODULE_UNMET CMP0195)
|
||||
endif()
|
||||
if(__SWIFT_SEPARATE_MODULE_UNMET)
|
||||
list(LENGTH __SWIFT_SEPARATE_MODULE_UNMET __SWIFT_SEPARATE_MODULE_UNMET_COUNT)
|
||||
list(JOIN __SWIFT_SEPARATE_MODULE_UNMET " and " __SWIFT_SEPARATE_MODULE_UNMET_STR)
|
||||
if(__SWIFT_SEPARATE_MODULE_UNMET_COUNT GREATER 1)
|
||||
set(__SWIFT_SEPARATE_MODULE_VERB "are")
|
||||
else()
|
||||
set(__SWIFT_SEPARATE_MODULE_VERB "is")
|
||||
endif()
|
||||
message(FATAL_ERROR
|
||||
"Policy CMP0215 is set to 'NEW', which requires policies CMP0157 and "
|
||||
"CMP0195 to be set to 'NEW', but ${__SWIFT_SEPARATE_MODULE_UNMET_STR} "
|
||||
"${__SWIFT_SEPARATE_MODULE_VERB} not. Note that CMP0157 must be set "
|
||||
"before the Swift language is enabled.")
|
||||
endif()
|
||||
unset(__SWIFT_SEPARATE_MODULE_CMP0157)
|
||||
unset(__SWIFT_SEPARATE_MODULE_CMP0195)
|
||||
unset(__SWIFT_SEPARATE_MODULE_UNMET)
|
||||
unset(__SWIFT_SEPARATE_MODULE_UNMET_COUNT)
|
||||
unset(__SWIFT_SEPARATE_MODULE_UNMET_STR)
|
||||
unset(__SWIFT_SEPARATE_MODULE_VERB)
|
||||
endif()
|
||||
unset(__SWIFT_SEPARATE_MODULE_CMP0215)
|
||||
endif()
|
||||
|
||||
cmake_initialize_per_config_variable(CMAKE_Swift_FLAGS "Swift Compiler Flags")
|
||||
|
||||
if(NOT CMAKE_Swift_NUM_THREADS MATCHES "^[0-9]+$")
|
||||
|
||||
@@ -1291,7 +1291,6 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatements(
|
||||
this->GeneratorTarget->GetObjectSources(objectSources, config);
|
||||
|
||||
std::vector<cmSourceFile const*> swiftSources;
|
||||
|
||||
for (cmSourceFile const* sf : objectSources) {
|
||||
if (this->GetLocalGenerator()->IsSplitSwiftBuild() &&
|
||||
sf->GetLanguage() == "Swift") {
|
||||
@@ -1301,6 +1300,7 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatements(
|
||||
firstForConfig);
|
||||
}
|
||||
}
|
||||
|
||||
WriteSwiftObjectBuildStatement(swiftSources, config, fileConfig,
|
||||
firstForConfig);
|
||||
}
|
||||
@@ -2223,9 +2223,6 @@ void cmNinjaTargetGenerator::WriteSwiftObjectBuildStatement(
|
||||
this->GetGlobalGenerator()->GetLanguageOutputExtension(language)));
|
||||
objBuild.RspFile = cmStrCat(targetObjectFilename, ".swift.rsp");
|
||||
|
||||
// Importable targets keep -emit-module on compile so swiftc still emits
|
||||
// .swiftdoc. When splitting module emission, both the .swiftmodule output
|
||||
// and -emit-module flags move entirely to the separate emit-module edge.
|
||||
if (targetIsImportable) {
|
||||
this->Configs[config].SwiftModuleOutput = moduleFilepath;
|
||||
}
|
||||
@@ -2267,8 +2264,8 @@ void cmNinjaTargetGenerator::WriteSwiftObjectBuildStatement(
|
||||
std::string const moduleOutputPath =
|
||||
this->LocalGenerator->ConvertToOutputFormat(moduleFilepath,
|
||||
cmOutputConverter::SHELL);
|
||||
if (targetIsImportable && !emitModuleSeparately &&
|
||||
commonFlags.find("-emit-module-path") == std::string::npos) {
|
||||
|
||||
if (targetIsImportable && !emitModuleSeparately) {
|
||||
std::string const emitModuleFlag = "-emit-module";
|
||||
std::string const modulePathFlag = "-emit-module-path";
|
||||
this->LocalGenerator->AppendFlags(
|
||||
@@ -2317,11 +2314,9 @@ void cmNinjaTargetGenerator::WriteSwiftObjectBuildStatement(
|
||||
// Skip if the flags already contain one (e.g. a directory-style path
|
||||
// set by the target's compile options).
|
||||
modBuild.Variables["FLAGS"] = commonFlags;
|
||||
if (commonFlags.find("-emit-module-path") == std::string::npos) {
|
||||
this->LocalGenerator->AppendFlags(
|
||||
modBuild.Variables["FLAGS"],
|
||||
cmStrCat("-emit-module-path ", moduleOutputPath));
|
||||
}
|
||||
this->LocalGenerator->AppendFlags(
|
||||
modBuild.Variables["FLAGS"],
|
||||
cmStrCat("-emit-module-path ", moduleOutputPath));
|
||||
|
||||
modBuild.RspFile = cmStrCat(moduleFilepath, ".rsp");
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
cmake_policy(SET CMP0157 NEW)
|
||||
cmake_policy(SET CMP0195 NEW)
|
||||
cmake_policy(SET CMP0215 NEW)
|
||||
|
||||
if(NOT CMAKE_GENERATOR MATCHES "Ninja")
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
# When the target's flags already contain -emit-module-path, the emit-module
|
||||
# edge should not append a second one that clobbers it.
|
||||
# Match command lines that have two -emit-module-path flags on the same line.
|
||||
string(
|
||||
REGEX MATCHALL
|
||||
"-emit-module-path [^\n]*-emit-module-path"
|
||||
duplicate_flags "${actual_stdout}")
|
||||
if(duplicate_flags)
|
||||
string(APPEND RunCMake_TEST_FAILED
|
||||
"Found command with duplicate -emit-module-path flags.\n")
|
||||
endif()
|
||||
@@ -1,22 +0,0 @@
|
||||
cmake_minimum_required(VERSION 4.0)
|
||||
|
||||
cmake_policy(SET CMP0157 NEW)
|
||||
cmake_policy(SET CMP0195 NEW)
|
||||
cmake_policy(SET CMP0215 NEW)
|
||||
|
||||
if(NOT CMAKE_GENERATOR MATCHES "Ninja")
|
||||
message(SEND_ERROR "this test must use a Ninja generator, found ${CMAKE_GENERATOR}")
|
||||
endif()
|
||||
|
||||
enable_language(Swift)
|
||||
|
||||
add_library(L STATIC L.swift)
|
||||
add_library(LClient STATIC LClient.swift)
|
||||
target_link_libraries(LClient PRIVATE L)
|
||||
|
||||
# Simulate a target whose flags already contain -emit-module-path with a
|
||||
# directory-style path (as seen with swift-syntax's CMake config). Use the
|
||||
# real module triple so the path matches GetSwiftModulePath() and the build
|
||||
# would succeed outside of dry-run.
|
||||
target_compile_options(L PRIVATE
|
||||
-emit-module-path ${CMAKE_CURRENT_BINARY_DIR}/L.swiftmodule/${CMAKE_Swift_MODULE_TRIPLE}.swiftmodule)
|
||||
@@ -1,4 +1,5 @@
|
||||
cmake_policy(SET CMP0157 NEW)
|
||||
cmake_policy(SET CMP0195 NEW)
|
||||
cmake_policy(SET CMP0215 NEW)
|
||||
|
||||
if(NOT CMAKE_GENERATOR MATCHES "Ninja")
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
cmake_policy(SET CMP0157 NEW)
|
||||
cmake_policy(SET CMP0195 NEW)
|
||||
cmake_policy(SET CMP0215 NEW)
|
||||
|
||||
if(NOT CMAKE_GENERATOR MATCHES "Ninja")
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
cmake_policy(SET CMP0157 NEW)
|
||||
cmake_policy(SET CMP0195 NEW)
|
||||
cmake_policy(SET CMP0215 NEW)
|
||||
|
||||
if(NOT CMAKE_GENERATOR MATCHES "Ninja")
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1,4 @@
|
||||
CMake Error at [^
|
||||
]*CMakeSwiftInformation\.cmake:[0-9]+ \(message\):
|
||||
Policy CMP0215 is set to 'NEW', which requires policies CMP0157 and CMP0195
|
||||
to be set to 'NEW', but CMP0157 and CMP0195 are not\.
|
||||
@@ -0,0 +1,14 @@
|
||||
cmake_minimum_required(VERSION 4.0)
|
||||
|
||||
# CMP0157 must be set before the Swift language is enabled.
|
||||
cmake_policy(SET CMP0157 OLD)
|
||||
cmake_policy(SET CMP0195 OLD)
|
||||
cmake_policy(SET CMP0215 NEW)
|
||||
|
||||
if(NOT CMAKE_GENERATOR MATCHES "Ninja")
|
||||
message(SEND_ERROR "this test must use a Ninja generator, found ${CMAKE_GENERATOR}")
|
||||
endif()
|
||||
|
||||
# CMP0215=NEW requires both CMP0157=NEW and CMP0195=NEW; neither is set here,
|
||||
# so enabling the Swift language must fail and name both policies.
|
||||
enable_language(Swift)
|
||||
@@ -5,7 +5,7 @@ if(NOT actual_stdout MATCHES
|
||||
endif()
|
||||
|
||||
if(NOT actual_stdout MATCHES
|
||||
"swiftc(\\.exe)?\"? [^\n]* -emit-module @.*L\\.swiftmodule\\.rsp")
|
||||
"swiftc(\\.exe)?\"? [^\n]* -emit-module @.*L\\.swiftmodule(/|\\\\)[-_a-zA-Z0-9]+\\.swiftmodule\\.rsp")
|
||||
string(APPEND RunCMake_TEST_FAILED
|
||||
"No Swift emit-module response-file command found for target L.\n")
|
||||
endif()
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
cmake_policy(SET CMP0157 NEW)
|
||||
cmake_policy(SET CMP0195 NEW)
|
||||
cmake_policy(SET CMP0215 NEW)
|
||||
|
||||
if(NOT CMAKE_GENERATOR MATCHES "Ninja")
|
||||
|
||||
@@ -184,15 +184,11 @@ if(RunCMake_GENERATOR MATCHES "Ninja")
|
||||
endblock()
|
||||
|
||||
block()
|
||||
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/EmitModuleSeparatelyExistingModulePath-build)
|
||||
run_cmake(EmitModuleSeparatelyExistingModulePath)
|
||||
set(RunCMake_TEST_NO_CLEAN 1)
|
||||
# -v: verbose to capture executed commands -n: dry-run to avoid actually compiling
|
||||
run_cmake_command(EmitModuleSeparatelyExistingModulePath-build ${CMAKE_COMMAND} --build . -- -vn)
|
||||
run_cmake(EmitModuleSeparatelyOrdering)
|
||||
endblock()
|
||||
|
||||
block()
|
||||
run_cmake(EmitModuleSeparatelyOrdering)
|
||||
run_cmake(EmitModuleSeparatelyRequiresPolicies)
|
||||
endblock()
|
||||
|
||||
block()
|
||||
|
||||
Reference in New Issue
Block a user