summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2010-12-17 15:07:19 (GMT)
committerBrad King <brad.king@kitware.com>2010-12-17 15:07:19 (GMT)
commit853de2ed1288dbf891778db30653927d0e223a44 (patch)
tree93a53e32c5d60af84c66c76511c103ab9ee52db1
parentd89e238e6c4b22fe3fde0f8e1e7987fb05f13aeb (diff)
parent45e1953c4037d4492668651ae3bbfd6a4a875bc1 (diff)
downloadCMake-853de2ed1288dbf891778db30653927d0e223a44.zip
CMake-853de2ed1288dbf891778db30653927d0e223a44.tar.gz
CMake-853de2ed1288dbf891778db30653927d0e223a44.tar.bz2
Merge branch 'custom-command-generator-expressions' into resolve/tests-if-CYGWIN
The tests-if-CYGWIN topic made a change to Tests/Testing/CMakeLists.txt in code that the custom-command-generator-expressions topic moved to the Tests/PerConfig/CMakeLists.txt file. Make the same change to the same content in the new file. (Only a small part of the file moved so rename detection did not do this automatically.)
-rw-r--r--Source/CMakeLists.txt3
-rw-r--r--Source/cmAddTestCommand.h15
-rw-r--r--Source/cmCustomCommand.cxx27
-rw-r--r--Source/cmCustomCommand.h11
-rw-r--r--Source/cmCustomCommandGenerator.cxx64
-rw-r--r--Source/cmCustomCommandGenerator.h37
-rw-r--r--Source/cmDocumentGeneratorExpressions.h30
-rw-r--r--Source/cmGlobalGenerator.cxx2
-rw-r--r--Source/cmGlobalXCodeGenerator.cxx43
-rw-r--r--Source/cmLocalGenerator.cxx50
-rw-r--r--Source/cmLocalGenerator.h9
-rw-r--r--Source/cmLocalUnixMakefileGenerator3.cxx36
-rw-r--r--Source/cmLocalVisualStudio6Generator.cxx27
-rw-r--r--Source/cmLocalVisualStudio7Generator.cxx23
-rw-r--r--Source/cmLocalVisualStudioGenerator.cxx47
-rw-r--r--Source/cmLocalVisualStudioGenerator.h6
-rw-r--r--Source/cmMakefile.cxx5
-rw-r--r--Source/cmTarget.cxx8
-rw-r--r--Source/cmVisualStudio10TargetGenerator.cxx26
-rw-r--r--Tests/CustomCommand/CMakeLists.txt5
-rw-r--r--Tests/ExportImport/Import/A/CMakeLists.txt50
-rw-r--r--Tests/PerConfig/CMakeLists.txt33
-rw-r--r--Tests/PerConfig/pcShared.c (renamed from Tests/Testing/pcShared.c)0
-rw-r--r--Tests/PerConfig/pcShared.h (renamed from Tests/Testing/pcShared.h)0
-rw-r--r--Tests/PerConfig/pcStatic.c (renamed from Tests/Testing/pcStatic.c)0
-rw-r--r--Tests/PerConfig/perconfig.c (renamed from Tests/Testing/perconfig.c)0
-rw-r--r--Tests/PerConfig/perconfig.cmake (renamed from Tests/Testing/driver.cmake)0
-rw-r--r--Tests/Testing/CMakeLists.txt34
-rwxr-xr-xbootstrap1
29 files changed, 348 insertions, 244 deletions
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index 718e52e..f183eb4 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -131,6 +131,8 @@ SET(SRCS
cmComputeTargetDepends.cxx
cmCustomCommand.cxx
cmCustomCommand.h
+ cmCustomCommandGenerator.cxx
+ cmCustomCommandGenerator.h
cmDefinitions.cxx
cmDefinitions.h
cmDepends.cxx
@@ -156,6 +158,7 @@ SET(SRCS
cmDocumentationFormatterText.cxx
cmDocumentationFormatterUsage.cxx
cmDocumentationSection.cxx
+ cmDocumentGeneratorExpressions.h
cmDocumentVariables.cxx
cmDynamicLoader.cxx
cmDynamicLoader.h
diff --git a/Source/cmAddTestCommand.h b/Source/cmAddTestCommand.h
index 79fb481..1cc86c4 100644
--- a/Source/cmAddTestCommand.h
+++ b/Source/cmAddTestCommand.h
@@ -13,6 +13,7 @@
#define cmAddTestCommand_h
#include "cmCommand.h"
+#include "cmDocumentGeneratorExpressions.h"
/** \class cmAddTestCommand
* \brief Add a test to the lists of tests to run.
@@ -77,19 +78,7 @@ public:
"\n"
"Arguments after COMMAND may use \"generator expressions\" with the "
"syntax \"$<...>\". "
- "These expressions are evaluted during build system generation and "
- "produce information specific to each generated build configuration. "
- "Valid expressions are:\n"
- " $<CONFIGURATION> = configuration name\n"
- " $<TARGET_FILE:tgt> = main file (.exe, .so.1.2, .a)\n"
- " $<TARGET_LINKER_FILE:tgt> = file used to link (.a, .lib, .so)\n"
- " $<TARGET_SONAME_FILE:tgt> = file with soname (.so.3)\n"
- "where \"tgt\" is the name of a target. "
- "Target file expressions produce a full path, but _DIR and _NAME "
- "versions can produce the directory and file name components:\n"
- " $<TARGET_FILE_DIR:tgt>/$<TARGET_FILE_NAME:tgt>\n"
- " $<TARGET_LINKER_FILE_DIR:tgt>/$<TARGET_LINKER_FILE_NAME:tgt>\n"
- " $<TARGET_SONAME_FILE_DIR:tgt>/$<TARGET_SONAME_FILE_NAME:tgt>\n"
+ CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS
"Example usage:\n"
" add_test(NAME mytest\n"
" COMMAND testDriver --config $<CONFIGURATION>\n"
diff --git a/Source/cmCustomCommand.cxx b/Source/cmCustomCommand.cxx
index 5db88fa..bd860ee 100644
--- a/Source/cmCustomCommand.cxx
+++ b/Source/cmCustomCommand.cxx
@@ -11,6 +11,8 @@
============================================================================*/
#include "cmCustomCommand.h"
+#include "cmMakefile.h"
+
//----------------------------------------------------------------------------
cmCustomCommand::cmCustomCommand()
{
@@ -28,12 +30,14 @@ cmCustomCommand::cmCustomCommand(const cmCustomCommand& r):
Comment(r.Comment),
WorkingDirectory(r.WorkingDirectory),
EscapeAllowMakeVars(r.EscapeAllowMakeVars),
- EscapeOldStyle(r.EscapeOldStyle)
+ EscapeOldStyle(r.EscapeOldStyle),
+ Backtrace(new cmListFileBacktrace(*r.Backtrace))
{
}
//----------------------------------------------------------------------------
-cmCustomCommand::cmCustomCommand(const std::vector<std::string>& outputs,
+cmCustomCommand::cmCustomCommand(cmMakefile* mf,
+ const std::vector<std::string>& outputs,
const std::vector<std::string>& depends,
const cmCustomCommandLines& commandLines,
const char* comment,
@@ -45,10 +49,21 @@ cmCustomCommand::cmCustomCommand(const std::vector<std::string>& outputs,
Comment(comment?comment:""),
WorkingDirectory(workingDirectory?workingDirectory:""),
EscapeAllowMakeVars(false),
- EscapeOldStyle(true)
+ EscapeOldStyle(true),
+ Backtrace(new cmListFileBacktrace)
{
this->EscapeOldStyle = true;
this->EscapeAllowMakeVars = false;
+ if(mf)
+ {
+ mf->GetBacktrace(*this->Backtrace);
+ }
+}
+
+//----------------------------------------------------------------------------
+cmCustomCommand::~cmCustomCommand()
+{
+ delete this->Backtrace;
}
//----------------------------------------------------------------------------
@@ -131,6 +146,12 @@ void cmCustomCommand::SetEscapeAllowMakeVars(bool b)
}
//----------------------------------------------------------------------------
+cmListFileBacktrace const& cmCustomCommand::GetBacktrace() const
+{
+ return *this->Backtrace;
+}
+
+//----------------------------------------------------------------------------
cmCustomCommand::ImplicitDependsList const&
cmCustomCommand::GetImplicitDepends() const
{
diff --git a/Source/cmCustomCommand.h b/Source/cmCustomCommand.h
index c9adddf..dd92e34 100644
--- a/Source/cmCustomCommand.h
+++ b/Source/cmCustomCommand.h
@@ -13,6 +13,8 @@
#define cmCustomCommand_h
#include "cmStandardIncludes.h"
+class cmMakefile;
+class cmListFileBacktrace;
/** \class cmCustomCommand
* \brief A class to encapsulate a custom command
@@ -27,12 +29,15 @@ public:
cmCustomCommand(const cmCustomCommand& r);
/** Main constructor specifies all information for the command. */
- cmCustomCommand(const std::vector<std::string>& outputs,
+ cmCustomCommand(cmMakefile* mf,
+ const std::vector<std::string>& outputs,
const std::vector<std::string>& depends,
const cmCustomCommandLines& commandLines,
const char* comment,
const char* workingDirectory);
+ ~cmCustomCommand();
+
/** Get the output file produced by the command. */
const std::vector<std::string>& GetOutputs() const;
@@ -63,6 +68,9 @@ public:
bool GetEscapeAllowMakeVars() const;
void SetEscapeAllowMakeVars(bool b);
+ /** Backtrace of the command that created this custom command. */
+ cmListFileBacktrace const& GetBacktrace() const;
+
typedef std::pair<cmStdString, cmStdString> ImplicitDependsPair;
class ImplicitDependsList: public std::vector<ImplicitDependsPair> {};
void SetImplicitDepends(ImplicitDependsList const&);
@@ -78,6 +86,7 @@ private:
std::string WorkingDirectory;
bool EscapeAllowMakeVars;
bool EscapeOldStyle;
+ cmListFileBacktrace* Backtrace;
ImplicitDependsList ImplicitDepends;
};
diff --git a/Source/cmCustomCommandGenerator.cxx b/Source/cmCustomCommandGenerator.cxx
new file mode 100644
index 0000000..2a3b553
--- /dev/null
+++ b/Source/cmCustomCommandGenerator.cxx
@@ -0,0 +1,64 @@
+/*============================================================================
+ CMake - Cross Platform Makefile Generator
+ Copyright 2000-2010 Kitware, Inc., Insight Software Consortium
+
+ Distributed under the OSI-approved BSD License (the "License");
+ see accompanying file Copyright.txt for details.
+
+ This software is distributed WITHOUT ANY WARRANTY; without even the
+ implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the License for more information.
+============================================================================*/
+#include "cmCustomCommandGenerator.h"
+
+#include "cmMakefile.h"
+#include "cmCustomCommand.h"
+#include "cmLocalGenerator.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())
+{
+}
+
+//----------------------------------------------------------------------------
+unsigned int cmCustomCommandGenerator::GetNumberOfCommands() const
+{
+ return static_cast<unsigned int>(this->CC.GetCommandLines().size());
+}
+
+//----------------------------------------------------------------------------
+std::string cmCustomCommandGenerator::GetCommand(unsigned int c) const
+{
+ std::string const& argv0 = this->CC.GetCommandLines()[c][0];
+ cmTarget* target = this->Makefile->FindTargetToUse(argv0.c_str());
+ if(target && target->GetType() == cmTarget::EXECUTABLE &&
+ (target->IsImported() || !this->Makefile->IsOn("CMAKE_CROSSCOMPILING")))
+ {
+ return target->GetLocation(this->Config);
+ }
+ return argv0;
+}
+
+//----------------------------------------------------------------------------
+void
+cmCustomCommandGenerator
+::AppendArguments(unsigned int c, std::string& cmd) const
+{
+ cmCustomCommandLine const& commandLine = this->CC.GetCommandLines()[c];
+ for(unsigned int j=1;j < commandLine.size(); ++j)
+ {
+ std::string const& arg = commandLine[j];
+ cmd += " ";
+ if(this->OldStyle)
+ {
+ cmd += this->LG->EscapeForShellOldStyle(arg.c_str());
+ }
+ else
+ {
+ cmd += this->LG->EscapeForShell(arg.c_str(), this->MakeVars);
+ }
+ }
+}
diff --git a/Source/cmCustomCommandGenerator.h b/Source/cmCustomCommandGenerator.h
new file mode 100644
index 0000000..5417ec5
--- /dev/null
+++ b/Source/cmCustomCommandGenerator.h
@@ -0,0 +1,37 @@
+/*============================================================================
+ CMake - Cross Platform Makefile Generator
+ Copyright 2000-2010 Kitware, Inc., Insight Software Consortium
+
+ Distributed under the OSI-approved BSD License (the "License");
+ see accompanying file Copyright.txt for details.
+
+ This software is distributed WITHOUT ANY WARRANTY; without even the
+ implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the License for more information.
+============================================================================*/
+#ifndef cmCustomCommandGenerator_h
+#define cmCustomCommandGenerator_h
+
+#include "cmStandardIncludes.h"
+
+class cmCustomCommand;
+class cmMakefile;
+class cmLocalGenerator;
+
+class cmCustomCommandGenerator
+{
+ cmCustomCommand const& CC;
+ const char* Config;
+ cmMakefile* Makefile;
+ cmLocalGenerator* LG;
+ bool OldStyle;
+ bool MakeVars;
+public:
+ cmCustomCommandGenerator(cmCustomCommand const& cc, const char* config,
+ cmMakefile* mf);
+ unsigned int GetNumberOfCommands() const;
+ std::string GetCommand(unsigned int c) const;
+ void AppendArguments(unsigned int c, std::string& cmd) const;
+};
+
+#endif
diff --git a/Source/cmDocumentGeneratorExpressions.h b/Source/cmDocumentGeneratorExpressions.h
new file mode 100644
index 0000000..5359013
--- /dev/null
+++ b/Source/cmDocumentGeneratorExpressions.h
@@ -0,0 +1,30 @@
+/*============================================================================
+ CMake - Cross Platform Makefile Generator
+ Copyright 2000-2010 Kitware, Inc., Insight Software Consortium
+
+ Distributed under the OSI-approved BSD License (the "License");
+ see accompanying file Copyright.txt for details.
+
+ This software is distributed WITHOUT ANY WARRANTY; without even the
+ implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ See the License for more information.
+============================================================================*/
+#ifndef cmDocumentGeneratorExpressions_h
+#define cmDocumentGeneratorExpressions_h
+
+#define CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS \
+ "Generator expressions are evaluted during build system generation " \
+ "to produce information specific to each build configuration. " \
+ "Valid expressions are:\n" \
+ " $<CONFIGURATION> = configuration name\n" \
+ " $<TARGET_FILE:tgt> = main file (.exe, .so.1.2, .a)\n" \
+ " $<TARGET_LINKER_FILE:tgt> = file used to link (.a, .lib, .so)\n" \
+ " $<TARGET_SONAME_FILE:tgt> = file with soname (.so.3)\n" \
+ "where \"tgt\" is the name of a target. " \
+ "Target file expressions produce a full path, but _DIR and _NAME " \
+ "versions can produce the directory and file name components:\n" \
+ " $<TARGET_FILE_DIR:tgt>/$<TARGET_FILE_NAME:tgt>\n" \
+ " $<TARGET_LINKER_FILE_DIR:tgt>/$<TARGET_LINKER_FILE_NAME:tgt>\n" \
+ " $<TARGET_SONAME_FILE_DIR:tgt>/$<TARGET_SONAME_FILE_NAME:tgt>\n"
+
+#endif
diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx
index 15abd02..f558509 100644
--- a/Source/cmGlobalGenerator.cxx
+++ b/Source/cmGlobalGenerator.cxx
@@ -1893,7 +1893,7 @@ cmTarget cmGlobalGenerator::CreateGlobalTarget(
std::vector<std::string> no_outputs;
std::vector<std::string> no_depends;
// Store the custom command in the target.
- cmCustomCommand cc(no_outputs, no_depends, *commandLines, 0,
+ cmCustomCommand cc(0, no_outputs, no_depends, *commandLines, 0,
workingDirectory);
target.GetPostBuildCommands().push_back(cc);
target.SetProperty("EchoString", message);
diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx
index 2f7bc44..e13acda 100644
--- a/Source/cmGlobalXCodeGenerator.cxx
+++ b/Source/cmGlobalXCodeGenerator.cxx
@@ -18,6 +18,7 @@
#include "cmGeneratedFileStream.h"
#include "cmComputeLinkInformation.h"
#include "cmSourceFile.h"
+#include "cmCustomCommandGenerator.h"
#include <cmsys/auto_ptr.hxx>
@@ -1314,8 +1315,7 @@ void cmGlobalXCodeGenerator
cmCustomCommand const& cc = *i;
if(!cc.GetCommandLines().empty())
{
- bool escapeOldStyle = cc.GetEscapeOldStyle();
- bool escapeAllowMakeVars = cc.GetEscapeAllowMakeVars();
+ cmCustomCommandGenerator ccg(cc, configName, this->CurrentMakefile);
makefileStream << "\n";
const std::vector<std::string>& outputs = cc.GetOutputs();
if(!outputs.empty())
@@ -1334,11 +1334,13 @@ void cmGlobalXCodeGenerator
cc.GetDepends().begin();
d != cc.GetDepends().end(); ++d)
{
- std::string dep =
- this->CurrentLocalGenerator->GetRealDependency(d->c_str(),
- configName);
- makefileStream << "\\\n" << this
- ->ConvertToRelativeForMake(dep.c_str());
+ std::string dep;
+ if(this->CurrentLocalGenerator
+ ->GetRealDependency(d->c_str(), configName, dep))
+ {
+ makefileStream << "\\\n" <<
+ this->ConvertToRelativeForMake(dep.c_str());
+ }
}
makefileStream << "\n";
@@ -1346,20 +1348,15 @@ void cmGlobalXCodeGenerator
{
std::string echo_cmd = "echo ";
echo_cmd += (this->CurrentLocalGenerator->
- EscapeForShell(comment, escapeAllowMakeVars));
+ EscapeForShell(comment, cc.GetEscapeAllowMakeVars()));
makefileStream << "\t" << echo_cmd.c_str() << "\n";
}
// Add each command line to the set of commands.
- for(cmCustomCommandLines::const_iterator cl =
- cc.GetCommandLines().begin();
- cl != cc.GetCommandLines().end(); ++cl)
+ for(unsigned int c = 0; c < ccg.GetNumberOfCommands(); ++c)
{
// Build the command line in a single string.
- const cmCustomCommandLine& commandLine = *cl;
- std::string cmd2 = this->CurrentLocalGenerator
- ->GetRealLocation(commandLine[0].c_str(), configName);
-
+ std::string cmd2 = ccg.GetCommand(c);
cmSystemTools::ReplaceString(cmd2, "/./", "/");
cmd2 = this->ConvertToRelativeForMake(cmd2.c_str());
std::string cmd;
@@ -1370,21 +1367,7 @@ void cmGlobalXCodeGenerator
cmd += " && ";
}
cmd += cmd2;
- for(unsigned int j=1; j < commandLine.size(); ++j)
- {
- cmd += " ";
- if(escapeOldStyle)
- {
- cmd += (this->CurrentLocalGenerator
- ->EscapeForShellOldStyle(commandLine[j].c_str()));
- }
- else
- {
- cmd += (this->CurrentLocalGenerator->
- EscapeForShell(commandLine[j].c_str(),
- escapeAllowMakeVars));
- }
- }
+ ccg.AppendArguments(c, cmd);
makefileStream << "\t" << cmd.c_str() << "\n";
}
}
diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index 5bffd52..d3cbc1f 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -1818,8 +1818,9 @@ void cmLocalGenerator::AddLanguageFlags(std::string& flags,
}
//----------------------------------------------------------------------------
-std::string cmLocalGenerator::GetRealDependency(const char* inName,
- const char* config)
+bool cmLocalGenerator::GetRealDependency(const char* inName,
+ const char* config,
+ std::string& dep)
{
// Older CMake code may specify the dependency using the target
// output file rather than the target name. Such code would have
@@ -1855,7 +1856,8 @@ std::string cmLocalGenerator::GetRealDependency(const char* inName,
// it is a full path to a depend that has the same name
// as a target but is in a different location so do not use
// the target as the depend
- return inName;
+ dep = inName;
+ return true;
}
}
switch (target->GetType())
@@ -1869,15 +1871,16 @@ std::string cmLocalGenerator::GetRealDependency(const char* inName,
// Get the location of the target's output file and depend on it.
if(const char* location = target->GetLocation(config))
{
- return location;
+ dep = location;
+ return true;
}
}
break;
case cmTarget::UTILITY:
case cmTarget::GLOBAL_TARGET:
- // Depending on a utility target may not work but just trust
- // the user to have given a valid name.
- return inName;
+ // A utility target has no file on which to depend. This was listed
+ // only to get the target-level dependency.
+ return false;
case cmTarget::INSTALL_FILES:
case cmTarget::INSTALL_PROGRAMS:
case cmTarget::INSTALL_DIRECTORY:
@@ -1889,41 +1892,24 @@ std::string cmLocalGenerator::GetRealDependency(const char* inName,
if(cmSystemTools::FileIsFullPath(inName))
{
// This is a full path. Return it as given.
- return inName;
+ dep = inName;
+ return true;
}
// Check for a source file in this directory that matches the
// dependency.
if(cmSourceFile* sf = this->Makefile->GetSource(inName))
{
- name = sf->GetFullPath();
- return name;
+ dep = sf->GetFullPath();
+ return true;
}
// Treat the name as relative to the source directory in which it
// was given.
- name = this->Makefile->GetCurrentDirectory();
- name += "/";
- name += inName;
- return name;
-}
-
-//----------------------------------------------------------------------------
-std::string cmLocalGenerator::GetRealLocation(const char* inName,
- const char* config)
-{
- std::string outName=inName;
- // Look for a CMake target with the given name, which is an executable
- // and which can be run
- cmTarget* target = this->Makefile->FindTargetToUse(inName);
- if ((target != 0)
- && (target->GetType() == cmTarget::EXECUTABLE)
- && ((this->Makefile->IsOn("CMAKE_CROSSCOMPILING") == false)
- || (target->IsImported() == true)))
- {
- outName = target->GetLocation( config );
- }
- return outName;
+ dep = this->Makefile->GetCurrentDirectory();
+ dep += "/";
+ dep += inName;
+ return true;
}
//----------------------------------------------------------------------------
diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h
index 43bf1e7..35aab99 100644
--- a/Source/cmLocalGenerator.h
+++ b/Source/cmLocalGenerator.h
@@ -158,18 +158,15 @@ public:
/** Translate a dependency as given in CMake code to the name to
appear in a generated build file. If the given name is that of
+ a utility target, returns false. If the given name is that of
a CMake target it will be transformed to the real output
location of that target for the given configuration. If the
given name is the full path to a file it will be returned.
Otherwise the name is treated as a relative path with respect to
the source directory of this generator. This should only be
used for dependencies of custom commands. */
- std::string GetRealDependency(const char* name, const char* config);
-
- /** Translate a command as given in CMake code to the location of the
- executable if the command is the name of a CMake executable target.
- If that's not the case, just return the original name. */
- std::string GetRealLocation(const char* inName, const char* config);
+ bool GetRealDependency(const char* name, const char* config,
+ std::string& dep);
///! for existing files convert to output path and short path if spaces
std::string ConvertToOutputForExisting(const char* remote,
diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx
index c5d8c0d..ff48009 100644
--- a/Source/cmLocalUnixMakefileGenerator3.cxx
+++ b/Source/cmLocalUnixMakefileGenerator3.cxx
@@ -19,6 +19,7 @@
#include "cmake.h"
#include "cmVersion.h"
#include "cmFileTimeComparison.h"
+#include "cmCustomCommandGenerator.h"
// Include dependency scanners for supported languages. Only the
// C/C++ scanner is needed for bootstrapping CMake.
@@ -902,9 +903,12 @@ cmLocalUnixMakefileGenerator3
d != cc.GetDepends().end(); ++d)
{
// Lookup the real name of the dependency in case it is a CMake target.
- std::string dep = this->GetRealDependency
- (d->c_str(), this->ConfigurationName.c_str());
- depends.push_back(dep);
+ std::string dep;
+ if(this->GetRealDependency(d->c_str(), this->ConfigurationName.c_str(),
+ dep))
+ {
+ depends.push_back(dep);
+ }
}
}
@@ -958,18 +962,15 @@ cmLocalUnixMakefileGenerator3
{
*content << dir;
}
- bool escapeOldStyle = cc.GetEscapeOldStyle();
- bool escapeAllowMakeVars = cc.GetEscapeAllowMakeVars();
+ cmCustomCommandGenerator ccg(cc, this->ConfigurationName.c_str(),
+ this->Makefile);
// Add each command line to the set of commands.
std::vector<std::string> commands1;
- for(cmCustomCommandLines::const_iterator cl = cc.GetCommandLines().begin();
- cl != cc.GetCommandLines().end(); ++cl)
+ for(unsigned int c = 0; c < ccg.GetNumberOfCommands(); ++c)
{
// Build the command line in a single string.
- const cmCustomCommandLine& commandLine = *cl;
- std::string cmd = GetRealLocation(commandLine[0].c_str(),
- this->ConfigurationName.c_str());
+ std::string cmd = ccg.GetCommand(c);
if (cmd.size())
{
// Use "call " before any invocations of .bat or .cmd files
@@ -1022,19 +1023,8 @@ cmLocalUnixMakefileGenerator3
std::string launcher =
this->MakeLauncher(cc, target, workingDir? NONE : START_OUTPUT);
cmd = launcher + this->Convert(cmd.c_str(),NONE,SHELL);
- for(unsigned int j=1; j < commandLine.size(); ++j)
- {
- cmd += " ";
- if(escapeOldStyle)
- {
- cmd += this->EscapeForShellOldStyle(commandLine[j].c_str());
- }
- else
- {
- cmd += this->EscapeForShell(commandLine[j].c_str(),
- escapeAllowMakeVars);
- }
- }
+
+ ccg.AppendArguments(c, cmd);
if(content)
{
// Rule content does not include the launcher.
diff --git a/Source/cmLocalVisualStudio6Generator.cxx b/Source/cmLocalVisualStudio6Generator.cxx
index eb4e4a4..7aabf4d 100644
--- a/Source/cmLocalVisualStudio6Generator.cxx
+++ b/Source/cmLocalVisualStudio6Generator.cxx
@@ -65,13 +65,7 @@ public:
{
this->Code += "\\\n\t";
}
- this->Code +=
- this->LG->ConstructScript(cc.GetCommandLines(),
- cc.GetWorkingDirectory(),
- this->Config,
- cc.GetEscapeOldStyle(),
- cc.GetEscapeAllowMakeVars(),
- "\\\n\t");
+ this->Code += this->LG->ConstructScript(cc, this->Config, "\\\n\t");
}
private:
cmLocalVisualStudio6Generator* LG;
@@ -659,12 +653,7 @@ cmLocalVisualStudio6Generator
{
std::string config = this->GetConfigName(*i);
std::string script =
- this->ConstructScript(command.GetCommandLines(),
- command.GetWorkingDirectory(),
- config.c_str(),
- command.GetEscapeOldStyle(),
- command.GetEscapeAllowMakeVars(),
- "\\\n\t");
+ this->ConstructScript(command, config.c_str(), "\\\n\t");
if (i == this->Configurations.begin())
{
@@ -686,10 +675,12 @@ cmLocalVisualStudio6Generator
++d)
{
// Lookup the real name of the dependency in case it is a CMake target.
- std::string dep = this->GetRealDependency(d->c_str(),
- config.c_str());
- fout << "\\\n\t" <<
- this->ConvertToOptionallyRelativeOutputPath(dep.c_str());
+ std::string dep;
+ if(this->GetRealDependency(d->c_str(), config.c_str(), dep))
+ {
+ fout << "\\\n\t" <<
+ this->ConvertToOptionallyRelativeOutputPath(dep.c_str());
+ }
}
fout << "\n";
@@ -847,7 +838,7 @@ cmLocalVisualStudio6Generator::MaybeCreateOutputDir(cmTarget& target,
std::vector<std::string> no_depends;
cmCustomCommandLines commands;
commands.push_back(command);
- pcc.reset(new cmCustomCommand(no_output, no_depends, commands, 0, 0));
+ pcc.reset(new cmCustomCommand(0, no_output, no_depends, commands, 0, 0));
pcc->SetEscapeOldStyle(false);
pcc->SetEscapeAllowMakeVars(true);
return pcc;
diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx
index 7fd7fd2..b22c429 100644
--- a/Source/cmLocalVisualStudio7Generator.cxx
+++ b/Source/cmLocalVisualStudio7Generator.cxx
@@ -546,12 +546,7 @@ public:
{
this->Stream << this->LG->EscapeForXML("\n");
}
- std::string script =
- this->LG->ConstructScript(cc.GetCommandLines(),
- cc.GetWorkingDirectory(),
- this->Config,
- cc.GetEscapeOldStyle(),
- cc.GetEscapeAllowMakeVars());
+ std::string script = this->LG->ConstructScript(cc, this->Config);
this->Stream << this->LG->EscapeForXML(script.c_str());
}
private:
@@ -1591,12 +1586,7 @@ WriteCustomRule(std::ostream& fout,
<< this->EscapeForXML(fc.CompileFlags.c_str()) << "\"/>\n";
}
- std::string script =
- this->ConstructScript(command.GetCommandLines(),
- command.GetWorkingDirectory(),
- i->c_str(),
- command.GetEscapeOldStyle(),
- command.GetEscapeAllowMakeVars());
+ std::string script = this->ConstructScript(command, i->c_str());
fout << "\t\t\t\t\t<Tool\n"
<< "\t\t\t\t\tName=\"" << customTool << "\"\n"
<< "\t\t\t\t\tDescription=\""
@@ -1624,9 +1614,12 @@ WriteCustomRule(std::ostream& fout,
++d)
{
// Get the real name of the dependency in case it is a CMake target.
- std::string dep = this->GetRealDependency(d->c_str(), i->c_str());
- fout << this->ConvertToXMLOutputPath(dep.c_str())
- << ";";
+ std::string dep;
+ if(this->GetRealDependency(d->c_str(), i->c_str(), dep))
+ {
+ fout << this->ConvertToXMLOutputPath(dep.c_str())
+ << ";";
+ }
}
}
fout << "\"\n";
diff --git a/Source/cmLocalVisualStudioGenerator.cxx b/Source/cmLocalVisualStudioGenerator.cxx
index ed0b07f..a044363 100644
--- a/Source/cmLocalVisualStudioGenerator.cxx
+++ b/Source/cmLocalVisualStudioGenerator.cxx
@@ -14,6 +14,7 @@
#include "cmMakefile.h"
#include "cmSourceFile.h"
#include "cmSystemTools.h"
+#include "cmCustomCommandGenerator.h"
#include "windows.h"
//----------------------------------------------------------------------------
@@ -52,7 +53,7 @@ cmLocalVisualStudioGenerator::MaybeCreateImplibDir(cmTarget& target,
std::vector<std::string> no_depends;
cmCustomCommandLines commands;
commands.push_back(command);
- pcc.reset(new cmCustomCommand(no_output, no_depends, commands, 0, 0));
+ pcc.reset(new cmCustomCommand(0, no_output, no_depends, commands, 0, 0));
pcc->SetEscapeOldStyle(false);
pcc->SetEscapeAllowMakeVars(true);
return pcc;
@@ -151,13 +152,15 @@ void cmLocalVisualStudioGenerator::ComputeObjectNameRequirements
//----------------------------------------------------------------------------
std::string
cmLocalVisualStudioGenerator
-::ConstructScript(const cmCustomCommandLines& commandLines,
- const char* workingDirectory,
+::ConstructScript(cmCustomCommand const& cc,
const char* configName,
- bool escapeOldStyle,
- bool escapeAllowMakeVars,
const char* newline_text)
{
+ const cmCustomCommandLines& commandLines = cc.GetCommandLines();
+ const char* workingDirectory = cc.GetWorkingDirectory();
+ cmCustomCommandGenerator ccg(cc, configName, this->Makefile);
+ RelativeRoot relativeRoot = workingDirectory? NONE : START_OUTPUT;
+
// Avoid leading or trailing newlines.
const char* newline = "";
@@ -196,40 +199,16 @@ cmLocalVisualStudioGenerator
}
}
// Write each command on a single line.
- for(cmCustomCommandLines::const_iterator cl = commandLines.begin();
- cl != commandLines.end(); ++cl)
+ for(unsigned int c = 0; c < ccg.GetNumberOfCommands(); ++c)
{
// Start a new line.
script += newline;
newline = newline_text;
- // Start with the command name.
- const cmCustomCommandLine& commandLine = *cl;
- std::string commandName = this->GetRealLocation(commandLine[0].c_str(),
- configName);
- if(!workingDirectory)
- {
- script += this->Convert(commandName.c_str(),START_OUTPUT,SHELL);
- }
- else
- {
- script += this->Convert(commandName.c_str(),NONE,SHELL);
- }
-
- // Add the arguments.
- for(unsigned int j=1;j < commandLine.size(); ++j)
- {
- script += " ";
- if(escapeOldStyle)
- {
- script += this->EscapeForShellOldStyle(commandLine[j].c_str());
- }
- else
- {
- script += this->EscapeForShell(commandLine[j].c_str(),
- escapeAllowMakeVars);
- }
- }
+ // Add this command line.
+ std::string cmd = ccg.GetCommand(c);
+ script += this->Convert(cmd.c_str(), relativeRoot, SHELL);
+ ccg.AppendArguments(c, script);
// After each custom command, check for an error result.
// If there was an error, jump to the VCReportError label,
diff --git a/Source/cmLocalVisualStudioGenerator.h b/Source/cmLocalVisualStudioGenerator.h
index 6034b22..551b01c 100644
--- a/Source/cmLocalVisualStudioGenerator.h
+++ b/Source/cmLocalVisualStudioGenerator.h
@@ -18,6 +18,7 @@
class cmSourceFile;
class cmSourceGroup;
+class cmCustomCommand;
/** \class cmLocalVisualStudioGenerator
* \brief Base class for Visual Studio generators.
@@ -31,11 +32,8 @@ public:
cmLocalVisualStudioGenerator();
virtual ~cmLocalVisualStudioGenerator();
/** Construct a script from the given list of command lines. */
- std::string ConstructScript(const cmCustomCommandLines& commandLines,
- const char* workingDirectory,
+ std::string ConstructScript(cmCustomCommand const& cc,
const char* configName,
- bool escapeOldStyle,
- bool escapeAllowMakeVars,
const char* newline = "\n");
protected:
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index 56e0ed9..3bce01c 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -827,7 +827,8 @@ cmMakefile::AddCustomCommandToTarget(const char* target,
{
// Add the command to the appropriate build step for the target.
std::vector<std::string> no_output;
- cmCustomCommand cc(no_output, depends, commandLines, comment, workingDir);
+ cmCustomCommand cc(this, no_output, depends,
+ commandLines, comment, workingDir);
cc.SetEscapeOldStyle(escapeOldStyle);
cc.SetEscapeAllowMakeVars(true);
switch(type)
@@ -947,7 +948,7 @@ cmMakefile::AddCustomCommandToOutput(const std::vector<std::string>& outputs,
if(file)
{
cmCustomCommand* cc =
- new cmCustomCommand(outputs, depends2, commandLines,
+ new cmCustomCommand(this, outputs, depends2, commandLines,
comment, workingDir);
cc->SetEscapeOldStyle(escapeOldStyle);
cc->SetEscapeAllowMakeVars(true);
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index ca61b1f..c82c11e 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -1357,8 +1357,8 @@ bool cmTargetTraceDependencies::IsUtility(std::string const& dep)
util = cmSystemTools::GetFilenameWithoutLastExtension(util);
}
- // Check for a non-imported target with this name.
- if(cmTarget* t = this->GlobalGenerator->FindTarget(0, util.c_str()))
+ // Check for a target with this name.
+ if(cmTarget* t = this->Makefile->FindTargetToUse(util.c_str()))
{
// If we find the target and the dep was given as a full path,
// then make sure it was not a full path to something else, and
@@ -1406,8 +1406,8 @@ cmTargetTraceDependencies
cit != cc.GetCommandLines().end(); ++cit)
{
std::string const& command = *cit->begin();
- // Look for a non-imported target with this name.
- if(cmTarget* t = this->GlobalGenerator->FindTarget(0, command.c_str()))
+ // Check for a target with this name.
+ if(cmTarget* t = this->Makefile->FindTargetToUse(command.c_str()))
{
if(t->GetType() == cmTarget::EXECUTABLE)
{
diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx
index 524be8b..eb8320c 100644
--- a/Source/cmVisualStudio10TargetGenerator.cxx
+++ b/Source/cmVisualStudio10TargetGenerator.cxx
@@ -367,13 +367,7 @@ cmVisualStudio10TargetGenerator::WriteCustomRule(cmSourceFile* source,
i != configs->end(); ++i)
{
std::string script =
- cmVS10EscapeXML(
- lg->ConstructScript(command.GetCommandLines(),
- command.GetWorkingDirectory(),
- i->c_str(),
- command.GetEscapeOldStyle(),
- command.GetEscapeAllowMakeVars())
- );
+ cmVS10EscapeXML(lg->ConstructScript(command, i->c_str()));
this->WritePlatformConfigTag("Message",i->c_str(), 3);
(*this->BuildFileStream ) << cmVS10EscapeXML(comment) << "</Message>\n";
this->WritePlatformConfigTag("Command", i->c_str(), 3);
@@ -386,10 +380,12 @@ cmVisualStudio10TargetGenerator::WriteCustomRule(cmSourceFile* source,
d != command.GetDepends().end();
++d)
{
- std::string dep = this->LocalGenerator->
- GetRealDependency(d->c_str(), i->c_str());
- this->ConvertToWindowsSlash(dep);
- (*this->BuildFileStream ) << ";" << dep;
+ std::string dep;
+ if(this->LocalGenerator->GetRealDependency(d->c_str(), i->c_str(), dep))
+ {
+ this->ConvertToWindowsSlash(dep);
+ (*this->BuildFileStream ) << ";" << dep;
+ }
}
(*this->BuildFileStream ) << ";%(AdditionalInputs)</AdditionalInputs>\n";
this->WritePlatformConfigTag("Outputs", i->c_str(), 3);
@@ -1458,13 +1454,7 @@ void cmVisualStudio10TargetGenerator::WriteEvent(
script += pre;
pre = "\n";
script +=
- cmVS10EscapeXML(
- lg->ConstructScript(command.GetCommandLines(),
- command.GetWorkingDirectory(),
- configName.c_str(),
- command.GetEscapeOldStyle(),
- command.GetEscapeAllowMakeVars())
- );
+ cmVS10EscapeXML(lg->ConstructScript(command, configName.c_str()));
}
comment = cmVS10EscapeComment(comment);
this->WriteString("<Message>",3);
diff --git a/Tests/CustomCommand/CMakeLists.txt b/Tests/CustomCommand/CMakeLists.txt
index 76208d4..746c9a7 100644
--- a/Tests/CustomCommand/CMakeLists.txt
+++ b/Tests/CustomCommand/CMakeLists.txt
@@ -130,6 +130,7 @@ ADD_CUSTOM_COMMAND(
################################################################
ADD_CUSTOM_COMMAND(OUTPUT ${PROJECT_BINARY_DIR}/foo.pre
DEPENDS ${PROJECT_SOURCE_DIR}/foo.in
+ TDocument # Ensure doc1.h generates before this target
COMMAND ${CMAKE_COMMAND}
ARGS -E copy ${PROJECT_SOURCE_DIR}/foo.in
${PROJECT_BINARY_DIR}/foo.pre
@@ -181,10 +182,6 @@ ADD_CUSTOM_COMMAND(OUTPUT ${PROJECT_BINARY_DIR}/generated.c
TARGET_LINK_LIBRARIES(CustomCommand GeneratedHeader)
-# must add a dependency on TDocument otherwise it might never build and
-# the CustomCommand executable really needs doc1.h
-ADD_DEPENDENCIES(CustomCommand TDocument)
-
##############################################################################
# Test for using just the target name as executable in the COMMAND
# section. Has to be recognized and replaced by CMake with the output
diff --git a/Tests/ExportImport/Import/A/CMakeLists.txt b/Tests/ExportImport/Import/A/CMakeLists.txt
index 0828343..e65e362 100644
--- a/Tests/ExportImport/Import/A/CMakeLists.txt
+++ b/Tests/ExportImport/Import/A/CMakeLists.txt
@@ -75,24 +75,64 @@ foreach(c DEBUG RELWITHDEBINFO)
set_property(TARGET imp_testExe1b PROPERTY COMPILE_DEFINITIONS_${c} EXE_DBG)
endforeach(c)
+#-----------------------------------------------------------------------------
# Create a custom target to generate a header for the libraries below.
-include_directories(${CMAKE_CURRENT_BINARY_DIR})
+# Drive the header generation through an indirect chain of imported
+# target dependencies.
+
+# testLib2tmp1.h
add_custom_command(
- OUTPUT testLib2.h
+ OUTPUT testLib2tmp1.h
VERBATIM COMMAND
- ${CMAKE_COMMAND} -E echo "extern int testLib2(void);" > testLib2.h
+ ${CMAKE_COMMAND} -E echo "extern int testLib2(void);" > testLib2tmp1.h
+ )
+
+# hdr_testLib2tmp1 needs testLib2tmp1.h
+add_custom_target(hdr_testLib2tmp1 DEPENDS testLib2tmp1.h)
+
+# exp_testExe2 needs hdr_testLib2tmp1
+add_dependencies(exp_testExe2 hdr_testLib2tmp1)
+
+# testLib2tmp.h needs exp_testExe2
+add_custom_command(
+ OUTPUT testLib2tmp.h
+ VERBATIM COMMAND exp_testExe2
+ COMMAND ${CMAKE_COMMAND} -E copy testLib2tmp1.h testLib2tmp.h
)
+
+# hdr_testLib2tmp needs testLib2tmp.h
+add_custom_target(hdr_testLib2tmp DEPENDS testLib2tmp.h)
+
+add_library(dep_testLib2tmp UNKNOWN IMPORTED)
+set_property(TARGET dep_testLib2tmp PROPERTY
+ IMPORTED_LOCATION ${CMAKE_CURRENT_BINARY_DIR}/testLib2tmp.h)
+
+# dep_testLib2tmp needs hdr_testLib2tmp
+add_dependencies(dep_testLib2tmp hdr_testLib2tmp)
+
+# testLib2.h needs dep_testLib2tmp
+add_custom_command(
+ OUTPUT testLib2.h
+ VERBATIM COMMAND ${CMAKE_COMMAND} -E copy testLib2tmp.h testLib2.h
+ DEPENDS dep_testLib2tmp
+ )
+
+# hdr_testLib2 needs testLib2.h
add_custom_target(hdr_testLib2 DEPENDS testLib2.h)
-# Drive the header generation through an indirect chain of imported
-# target dependencies.
add_library(dep_testLib2 UNKNOWN IMPORTED)
+
+# dep_testLib2 needs hdr_testLib2
add_dependencies(dep_testLib2 hdr_testLib2)
+
+# exp_testLib2 and bld_testLib2 both need dep_testLib2
add_dependencies(bld_testLib2 dep_testLib2)
add_dependencies(exp_testLib2 dep_testLib2)
+#-----------------------------------------------------------------------------
# Create a library to be linked by another directory in this project
# to test transitive linking to otherwise invisible imported targets.
+include_directories(${CMAKE_CURRENT_BINARY_DIR})
add_library(imp_lib1 STATIC imp_lib1.c)
target_link_libraries(imp_lib1 exp_testLib2)
add_library(imp_lib1b STATIC imp_lib1.c)
diff --git a/Tests/PerConfig/CMakeLists.txt b/Tests/PerConfig/CMakeLists.txt
new file mode 100644
index 0000000..2a55d33
--- /dev/null
+++ b/Tests/PerConfig/CMakeLists.txt
@@ -0,0 +1,33 @@
+project(PerConfig C)
+
+# Targets with per-configuration names.
+ADD_LIBRARY(pcStatic STATIC pcStatic.c)
+SET_PROPERTY(TARGET pcStatic PROPERTY RELEASE_POSTFIX -opt)
+SET_PROPERTY(TARGET pcStatic PROPERTY DEBUG_POSTFIX -dbg)
+ADD_LIBRARY(pcShared SHARED pcShared.c)
+SET_PROPERTY(TARGET pcShared PROPERTY RELEASE_POSTFIX -opt)
+SET_PROPERTY(TARGET pcShared PROPERTY DEBUG_POSTFIX -dbg)
+SET_PROPERTY(TARGET pcShared PROPERTY VERSION 1.2)
+SET_PROPERTY(TARGET pcShared PROPERTY SOVERSION 3)
+IF(UNIX AND NOT CYGWIN)
+ SET(soname_file -DpcShared_soname_file=$<TARGET_SONAME_FILE:pcShared>)
+ENDIF()
+ADD_EXECUTABLE(perconfig perconfig.c)
+TARGET_LINK_LIBRARIES(perconfig pcStatic pcShared)
+SET_PROPERTY(TARGET perconfig PROPERTY RELEASE_POSTFIX -opt)
+SET_PROPERTY(TARGET perconfig PROPERTY DEBUG_POSTFIX -dbg)
+
+SET(PerConfig_COMMAND
+ ${CMAKE_COMMAND}
+ -Dconfiguration=$<CONFIGURATION>
+ -Dperconfig_file_dir=$<TARGET_FILE_DIR:perconfig>
+ -Dperconfig_file_name=$<TARGET_FILE_NAME:perconfig>
+ -Dperconfig_file=$<TARGET_FILE:perconfig>
+ -DpcStatic_file=$<TARGET_FILE:pcStatic>
+ -DpcStatic_linker_file=$<TARGET_LINKER_FILE:pcStatic>
+ -DpcShared_file=$<TARGET_FILE:pcShared>
+ -DpcShared_linker_file=$<TARGET_LINKER_FILE:pcShared>
+ ${soname_file}
+ -P ${PerConfig_SOURCE_DIR}/perconfig.cmake
+ )
+SET(PerConfig_COMMAND "${PerConfig_COMMAND}" PARENT_SCOPE)
diff --git a/Tests/Testing/pcShared.c b/Tests/PerConfig/pcShared.c
index b08fadc..b08fadc 100644
--- a/Tests/Testing/pcShared.c
+++ b/Tests/PerConfig/pcShared.c
diff --git a/Tests/Testing/pcShared.h b/Tests/PerConfig/pcShared.h
index 59a6ef4..59a6ef4 100644
--- a/Tests/Testing/pcShared.h
+++ b/Tests/PerConfig/pcShared.h
diff --git a/Tests/Testing/pcStatic.c b/Tests/PerConfig/pcStatic.c
index 7e1bf51..7e1bf51 100644
--- a/Tests/Testing/pcStatic.c
+++ b/Tests/PerConfig/pcStatic.c
diff --git a/Tests/Testing/perconfig.c b/Tests/PerConfig/perconfig.c
index d942d45..d942d45 100644
--- a/Tests/Testing/perconfig.c
+++ b/Tests/PerConfig/perconfig.c
diff --git a/Tests/Testing/driver.cmake b/Tests/PerConfig/perconfig.cmake
index 4a93acc..4a93acc 100644
--- a/Tests/Testing/driver.cmake
+++ b/Tests/PerConfig/perconfig.cmake
diff --git a/Tests/Testing/CMakeLists.txt b/Tests/Testing/CMakeLists.txt
index 9e7a637..815b52b 100644
--- a/Tests/Testing/CMakeLists.txt
+++ b/Tests/Testing/CMakeLists.txt
@@ -53,35 +53,7 @@ ADD_TEST(testing.1 ${Testing_BINARY_DIR}/bin/testing)
#
ADD_SUBDIRECTORY(Sub/Sub2)
-# Per-config target name test.
-ADD_LIBRARY(pcStatic STATIC pcStatic.c)
-SET_PROPERTY(TARGET pcStatic PROPERTY RELEASE_POSTFIX -opt)
-SET_PROPERTY(TARGET pcStatic PROPERTY DEBUG_POSTFIX -dbg)
-ADD_LIBRARY(pcShared SHARED pcShared.c)
-SET_PROPERTY(TARGET pcShared PROPERTY RELEASE_POSTFIX -opt)
-SET_PROPERTY(TARGET pcShared PROPERTY DEBUG_POSTFIX -dbg)
-SET_PROPERTY(TARGET pcShared PROPERTY VERSION 1.2)
-SET_PROPERTY(TARGET pcShared PROPERTY SOVERSION 3)
-IF(UNIX AND NOT CYGWIN)
- SET(soname_file -DpcShared_soname_file=$<TARGET_SONAME_FILE:pcShared>)
-ENDIF()
-ADD_EXECUTABLE(perconfig perconfig.c)
-TARGET_LINK_LIBRARIES(perconfig pcStatic pcShared)
-SET_PROPERTY(TARGET perconfig PROPERTY RELEASE_POSTFIX -opt)
-SET_PROPERTY(TARGET perconfig PROPERTY DEBUG_POSTFIX -dbg)
+# Per-config target name and generator expressions.
+ADD_SUBDIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/../PerConfig PerConfig)
ADD_TEST(NAME testing.perconfig COMMAND perconfig)
-
-# Test using a driver script with generator expressions.
-ADD_TEST(NAME testing.driver
- COMMAND ${CMAKE_COMMAND}
- -Dconfiguration=$<CONFIGURATION>
- -Dperconfig_file_dir=$<TARGET_FILE_DIR:perconfig>
- -Dperconfig_file_name=$<TARGET_FILE_NAME:perconfig>
- -Dperconfig_file=$<TARGET_FILE:perconfig>
- -DpcStatic_file=$<TARGET_FILE:pcStatic>
- -DpcStatic_linker_file=$<TARGET_LINKER_FILE:pcStatic>
- -DpcShared_file=$<TARGET_FILE:pcShared>
- -DpcShared_linker_file=$<TARGET_LINKER_FILE:pcShared>
- ${soname_file}
- -P ${Testing_SOURCE_DIR}/driver.cmake
- )
+ADD_TEST(NAME testing.driver COMMAND ${PerConfig_COMMAND})
diff --git a/bootstrap b/bootstrap
index 0da868d..b4e19ef 100755
--- a/bootstrap
+++ b/bootstrap
@@ -215,6 +215,7 @@ CMAKE_CXX_SOURCES="\
cmTarget \
cmTest \
cmCustomCommand \
+ cmCustomCommandGenerator \
cmDocumentVariables \
cmCacheManager \
cmListFileCache \