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 $<TARGET_FILE:mytarget> and are evaluated during build system
generation.  This syntax allows per-configuration target output files to
be referenced in custom command lines.
This commit is contained in:
Brad King 2010-12-08 16:13:07 -05:00
parent 4749e4cb76
commit f0cdb6001b
7 changed files with 55 additions and 6 deletions

View File

@ -13,6 +13,7 @@
#define cmAddCustomCommandCommand_h #define cmAddCustomCommandCommand_h
#include "cmCommand.h" #include "cmCommand.h"
#include "cmDocumentGeneratorExpressions.h"
/** \class cmAddCustomCommandCommand /** \class cmAddCustomCommandCommand
* \brief * \brief
@ -146,8 +147,15 @@ public:
"target-level dependency will be added so that the executable target " "target-level dependency will be added so that the executable target "
"will be built before any target using this custom command. However " "will be built before any target using this custom command. However "
"this does NOT add a file-level dependency that would cause the " "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. " "The DEPENDS option specifies files on which the command depends. "
"If any dependency is an OUTPUT of another custom command in the " "If any dependency is an OUTPUT of another custom command in the "
"same directory (CMakeLists.txt file) CMake automatically brings the " "same directory (CMakeLists.txt file) CMake automatically brings the "

View File

@ -14,15 +14,23 @@
#include "cmMakefile.h" #include "cmMakefile.h"
#include "cmCustomCommand.h" #include "cmCustomCommand.h"
#include "cmLocalGenerator.h" #include "cmLocalGenerator.h"
#include "cmGeneratorExpression.h"
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
cmCustomCommandGenerator::cmCustomCommandGenerator( cmCustomCommandGenerator::cmCustomCommandGenerator(
cmCustomCommand const& cc, const char* config, cmMakefile* mf): cmCustomCommand const& cc, const char* config, cmMakefile* mf):
CC(cc), Config(config), Makefile(mf), LG(mf->GetLocalGenerator()), 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 unsigned int cmCustomCommandGenerator::GetNumberOfCommands() const
{ {
@ -39,7 +47,7 @@ std::string cmCustomCommandGenerator::GetCommand(unsigned int c) const
{ {
return target->GetLocation(this->Config); return target->GetLocation(this->Config);
} }
return argv0; return this->GE->Process(argv0);
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@ -50,7 +58,7 @@ cmCustomCommandGenerator
cmCustomCommandLine const& commandLine = this->CC.GetCommandLines()[c]; cmCustomCommandLine const& commandLine = this->CC.GetCommandLines()[c];
for(unsigned int j=1;j < commandLine.size(); ++j) for(unsigned int j=1;j < commandLine.size(); ++j)
{ {
std::string const& arg = commandLine[j]; std::string arg = this->GE->Process(commandLine[j]);
cmd += " "; cmd += " ";
if(this->OldStyle) if(this->OldStyle)
{ {

View File

@ -17,6 +17,7 @@
class cmCustomCommand; class cmCustomCommand;
class cmMakefile; class cmMakefile;
class cmLocalGenerator; class cmLocalGenerator;
class cmGeneratorExpression;
class cmCustomCommandGenerator class cmCustomCommandGenerator
{ {
@ -26,9 +27,11 @@ class cmCustomCommandGenerator
cmLocalGenerator* LG; cmLocalGenerator* LG;
bool OldStyle; bool OldStyle;
bool MakeVars; bool MakeVars;
cmGeneratorExpression* GE;
public: public:
cmCustomCommandGenerator(cmCustomCommand const& cc, const char* config, cmCustomCommandGenerator(cmCustomCommand const& cc, const char* config,
cmMakefile* mf); cmMakefile* mf);
~cmCustomCommandGenerator();
unsigned int GetNumberOfCommands() const; unsigned int GetNumberOfCommands() const;
std::string GetCommand(unsigned int c) const; std::string GetCommand(unsigned int c) const;
void AppendArguments(unsigned int c, std::string& cmd) const; void AppendArguments(unsigned int c, std::string& cmd) const;

View File

@ -17,6 +17,7 @@
#include "cmGlobalGenerator.h" #include "cmGlobalGenerator.h"
#include "cmComputeLinkInformation.h" #include "cmComputeLinkInformation.h"
#include "cmListFileCache.h" #include "cmListFileCache.h"
#include "cmGeneratorExpression.h"
#include <cmsys/RegularExpression.hxx> #include <cmsys/RegularExpression.hxx>
#include <map> #include <map>
#include <set> #include <set>
@ -1402,6 +1403,7 @@ cmTargetTraceDependencies
{ {
// Transform command names that reference targets built in this // Transform command names that reference targets built in this
// project to corresponding target-level dependencies. // project to corresponding target-level dependencies.
cmGeneratorExpression ge(this->Makefile, 0, cc.GetBacktrace(), true);
for(cmCustomCommandLines::const_iterator cit = cc.GetCommandLines().begin(); for(cmCustomCommandLines::const_iterator cit = cc.GetCommandLines().begin();
cit != cc.GetCommandLines().end(); ++cit) cit != cc.GetCommandLines().end(); ++cit)
{ {
@ -1418,6 +1420,21 @@ cmTargetTraceDependencies
this->Target->AddUtility(command.c_str()); 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<cmTarget*> targets = ge.GetTargets();
for(std::set<cmTarget*>::iterator ti = targets.begin();
ti != targets.end(); ++ti)
{
this->Target->AddUtility((*ti)->GetName());
} }
// Queue the custom command dependencies. // Queue the custom command dependencies.

View File

@ -423,3 +423,15 @@ ADD_CUSTOM_TARGET(DifferentName ALL
) )
# #
# </SameNameTest> # </SameNameTest>
# 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=$<TARGET_FILE:perconfig>" "config=$<CONFIGURATION>"
DEPENDS perconfig.out)

View File

@ -31,3 +31,4 @@ SET(PerConfig_COMMAND
-P ${PerConfig_SOURCE_DIR}/perconfig.cmake -P ${PerConfig_SOURCE_DIR}/perconfig.cmake
) )
SET(PerConfig_COMMAND "${PerConfig_COMMAND}" PARENT_SCOPE) SET(PerConfig_COMMAND "${PerConfig_COMMAND}" PARENT_SCOPE)
SET(PerConfig_DEPENDS ${PerConfig_SOURCE_DIR}/perconfig.cmake perconfig pcStatic pcShared)

View File

@ -10,7 +10,7 @@ foreach(v
pcShared_linker_file pcShared_linker_file
pcShared_soname_file pcShared_soname_file
) )
message("${v}=${${v}}") message(STATUS "${v}=${${v}}")
endforeach() endforeach()
# Verify that file names match as expected. # Verify that file names match as expected.