1
0
mirror of https://github.com/Kitware/CMake.git synced 2025-10-16 05:26:58 +08:00

Ninja Multi-Config: Split long command lines by config

Fixes: #22123
This commit is contained in:
Kyle Edwards
2021-04-30 14:45:19 -04:00
parent 1ad4501ae9
commit ad08f93ee4
9 changed files with 66 additions and 30 deletions

View File

@@ -407,7 +407,8 @@ void cmLocalNinjaGenerator::AppendCustomCommandDeps(
} }
std::string cmLocalNinjaGenerator::WriteCommandScript( std::string cmLocalNinjaGenerator::WriteCommandScript(
std::vector<std::string> const& cmdLines, std::string const& customStep, std::vector<std::string> const& cmdLines, std::string const& outputConfig,
std::string const& commandConfig, std::string const& customStep,
cmGeneratorTarget const* target) const cmGeneratorTarget const* target) const
{ {
std::string scriptPath; std::string scriptPath;
@@ -416,9 +417,13 @@ std::string cmLocalNinjaGenerator::WriteCommandScript(
} else { } else {
scriptPath = cmStrCat(this->GetCurrentBinaryDirectory(), "/CMakeFiles"); scriptPath = cmStrCat(this->GetCurrentBinaryDirectory(), "/CMakeFiles");
} }
scriptPath += this->GetGlobalNinjaGenerator()->ConfigDirectory(outputConfig);
cmSystemTools::MakeDirectory(scriptPath); cmSystemTools::MakeDirectory(scriptPath);
scriptPath += '/'; scriptPath += '/';
scriptPath += customStep; scriptPath += customStep;
if (this->GlobalGenerator->IsMultiConfig()) {
scriptPath += cmStrCat('-', commandConfig);
}
#ifdef _WIN32 #ifdef _WIN32
scriptPath += ".bat"; scriptPath += ".bat";
#else #else
@@ -461,7 +466,8 @@ std::string cmLocalNinjaGenerator::WriteCommandScript(
} }
std::string cmLocalNinjaGenerator::BuildCommandLine( std::string cmLocalNinjaGenerator::BuildCommandLine(
std::vector<std::string> const& cmdLines, std::string const& customStep, std::vector<std::string> const& cmdLines, std::string const& outputConfig,
std::string const& commandConfig, std::string const& customStep,
cmGeneratorTarget const* target) const cmGeneratorTarget const* target) const
{ {
// If we have no commands but we need to build a command anyway, use noop. // If we have no commands but we need to build a command anyway, use noop.
@@ -480,8 +486,8 @@ std::string cmLocalNinjaGenerator::BuildCommandLine(
cmdLinesTotal += cmd.length() + 6; cmdLinesTotal += cmd.length() + 6;
} }
if (cmdLinesTotal > cmSystemTools::CalculateCommandLineLengthLimit() / 2) { if (cmdLinesTotal > cmSystemTools::CalculateCommandLineLengthLimit() / 2) {
std::string const scriptPath = std::string const scriptPath = this->WriteCommandScript(
this->WriteCommandScript(cmdLines, customStep, target); cmdLines, outputConfig, commandConfig, customStep, target);
std::string cmd std::string cmd
#ifndef _WIN32 #ifndef _WIN32
= "/bin/sh " = "/bin/sh "
@@ -694,7 +700,8 @@ void cmLocalNinjaGenerator::WriteCustomCommandBuildStatement(
} }
gg->WriteCustomCommandBuild( gg->WriteCustomCommandBuild(
this->BuildCommandLine(cmdLines, customStep), this->BuildCommandLine(cmdLines, ccg.GetOutputConfig(), fileConfig,
customStep),
this->ConstructComment(ccg), "Custom command for " + ninjaOutputs[0], this->ConstructComment(ccg), "Custom command for " + ninjaOutputs[0],
depfile, cc->GetJobPool(), cc->GetUsesTerminal(), depfile, cc->GetJobPool(), cc->GetUsesTerminal(),
/*restat*/ !symbolic || !byproducts.empty(), ninjaOutputs, fileConfig, /*restat*/ !symbolic || !byproducts.empty(), ninjaOutputs, fileConfig,

View File

@@ -60,7 +60,8 @@ public:
} }
std::string BuildCommandLine( std::string BuildCommandLine(
std::vector<std::string> const& cmdLines, std::vector<std::string> const& cmdLines, std::string const& outputConfig,
std::string const& commandConfig,
std::string const& customStep = std::string(), std::string const& customStep = std::string(),
cmGeneratorTarget const* target = nullptr) const; cmGeneratorTarget const* target = nullptr) const;
@@ -119,6 +120,8 @@ private:
std::string MakeCustomLauncher(cmCustomCommandGenerator const& ccg); std::string MakeCustomLauncher(cmCustomCommandGenerator const& ccg);
std::string WriteCommandScript(std::vector<std::string> const& cmdLines, std::string WriteCommandScript(std::vector<std::string> const& cmdLines,
std::string const& outputConfig,
std::string const& commandConfig,
std::string const& customStep, std::string const& customStep,
cmGeneratorTarget const* target) const; cmGeneratorTarget const* target) const;

View File

@@ -287,7 +287,8 @@ void cmNinjaNormalTargetGenerator::WriteNvidiaDeviceLinkRule(
// If there is no ranlib the command will be ":". Skip it. // If there is no ranlib the command will be ":". Skip it.
cm::erase_if(linkCmds, cmNinjaRemoveNoOpCommands()); cm::erase_if(linkCmds, cmNinjaRemoveNoOpCommands());
rule.Command = this->GetLocalGenerator()->BuildCommandLine(linkCmds); rule.Command =
this->GetLocalGenerator()->BuildCommandLine(linkCmds, config, config);
// Write the linker rule with response file if needed. // Write the linker rule with response file if needed.
rule.Comment = rule.Comment =
@@ -310,7 +311,8 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkRules(
cmNinjaRule rule(this->LanguageLinkerCudaDeviceRule(config)); cmNinjaRule rule(this->LanguageLinkerCudaDeviceRule(config));
rule.Command = this->GetLocalGenerator()->BuildCommandLine( rule.Command = this->GetLocalGenerator()->BuildCommandLine(
{ cmStrCat(mf->GetRequiredDefinition("CMAKE_CUDA_DEVICE_LINKER"), { cmStrCat(mf->GetRequiredDefinition("CMAKE_CUDA_DEVICE_LINKER"),
" -arch=$ARCH $REGISTER -o=$out $in") }); " -arch=$ARCH $REGISTER -o=$out $in") },
config, config);
rule.Comment = "Rule for CUDA device linking."; rule.Comment = "Rule for CUDA device linking.";
rule.Description = "Linking CUDA $out"; rule.Description = "Linking CUDA $out";
this->GetGlobalGenerator()->AddRule(rule); this->GetGlobalGenerator()->AddRule(rule);
@@ -336,7 +338,8 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkRules(
compileCmd, vars); compileCmd, vars);
rule.Name = this->LanguageLinkerCudaDeviceCompileRule(config); rule.Name = this->LanguageLinkerCudaDeviceCompileRule(config);
rule.Command = this->GetLocalGenerator()->BuildCommandLine({ compileCmd }); rule.Command = this->GetLocalGenerator()->BuildCommandLine({ compileCmd },
config, config);
rule.Comment = "Rule for compiling CUDA device stubs."; rule.Comment = "Rule for compiling CUDA device stubs.";
rule.Description = "Compiling CUDA device stub $out"; rule.Description = "Compiling CUDA device stub $out";
this->GetGlobalGenerator()->AddRule(rule); this->GetGlobalGenerator()->AddRule(rule);
@@ -345,7 +348,8 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkRules(
rule.Command = this->GetLocalGenerator()->BuildCommandLine( rule.Command = this->GetLocalGenerator()->BuildCommandLine(
{ cmStrCat(mf->GetRequiredDefinition("CMAKE_CUDA_FATBINARY"), { cmStrCat(mf->GetRequiredDefinition("CMAKE_CUDA_FATBINARY"),
" -64 -cmdline=--compile-only -compress-all -link " " -64 -cmdline=--compile-only -compress-all -link "
"--embedded-fatbin=$out $PROFILES") }); "--embedded-fatbin=$out $PROFILES") },
config, config);
rule.Comment = "Rule for CUDA fatbinaries."; rule.Comment = "Rule for CUDA fatbinaries.";
rule.Description = "Creating fatbinary $out"; rule.Description = "Creating fatbinary $out";
this->GetGlobalGenerator()->AddRule(rule); this->GetGlobalGenerator()->AddRule(rule);
@@ -475,7 +479,8 @@ void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile,
linkCmds.insert(linkCmds.begin(), "$PRE_LINK"); linkCmds.insert(linkCmds.begin(), "$PRE_LINK");
linkCmds.emplace_back("$POST_BUILD"); linkCmds.emplace_back("$POST_BUILD");
rule.Command = this->GetLocalGenerator()->BuildCommandLine(linkCmds); rule.Command =
this->GetLocalGenerator()->BuildCommandLine(linkCmds, config, config);
// Write the linker rule with response file if needed. // Write the linker rule with response file if needed.
rule.Comment = rule.Comment =
@@ -500,7 +505,8 @@ void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile,
std::vector<std::string> cmd; std::vector<std::string> cmd;
cmd.push_back(cmakeCommand + " -E cmake_symlink_executable $in $out"); cmd.push_back(cmakeCommand + " -E cmake_symlink_executable $in $out");
cmd.emplace_back("$POST_BUILD"); cmd.emplace_back("$POST_BUILD");
rule.Command = this->GetLocalGenerator()->BuildCommandLine(cmd); rule.Command =
this->GetLocalGenerator()->BuildCommandLine(cmd, config, config);
} }
rule.Description = "Creating executable symlink $out"; rule.Description = "Creating executable symlink $out";
rule.Comment = "Rule for creating executable symlink."; rule.Comment = "Rule for creating executable symlink.";
@@ -512,7 +518,8 @@ void cmNinjaNormalTargetGenerator::WriteLinkRule(bool useResponseFile,
cmd.push_back(cmakeCommand + cmd.push_back(cmakeCommand +
" -E cmake_symlink_library $in $SONAME $out"); " -E cmake_symlink_library $in $SONAME $out");
cmd.emplace_back("$POST_BUILD"); cmd.emplace_back("$POST_BUILD");
rule.Command = this->GetLocalGenerator()->BuildCommandLine(cmd); rule.Command =
this->GetLocalGenerator()->BuildCommandLine(cmd, config, config);
} }
rule.Description = "Creating library symlink $out"; rule.Description = "Creating library symlink $out";
rule.Comment = "Rule for creating library symlink."; rule.Comment = "Rule for creating library symlink.";
@@ -1310,10 +1317,11 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement(
preLinkCmdLines.push_back("cd " + homeOutDir); preLinkCmdLines.push_back("cd " + homeOutDir);
} }
vars["PRE_LINK"] = localGen.BuildCommandLine(preLinkCmdLines, "pre-link", vars["PRE_LINK"] = localGen.BuildCommandLine(
this->GeneratorTarget); preLinkCmdLines, config, fileConfig, "pre-link", this->GeneratorTarget);
std::string postBuildCmdLine = localGen.BuildCommandLine( std::string postBuildCmdLine =
postBuildCmdLines, "post-build", this->GeneratorTarget); localGen.BuildCommandLine(postBuildCmdLines, config, fileConfig,
"post-build", this->GeneratorTarget);
cmNinjaVars symlinkVars; cmNinjaVars symlinkVars;
bool const symlinkNeeded = bool const symlinkNeeded =

