From f0cdb6001b3e915fc0d9c1120165d49725440bbd Mon Sep 17 00:00:00 2001 From: Brad King Date: Wed, 8 Dec 2010 16:13:07 -0500 Subject: Introduce "generator expression" syntax to custom commands (#11209) Evaluate in the COMMAND arguments of custom commands the generator expression syntax introduced in commit d2e1f2b4 (Introduce "generator expressions" to add_test, 2009-08-11). These expressions have a syntax like $ and are evaluated during build system generation. This syntax allows per-configuration target output files to be referenced in custom command lines. --- Source/cmAddCustomCommandCommand.h | 12 ++++++++++-- Source/cmCustomCommandGenerator.cxx | 14 +++++++++++--- Source/cmCustomCommandGenerator.h | 3 +++ Source/cmTarget.cxx | 17 +++++++++++++++++ Tests/CustomCommand/CMakeLists.txt | 12 ++++++++++++ Tests/PerConfig/CMakeLists.txt | 1 + Tests/PerConfig/perconfig.cmake | 2 +- 7 files changed, 55 insertions(+), 6 deletions(-) diff --git a/Source/cmAddCustomCommandCommand.h b/Source/cmAddCustomCommandCommand.h index 6c5e1af..490e043 100644 --- a/Source/cmAddCustomCommandCommand.h +++ b/Source/cmAddCustomCommandCommand.h @@ -13,6 +13,7 @@ #define cmAddCustomCommandCommand_h #include "cmCommand.h" +#include "cmDocumentGeneratorExpressions.h" /** \class cmAddCustomCommandCommand * \brief @@ -146,8 +147,15 @@ public: "target-level dependency will be added so that the executable target " "will be built before any target using this custom command. However " "this does NOT add a file-level dependency that would cause the " - "custom command to re-run whenever the executable is recompiled.\n" - + "custom command to re-run whenever the executable is recompiled." + "\n" + "Arguments to COMMAND may use \"generator expressions\" with the " + "syntax \"$<...>\". " + CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS + "References to target names in generator expressions imply " + "target-level dependencies, but NOT file-level dependencies. " + "List target names with the DEPENDS option to add file dependencies." + "\n" "The DEPENDS option specifies files on which the command depends. " "If any dependency is an OUTPUT of another custom command in the " "same directory (CMakeLists.txt file) CMake automatically brings the " diff --git a/Source/cmCustomCommandGenerator.cxx b/Source/cmCustomCommandGenerator.cxx index 2a3b553..a650129 100644 --- a/Source/cmCustomCommandGenerator.cxx +++ b/Source/cmCustomCommandGenerator.cxx @@ -14,16 +14,24 @@ #include "cmMakefile.h" #include "cmCustomCommand.h" #include "cmLocalGenerator.h" +#include "cmGeneratorExpression.h" //---------------------------------------------------------------------------- cmCustomCommandGenerator::cmCustomCommandGenerator( cmCustomCommand const& cc, const char* config, cmMakefile* mf): CC(cc), Config(config), Makefile(mf), LG(mf->GetLocalGenerator()), - OldStyle(cc.GetEscapeOldStyle()), MakeVars(cc.GetEscapeAllowMakeVars()) + OldStyle(cc.GetEscapeOldStyle()), MakeVars(cc.GetEscapeAllowMakeVars()), + GE(new cmGeneratorExpression(mf, config, cc.GetBacktrace())) { } //---------------------------------------------------------------------------- +cmCustomCommandGenerator::~cmCustomCommandGenerator() +{ + delete this->GE; +} + +//---------------------------------------------------------------------------- unsigned int cmCustomCommandGenerator::GetNumberOfCommands() const { return static_cast(this->CC.GetCommandLines().size()); @@ -39,7 +47,7 @@ std::string cmCustomCommandGenerator::GetCommand(unsigned int c) const { return target->GetLocation(this->Config); } - return argv0; + return this->GE->Process(argv0); } //---------------------------------------------------------------------------- @@ -50,7 +58,7 @@ cmCustomCommandGenerator cmCustomCommandLine const& commandLine = this->CC.GetCommandLines()[c]; for(unsigned int j=1;j < commandLine.size(); ++j) { - std::string const& arg = commandLine[j]; + std::string arg = this->GE->Process(commandLine[j]); cmd += " "; if(this->OldStyle) { diff --git a/Source/cmCustomCommandGenerator.h b/Source/cmCustomCommandGenerator.h index 5417ec5..4e89f27 100644 --- a/Source/cmCustomCommandGenerator.h +++ b/Source/cmCustomCommandGenerator.h @@ -17,6 +17,7 @@ class cmCustomCommand; class cmMakefile; class cmLocalGenerator; +class cmGeneratorExpression; class cmCustomCommandGenerator { @@ -26,9 +27,11 @@ class cmCustomCommandGenerator cmLocalGenerator* LG; bool OldStyle; bool MakeVars; + cmGeneratorExpression* GE; public: cmCustomCommandGenerator(cmCustomCommand const& cc, const char* config, cmMakefile* mf); + ~cmCustomCommandGenerator(); unsigned int GetNumberOfCommands() const; std::string GetCommand(unsigned int c) const; void AppendArguments(unsigned int c, std::string& cmd) const; diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index c82c11e..40f68e4 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -17,6 +17,7 @@ #include "cmGlobalGenerator.h" #include "cmComputeLinkInformation.h" #include "cmListFileCache.h" +#include "cmGeneratorExpression.h" #include #include #include @@ -1402,6 +1403,7 @@ cmTargetTraceDependencies { // Transform command names that reference targets built in this // project to corresponding target-level dependencies. + cmGeneratorExpression ge(this->Makefile, 0, cc.GetBacktrace(), true); for(cmCustomCommandLines::const_iterator cit = cc.GetCommandLines().begin(); cit != cc.GetCommandLines().end(); ++cit) { @@ -1418,6 +1420,21 @@ cmTargetTraceDependencies this->Target->AddUtility(command.c_str()); } } + + // Check for target references in generator expressions. + for(cmCustomCommandLine::const_iterator cli = cit->begin(); + cli != cit->end(); ++cli) + { + ge.Process(*cli); + } + } + + // Add target-level dependencies referenced by generator expressions. + std::set targets = ge.GetTargets(); + for(std::set::iterator ti = targets.begin(); + ti != targets.end(); ++ti) + { + this->Target->AddUtility((*ti)->GetName()); } // Queue the custom command dependencies. diff --git a/Tests/CustomCommand/CMakeLists.txt b/Tests/CustomCommand/CMakeLists.txt index 746c9a7..450323e 100644 --- a/Tests/CustomCommand/CMakeLists.txt +++ b/Tests/CustomCommand/CMakeLists.txt @@ -423,3 +423,15 @@ ADD_CUSTOM_TARGET(DifferentName ALL ) # # + +# Per-config target name and generator expressions. +ADD_SUBDIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/../PerConfig PerConfig) +ADD_CUSTOM_COMMAND( + OUTPUT perconfig.out + COMMAND ${PerConfig_COMMAND} + DEPENDS ${PerConfig_DEPENDS} + VERBATIM + ) +ADD_CUSTOM_TARGET(perconfig_target ALL + COMMAND ${CMAKE_COMMAND} -E echo "perconfig=$" "config=$" + DEPENDS perconfig.out) diff --git a/Tests/PerConfig/CMakeLists.txt b/Tests/PerConfig/CMakeLists.txt index a45abc8..7b7bf2e 100644 --- a/Tests/PerConfig/CMakeLists.txt +++ b/Tests/PerConfig/CMakeLists.txt @@ -31,3 +31,4 @@ SET(PerConfig_COMMAND -P ${PerConfig_SOURCE_DIR}/perconfig.cmake ) SET(PerConfig_COMMAND "${PerConfig_COMMAND}" PARENT_SCOPE) +SET(PerConfig_DEPENDS ${PerConfig_SOURCE_DIR}/perconfig.cmake perconfig pcStatic pcShared) diff --git a/Tests/PerConfig/perconfig.cmake b/Tests/PerConfig/perconfig.cmake index 4a93acc..6a710ca 100644 --- a/Tests/PerConfig/perconfig.cmake +++ b/Tests/PerConfig/perconfig.cmake @@ -10,7 +10,7 @@ foreach(v pcShared_linker_file pcShared_soname_file ) - message("${v}=${${v}}") + message(STATUS "${v}=${${v}}") endforeach() # Verify that file names match as expected. -- cgit v0.12