Ninja: Swift: Extract helpers and reorder module flags

Extract SetupResponseFile and ExpandRuleCommands helpers from
WriteCompileRule to allow reuse by new rule types.

Reorder flag appending in WriteSwiftObjectBuildStatement so that
-module-name and -module-link-name precede -emit-module, preparing
for a separate emit-module edge that shares common flags.  Update
test regexes accordingly.

Issue: #27748
This commit is contained in:
Roman Lavrov
2026-04-24 10:17:11 -04:00
committed by Brad King
parent 811bf8fb89
commit 0f20ba5b68
6 changed files with 77 additions and 58 deletions
+62 -45
View File
@@ -681,6 +681,50 @@ cmNinjaRule GetScanRule(
return rule;
}
void SetupResponseFile(cmNinjaRule& rule,
cmRulePlaceholderExpander::RuleVariables& vars,
std::string& flags, std::string const& lang,
std::string const& responseFlag)
{
rule.RspFile = "$RSP_FILE";
rule.RspContent =
cmStrCat(' ', vars.Defines, ' ', vars.Includes, ' ', flags);
flags = cmStrCat(responseFlag, rule.RspFile);
vars.Defines = "";
vars.Includes = "";
// Swift consumes all source files in a module at once, which reaches
// command line length limits pretty quickly. Inject source files into the
// response file in this case as well.
if (lang == "Swift") {
rule.RspContent = cmStrCat(rule.RspContent, ' ', vars.Source);
vars.Source = "";
}
}
cmList ExpandRuleCommands(std::string const& command,
cmRulePlaceholderExpander::RuleVariables const& vars,
cmMakefile const* mf, std::string const& lang,
std::string const& launcher,
cmLocalGenerator* localGenerator,
cmRulePlaceholderExpander* rulePlaceholderExpander)
{
std::string const extraCommands =
mf->GetSafeDefinition(cmStrCat("CMAKE_", lang, "_DEPENDS_EXTRA_COMMANDS"));
cmList commands(command);
if (!commands.empty()) {
commands.front().insert(0, "${CODE_CHECK}");
commands.front().insert(0, "${LAUNCHER}");
}
if (!extraCommands.empty()) {
commands.append(extraCommands);
}
for (std::string& cmd : commands) {
cmd = cmStrCat(launcher, cmd);
rulePlaceholderExpander->ExpandRuleVariables(localGenerator, cmd, vars);
}
return commands;
}
}
void cmNinjaTargetGenerator::WriteCompileRule(std::string const& lang,
@@ -883,20 +927,7 @@ void cmNinjaTargetGenerator::WriteCompileRule(std::string const& lang,
cmNinjaRule rule(this->LanguageCompilerRule(lang, config, withScanning));
// If using a response file, move defines, includes, and flags into it.
if (!responseFlag.empty()) {
rule.RspFile = "$RSP_FILE";
rule.RspContent =
cmStrCat(' ', vars.Defines, ' ', vars.Includes, ' ', flags);
flags = cmStrCat(responseFlag, rule.RspFile);
vars.Defines = "";
vars.Includes = "";
// Swift consumes all source files in a module at once, which reaches
// command line length limits pretty quickly. Inject source files into the
// response file in this case as well.
if (lang == "Swift") {
rule.RspContent = cmStrCat(rule.RspContent, ' ', vars.Source);
vars.Source = "";
}
SetupResponseFile(rule, vars, flags, lang, responseFlag);
}
// Tell ninja dependency format so all deps can be loaded into a database
@@ -987,29 +1018,14 @@ void cmNinjaTargetGenerator::WriteCompileRule(std::string const& lang,
// Rule for compiling object file.
std::string const cmdVar = this->GetCompileTemplateVar(lang);
std::string const& compileCmd = mf->GetRequiredDefinition(cmdVar);
cmList compileCmds(compileCmd);
if (!compileCmds.empty()) {
compileCmds.front().insert(0, "${CODE_CHECK}");
compileCmds.front().insert(0, "${LAUNCHER}");
}
cmList compileCmds = ExpandRuleCommands(compileCmd, vars, mf, lang, launcher,
this->GetLocalGenerator(),
rulePlaceholderExpander.get());
if (!compileCmds.empty()) {
compileCmds.front().insert(0, cldeps);
}
auto const& extraCommands = this->GetMakefile()->GetSafeDefinition(
cmStrCat("CMAKE_", lang, "_DEPENDS_EXTRA_COMMANDS"));
if (!extraCommands.empty()) {
compileCmds.append(extraCommands);
}
for (auto& i : compileCmds) {
i = cmStrCat(launcher, i);
rulePlaceholderExpander->ExpandRuleVariables(this->GetLocalGenerator(), i,
vars);
}
rule.Command =
this->GetLocalGenerator()->BuildCommandLine(compileCmds, config, config);
@@ -2102,19 +2118,6 @@ void cmNinjaTargetGenerator::WriteSwiftObjectBuildStatement(
return true;
};
// 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);
}
this->LocalGenerator->AppendFlags(vars["FLAGS"],
cmStrCat("-module-name ", moduleName));
@@ -2128,6 +2131,20 @@ void cmNinjaTargetGenerator::WriteSwiftObjectBuildStatement(
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;
@@ -1,2 +1,3 @@
swiftc(\.exe)?"? [^
]* -emit-module -emit-module-path El(/|\\)((Debug|Release)(/|\\))?El\.swiftmodule(/|\\)[-_a-z0-9]+\.swiftmodule -module-name El
]* -module-name El [^
]* -emit-module -emit-module-path El(/|\\)((Debug|Release)(/|\\))?El\.swiftmodule(/|\\)[-_a-z0-9]+\.swiftmodule
@@ -1,2 +1,3 @@
swiftc(\.exe)?"? [^
]* -emit-module -emit-module-path El(/|\\)((Debug|Release)(/|\\))?El\.swiftmodule -module-name El
]* -module-name El [^
]* -emit-module -emit-module-path El(/|\\)((Debug|Release)(/|\\))?El\.swiftmodule
@@ -1,12 +1,12 @@
.*swiftc(\.exe)?"? [^
]* -parse-as-library -static[^
]* -emit-module -emit-module-path (Debug/|Release/)?StaticLibrary\.swiftmodule[^
]* -module-name StaticLibrary [^
]* -emit-module -emit-module-path (Debug/|Release/)?StaticLibrary\.swiftmodule [^
]*
.*swiftc(\.exe)?"? [^
]* -parse-as-library[^
]* -emit-module -emit-module-path (debug|release)/modules/DynamicLibrary\.swiftmodule[^
]* -module-name DynamicLibrary [^
]* -emit-module -emit-module-path (debug|release)/modules/DynamicLibrary\.swiftmodule [^
]*
.*swiftc(\.exe)?"? [^
]* -emit-library [^
@@ -14,7 +14,7 @@
]*
.*swiftc(\.exe)?"? [^
]* -parse-as-library[^
]* -emit-module -emit-module-path Modules/(Debug/|Release/)?DynamicLibrary2\.swiftmodule[^
]* -module-name DynamicLibrary2[^
]* -module-name DynamicLibrary2 [^
]* -emit-module -emit-module-path Modules/(Debug/|Release/)?DynamicLibrary2\.swiftmodule [^
]*
.*swiftc(\.exe)?"? -j [0-9]+ -num-threads [0-9]+ -c -module-name Executable
@@ -1,12 +1,12 @@
.*swiftc(\.exe)?"? [^
]* -parse-as-library -static[^
]* -emit-module -emit-module-path (Debug\\|Release\\)?StaticLibrary\.swiftmodule[^
]* -module-name StaticLibrary [^
]* -emit-module -emit-module-path (Debug\\|Release\\)?StaticLibrary\.swiftmodule [^
]*
.*swiftc(\.exe)?"? [^
]* -parse-as-library[^
]* -emit-module -emit-module-path (debug|release)\\modules\\DynamicLibrary\.swiftmodule[^
]* -module-name DynamicLibrary [^
]* -emit-module -emit-module-path (debug|release)\\modules\\DynamicLibrary\.swiftmodule [^
]*
.*swiftc(\.exe)?"? [^
]* -emit-library [^
@@ -14,7 +14,7 @@
]*
.*swiftc(\.exe)?"? [^
]* -parse-as-library[^
]* -emit-module -emit-module-path Modules\\(Debug\\|Release\\)?DynamicLibrary2\.swiftmodule[^
]* -module-name DynamicLibrary2 [^
]* -emit-module -emit-module-path Modules\\(Debug\\|Release\\)?DynamicLibrary2\.swiftmodule [^
]*
.*swiftc(\.exe)?"? -j [0-9]+ -num-threads [0-9]+ -c -module-name Executable
@@ -1,12 +1,12 @@
.*swiftc(\.exe)?"? [^
]* -parse-as-library -static[^
]* -emit-module -emit-module-path (Debug/|Release/)?StaticLibrary\.swiftmodule[^
]* -module-name StaticLibrary [^
]* -emit-module -emit-module-path (Debug/|Release/)?StaticLibrary\.swiftmodule [^
]*
.*swiftc(\.exe)?"? [^
]* -parse-as-library[^
]* -emit-module -emit-module-path (debug|release)/modules/DynamicLibrary\.swiftmodule[^
]* -module-name DynamicLibrary [^
]* -emit-module -emit-module-path (debug|release)/modules/DynamicLibrary\.swiftmodule [^
]*
.*swiftc(\.exe)?"? [^
]* -emit-library [^
@@ -14,7 +14,7 @@
]*
.*swiftc(\.exe)?"? [^
]* -parse-as-library[^
]* -emit-module -emit-module-path Modules/(Debug/|Release/)?DynamicLibrary2\.swiftmodule[^
]* -module-name DynamicLibrary2[^
]* -module-name DynamicLibrary2 [^
]* -emit-module -emit-module-path Modules/(Debug/|Release/)?DynamicLibrary2\.swiftmodule [^
]*
.*swiftc(\.exe)?"? -j [0-9]+ -num-threads [0-9]+ -c -module-name Executable