Attached Files | CustomCommandsByConfiguration.zip [^] (11,670 bytes) 2009-11-27 19:19
0001-Per-config-add_custom_command.patch [^] (39,624 bytes) 2010-12-15 14:19 [Show Content] [Hide Content]From 8d7764034ab9104df9886cf218d905f7d8af4a33 Mon Sep 17 00:00:00 2001
From: Steven Wilson <steven.wesley.wilson@gmail.com>
Date: Fri, 27 Nov 2009 19:19:00 -0500
Subject: [PATCH] Per-config add_custom_command
Add a new keyword to the add_custom_command CMake directive called
CONFIG. The CONFIG option specifies that the custom command(s) should
run only when the given build configuration is active. This option
allows custom commands to have configuration specific behavior. When
the CONFIG option is not present, add_custom_command command behaves as
before.
---
Source/cmAddCustomCommandCommand.cxx | 74 +++++++--
Source/cmAddCustomCommandCommand.h | 10 +-
Source/cmCustomCommand.cxx | 107 +++++++++++++
Source/cmCustomCommand.h | 29 ++++
Source/cmGlobalXCodeGenerator.cxx | 20 ++-
Source/cmLocalUnixMakefileGenerator3.cxx | 18 ++-
Source/cmLocalVisualStudio6Generator.cxx | 26 +++-
Source/cmLocalVisualStudio7Generator.cxx | 25 +++-
Source/cmMakefile.cxx | 238 ++++++++++++++++++++++++++++
Source/cmMakefile.h | 34 ++++
Source/cmSystemTools.cxx | 11 ++-
Source/cmSystemTools.h | 3 +-
Source/cmVisualStudio10TargetGenerator.cxx | 25 +++-
13 files changed, 590 insertions(+), 30 deletions(-)
diff --git a/Source/cmAddCustomCommandCommand.cxx b/Source/cmAddCustomCommandCommand.cxx
index f6b3234..24a1efe 100644
--- a/Source/cmAddCustomCommandCommand.cxx
+++ b/Source/cmAddCustomCommandCommand.cxx
@@ -37,6 +37,7 @@ bool cmAddCustomCommandCommand
bool append = false;
std::string implicit_depends_lang;
cmCustomCommand::ImplicitDependsList implicit_depends;
+ std::string intendedConfig;
// Accumulate one command line at a time.
cmCustomCommandLine currentLine;
@@ -58,6 +59,7 @@ bool cmAddCustomCommandCommand
doing_outputs,
doing_comment,
doing_working_directory,
+ doing_config,
doing_nothing
};
@@ -138,6 +140,10 @@ bool cmAddCustomCommandCommand
{
doing = doing_comment;
}
+ else if (copy == "CONFIG")
+ {
+ doing = doing_config;
+ }
else
{
std::string filename;
@@ -221,6 +227,9 @@ bool cmAddCustomCommandCommand
comment_buffer = copy;
comment = comment_buffer.c_str();
break;
+ case doing_config:
+ intendedConfig = copy;
+ break;
default:
this->SetError("Wrong syntax. Unknown type of argument.");
return false;
@@ -270,7 +279,14 @@ bool cmAddCustomCommandCommand
{
if(cmCustomCommand* cc = sf->GetCustomCommand())
{
- cc->AppendCommands(commandLines);
+ if(! intendedConfig.empty())
+ {
+ cc->AppendCommands(commandLines, intendedConfig);
+ }
+ else
+ {
+ cc->AppendCommands(commandLines);
+ }
cc->AppendDepends(depends);
cc->AppendImplicitDepends(implicit_depends);
return true;
@@ -291,19 +307,42 @@ bool cmAddCustomCommandCommand
{
// Source is empty, use the target.
std::vector<std::string> no_depends;
- this->Makefile->AddCustomCommandToTarget(target.c_str(), no_depends,
- commandLines, cctype,
- comment, working.c_str(),
- escapeOldStyle);
+ if(! intendedConfig.empty())
+ {
+ this->Makefile->AddCustomCommandToTarget(target.c_str(), no_depends,
+ commandLines, cctype,
+ comment, working.c_str(),
+ intendedConfig,
+ escapeOldStyle);
+ }
+ else
+ {
+ this->Makefile->AddCustomCommandToTarget(target.c_str(), no_depends,
+ commandLines, cctype,
+ comment, working.c_str(),
+ escapeOldStyle);
+ }
}
else if(target.empty())
{
// Target is empty, use the output.
- this->Makefile->AddCustomCommandToOutput(output, depends,
- main_dependency.c_str(),
- commandLines, comment,
- working.c_str(), false,
- escapeOldStyle);
+ if(! intendedConfig.empty())
+ {
+ this->Makefile->AddCustomCommandToOutput(output, depends,
+ main_dependency.c_str(),
+ commandLines, comment,
+ working.c_str(),
+ intendedConfig, false,
+ escapeOldStyle);
+ }
+ else
+ {
+ this->Makefile->AddCustomCommandToOutput(output, depends,
+ main_dependency.c_str(),
+ commandLines, comment,
+ working.c_str(), false,
+ escapeOldStyle);
+ }
// Add implicit dependency scanning requests if any were given.
if(!implicit_depends.empty())
@@ -331,9 +370,18 @@ bool cmAddCustomCommandCommand
else
{
// Use the old-style mode for backward compatibility.
- this->Makefile->AddCustomCommandOldStyle(target.c_str(), outputs, depends,
- source.c_str(), commandLines,
- comment);
+ if(! intendedConfig.empty())
+ {
+ this->Makefile->AddCustomCommandOldStyle(target.c_str(), outputs, depends,
+ source.c_str(), commandLines,
+ comment, intendedConfig);
+ }
+ else
+ {
+ this->Makefile->AddCustomCommandOldStyle(target.c_str(), outputs, depends,
+ source.c_str(), commandLines,
+ comment);
+ }
}
return true;
diff --git a/Source/cmAddCustomCommandCommand.h b/Source/cmAddCustomCommandCommand.h
index c67caa5..85429e4 100644
--- a/Source/cmAddCustomCommandCommand.h
+++ b/Source/cmAddCustomCommandCommand.h
@@ -69,7 +69,8 @@ public:
" [DEPENDS [depends...]]\n"
" [IMPLICIT_DEPENDS <lang1> depend1 ...]\n"
" [WORKING_DIRECTORY dir]\n"
- " [COMMENT comment] [VERBATIM] [APPEND])\n"
+ " [COMMENT comment] [VERBATIM] [APPEND]\n"
+ " [CONFIG Debug | MinSizeRel | Release | RelWithDebInfo | ...])\n"
"This defines a command to generate specified OUTPUT file(s). "
"A target created in the same directory (CMakeLists.txt file) that "
"specifies any output of the custom command as a source file is given "
@@ -97,7 +98,8 @@ public:
" COMMAND command1 [ARGS] [args1...]\n"
" [COMMAND command2 [ARGS] [args2...] ...]\n"
" [WORKING_DIRECTORY dir]\n"
- " [COMMENT comment] [VERBATIM])\n"
+ " [COMMENT comment] [VERBATIM]\n"
+ " [CONFIG Debug | MinSizeRel | Release | RelWithDebInfo | ...])\n"
"This defines a new command that will be associated with "
"building the specified target. When the command will "
"happen is determined by which of the following is specified:\n"
@@ -158,6 +160,10 @@ public:
"if the target is an executable or library a file-level dependency "
"is created to cause the custom command to re-run whenever the target "
"is recompiled.\n"
+
+ "The CONFIG option specifies that the custom command(s) should run "
+ "only when the given build configuration is active. This option allows "
+ "custom commands to have configuration specific behavior.\n"
;
}
diff --git a/Source/cmCustomCommand.cxx b/Source/cmCustomCommand.cxx
index 5db88fa..a6f3b05 100644
--- a/Source/cmCustomCommand.cxx
+++ b/Source/cmCustomCommand.cxx
@@ -24,6 +24,7 @@ cmCustomCommand::cmCustomCommand(const cmCustomCommand& r):
Outputs(r.Outputs),
Depends(r.Depends),
CommandLines(r.CommandLines),
+ ConfigurationCommandLines(r.ConfigurationCommandLines),
HaveComment(r.HaveComment),
Comment(r.Comment),
WorkingDirectory(r.WorkingDirectory),
@@ -52,6 +53,26 @@ cmCustomCommand::cmCustomCommand(const std::vector<std::string>& outputs,
}
//----------------------------------------------------------------------------
+cmCustomCommand::cmCustomCommand(const std::vector<std::string>& outputs,
+ const std::vector<std::string>& depends,
+ const cmCustomCommandLines& commandLines,
+ const char* comment,
+ const char* workingDirectory,
+ const std::string& configName):
+ Outputs(outputs),
+ Depends(depends),
+ HaveComment(comment?true:false),
+ Comment(comment?comment:""),
+ WorkingDirectory(workingDirectory?workingDirectory:""),
+ EscapeAllowMakeVars(false),
+ EscapeOldStyle(true)
+{
+ ConfigurationCommandLines[configName] = commandLines;
+ this->EscapeOldStyle = true;
+ this->EscapeAllowMakeVars = false;
+}
+
+//----------------------------------------------------------------------------
const std::vector<std::string>& cmCustomCommand::GetOutputs() const
{
return this->Outputs;
@@ -80,6 +101,27 @@ const cmCustomCommandLines& cmCustomCommand::GetCommandLines() const
}
//----------------------------------------------------------------------------
+const cmCustomCommandLines& cmCustomCommand::GetCommandLines(const
+ std::string& configName) const
+{
+ std::map<std::string, cmCustomCommandLines>::const_iterator ci =
+ this->ConfigurationCommandLines.find(configName);
+ if(ci != this->ConfigurationCommandLines.end())
+ {
+ return ci->second;
+ }
+ return this->CommandLines;
+}
+
+//----------------------------------------------------------------------------
+const cmCustomCommandLines& cmCustomCommand::GetCommandLines(const
+ char *configName) const
+{
+ std::string config(configName);
+ return this->GetCommandLines(config);
+}
+
+//----------------------------------------------------------------------------
const char* cmCustomCommand::GetComment() const
{
const char* no_comment = 0;
@@ -97,6 +139,35 @@ void cmCustomCommand::AppendCommands(const cmCustomCommandLines& commandLines)
}
//----------------------------------------------------------------------------
+void cmCustomCommand::AppendCommands(const cmCustomCommandLines& commandLines,
+ const std::string& configName)
+{
+ cmCustomCommandLines configLines =
+ this->ConfigurationCommandLines[configName];
+ for(cmCustomCommandLines::const_iterator ci = commandLines.begin();
+ ci != commandLines.end(); ci++)
+ {
+ configLines.push_back(*ci);
+ }
+ this->ConfigurationCommandLines[configName] = configLines;
+}
+
+//----------------------------------------------------------------------------
+void cmCustomCommand::AppendCommands(const cmCustomCommandLines& commandLines,
+ const char *configName)
+{
+ std::string config(configName);
+ cmCustomCommandLines configLines =
+ this->ConfigurationCommandLines[config];
+ for(cmCustomCommandLines::const_iterator ci = commandLines.begin();
+ ci != commandLines.end(); ci++)
+ {
+ configLines.push_back(*ci);
+ }
+ this->ConfigurationCommandLines[config] = configLines;
+}
+
+//----------------------------------------------------------------------------
void cmCustomCommand::AppendDepends(const std::vector<std::string>& depends)
{
for(std::vector<std::string>::const_iterator i=depends.begin();
@@ -131,6 +202,42 @@ void cmCustomCommand::SetEscapeAllowMakeVars(bool b)
}
//----------------------------------------------------------------------------
+bool cmCustomCommand::HasCommandLines() const
+{
+ if(! this->CommandLines.empty())
+ {
+ return true;
+ }
+
+ return false;
+}
+
+//----------------------------------------------------------------------------
+bool cmCustomCommand::HasCommandLines(const std::string& configName) const
+{
+ if(! this->ConfigurationCommandLines.empty())
+ {
+ for(std::map<std::string,cmCustomCommandLines>::const_iterator ci =
+ this->ConfigurationCommandLines.begin(); ci !=
+ this->ConfigurationCommandLines.end(); ci++)
+ {
+ if(configName == ci->first && (! ci->second.empty()))
+ {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+//----------------------------------------------------------------------------
+bool cmCustomCommand::HasCommandLines(const char *configName) const
+{
+ std::string config(configName);
+ return this->HasCommandLines(config);
+}
+
+//----------------------------------------------------------------------------
cmCustomCommand::ImplicitDependsList const&
cmCustomCommand::GetImplicitDepends() const
{
diff --git a/Source/cmCustomCommand.h b/Source/cmCustomCommand.h
index c9adddf..80b6ff3 100644
--- a/Source/cmCustomCommand.h
+++ b/Source/cmCustomCommand.h
@@ -33,6 +33,14 @@ public:
const char* comment,
const char* workingDirectory);
+ /** Main constructor specifies all information for the command. */
+ cmCustomCommand(const std::vector<std::string>& outputs,
+ const std::vector<std::string>& depends,
+ const cmCustomCommandLines& commandLines,
+ const char* comment,
+ const char* workingDirectory,
+ const std::string& configName);
+
/** Get the output file produced by the command. */
const std::vector<std::string>& GetOutputs() const;
@@ -45,12 +53,28 @@ public:
/** Get the list of command lines. */
const cmCustomCommandLines& GetCommandLines() const;
+ /** Get the list of command lines by configuration. */
+ const cmCustomCommandLines&
+ GetCommandLines(const std::string& configName) const;
+
+ /** Get the list of command lines by configuration. */
+ const cmCustomCommandLines&
+ GetCommandLines(const char *configName) const;
+
/** Get the comment string for the command. */
const char* GetComment() const;
/** Append to the list of command lines. */
void AppendCommands(const cmCustomCommandLines& commandLines);
+ /** Append to the list of command lines by configuration. */
+ void AppendCommands(const cmCustomCommandLines& commandLines, const
+ std::string& configName);
+
+ /** Append to the list of command lines by configuration. */
+ void AppendCommands(const cmCustomCommandLines& commandLines, const
+ char *configName);
+
/** Append to the list of dependencies. */
void AppendDepends(const std::vector<std::string>& depends);
@@ -63,6 +87,10 @@ public:
bool GetEscapeAllowMakeVars() const;
void SetEscapeAllowMakeVars(bool b);
+ bool HasCommandLines() const;
+ bool HasCommandLines(const std::string& configName) const;
+ bool HasCommandLines(const char *configName) const;
+
typedef std::pair<cmStdString, cmStdString> ImplicitDependsPair;
class ImplicitDependsList: public std::vector<ImplicitDependsPair> {};
void SetImplicitDepends(ImplicitDependsList const&);
@@ -73,6 +101,7 @@ private:
std::vector<std::string> Outputs;
std::vector<std::string> Depends;
cmCustomCommandLines CommandLines;
+ std::map<std::string, cmCustomCommandLines> ConfigurationCommandLines;
bool HaveComment;
std::string Comment;
std::string WorkingDirectory;
diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx
index a409e5f..f7d84ec 100644
--- a/Source/cmGlobalXCodeGenerator.cxx
+++ b/Source/cmGlobalXCodeGenerator.cxx
@@ -1212,7 +1212,7 @@ cmGlobalXCodeGenerator::AddCommandsToBuildPhase(cmXCodeObject* buildphase,
i != commands.end(); ++i)
{
cmCustomCommand const& cc = *i;
- if(!cc.GetCommandLines().empty())
+ if(cc.HasCommandLines())
{
const std::vector<std::string>& outputs = cc.GetOutputs();
if(!outputs.empty())
@@ -1302,7 +1302,7 @@ void cmGlobalXCodeGenerator
i != commands.end(); ++i)
{
cmCustomCommand const& cc = *i;
- if(!cc.GetCommandLines().empty())
+ if(cc.HasCommandLines() || cc.HasCommandLines(configName))
{
const std::vector<std::string>& outputs = cc.GetOutputs();
if(!outputs.empty())
@@ -1328,7 +1328,7 @@ void cmGlobalXCodeGenerator
i != commands.end(); ++i)
{
cmCustomCommand const& cc = *i;
- if(!cc.GetCommandLines().empty())
+ if(cc.HasCommandLines() || cc.HasCommandLines(configName))
{
bool escapeOldStyle = cc.GetEscapeOldStyle();
bool escapeAllowMakeVars = cc.GetEscapeAllowMakeVars();
@@ -1366,10 +1366,20 @@ void cmGlobalXCodeGenerator
makefileStream << "\t" << echo_cmd.c_str() << "\n";
}
+ cmCustomCommandLines lines;
+
+ if(cc.HasCommandLines(configName))
+ {
+ lines = cc.GetCommandLines(configName);
+ }
+ else
+ {
+ lines = cc.GetCommandLines();
+ }
+
// Add each command line to the set of commands.
for(cmCustomCommandLines::const_iterator cl =
- cc.GetCommandLines().begin();
- cl != cc.GetCommandLines().end(); ++cl)
+ lines.begin(); cl != lines.end(); ++cl)
{
// Build the command line in a single string.
const cmCustomCommandLine& commandLine = *cl;
diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx
index fce5a9c..1685945 100644
--- a/Source/cmLocalUnixMakefileGenerator3.cxx
+++ b/Source/cmLocalUnixMakefileGenerator3.cxx
@@ -962,10 +962,24 @@ cmLocalUnixMakefileGenerator3
bool escapeOldStyle = cc.GetEscapeOldStyle();
bool escapeAllowMakeVars = cc.GetEscapeAllowMakeVars();
+ cmCustomCommandLines lines;
+
+ const char *buildType =
+ this->Makefile->GetDefinition("CMAKE_BUILD_TYPE");
+
+ if(buildType && cc.HasCommandLines(buildType))
+ {
+ lines = cc.GetCommandLines(buildType);
+ }
+ else
+ {
+ lines = cc.GetCommandLines();
+ }
+
// 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(cmCustomCommandLines::const_iterator cl = lines.begin();
+ cl != lines.end(); ++cl)
{
// Build the command line in a single string.
const cmCustomCommandLine& commandLine = *cl;
diff --git a/Source/cmLocalVisualStudio6Generator.cxx b/Source/cmLocalVisualStudio6Generator.cxx
index 2cf840d..ee9815e 100644
--- a/Source/cmLocalVisualStudio6Generator.cxx
+++ b/Source/cmLocalVisualStudio6Generator.cxx
@@ -65,8 +65,19 @@ public:
{
this->Code += "\\\n\t";
}
+
+ cmCustomCommandLines lines;
+ if(cc.HasCommandLines(this->Config))
+ {
+ lines = cc.GetCommandLines(this->Config);
+ }
+ else
+ {
+ lines = cc.GetCommandLines();
+ }
+
this->Code +=
- this->LG->ConstructScript(cc.GetCommandLines(),
+ this->LG->ConstructScript(lines,
cc.GetWorkingDirectory(),
this->Config,
cc.GetEscapeOldStyle(),
@@ -658,8 +669,19 @@ cmLocalVisualStudio6Generator
for(i = this->Configurations.begin(); i != this->Configurations.end(); ++i)
{
std::string config = this->GetConfigName(*i);
+
+ cmCustomCommandLines lines;
+ if(command.HasCommandLines(*i))
+ {
+ lines = command.GetCommandLines(*i);
+ }
+ else
+ {
+ lines = command.GetCommandLines();
+ }
+
std::string script =
- this->ConstructScript(command.GetCommandLines(),
+ this->ConstructScript(lines,
command.GetWorkingDirectory(),
config.c_str(),
command.GetEscapeOldStyle(),
diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx
index 2084808..f1232f9 100644
--- a/Source/cmLocalVisualStudio7Generator.cxx
+++ b/Source/cmLocalVisualStudio7Generator.cxx
@@ -523,8 +523,19 @@ public:
{
this->Stream << this->LG->EscapeForXML("\n");
}
+
+ cmCustomCommandLines lines;
+ if(cc.HasCommandLines(this->Config))
+ {
+ lines = cc.GetCommandLines(this->Config);
+ }
+ else
+ {
+ lines = cc.GetCommandLines();
+ }
+
std::string script =
- this->LG->ConstructScript(cc.GetCommandLines(),
+ this->LG->ConstructScript(lines,
cc.GetWorkingDirectory(),
this->Config,
cc.GetEscapeOldStyle(),
@@ -1544,8 +1555,18 @@ WriteCustomRule(std::ostream& fout,
<< this->EscapeForXML(fc.CompileFlags.c_str()) << "\"/>\n";
}
+ cmCustomCommandLines lines;
+ if(command.HasCommandLines(*i))
+ {
+ lines = command.GetCommandLines(*i);
+ }
+ else
+ {
+ lines = command.GetCommandLines();
+ }
+
std::string script =
- this->ConstructScript(command.GetCommandLines(),
+ this->ConstructScript(lines,
command.GetWorkingDirectory(),
i->c_str(),
command.GetEscapeOldStyle(),
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index d09188a..c994346 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -850,6 +850,41 @@ cmMakefile::AddCustomCommandToTarget(const char* target,
//----------------------------------------------------------------------------
void
+cmMakefile::AddCustomCommandToTarget(const char* target,
+ const std::vector<std::string>& depends,
+ const cmCustomCommandLines& commandLines,
+ cmTarget::CustomCommandType type,
+ const char* comment,
+ const char* workingDir,
+ const std::string& configName,
+ bool escapeOldStyle)
+{
+ // Find the target to which to add the custom command.
+ cmTargets::iterator ti = this->Targets.find(target);
+ if(ti != this->Targets.end())
+ {
+ // 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, configName);
+ cc.SetEscapeOldStyle(escapeOldStyle);
+ cc.SetEscapeAllowMakeVars(true);
+ switch(type)
+ {
+ case cmTarget::PRE_BUILD:
+ ti->second.GetPreBuildCommands().push_back(cc);
+ break;
+ case cmTarget::PRE_LINK:
+ ti->second.GetPreLinkCommands().push_back(cc);
+ break;
+ case cmTarget::POST_BUILD:
+ ti->second.GetPostBuildCommands().push_back(cc);
+ break;
+ }
+ }
+}
+
+//----------------------------------------------------------------------------
+void
cmMakefile::AddCustomCommandToOutput(const std::vector<std::string>& outputs,
const std::vector<std::string>& depends,
const char* main_dependency,
@@ -952,6 +987,119 @@ cmMakefile::AddCustomCommandToOutput(const std::vector<std::string>& outputs,
//----------------------------------------------------------------------------
void
+cmMakefile::AddCustomCommandToOutput(const std::vector<std::string>& outputs,
+ const std::vector<std::string>& depends,
+ const char* main_dependency,
+ const cmCustomCommandLines& commandLines,
+ const char* comment,
+ const char* workingDir,
+ const std::string& configName,
+ bool replace,
+ bool escapeOldStyle)
+{
+ // Make sure there is at least one output.
+ if(outputs.empty())
+ {
+ cmSystemTools::Error("Attempt to add a custom rule with no output!");
+ return;
+ }
+
+ // Choose a source file on which to store the custom command.
+ cmSourceFile* file = 0;
+ if(main_dependency && main_dependency[0])
+ {
+ // The main dependency was specified. Use it unless a different
+ // custom command already used it.
+ file = this->GetSource(main_dependency);
+ if(file && file->GetCustomCommand() && !replace)
+ {
+ // The main dependency already has a custom command.
+ if(commandLines == file->GetCustomCommand()->GetCommandLines(configName))
+ {
+ // The existing custom command is identical. Silently ignore
+ // the duplicate.
+ return;
+ }
+ else
+ {
+ // The existing custom command is different. We need to
+ // generate a rule file for this new command.
+ file = 0;
+ }
+ }
+ else
+ {
+ // The main dependency does not have a custom command or we are
+ // allowed to replace it. Use it to store the command.
+ file = this->GetOrCreateSource(main_dependency);
+ }
+ }
+
+ // Generate a rule file if the main dependency is not available.
+ if(!file)
+ {
+ // Construct a rule file associated with the first output produced.
+ std::string outName = outputs[0];
+ outName += ".rule";
+ // Check if the rule file already exists.
+ file = this->GetSource(outName.c_str());
+ if(file && file->GetCustomCommand() && !replace)
+ {
+ // The rule file already exists.
+ cmCustomCommand *cc = file->GetCustomCommand();
+
+ if(cc->HasCommandLines(configName))
+ {
+ if(commandLines != cc->GetCommandLines(configName))
+ {
+ cmSystemTools::Error("Attempt to add a custom rule to output \"",
+ outName.c_str(),
+ "\" which already has a custom rule for ",
+ "configuration \"", configName.c_str(), "\".");
+ }
+ }
+ else
+ {
+ cc->AppendCommands(commandLines, configName);
+ }
+ return;
+ }
+
+ // Create a cmSourceFile for the rule file.
+ file = this->GetOrCreateSource(outName.c_str(), true);
+ }
+
+ // Always create the output sources and mark them generated.
+ for(std::vector<std::string>::const_iterator o = outputs.begin();
+ o != outputs.end(); ++o)
+ {
+ if(cmSourceFile* out = this->GetOrCreateSource(o->c_str(), true))
+ {
+ out->SetProperty("GENERATED", "1");
+ }
+ }
+
+ // Construct a complete list of dependencies.
+ std::vector<std::string> depends2(depends);
+ if(main_dependency && main_dependency[0])
+ {
+ depends2.push_back(main_dependency);
+ }
+
+ // Attach the custom command to the file.
+ if(file)
+ {
+ cmCustomCommand* cc =
+ new cmCustomCommand(outputs, depends2, commandLines,
+ comment, workingDir, configName);
+ cc->SetEscapeOldStyle(escapeOldStyle);
+ cc->SetEscapeAllowMakeVars(true);
+ file->SetCustomCommand(cc);
+ }
+}
+
+//----------------------------------------------------------------------------
+void
cmMakefile::AddCustomCommandToOutput(const char* output,
const std::vector<std::string>& depends,
const char* main_dependency,
@@ -970,6 +1118,25 @@ cmMakefile::AddCustomCommandToOutput(const char* output,
//----------------------------------------------------------------------------
void
+cmMakefile::AddCustomCommandToOutput(const char* output,
+ const std::vector<std::string>& depends,
+ const char* main_dependency,
+ const cmCustomCommandLines& commandLines,
+ const char* comment,
+ const char* workingDir,
+ const std::string& configName,
+ bool replace,
+ bool escapeOldStyle)
+{
+ std::vector<std::string> outputs;
+ outputs.push_back(output);
+ this->AddCustomCommandToOutput(outputs, depends, main_dependency,
+ commandLines, comment, workingDir,
+ configName, replace, escapeOldStyle);
+}
+
+//----------------------------------------------------------------------------
+void
cmMakefile::AddCustomCommandOldStyle(const char* target,
const std::vector<std::string>& outputs,
const std::vector<std::string>& depends,
@@ -1038,6 +1205,77 @@ cmMakefile::AddCustomCommandOldStyle(const char* target,
}
//----------------------------------------------------------------------------
+void
+cmMakefile::AddCustomCommandOldStyle(const char* target,
+ const std::vector<std::string>& outputs,
+ const std::vector<std::string>& depends,
+ const char* source,
+ const cmCustomCommandLines& commandLines,
+ const char* comment,
+ const std::string& configName)
+{
+ // Translate the old-style signature to one of the new-style
+ // signatures.
+ if(strcmp(source, target) == 0)
+ {
+ // In the old-style signature if the source and target were the
+ // same then it added a post-build rule to the target. Preserve
+ // this behavior.
+ this->AddCustomCommandToTarget(target, depends, commandLines,
+ cmTarget::POST_BUILD, comment, 0,
+ configName);
+ return;
+ }
+
+ // Each output must get its own copy of this rule.
+ cmsys::RegularExpression sourceFiles("\\.(C|M|c|c\\+\\+|cc|cpp|cxx|m|mm|"
+ "rc|def|r|odl|idl|hpj|bat|h|h\\+\\+|"
+ "hm|hpp|hxx|in|txx|inl)$");
+ for(std::vector<std::string>::const_iterator oi = outputs.begin();
+ oi != outputs.end(); ++oi)
+ {
+ // Get the name of this output.
+ const char* output = oi->c_str();
+
+ // Choose whether to use a main dependency.
+ if(sourceFiles.find(source))
+ {
+ // The source looks like a real file. Use it as the main dependency.
+ this->AddCustomCommandToOutput(output, depends, source,
+ commandLines, comment, 0, configName);
+ }
+ else
+ {
+ // The source may not be a real file. Do not use a main dependency.
+ const char* no_main_dependency = 0;
+ std::vector<std::string> depends2 = depends;
+ depends2.push_back(source);
+ this->AddCustomCommandToOutput(output, depends2, no_main_dependency,
+ commandLines, comment, 0, configName);
+ }
+
+ // If the rule was added to the source (and not a .rule file),
+ // then add the source to the target to make sure the rule is
+ // included.
+ std::string sname = output;
+ sname += ".rule";
+ if(!this->GetSource(sname.c_str()))
+ {
+ if (this->Targets.find(target) != this->Targets.end())
+ {
+ this->Targets[target].AddSource(source);
+ }
+ else
+ {
+ cmSystemTools::Error("Attempt to add a custom rule to a target "
+ "that does not exist yet for target ", target);
+ return;
+ }
+ }
+ }
+}
+
+//----------------------------------------------------------------------------
void cmMakefile::AddUtilityCommand(const char* utilityName,
bool excludeFromAll,
const std::vector<std::string>& depends,
diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h
index 63f81b8..376f166 100644
--- a/Source/cmMakefile.h
+++ b/Source/cmMakefile.h
@@ -167,6 +167,14 @@ public:
cmTarget::CustomCommandType type,
const char* comment, const char* workingDir,
bool escapeOldStyle = true);
+ void AddCustomCommandToTarget(const char* target,
+ const std::vector<std::string>& depends,
+ const cmCustomCommandLines& commandLines,
+ cmTarget::CustomCommandType type,
+ const char* comment, const char* workingDir,
+ const std::string& configName,
+ bool escapeOldStyle = true);
+
void AddCustomCommandToOutput(const std::vector<std::string>& outputs,
const std::vector<std::string>& depends,
const char* main_dependency,
@@ -174,19 +182,45 @@ public:
const char* comment, const char* workingDir,
bool replace = false,
bool escapeOldStyle = true);
+ void AddCustomCommandToOutput(const std::vector<std::string>& outputs,
+ const std::vector<std::string>& depends,
+ const char* main_dependency,
+ const cmCustomCommandLines& commandLines,
+ const char* comment, const char* workingDir,
+ const std::string& configName,
+ bool replace = false,
+ bool escapeOldStyle = true);
+
+
+ void AddCustomCommandToOutput(const char* output,
+ const std::vector<std::string>& depends,
+ const char* main_dependency,
+ const cmCustomCommandLines& commandLines,
+ const char* comment, const char* workingDir,
+ bool replace = false,
+ bool escapeOldStyle = true);
void AddCustomCommandToOutput(const char* output,
const std::vector<std::string>& depends,
const char* main_dependency,
const cmCustomCommandLines& commandLines,
const char* comment, const char* workingDir,
+ const std::string& configName,
bool replace = false,
bool escapeOldStyle = true);
+
void AddCustomCommandOldStyle(const char* target,
const std::vector<std::string>& outputs,
const std::vector<std::string>& depends,
const char* source,
const cmCustomCommandLines& commandLines,
const char* comment);
+ void AddCustomCommandOldStyle(const char* target,
+ const std::vector<std::string>& outputs,
+ const std::vector<std::string>& depends,
+ const char* source,
+ const cmCustomCommandLines& commandLines,
+ const char* comment,
+ const std::string& configName);
/**
* Add a define flag to the build.
diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx
index f5fba5c..e698f60 100644
--- a/Source/cmSystemTools.cxx
+++ b/Source/cmSystemTools.cxx
@@ -235,7 +235,8 @@ std::string cmSystemTools::EscapeSpaces(const char* str)
}
void cmSystemTools::Error(const char* m1, const char* m2,
- const char* m3, const char* m4)
+ const char* m3, const char* m4,
+ const char* m5, const char* m6)
{
std::string message = "CMake Error: ";
if(m1)
@@ -254,6 +255,14 @@ void cmSystemTools::Error(const char* m1, const char* m2,
{
message += m4;
}
+ if(m5)
+ {
+ message += m5;
+ }
+ if(m6)
+ {
+ message += m6;
+ }
cmSystemTools::s_ErrorOccured = true;
cmSystemTools::Message(message.c_str(),"Error");
}
diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h
index 6364870..e1a3101 100644
--- a/Source/cmSystemTools.h
+++ b/Source/cmSystemTools.h
@@ -68,7 +68,8 @@ public:
* Display an error message.
*/
static void Error(const char* m, const char* m2=0,
- const char* m3=0, const char* m4=0);
+ const char* m3=0, const char* m4=0, const char *m5=0,
+ const char *m6=0);
/**
* Display a message.
diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx
index 17d1685..0b5996a 100644
--- a/Source/cmVisualStudio10TargetGenerator.cxx
+++ b/Source/cmVisualStudio10TargetGenerator.cxx
@@ -331,9 +331,19 @@ cmVisualStudio10TargetGenerator::WriteCustomRule(cmSourceFile* source,
for(std::vector<std::string>::iterator i = configs->begin();
i != configs->end(); ++i)
{
+ cmCustomCommandLines lines;
+ if(command.HasCommandLines(*i))
+ {
+ lines = command.GetCommandLines(*i);
+ }
+ else
+ {
+ lines = command.GetCommandLines();
+ }
+
std::string script =
cmVS10EscapeXML(
- lg->ConstructScript(command.GetCommandLines(),
+ lg->ConstructScript(lines,
command.GetWorkingDirectory(),
i->c_str(),
command.GetEscapeOldStyle(),
@@ -1309,9 +1319,20 @@ void cmVisualStudio10TargetGenerator::WriteEvent(
comment += lg->ConstructComment(command);
script += pre;
pre = "\n";
+
+ cmCustomCommandLines lines;
+ if(command.HasCommandLines(configName))
+ {
+ lines = command.GetCommandLines(configName);
+ }
+ else
+ {
+ lines = command.GetCommandLines();
+ }
+
script +=
cmVS10EscapeXML(
- lg->ConstructScript(command.GetCommandLines(),
+ lg->ConstructScript(lines,
command.GetWorkingDirectory(),
configName.c_str(),
command.GetEscapeOldStyle(),
--
1.7.2.3
a14a8562+0001-Per-config-add_custom_command.patch [^] (39,620 bytes) 2010-12-15 14:26 [Show Content] [Hide Content]From 47d23f42db075a3cd65fb4f650ac3a03d10a6be8 Mon Sep 17 00:00:00 2001
From: Steven Wilson <steven.wesley.wilson@gmail.com>
Date: Fri, 27 Nov 2009 19:19:00 -0500
Subject: [PATCH] Per-config add_custom_command
Add a new keyword to the add_custom_command CMake directive called
CONFIG. The CONFIG option specifies that the custom command(s) should
run only when the given build configuration is active. This option
allows custom commands to have configuration specific behavior. When
the CONFIG option is not present, add_custom_command command behaves as
before.
---
Source/cmAddCustomCommandCommand.cxx | 74 +++++++--
Source/cmAddCustomCommandCommand.h | 10 +-
Source/cmCustomCommand.cxx | 107 +++++++++++++
Source/cmCustomCommand.h | 29 ++++
Source/cmGlobalXCodeGenerator.cxx | 20 ++-
Source/cmLocalUnixMakefileGenerator3.cxx | 18 ++-
Source/cmLocalVisualStudio6Generator.cxx | 26 +++-
Source/cmLocalVisualStudio7Generator.cxx | 25 +++-
Source/cmMakefile.cxx | 238 ++++++++++++++++++++++++++++
Source/cmMakefile.h | 34 ++++
Source/cmSystemTools.cxx | 11 ++-
Source/cmSystemTools.h | 3 +-
Source/cmVisualStudio10TargetGenerator.cxx | 25 +++-
13 files changed, 590 insertions(+), 30 deletions(-)
diff --git a/Source/cmAddCustomCommandCommand.cxx b/Source/cmAddCustomCommandCommand.cxx
index f6b3234..24a1efe 100644
--- a/Source/cmAddCustomCommandCommand.cxx
+++ b/Source/cmAddCustomCommandCommand.cxx
@@ -37,6 +37,7 @@ bool cmAddCustomCommandCommand
bool append = false;
std::string implicit_depends_lang;
cmCustomCommand::ImplicitDependsList implicit_depends;
+ std::string intendedConfig;
// Accumulate one command line at a time.
cmCustomCommandLine currentLine;
@@ -58,6 +59,7 @@ bool cmAddCustomCommandCommand
doing_outputs,
doing_comment,
doing_working_directory,
+ doing_config,
doing_nothing
};
@@ -138,6 +140,10 @@ bool cmAddCustomCommandCommand
{
doing = doing_comment;
}
+ else if (copy == "CONFIG")
+ {
+ doing = doing_config;
+ }
else
{
std::string filename;
@@ -221,6 +227,9 @@ bool cmAddCustomCommandCommand
comment_buffer = copy;
comment = comment_buffer.c_str();
break;
+ case doing_config:
+ intendedConfig = copy;
+ break;
default:
this->SetError("Wrong syntax. Unknown type of argument.");
return false;
@@ -270,7 +279,14 @@ bool cmAddCustomCommandCommand
{
if(cmCustomCommand* cc = sf->GetCustomCommand())
{
- cc->AppendCommands(commandLines);
+ if(! intendedConfig.empty())
+ {
+ cc->AppendCommands(commandLines, intendedConfig);
+ }
+ else
+ {
+ cc->AppendCommands(commandLines);
+ }
cc->AppendDepends(depends);
cc->AppendImplicitDepends(implicit_depends);
return true;
@@ -291,19 +307,42 @@ bool cmAddCustomCommandCommand
{
// Source is empty, use the target.
std::vector<std::string> no_depends;
- this->Makefile->AddCustomCommandToTarget(target.c_str(), no_depends,
- commandLines, cctype,
- comment, working.c_str(),
- escapeOldStyle);
+ if(! intendedConfig.empty())
+ {
+ this->Makefile->AddCustomCommandToTarget(target.c_str(), no_depends,
+ commandLines, cctype,
+ comment, working.c_str(),
+ intendedConfig,
+ escapeOldStyle);
+ }
+ else
+ {
+ this->Makefile->AddCustomCommandToTarget(target.c_str(), no_depends,
+ commandLines, cctype,
+ comment, working.c_str(),
+ escapeOldStyle);
+ }
}
else if(target.empty())
{
// Target is empty, use the output.
- this->Makefile->AddCustomCommandToOutput(output, depends,
- main_dependency.c_str(),
- commandLines, comment,
- working.c_str(), false,
- escapeOldStyle);
+ if(! intendedConfig.empty())
+ {
+ this->Makefile->AddCustomCommandToOutput(output, depends,
+ main_dependency.c_str(),
+ commandLines, comment,
+ working.c_str(),
+ intendedConfig, false,
+ escapeOldStyle);
+ }
+ else
+ {
+ this->Makefile->AddCustomCommandToOutput(output, depends,
+ main_dependency.c_str(),
+ commandLines, comment,
+ working.c_str(), false,
+ escapeOldStyle);
+ }
// Add implicit dependency scanning requests if any were given.
if(!implicit_depends.empty())
@@ -331,9 +370,18 @@ bool cmAddCustomCommandCommand
else
{
// Use the old-style mode for backward compatibility.
- this->Makefile->AddCustomCommandOldStyle(target.c_str(), outputs, depends,
- source.c_str(), commandLines,
- comment);
+ if(! intendedConfig.empty())
+ {
+ this->Makefile->AddCustomCommandOldStyle(target.c_str(), outputs, depends,
+ source.c_str(), commandLines,
+ comment, intendedConfig);
+ }
+ else
+ {
+ this->Makefile->AddCustomCommandOldStyle(target.c_str(), outputs, depends,
+ source.c_str(), commandLines,
+ comment);
+ }
}
return true;
diff --git a/Source/cmAddCustomCommandCommand.h b/Source/cmAddCustomCommandCommand.h
index 6c5e1af..7799983 100644
--- a/Source/cmAddCustomCommandCommand.h
+++ b/Source/cmAddCustomCommandCommand.h
@@ -69,7 +69,8 @@ public:
" [DEPENDS [depends...]]\n"
" [IMPLICIT_DEPENDS <lang1> depend1 ...]\n"
" [WORKING_DIRECTORY dir]\n"
- " [COMMENT comment] [VERBATIM] [APPEND])\n"
+ " [COMMENT comment] [VERBATIM] [APPEND]\n"
+ " [CONFIG Debug | MinSizeRel | Release | RelWithDebInfo | ...])\n"
"This defines a command to generate specified OUTPUT file(s). "
"A target created in the same directory (CMakeLists.txt file) that "
"specifies any output of the custom command as a source file is given "
@@ -97,7 +98,8 @@ public:
" COMMAND command1 [ARGS] [args1...]\n"
" [COMMAND command2 [ARGS] [args2...] ...]\n"
" [WORKING_DIRECTORY dir]\n"
- " [COMMENT comment] [VERBATIM])\n"
+ " [COMMENT comment] [VERBATIM]\n"
+ " [CONFIG Debug | MinSizeRel | Release | RelWithDebInfo | ...])\n"
"This defines a new command that will be associated with "
"building the specified target. When the command will "
"happen is determined by which of the following is specified:\n"
@@ -161,6 +163,10 @@ public:
"if the target is an executable or library a file-level dependency "
"is created to cause the custom command to re-run whenever the target "
"is recompiled.\n"
+
+ "The CONFIG option specifies that the custom command(s) should run "
+ "only when the given build configuration is active. This option allows "
+ "custom commands to have configuration specific behavior.\n"
;
}
diff --git a/Source/cmCustomCommand.cxx b/Source/cmCustomCommand.cxx
index 5db88fa..a6f3b05 100644
--- a/Source/cmCustomCommand.cxx
+++ b/Source/cmCustomCommand.cxx
@@ -24,6 +24,7 @@ cmCustomCommand::cmCustomCommand(const cmCustomCommand& r):
Outputs(r.Outputs),
Depends(r.Depends),
CommandLines(r.CommandLines),
+ ConfigurationCommandLines(r.ConfigurationCommandLines),
HaveComment(r.HaveComment),
Comment(r.Comment),
WorkingDirectory(r.WorkingDirectory),
@@ -52,6 +53,26 @@ cmCustomCommand::cmCustomCommand(const std::vector<std::string>& outputs,
}
//----------------------------------------------------------------------------
+cmCustomCommand::cmCustomCommand(const std::vector<std::string>& outputs,
+ const std::vector<std::string>& depends,
+ const cmCustomCommandLines& commandLines,
+ const char* comment,
+ const char* workingDirectory,
+ const std::string& configName):
+ Outputs(outputs),
+ Depends(depends),
+ HaveComment(comment?true:false),
+ Comment(comment?comment:""),
+ WorkingDirectory(workingDirectory?workingDirectory:""),
+ EscapeAllowMakeVars(false),
+ EscapeOldStyle(true)
+{
+ ConfigurationCommandLines[configName] = commandLines;
+ this->EscapeOldStyle = true;
+ this->EscapeAllowMakeVars = false;
+}
+
+//----------------------------------------------------------------------------
const std::vector<std::string>& cmCustomCommand::GetOutputs() const
{
return this->Outputs;
@@ -80,6 +101,27 @@ const cmCustomCommandLines& cmCustomCommand::GetCommandLines() const
}
//----------------------------------------------------------------------------
+const cmCustomCommandLines& cmCustomCommand::GetCommandLines(const
+ std::string& configName) const
+{
+ std::map<std::string, cmCustomCommandLines>::const_iterator ci =
+ this->ConfigurationCommandLines.find(configName);
+ if(ci != this->ConfigurationCommandLines.end())
+ {
+ return ci->second;
+ }
+ return this->CommandLines;
+}
+
+//----------------------------------------------------------------------------
+const cmCustomCommandLines& cmCustomCommand::GetCommandLines(const
+ char *configName) const
+{
+ std::string config(configName);
+ return this->GetCommandLines(config);
+}
+
+//----------------------------------------------------------------------------
const char* cmCustomCommand::GetComment() const
{
const char* no_comment = 0;
@@ -97,6 +139,35 @@ void cmCustomCommand::AppendCommands(const cmCustomCommandLines& commandLines)
}
//----------------------------------------------------------------------------
+void cmCustomCommand::AppendCommands(const cmCustomCommandLines& commandLines,
+ const std::string& configName)
+{
+ cmCustomCommandLines configLines =
+ this->ConfigurationCommandLines[configName];
+ for(cmCustomCommandLines::const_iterator ci = commandLines.begin();
+ ci != commandLines.end(); ci++)
+ {
+ configLines.push_back(*ci);
+ }
+ this->ConfigurationCommandLines[configName] = configLines;
+}
+
+//----------------------------------------------------------------------------
+void cmCustomCommand::AppendCommands(const cmCustomCommandLines& commandLines,
+ const char *configName)
+{
+ std::string config(configName);
+ cmCustomCommandLines configLines =
+ this->ConfigurationCommandLines[config];
+ for(cmCustomCommandLines::const_iterator ci = commandLines.begin();
+ ci != commandLines.end(); ci++)
+ {
+ configLines.push_back(*ci);
+ }
+ this->ConfigurationCommandLines[config] = configLines;
+}
+
+//----------------------------------------------------------------------------
void cmCustomCommand::AppendDepends(const std::vector<std::string>& depends)
{
for(std::vector<std::string>::const_iterator i=depends.begin();
@@ -131,6 +202,42 @@ void cmCustomCommand::SetEscapeAllowMakeVars(bool b)
}
//----------------------------------------------------------------------------
+bool cmCustomCommand::HasCommandLines() const
+{
+ if(! this->CommandLines.empty())
+ {
+ return true;
+ }
+
+ return false;
+}
+
+//----------------------------------------------------------------------------
+bool cmCustomCommand::HasCommandLines(const std::string& configName) const
+{
+ if(! this->ConfigurationCommandLines.empty())
+ {
+ for(std::map<std::string,cmCustomCommandLines>::const_iterator ci =
+ this->ConfigurationCommandLines.begin(); ci !=
+ this->ConfigurationCommandLines.end(); ci++)
+ {
+ if(configName == ci->first && (! ci->second.empty()))
+ {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+//----------------------------------------------------------------------------
+bool cmCustomCommand::HasCommandLines(const char *configName) const
+{
+ std::string config(configName);
+ return this->HasCommandLines(config);
+}
+
+//----------------------------------------------------------------------------
cmCustomCommand::ImplicitDependsList const&
cmCustomCommand::GetImplicitDepends() const
{
diff --git a/Source/cmCustomCommand.h b/Source/cmCustomCommand.h
index c9adddf..80b6ff3 100644
--- a/Source/cmCustomCommand.h
+++ b/Source/cmCustomCommand.h
@@ -33,6 +33,14 @@ public:
const char* comment,
const char* workingDirectory);
+ /** Main constructor specifies all information for the command. */
+ cmCustomCommand(const std::vector<std::string>& outputs,
+ const std::vector<std::string>& depends,
+ const cmCustomCommandLines& commandLines,
+ const char* comment,
+ const char* workingDirectory,
+ const std::string& configName);
+
/** Get the output file produced by the command. */
const std::vector<std::string>& GetOutputs() const;
@@ -45,12 +53,28 @@ public:
/** Get the list of command lines. */
const cmCustomCommandLines& GetCommandLines() const;
+ /** Get the list of command lines by configuration. */
+ const cmCustomCommandLines&
+ GetCommandLines(const std::string& configName) const;
+
+ /** Get the list of command lines by configuration. */
+ const cmCustomCommandLines&
+ GetCommandLines(const char *configName) const;
+
/** Get the comment string for the command. */
const char* GetComment() const;
/** Append to the list of command lines. */
void AppendCommands(const cmCustomCommandLines& commandLines);
+ /** Append to the list of command lines by configuration. */
+ void AppendCommands(const cmCustomCommandLines& commandLines, const
+ std::string& configName);
+
+ /** Append to the list of command lines by configuration. */
+ void AppendCommands(const cmCustomCommandLines& commandLines, const
+ char *configName);
+
/** Append to the list of dependencies. */
void AppendDepends(const std::vector<std::string>& depends);
@@ -63,6 +87,10 @@ public:
bool GetEscapeAllowMakeVars() const;
void SetEscapeAllowMakeVars(bool b);
+ bool HasCommandLines() const;
+ bool HasCommandLines(const std::string& configName) const;
+ bool HasCommandLines(const char *configName) const;
+
typedef std::pair<cmStdString, cmStdString> ImplicitDependsPair;
class ImplicitDependsList: public std::vector<ImplicitDependsPair> {};
void SetImplicitDepends(ImplicitDependsList const&);
@@ -73,6 +101,7 @@ private:
std::vector<std::string> Outputs;
std::vector<std::string> Depends;
cmCustomCommandLines CommandLines;
+ std::map<std::string, cmCustomCommandLines> ConfigurationCommandLines;
bool HaveComment;
std::string Comment;
std::string WorkingDirectory;
diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx
index 29c2d06..bbb392c 100644
--- a/Source/cmGlobalXCodeGenerator.cxx
+++ b/Source/cmGlobalXCodeGenerator.cxx
@@ -1196,7 +1196,7 @@ cmGlobalXCodeGenerator::AddCommandsToBuildPhase(cmXCodeObject* buildphase,
i != commands.end(); ++i)
{
cmCustomCommand const& cc = *i;
- if(!cc.GetCommandLines().empty())
+ if(cc.HasCommandLines())
{
const std::vector<std::string>& outputs = cc.GetOutputs();
if(!outputs.empty())
@@ -1286,7 +1286,7 @@ void cmGlobalXCodeGenerator
i != commands.end(); ++i)
{
cmCustomCommand const& cc = *i;
- if(!cc.GetCommandLines().empty())
+ if(cc.HasCommandLines() || cc.HasCommandLines(configName))
{
const std::vector<std::string>& outputs = cc.GetOutputs();
if(!outputs.empty())
@@ -1312,7 +1312,7 @@ void cmGlobalXCodeGenerator
i != commands.end(); ++i)
{
cmCustomCommand const& cc = *i;
- if(!cc.GetCommandLines().empty())
+ if(cc.HasCommandLines() || cc.HasCommandLines(configName))
{
bool escapeOldStyle = cc.GetEscapeOldStyle();
bool escapeAllowMakeVars = cc.GetEscapeAllowMakeVars();
@@ -1352,10 +1352,20 @@ void cmGlobalXCodeGenerator
makefileStream << "\t" << echo_cmd.c_str() << "\n";
}
+ cmCustomCommandLines lines;
+
+ if(cc.HasCommandLines(configName))
+ {
+ lines = cc.GetCommandLines(configName);
+ }
+ else
+ {
+ lines = cc.GetCommandLines();
+ }
+
// Add each command line to the set of commands.
for(cmCustomCommandLines::const_iterator cl =
- cc.GetCommandLines().begin();
- cl != cc.GetCommandLines().end(); ++cl)
+ lines.begin(); cl != lines.end(); ++cl)
{
// Build the command line in a single string.
const cmCustomCommandLine& commandLine = *cl;
diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx
index 15ae139..a0061a4 100644
--- a/Source/cmLocalUnixMakefileGenerator3.cxx
+++ b/Source/cmLocalUnixMakefileGenerator3.cxx
@@ -964,10 +964,24 @@ cmLocalUnixMakefileGenerator3
bool escapeOldStyle = cc.GetEscapeOldStyle();
bool escapeAllowMakeVars = cc.GetEscapeAllowMakeVars();
+ cmCustomCommandLines lines;
+
+ const char *buildType =
+ this->Makefile->GetDefinition("CMAKE_BUILD_TYPE");
+
+ if(buildType && cc.HasCommandLines(buildType))
+ {
+ lines = cc.GetCommandLines(buildType);
+ }
+ else
+ {
+ lines = cc.GetCommandLines();
+ }
+
// 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(cmCustomCommandLines::const_iterator cl = lines.begin();
+ cl != lines.end(); ++cl)
{
// Build the command line in a single string.
const cmCustomCommandLine& commandLine = *cl;
diff --git a/Source/cmLocalVisualStudio6Generator.cxx b/Source/cmLocalVisualStudio6Generator.cxx
index b50c133..0b87345 100644
--- a/Source/cmLocalVisualStudio6Generator.cxx
+++ b/Source/cmLocalVisualStudio6Generator.cxx
@@ -65,8 +65,19 @@ public:
{
this->Code += "\\\n\t";
}
+
+ cmCustomCommandLines lines;
+ if(cc.HasCommandLines(this->Config))
+ {
+ lines = cc.GetCommandLines(this->Config);
+ }
+ else
+ {
+ lines = cc.GetCommandLines();
+ }
+
this->Code +=
- this->LG->ConstructScript(cc.GetCommandLines(),
+ this->LG->ConstructScript(lines,
cc.GetWorkingDirectory(),
this->Config,
cc.GetEscapeOldStyle(),
@@ -658,8 +669,19 @@ cmLocalVisualStudio6Generator
for(i = this->Configurations.begin(); i != this->Configurations.end(); ++i)
{
std::string config = this->GetConfigName(*i);
+
+ cmCustomCommandLines lines;
+ if(command.HasCommandLines(*i))
+ {
+ lines = command.GetCommandLines(*i);
+ }
+ else
+ {
+ lines = command.GetCommandLines();
+ }
+
std::string script =
- this->ConstructScript(command.GetCommandLines(),
+ this->ConstructScript(lines,
command.GetWorkingDirectory(),
config.c_str(),
command.GetEscapeOldStyle(),
diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx
index 9a87cc4..22c9dc1 100644
--- a/Source/cmLocalVisualStudio7Generator.cxx
+++ b/Source/cmLocalVisualStudio7Generator.cxx
@@ -546,8 +546,19 @@ public:
{
this->Stream << this->LG->EscapeForXML("\n");
}
+
+ cmCustomCommandLines lines;
+ if(cc.HasCommandLines(this->Config))
+ {
+ lines = cc.GetCommandLines(this->Config);
+ }
+ else
+ {
+ lines = cc.GetCommandLines();
+ }
+
std::string script =
- this->LG->ConstructScript(cc.GetCommandLines(),
+ this->LG->ConstructScript(lines,
cc.GetWorkingDirectory(),
this->Config,
cc.GetEscapeOldStyle(),
@@ -1591,8 +1602,18 @@ WriteCustomRule(std::ostream& fout,
<< this->EscapeForXML(fc.CompileFlags.c_str()) << "\"/>\n";
}
+ cmCustomCommandLines lines;
+ if(command.HasCommandLines(*i))
+ {
+ lines = command.GetCommandLines(*i);
+ }
+ else
+ {
+ lines = command.GetCommandLines();
+ }
+
std::string script =
- this->ConstructScript(command.GetCommandLines(),
+ this->ConstructScript(lines,
command.GetWorkingDirectory(),
i->c_str(),
command.GetEscapeOldStyle(),
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index 9983e5d..088c735 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -847,6 +847,41 @@ cmMakefile::AddCustomCommandToTarget(const char* target,
//----------------------------------------------------------------------------
void
+cmMakefile::AddCustomCommandToTarget(const char* target,
+ const std::vector<std::string>& depends,
+ const cmCustomCommandLines& commandLines,
+ cmTarget::CustomCommandType type,
+ const char* comment,
+ const char* workingDir,
+ const std::string& configName,
+ bool escapeOldStyle)
+{
+ // Find the target to which to add the custom command.
+ cmTargets::iterator ti = this->Targets.find(target);
+ if(ti != this->Targets.end())
+ {
+ // 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, configName);
+ cc.SetEscapeOldStyle(escapeOldStyle);
+ cc.SetEscapeAllowMakeVars(true);
+ switch(type)
+ {
+ case cmTarget::PRE_BUILD:
+ ti->second.GetPreBuildCommands().push_back(cc);
+ break;
+ case cmTarget::PRE_LINK:
+ ti->second.GetPreLinkCommands().push_back(cc);
+ break;
+ case cmTarget::POST_BUILD:
+ ti->second.GetPostBuildCommands().push_back(cc);
+ break;
+ }
+ }
+}
+
+//----------------------------------------------------------------------------
+void
cmMakefile::AddCustomCommandToOutput(const std::vector<std::string>& outputs,
const std::vector<std::string>& depends,
const char* main_dependency,
@@ -957,6 +992,119 @@ cmMakefile::AddCustomCommandToOutput(const std::vector<std::string>& outputs,
//----------------------------------------------------------------------------
void
+cmMakefile::AddCustomCommandToOutput(const std::vector<std::string>& outputs,
+ const std::vector<std::string>& depends,
+ const char* main_dependency,
+ const cmCustomCommandLines& commandLines,
+ const char* comment,
+ const char* workingDir,
+ const std::string& configName,
+ bool replace,
+ bool escapeOldStyle)
+{
+ // Make sure there is at least one output.
+ if(outputs.empty())
+ {
+ cmSystemTools::Error("Attempt to add a custom rule with no output!");
+ return;
+ }
+
+ // Choose a source file on which to store the custom command.
+ cmSourceFile* file = 0;
+ if(main_dependency && main_dependency[0])
+ {
+ // The main dependency was specified. Use it unless a different
+ // custom command already used it.
+ file = this->GetSource(main_dependency);
+ if(file && file->GetCustomCommand() && !replace)
+ {
+ // The main dependency already has a custom command.
+ if(commandLines == file->GetCustomCommand()->GetCommandLines(configName))
+ {
+ // The existing custom command is identical. Silently ignore
+ // the duplicate.
+ return;
+ }
+ else
+ {
+ // The existing custom command is different. We need to
+ // generate a rule file for this new command.
+ file = 0;
+ }
+ }
+ else
+ {
+ // The main dependency does not have a custom command or we are
+ // allowed to replace it. Use it to store the command.
+ file = this->GetOrCreateSource(main_dependency);
+ }
+ }
+
+ // Generate a rule file if the main dependency is not available.
+ if(!file)
+ {
+ // Construct a rule file associated with the first output produced.
+ std::string outName = outputs[0];
+ outName += ".rule";
+ // Check if the rule file already exists.
+ file = this->GetSource(outName.c_str());
+ if(file && file->GetCustomCommand() && !replace)
+ {
+ // The rule file already exists.
+ cmCustomCommand *cc = file->GetCustomCommand();
+
+ if(cc->HasCommandLines(configName))
+ {
+ if(commandLines != cc->GetCommandLines(configName))
+ {
+ cmSystemTools::Error("Attempt to add a custom rule to output \"",
+ outName.c_str(),
+ "\" which already has a custom rule for ",
+ "configuration \"", configName.c_str(), "\".");
+ }
+ }
+ else
+ {
+ cc->AppendCommands(commandLines, configName);
+ }
+ return;
+ }
+
+ // Create a cmSourceFile for the rule file.
+ file = this->GetOrCreateSource(outName.c_str(), true);
+ }
+
+ // Always create the output sources and mark them generated.
+ for(std::vector<std::string>::const_iterator o = outputs.begin();
+ o != outputs.end(); ++o)
+ {
+ if(cmSourceFile* out = this->GetOrCreateSource(o->c_str(), true))
+ {
+ out->SetProperty("GENERATED", "1");
+ }
+ }
+
+ // Construct a complete list of dependencies.
+ std::vector<std::string> depends2(depends);
+ if(main_dependency && main_dependency[0])
+ {
+ depends2.push_back(main_dependency);
+ }
+
+ // Attach the custom command to the file.
+ if(file)
+ {
+ cmCustomCommand* cc =
+ new cmCustomCommand(outputs, depends2, commandLines,
+ comment, workingDir, configName);
+ cc->SetEscapeOldStyle(escapeOldStyle);
+ cc->SetEscapeAllowMakeVars(true);
+ file->SetCustomCommand(cc);
+ }
+}
+
+//----------------------------------------------------------------------------
+void
cmMakefile::AddCustomCommandToOutput(const char* output,
const std::vector<std::string>& depends,
const char* main_dependency,
@@ -975,6 +1123,25 @@ cmMakefile::AddCustomCommandToOutput(const char* output,
//----------------------------------------------------------------------------
void
+cmMakefile::AddCustomCommandToOutput(const char* output,
+ const std::vector<std::string>& depends,
+ const char* main_dependency,
+ const cmCustomCommandLines& commandLines,
+ const char* comment,
+ const char* workingDir,
+ const std::string& configName,
+ bool replace,
+ bool escapeOldStyle)
+{
+ std::vector<std::string> outputs;
+ outputs.push_back(output);
+ this->AddCustomCommandToOutput(outputs, depends, main_dependency,
+ commandLines, comment, workingDir,
+ configName, replace, escapeOldStyle);
+}
+
+//----------------------------------------------------------------------------
+void
cmMakefile::AddCustomCommandOldStyle(const char* target,
const std::vector<std::string>& outputs,
const std::vector<std::string>& depends,
@@ -1043,6 +1210,77 @@ cmMakefile::AddCustomCommandOldStyle(const char* target,
}
//----------------------------------------------------------------------------
+void
+cmMakefile::AddCustomCommandOldStyle(const char* target,
+ const std::vector<std::string>& outputs,
+ const std::vector<std::string>& depends,
+ const char* source,
+ const cmCustomCommandLines& commandLines,
+ const char* comment,
+ const std::string& configName)
+{
+ // Translate the old-style signature to one of the new-style
+ // signatures.
+ if(strcmp(source, target) == 0)
+ {
+ // In the old-style signature if the source and target were the
+ // same then it added a post-build rule to the target. Preserve
+ // this behavior.
+ this->AddCustomCommandToTarget(target, depends, commandLines,
+ cmTarget::POST_BUILD, comment, 0,
+ configName);
+ return;
+ }
+
+ // Each output must get its own copy of this rule.
+ cmsys::RegularExpression sourceFiles("\\.(C|M|c|c\\+\\+|cc|cpp|cxx|m|mm|"
+ "rc|def|r|odl|idl|hpj|bat|h|h\\+\\+|"
+ "hm|hpp|hxx|in|txx|inl)$");
+ for(std::vector<std::string>::const_iterator oi = outputs.begin();
+ oi != outputs.end(); ++oi)
+ {
+ // Get the name of this output.
+ const char* output = oi->c_str();
+
+ // Choose whether to use a main dependency.
+ if(sourceFiles.find(source))
+ {
+ // The source looks like a real file. Use it as the main dependency.
+ this->AddCustomCommandToOutput(output, depends, source,
+ commandLines, comment, 0, configName);
+ }
+ else
+ {
+ // The source may not be a real file. Do not use a main dependency.
+ const char* no_main_dependency = 0;
+ std::vector<std::string> depends2 = depends;
+ depends2.push_back(source);
+ this->AddCustomCommandToOutput(output, depends2, no_main_dependency,
+ commandLines, comment, 0, configName);
+ }
+
+ // If the rule was added to the source (and not a .rule file),
+ // then add the source to the target to make sure the rule is
+ // included.
+ std::string sname = output;
+ sname += ".rule";
+ if(!this->GetSource(sname.c_str()))
+ {
+ if (this->Targets.find(target) != this->Targets.end())
+ {
+ this->Targets[target].AddSource(source);
+ }
+ else
+ {
+ cmSystemTools::Error("Attempt to add a custom rule to a target "
+ "that does not exist yet for target ", target);
+ return;
+ }
+ }
+ }
+}
+
+//----------------------------------------------------------------------------
void cmMakefile::AddUtilityCommand(const char* utilityName,
bool excludeFromAll,
const std::vector<std::string>& depends,
diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h
index 8b8a3f8..aaa51b4 100644
--- a/Source/cmMakefile.h
+++ b/Source/cmMakefile.h
@@ -166,6 +166,14 @@ public:
cmTarget::CustomCommandType type,
const char* comment, const char* workingDir,
bool escapeOldStyle = true);
+ void AddCustomCommandToTarget(const char* target,
+ const std::vector<std::string>& depends,
+ const cmCustomCommandLines& commandLines,
+ cmTarget::CustomCommandType type,
+ const char* comment, const char* workingDir,
+ const std::string& configName,
+ bool escapeOldStyle = true);
+
void AddCustomCommandToOutput(const std::vector<std::string>& outputs,
const std::vector<std::string>& depends,
const char* main_dependency,
@@ -173,19 +181,45 @@ public:
const char* comment, const char* workingDir,
bool replace = false,
bool escapeOldStyle = true);
+ void AddCustomCommandToOutput(const std::vector<std::string>& outputs,
+ const std::vector<std::string>& depends,
+ const char* main_dependency,
+ const cmCustomCommandLines& commandLines,
+ const char* comment, const char* workingDir,
+ const std::string& configName,
+ bool replace = false,
+ bool escapeOldStyle = true);
+
+
+ void AddCustomCommandToOutput(const char* output,
+ const std::vector<std::string>& depends,
+ const char* main_dependency,
+ const cmCustomCommandLines& commandLines,
+ const char* comment, const char* workingDir,
+ bool replace = false,
+ bool escapeOldStyle = true);
void AddCustomCommandToOutput(const char* output,
const std::vector<std::string>& depends,
const char* main_dependency,
const cmCustomCommandLines& commandLines,
const char* comment, const char* workingDir,
+ const std::string& configName,
bool replace = false,
bool escapeOldStyle = true);
+
void AddCustomCommandOldStyle(const char* target,
const std::vector<std::string>& outputs,
const std::vector<std::string>& depends,
const char* source,
const cmCustomCommandLines& commandLines,
const char* comment);
+ void AddCustomCommandOldStyle(const char* target,
+ const std::vector<std::string>& outputs,
+ const std::vector<std::string>& depends,
+ const char* source,
+ const cmCustomCommandLines& commandLines,
+ const char* comment,
+ const std::string& configName);
/**
* Add a define flag to the build.
diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx
index 7bc89a4..69535b9 100644
--- a/Source/cmSystemTools.cxx
+++ b/Source/cmSystemTools.cxx
@@ -192,7 +192,8 @@ std::string cmSystemTools::EscapeQuotes(const char* str)
}
void cmSystemTools::Error(const char* m1, const char* m2,
- const char* m3, const char* m4)
+ const char* m3, const char* m4,
+ const char* m5, const char* m6)
{
std::string message = "CMake Error: ";
if(m1)
@@ -211,6 +212,14 @@ void cmSystemTools::Error(const char* m1, const char* m2,
{
message += m4;
}
+ if(m5)
+ {
+ message += m5;
+ }
+ if(m6)
+ {
+ message += m6;
+ }
cmSystemTools::s_ErrorOccured = true;
cmSystemTools::Message(message.c_str(),"Error");
}
diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h
index 6f9147c..676b539 100644
--- a/Source/cmSystemTools.h
+++ b/Source/cmSystemTools.h
@@ -62,7 +62,8 @@ public:
* Display an error message.
*/
static void Error(const char* m, const char* m2=0,
- const char* m3=0, const char* m4=0);
+ const char* m3=0, const char* m4=0, const char *m5=0,
+ const char *m6=0);
/**
* Display a message.
diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx
index f78aeec..509bdca 100644
--- a/Source/cmVisualStudio10TargetGenerator.cxx
+++ b/Source/cmVisualStudio10TargetGenerator.cxx
@@ -375,9 +375,19 @@ cmVisualStudio10TargetGenerator::WriteCustomRule(cmSourceFile* source,
for(std::vector<std::string>::iterator i = configs->begin();
i != configs->end(); ++i)
{
+ cmCustomCommandLines lines;
+ if(command.HasCommandLines(*i))
+ {
+ lines = command.GetCommandLines(*i);
+ }
+ else
+ {
+ lines = command.GetCommandLines();
+ }
+
std::string script =
cmVS10EscapeXML(
- lg->ConstructScript(command.GetCommandLines(),
+ lg->ConstructScript(lines,
command.GetWorkingDirectory(),
i->c_str(),
command.GetEscapeOldStyle(),
@@ -1468,9 +1478,20 @@ void cmVisualStudio10TargetGenerator::WriteEvent(
comment += lg->ConstructComment(command);
script += pre;
pre = "\n";
+
+ cmCustomCommandLines lines;
+ if(command.HasCommandLines(configName))
+ {
+ lines = command.GetCommandLines(configName);
+ }
+ else
+ {
+ lines = command.GetCommandLines();
+ }
+
script +=
cmVS10EscapeXML(
- lg->ConstructScript(command.GetCommandLines(),
+ lg->ConstructScript(lines,
command.GetWorkingDirectory(),
configName.c_str(),
command.GetEscapeOldStyle(),
--
1.7.2.3
|