Merge topic 'custom-command-multiple-outputs'
66a9c90c
Makefile: Fix multiple custom command outputs regression (#15116)
This commit is contained in:
commit
387466dd95
|
@ -49,7 +49,6 @@ cmLocalGenerator *cmGlobalBorlandMakefileGenerator::CreateLocalGenerator()
|
|||
lg->SetUnixCD(false);
|
||||
lg->SetMakeCommandEscapeTargetTwice(true);
|
||||
lg->SetBorlandMakeCurlyHack(true);
|
||||
lg->SetNoMultiOutputMultiDepRules(true);
|
||||
return lg;
|
||||
}
|
||||
|
||||
|
|
|
@ -92,7 +92,6 @@ cmLocalUnixMakefileGenerator3::cmLocalUnixMakefileGenerator3()
|
|||
this->SkipAssemblySourceRules = false;
|
||||
this->MakeCommandEscapeTargetTwice = false;
|
||||
this->BorlandMakeCurlyHack = false;
|
||||
this->NoMultiOutputMultiDepRules = false;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
@ -600,7 +599,6 @@ const std::string &cmLocalUnixMakefileGenerator3::GetHomeRelativeOutputPath()
|
|||
return this->HomeRelativeOutputPath;
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void
|
||||
cmLocalUnixMakefileGenerator3
|
||||
|
@ -619,30 +617,6 @@ cmLocalUnixMakefileGenerator3
|
|||
comment);
|
||||
return;
|
||||
}
|
||||
std::vector<std::string> outputs(1, target);
|
||||
this->WriteMakeRule(os, comment,
|
||||
outputs, depends, commands,
|
||||
symbolic, in_help);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void
|
||||
cmLocalUnixMakefileGenerator3
|
||||
::WriteMakeRule(std::ostream& os,
|
||||
const char* comment,
|
||||
const std::vector<std::string>& outputs,
|
||||
const std::vector<std::string>& depends,
|
||||
const std::vector<std::string>& commands,
|
||||
bool symbolic,
|
||||
bool in_help)
|
||||
{
|
||||
// Make sure there is an output.
|
||||
if(outputs.empty())
|
||||
{
|
||||
cmSystemTools::Error("No outputs for WriteMakeRule! called with comment: ",
|
||||
comment);
|
||||
return;
|
||||
}
|
||||
|
||||
std::string replace;
|
||||
|
||||
|
@ -661,17 +635,7 @@ cmLocalUnixMakefileGenerator3
|
|||
}
|
||||
|
||||
// Construct the left hand side of the rule.
|
||||
std::string tgt;
|
||||
{
|
||||
const char* sep = "";
|
||||
for (std::vector<std::string>::const_iterator i = outputs.begin();
|
||||
i != outputs.end(); ++i)
|
||||
{
|
||||
tgt += sep;
|
||||
tgt += this->Convert(*i,HOME_OUTPUT,MAKERULE);
|
||||
sep = " ";
|
||||
}
|
||||
}
|
||||
std::string tgt = this->Convert(target, HOME_OUTPUT, MAKERULE);
|
||||
|
||||
const char* space = "";
|
||||
if(tgt.size() == 1)
|
||||
|
@ -697,19 +661,6 @@ cmLocalUnixMakefileGenerator3
|
|||
// No dependencies. The commands will always run.
|
||||
os << cmMakeSafe(tgt) << space << ":\n";
|
||||
}
|
||||
else if(this->NoMultiOutputMultiDepRules && outputs.size() >= 2)
|
||||
{
|
||||
// Borland make does not understand multiple dependency rules when
|
||||
// there are multiple outputs, so write them all on one line.
|
||||
os << cmMakeSafe(tgt) << space << ":";
|
||||
for(std::vector<std::string>::const_iterator dep = depends.begin();
|
||||
dep != depends.end(); ++dep)
|
||||
{
|
||||
replace = this->Convert(*dep, HOME_OUTPUT, MAKERULE);
|
||||
os << " " << cmMakeSafe(replace);
|
||||
}
|
||||
os << "\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
// Split dependencies into multiple rule lines. This allows for
|
||||
|
@ -733,8 +684,7 @@ cmLocalUnixMakefileGenerator3
|
|||
// Add the output to the local help if requested.
|
||||
if(in_help)
|
||||
{
|
||||
this->LocalHelp.insert(this->LocalHelp.end(),
|
||||
outputs.begin(), outputs.end());
|
||||
this->LocalHelp.push_back(target);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1754,8 +1704,6 @@ cmLocalUnixMakefileGenerator3
|
|||
//----------------------------------------------------------------------------
|
||||
void cmLocalUnixMakefileGenerator3::CheckMultipleOutputs(bool verbose)
|
||||
{
|
||||
// Nothing populates multiple output pairs anymore, but we need to
|
||||
// honor it when working in a build tree generated by an older CMake.
|
||||
cmMakefile* mf = this->Makefile;
|
||||
|
||||
// Get the string listing the multiple output pairs.
|
||||
|
|
|
@ -61,13 +61,6 @@ public:
|
|||
const std::vector<std::string>& commands,
|
||||
bool symbolic,
|
||||
bool in_help = false);
|
||||
void WriteMakeRule(std::ostream& os,
|
||||
const char* comment,
|
||||
const std::vector<std::string>& outputs,
|
||||
const std::vector<std::string>& depends,
|
||||
const std::vector<std::string>& commands,
|
||||
bool symbolic,
|
||||
bool in_help = false);
|
||||
|
||||
// write the main variables used by the makefiles
|
||||
void WriteMakeVariables(std::ostream& makefileStream);
|
||||
|
@ -161,9 +154,6 @@ public:
|
|||
void SetBorlandMakeCurlyHack(bool b)
|
||||
{ this->BorlandMakeCurlyHack = b; }
|
||||
|
||||
void SetNoMultiOutputMultiDepRules(bool b)
|
||||
{ this->NoMultiOutputMultiDepRules = b; }
|
||||
|
||||
// used in writing out Cmake files such as WriteDirectoryInformation
|
||||
static void WriteCMakeArgument(std::ostream& os, const char* s);
|
||||
|
||||
|
@ -349,7 +339,6 @@ private:
|
|||
bool PassMakeflags;
|
||||
bool MakeCommandEscapeTargetTwice;
|
||||
bool BorlandMakeCurlyHack;
|
||||
bool NoMultiOutputMultiDepRules;
|
||||
//==========================================================================
|
||||
|
||||
std::string HomeRelativeOutputPath;
|
||||
|
|
|
@ -769,9 +769,8 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules
|
|||
}
|
||||
|
||||
// Write the build rule.
|
||||
this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
|
||||
outputs, depends, commands, false);
|
||||
|
||||
this->WriteMakeRule(*this->BuildFileStream, 0, outputs,
|
||||
depends, commands, false);
|
||||
|
||||
// Write the main driver rule to build everything in this target.
|
||||
this->WriteTargetDriverRule(targetFullPath, relink);
|
||||
|
|
|
@ -769,8 +769,8 @@ cmMakefileTargetGenerator
|
|||
}
|
||||
|
||||
// Write the rule.
|
||||
this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
|
||||
outputs, depends, commands, false);
|
||||
this->WriteMakeRule(*this->BuildFileStream, 0, outputs,
|
||||
depends, commands, false);
|
||||
|
||||
bool do_preprocess_rules = lang_has_preprocessor &&
|
||||
this->LocalGenerator->GetCreatePreprocessedSourceRules();
|
||||
|
@ -991,6 +991,57 @@ void cmMakefileTargetGenerator::WriteTargetCleanRules()
|
|||
depends, commands, true);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void cmMakefileTargetGenerator::WriteMakeRule(
|
||||
std::ostream& os,
|
||||
const char* comment,
|
||||
const std::vector<std::string>& outputs,
|
||||
const std::vector<std::string>& depends,
|
||||
const std::vector<std::string>& commands,
|
||||
bool symbolic,
|
||||
bool in_help)
|
||||
{
|
||||
if (outputs.size() == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// We always attach the actual commands to the first output.
|
||||
this->LocalGenerator->WriteMakeRule(os, comment, outputs[0], depends,
|
||||
commands, symbolic, in_help);
|
||||
|
||||
// For single outputs, we are done.
|
||||
if (outputs.size() == 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// For multiple outputs, make the extra ones depend on the first one.
|
||||
std::vector<std::string> const output_depends(1, outputs[0]);
|
||||
for (std::vector<std::string>::const_iterator o = outputs.begin()+1;
|
||||
o != outputs.end(); ++o)
|
||||
{
|
||||
// Touch the extra output so "make" knows that it was updated,
|
||||
// but only if the output was acually created.
|
||||
std::string const out = this->Convert(*o, cmLocalGenerator::HOME_OUTPUT,
|
||||
cmLocalGenerator::SHELL);
|
||||
std::vector<std::string> output_commands;
|
||||
if (!symbolic)
|
||||
{
|
||||
output_commands.push_back("@$(CMAKE_COMMAND) -E touch_nocreate " + out);
|
||||
}
|
||||
this->LocalGenerator->WriteMakeRule(os, 0, *o, output_depends,
|
||||
output_commands, symbolic, in_help);
|
||||
|
||||
if (!symbolic)
|
||||
{
|
||||
// At build time, remove the first output if this one does not exist
|
||||
// so that "make" will rerun the real commands that create this one.
|
||||
MultipleOutputPairsType::value_type p(*o, outputs[0]);
|
||||
this->MultipleOutputPairs.insert(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
void cmMakefileTargetGenerator::WriteTargetDependRules()
|
||||
|
@ -1011,6 +1062,25 @@ void cmMakefileTargetGenerator::WriteTargetDependRules()
|
|||
this->LocalGenerator->
|
||||
WriteDependLanguageInfo(*this->InfoFileStream,*this->Target);
|
||||
|
||||
// Store multiple output pairs in the depend info file.
|
||||
if(!this->MultipleOutputPairs.empty())
|
||||
{
|
||||
*this->InfoFileStream
|
||||
<< "\n"
|
||||
<< "# Pairs of files generated by the same build rule.\n"
|
||||
<< "set(CMAKE_MULTIPLE_OUTPUT_PAIRS\n";
|
||||
for(MultipleOutputPairsType::const_iterator pi =
|
||||
this->MultipleOutputPairs.begin();
|
||||
pi != this->MultipleOutputPairs.end(); ++pi)
|
||||
{
|
||||
*this->InfoFileStream
|
||||
<< " " << this->LocalGenerator->EscapeForCMake(pi->first)
|
||||
<< " " << this->LocalGenerator->EscapeForCMake(pi->second)
|
||||
<< "\n";
|
||||
}
|
||||
*this->InfoFileStream << " )\n\n";
|
||||
}
|
||||
|
||||
// Store list of targets linked directly or transitively.
|
||||
{
|
||||
*this->InfoFileStream
|
||||
|
@ -1240,9 +1310,8 @@ void cmMakefileTargetGenerator
|
|||
symbolic = sf->GetPropertyAsBool("SYMBOLIC");
|
||||
}
|
||||
}
|
||||
this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
|
||||
outputs, depends, commands,
|
||||
symbolic);
|
||||
this->WriteMakeRule(*this->BuildFileStream, 0, outputs,
|
||||
depends, commands, symbolic);
|
||||
|
||||
// If the rule has changed make sure the output is rebuilt.
|
||||
if(!symbolic)
|
||||
|
|
|
@ -222,6 +222,16 @@ protected:
|
|||
// Set of extra output files to be driven by the build.
|
||||
std::set<std::string> ExtraFiles;
|
||||
|
||||
typedef std::map<std::string, std::string> MultipleOutputPairsType;
|
||||
MultipleOutputPairsType MultipleOutputPairs;
|
||||
void WriteMakeRule(std::ostream& os,
|
||||
const char* comment,
|
||||
const std::vector<std::string>& outputs,
|
||||
const std::vector<std::string>& depends,
|
||||
const std::vector<std::string>& commands,
|
||||
bool symbolic,
|
||||
bool in_help = false);
|
||||
|
||||
// Target name info.
|
||||
std::string TargetNameOut;
|
||||
std::string TargetNameSO;
|
||||
|
|
Loading…
Reference in New Issue