summaryrefslogtreecommitdiffstats
path: root/Source/cmMakefile.cxx
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2006-04-11 15:06:19 (GMT)
committerBrad King <brad.king@kitware.com>2006-04-11 15:06:19 (GMT)
commitd5719f22c1dca3e100f1e3b5dfaa4fe7d26796a0 (patch)
tree714a99bed97290f96ff8f846fa6864cebbdc0a28 /Source/cmMakefile.cxx
parentb613cf0be806cc1d37d2b590f1a5ba7898236ae8 (diff)
downloadCMake-d5719f22c1dca3e100f1e3b5dfaa4fe7d26796a0.zip
CMake-d5719f22c1dca3e100f1e3b5dfaa4fe7d26796a0.tar.gz
CMake-d5719f22c1dca3e100f1e3b5dfaa4fe7d26796a0.tar.bz2
ENH: Added support for multiple outputs generated by a single custom command. For Visual Studio generators the native tool provides support. For Xcode and Makefile generators a simple trick is used. The first output is considered primary and has the build rule attached. Other outputs simply depend on the first output with no build rule. During cmake_check_build_system CMake detects when a secondary output is missing and removes the primary output to make sure all outputs are regenerated. This approach always builds the custom command at the right time and only once even during parallel builds.
Diffstat (limited to 'Source/cmMakefile.cxx')
-rw-r--r--Source/cmMakefile.cxx75
1 files changed, 58 insertions, 17 deletions
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index 7e434cf..3d3b2d1 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -499,7 +499,7 @@ cmMakefile::AddCustomCommandToTarget(const char* target,
if(ti != this->Targets.end())
{
// Add the command to the appropriate build step for the target.
- const char* no_output = 0;
+ std::vector<std::string> no_output;
cmCustomCommand cc(no_output, depends, commandLines, comment, workingDir);
switch(type)
{
@@ -530,7 +530,7 @@ cmMakefile::AddCustomCommandToTarget(const char* target,
//----------------------------------------------------------------------------
void
-cmMakefile::AddCustomCommandToOutput(const char* output,
+cmMakefile::AddCustomCommandToOutput(const std::vector<std::string>& outputs,
const std::vector<std::string>& depends,
const char* main_dependency,
const cmCustomCommandLines& commandLines,
@@ -538,6 +538,13 @@ cmMakefile::AddCustomCommandToOutput(const char* output,
const char* workingDir,
bool replace)
{
+ // 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])
@@ -572,8 +579,8 @@ cmMakefile::AddCustomCommandToOutput(const char* output,
// Generate a rule file if the main dependency is not available.
if(!file)
{
- // Construct a rule file associated with the output produced.
- std::string outName = output;
+ // Construct a rule file associated with the first output produced.
+ std::string outName = outputs[0];
outName += ".rule";
// Check if the rule file already exists.
@@ -584,7 +591,8 @@ cmMakefile::AddCustomCommandToOutput(const char* output,
if(commandLines != file->GetCustomCommand()->GetCommandLines())
{
cmSystemTools::Error("Attempt to add a custom rule to output \"",
- output, "\" which already has a custom rule.");
+ outName.c_str(),
+ "\" which already has a custom rule.");
}
return;
}
@@ -593,10 +601,14 @@ cmMakefile::AddCustomCommandToOutput(const char* output,
file = this->GetOrCreateSource(outName.c_str(), true);
}
- // Always create the output and mark it generated.
- if(cmSourceFile* out = this->GetOrCreateSource(output, true))
+ // Always create the output sources and mark them generated.
+ for(std::vector<std::string>::const_iterator o = outputs.begin();
+ o != outputs.end(); ++o)
{
- out->SetProperty("GENERATED", "1");
+ if(cmSourceFile* out = this->GetOrCreateSource(o->c_str(), true))
+ {
+ out->SetProperty("GENERATED", "1");
+ }
}
// Construct a complete list of dependencies.
@@ -610,13 +622,31 @@ cmMakefile::AddCustomCommandToOutput(const char* output,
if(file)
{
cmCustomCommand* cc =
- new cmCustomCommand(output, depends2, commandLines, comment, workingDir);
+ new cmCustomCommand(outputs, depends2, commandLines,
+ comment, workingDir);
file->SetCustomCommand(cc);
}
}
//----------------------------------------------------------------------------
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,
+ bool replace)
+{
+ std::vector<std::string> outputs;
+ outputs.push_back(output);
+ this->AddCustomCommandToOutput(outputs, depends, main_dependency,
+ commandLines, comment, workingDir,
+ replace);
+}
+
+//----------------------------------------------------------------------------
+void
cmMakefile::AddCustomCommandOldStyle(const char* target,
const std::vector<std::string>& outputs,
const std::vector<std::string>& depends,
@@ -735,7 +765,12 @@ void cmMakefile::AddUtilityCommand(const char* utilityName, bool all,
target.SetInAll(all);
target.SetMakefile(this);
// Store the custom command in the target.
- cmCustomCommand cc(output, depends, commandLines, 0, workingDirectory);
+ std::vector<std::string> outputs;
+ if(output)
+ {
+ outputs.push_back(output);
+ }
+ cmCustomCommand cc(outputs, depends, commandLines, 0, workingDirectory);
target.GetPostBuildCommands().push_back(cc);
// Add the target to the set of targets.
@@ -1149,14 +1184,20 @@ cmSourceFile *cmMakefile::GetSourceFileWithOutput(const char *cname)
if ((*i)->GetCustomCommand())
{
// is the output of the custom command match the source files name
- out = (*i)->GetCustomCommand()->GetOutput();
- std::string::size_type pos = out.rfind(name);
- // If the output matches exactly
- if (pos != out.npos &&
- pos == out.size() - name.size() &&
- (pos ==0 || out[pos-1] == '/'))
+ const std::vector<std::string>& outputs =
+ (*i)->GetCustomCommand()->GetOutputs();
+ for(std::vector<std::string>::const_iterator o = outputs.begin();
+ o != outputs.end(); ++o)
{
- return *i;
+ out = *o;
+ std::string::size_type pos = out.rfind(name);
+ // If the output matches exactly
+ if (pos != out.npos &&
+ pos == out.size() - name.size() &&
+ (pos ==0 || out[pos-1] == '/'))
+ {
+ return *i;
+ }
}
}
}