summaryrefslogtreecommitdiffstats
path: root/Source
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2014-11-25 15:18:16 (GMT)
committerCMake Topic Stage <kwrobot@kitware.com>2014-11-25 15:18:16 (GMT)
commit0f192080761529518128ee697d477ab5ec2e7ea8 (patch)
treec76d41b78e0533aff28830ef506e768ed6aa4acc /Source
parentc5ac0fce5cf1020f661418eb1dc1f35c8f3207ed (diff)
parent557aef0b94c86d13e802e6e8e34a491304d7be2f (diff)
downloadCMake-0f192080761529518128ee697d477ab5ec2e7ea8.zip
CMake-0f192080761529518128ee697d477ab5ec2e7ea8.tar.gz
CMake-0f192080761529518128ee697d477ab5ec2e7ea8.tar.bz2
Merge topic 'custom-command-byproducts'
557aef0b ExternalProject: Add options to specify BYPRODUCTS (#14963) e15a7075 Add an option for explicit BYPRODUCTS of custom commands (#14963)
Diffstat (limited to 'Source')
-rw-r--r--Source/cmAddCustomCommandCommand.cxx26
-rw-r--r--Source/cmAddCustomTargetCommand.cxx29
-rw-r--r--Source/cmCPluginAPI.cxx3
-rw-r--r--Source/cmCustomCommand.cxx10
-rw-r--r--Source/cmCustomCommand.h5
-rw-r--r--Source/cmCustomCommandGenerator.cxx6
-rw-r--r--Source/cmCustomCommandGenerator.h1
-rw-r--r--Source/cmGlobalGenerator.cxx5
-rw-r--r--Source/cmGlobalVisualStudio8Generator.cxx3
-rw-r--r--Source/cmGlobalXCodeGenerator.cxx3
-rw-r--r--Source/cmLocalNinjaGenerator.cxx10
-rw-r--r--Source/cmLocalVisualStudio6Generator.cxx4
-rw-r--r--Source/cmLocalVisualStudioGenerator.cxx4
-rw-r--r--Source/cmMakefile.cxx70
-rw-r--r--Source/cmMakefile.h13
-rw-r--r--Source/cmNinjaNormalTargetGenerator.cxx17
-rw-r--r--Source/cmNinjaTargetGenerator.cxx3
-rw-r--r--Source/cmNinjaUtilityTargetGenerator.cxx21
-rw-r--r--Source/cmQtAutoGenerators.cxx7
19 files changed, 210 insertions, 30 deletions
diff --git a/Source/cmAddCustomCommandCommand.cxx b/Source/cmAddCustomCommandCommand.cxx
index 410f978..818b910 100644
--- a/Source/cmAddCustomCommandCommand.cxx
+++ b/Source/cmAddCustomCommandCommand.cxx
@@ -32,7 +32,7 @@ bool cmAddCustomCommandCommand
std::string source, target, main_dependency, working;
std::string comment_buffer;
const char* comment = 0;
- std::vector<std::string> depends, outputs, output;
+ std::vector<std::string> depends, outputs, output, byproducts;
bool verbatim = false;
bool append = false;
bool uses_terminal = false;
@@ -57,6 +57,7 @@ bool cmAddCustomCommandCommand
doing_main_dependency,
doing_output,
doing_outputs,
+ doing_byproducts,
doing_comment,
doing_working_directory,
doing_nothing
@@ -127,6 +128,10 @@ bool cmAddCustomCommandCommand
{
doing = doing_output;
}
+ else if (copy == "BYPRODUCTS")
+ {
+ doing = doing_byproducts;
+ }
else if (copy == "WORKING_DIRECTORY")
{
doing = doing_working_directory;
@@ -150,6 +155,7 @@ bool cmAddCustomCommandCommand
{
case doing_output:
case doing_outputs:
+ case doing_byproducts:
if (!cmSystemTools::FileIsFullPath(copy.c_str()))
{
// This is an output to be generated, so it should be
@@ -233,6 +239,9 @@ bool cmAddCustomCommandCommand
case doing_outputs:
outputs.push_back(filename);
break;
+ case doing_byproducts:
+ byproducts.push_back(filename);
+ break;
case doing_comment:
comment_buffer = copy;
comment = comment_buffer.c_str();
@@ -272,7 +281,9 @@ bool cmAddCustomCommandCommand
}
// Make sure the output names and locations are safe.
- if(!this->CheckOutputs(output) || !this->CheckOutputs(outputs))
+ if(!this->CheckOutputs(output) ||
+ !this->CheckOutputs(outputs) ||
+ !this->CheckOutputs(byproducts))
{
return false;
}
@@ -314,7 +325,7 @@ bool cmAddCustomCommandCommand
{
// Source is empty, use the target.
std::vector<std::string> no_depends;
- this->Makefile->AddCustomCommandToTarget(target, no_depends,
+ this->Makefile->AddCustomCommandToTarget(target, byproducts, no_depends,
commandLines, cctype,
comment, working.c_str(),
escapeOldStyle, uses_terminal);
@@ -322,8 +333,8 @@ bool cmAddCustomCommandCommand
else if(target.empty())
{
// Target is empty, use the output.
- this->Makefile->AddCustomCommandToOutput(output, depends,
- main_dependency,
+ this->Makefile->AddCustomCommandToOutput(output, byproducts,
+ depends, main_dependency,
commandLines, comment,
working.c_str(), false,
escapeOldStyle, uses_terminal);
@@ -351,6 +362,11 @@ bool cmAddCustomCommandCommand
}
}
}
+ else if (!byproducts.empty())
+ {
+ this->SetError("BYPRODUCTS may not be specified with SOURCE signatures");
+ return false;
+ }
else if (uses_terminal)
{
this->SetError("USES_TERMINAL may not be used with SOURCE signatures");
diff --git a/Source/cmAddCustomTargetCommand.cxx b/Source/cmAddCustomTargetCommand.cxx
index fc4f8f1..09c8af5 100644
--- a/Source/cmAddCustomTargetCommand.cxx
+++ b/Source/cmAddCustomTargetCommand.cxx
@@ -45,7 +45,7 @@ bool cmAddCustomTargetCommand
cmCustomCommandLines commandLines;
// Accumulate dependencies.
- std::vector<std::string> depends;
+ std::vector<std::string> depends, byproducts;
std::string working_directory;
bool verbatim = false;
bool uses_terminal = false;
@@ -57,6 +57,7 @@ bool cmAddCustomTargetCommand
enum tdoing {
doing_command,
doing_depends,
+ doing_byproducts,
doing_working_directory,
doing_comment,
doing_source,
@@ -85,6 +86,10 @@ bool cmAddCustomTargetCommand
{
doing = doing_depends;
}
+ else if(copy == "BYPRODUCTS")
+ {
+ doing = doing_byproducts;
+ }
else if(copy == "WORKING_DIRECTORY")
{
doing = doing_working_directory;
@@ -128,6 +133,19 @@ bool cmAddCustomTargetCommand
case doing_command:
currentLine.push_back(copy);
break;
+ case doing_byproducts:
+ {
+ std::string filename;
+ if (!cmSystemTools::FileIsFullPath(copy.c_str()))
+ {
+ filename = this->Makefile->GetCurrentOutputDirectory();
+ filename += "/";
+ }
+ filename += copy;
+ cmSystemTools::ConvertToUnixSlashes(filename);
+ byproducts.push_back(filename);
+ }
+ break;
case doing_depends:
{
std::string dep = copy;
@@ -227,6 +245,12 @@ bool cmAddCustomTargetCommand
cmSystemTools::CollapseFullPath(working_directory, build_dir);
}
+ if (commandLines.empty() && !byproducts.empty())
+ {
+ this->Makefile->IssueMessage(cmake::FATAL_ERROR,
+ "BYPRODUCTS may not be specified without any COMMAND");
+ return true;
+ }
if (commandLines.empty() && uses_terminal)
{
this->Makefile->IssueMessage(cmake::FATAL_ERROR,
@@ -238,7 +262,8 @@ bool cmAddCustomTargetCommand
bool escapeOldStyle = !verbatim;
cmTarget* target =
this->Makefile->AddUtilityCommand(targetName, excludeFromAll,
- working_directory.c_str(), depends,
+ working_directory.c_str(),
+ byproducts, depends,
commandLines, escapeOldStyle, comment,
uses_terminal);
diff --git a/Source/cmCPluginAPI.cxx b/Source/cmCPluginAPI.cxx
index dd2a1b8..b304f28 100644
--- a/Source/cmCPluginAPI.cxx
+++ b/Source/cmCPluginAPI.cxx
@@ -353,10 +353,11 @@ void CCONV cmAddCustomCommandToTarget(void *arg, const char* target,
}
// Pass the call to the makefile instance.
+ std::vector<std::string> no_byproducts;
std::vector<std::string> no_depends;
const char* no_comment = 0;
const char* no_working_dir = 0;
- mf->AddCustomCommandToTarget(target, no_depends, commandLines,
+ mf->AddCustomCommandToTarget(target, no_byproducts, no_depends, commandLines,
cctype, no_comment, no_working_dir);
}
diff --git a/Source/cmCustomCommand.cxx b/Source/cmCustomCommand.cxx
index 45369cc..2afb029 100644
--- a/Source/cmCustomCommand.cxx
+++ b/Source/cmCustomCommand.cxx
@@ -28,6 +28,7 @@ cmCustomCommand::cmCustomCommand()
//----------------------------------------------------------------------------
cmCustomCommand::cmCustomCommand(const cmCustomCommand& r):
Outputs(r.Outputs),
+ Byproducts(r.Byproducts),
Depends(r.Depends),
CommandLines(r.CommandLines),
HaveComment(r.HaveComment),
@@ -49,6 +50,7 @@ cmCustomCommand& cmCustomCommand::operator=(cmCustomCommand const& r)
}
this->Outputs = r.Outputs;
+ this->Byproducts= r.Byproducts;
this->Depends = r.Depends;
this->CommandLines = r.CommandLines;
this->HaveComment = r.HaveComment;
@@ -66,11 +68,13 @@ cmCustomCommand& cmCustomCommand::operator=(cmCustomCommand const& r)
//----------------------------------------------------------------------------
cmCustomCommand::cmCustomCommand(cmMakefile const* mf,
const std::vector<std::string>& outputs,
+ const std::vector<std::string>& byproducts,
const std::vector<std::string>& depends,
const cmCustomCommandLines& commandLines,
const char* comment,
const char* workingDirectory):
Outputs(outputs),
+ Byproducts(byproducts),
Depends(depends),
CommandLines(commandLines),
HaveComment(comment?true:false),
@@ -100,6 +104,12 @@ const std::vector<std::string>& cmCustomCommand::GetOutputs() const
}
//----------------------------------------------------------------------------
+const std::vector<std::string>& cmCustomCommand::GetByproducts() const
+{
+ return this->Byproducts;
+}
+
+//----------------------------------------------------------------------------
const std::vector<std::string>& cmCustomCommand::GetDepends() const
{
return this->Depends;
diff --git a/Source/cmCustomCommand.h b/Source/cmCustomCommand.h
index 283a0e4..0bfaef2 100644
--- a/Source/cmCustomCommand.h
+++ b/Source/cmCustomCommand.h
@@ -32,6 +32,7 @@ public:
/** Main constructor specifies all information for the command. */
cmCustomCommand(cmMakefile const* mf,
const std::vector<std::string>& outputs,
+ const std::vector<std::string>& byproducts,
const std::vector<std::string>& depends,
const cmCustomCommandLines& commandLines,
const char* comment,
@@ -42,6 +43,9 @@ public:
/** Get the output file produced by the command. */
const std::vector<std::string>& GetOutputs() const;
+ /** Get the extra files produced by the command. */
+ const std::vector<std::string>& GetByproducts() const;
+
/** Get the vector that holds the list of dependencies. */
const std::vector<std::string>& GetDepends() const;
@@ -86,6 +90,7 @@ public:
private:
std::vector<std::string> Outputs;
+ std::vector<std::string> Byproducts;
std::vector<std::string> Depends;
cmCustomCommandLines CommandLines;
bool HaveComment;
diff --git a/Source/cmCustomCommandGenerator.cxx b/Source/cmCustomCommandGenerator.cxx
index 1bca6e6..162d7a1 100644
--- a/Source/cmCustomCommandGenerator.cxx
+++ b/Source/cmCustomCommandGenerator.cxx
@@ -91,6 +91,12 @@ std::vector<std::string> const& cmCustomCommandGenerator::GetOutputs() const
}
//----------------------------------------------------------------------------
+std::vector<std::string> const& cmCustomCommandGenerator::GetByproducts() const
+{
+ return this->CC.GetByproducts();
+}
+
+//----------------------------------------------------------------------------
std::vector<std::string> const& cmCustomCommandGenerator::GetDepends() const
{
if (!this->DependsDone)
diff --git a/Source/cmCustomCommandGenerator.h b/Source/cmCustomCommandGenerator.h
index 0d8a0a4..b4ae014 100644
--- a/Source/cmCustomCommandGenerator.h
+++ b/Source/cmCustomCommandGenerator.h
@@ -42,6 +42,7 @@ public:
const char* GetComment() const;
std::string GetWorkingDirectory() const;
std::vector<std::string> const& GetOutputs() const;
+ std::vector<std::string> const& GetByproducts() const;
std::vector<std::string> const& GetDepends() const;
};
diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx
index 4d49fe3..b9c9b3b 100644
--- a/Source/cmGlobalGenerator.cxx
+++ b/Source/cmGlobalGenerator.cxx
@@ -2510,10 +2510,11 @@ cmTarget cmGlobalGenerator::CreateGlobalTarget(
target.SetProperty("EXCLUDE_FROM_ALL","TRUE");
std::vector<std::string> no_outputs;
+ std::vector<std::string> no_byproducts;
std::vector<std::string> no_depends;
// Store the custom command in the target.
- cmCustomCommand cc(0, no_outputs, no_depends, *commandLines, 0,
- workingDirectory);
+ cmCustomCommand cc(0, no_outputs, no_byproducts, no_depends,
+ *commandLines, 0, workingDirectory);
cc.SetUsesTerminal(uses_terminal);
target.AddPostBuildCommand(cc);
target.SetProperty("EchoString", message);
diff --git a/Source/cmGlobalVisualStudio8Generator.cxx b/Source/cmGlobalVisualStudio8Generator.cxx
index 745515b..e6ce45d 100644
--- a/Source/cmGlobalVisualStudio8Generator.cxx
+++ b/Source/cmGlobalVisualStudio8Generator.cxx
@@ -341,9 +341,10 @@ bool cmGlobalVisualStudio8Generator::AddCheckTarget()
// overwritten by the CreateVCProjBuildRule.
// (this could be avoided with per-target source files)
std::string no_main_dependency = "";
+ std::vector<std::string> no_byproducts;
if(cmSourceFile* file =
mf->AddCustomCommandToOutput(
- stamps, listFiles,
+ stamps, no_byproducts, listFiles,
no_main_dependency, commandLines, "Checking Build System",
no_working_directory, true))
{
diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx
index 5e7a898..b9f64e2 100644
--- a/Source/cmGlobalXCodeGenerator.cxx
+++ b/Source/cmGlobalXCodeGenerator.cxx
@@ -477,7 +477,9 @@ cmGlobalXCodeGenerator::AddExtraTargets(cmLocalGenerator* root,
this->PostBuildMakeTarget(target.GetName(), "$(CONFIGURATION)");
cmCustomCommandLines commandLines;
commandLines.push_back(makeHelper);
+ std::vector<std::string> no_byproducts;
lg->GetMakefile()->AddCustomCommandToTarget(target.GetName(),
+ no_byproducts,
no_depends,
commandLines,
cmTarget::POST_BUILD,
@@ -1368,6 +1370,7 @@ void cmGlobalXCodeGenerator::CreateCustomCommands(cmXCodeObject* buildPhases,
cmCustomCommand command(this->CurrentMakefile,
std::vector<std::string>(),
std::vector<std::string>(),
+ std::vector<std::string>(),
cmd,
"Creating symlinks",
"");
diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx
index 3c39b62..0b0d971 100644
--- a/Source/cmLocalNinjaGenerator.cxx
+++ b/Source/cmLocalNinjaGenerator.cxx
@@ -440,10 +440,18 @@ cmLocalNinjaGenerator::WriteCustomCommandBuildStatement(
cmCustomCommandGenerator ccg(*cc, this->GetConfigName(), this->Makefile);
const std::vector<std::string> &outputs = ccg.GetOutputs();
- cmNinjaDeps ninjaOutputs(outputs.size()), ninjaDeps;
+ const std::vector<std::string> &byproducts = ccg.GetByproducts();
+ cmNinjaDeps ninjaOutputs(outputs.size()+byproducts.size()), ninjaDeps;
+#if 0
+#error TODO: Once CC in an ExternalProject target must provide the \
+ file of each imported target that has an add_dependencies pointing \
+ at us. How to know which ExternalProject step actually provides it?
+#endif
std::transform(outputs.begin(), outputs.end(),
ninjaOutputs.begin(), MapToNinjaPath());
+ std::transform(byproducts.begin(), byproducts.end(),
+ ninjaOutputs.begin() + outputs.size(), MapToNinjaPath());
this->AppendCustomCommandDeps(ccg, ninjaDeps);
for (cmNinjaDeps::iterator i = ninjaOutputs.begin(); i != ninjaOutputs.end();
diff --git a/Source/cmLocalVisualStudio6Generator.cxx b/Source/cmLocalVisualStudio6Generator.cxx
index c14fb2b..b9a5074 100644
--- a/Source/cmLocalVisualStudio6Generator.cxx
+++ b/Source/cmLocalVisualStudio6Generator.cxx
@@ -821,10 +821,12 @@ cmLocalVisualStudio6Generator::MaybeCreateOutputDir(cmTarget& target,
command.push_back("make_directory");
command.push_back(outDir);
std::vector<std::string> no_output;
+ std::vector<std::string> no_byproducts;
std::vector<std::string> no_depends;
cmCustomCommandLines commands;
commands.push_back(command);
- pcc.reset(new cmCustomCommand(0, no_output, no_depends, commands, 0, 0));
+ pcc.reset(new cmCustomCommand(0, no_output, no_byproducts,
+ no_depends, commands, 0, 0));
pcc->SetEscapeOldStyle(false);
pcc->SetEscapeAllowMakeVars(true);
return pcc;
diff --git a/Source/cmLocalVisualStudioGenerator.cxx b/Source/cmLocalVisualStudioGenerator.cxx
index 9680d43..f01aa6b 100644
--- a/Source/cmLocalVisualStudioGenerator.cxx
+++ b/Source/cmLocalVisualStudioGenerator.cxx
@@ -95,10 +95,12 @@ cmLocalVisualStudioGenerator::MaybeCreateImplibDir(cmTarget& target,
command.push_back("make_directory");
command.push_back(impDir);
std::vector<std::string> no_output;
+ std::vector<std::string> no_byproducts;
std::vector<std::string> no_depends;
cmCustomCommandLines commands;
commands.push_back(command);
- pcc.reset(new cmCustomCommand(0, no_output, no_depends, commands, 0, 0));
+ pcc.reset(new cmCustomCommand(0, no_output, no_byproducts,
+ no_depends, commands, 0, 0));
pcc->SetEscapeOldStyle(false);
pcc->SetEscapeAllowMakeVars(true);
return pcc;
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index 7e5e4e7..61807b2 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -880,13 +880,14 @@ void cmMakefile::ConfigureFinalPass()
//----------------------------------------------------------------------------
void
cmMakefile::AddCustomCommandToTarget(const std::string& target,
+ const std::vector<std::string>& byproducts,
const std::vector<std::string>& depends,
const cmCustomCommandLines& commandLines,
cmTarget::CustomCommandType type,
const char* comment,
const char* workingDir,
bool escapeOldStyle,
- bool uses_terminal) const
+ bool uses_terminal)
{
// Find the target to which to add the custom command.
cmTargets::iterator ti = this->Targets.find(target);
@@ -936,9 +937,20 @@ cmMakefile::AddCustomCommandToTarget(const std::string& target,
this->IssueMessage(cmake::FATAL_ERROR, e.str());
return;
}
+
+ // Always create the byproduct sources and mark them generated.
+ for(std::vector<std::string>::const_iterator o = byproducts.begin();
+ o != byproducts.end(); ++o)
+ {
+ if(cmSourceFile* out = this->GetOrCreateSource(*o, true))
+ {
+ out->SetProperty("GENERATED", "1");
+ }
+ }
+
// Add the command to the appropriate build step for the target.
std::vector<std::string> no_output;
- cmCustomCommand cc(this, no_output, depends,
+ cmCustomCommand cc(this, no_output, byproducts, depends,
commandLines, comment, workingDir);
cc.SetEscapeOldStyle(escapeOldStyle);
cc.SetEscapeAllowMakeVars(true);
@@ -960,6 +972,7 @@ cmMakefile::AddCustomCommandToTarget(const std::string& target,
//----------------------------------------------------------------------------
cmSourceFile*
cmMakefile::AddCustomCommandToOutput(const std::vector<std::string>& outputs,
+ const std::vector<std::string>& byproducts,
const std::vector<std::string>& depends,
const std::string& main_dependency,
const cmCustomCommandLines& commandLines,
@@ -1058,6 +1071,14 @@ cmMakefile::AddCustomCommandToOutput(const std::vector<std::string>& outputs,
out->SetProperty("GENERATED", "1");
}
}
+ for(std::vector<std::string>::const_iterator o = byproducts.begin();
+ o != byproducts.end(); ++o)
+ {
+ if(cmSourceFile* out = this->GetOrCreateSource(*o, true))
+ {
+ out->SetProperty("GENERATED", "1");
+ }
+ }
// Attach the custom command to the file.
if(file)
@@ -1070,8 +1091,8 @@ cmMakefile::AddCustomCommandToOutput(const std::vector<std::string>& outputs,
}
cmCustomCommand* cc =
- new cmCustomCommand(this, outputs, depends2, commandLines,
- comment, workingDir);
+ new cmCustomCommand(this, outputs, byproducts, depends2,
+ commandLines, comment, workingDir);
cc->SetEscapeOldStyle(escapeOldStyle);
cc->SetEscapeAllowMakeVars(true);
cc->SetUsesTerminal(uses_terminal);
@@ -1128,7 +1149,9 @@ cmMakefile::AddCustomCommandToOutput(const std::string& output,
{
std::vector<std::string> outputs;
outputs.push_back(output);
- return this->AddCustomCommandToOutput(outputs, depends, main_dependency,
+ std::vector<std::string> no_byproducts;
+ return this->AddCustomCommandToOutput(outputs, no_byproducts,
+ depends, main_dependency,
commandLines, comment, workingDir,
replace, escapeOldStyle,
uses_terminal);
@@ -1150,7 +1173,9 @@ cmMakefile::AddCustomCommandOldStyle(const std::string& target,
// 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,
+ std::vector<std::string> no_byproducts;
+ this->AddCustomCommandToTarget(target, no_byproducts,
+ depends, commandLines,
cmTarget::POST_BUILD, comment, 0);
return;
}
@@ -1251,6 +1276,23 @@ cmMakefile::AddUtilityCommand(const std::string& utilityName,
bool escapeOldStyle, const char* comment,
bool uses_terminal)
{
+ std::vector<std::string> no_byproducts;
+ return this->AddUtilityCommand(utilityName, excludeFromAll, workingDirectory,
+ no_byproducts, depends, commandLines,
+ escapeOldStyle, comment, uses_terminal);
+}
+
+//----------------------------------------------------------------------------
+cmTarget*
+cmMakefile::AddUtilityCommand(const std::string& utilityName,
+ bool excludeFromAll,
+ const char* workingDirectory,
+ const std::vector<std::string>& byproducts,
+ const std::vector<std::string>& depends,
+ const cmCustomCommandLines& commandLines,
+ bool escapeOldStyle, const char* comment,
+ bool uses_terminal)
+{
// Create a target instance for this utility.
cmTarget* target = this->AddNewTarget(cmTarget::UTILITY, utilityName);
if (excludeFromAll)
@@ -1270,10 +1312,12 @@ cmMakefile::AddUtilityCommand(const std::string& utilityName,
force += cmake::GetCMakeFilesDirectory();
force += "/";
force += utilityName;
+ std::vector<std::string> forced;
+ forced.push_back(force);
std::string no_main_dependency = "";
bool no_replace = false;
- this->AddCustomCommandToOutput(force, depends,
- no_main_dependency,
+ this->AddCustomCommandToOutput(forced, byproducts,
+ depends, no_main_dependency,
commandLines, comment,
workingDirectory, no_replace,
escapeOldStyle, uses_terminal);
@@ -1289,6 +1333,16 @@ cmMakefile::AddUtilityCommand(const std::string& utilityName,
cmSystemTools::Error("Could not get source file entry for ",
force.c_str());
}
+
+ // Always create the byproduct sources and mark them generated.
+ for(std::vector<std::string>::const_iterator o = byproducts.begin();
+ o != byproducts.end(); ++o)
+ {
+ if(cmSourceFile* out = this->GetOrCreateSource(*o, true))
+ {
+ out->SetProperty("GENERATED", "1");
+ }
+ }
}
return target;
}
diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h
index 73c299e..0458d54 100644
--- a/Source/cmMakefile.h
+++ b/Source/cmMakefile.h
@@ -170,14 +170,16 @@ public:
/** Add a custom command to the build. */
void AddCustomCommandToTarget(const std::string& target,
+ const std::vector<std::string>& byproducts,
const std::vector<std::string>& depends,
const cmCustomCommandLines& commandLines,
cmTarget::CustomCommandType type,
const char* comment, const char* workingDir,
bool escapeOldStyle = true,
- bool uses_terminal = false) const;
+ bool uses_terminal = false);
cmSourceFile* AddCustomCommandToOutput(
const std::vector<std::string>& outputs,
+ const std::vector<std::string>& byproducts,
const std::vector<std::string>& depends,
const std::string& main_dependency,
const cmCustomCommandLines& commandLines,
@@ -242,6 +244,15 @@ public:
bool escapeOldStyle = true,
const char* comment = 0,
bool uses_terminal = false);
+ cmTarget* AddUtilityCommand(const std::string& utilityName,
+ bool excludeFromAll,
+ const char* workingDirectory,
+ const std::vector<std::string>& byproducts,
+ const std::vector<std::string>& depends,
+ const cmCustomCommandLines& commandLines,
+ bool escapeOldStyle = true,
+ const char* comment = 0,
+ bool uses_terminal = false);
/**
* Add a link library to the build.
diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx
index 48c4a2d..25931f3 100644
--- a/Source/cmNinjaNormalTargetGenerator.cxx
+++ b/Source/cmNinjaNormalTargetGenerator.cxx
@@ -256,7 +256,7 @@ cmNinjaNormalTargetGenerator
/*deptype*/ "",
rspfile,
rspcontent,
- /*restat*/ "",
+ /*restat*/ "$RESTAT",
/*generator*/ false);
}
@@ -556,6 +556,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
&postBuildCmdLines
};
+ cmNinjaDeps byproducts;
for (unsigned i = 0; i != 3; ++i)
{
for (std::vector<cmCustomCommand>::const_iterator
@@ -564,6 +565,9 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
{
cmCustomCommandGenerator ccg(*ci, cfgName, mf);
localGen.AppendCustomCommandLines(ccg, *cmdLineLists[i]);
+ std::vector<std::string> const& ccByproducts = ccg.GetByproducts();
+ std::transform(ccByproducts.begin(), ccByproducts.end(),
+ std::back_inserter(byproducts), MapToNinjaPath());
}
}
@@ -611,6 +615,17 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
this->GetLocalGenerator()->AppendTargetDepends(this->GetTarget(),
orderOnlyDeps);
+ // Ninja should restat after linking if and only if there are byproducts.
+ vars["RESTAT"] = byproducts.empty()? "" : "1";
+
+ for (cmNinjaDeps::const_iterator oi = byproducts.begin(),
+ oe = byproducts.end();
+ oi != oe; ++oi)
+ {
+ this->GetGlobalGenerator()->SeenCustomCommandOutput(*oi);
+ outputs.push_back(*oi);
+ }
+
// Write the build statement for this target.
globalGen.WriteBuild(this->GetBuildFileStream(),
comment.str(),
diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx
index 57fbcd3..7967762 100644
--- a/Source/cmNinjaTargetGenerator.cxx
+++ b/Source/cmNinjaTargetGenerator.cxx
@@ -538,8 +538,11 @@ cmNinjaTargetGenerator
cmCustomCommandGenerator ccg(*cc, this->GetConfigName(),
this->GetMakefile());
const std::vector<std::string>& ccoutputs = ccg.GetOutputs();
+ const std::vector<std::string>& ccbyproducts= ccg.GetByproducts();
std::transform(ccoutputs.begin(), ccoutputs.end(),
std::back_inserter(orderOnlyDeps), MapToNinjaPath());
+ std::transform(ccbyproducts.begin(), ccbyproducts.end(),
+ std::back_inserter(orderOnlyDeps), MapToNinjaPath());
}
if (!orderOnlyDeps.empty())
diff --git a/Source/cmNinjaUtilityTargetGenerator.cxx b/Source/cmNinjaUtilityTargetGenerator.cxx
index c0a14ec..42d6b46 100644
--- a/Source/cmNinjaUtilityTargetGenerator.cxx
+++ b/Source/cmNinjaUtilityTargetGenerator.cxx
@@ -27,8 +27,11 @@ cmNinjaUtilityTargetGenerator::~cmNinjaUtilityTargetGenerator() {}
void cmNinjaUtilityTargetGenerator::Generate()
{
+ std::string utilCommandName = cmake::GetCMakeFilesDirectoryPostSlash();
+ utilCommandName += this->GetTargetName() + ".util";
+
std::vector<std::string> commands;
- cmNinjaDeps deps, outputs;
+ cmNinjaDeps deps, outputs, util_outputs(1, utilCommandName);
const std::vector<cmCustomCommand> *cmdLists[2] = {
&this->GetTarget()->GetPreBuildCommands(),
@@ -44,6 +47,9 @@ void cmNinjaUtilityTargetGenerator::Generate()
this->GetMakefile());
this->GetLocalGenerator()->AppendCustomCommandDeps(ccg, deps);
this->GetLocalGenerator()->AppendCustomCommandLines(ccg, commands);
+ std::vector<std::string> const& ccByproducts = ccg.GetByproducts();
+ std::transform(ccByproducts.begin(), ccByproducts.end(),
+ std::back_inserter(util_outputs), MapToNinjaPath());
if (ci->GetUsesTerminal())
uses_terminal = true;
}
@@ -64,8 +70,11 @@ void cmNinjaUtilityTargetGenerator::Generate()
// Depend on all custom command outputs.
const std::vector<std::string>& ccOutputs = ccg.GetOutputs();
+ const std::vector<std::string>& ccByproducts = ccg.GetByproducts();
std::transform(ccOutputs.begin(), ccOutputs.end(),
std::back_inserter(deps), MapToNinjaPath());
+ std::transform(ccByproducts.begin(), ccByproducts.end(),
+ std::back_inserter(deps), MapToNinjaPath());
}
}
@@ -107,15 +116,19 @@ void cmNinjaUtilityTargetGenerator::Generate()
if (command.find('$') != std::string::npos)
return;
- std::string utilCommandName = cmake::GetCMakeFilesDirectoryPostSlash();
- utilCommandName += this->GetTargetName() + ".util";
+ for (cmNinjaDeps::const_iterator
+ oi = util_outputs.begin(), oe = util_outputs.end();
+ oi != oe; ++oi)
+ {
+ this->GetGlobalGenerator()->SeenCustomCommandOutput(*oi);
+ }
this->GetGlobalGenerator()->WriteCustomCommandBuild(
command,
desc,
"Utility command for " + this->GetTargetName(),
uses_terminal,
- cmNinjaDeps(1, utilCommandName),
+ util_outputs,
deps);
this->GetGlobalGenerator()->WritePhonyBuild(this->GetBuildFileStream(),
diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx
index 929cbc0..8f9c091 100644
--- a/Source/cmQtAutoGenerators.cxx
+++ b/Source/cmQtAutoGenerators.cxx
@@ -438,7 +438,8 @@ bool cmQtAutoGenerators::InitializeAutogenTarget(cmTarget* target)
// rejection in cmMakefile::AddCustomCommandToTarget because we know
// PRE_BUILD will work for an OBJECT_LIBRARY in this specific case.
std::vector<std::string> no_output;
- cmCustomCommand cc(makefile, no_output, depends,
+ std::vector<std::string> no_byproducts;
+ cmCustomCommand cc(makefile, no_output, no_byproducts, depends,
commandLines, autogenComment.c_str(),
workingDirectory.c_str());
cc.SetEscapeOldStyle(false);
@@ -451,7 +452,9 @@ bool cmQtAutoGenerators::InitializeAutogenTarget(cmTarget* target)
cmTarget* autogenTarget = 0;
if (!rcc_output.empty())
{
- makefile->AddCustomCommandToOutput(rcc_output, depends, "",
+ std::vector<std::string> no_byproducts;
+ makefile->AddCustomCommandToOutput(rcc_output, no_byproducts,
+ depends, "",
commandLines, 0,
workingDirectory.c_str(),
false, false);