Swift: Refactor module / object builds

Splitting up the computation of common variables, module build
variables, and object build variables to make it a little easier to
focus on each one.

Updated tests to reflect updated flag order and updated object-build
description.
This commit is contained in:
Evan Wilde
2026-08-14 17:02:20 -07:00
parent 03f6a7f440
commit 23b33482f1
9 changed files with 269 additions and 229 deletions
+1 -5
View File
@@ -163,11 +163,7 @@ if(CMAKE_Swift_COMPILATION_MODE_DEFAULT)
# Omit the object output. The output is controlled by the output-file-map
# for normal builds. For wholemodule builds, CMake appends the appropriate
# flags.
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>")
set(CMAKE_Swift_COMPILE_OBJECT "<CMAKE_Swift_COMPILER> ${CMAKE_Swift_PARALLEL_FLAGS} <DEFINES> <FLAGS> <INCLUDES> <SOURCE>")
endif()
if(NOT CMAKE_Swift_CREATE_SHARED_LIBRARY)
+211 -204
View File
@@ -131,15 +131,6 @@ 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
{
@@ -1054,40 +1045,6 @@ 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, cldeps,
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(
@@ -2150,39 +2107,18 @@ void cmNinjaTargetGenerator::WriteSwiftObjectBuildStatement(
}
std::string const language = "Swift";
cmGeneratorTarget const& target = *this->GeneratorTarget;
std::string const moduleName = target.GetSwiftModuleName();
std::string const moduleFilePath =
this->ConvertToNinjaPath(target.GetSwiftModulePath(config));
std::string const objectDir = this->ConvertToNinjaPath(
cmStrCat(this->GeneratorTarget->GetSupportDirectory(),
this->GetGlobalGenerator()->ConfigDirectory(config)));
cmGeneratorTarget const& target = *this->GeneratorTarget;
cmNinjaBuild objBuild(
this->LanguageCompilerRule(language, config, WithScanning::No));
cmNinjaVars& vars = objBuild.Variables;
// The swift toolchain leaves outputs untouched if there are no meaningful
// changes to input files (e.g. addition of a comment).
vars.emplace("restat", "1");
std::string const moduleName = target.GetSwiftModuleName();
std::string const moduleFilepath =
this->ConvertToNinjaPath(target.GetSwiftModulePath(config));
vars.emplace("description",
cmStrCat("Building Swift Module '", moduleName, "' with ",
sources.size(),
sources.size() == 1 ? " source" : " sources"));
bool const isSingleOutput = [this, compileMode]() -> bool {
bool isMultiThread = false;
if (cmValue numThreadStr =
this->GetMakefile()->GetDefinition("CMAKE_Swift_NUM_THREADS")) {
unsigned long numThreads;
cmStrToULong(*numThreadStr, &numThreads);
// numThreads == 1 is multi-threaded according to swiftc
isMultiThread = numThreads > 0;
}
return !isMultiThread && compileMode == cmSwiftCompileMode::Wholemodule;
}();
std::string const moduleObjectFilename = this->ConvertToNinjaPath(cmStrCat(
objectDir, '/', moduleName,
this->GetGlobalGenerator()->GetLanguageOutputExtension(language)));
// Does this swift target emit a module file for importing into other
// targets?
@@ -2196,13 +2132,20 @@ void cmNinjaTargetGenerator::WriteSwiftObjectBuildStatement(
};
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;
// num-threads 0 && wmo -> one object file for the entire module
bool const isSingleOutput = [this, compileMode]() -> bool {
bool isMultiThread = false;
if (cmValue numThreadStr =
this->GetMakefile()->GetDefinition("CMAKE_Swift_NUM_THREADS")) {
unsigned long numThreads;
cmStrToULong(*numThreadStr, &numThreads);
// numThreads == 1 is multi-threaded according to swiftc
isMultiThread = numThreads > 0;
}
return !isMultiThread && compileMode == cmSwiftCompileMode::Wholemodule;
}();
bool const emitModuleSeparately = [&]() -> bool {
cmValue prop =
this->GeneratorTarget->GetProperty("Swift_SEPARATE_MODULE_EMISSION");
if (prop) {
@@ -2211,154 +2154,218 @@ void cmNinjaTargetGenerator::WriteSwiftObjectBuildStatement(
return this->GeneratorTarget->GetPolicyStatusCMP0215() == cmPolicies::NEW;
}();
// Build flags common to both compile and emit-module edges.
if (target.GetType() != cm::TargetType::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() == cm::TargetType::STATIC_LIBRARY) {
this->LocalGenerator->AppendFlags(vars["FLAGS"], "-static");
}
this->LocalGenerator->AppendFlags(vars["FLAGS"],
cmStrCat("-module-name ", moduleName));
// 1. Common:
// Variables:
// - Flags:
// - module-name
// - module-link-name
// - parse as library
// - Swift_FLAGS
// - output-file-map
// - Defines (all)
// - Include directories (all)
// - restat: 1
// Source List
//
// 2. Module Build Specific:
// Variables:
// - Flags
// - emit-module-path
// - module build description
// - Module response file
// - Module Outputs
//
// 3. Object Build Specific:
// Variables:
// - Flags:
// - -o
// - -c
// - Object response file
// - Object Outputs
if (target.GetType() != cm::TargetType::EXECUTABLE) {
std::string const libraryLinkNameFlag = "-module-link-name";
std::string const libraryLinkName =
this->GetGeneratorTarget()->GetLibraryNames(config).Base;
this->LocalGenerator->AppendFlags(
vars["FLAGS"], cmStrCat(libraryLinkNameFlag, ' ', libraryLinkName));
}
this->LocalGenerator->AppendFlags(vars["FLAGS"],
this->GetFlags(language, config));
vars["DEFINES"] = this->GetDefines(language, config);
vars["INCLUDES"] = this->GetIncludes(language, config);
vars["CONFIG"] = config;
//
//// Common variables
//
cmNinjaVars commonVariables;
cmNinjaDeps commonExplicitDeps;
cmNinjaDeps objectOutputs;
{
this->LocalGenerator->AppendFlags(commonVariables["FLAGS"],
cmStrCat("-module-name ", moduleName));
// target-level object filename
std::string const targetObjectFilename = this->ConvertToNinjaPath(cmStrCat(
objectDir, '/', moduleName,
this->GetGlobalGenerator()->GetLanguageOutputExtension(language)));
objBuild.RspFile = cmStrCat(targetObjectFilename, ".swift.rsp");
if (target.GetType() != cm::TargetType::EXECUTABLE) {
std::string const libraryLinkNameFlag = "-module-link-name ";
std::string const libraryLinkName =
this->GetGeneratorTarget()->GetLibraryNames(config).Base;
if (targetIsImportable) {
this->Configs[config].SwiftModuleOutput = moduleFilepath;
}
if (targetIsImportable && !emitModuleSeparately) {
objBuild.Outputs.push_back(moduleFilepath);
}
this->LocalGenerator->AppendFlags(
commonVariables["FLAGS"],
cmStrCat(libraryLinkNameFlag, libraryLinkName));
this->LocalGenerator->AppendFlags(commonVariables["FLAGS"],
"-parse-as-library");
}
if (target.GetType() == cm::TargetType::STATIC_LIBRARY) {
this->LocalGenerator->AppendFlags(commonVariables["FLAGS"], "-static");
}
if (isSingleOutput) {
objBuild.Outputs.push_back(targetObjectFilename);
this->Configs[config].Objects.push_back(targetObjectFilename);
}
this->LocalGenerator->AppendFlags(commonVariables["FLAGS"],
this->GetFlags(language, config));
commonVariables.emplace("DEFINES", this->GetDefines(language, config));
commonVariables.emplace("INCLUDES", this->GetIncludes(language, config));
commonVariables.emplace("CONFIG", config);
commonVariables.emplace("restat", "1");
for (cmSourceFile const* sf : sources) {
// Add dependency to object build on each source file
std::string const sourceFilePath = this->GetCompiledSourceNinjaPath(sf);
objBuild.ExplicitDeps.push_back(sourceFilePath);
for (cmSourceFile const* sf : sources) {
std::string const sourceFilePath = this->GetCompiledSourceNinjaPath(sf);
commonExplicitDeps.push_back(sourceFilePath);
if (!isSingleOutput) {
// Object outputs
std::string const objectFilepath =
this->ConvertToNinjaPath(this->GetObjectFilePath(sf, config));
this->EnsureParentDirectoryExists(objectFilepath);
objBuild.Outputs.push_back(objectFilepath);
this->Configs[config].Objects.push_back(objectFilepath);
if (!isSingleOutput) {
std::string const objectFilePath =
this->ConvertToNinjaPath(this->GetObjectFilePath(sf, config));
this->EnsureParentDirectoryExists(objectFilePath);
objectOutputs.push_back(objectFilePath);
this->Configs[config].Objects.push_back(objectFilePath);
// Add OFM data
this->EmitSwiftDependencyInfo(sf, config);
this->EmitSwiftDependencyInfo(sf, config);
}
}
if (isSingleOutput) {
objectOutputs.push_back(moduleObjectFilename);
this->Configs[config].Objects.push_back(moduleObjectFilename);
} else {
this->GenerateSwiftOutputFileMap(config, commonVariables["FLAGS"]);
}
}
if (!isSingleOutput) {
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 && !emitModuleSeparately) {
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"],
vars["INCLUDES"], config, isSingleOutput);
}
for (cmTargetDepend const& dep :
this->GetGlobalGenerator()->GetTargetDirectDepends(&target)) {
if (!dep->IsLanguageUsed("Swift", config)) {
continue;
//
//// Module build
//
cmNinjaVars moduleVariables;
cmNinjaDeps moduleOutputs;
cmNinjaDeps importedModuleDeps;
{
for (cmTargetDepend const& dep :
this->GetGlobalGenerator()->GetTargetDirectDepends(&target)) {
if (!dep->IsLanguageUsed("Swift", config)) {
continue;
}
// If the dependency emits a swiftmodule, add a dependency edge on that
// swiftmodule to the ninja build graph.
if (isImportableTarget(*dep)) {
std::string const depModuleFilepath =
this->ConvertToNinjaPath(dep->GetSwiftModulePath(config));
importedModuleDeps.push_back(depModuleFilepath);
}
}
// If the dependency emits a swiftmodule, add a dependency edge on that
// swiftmodule to the ninja build graph.
if (isImportableTarget(*dep)) {
std::string const depModuleFilepath =
this->ConvertToNinjaPath(dep->GetSwiftModulePath(config));
objBuild.ImplicitDeps.push_back(depModuleFilepath);
if (targetIsImportable) {
this->LocalGenerator->AppendFlags(moduleVariables["FLAGS"],
"-emit-module");
this->Configs[config].SwiftModuleOutput = moduleFilePath;
std::string const moduleOutputPath =
this->LocalGenerator->ConvertToOutputFormat(moduleFilePath,
cmOutputConverter::SHELL);
this->LocalGenerator->AppendFlags(
moduleVariables["FLAGS"],
cmStrCat("-emit-module-path ", moduleOutputPath));
this->EnsureParentDirectoryExists(moduleFilePath);
moduleOutputs.push_back(moduleFilePath);
if (emitModuleSeparately) {
cmNinjaBuild moduleBuild(
this->LanguageCompilerRule(language, config, WithScanning::No));
moduleBuild.Variables = moduleVariables;
this->LocalGenerator->AppendFlags(moduleBuild.Variables["FLAGS"],
commonVariables["FLAGS"]);
this->LocalGenerator->AppendFlags(moduleBuild.Variables["DEFINES"],
commonVariables["DEFINES"]);
this->LocalGenerator->AppendFlags(moduleBuild.Variables["INCLUDES"],
commonVariables["INCLUDES"]);
moduleBuild.Variables.insert(commonVariables.begin(),
commonVariables.end());
moduleBuild.ExplicitDeps = commonExplicitDeps;
moduleBuild.ImplicitDeps = importedModuleDeps;
moduleBuild.Variables.emplace(
"description",
cmStrCat("Building Swift Module '", moduleName, "' with ",
sources.size(),
sources.size() == 1 ? " source" : " sources"));
moduleBuild.Outputs = moduleOutputs;
moduleBuild.RspFile = cmStrCat(moduleFilePath, ".rsp");
moduleBuild.OrderOnlyDeps.push_back(
this->OrderDependsTargetForTarget(config));
this->GetGlobalGenerator()->WriteBuild(
this->GetImplFileStream(fileConfig), moduleBuild,
this->ForceResponseFile() ? -1 : 0);
}
}
}
objBuild.OrderOnlyDeps.push_back(this->OrderDependsTargetForTarget(config));
//
//// Object build
//
{
cmNinjaBuild objectBuild(
this->LanguageCompilerRule(language, config, WithScanning::No));
cmNinjaVars& objectVariables = objectBuild.Variables;
// 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);
this->LocalGenerator->AppendFlags(objectVariables["FLAGS"], "-c");
if (isSingleOutput) {
this->LocalGenerator->AppendFlags(objectVariables["FLAGS"],
cmStrCat("-o ", moduleObjectFilename));
}
// 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.
// Skip if the flags already contain one (e.g. a directory-style path
// set by the target's compile options).
modBuild.Variables["FLAGS"] = commonFlags;
this->LocalGenerator->AppendFlags(
modBuild.Variables["FLAGS"],
cmStrCat("-emit-module-path ", moduleOutputPath));
this->LocalGenerator->AppendFlags(objectBuild.Variables["FLAGS"],
commonVariables["FLAGS"]);
this->LocalGenerator->AppendFlags(objectBuild.Variables["DEFINES"],
commonVariables["DEFINES"]);
this->LocalGenerator->AppendFlags(objectBuild.Variables["INCLUDES"],
commonVariables["INCLUDES"]);
objectBuild.Variables.insert(commonVariables.begin(),
commonVariables.end());
objectVariables.emplace(
"description",
cmStrCat("Building Swift Module '", moduleName, "' objects with ",
sources.size(), sources.size() == 1 ? " source" : " sources"));
objectBuild.ExplicitDeps = commonExplicitDeps;
objectBuild.ImplicitDeps = importedModuleDeps;
objectBuild.Outputs = objectOutputs;
objectBuild.RspFile = cmStrCat(moduleObjectFilename, ".swift.rsp");
objectBuild.OrderOnlyDeps.push_back(
this->OrderDependsTargetForTarget(config));
modBuild.RspFile = cmStrCat(moduleFilepath, ".rsp");
if (emitModuleSeparately && targetIsImportable) {
// Both edges share the same -output-file-map; serialize the compile
// edge after emit-module so they do not race on the module .swiftdeps.
objectBuild.OrderOnlyDeps.push_back(moduleFilePath);
} else {
this->LocalGenerator->AppendFlags(objectBuild.Variables["FLAGS"],
moduleVariables["FLAGS"]);
objectBuild.Outputs.insert(objectBuild.Outputs.end(),
moduleOutputs.begin(), moduleOutputs.end());
}
// Output is just the .swiftmodule
this->EnsureParentDirectoryExists(moduleFilepath);
modBuild.Outputs.clear();
modBuild.Outputs.push_back(moduleFilepath);
if (firstForConfig) {
this->ExportSwiftObjectCompileCommand(
sources, moduleObjectFilename,
cmStrCat(commonVariables["FLAGS"], ' ', moduleVariables["FLAGS"], ' ',
objectVariables["FLAGS"]),
cmStrCat(commonVariables["DEFINES"], ' ', moduleVariables["DEFINES"],
' ', objectVariables["DEFINES"]),
cmStrCat(commonVariables["INCLUDES"], ' ', moduleVariables["INCLUDES"],
' ', objectVariables["INCLUDES"]),
config, isSingleOutput);
}
this->GetGlobalGenerator()->WriteBuild(this->GetImplFileStream(fileConfig),
modBuild,
objectBuild,
this->ForceResponseFile() ? -1 : 0);
// Both edges share the same -output-file-map; serialize the compile
// edge after emit-module so they do not race on the module .swiftdeps.
objBuild.OrderOnlyDeps.push_back(moduleFilepath);
}
// Write object build
this->GetGlobalGenerator()->WriteBuild(this->GetImplFileStream(fileConfig),
objBuild,
this->ForceResponseFile() ? -1 : 0);
}
void cmNinjaTargetGenerator::WriteTargetDependInfo(std::string const& lang,
-2
View File
@@ -78,8 +78,6 @@ 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,
@@ -5,13 +5,52 @@ if(EXISTS "${RunCMake_TEST_BINARY_DIR}/no-swift-module-triple")
endif()
if(NOT actual_stdout MATCHES
"swiftc(\\.exe)?\"? [^\n]* -c @CMakeFiles(/|\\\\)L\\.dir(/|\\\\)(Debug(/|\\\\))?L\\.o(bj)?\\.swift\\.rsp")
"swiftc(\\.exe)?\"? [^\n]* @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(/|\\\\)[-_a-zA-Z0-9]+\\.swiftmodule\\.rsp")
"swiftc(\\.exe)?\"? [^\n]* @[^\n]*L\\.swiftmodule(/|\\\\)[^\n]*\\.swiftmodule\\.rsp")
string(APPEND RunCMake_TEST_FAILED
"No Swift emit-module response-file command found for target L.\n")
endif()
# Response files are written by ninja at build time.
# Inspect the build.ninja file instead.
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)
# The emit-module edge for L: RSP_FILE set and -emit-module in its FLAGS.
string(REGEX MATCH
"build [^\n]*L\\.swiftmodule(/|\\\\)[^\n:]*\\.swiftmodule:[^\n]*(\n [^\n]+)*"
module_edge "${build_ninja}")
if(NOT module_edge)
string(APPEND RunCMake_TEST_FAILED
"Could not find emit-module edge for L.\n")
elseif(NOT module_edge MATCHES "\n FLAGS = [^\n]* ?-emit-module ")
string(APPEND RunCMake_TEST_FAILED
"Emit-module edge for L is missing -emit-module in FLAGS.\nEdge:\n${module_edge}\n")
elseif(NOT module_edge MATCHES "\n RSP_FILE = [^\n]*L\\.swiftmodule(/|\\\\)[^\n]*\\.swiftmodule\\.rsp")
string(APPEND RunCMake_TEST_FAILED
"Emit-module edge for L is missing a response file.\nEdge:\n${module_edge}\n")
endif()
# The object compile edge for L: RSP_FILE set and -c in its FLAGS.
string(REGEX MATCH
"build [^\n]*L\\.swift\\.o(bj)?:[^\n]*(\n [^\n]+)*"
object_edge "${build_ninja}")
if(NOT object_edge)
string(APPEND RunCMake_TEST_FAILED
"Could not find object compile edge for L.swift.\n")
elseif(NOT object_edge MATCHES "\n FLAGS = [^\n]* ?-c ")
string(APPEND RunCMake_TEST_FAILED
"Object compile edge for L.swift is missing -c in FLAGS.\nEdge:\n${object_edge}\n")
elseif(NOT object_edge MATCHES "\n RSP_FILE = [^\n]*L\\.o(bj)?\\.swift\\.rsp")
string(APPEND RunCMake_TEST_FAILED
"Object compile edge for L.swift is missing a response file.\nEdge:\n${object_edge}\n")
endif()
@@ -1,2 +1,2 @@
swiftc(\.exe)?"? -j [0-9]+ -num-threads [0-9]+ -c @CMakeFiles(/|\\)L\.dir(/|\\)(Debug(/|\\))?L\.o(bj)?\.swift\.rsp
swiftc(\.exe)?"? -j [0-9]+ -num-threads [0-9]+ @CMakeFiles(/|\\)L\.dir(/|\\)(Debug(/|\\))?L\.o(bj)?\.swift\.rsp
.*swiftc(\.exe)?"? -emit-library -static -o (Debug(/|\\))?(libL\.a|L\.lib) @CMakeFiles(/|\\)L\.(Debug\.)?rsp
@@ -1,3 +1,3 @@
.*Building Swift Module 'A' with 1 source
.*Building Swift Module 'B' with 1 source
FAILED:( \[code=[0-9]+\])? (Debug(/|\\))?B\.swiftmodule CMakeFiles(/|\\)B\.dir(/|\\)(Debug(/|\\))?b\.swift\.o(bj)?
.*Building Swift Module 'A' objects with 1 source
.*Building Swift Module 'B' objects with 1 source
FAILED:( \[code=[0-9]+\])? CMakeFiles(/|\\)B\.dir(/|\\)(Debug(/|\\))?b\.swift\.o(bj)? (Debug(/|\\))?B\.swiftmodule
@@ -1,11 +1,11 @@
.*swiftc(\.exe)?"? [^
]* -parse-as-library -static[^
]* -module-name StaticLibrary [^
]* -parse-as-library -static[^
]* -emit-module -emit-module-path (Debug/|Release/)?StaticLibrary\.swiftmodule [^
]*
.*swiftc(\.exe)?"? [^
]* -parse-as-library[^
]* -module-name DynamicLibrary [^
]* -parse-as-library[^
]* -emit-module -emit-module-path (debug|release)/modules/DynamicLibrary\.swiftmodule [^
]*
.*swiftc(\.exe)?"? [^
@@ -13,8 +13,8 @@
]* -Xlinker -install_name -Xlinker @rpath/libDynamicLibrary\.dylib -o ([A-Za-z]+/)?libDynamicLibrary\.dylib [^
]*
.*swiftc(\.exe)?"? [^
]* -parse-as-library[^
]* -module-name DynamicLibrary2 [^
]* -parse-as-library[^
]* -emit-module -emit-module-path Modules/(Debug/|Release/)?DynamicLibrary2\.swiftmodule [^
]*
.*swiftc(\.exe)?"? -j [0-9]+ -num-threads [0-9]+ -c -module-name Executable
.*swiftc(\.exe)?"? -j [0-9]+ -num-threads [0-9]+ +-c -module-name Executable
@@ -1,11 +1,11 @@
.*swiftc(\.exe)?"? [^
]* -parse-as-library -static[^
]* -module-name StaticLibrary [^
]* -parse-as-library -static[^
]* -emit-module -emit-module-path (Debug\\|Release\\)?StaticLibrary\.swiftmodule [^
]*
.*swiftc(\.exe)?"? [^
]* -parse-as-library[^
]* -module-name DynamicLibrary [^
]* -parse-as-library[^
]* -emit-module -emit-module-path (debug|release)\\modules\\DynamicLibrary\.swiftmodule [^
]*
.*swiftc(\.exe)?"? [^
@@ -13,8 +13,8 @@
]* -Xlinker -implib:(Debug\\|Release\\)?DynamicLibrary\.lib +-o ([A-Za-z]+/)?(Debug\\|Release\\)?DynamicLibrary\.dll [^
]*
.*swiftc(\.exe)?"? [^
]* -parse-as-library[^
]* -module-name DynamicLibrary2 [^
]* -parse-as-library[^
]* -emit-module -emit-module-path Modules\\(Debug\\|Release\\)?DynamicLibrary2\.swiftmodule [^
]*
.*swiftc(\.exe)?"? -j [0-9]+ -num-threads [0-9]+ -c -module-name Executable
.*swiftc(\.exe)?"? -j [0-9]+ -num-threads [0-9]+ +-c -module-name Executable
@@ -1,11 +1,11 @@
.*swiftc(\.exe)?"? [^
]* -parse-as-library -static[^
]* -module-name StaticLibrary [^
]* -parse-as-library -static[^
]* -emit-module -emit-module-path (Debug/|Release/)?StaticLibrary\.swiftmodule [^
]*
.*swiftc(\.exe)?"? [^
]* -parse-as-library[^
]* -module-name DynamicLibrary [^
]* -parse-as-library[^
]* -emit-module -emit-module-path (debug|release)/modules/DynamicLibrary\.swiftmodule [^
]*
.*swiftc(\.exe)?"? [^
@@ -13,8 +13,8 @@
]* -Xlinker -soname -Xlinker libDynamicLibrary\.so -o ([A-Za-z]+/)?libDynamicLibrary\.so [^
]*
.*swiftc(\.exe)?"? [^
]* -parse-as-library[^
]* -module-name DynamicLibrary2 [^
]* -parse-as-library[^
]* -emit-module -emit-module-path Modules/(Debug/|Release/)?DynamicLibrary2\.swiftmodule [^
]*
.*swiftc(\.exe)?"? -j [0-9]+ -num-threads [0-9]+ -c -module-name Executable
.*swiftc(\.exe)?"? -j [0-9]+ -num-threads [0-9]+ +-c -module-name Executable