mirror of
https://gitlab.kitware.com/cmake/cmake.git
synced 2026-09-25 04:09:36 +03:00
Swift/Ninja: Emit modules separately from compilation
Add policy CMP0215 to emit `.swiftmodule` from a dedicated `-emit-module` build edge for importable Swift targets in the Ninja generator. Downstream targets can begin compiling as soon as the module interface is ready, overlapping with upstream object compilation and linking. When CMP0215 is NEW and CMP0157 is NEW, separate module emission is enabled by default. The `Swift_SEPARATE_MODULE_EMISSION` target property (initialized by the `CMAKE_Swift_SEPARATE_MODULE_EMISSION` variable) can override this per target. The compile edge still passes `-emit-module` so that swiftc continues to produce `.swiftdoc`; only the `.swiftmodule` output moves to the new edge. Also fix swiftmodule dependency edges in cmNinjaNormalTargetGenerator to use IsLanguageUsed instead of GetLinkerLanguage, so C/C++ targets whose linker language propagated to Swift do not produce spurious implicit dependencies. Closes: #27748
This commit is contained in:
@@ -415,6 +415,7 @@ syn keyword cmakeProperty contained
|
||||
\ Swift_LANGUAGE_VERSION
|
||||
\ Swift_MODULE_DIRECTORY
|
||||
\ Swift_MODULE_NAME
|
||||
\ Swift_SEPARATE_MODULE_EMISSION
|
||||
\ TARGET_ARCHIVES_MAY_BE_SHARED_LIBS
|
||||
\ TARGET_MESSAGES
|
||||
\ TARGET_SUPPORTS_SHARED_LIBS
|
||||
@@ -2037,6 +2038,7 @@ syn keyword cmakeVariable contained
|
||||
\ CMAKE_Swift_NUM_THREADS
|
||||
\ CMAKE_Swift_OUTPUT_EXTENSION
|
||||
\ CMAKE_Swift_PLATFORM_ID
|
||||
\ CMAKE_Swift_SEPARATE_MODULE_EMISSION
|
||||
\ CMAKE_Swift_SIMULATE_ID
|
||||
\ CMAKE_Swift_SIMULATE_VERSION
|
||||
\ CMAKE_Swift_SIZEOF_DATA_PTR
|
||||
|
||||
@@ -100,6 +100,7 @@ Policies Introduced by CMake 4.4
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
CMP0215: Ninja generators emit Swift modules separately from compilation. </policy/CMP0215>
|
||||
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>
|
||||
|
||||
@@ -427,6 +427,7 @@ Properties on Targets
|
||||
/prop_tgt/Swift_LANGUAGE_VERSION
|
||||
/prop_tgt/Swift_MODULE_DIRECTORY
|
||||
/prop_tgt/Swift_MODULE_NAME
|
||||
/prop_tgt/Swift_SEPARATE_MODULE_EMISSION
|
||||
/prop_tgt/SYMBOLIC
|
||||
/prop_tgt/SYSTEM
|
||||
/prop_tgt/TEST_LAUNCHER
|
||||
|
||||
@@ -142,6 +142,7 @@ Variables that Provide Information
|
||||
/variable/CMAKE_Swift_COMPILATION_MODE
|
||||
/variable/CMAKE_Swift_MODULE_DIRECTORY
|
||||
/variable/CMAKE_Swift_NUM_THREADS
|
||||
/variable/CMAKE_Swift_SEPARATE_MODULE_EMISSION
|
||||
/variable/CMAKE_TEST_LAUNCHER
|
||||
/variable/CMAKE_TOOLCHAIN_FILE
|
||||
/variable/CMAKE_TWEAK_VERSION
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
CMP0215
|
||||
-------
|
||||
|
||||
.. versionadded:: 4.4
|
||||
|
||||
:ref:`Ninja Generators` emit Swift modules separately from compilation.
|
||||
|
||||
In CMake 4.3 and below, Swift targets built by :ref:`Ninja Generators`
|
||||
emit ``.swiftmodule`` from the Swift compile edge together with object files.
|
||||
Because Ninja treats a build edge as atomic, downstream Swift targets
|
||||
must wait for compilation outputs to finish before they can use the module
|
||||
interface.
|
||||
|
||||
CMake 4.4 and above prefer to emit ``.swiftmodule`` from a dedicated
|
||||
``-emit-module`` build edge so that downstream Swift targets can begin
|
||||
compiling as soon as the module interface is available. This policy
|
||||
provides compatibility with projects that have not been updated.
|
||||
|
||||
The ``OLD`` behavior for this policy is to not emit modules separately.
|
||||
The ``NEW`` behavior for this policy is to emit ``.swiftmodule`` from a
|
||||
dedicated build edge for importable Swift targets by default.
|
||||
|
||||
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.
|
||||
|
||||
.. |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
|
||||
@@ -0,0 +1,24 @@
|
||||
Swift_SEPARATE_MODULE_EMISSION
|
||||
------------------------------
|
||||
|
||||
.. versionadded:: 4.4
|
||||
|
||||
Emit Swift modules separately from compilation in the :ref:`Ninja Generators`.
|
||||
|
||||
When this property is set to ``ON`` on an importable Swift target built by
|
||||
:ref:`Ninja Generators`, CMake emits a separate ``-emit-module`` build edge
|
||||
that produces the ``.swiftmodule`` independently of object compilation.
|
||||
This allows downstream Swift targets to begin compiling as soon as the
|
||||
module interface is available, rather than waiting for all upstream
|
||||
compilation outputs.
|
||||
|
||||
The property is initialized from the value of the
|
||||
:variable:`CMAKE_Swift_SEPARATE_MODULE_EMISSION` variable, if it is set.
|
||||
If this property is not set, separate module emission is enabled by default.
|
||||
See policy :policy:`CMP0215`.
|
||||
|
||||
.. 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.
|
||||
@@ -0,0 +1,8 @@
|
||||
swift-ninja-separate-swiftmodule-edge
|
||||
-------------------------------------
|
||||
|
||||
* The :ref:`Ninja Generators` gained the
|
||||
: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.
|
||||
@@ -0,0 +1,24 @@
|
||||
CMAKE_Swift_SEPARATE_MODULE_EMISSION
|
||||
-------------------------------------
|
||||
|
||||
.. versionadded:: 4.4
|
||||
|
||||
Specify whether Swift targets emit ``.swiftmodule`` from a dedicated build
|
||||
edge. This variable is used to initialize the
|
||||
:prop_tgt:`Swift_SEPARATE_MODULE_EMISSION` property on targets as they are
|
||||
created.
|
||||
|
||||
When set to ``ON``, importable Swift targets built by :ref:`Ninja Generators`
|
||||
produce the ``.swiftmodule`` from a separate ``-emit-module`` build edge,
|
||||
allowing downstream Swift targets to compile in parallel with upstream
|
||||
object compilation.
|
||||
|
||||
If this variable is not set, separate module emission is enabled by default
|
||||
in targets that do not set :prop_tgt:`Swift_SEPARATE_MODULE_EMISSION`.
|
||||
See policy :policy:`CMP0215`.
|
||||
|
||||
.. 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.
|
||||
@@ -124,6 +124,10 @@ if(CMAKE_Swift_COMPILATION_MODE_DEFAULT)
|
||||
set(CMAKE_Swift_COMPILE_OBJECT "<CMAKE_Swift_COMPILER> ${CMAKE_Swift_PARALLEL_FLAGS} -c <DEFINES> <FLAGS> <INCLUDES> <SOURCE>")
|
||||
endif()
|
||||
|
||||
if(NOT CMAKE_Swift_EMIT_MODULE)
|
||||
set(CMAKE_Swift_EMIT_MODULE "<CMAKE_Swift_COMPILER> ${CMAKE_Swift_PARALLEL_FLAGS} -emit-module <DEFINES> <FLAGS> <INCLUDES> <SOURCE>")
|
||||
endif()
|
||||
|
||||
if(NOT CMAKE_Swift_CREATE_SHARED_LIBRARY)
|
||||
set(CMAKE_Swift_CREATE_SHARED_LIBRARY "<CMAKE_Swift_COMPILER> ${CMAKE_Swift_PARALLEL_FLAGS} -emit-library <LANGUAGE_COMPILE_FLAGS> <LINK_FLAGS> ${CMAKE_Swift_IMPLIB_LINKER_FLAGS} <SONAME_FLAG> <TARGET_INSTALLNAME_DIR><TARGET_SONAME> -o <TARGET> <OBJECTS> <LINK_LIBRARIES>")
|
||||
endif()
|
||||
|
||||
@@ -1639,10 +1639,11 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement(
|
||||
if (cmComputeLinkInformation* cli =
|
||||
this->GeneratorTarget->GetLinkInformation(config)) {
|
||||
for (auto const& dependency : cli->GetItems()) {
|
||||
// Both the current target and the linked target must be swift targets
|
||||
// in order for there to be a swiftmodule to depend on
|
||||
// Only depend on swiftmodule from targets that actually compile
|
||||
// Swift sources. A C/C++ target may have Swift as its linker
|
||||
// language (due to language propagation) without producing one.
|
||||
if (dependency.Target &&
|
||||
dependency.Target->GetLinkerLanguage(config) == "Swift") {
|
||||
dependency.Target->IsLanguageUsed("Swift", config)) {
|
||||
std::string swiftmodule = this->ConvertToNinjaPath(
|
||||
dependency.Target->GetSwiftModulePath(config));
|
||||
linkBuild.ImplicitDeps.emplace_back(swiftmodule);
|
||||
|
||||
@@ -130,6 +130,15 @@ std::string cmNinjaTargetGenerator::LanguageCompilerRule(
|
||||
withScanning == WithScanning::Yes ? "_scanned_" : "_unscanned_", config);
|
||||
}
|
||||
|
||||
std::string cmNinjaTargetGenerator::LanguageEmitModuleRule(
|
||||
std::string const& lang, std::string const& config) const
|
||||
{
|
||||
return cmStrCat(
|
||||
lang, "_EMIT_MODULE__",
|
||||
cmGlobalNinjaGenerator::EncodeRuleName(this->GeneratorTarget->GetName()),
|
||||
'_', config);
|
||||
}
|
||||
|
||||
std::string cmNinjaTargetGenerator::LanguagePreprocessAndScanRule(
|
||||
std::string const& lang, std::string const& config) const
|
||||
{
|
||||
@@ -1033,6 +1042,40 @@ void cmNinjaTargetGenerator::WriteCompileRule(std::string const& lang,
|
||||
rule.Comment = cmStrCat("Rule for compiling ", lang, " files.");
|
||||
rule.Description = cmStrCat("Building ", lang, " object $out");
|
||||
this->GetGlobalGenerator()->AddRule(rule);
|
||||
|
||||
// Write a separate emit-module rule for Swift (produces .swiftmodule
|
||||
// without compile outputs, enabling downstream modules to compile in
|
||||
// parallel with upstream compilation).
|
||||
if (lang == "Swift" && withScanning == WithScanning::No) {
|
||||
std::string const emitModCmdVar = "CMAKE_Swift_EMIT_MODULE";
|
||||
cmValue emitModCmdVal = mf->GetDefinition(emitModCmdVar);
|
||||
if (emitModCmdVal) {
|
||||
cmNinjaRule emitModRule(this->LanguageEmitModuleRule(lang, config));
|
||||
cmRulePlaceholderExpander::RuleVariables emVars = vars;
|
||||
std::string emFlags = "$FLAGS";
|
||||
if (!responseFlag.empty()) {
|
||||
// Reset placeholders after compile response-file setup.
|
||||
emVars.Source = "$in";
|
||||
emVars.Object = "$out";
|
||||
emVars.Defines = "$DEFINES";
|
||||
emVars.Includes = "$INCLUDES";
|
||||
SetupResponseFile(emitModRule, emVars, emFlags, lang, responseFlag);
|
||||
}
|
||||
|
||||
emVars.Flags = emFlags.c_str();
|
||||
emitModRule.Restat = "1";
|
||||
|
||||
cmList emitModCmds = ExpandRuleCommands(
|
||||
*emitModCmdVal, emVars, mf, lang, launcher, this->GetLocalGenerator(),
|
||||
rulePlaceholderExpander.get());
|
||||
emitModRule.Command = this->GetLocalGenerator()->BuildCommandLine(
|
||||
emitModCmds, config, config);
|
||||
emitModRule.Comment = "Rule for emitting Swift .swiftmodule files.";
|
||||
emitModRule.Description =
|
||||
cmStrCat("Emitting Swift .swiftmodule ", "$out");
|
||||
this->GetGlobalGenerator()->AddRule(emitModRule);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cmNinjaTargetGenerator::WriteObjectBuildStatements(
|
||||
@@ -2033,7 +2076,8 @@ void cmNinjaTargetGenerator::WriteSwiftObjectBuildStatement(
|
||||
// - Definitions
|
||||
// - Include paths
|
||||
// - (single-output) output object filename
|
||||
// - Swiftmodule
|
||||
// - Swiftmodule (for importable targets), produced either by the compile
|
||||
// edge or by a separate emit-module edge
|
||||
//
|
||||
// Per-File:
|
||||
// - compile-command
|
||||
@@ -2095,18 +2139,6 @@ void cmNinjaTargetGenerator::WriteSwiftObjectBuildStatement(
|
||||
return !isMultiThread && compileMode == cmSwiftCompileMode::Wholemodule;
|
||||
}();
|
||||
|
||||
// Without `-emit-library` or `-emit-executable`, targets with a single
|
||||
// source file parse as a Swift script instead of like normal source. For
|
||||
// non-executable targets, append this to ensure that they are parsed like a
|
||||
// normal source.
|
||||
if (target.GetType() != cmStateEnums::EXECUTABLE) {
|
||||
this->LocalGenerator->AppendFlags(vars["FLAGS"], "-parse-as-library");
|
||||
}
|
||||
|
||||
if (target.GetType() == cmStateEnums::STATIC_LIBRARY) {
|
||||
this->LocalGenerator->AppendFlags(vars["FLAGS"], "-static");
|
||||
}
|
||||
|
||||
// Does this swift target emit a module file for importing into other
|
||||
// targets?
|
||||
auto isImportableTarget = [](cmGeneratorTarget const& tgt) -> bool {
|
||||
@@ -2117,7 +2149,34 @@ void cmNinjaTargetGenerator::WriteSwiftObjectBuildStatement(
|
||||
}
|
||||
return true;
|
||||
};
|
||||
bool const targetIsImportable = isImportableTarget(target);
|
||||
|
||||
// Check if we can emit the module separately (produces .swiftmodule before
|
||||
// compilation finishes, enabling downstream modules to compile in parallel).
|
||||
bool const emitModuleSeparately = [&]() -> bool {
|
||||
if (!targetIsImportable ||
|
||||
!this->GetMakefile()->GetDefinition("CMAKE_Swift_EMIT_MODULE")) {
|
||||
return false;
|
||||
}
|
||||
cmValue prop =
|
||||
this->GeneratorTarget->GetProperty("Swift_SEPARATE_MODULE_EMISSION");
|
||||
if (prop) {
|
||||
return prop.IsOn();
|
||||
}
|
||||
return this->GeneratorTarget->GetPolicyStatusCMP0215() == cmPolicies::NEW;
|
||||
}();
|
||||
|
||||
// Build flags common to both compile and emit-module edges.
|
||||
if (target.GetType() != cmStateEnums::EXECUTABLE) {
|
||||
// Without `-emit-library` or `-emit-executable`, targets with a single
|
||||
// source file parse as a Swift script instead of like normal source. For
|
||||
// non-executable targets, append this to ensure that they are parsed like
|
||||
// a normal source.
|
||||
this->LocalGenerator->AppendFlags(vars["FLAGS"], "-parse-as-library");
|
||||
}
|
||||
if (target.GetType() == cmStateEnums::STATIC_LIBRARY) {
|
||||
this->LocalGenerator->AppendFlags(vars["FLAGS"], "-static");
|
||||
}
|
||||
this->LocalGenerator->AppendFlags(vars["FLAGS"],
|
||||
cmStrCat("-module-name ", moduleName));
|
||||
|
||||
@@ -2128,23 +2187,8 @@ void cmNinjaTargetGenerator::WriteSwiftObjectBuildStatement(
|
||||
this->LocalGenerator->AppendFlags(
|
||||
vars["FLAGS"], cmStrCat(libraryLinkNameFlag, ' ', libraryLinkName));
|
||||
}
|
||||
|
||||
this->LocalGenerator->AppendFlags(vars["FLAGS"],
|
||||
this->GetFlags(language, config));
|
||||
|
||||
// Swift modules only make sense to emit from things that can be imported.
|
||||
// Executables that don't export symbols can't be imported, so don't try to
|
||||
// emit a swiftmodule for them. It will break.
|
||||
if (isImportableTarget(target)) {
|
||||
std::string const emitModuleFlag = "-emit-module";
|
||||
std::string const modulePathFlag = "-emit-module-path";
|
||||
this->LocalGenerator->AppendFlags(
|
||||
vars["FLAGS"],
|
||||
{ emitModuleFlag, modulePathFlag,
|
||||
this->LocalGenerator->ConvertToOutputFormat(
|
||||
moduleFilepath, cmOutputConverter::SHELL) });
|
||||
objBuild.Outputs.push_back(moduleFilepath);
|
||||
}
|
||||
vars["DEFINES"] = this->GetDefines(language, config);
|
||||
vars["INCLUDES"] = this->GetIncludes(language, config);
|
||||
vars["CONFIG"] = config;
|
||||
@@ -2155,9 +2199,14 @@ 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, only the .swiftmodule output
|
||||
// moves to the separate emit-module edge.
|
||||
if (targetIsImportable && !emitModuleSeparately) {
|
||||
objBuild.Outputs.push_back(moduleFilepath);
|
||||
}
|
||||
|
||||
if (isSingleOutput) {
|
||||
this->LocalGenerator->AppendFlags(vars["FLAGS"],
|
||||
cmStrCat("-o ", targetObjectFilename));
|
||||
objBuild.Outputs.push_back(targetObjectFilename);
|
||||
this->Configs[config].Objects.push_back(targetObjectFilename);
|
||||
}
|
||||
@@ -2184,6 +2233,25 @@ void cmNinjaTargetGenerator::WriteSwiftObjectBuildStatement(
|
||||
this->GenerateSwiftOutputFileMap(config, vars["FLAGS"]);
|
||||
}
|
||||
|
||||
// Save common flags for the emit-module edge before adding
|
||||
// compile-specific flags (-emit-module, -emit-module-path, -o).
|
||||
std::string const commonFlags = vars["FLAGS"];
|
||||
|
||||
std::string const moduleOutputPath =
|
||||
this->LocalGenerator->ConvertToOutputFormat(moduleFilepath,
|
||||
cmOutputConverter::SHELL);
|
||||
if (targetIsImportable) {
|
||||
std::string const emitModuleFlag = "-emit-module";
|
||||
std::string const modulePathFlag = "-emit-module-path";
|
||||
this->LocalGenerator->AppendFlags(
|
||||
vars["FLAGS"], { emitModuleFlag, modulePathFlag, moduleOutputPath });
|
||||
}
|
||||
|
||||
if (isSingleOutput) {
|
||||
this->LocalGenerator->AppendFlags(vars["FLAGS"],
|
||||
cmStrCat("-o ", targetObjectFilename));
|
||||
}
|
||||
|
||||
if (firstForConfig) {
|
||||
this->ExportSwiftObjectCompileCommand(
|
||||
sources, targetObjectFilename, vars["FLAGS"], vars["DEFINES"],
|
||||
@@ -2211,6 +2279,34 @@ void cmNinjaTargetGenerator::WriteSwiftObjectBuildStatement(
|
||||
this->GetGlobalGenerator()->WriteBuild(this->GetImplFileStream(fileConfig),
|
||||
objBuild,
|
||||
this->ForceResponseFile() ? -1 : 0);
|
||||
|
||||
// Write a separate emit-module build edge that produces .swiftmodule
|
||||
// without compile outputs. This allows downstream Swift targets to start
|
||||
// compiling as soon as the module interface is ready, overlapping with
|
||||
// upstream compilation and linking.
|
||||
if (emitModuleSeparately) {
|
||||
cmNinjaBuild modBuild = objBuild;
|
||||
modBuild.Rule = this->LanguageEmitModuleRule(language, config);
|
||||
|
||||
// Start from common flags (shared with compile edge) and add
|
||||
// emit-module-specific flags. The emit-module rule template already
|
||||
// contains -emit-module, so we only need -emit-module-path here.
|
||||
modBuild.Variables["FLAGS"] = commonFlags;
|
||||
this->LocalGenerator->AppendFlags(
|
||||
modBuild.Variables["FLAGS"],
|
||||
cmStrCat("-emit-module-path ", moduleOutputPath));
|
||||
|
||||
modBuild.RspFile = cmStrCat(moduleFilepath, ".rsp");
|
||||
|
||||
// Output is just the .swiftmodule
|
||||
this->EnsureParentDirectoryExists(moduleFilepath);
|
||||
modBuild.Outputs.clear();
|
||||
modBuild.Outputs.push_back(moduleFilepath);
|
||||
|
||||
this->GetGlobalGenerator()->WriteBuild(this->GetImplFileStream(fileConfig),
|
||||
modBuild,
|
||||
this->ForceResponseFile() ? -1 : 0);
|
||||
}
|
||||
}
|
||||
|
||||
void cmNinjaTargetGenerator::WriteTargetDependInfo(std::string const& lang,
|
||||
|
||||
@@ -78,6 +78,8 @@ protected:
|
||||
std::string LanguageCompilerRule(std::string const& lang,
|
||||
std::string const& config,
|
||||
WithScanning withScanning) const;
|
||||
std::string LanguageEmitModuleRule(std::string const& lang,
|
||||
std::string const& config) const;
|
||||
std::string LanguagePreprocessAndScanRule(std::string const& lang,
|
||||
std::string const& config) const;
|
||||
std::string LanguageScanRule(std::string const& lang,
|
||||
|
||||
+6
-2
@@ -642,7 +642,10 @@ class cmMakefile;
|
||||
4, 4, 0, WARN) \
|
||||
SELECT(POLICY, CMP0214, \
|
||||
"Honor CMAKE_EXE_LINKER_FLAGS for Swift executable targets.", 4, 4, \
|
||||
0, WARN)
|
||||
0, WARN) \
|
||||
SELECT(POLICY, CMP0215, \
|
||||
"Ninja generators emit Swift modules separately from compilation.", \
|
||||
4, 4, 0, WARN)
|
||||
|
||||
#define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1)
|
||||
#define CM_FOR_EACH_POLICY_ID(POLICY) \
|
||||
@@ -699,7 +702,8 @@ class cmMakefile;
|
||||
F(CMP0209) \
|
||||
F(CMP0210) \
|
||||
F(CMP0211) \
|
||||
F(CMP0214)
|
||||
F(CMP0214) \
|
||||
F(CMP0215)
|
||||
|
||||
#define CM_FOR_EACH_CUSTOM_COMMAND_POLICY(F) \
|
||||
F(CMP0116) \
|
||||
|
||||
@@ -381,6 +381,7 @@ TargetProperty const StaticTargetProperties[] = {
|
||||
{ "Swift_LANGUAGE_VERSION"_s, IC::CanCompileSources },
|
||||
{ "Swift_MODULE_DIRECTORY"_s, IC::CanCompileSources },
|
||||
{ "Swift_COMPILATION_MODE"_s, IC::CanCompileSources },
|
||||
{ "Swift_SEPARATE_MODULE_EMISSION"_s, IC::CanCompileSources },
|
||||
// ---- Rust
|
||||
{ "Rust_EDITION"_s, IC::CanCompileSources },
|
||||
{ "Rust_MAIN_CRATE_ROOT"_s, IC::CanCompileSources },
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
string(
|
||||
REGEX MATCHALL
|
||||
"swiftc(\\.exe)?\"? [^\n]* -emit-module-path [^\n]*L\\.swiftmodule"
|
||||
swift_module_commands "${actual_stdout}")
|
||||
list(LENGTH swift_module_commands swift_module_command_count)
|
||||
if(swift_module_command_count LESS 2)
|
||||
string(APPEND RunCMake_TEST_FAILED
|
||||
"Expected separate compile and emit-module commands for L, found ${swift_module_command_count} command(s) with '-emit-module-path ... L.swiftmodule'.\n")
|
||||
endif()
|
||||
@@ -0,0 +1,12 @@
|
||||
cmake_policy(SET CMP0157 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)
|
||||
@@ -0,0 +1,11 @@
|
||||
if(NOT actual_stdout MATCHES
|
||||
"swiftc(\\.exe)?\"? [^\n]* -c @CMakeFiles(/|\\\\)L\\.dir(/|\\\\)(Debug(/|\\\\))?L\\.o(bj)?\\.swift\\.rsp")
|
||||
string(APPEND RunCMake_TEST_FAILED
|
||||
"No Swift compile response-file command found for target L.\n")
|
||||
endif()
|
||||
|
||||
if(NOT actual_stdout MATCHES
|
||||
"swiftc(\\.exe)?\"? [^\n]* -emit-module @.*L\\.swiftmodule\\.rsp")
|
||||
string(APPEND RunCMake_TEST_FAILED
|
||||
"No Swift emit-module response-file command found for target L.\n")
|
||||
endif()
|
||||
@@ -0,0 +1,14 @@
|
||||
cmake_policy(SET CMP0157 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()
|
||||
|
||||
set(CMAKE_NINJA_FORCE_RESPONSE_FILE TRUE)
|
||||
|
||||
enable_language(Swift)
|
||||
|
||||
add_library(L STATIC L.swift)
|
||||
add_library(LClient STATIC LClient.swift)
|
||||
target_link_libraries(LClient PRIVATE L)
|
||||
@@ -0,0 +1,2 @@
|
||||
import L
|
||||
public func consume() -> Int { return ThirtyTwo }
|
||||
@@ -146,6 +146,22 @@ if(RunCMake_GENERATOR MATCHES "Ninja")
|
||||
run_cmake_command(ForceResponseFile-check ${CMAKE_COMMAND} --build . -- -vn)
|
||||
endblock()
|
||||
|
||||
block()
|
||||
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/EmitModuleSeparately-build)
|
||||
run_cmake(EmitModuleSeparately)
|
||||
set(RunCMake_TEST_NO_CLEAN 1)
|
||||
# -v: verbose to capture executed commands -n: dry-run to avoid actually compiling
|
||||
run_cmake_command(EmitModuleSeparately-build ${CMAKE_COMMAND} --build . -- -vn)
|
||||
endblock()
|
||||
|
||||
block()
|
||||
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/EmitModuleSeparatelyResponseFile-build)
|
||||
run_cmake(EmitModuleSeparatelyResponseFile)
|
||||
set(RunCMake_TEST_NO_CLEAN 1)
|
||||
# -v: verbose to capture executed commands -n: dry-run to avoid actually compiling
|
||||
run_cmake_command(EmitModuleSeparatelyResponseFile-build ${CMAKE_COMMAND} --build . -- -vn)
|
||||
endblock()
|
||||
|
||||
block()
|
||||
if(CMAKE_SYSTEM_NAME MATCHES Windows)
|
||||
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/ImportLibraryFlags-build)
|
||||
|
||||
@@ -56,6 +56,7 @@
|
||||
\* CMP0210
|
||||
\* CMP0211
|
||||
\* CMP0214
|
||||
\* CMP0215
|
||||
|
||||
Call Stack \(most recent call first\):
|
||||
CMakeLists\.txt:3 \(include\)
|
||||
|
||||
Reference in New Issue
Block a user