View File

@@ -537,7 +537,8 @@ cmNinjaRule GetScanRule(
cmRulePlaceholderExpander::RuleVariables const& vars, cmRulePlaceholderExpander::RuleVariables const& vars,
const std::string& responseFlag, const std::string& flags, const std::string& responseFlag, const std::string& flags,
cmRulePlaceholderExpander* const rulePlaceholderExpander, cmRulePlaceholderExpander* const rulePlaceholderExpander,
cmLocalNinjaGenerator* generator, std::vector<std::string> scanCmds) cmLocalNinjaGenerator* generator, std::vector<std::string> scanCmds,
const std::string& outputConfig)
{ {
cmNinjaRule rule(ruleName); cmNinjaRule rule(ruleName);
// Scanning always uses a depfile for preprocessor dependencies. // Scanning always uses a depfile for preprocessor dependencies.
@@ -578,7 +579,8 @@ cmNinjaRule GetScanRule(
for (std::string& scanCmd : scanCmds) { for (std::string& scanCmd : scanCmds) {
rulePlaceholderExpander->ExpandRuleVariables(generator, scanCmd, scanVars); rulePlaceholderExpander->ExpandRuleVariables(generator, scanCmd, scanVars);
} }
rule.Command = generator->BuildCommandLine(scanCmds); rule.Command =
generator->BuildCommandLine(scanCmds, outputConfig, outputConfig);
return rule; return rule;
} }
@@ -670,7 +672,7 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang,
auto scanRule = GetScanRule( auto scanRule = GetScanRule(
scanRuleName, vars, responseFlag, flags, rulePlaceholderExpander.get(), scanRuleName, vars, responseFlag, flags, rulePlaceholderExpander.get(),
this->GetLocalGenerator(), std::move(scanCommands)); this->GetLocalGenerator(), std::move(scanCommands), config);
scanRule.Comment = scanRule.Comment =
cmStrCat("Rule for generating ", lang, " dependencies."); cmStrCat("Rule for generating ", lang, " dependencies.");
@@ -700,7 +702,7 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang,
auto scanRule = GetScanRule( auto scanRule = GetScanRule(
scanRuleName, vars, "", flags, rulePlaceholderExpander.get(), scanRuleName, vars, "", flags, rulePlaceholderExpander.get(),
this->GetLocalGenerator(), std::move(scanCommands)); this->GetLocalGenerator(), std::move(scanCommands), config);
// Write the rule for generating dependencies for the given language. // Write the rule for generating dependencies for the given language.
scanRule.Comment = cmStrCat("Rule for generating ", lang, scanRule.Comment = cmStrCat("Rule for generating ", lang,
@@ -732,7 +734,8 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang,
ddModmapArg, " --dd=$out @", rule.RspFile); ddModmapArg, " --dd=$out @", rule.RspFile);
ddCmds.emplace_back(std::move(ccmd)); ddCmds.emplace_back(std::move(ccmd));
} }
rule.Command = this->GetLocalGenerator()->BuildCommandLine(ddCmds); rule.Command =
this->GetLocalGenerator()->BuildCommandLine(ddCmds, config, config);
} }
rule.Comment = rule.Comment =
cmStrCat("Rule to generate ninja dyndep files for ", lang, '.'); cmStrCat("Rule to generate ninja dyndep files for ", lang, '.');
@@ -928,7 +931,8 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang,
vars); vars);
} }
rule.Command = this->GetLocalGenerator()->BuildCommandLine(compileCmds); rule.Command =
this->GetLocalGenerator()->BuildCommandLine(compileCmds, config, config);
// Write the rule for compiling file of the given language. // Write the rule for compiling file of the given language.
rule.Comment = cmStrCat("Rule for compiling ", lang, " files."); rule.Comment = cmStrCat("Rule for compiling ", lang, " files.");
@@ -1246,7 +1250,7 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement(
this->ExportObjectCompileCommand( this->ExportObjectCompileCommand(
language, sourceFileName, objectDir, objectFileName, objectFileDir, language, sourceFileName, objectDir, objectFileName, objectFileDir,
vars["FLAGS"], vars["DEFINES"], vars["INCLUDES"]); vars["FLAGS"], vars["DEFINES"], vars["INCLUDES"], config);
objBuild.Outputs.push_back(objectFileName); objBuild.Outputs.push_back(objectFileName);
if (firstForConfig) { if (firstForConfig) {
@@ -1617,7 +1621,8 @@ void cmNinjaTargetGenerator::ExportObjectCompileCommand(
std::string const& language, std::string const& sourceFileName, std::string const& language, std::string const& sourceFileName,
std::string const& objectDir, std::string const& objectFileName, std::string const& objectDir, std::string const& objectFileName,
std::string const& objectFileDir, std::string const& flags, std::string const& objectFileDir, std::string const& flags,
std::string const& defines, std::string const& includes) std::string const& defines, std::string const& includes,
std::string const& outputConfig)
{ {
if (!this->GeneratorTarget->GetPropertyAsBool("EXPORT_COMPILE_COMMANDS")) { if (!this->GeneratorTarget->GetPropertyAsBool("EXPORT_COMPILE_COMMANDS")) {
return; return;
@@ -1679,8 +1684,8 @@ void cmNinjaTargetGenerator::ExportObjectCompileCommand(
compileObjectVars); compileObjectVars);
} }
std::string cmdLine = std::string cmdLine = this->GetLocalGenerator()->BuildCommandLine(
this->GetLocalGenerator()->BuildCommandLine(compileCmds); compileCmds, outputConfig, outputConfig);
this->GetGlobalGenerator()->AddCXXCompileCommand(cmdLine, sourceFileName); this->GetGlobalGenerator()->AddCXXCompileCommand(cmdLine, sourceFileName);
} }

View File

@@ -162,7 +162,8 @@ protected:
std::string const& language, std::string const& sourceFileName, std::string const& language, std::string const& sourceFileName,
std::string const& objectDir, std::string const& objectFileName, std::string const& objectDir, std::string const& objectFileName,
std::string const& objectFileDir, std::string const& flags, std::string const& objectFileDir, std::string const& flags,
std::string const& defines, std::string const& includes); std::string const& defines, std::string const& includes,
std::string const& outputConfig);
void AdditionalCleanFiles(const std::string& config); void AdditionalCleanFiles(const std::string& config);

