Commit 7b64b0cd authored by Brad King's avatar Brad King
Browse files

cmLocalGenerator: Refactor custom command generator construction

Add support for constructing and using multiple generators for one
custom command.  cmGeneratorTarget contains a code path that needs this
behavior when used with Ninja but not other generators, so use virtual
dispatch through cmLocalGenerator.
parent d29da8ed
...@@ -3079,15 +3079,16 @@ void cmTargetTraceDependencies::CheckCustomCommand(cmCustomCommand const& cc) ...@@ -3079,15 +3079,16 @@ void cmTargetTraceDependencies::CheckCustomCommand(cmCustomCommand const& cc)
std::set<std::string> depends; std::set<std::string> depends;
for (std::string const& config : for (std::string const& config :
this->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig)) { this->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig)) {
cmCustomCommandGenerator ccg(cc, config, this->LocalGenerator); for (cmCustomCommandGenerator const& ccg :
this->LocalGenerator->MakeCustomCommandGenerators(cc, config)) {
// Collect target-level dependencies referenced in command lines.
for (auto const& util : ccg.GetUtilities()) {
this->GeneratorTarget->Target->AddUtility(util);
}
// Collect target-level dependencies referenced in command lines. // Collect file-level dependencies referenced in DEPENDS.
for (auto const& util : ccg.GetUtilities()) { depends.insert(ccg.GetDepends().begin(), ccg.GetDepends().end());
this->GeneratorTarget->Target->AddUtility(util);
} }
// Collect file-level dependencies referenced in DEPENDS.
depends.insert(ccg.GetDepends().begin(), ccg.GetDepends().end());
} }
// Queue file-level dependencies. // Queue file-level dependencies.
......
...@@ -4232,6 +4232,15 @@ cmSourceFile* cmLocalGenerator::GetSourceFileWithOutput( ...@@ -4232,6 +4232,15 @@ cmSourceFile* cmLocalGenerator::GetSourceFileWithOutput(
return nullptr; return nullptr;
} }
std::vector<cmCustomCommandGenerator>
cmLocalGenerator::MakeCustomCommandGenerators(cmCustomCommand const& cc,
std::string const& config)
{
std::vector<cmCustomCommandGenerator> ccgs;
ccgs.emplace_back(cc, config, this);
return ccgs;
}
std::vector<std::string> cmLocalGenerator::ExpandCustomCommandOutputPaths( std::vector<std::string> cmLocalGenerator::ExpandCustomCommandOutputPaths(
cmCompiledGeneratorExpression const& cge, std::string const& config) cmCompiledGeneratorExpression const& cge, std::string const& config)
{ {
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
class cmCompiledGeneratorExpression; class cmCompiledGeneratorExpression;
class cmComputeLinkInformation; class cmComputeLinkInformation;
class cmCustomCommand;
class cmCustomCommandGenerator; class cmCustomCommandGenerator;
class cmCustomCommandLines; class cmCustomCommandLines;
class cmGeneratorTarget; class cmGeneratorTarget;
...@@ -363,6 +364,9 @@ public: ...@@ -363,6 +364,9 @@ public:
bool command_expand_lists = false, const std::string& job_pool = "", bool command_expand_lists = false, const std::string& job_pool = "",
bool stdPipesUTF8 = false); bool stdPipesUTF8 = false);
virtual std::vector<cmCustomCommandGenerator> MakeCustomCommandGenerators(
cmCustomCommand const& cc, std::string const& config);
std::vector<std::string> ExpandCustomCommandOutputPaths( std::vector<std::string> ExpandCustomCommandOutputPaths(
cmCompiledGeneratorExpression const& cge, std::string const& config); cmCompiledGeneratorExpression const& cge, std::string const& config);
std::vector<std::string> ExpandCustomCommandOutputGenex( std::vector<std::string> ExpandCustomCommandOutputGenex(
......
...@@ -575,97 +575,108 @@ void cmLocalNinjaGenerator::WriteCustomCommandBuildStatement( ...@@ -575,97 +575,108 @@ void cmLocalNinjaGenerator::WriteCustomCommandBuildStatement(
return; return;
} }
bool transformDepfile = false; for (cmCustomCommandGenerator const& ccg :
auto cmp0116 = this->GetPolicyStatus(cmPolicies::CMP0116); this->MakeCustomCommandGenerators(*cc, config)) {
switch (cmp0116) {
case cmPolicies::OLD:
case cmPolicies::WARN:
break;
case cmPolicies::REQUIRED_IF_USED:
case cmPolicies::REQUIRED_ALWAYS:
case cmPolicies::NEW:
transformDepfile = true;
break;
}
cmCustomCommandGenerator ccg(*cc, config, this, transformDepfile); const std::vector<std::string>& outputs = ccg.GetOutputs();
const std::vector<std::string>& byproducts = ccg.GetByproducts();
const std::vector<std::string>& outputs = ccg.GetOutputs(); bool symbolic = false;
const std::vector<std::string>& byproducts = ccg.GetByproducts(); for (std::string const& output : outputs) {
if (cmSourceFile* sf = this->Makefile->GetSource(output)) {
bool symbolic = false; if (sf->GetPropertyAsBool("SYMBOLIC")) {
for (std::string const& output : outputs) { symbolic = true;
if (cmSourceFile* sf = this->Makefile->GetSource(output)) { break;
if (sf->GetPropertyAsBool("SYMBOLIC")) { }
symbolic = true;
break;
} }
} }
}
cmNinjaDeps ninjaOutputs(outputs.size() + byproducts.size()); cmNinjaDeps ninjaOutputs(outputs.size() + byproducts.size());
std::transform(outputs.begin(), outputs.end(), ninjaOutputs.begin(), std::transform(outputs.begin(), outputs.end(), ninjaOutputs.begin(),
gg->MapToNinjaPath()); gg->MapToNinjaPath());
std::transform(byproducts.begin(), byproducts.end(), std::transform(byproducts.begin(), byproducts.end(),
ninjaOutputs.begin() + outputs.size(), gg->MapToNinjaPath()); ninjaOutputs.begin() + outputs.size(),
gg->MapToNinjaPath());
for (std::string const& ninjaOutput : ninjaOutputs) { for (std::string const& ninjaOutput : ninjaOutputs) {
gg->SeenCustomCommandOutput(ninjaOutput); gg->SeenCustomCommandOutput(ninjaOutput);
} }
cmNinjaDeps ninjaDeps; cmNinjaDeps ninjaDeps;
this->AppendCustomCommandDeps(ccg, ninjaDeps, config); this->AppendCustomCommandDeps(ccg, ninjaDeps, config);
std::vector<std::string> cmdLines; std::vector<std::string> cmdLines;
this->AppendCustomCommandLines(ccg, cmdLines); this->AppendCustomCommandLines(ccg, cmdLines);
if (cmdLines.empty()) { if (cmdLines.empty()) {
cmNinjaBuild build("phony"); cmNinjaBuild build("phony");
build.Comment = "Phony custom command for " + ninjaOutputs[0]; build.Comment = "Phony custom command for " + ninjaOutputs[0];
build.Outputs = std::move(ninjaOutputs); build.Outputs = std::move(ninjaOutputs);
build.ExplicitDeps = std::move(ninjaDeps); build.ExplicitDeps = std::move(ninjaDeps);
build.OrderOnlyDeps = orderOnlyDeps; build.OrderOnlyDeps = orderOnlyDeps;
gg->WriteBuild(this->GetImplFileStream(config), build); gg->WriteBuild(this->GetImplFileStream(config), build);
} else { } else {
std::string customStep = cmSystemTools::GetFilenameName(ninjaOutputs[0]); std::string customStep = cmSystemTools::GetFilenameName(ninjaOutputs[0]);
// Hash full path to make unique. // Hash full path to make unique.
customStep += '-'; customStep += '-';
cmCryptoHash hash(cmCryptoHash::AlgoSHA256); cmCryptoHash hash(cmCryptoHash::AlgoSHA256);
customStep += hash.HashString(ninjaOutputs[0]).substr(0, 7); customStep += hash.HashString(ninjaOutputs[0]).substr(0, 7);
std::string depfile = cc->GetDepfile(); std::string depfile = cc->GetDepfile();
if (!depfile.empty()) { if (!depfile.empty()) {
switch (cmp0116) { switch (this->GetPolicyStatus(cmPolicies::CMP0116)) {
case cmPolicies::WARN: case cmPolicies::WARN:
if (this->GetCurrentBinaryDirectory() != if (this->GetCurrentBinaryDirectory() !=
this->GetBinaryDirectory() || this->GetBinaryDirectory() ||
this->Makefile->PolicyOptionalWarningEnabled( this->Makefile->PolicyOptionalWarningEnabled(
"CMAKE_POLICY_WARNING_CMP0116")) { "CMAKE_POLICY_WARNING_CMP0116")) {
this->GetCMakeInstance()->IssueMessage( this->GetCMakeInstance()->IssueMessage(
MessageType::AUTHOR_WARNING, MessageType::AUTHOR_WARNING,
cmPolicies::GetPolicyWarning(cmPolicies::CMP0116), cmPolicies::GetPolicyWarning(cmPolicies::CMP0116),
cc->GetBacktrace()); cc->GetBacktrace());
} }
CM_FALLTHROUGH; CM_FALLTHROUGH;
case cmPolicies::OLD: case cmPolicies::OLD:
break; break;
case cmPolicies::REQUIRED_IF_USED: case cmPolicies::REQUIRED_IF_USED:
case cmPolicies::REQUIRED_ALWAYS: case cmPolicies::REQUIRED_ALWAYS:
case cmPolicies::NEW: case cmPolicies::NEW:
cmSystemTools::MakeDirectory( cmSystemTools::MakeDirectory(
cmStrCat(this->GetBinaryDirectory(), "/CMakeFiles/d")); cmStrCat(this->GetBinaryDirectory(), "/CMakeFiles/d"));
depfile = ccg.GetInternalDepfile(); depfile = ccg.GetInternalDepfile();
break; break;
}
} }
gg->WriteCustomCommandBuild(
this->BuildCommandLine(cmdLines, customStep),
this->ConstructComment(ccg), "Custom command for " + ninjaOutputs[0],
depfile, cc->GetJobPool(), cc->GetUsesTerminal(),
/*restat*/ !symbolic || !byproducts.empty(), ninjaOutputs, config,
ninjaDeps, orderOnlyDeps);
} }
}
}
gg->WriteCustomCommandBuild( std::vector<cmCustomCommandGenerator>
this->BuildCommandLine(cmdLines, customStep), cmLocalNinjaGenerator::MakeCustomCommandGenerators(cmCustomCommand const& cc,
this->ConstructComment(ccg), "Custom command for " + ninjaOutputs[0], std::string const& config)
depfile, cc->GetJobPool(), cc->GetUsesTerminal(), {
/*restat*/ !symbolic || !byproducts.empty(), ninjaOutputs, config, bool transformDepfile = false;
ninjaDeps, orderOnlyDeps); switch (this->GetPolicyStatus(cmPolicies::CMP0116)) {
case cmPolicies::OLD:
case cmPolicies::WARN:
break;
case cmPolicies::REQUIRED_IF_USED:
case cmPolicies::REQUIRED_ALWAYS:
case cmPolicies::NEW:
transformDepfile = true;
break;
} }
std::vector<cmCustomCommandGenerator> ccgs;
ccgs.emplace_back(cc, config, this, transformDepfile);
return ccgs;
} }
void cmLocalNinjaGenerator::AddCustomCommandTarget(cmCustomCommand const* cc, void cmLocalNinjaGenerator::AddCustomCommandTarget(cmCustomCommand const* cc,
......
...@@ -70,6 +70,9 @@ public: ...@@ -70,6 +70,9 @@ public:
const std::string& fileConfig, const std::string& fileConfig,
cmNinjaTargetDepends depends); cmNinjaTargetDepends depends);
std::vector<cmCustomCommandGenerator> MakeCustomCommandGenerators(
cmCustomCommand const& cc, std::string const& config) override;
void AddCustomCommandTarget(cmCustomCommand const* cc, void AddCustomCommandTarget(cmCustomCommand const* cc,
cmGeneratorTarget* target); cmGeneratorTarget* target);
void AppendCustomCommandLines(cmCustomCommandGenerator const& ccg, void AppendCustomCommandLines(cmCustomCommandGenerator const& ccg,
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment