Ninja Multi-Config: Fix custom command target dependencies in cross-configs

Generator expressions in a non-cross custom command's `COMMAND`
arguments are evaluated in the command config.  Target-level
dependencies implied by `TARGET_FILE` must therefore be cross
dependencies.  This is important to generate proper target-level
dependencies on the cross-config build statements for the target to
which the custom command is attached.

Fixes: #22855
This commit is contained in:
Brad King
2021-11-04 12:02:10 -04:00
parent a883363935
commit 95f44e00cd
6 changed files with 34 additions and 4 deletions

View File

@@ -91,7 +91,7 @@ std::string EvaluateSplitConfigGenex(
// Record targets referenced by the genex.
if (utils) {
// FIXME: What is the proper condition for a cross-dependency?
// Use a cross-dependency if we referenced the command config.
bool const cross = !useOutputConfig;
for (cmGeneratorTarget* gt : cge->GetTargets()) {
utils->emplace(BT<std::pair<std::string, bool>>(
@@ -176,6 +176,8 @@ cmCustomCommandGenerator::cmCustomCommandGenerator(
cmGeneratorTarget const* target{ lg->FindGeneratorTargetToUse(
this->Target) };
bool const distinctConfigs = this->OutputConfig != this->CommandConfig;
const cmCustomCommandLines& cmdlines = this->CC->GetCommandLines();
for (cmCustomCommandLine const& cmdline : cmdlines) {
cmCustomCommandLine argv;
@@ -191,8 +193,10 @@ cmCustomCommandGenerator::cmCustomCommandGenerator(
argv.push_back(std::move(parsed_arg));
}
// For remaining arguments, we default to the OUTPUT_CONFIG.
useOutputConfig = true;
if (distinctConfigs) {
// For remaining arguments, we default to the OUTPUT_CONFIG.
useOutputConfig = true;
}
}
if (!argv.empty()) {
@@ -200,7 +204,7 @@ cmCustomCommandGenerator::cmCustomCommandGenerator(
// collect the target to add a target-level dependency on it.
cmGeneratorTarget* gt = this->LG->FindGeneratorTargetToUse(argv.front());
if (gt && gt->GetType() == cmStateEnums::EXECUTABLE) {
// FIXME: What is the proper condition for a cross-dependency?
// GetArgv0Location uses the command config, so use a cross-dependency.
bool const cross = true;
this->Utilities.emplace(BT<std::pair<std::string, bool>>(
{ gt->GetName(), cross }, cc.GetBacktrace()));