View File

@@ -139,8 +139,8 @@ void cmNinjaUtilityTargetGenerator::WriteUtilBuildStatements(
gg->WriteBuild(this->GetCommonFileStream(), phonyBuild); gg->WriteBuild(this->GetCommonFileStream(), phonyBuild);
} }
} else { } else {
std::string command = std::string command = lg->BuildCommandLine(
lg->BuildCommandLine(commands, "utility", this->GeneratorTarget); commands, config, fileConfig, "utility", this->GeneratorTarget);
std::string desc; std::string desc;
cmProp echoStr = genTarget->GetProperty("EchoString"); cmProp echoStr = genTarget->GetProperty("EchoString");
if (echoStr) { if (echoStr) {

View File

@@ -0,0 +1,2 @@
Post-build Debug Release \.*$

View File

@@ -14,3 +14,10 @@ add_custom_target(
ALL ALL
DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/gen.txt" DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/gen.txt"
) )
add_executable(exe main.c)
add_custom_command(
TARGET exe POST_BUILD
COMMAND ${CMAKE_COMMAND} -E echo "Post-build $<CONFIG> $<COMMAND_CONFIG:$<CONFIG>> ${very_long}"
)

View File

@@ -198,8 +198,11 @@ run_cmake_build(PostBuild release Release Exe)
run_cmake_build(PostBuild debug-in-release-graph Release Exe:Debug) run_cmake_build(PostBuild debug-in-release-graph Release Exe:Debug)
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/LongCommandLine-build) set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/LongCommandLine-build)
set(RunCMake_TEST_OPTIONS "-DCMAKE_CROSS_CONFIGS=all")
run_cmake_configure(LongCommandLine) run_cmake_configure(LongCommandLine)
unset(RunCMake_TEST_OPTIONS)
run_cmake_build(LongCommandLine release Release custom) run_cmake_build(LongCommandLine release Release custom)
run_cmake_build(LongCommandLine release-config Release exe:Debug)
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/Framework-build) set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/Framework-build)
set(RunCMake_TEST_OPTIONS "-DCMAKE_CROSS_CONFIGS=all") set(RunCMake_TEST_OPTIONS "-DCMAKE_CROSS_CONFIGS=all")