From e7480d670b9a20bc5d8b17db5a9427fafb212e85 Mon Sep 17 00:00:00 2001 From: Brad King Date: Fri, 28 Oct 2016 11:33:02 -0400 Subject: 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 Closes: #16288 --- Source/cmCustomCommandGenerator.cxx | 45 ++++++++++++++++++------- Source/cmCustomCommandGenerator.h | 4 ++- Tests/RunCMake/pseudo_emulator_custom_command.c | 3 +- 3 files changed, 37 insertions(+), 15 deletions(-) diff --git a/Source/cmCustomCommandGenerator.cxx b/Source/cmCustomCommandGenerator.cxx index 2125f1b..8bd3a89 100644 --- a/Source/cmCustomCommandGenerator.cxx +++ b/Source/cmCustomCommandGenerator.cxx @@ -38,32 +38,44 @@ unsigned int cmCustomCommandGenerator::GetNumberOfCommands() const return static_cast(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]; cmGeneratorTarget* target = this->LG->FindGeneratorTargetToUse(argv0); - if (target && target->GetType() == cmStateEnums::EXECUTABLE) { - return target->GetProperty("CROSSCOMPILING_EMULATOR") != CM_NULLPTR; + if (target && target->GetType() == cmStateEnums::EXECUTABLE && + !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]; cmGeneratorTarget* target = this->LG->FindGeneratorTargetToUse(argv0); if (target && target->GetType() == cmStateEnums::EXECUTABLE && (target->IsImported() || + target->GetProperty("CROSSCOMPILING_EMULATOR") || !this->LG->GetMakefile()->IsOn("CMAKE_CROSSCOMPILING"))) { return target->GetLocation(this->Config); } - if (target && target->GetType() == cmStateEnums::EXECUTABLE) { - const char* emulator = target->GetProperty("CROSSCOMPILING_EMULATOR"); - if (emulator) { - return std::string(emulator); - } + return CM_NULLPTR; +} + +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 cge = this->GE->Parse(argv0); std::string exe = cge->Evaluate(this->LG, this->Config); @@ -99,13 +111,20 @@ void cmCustomCommandGenerator::AppendArguments(unsigned int c, std::string& cmd) const { unsigned int offset = 1; - if (this->UseCrossCompilingEmulator(c)) { + if (this->GetCrossCompilingEmulator(c) != CM_NULLPTR) { offset = 0; } cmCustomCommandLine const& commandLine = this->CC.GetCommandLines()[c]; for (unsigned int j = offset; j < commandLine.size(); ++j) { - std::string arg = - this->GE->Parse(commandLine[j])->Evaluate(this->LG, this->Config); + std::string arg; + 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 += " "; if (this->OldStyle) { cmd += escapeForShellOldStyle(arg); diff --git a/Source/cmCustomCommandGenerator.h b/Source/cmCustomCommandGenerator.h index 23cc596..8983c54 100644 --- a/Source/cmCustomCommandGenerator.h +++ b/Source/cmCustomCommandGenerator.h @@ -23,6 +23,9 @@ class cmCustomCommandGenerator mutable bool DependsDone; mutable std::vector Depends; + const char* GetCrossCompilingEmulator(unsigned int c) const; + const char* GetArgv0Location(unsigned int c) const; + public: cmCustomCommandGenerator(cmCustomCommand const& cc, const std::string& config, cmLocalGenerator* lg); @@ -30,7 +33,6 @@ public: cmCustomCommand const& GetCC() const { return this->CC; } unsigned int GetNumberOfCommands() const; std::string GetCommand(unsigned int c) const; - bool UseCrossCompilingEmulator(unsigned int c) const; void AppendArguments(unsigned int c, std::string& cmd) const; const char* GetComment() const; std::string GetWorkingDirectory() const; diff --git a/Tests/RunCMake/pseudo_emulator_custom_command.c b/Tests/RunCMake/pseudo_emulator_custom_command.c index 760e83c..3a94795 100644 --- a/Tests/RunCMake/pseudo_emulator_custom_command.c +++ b/Tests/RunCMake/pseudo_emulator_custom_command.c @@ -14,7 +14,8 @@ int main(int argc, const char* argv[]) { 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]; if (argc < 2) { return EXIT_FAILURE; -- cgit v0.12