Xcode: Fix rebuild with multiple custom command outputs (#15116)

The Xcode generator uses Makefiles under a run-script build-phase to
drive custom commands.  Fix the generated makefiles for custom commands
with multiple outputs to list all the outputs on the left hand side of
the build rule.  This is much simpler and more reliable than the old
multiple-output-pair infrastructure.
This commit is contained in:
Brad King 2014-12-05 09:50:31 -05:00
parent 470c549c62
commit 8a4c6d2d2e
2 changed files with 12 additions and 52 deletions

View File

@ -1498,7 +1498,6 @@ cmGlobalXCodeGenerator::AddCommandsToBuildPhase(cmXCodeObject* buildphase,
const & commands, const & commands,
const char* name) const char* name)
{ {
bool haveMultipleOutputPairs = false;
std::string dir = this->CurrentMakefile->GetCurrentOutputDirectory(); std::string dir = this->CurrentMakefile->GetCurrentOutputDirectory();
dir += "/CMakeScripts"; dir += "/CMakeScripts";
cmSystemTools::MakeDirectory(dir.c_str()); cmSystemTools::MakeDirectory(dir.c_str());
@ -1517,8 +1516,7 @@ cmGlobalXCodeGenerator::AddCommandsToBuildPhase(cmXCodeObject* buildphase,
this->CreateCustomRulesMakefile(makefile.c_str(), this->CreateCustomRulesMakefile(makefile.c_str(),
target, target,
commands, commands,
currentConfig->c_str(), currentConfig->c_str());
haveMultipleOutputPairs);
} }
std::string cdir = this->CurrentMakefile->GetCurrentOutputDirectory(); std::string cdir = this->CurrentMakefile->GetCurrentOutputDirectory();
@ -1528,10 +1526,6 @@ cmGlobalXCodeGenerator::AddCommandsToBuildPhase(cmXCodeObject* buildphase,
makecmd += " -f "; makecmd += " -f ";
makecmd += this->ConvertToRelativeForMake( makecmd += this->ConvertToRelativeForMake(
(makefile+"$CONFIGURATION").c_str()); (makefile+"$CONFIGURATION").c_str());
if(haveMultipleOutputPairs)
{
makecmd += " cmake_check_multiple_outputs";
}
makecmd += " all"; makecmd += " all";
cmSystemTools::ReplaceString(makecmd, "\\ ", "\\\\ "); cmSystemTools::ReplaceString(makecmd, "\\ ", "\\\\ ");
buildphase->AddAttribute("shellScript", buildphase->AddAttribute("shellScript",
@ -1546,8 +1540,7 @@ void cmGlobalXCodeGenerator
cmTarget& target, cmTarget& target,
std::vector<cmCustomCommand> std::vector<cmCustomCommand>
const & commands, const & commands,
const std::string& configName, const std::string& configName)
bool& haveMultipleOutputPairs)
{ {
std::string makefileName=makefileBasename; std::string makefileName=makefileBasename;
if(this->XcodeVersion > 20) if(this->XcodeVersion > 20)
@ -1570,7 +1563,6 @@ void cmGlobalXCodeGenerator
makefileStream << "all: "; makefileStream << "all: ";
std::map<const cmCustomCommand*, std::string> tname; std::map<const cmCustomCommand*, std::string> tname;
int count = 0; int count = 0;
std::map<std::string, std::string> multipleOutputPairs;
for(std::vector<cmCustomCommand>::const_iterator i = commands.begin(); for(std::vector<cmCustomCommand>::const_iterator i = commands.begin();
i != commands.end(); ++i) i != commands.end(); ++i)
{ {
@ -1586,16 +1578,6 @@ void cmGlobalXCodeGenerator
makefileStream makefileStream
<< "\\\n\t" << this->ConvertToRelativeForMake(o->c_str()); << "\\\n\t" << this->ConvertToRelativeForMake(o->c_str());
} }
// If there is more than one output treat the first as the
// primary output and make the rest depend on it.
std::vector<std::string>::const_iterator o = outputs.begin();
std::string primaryOutput = this->ConvertToRelativeForMake(o->c_str());
for(++o; o != outputs.end(); ++o)
{
std::string currentOutput=this->ConvertToRelativeForMake(o->c_str());
multipleOutputPairs[currentOutput] = primaryOutput;
}
} }
else else
{ {
@ -1618,9 +1600,15 @@ void cmGlobalXCodeGenerator
if(!outputs.empty()) if(!outputs.empty())
{ {
// There is at least one output, start the rule for it // There is at least one output, start the rule for it
std::string primary_output = const char* sep = "";
this->ConvertToRelativeForMake(outputs.begin()->c_str()); for(std::vector<std::string>::const_iterator oi = outputs.begin();
makefileStream << primary_output << ": "; oi != outputs.end(); ++oi)
{
makefileStream << sep <<
this->ConvertToRelativeForMake(oi->c_str());
sep = " ";
}
makefileStream << ": ";
} }
else else
{ {
@ -1670,33 +1658,6 @@ void cmGlobalXCodeGenerator
} }
} }
} }
// Add rules to deal with multiple outputs of custom commands.
if(!multipleOutputPairs.empty())
{
makefileStream <<
"\n# Dependencies of multiple outputs to their primary outputs \n";
for(std::map<std::string, std::string>::const_iterator o =
multipleOutputPairs.begin(); o != multipleOutputPairs.end(); ++o)
{
makefileStream << o->first << ": " << o->second << "\n";
}
makefileStream <<
"\n"
"cmake_check_multiple_outputs:\n";
for(std::map<std::string, std::string>::const_iterator o =
multipleOutputPairs.begin(); o != multipleOutputPairs.end(); ++o)
{
makefileStream << "\t@if [ ! -f "
<< o->first << " ]; then rm -f "
<< o->second << "; fi\n";
}
}
haveMultipleOutputPairs =
haveMultipleOutputPairs || !multipleOutputPairs.empty();
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------

View File

@ -118,8 +118,7 @@ private:
void CreateCustomRulesMakefile(const char* makefileBasename, void CreateCustomRulesMakefile(const char* makefileBasename,
cmTarget& target, cmTarget& target,
std::vector<cmCustomCommand> const & commands, std::vector<cmCustomCommand> const & commands,
const std::string& configName, const std::string& configName);
bool& haveMultipleOutputPairs);
cmXCodeObject* FindXCodeTarget(cmTarget const*); cmXCodeObject* FindXCodeTarget(cmTarget const*);
std::string GetOrCreateId(const std::string& name, const std::string& id); std::string GetOrCreateId(const std::string& name, const std::string& id);