cmGeneratorTarget: Refactor custom command dependency evaluation

Previously we only used cmCustomCommandGenerator to evaluate generator
expressions for dependencies.  Use it for command lines too.  It also
collects target references for us, with backtraces.
This commit is contained in:
Brad King
2020-10-27 11:27:51 -04:00
parent c404f64289
commit 3e36d5e846
3 changed files with 21 additions and 64 deletions

View File

@@ -24,9 +24,7 @@
#include "cmAlgorithms.h"
#include "cmComputeLinkInformation.h"
#include "cmCustomCommand.h"
#include "cmCustomCommandGenerator.h"
#include "cmCustomCommandLines.h"
#include "cmFileTimes.h"
#include "cmGeneratedFileStream.h"
#include "cmGeneratorExpression.h"
@@ -2892,9 +2890,6 @@ private:
bool IsUtility(std::string const& dep);
void CheckCustomCommand(cmCustomCommand const& cc);
void CheckCustomCommands(const std::vector<cmCustomCommand>& commands);
void FollowCommandDepends(cmCustomCommand const& cc,
const std::string& config,
std::set<std::string>& emitted);
};
cmTargetTraceDependencies::cmTargetTraceDependencies(cmGeneratorTarget* target)
@@ -3081,71 +3076,27 @@ bool cmTargetTraceDependencies::IsUtility(std::string const& dep)
void cmTargetTraceDependencies::CheckCustomCommand(cmCustomCommand const& cc)
{
// Transform command names that reference targets built in this
// project to corresponding target-level dependencies.
cmGeneratorExpression ge(cc.GetBacktrace());
// Collect dependencies referenced by all configurations.
std::set<std::string> depends;
for (std::string const& config :
this->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig)) {
cmCustomCommandGenerator ccg(cc, config, this->LocalGenerator);
// Add target-level dependencies referenced by generator expressions.
std::set<cmGeneratorTarget*> targets;
for (cmCustomCommandLine const& cCmdLine : cc.GetCommandLines()) {
std::string const& command = cCmdLine.front();
// Check for a target with this name.
if (cmGeneratorTarget* t =
this->LocalGenerator->FindGeneratorTargetToUse(command)) {
if (t->GetType() == cmStateEnums::EXECUTABLE) {
// The command refers to an executable target built in
// this project. Add the target-level dependency to make
// sure the executable is up to date before this custom
// command possibly runs.
this->GeneratorTarget->Target->AddUtility(command, true);
}
// Collect target-level dependencies referenced in command lines.
for (auto const& util : ccg.GetUtilities()) {
this->GeneratorTarget->Target->AddUtility(util);
}
// Check for target references in generator expressions.
std::vector<std::string> const& configs =
this->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig);
for (std::string const& c : configs) {
for (std::string const& cl : cCmdLine) {
const std::unique_ptr<cmCompiledGeneratorExpression> cge =
ge.Parse(cl);
cge->SetQuiet(true);
cge->Evaluate(this->GeneratorTarget->GetLocalGenerator(), c);
std::set<cmGeneratorTarget*> geTargets = cge->GetTargets();
targets.insert(geTargets.begin(), geTargets.end());
}
}
// Collect file-level dependencies referenced in DEPENDS.
depends.insert(ccg.GetDepends().begin(), ccg.GetDepends().end());
}
for (cmGeneratorTarget* target : targets) {
this->GeneratorTarget->Target->AddUtility(target->GetName(), true);
}
// Queue the custom command dependencies.
std::set<std::string> emitted;
std::vector<std::string> const& configs =
this->Makefile->GetGeneratorConfigs(cmMakefile::IncludeEmptyConfig);
for (std::string const& conf : configs) {
this->FollowCommandDepends(cc, conf, emitted);
}
}
void cmTargetTraceDependencies::FollowCommandDepends(
cmCustomCommand const& cc, const std::string& config,
std::set<std::string>& emitted)
{
cmCustomCommandGenerator ccg(cc, config,
this->GeneratorTarget->LocalGenerator);
const std::vector<std::string>& depends = ccg.GetDepends();
// Queue file-level dependencies.
for (std::string const& dep : depends) {
if (emitted.insert(dep).second) {
if (!this->IsUtility(dep)) {
// The dependency does not name a target and may be a file we
// know how to generate. Queue it.
this->FollowName(dep);
}
if (!this->IsUtility(dep)) {
// The dependency does not name a target and may be a file we
// know how to generate. Queue it.
this->FollowName(dep);
}
}
}

View File

@@ -623,6 +623,11 @@ void cmTarget::AddUtility(std::string const& name, bool cross, cmMakefile* mf)
{ name, cross }, mf ? mf->GetBacktrace() : cmListFileBacktrace()));
}
void cmTarget::AddUtility(BT<std::pair<std::string, bool>> util)
{
impl->Utilities.emplace(std::move(util));
}
std::set<BT<std::pair<std::string, bool>>> const& cmTarget::GetUtilities()
const
{

View File

@@ -164,6 +164,7 @@ public:
*/
void AddUtility(std::string const& name, bool cross,
cmMakefile* mf = nullptr);
void AddUtility(BT<std::pair<std::string, bool>> util);
//! Get the utilities used by this target
std::set<BT<std::pair<std::string, bool>>> const& GetUtilities() const;