ENH: Add a depends check step to custom targets. Add support for the IMPLICIT_DEPENDS feature of custom commands when building in custom targets. Convert multiple-output pair checks to be per-target instead of global.
This commit is contained in:
parent
6586149d64
commit
d83b4cd255
|
@ -1680,13 +1680,6 @@ void cmGlobalGenerator::AppendDirectoryForConfig(const char*, const char*,
|
||||||
// configuration.
|
// configuration.
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
void cmGlobalGenerator::CheckMultipleOutputs(cmMakefile*, bool)
|
|
||||||
{
|
|
||||||
// Only certain generators need this check. They define this
|
|
||||||
// method.
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
std::vector<cmTarget *>& cmGlobalGenerator
|
std::vector<cmTarget *>& cmGlobalGenerator
|
||||||
::GetTargetDepends(cmTarget& target)
|
::GetTargetDepends(cmTarget& target)
|
||||||
|
|
|
@ -211,9 +211,6 @@ public:
|
||||||
|
|
||||||
void AddTarget(cmTargets::value_type &v);
|
void AddTarget(cmTargets::value_type &v);
|
||||||
|
|
||||||
/** Support for multiple custom command outputs. */
|
|
||||||
virtual void CheckMultipleOutputs(cmMakefile* mf, bool verbose);
|
|
||||||
|
|
||||||
virtual const char* GetAllTargetName() { return "ALL_BUILD"; }
|
virtual const char* GetAllTargetName() { return "ALL_BUILD"; }
|
||||||
virtual const char* GetInstallTargetName() { return "INSTALL"; }
|
virtual const char* GetInstallTargetName() { return "INSTALL"; }
|
||||||
virtual const char* GetInstallLocalTargetName() { return 0; }
|
virtual const char* GetInstallLocalTargetName() { return 0; }
|
||||||
|
|
|
@ -132,16 +132,6 @@ void cmGlobalUnixMakefileGenerator3
|
||||||
"default make target. A \"make install\" target is also provided.";
|
"default make target. A \"make install\" target is also provided.";
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
void
|
|
||||||
cmGlobalUnixMakefileGenerator3
|
|
||||||
::AddMultipleOutputPair(const char* depender, const char* dependee)
|
|
||||||
{
|
|
||||||
MultipleOutputPairsType::value_type p(depender, dependee);
|
|
||||||
this->MultipleOutputPairs.insert(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
void cmGlobalUnixMakefileGenerator3::Generate()
|
void cmGlobalUnixMakefileGenerator3::Generate()
|
||||||
{
|
{
|
||||||
|
@ -373,62 +363,6 @@ void cmGlobalUnixMakefileGenerator3::WriteMainCMakefile()
|
||||||
|
|
||||||
this->WriteMainCMakefileLanguageRules(cmakefileStream,
|
this->WriteMainCMakefileLanguageRules(cmakefileStream,
|
||||||
this->LocalGenerators);
|
this->LocalGenerators);
|
||||||
|
|
||||||
if(!this->MultipleOutputPairs.empty())
|
|
||||||
{
|
|
||||||
cmakefileStream
|
|
||||||
<< "\n"
|
|
||||||
<< "SET(CMAKE_MULTIPLE_OUTPUT_PAIRS\n";
|
|
||||||
for(MultipleOutputPairsType::const_iterator pi =
|
|
||||||
this->MultipleOutputPairs.begin();
|
|
||||||
pi != this->MultipleOutputPairs.end(); ++pi)
|
|
||||||
{
|
|
||||||
cmakefileStream << " \"" << pi->first << "\" \""
|
|
||||||
<< pi->second << "\"\n";
|
|
||||||
}
|
|
||||||
cmakefileStream << " )\n\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
|
||||||
void cmGlobalUnixMakefileGenerator3::CheckMultipleOutputs(cmMakefile* mf,
|
|
||||||
bool verbose)
|
|
||||||
{
|
|
||||||
// Get the string listing the multiple output pairs.
|
|
||||||
const char* pairs_string = mf->GetDefinition("CMAKE_MULTIPLE_OUTPUT_PAIRS");
|
|
||||||
if(!pairs_string)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert the string to a list and preserve empty entries.
|
|
||||||
std::vector<std::string> pairs;
|
|
||||||
cmSystemTools::ExpandListArgument(pairs_string, pairs, true);
|
|
||||||
for(std::vector<std::string>::const_iterator i = pairs.begin();
|
|
||||||
i != pairs.end(); ++i)
|
|
||||||
{
|
|
||||||
const std::string& depender = *i;
|
|
||||||
if(++i != pairs.end())
|
|
||||||
{
|
|
||||||
const std::string& dependee = *i;
|
|
||||||
|
|
||||||
// If the depender is missing then delete the dependee to make
|
|
||||||
// sure both will be regenerated.
|
|
||||||
if(cmSystemTools::FileExists(dependee.c_str()) &&
|
|
||||||
!cmSystemTools::FileExists(depender.c_str()))
|
|
||||||
{
|
|
||||||
if(verbose)
|
|
||||||
{
|
|
||||||
cmOStringStream msg;
|
|
||||||
msg << "Deleting primary custom command output \"" << dependee
|
|
||||||
<< "\" because another output \""
|
|
||||||
<< depender << "\" does not exist." << std::endl;
|
|
||||||
cmSystemTools::Stdout(msg.str().c_str());
|
|
||||||
}
|
|
||||||
cmSystemTools::RemoveFile(dependee.c_str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void cmGlobalUnixMakefileGenerator3
|
void cmGlobalUnixMakefileGenerator3
|
||||||
|
@ -763,21 +697,18 @@ cmGlobalUnixMakefileGenerator3
|
||||||
<< localName << "\n\n";
|
<< localName << "\n\n";
|
||||||
|
|
||||||
commands.clear();
|
commands.clear();
|
||||||
if (t->second.GetType() != cmTarget::UTILITY)
|
makeTargetName = localName;
|
||||||
|
makeTargetName += "/depend";
|
||||||
|
commands.push_back(lg->GetRecursiveMakeCall
|
||||||
|
(makefileName.c_str(),makeTargetName.c_str()));
|
||||||
|
|
||||||
|
// add requires if we need it for this generator
|
||||||
|
if (needRequiresStep)
|
||||||
{
|
{
|
||||||
makeTargetName = localName;
|
makeTargetName = localName;
|
||||||
makeTargetName += "/depend";
|
makeTargetName += "/requires";
|
||||||
commands.push_back(lg->GetRecursiveMakeCall
|
commands.push_back(lg->GetRecursiveMakeCall
|
||||||
(makefileName.c_str(),makeTargetName.c_str()));
|
(makefileName.c_str(),makeTargetName.c_str()));
|
||||||
|
|
||||||
// add requires if we need it for this generator
|
|
||||||
if (needRequiresStep)
|
|
||||||
{
|
|
||||||
makeTargetName = localName;
|
|
||||||
makeTargetName += "/requires";
|
|
||||||
commands.push_back(lg->GetRecursiveMakeCall
|
|
||||||
(makefileName.c_str(),makeTargetName.c_str()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
makeTargetName = localName;
|
makeTargetName = localName;
|
||||||
makeTargetName += "/build";
|
makeTargetName += "/build";
|
||||||
|
|
|
@ -98,19 +98,6 @@ public:
|
||||||
void WriteConvenienceRules(std::ostream& ruleFileStream,
|
void WriteConvenienceRules(std::ostream& ruleFileStream,
|
||||||
std::set<cmStdString> &emitted);
|
std::set<cmStdString> &emitted);
|
||||||
|
|
||||||
/** In order to support parallel builds for custom commands with
|
|
||||||
multiple outputs the outputs are given a serial order, and only
|
|
||||||
the first output actually has the build rule. Other outputs
|
|
||||||
just depend on the first one. The check-build-system step must
|
|
||||||
remove a dependee if the depender is missing to make sure both
|
|
||||||
are regenerated properly. This method is used by the local
|
|
||||||
makefile generators to register such pairs. */
|
|
||||||
void AddMultipleOutputPair(const char* depender, const char* dependee);
|
|
||||||
|
|
||||||
/** Support for multiple custom command outputs. Called during
|
|
||||||
check-build-system step. */
|
|
||||||
virtual void CheckMultipleOutputs(cmMakefile* mf, bool verbose);
|
|
||||||
|
|
||||||
/** Get the command to use for a target that has no rule. This is
|
/** Get the command to use for a target that has no rule. This is
|
||||||
used for multiple output dependencies and for cmake_force. */
|
used for multiple output dependencies and for cmake_force. */
|
||||||
std::string GetEmptyRuleHackCommand() { return this->EmptyRuleHackCommand; }
|
std::string GetEmptyRuleHackCommand() { return this->EmptyRuleHackCommand; }
|
||||||
|
@ -191,9 +178,6 @@ protected:
|
||||||
// in the rule to satisfy the make program.
|
// in the rule to satisfy the make program.
|
||||||
std::string EmptyRuleHackCommand;
|
std::string EmptyRuleHackCommand;
|
||||||
|
|
||||||
typedef std::map<cmStdString, cmStdString> MultipleOutputPairsType;
|
|
||||||
MultipleOutputPairsType MultipleOutputPairs;
|
|
||||||
|
|
||||||
std::map<cmStdString, int > TargetSourceFileCount;
|
std::map<cmStdString, int > TargetSourceFileCount;
|
||||||
bool ForceVerboseMakefiles;
|
bool ForceVerboseMakefiles;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1229,6 +1229,16 @@ bool cmLocalUnixMakefileGenerator3::UpdateDependencies(const char* tgtInfo,
|
||||||
bool verbose,
|
bool verbose,
|
||||||
bool color)
|
bool color)
|
||||||
{
|
{
|
||||||
|
// read in the target info file
|
||||||
|
if(!this->Makefile->ReadListFile(0, tgtInfo) ||
|
||||||
|
cmSystemTools::GetErrorOccuredFlag())
|
||||||
|
{
|
||||||
|
cmSystemTools::Error("Target DependInfo.cmake file not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if any multiple output pairs have a missing file.
|
||||||
|
this->CheckMultipleOutputs(verbose);
|
||||||
|
|
||||||
std::string dir = cmSystemTools::GetFilenamePath(tgtInfo);
|
std::string dir = cmSystemTools::GetFilenamePath(tgtInfo);
|
||||||
std::string internalDependFile = dir + "/depend.internal";
|
std::string internalDependFile = dir + "/depend.internal";
|
||||||
std::string dependFile = dir + "/depend.make";
|
std::string dependFile = dir + "/depend.make";
|
||||||
|
@ -1257,7 +1267,7 @@ bool cmLocalUnixMakefileGenerator3::UpdateDependencies(const char* tgtInfo,
|
||||||
fprintf(stdout, "%s\n", message.c_str());
|
fprintf(stdout, "%s\n", message.c_str());
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return this->ScanDependencies(tgtInfo);
|
return this->ScanDependencies(dir.c_str());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1267,11 +1277,10 @@ bool cmLocalUnixMakefileGenerator3::UpdateDependencies(const char* tgtInfo,
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
bool cmLocalUnixMakefileGenerator3::ScanDependencies(const char* tgtInfo)
|
bool
|
||||||
|
cmLocalUnixMakefileGenerator3
|
||||||
|
::ScanDependencies(const char* targetDir)
|
||||||
{
|
{
|
||||||
// The info file for this target
|
|
||||||
std::string infoFile = tgtInfo;
|
|
||||||
|
|
||||||
// Read the directory information file.
|
// Read the directory information file.
|
||||||
cmMakefile* mf = this->Makefile;
|
cmMakefile* mf = this->Makefile;
|
||||||
bool haveDirectoryInfo = false;
|
bool haveDirectoryInfo = false;
|
||||||
|
@ -1284,13 +1293,6 @@ bool cmLocalUnixMakefileGenerator3::ScanDependencies(const char* tgtInfo)
|
||||||
haveDirectoryInfo = true;
|
haveDirectoryInfo = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// read in the target info file
|
|
||||||
if(!mf->ReadListFile(0, infoFile.c_str()) ||
|
|
||||||
cmSystemTools::GetErrorOccuredFlag())
|
|
||||||
{
|
|
||||||
cmSystemTools::Error("Target DependInfo.cmake file not found");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Lookup useful directory information.
|
// Lookup useful directory information.
|
||||||
if(haveDirectoryInfo)
|
if(haveDirectoryInfo)
|
||||||
{
|
{
|
||||||
|
@ -1322,7 +1324,7 @@ bool cmLocalUnixMakefileGenerator3::ScanDependencies(const char* tgtInfo)
|
||||||
}
|
}
|
||||||
|
|
||||||
// create the file stream for the depends file
|
// create the file stream for the depends file
|
||||||
std::string dir = cmSystemTools::GetFilenamePath(infoFile);
|
std::string dir = targetDir;
|
||||||
|
|
||||||
// Open the rule file. This should be copy-if-different because the
|
// Open the rule file. This should be copy-if-different because the
|
||||||
// rules may depend on this file itself.
|
// rules may depend on this file itself.
|
||||||
|
@ -1449,6 +1451,48 @@ bool cmLocalUnixMakefileGenerator3::ScanDependencies(const char* tgtInfo)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
void cmLocalUnixMakefileGenerator3::CheckMultipleOutputs(bool verbose)
|
||||||
|
{
|
||||||
|
cmMakefile* mf = this->Makefile;
|
||||||
|
|
||||||
|
// Get the string listing the multiple output pairs.
|
||||||
|
const char* pairs_string = mf->GetDefinition("CMAKE_MULTIPLE_OUTPUT_PAIRS");
|
||||||
|
if(!pairs_string)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert the string to a list and preserve empty entries.
|
||||||
|
std::vector<std::string> pairs;
|
||||||
|
cmSystemTools::ExpandListArgument(pairs_string, pairs, true);
|
||||||
|
for(std::vector<std::string>::const_iterator i = pairs.begin();
|
||||||
|
i != pairs.end(); ++i)
|
||||||
|
{
|
||||||
|
const std::string& depender = *i;
|
||||||
|
if(++i != pairs.end())
|
||||||
|
{
|
||||||
|
const std::string& dependee = *i;
|
||||||
|
|
||||||
|
// If the depender is missing then delete the dependee to make
|
||||||
|
// sure both will be regenerated.
|
||||||
|
if(cmSystemTools::FileExists(dependee.c_str()) &&
|
||||||
|
!cmSystemTools::FileExists(depender.c_str()))
|
||||||
|
{
|
||||||
|
if(verbose)
|
||||||
|
{
|
||||||
|
cmOStringStream msg;
|
||||||
|
msg << "Deleting primary custom command output \"" << dependee
|
||||||
|
<< "\" because another output \""
|
||||||
|
<< depender << "\" does not exist." << std::endl;
|
||||||
|
cmSystemTools::Stdout(msg.str().c_str());
|
||||||
|
}
|
||||||
|
cmSystemTools::RemoveFile(dependee.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
void cmLocalUnixMakefileGenerator3
|
void cmLocalUnixMakefileGenerator3
|
||||||
::WriteLocalAllRules(std::ostream& ruleFileStream)
|
::WriteLocalAllRules(std::ostream& ruleFileStream)
|
||||||
|
|
|
@ -203,9 +203,6 @@ public:
|
||||||
virtual bool UpdateDependencies(const char* tgtInfo,
|
virtual bool UpdateDependencies(const char* tgtInfo,
|
||||||
bool verbose, bool color);
|
bool verbose, bool color);
|
||||||
|
|
||||||
/** Called from command-line hook to scan dependencies. */
|
|
||||||
bool ScanDependencies(const char* tgtInfo);
|
|
||||||
|
|
||||||
/** Called from command-line hook to clear dependencies. */
|
/** Called from command-line hook to clear dependencies. */
|
||||||
virtual void ClearDependencies(cmMakefile* mf, bool verbose);
|
virtual void ClearDependencies(cmMakefile* mf, bool verbose);
|
||||||
|
|
||||||
|
@ -325,6 +322,10 @@ protected:
|
||||||
|
|
||||||
std::map<cmStdString, std::vector<int> > ProgressFiles;
|
std::map<cmStdString, std::vector<int> > ProgressFiles;
|
||||||
|
|
||||||
|
// Helper methods for dependeny updates.
|
||||||
|
bool ScanDependencies(const char* targetDir);
|
||||||
|
void CheckMultipleOutputs(bool verbose);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class cmMakefileTargetGenerator;
|
friend class cmMakefileTargetGenerator;
|
||||||
friend class cmMakefileExecutableTargetGenerator;
|
friend class cmMakefileExecutableTargetGenerator;
|
||||||
|
|
|
@ -45,9 +45,6 @@ void cmMakefileExecutableTargetGenerator::WriteRuleFiles()
|
||||||
// write the per-target per-language flags
|
// write the per-target per-language flags
|
||||||
this->WriteTargetLanguageFlags();
|
this->WriteTargetLanguageFlags();
|
||||||
|
|
||||||
// Write the dependency generation rule.
|
|
||||||
this->WriteTargetDependRules();
|
|
||||||
|
|
||||||
// write the link rules
|
// write the link rules
|
||||||
this->WriteExecutableRule(false);
|
this->WriteExecutableRule(false);
|
||||||
if(this->Target->NeedRelinkBeforeInstall())
|
if(this->Target->NeedRelinkBeforeInstall())
|
||||||
|
@ -62,6 +59,10 @@ void cmMakefileExecutableTargetGenerator::WriteRuleFiles()
|
||||||
// Write clean target
|
// Write clean target
|
||||||
this->WriteTargetCleanRules();
|
this->WriteTargetCleanRules();
|
||||||
|
|
||||||
|
// Write the dependency generation rule. This must be done last so
|
||||||
|
// that multiple output pair information is available.
|
||||||
|
this->WriteTargetDependRules();
|
||||||
|
|
||||||
// close the streams
|
// close the streams
|
||||||
this->CloseFileStreams();
|
this->CloseFileStreams();
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,9 +47,6 @@ void cmMakefileLibraryTargetGenerator::WriteRuleFiles()
|
||||||
// write the per-target per-language flags
|
// write the per-target per-language flags
|
||||||
this->WriteTargetLanguageFlags();
|
this->WriteTargetLanguageFlags();
|
||||||
|
|
||||||
// Write the dependency generation rule.
|
|
||||||
this->WriteTargetDependRules();
|
|
||||||
|
|
||||||
// write the link rules
|
// write the link rules
|
||||||
// Write the rule for this target type.
|
// Write the rule for this target type.
|
||||||
switch(this->Target->GetType())
|
switch(this->Target->GetType())
|
||||||
|
@ -85,6 +82,10 @@ void cmMakefileLibraryTargetGenerator::WriteRuleFiles()
|
||||||
// Write clean target
|
// Write clean target
|
||||||
this->WriteTargetCleanRules();
|
this->WriteTargetCleanRules();
|
||||||
|
|
||||||
|
// Write the dependency generation rule. This must be done last so
|
||||||
|
// that multiple output pair information is available.
|
||||||
|
this->WriteTargetDependRules();
|
||||||
|
|
||||||
// close the streams
|
// close the streams
|
||||||
this->CloseFileStreams();
|
this->CloseFileStreams();
|
||||||
}
|
}
|
||||||
|
|
|
@ -775,6 +775,23 @@ void cmMakefileTargetGenerator::WriteTargetDependRules()
|
||||||
this->LocalGenerator->
|
this->LocalGenerator->
|
||||||
WriteDependLanguageInfo(*this->InfoFileStream,*this->Target);
|
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 << " \"" << pi->first << "\" \""
|
||||||
|
<< pi->second << "\"\n";
|
||||||
|
}
|
||||||
|
*this->InfoFileStream << " )\n\n";
|
||||||
|
}
|
||||||
|
|
||||||
// and now write the rule to use it
|
// and now write the rule to use it
|
||||||
std::vector<std::string> depends;
|
std::vector<std::string> depends;
|
||||||
std::vector<std::string> commands;
|
std::vector<std::string> commands;
|
||||||
|
@ -993,7 +1010,7 @@ cmMakefileTargetGenerator
|
||||||
// the check-build-system step will remove the primary output if any
|
// the check-build-system step will remove the primary output if any
|
||||||
// extra outputs are missing. This forces the rule to regenerate
|
// extra outputs are missing. This forces the rule to regenerate
|
||||||
// all outputs.
|
// all outputs.
|
||||||
this->GlobalGenerator->AddMultipleOutputPair(out, in);
|
this->AddMultipleOutputPair(out, in);
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
|
@ -1334,3 +1351,12 @@ void cmMakefileTargetGenerator::WriteProgressVariables(unsigned long total,
|
||||||
current += this->NumberOfProgressActions;
|
current += this->NumberOfProgressActions;
|
||||||
delete progressFileStream;
|
delete progressFileStream;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------
|
||||||
|
void
|
||||||
|
cmMakefileTargetGenerator
|
||||||
|
::AddMultipleOutputPair(const char* depender, const char* dependee)
|
||||||
|
{
|
||||||
|
MultipleOutputPairsType::value_type p(depender, dependee);
|
||||||
|
this->MultipleOutputPairs.insert(p);
|
||||||
|
}
|
||||||
|
|
|
@ -119,6 +119,15 @@ protected:
|
||||||
// append intertarget dependencies
|
// append intertarget dependencies
|
||||||
void AppendTargetDepends(std::vector<std::string>& depends);
|
void AppendTargetDepends(std::vector<std::string>& depends);
|
||||||
|
|
||||||
|
/** In order to support parallel builds for custom commands with
|
||||||
|
multiple outputs the outputs are given a serial order, and only
|
||||||
|
the first output actually has the build rule. Other outputs
|
||||||
|
just depend on the first one. The check-build-system step must
|
||||||
|
remove a dependee if the depender is missing to make sure both
|
||||||
|
are regenerated properly. This method is used by the local
|
||||||
|
makefile generators to register such pairs. */
|
||||||
|
void AddMultipleOutputPair(const char* depender, const char* dependee);
|
||||||
|
|
||||||
virtual void CloseFileStreams();
|
virtual void CloseFileStreams();
|
||||||
void RemoveForbiddenFlags(const char* flagVar, const char* linkLang,
|
void RemoveForbiddenFlags(const char* flagVar, const char* linkLang,
|
||||||
std::string& linkFlags);
|
std::string& linkFlags);
|
||||||
|
@ -166,6 +175,8 @@ protected:
|
||||||
// Set of object file names that will be built in this directory.
|
// Set of object file names that will be built in this directory.
|
||||||
std::set<cmStdString> ObjectFiles;
|
std::set<cmStdString> ObjectFiles;
|
||||||
|
|
||||||
|
typedef std::map<cmStdString, cmStdString> MultipleOutputPairsType;
|
||||||
|
MultipleOutputPairsType MultipleOutputPairs;
|
||||||
|
|
||||||
//==================================================================
|
//==================================================================
|
||||||
// Convenience routines that do nothing more than forward to
|
// Convenience routines that do nothing more than forward to
|
||||||
|
|
|
@ -89,6 +89,10 @@ void cmMakefileUtilityTargetGenerator::WriteRuleFiles()
|
||||||
// Write clean target
|
// Write clean target
|
||||||
this->WriteTargetCleanRules();
|
this->WriteTargetCleanRules();
|
||||||
|
|
||||||
|
// Write the dependency generation rule. This must be done last so
|
||||||
|
// that multiple output pair information is available.
|
||||||
|
this->WriteTargetDependRules();
|
||||||
|
|
||||||
// close the streams
|
// close the streams
|
||||||
this->CloseFileStreams();
|
this->CloseFileStreams();
|
||||||
}
|
}
|
||||||
|
|
|
@ -2547,29 +2547,24 @@ int cmake::CheckBuildSystem()
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now that we know the generator used to build the project, use it
|
if(this->ClearBuildSystem)
|
||||||
// to check the dependency integrity.
|
|
||||||
const char* genName = mf->GetDefinition("CMAKE_DEPENDS_GENERATOR");
|
|
||||||
if (!genName || genName[0] == '\0')
|
|
||||||
{
|
{
|
||||||
genName = "Unix Makefiles";
|
// Get the generator used for this build system.
|
||||||
}
|
const char* genName = mf->GetDefinition("CMAKE_DEPENDS_GENERATOR");
|
||||||
// this global generator is never set to the cmake object so it is never
|
if(!genName || genName[0] == '\0')
|
||||||
// deleted, so make it an auto_ptr
|
|
||||||
std::auto_ptr<cmGlobalGenerator> ggd(this->CreateGlobalGenerator(genName));
|
|
||||||
if (ggd.get())
|
|
||||||
{
|
|
||||||
// Check the dependencies in case source files were removed.
|
|
||||||
std::auto_ptr<cmLocalGenerator> lgd(ggd->CreateLocalGenerator());
|
|
||||||
lgd->SetGlobalGenerator(ggd.get());
|
|
||||||
|
|
||||||
if(this->ClearBuildSystem)
|
|
||||||
{
|
{
|
||||||
lgd->ClearDependencies(mf, verbose);
|
genName = "Unix Makefiles";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for multiple output pairs.
|
// Create the generator and use it to clear the dependencies.
|
||||||
ggd->CheckMultipleOutputs(mf, verbose);
|
std::auto_ptr<cmGlobalGenerator>
|
||||||
|
ggd(this->CreateGlobalGenerator(genName));
|
||||||
|
if(ggd.get())
|
||||||
|
{
|
||||||
|
std::auto_ptr<cmLocalGenerator> lgd(ggd->CreateLocalGenerator());
|
||||||
|
lgd->SetGlobalGenerator(ggd.get());
|
||||||
|
lgd->ClearDependencies(mf, verbose);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the set of dependencies and outputs.
|
// Get the set of dependencies and outputs.
|
||||||
|
|
|
@ -13,6 +13,8 @@ write_file(${BuildDepends_BINARY_DIR}/Project/foo.cxx
|
||||||
|
|
||||||
file(WRITE ${BuildDepends_BINARY_DIR}/Project/zot.hxx.in
|
file(WRITE ${BuildDepends_BINARY_DIR}/Project/zot.hxx.in
|
||||||
"static const char* zot = \"zot\";\n")
|
"static const char* zot = \"zot\";\n")
|
||||||
|
file(WRITE ${BuildDepends_BINARY_DIR}/Project/zot_custom.hxx.in
|
||||||
|
"static const char* zot_custom = \"zot_custom\";\n")
|
||||||
|
|
||||||
message("Building project first time")
|
message("Building project first time")
|
||||||
try_compile(RESULT
|
try_compile(RESULT
|
||||||
|
@ -70,11 +72,11 @@ execute_process(COMMAND ${zot} OUTPUT_VARIABLE out RESULT_VARIABLE runResult)
|
||||||
string(REGEX REPLACE "[\r\n]" " " out "${out}")
|
string(REGEX REPLACE "[\r\n]" " " out "${out}")
|
||||||
message("Run result: ${runResult} Output: \"${out}\"")
|
message("Run result: ${runResult} Output: \"${out}\"")
|
||||||
|
|
||||||
if("${out}" STREQUAL "zot ")
|
if("${out}" STREQUAL "[zot] [zot_custom] ")
|
||||||
message("Worked!")
|
message("Worked!")
|
||||||
else("${out}" STREQUAL "zot ")
|
else("${out}" STREQUAL "[zot] [zot_custom] ")
|
||||||
message(SEND_ERROR "Project did not initially build properly: ${out}")
|
message(SEND_ERROR "Project did not initially build properly: ${out}")
|
||||||
endif("${out}" STREQUAL "zot ")
|
endif("${out}" STREQUAL "[zot] [zot_custom] ")
|
||||||
|
|
||||||
message("Waiting 3 seconds...")
|
message("Waiting 3 seconds...")
|
||||||
# any additional argument will cause ${bar} to wait forever
|
# any additional argument will cause ${bar} to wait forever
|
||||||
|
@ -85,6 +87,8 @@ write_file(${BuildDepends_BINARY_DIR}/Project/foo.cxx
|
||||||
"const char* foo() { return \"foo changed\";}" )
|
"const char* foo() { return \"foo changed\";}" )
|
||||||
file(WRITE ${BuildDepends_BINARY_DIR}/Project/zot.hxx.in
|
file(WRITE ${BuildDepends_BINARY_DIR}/Project/zot.hxx.in
|
||||||
"static const char* zot = \"zot changed\";\n")
|
"static const char* zot = \"zot changed\";\n")
|
||||||
|
file(WRITE ${BuildDepends_BINARY_DIR}/Project/zot_custom.hxx.in
|
||||||
|
"static const char* zot_custom = \"zot_custom changed\";\n")
|
||||||
|
|
||||||
message("Building project second time")
|
message("Building project second time")
|
||||||
try_compile(RESULT
|
try_compile(RESULT
|
||||||
|
@ -137,8 +141,8 @@ execute_process(COMMAND ${zot} OUTPUT_VARIABLE out RESULT_VARIABLE runResult)
|
||||||
string(REGEX REPLACE "[\r\n]" " " out "${out}")
|
string(REGEX REPLACE "[\r\n]" " " out "${out}")
|
||||||
message("Run result: ${runResult} Output: \"${out}\"")
|
message("Run result: ${runResult} Output: \"${out}\"")
|
||||||
|
|
||||||
if("${out}" STREQUAL "zot changed ")
|
if("${out}" STREQUAL "[zot changed] [zot_custom changed] ")
|
||||||
message("Worked!")
|
message("Worked!")
|
||||||
else("${out}" STREQUAL "zot changed ")
|
else("${out}" STREQUAL "[zot changed] [zot_custom changed] ")
|
||||||
message(SEND_ERROR "Project did not rebuild properly!")
|
message(SEND_ERROR "Project did not rebuild properly!")
|
||||||
endif("${out}" STREQUAL "zot changed ")
|
endif("${out}" STREQUAL "[zot changed] [zot_custom changed] ")
|
||||||
|
|
|
@ -32,9 +32,12 @@ add_executable(bar bar.cxx
|
||||||
IF("${CMAKE_GENERATOR}" MATCHES "Make")
|
IF("${CMAKE_GENERATOR}" MATCHES "Make")
|
||||||
# Test the IMPLICIT_DEPENDS feature.
|
# Test the IMPLICIT_DEPENDS feature.
|
||||||
SET(ZOT_DEPENDS IMPLICIT_DEPENDS CXX ${CMAKE_CURRENT_SOURCE_DIR}/dep.cxx)
|
SET(ZOT_DEPENDS IMPLICIT_DEPENDS CXX ${CMAKE_CURRENT_SOURCE_DIR}/dep.cxx)
|
||||||
|
SET(ZOT_CUSTOM_DEP
|
||||||
|
IMPLICIT_DEPENDS CXX ${CMAKE_CURRENT_SOURCE_DIR}/dep_custom.cxx)
|
||||||
ELSE("${CMAKE_GENERATOR}" MATCHES "Make")
|
ELSE("${CMAKE_GENERATOR}" MATCHES "Make")
|
||||||
# No IMPLICIT_DEPENDS...just depend directly.
|
# No IMPLICIT_DEPENDS...just depend directly.
|
||||||
SET(ZOT_DEPENDS DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/zot.hxx.in)
|
SET(ZOT_DEPENDS DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/zot.hxx.in)
|
||||||
|
SET(ZOT_CUSTOM_DEP DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/zot_custom.hxx.in)
|
||||||
ENDIF("${CMAKE_GENERATOR}" MATCHES "Make")
|
ENDIF("${CMAKE_GENERATOR}" MATCHES "Make")
|
||||||
add_custom_command(
|
add_custom_command(
|
||||||
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/zot.hxx
|
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/zot.hxx
|
||||||
|
@ -44,4 +47,15 @@ add_custom_command(
|
||||||
${ZOT_DEPENDS}
|
${ZOT_DEPENDS}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
add_custom_command(
|
||||||
|
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/zot_custom.hxx
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/zot_custom.hxx.in
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/zot_custom.hxx
|
||||||
|
${ZOT_CUSTOM_DEP}
|
||||||
|
)
|
||||||
|
add_custom_target(zot_custom ALL DEPENDS
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/zot_custom.hxx)
|
||||||
|
|
||||||
add_executable(zot zot.cxx ${CMAKE_CURRENT_BINARY_DIR}/zot.hxx)
|
add_executable(zot zot.cxx ${CMAKE_CURRENT_BINARY_DIR}/zot.hxx)
|
||||||
|
add_dependencies(zot zot_custom)
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
#include <zot_custom.hxx.in>
|
|
@ -1,9 +1,10 @@
|
||||||
#include <zot.hxx>
|
#include <zot.hxx>
|
||||||
|
#include <zot_custom.hxx>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
printf("%s\n", zot);
|
printf("[%s] [%s]\n", zot, zot_custom);
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue