Fix custom command target substitution with CROSSCOMPILING_EMULATOR

In commit v3.6.0-rc1~88^2 (CustomCommandGenerator: Add support for
CROSSCOMPILING_EMULATOR, 2016-05-04) logic was introduced to substitute
a target's `CROSSCOMPILING_EMULATOR` for argv0 in a custom command.
However, it broke the case when the argv0 was a target name and now
fails to expand the target name to its location at the same time as
inserting the emulator.  Fix the latter case.

Inspired-by: Brian Maher <brian@brimworks.com>
Closes: #16288
This commit is contained in:
Brad King
2016-10-28 11:33:02 -04:00
parent ee0f2d23fc
commit e7480d670b
3 changed files with 37 additions and 15 deletions
+32 -13
View File
@@ -38,32 +38,44 @@ unsigned int cmCustomCommandGenerator::GetNumberOfCommands() const
return static_cast<unsigned int>(this->CC.GetCommandLines().size()); return static_cast<unsigned int>(this->CC.GetCommandLines().size());
} }
bool cmCustomCommandGenerator::UseCrossCompilingEmulator(unsigned int c) const const char* cmCustomCommandGenerator::GetCrossCompilingEmulator(
unsigned int c) const
{ {
if (!this->LG->GetMakefile()->IsOn("CMAKE_CROSSCOMPILING")) {
return CM_NULLPTR;
}
std::string const& argv0 = this->CC.GetCommandLines()[c][0]; std::string const& argv0 = this->CC.GetCommandLines()[c][0];
cmGeneratorTarget* target = this->LG->FindGeneratorTargetToUse(argv0); cmGeneratorTarget* target = this->LG->FindGeneratorTargetToUse(argv0);
if (target && target->GetType() == cmStateEnums::EXECUTABLE) { if (target && target->GetType() == cmStateEnums::EXECUTABLE &&
return target->GetProperty("CROSSCOMPILING_EMULATOR") != CM_NULLPTR; !target->IsImported()) {
return target->GetProperty("CROSSCOMPILING_EMULATOR");
} }
return false; return CM_NULLPTR;
} }
std::string cmCustomCommandGenerator::GetCommand(unsigned int c) const const char* cmCustomCommandGenerator::GetArgv0Location(unsigned int c) const
{ {
std::string const& argv0 = this->CC.GetCommandLines()[c][0]; std::string const& argv0 = this->CC.GetCommandLines()[c][0];
cmGeneratorTarget* target = this->LG->FindGeneratorTargetToUse(argv0); cmGeneratorTarget* target = this->LG->FindGeneratorTargetToUse(argv0);
if (target && target->GetType() == cmStateEnums::EXECUTABLE && if (target && target->GetType() == cmStateEnums::EXECUTABLE &&
(target->IsImported() || (target->IsImported() ||
target->GetProperty("CROSSCOMPILING_EMULATOR") ||
!this->LG->GetMakefile()->IsOn("CMAKE_CROSSCOMPILING"))) { !this->LG->GetMakefile()->IsOn("CMAKE_CROSSCOMPILING"))) {
return target->GetLocation(this->Config); return target->GetLocation(this->Config);
} }
if (target && target->GetType() == cmStateEnums::EXECUTABLE) { return CM_NULLPTR;
const char* emulator = target->GetProperty("CROSSCOMPILING_EMULATOR"); }
if (emulator) {
return std::string(emulator); std::string cmCustomCommandGenerator::GetCommand(unsigned int c) const
} {
if (const char* emulator = this->GetCrossCompilingEmulator(c)) {
return std::string(emulator);
}
if (const char* location = this->GetArgv0Location(c)) {
return std::string(location);
} }
std::string const& argv0 = this->CC.GetCommandLines()[c][0];
CM_AUTO_PTR<cmCompiledGeneratorExpression> cge = this->GE->Parse(argv0); CM_AUTO_PTR<cmCompiledGeneratorExpression> cge = this->GE->Parse(argv0);
std::string exe = cge->Evaluate(this->LG, this->Config); std::string exe = cge->Evaluate(this->LG, this->Config);
@@ -99,13 +111,20 @@ void cmCustomCommandGenerator::AppendArguments(unsigned int c,
std::string& cmd) const std::string& cmd) const
{ {
unsigned int offset = 1; unsigned int offset = 1;
if (this->UseCrossCompilingEmulator(c)) { if (this->GetCrossCompilingEmulator(c) != CM_NULLPTR) {
offset = 0; offset = 0;
} }
cmCustomCommandLine const& commandLine = this->CC.GetCommandLines()[c]; cmCustomCommandLine const& commandLine = this->CC.GetCommandLines()[c];
for (unsigned int j = offset; j < commandLine.size(); ++j) { for (unsigned int j = offset; j < commandLine.size(); ++j) {
std::string arg = std::string arg;
this->GE->Parse(commandLine[j])->Evaluate(this->LG, this->Config); if (const char* location =
j == 0 ? this->GetArgv0Location(c) : CM_NULLPTR) {
// GetCommand returned the emulator instead of the argv0 location,
// so transform the latter now.
arg = location;
} else {
arg = this->GE->Parse(commandLine[j])->Evaluate(this->LG, this->Config);
}
cmd += " "; cmd += " ";
if (this->OldStyle) { if (this->OldStyle) {
cmd += escapeForShellOldStyle(arg); cmd += escapeForShellOldStyle(arg);
+3 -1
View File
@@ -23,6 +23,9 @@ class cmCustomCommandGenerator
mutable bool DependsDone; mutable bool DependsDone;
mutable std::vector<std::string> Depends; mutable std::vector<std::string> Depends;
const char* GetCrossCompilingEmulator(unsigned int c) const;
const char* GetArgv0Location(unsigned int c) const;
public: public:
cmCustomCommandGenerator(cmCustomCommand const& cc, cmCustomCommandGenerator(cmCustomCommand const& cc,
const std::string& config, cmLocalGenerator* lg); const std::string& config, cmLocalGenerator* lg);
@@ -30,7 +33,6 @@ public:
cmCustomCommand const& GetCC() const { return this->CC; } cmCustomCommand const& GetCC() const { return this->CC; }
unsigned int GetNumberOfCommands() const; unsigned int GetNumberOfCommands() const;
std::string GetCommand(unsigned int c) const; std::string GetCommand(unsigned int c) const;
bool UseCrossCompilingEmulator(unsigned int c) const;
void AppendArguments(unsigned int c, std::string& cmd) const; void AppendArguments(unsigned int c, std::string& cmd) const;
const char* GetComment() const; const char* GetComment() const;
std::string GetWorkingDirectory() const; std::string GetWorkingDirectory() const;
@@ -14,7 +14,8 @@
int main(int argc, const char* argv[]) int main(int argc, const char* argv[])
{ {
const char* substring_failure = "generated_exe_emulator_unexpected"; const char* substring_failure = "generated_exe_emulator_unexpected";
const char* substring_success = "generated_exe_emulator_expected"; // Require a slash to make sure it is a path and not a target name.
const char* substring_success = "/generated_exe_emulator_expected";
const char* str = argv[1]; const char* str = argv[1];
if (argc < 2) { if (argc < 2) {
return EXIT_FAILURE; return EXIT_FAILURE;