ENH: Make sure all custom command outputs are up to date before scanning dependencies. This avoids the need to pass a list of generated files to the dependency scanning code and to rescan after the files have been generated. Currently there is no notion of implicit dependencies of the custom commands themselves so this design is safe. We only need to make sure implicit dependencies are up to date before the make process for the /build part of a target is executed because only this process loads them. This is a step towards fixing bug#3658.

This commit is contained in:
Brad King 2006-08-31 14:09:56 -04:00
parent f12742d6cd
commit 409f70bc91
4 changed files with 22 additions and 135 deletions

View File

@ -24,20 +24,18 @@
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
cmDependsC::cmDependsC(): cmDependsC::cmDependsC():
IncludePath(0), GeneratedFiles(0) IncludePath(0)
{ {
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// yummy look at all those constructor arguments // yummy look at all those constructor arguments
cmDependsC::cmDependsC(std::vector<std::string> const& includes, cmDependsC::cmDependsC(std::vector<std::string> const& includes,
const char* scanRegex, const char* complainRegex, const char* scanRegex, const char* complainRegex,
std::set<cmStdString> const& generatedFiles,
const cmStdString& cacheFileName): const cmStdString& cacheFileName):
IncludePath(&includes), IncludePath(&includes),
IncludeRegexLine("^[ \t]*#[ \t]*include[ \t]*[<\"]([^\">]+)([\">])"), IncludeRegexLine("^[ \t]*#[ \t]*include[ \t]*[<\"]([^\">]+)([\">])"),
IncludeRegexScan(scanRegex), IncludeRegexScan(scanRegex),
IncludeRegexComplain(complainRegex), IncludeRegexComplain(complainRegex),
GeneratedFiles(&generatedFiles),
CacheFileName(cacheFileName) CacheFileName(cacheFileName)
{ {
this->ReadCacheFile(); this->ReadCacheFile();
@ -96,15 +94,13 @@ bool cmDependsC::WriteDependencies(const char *src, const char *obj,
std::string fullName; std::string fullName;
if(first || cmSystemTools::FileIsFullPath(current.FileName.c_str())) if(first || cmSystemTools::FileIsFullPath(current.FileName.c_str()))
{ {
if(this->FileExistsOrIsGenerated(current.FileName, scanned, if(cmSystemTools::FileExists(current.FileName.c_str()))
dependencies))
{ {
fullName = current.FileName; fullName = current.FileName;
} }
} }
else if(!current.QuotedLocation.empty() && else if(!current.QuotedLocation.empty() &&
this->FileExistsOrIsGenerated(current.QuotedLocation, scanned, cmSystemTools::FileExists(current.QuotedLocation.c_str()))
dependencies))
{ {
// The include statement producing this entry was a double-quote // The include statement producing this entry was a double-quote
// include and the included file is present in the directory of // include and the included file is present in the directory of
@ -130,7 +126,7 @@ bool cmDependsC::WriteDependencies(const char *src, const char *obj,
temp += current.FileName; temp += current.FileName;
// Look for the file in this location. // Look for the file in this location.
if(this->FileExistsOrIsGenerated(temp, scanned, dependencies)) if(cmSystemTools::FileExists(temp.c_str()))
{ {
fullName = temp; fullName = temp;
break; break;
@ -359,57 +355,3 @@ void cmDependsC::Scan(std::istream& is, const char* directory,
} }
} }
} }
//----------------------------------------------------------------------------
bool cmDependsC::FileExistsOrIsGenerated(const std::string& fname,
std::set<cmStdString>& scanned,
std::set<cmStdString>& dependencies)
{
// Check for a generated file.
if(this->FileIsGenerated(fname, scanned, dependencies))
{
return true;
}
else if(cmSystemTools::FileIsFullPath(fname.c_str()))
{
// The generated file may have been listed with a relative path.
// Note that CMAKE_GENERATED_FILES is written with a conversion
// relative to the home output directory.
std::string rname =
this->LocalGenerator->Convert(fname.c_str(),
cmLocalGenerator::HOME_OUTPUT,
cmLocalGenerator::UNCHANGED);
if(this->FileIsGenerated(rname, scanned, dependencies))
{
return true;
}
}
// Check for an existing file.
return cmSystemTools::FileExists(fname.c_str());
}
//----------------------------------------------------------------------------
bool cmDependsC::FileIsGenerated(const std::string& fname,
std::set<cmStdString>& scanned,
std::set<cmStdString>& dependencies)
{
if(this->GeneratedFiles &&
std::set<cmStdString>::const_iterator(this->GeneratedFiles->find(fname))
!= this->GeneratedFiles->end())
{
// If the file does not really exist yet pretend it has already
// been scanned. When it exists later then dependencies will be
// rescanned.
if(!cmSystemTools::FileExists(fname.c_str()))
{
scanned.insert(fname);
dependencies.insert(fname);
}
return true;
}
else
{
return false;
}
}

View File

@ -32,7 +32,6 @@ public:
cmDependsC(); cmDependsC();
cmDependsC(std::vector<std::string> const& includes, cmDependsC(std::vector<std::string> const& includes,
const char* scanRegex, const char* complainRegex, const char* scanRegex, const char* complainRegex,
std::set<cmStdString> const& generatedFiles,
const cmStdString& cachFileName); const cmStdString& cachFileName);
/** Virtual destructor to cleanup subclasses properly. */ /** Virtual destructor to cleanup subclasses properly. */
@ -51,14 +50,6 @@ protected:
void Scan(std::istream& is, const char* directory, void Scan(std::istream& is, const char* directory,
const cmStdString& fullName); const cmStdString& fullName);
// Method to test for the existence of a file.
bool FileExistsOrIsGenerated(const std::string& fname,
std::set<cmStdString>& scanned,
std::set<cmStdString>& dependencies);
bool FileIsGenerated(const std::string& fname,
std::set<cmStdString>& scanned,
std::set<cmStdString>& dependencies);
// The include file search path. // The include file search path.
std::vector<std::string> const* IncludePath; std::vector<std::string> const* IncludePath;
@ -70,8 +61,6 @@ protected:
cmsys::RegularExpression IncludeRegexScan; cmsys::RegularExpression IncludeRegexScan;
cmsys::RegularExpression IncludeRegexComplain; cmsys::RegularExpression IncludeRegexComplain;
// Set of generated files available.
std::set<cmStdString> const* GeneratedFiles;
public: public:
// Data structures for dependency graph walk. // Data structures for dependency graph walk.
struct UnscannedEntry struct UnscannedEntry

View File

@ -477,8 +477,6 @@ void cmLocalUnixMakefileGenerator3::WriteDirectoryInformationFile()
for(std::vector<std::string>::iterator i = includeDirs.begin(); for(std::vector<std::string>::iterator i = includeDirs.begin();
i != includeDirs.end(); ++i) i != includeDirs.end(); ++i)
{ {
// Note: This path conversion must match that used for
// CMAKE_GENERATED_FILES so that the file names match.
infoFileStream infoFileStream
<< " \"" << this->Convert(i->c_str(),HOME_OUTPUT).c_str() << "\"\n"; << " \"" << this->Convert(i->c_str(),HOME_OUTPUT).c_str() << "\"\n";
} }
@ -509,30 +507,6 @@ void cmLocalUnixMakefileGenerator3::WriteDirectoryInformationFile()
infoFileStream infoFileStream
<< "SET(CMAKE_CXX_INCLUDE_REGEX_COMPLAIN " << "SET(CMAKE_CXX_INCLUDE_REGEX_COMPLAIN "
"${CMAKE_C_INCLUDE_REGEX_COMPLAIN})\n"; "${CMAKE_C_INCLUDE_REGEX_COMPLAIN})\n";
// Store the set of available generated files.
infoFileStream
<< "\n"
<< "# The set of files generated by rules in this directory:\n";
infoFileStream
<< "SET(CMAKE_GENERATED_FILES\n";
for(std::vector<cmSourceFile*>::const_iterator
i = this->Makefile->GetSourceFiles().begin();
i != this->Makefile->GetSourceFiles().end(); ++i)
{
cmSourceFile* src = *i;
if(src->GetPropertyAsBool("GENERATED"))
{
// Note: This path conversion must match that used for
// CMAKE_C_INCLUDE_PATH so that the file names match.
infoFileStream
<< " \""
<< this->Convert(src->GetFullPath().c_str(), HOME_OUTPUT)
<< "\"\n";
}
}
infoFileStream
<< ")\n";
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@ -1292,24 +1266,6 @@ bool cmLocalUnixMakefileGenerator3::ScanDependencies(const char* tgtInfo)
this->WriteDisclaimer(ruleFileStream); this->WriteDisclaimer(ruleFileStream);
this->WriteDisclaimer(internalRuleFileStream); this->WriteDisclaimer(internalRuleFileStream);
// Get the set of generated files.
std::vector<std::string> generatedFilesVec;
if(haveDirectoryInfo)
{
if(const char* generated = mf->GetDefinition("CMAKE_GENERATED_FILES"))
{
cmSystemTools::ExpandListArgument(generated, generatedFilesVec);
}
}
// Sort for efficient lookup.
std::set<cmStdString> generatedFiles;
for(std::vector<std::string>::iterator gfi = generatedFilesVec.begin();
gfi != generatedFilesVec.end(); ++gfi)
{
generatedFiles.insert(*gfi);
}
// for each language we need to scan, scan it // for each language we need to scan, scan it
const char *langStr = mf->GetSafeDefinition("CMAKE_DEPENDS_LANGUAGES"); const char *langStr = mf->GetSafeDefinition("CMAKE_DEPENDS_LANGUAGES");
std::vector<std::string> langs; std::vector<std::string> langs;
@ -1367,7 +1323,7 @@ bool cmLocalUnixMakefileGenerator3::ScanDependencies(const char* tgtInfo)
scanner = new cmDependsC(includes, scanner = new cmDependsC(includes,
includeRegexScan.c_str(), includeRegexScan.c_str(),
includeRegexComplain.c_str(), includeRegexComplain.c_str(),
generatedFiles, includeCacheFileName); includeCacheFileName);
scanner->SetLocalGenerator(this); scanner->SetLocalGenerator(this);
} }
#ifdef CMAKE_BUILD_WITH_CMAKE #ifdef CMAKE_BUILD_WITH_CMAKE

View File

@ -775,6 +775,23 @@ void cmMakefileTargetGenerator::WriteTargetDependRules()
cmLocalGenerator::FULL, cmLocalGenerator::SHELL); cmLocalGenerator::FULL, cmLocalGenerator::SHELL);
commands.push_back(depCmd.str()); commands.push_back(depCmd.str());
// Make sure all custom command outputs in this target are built.
const std::vector<cmSourceFile*>& sources =
this->Target->GetSourceFiles();
for(std::vector<cmSourceFile*>::const_iterator source = sources.begin();
source != sources.end(); ++source)
{
if(cmCustomCommand* cc = (*source)->GetCustomCommand())
{
const std::vector<std::string>& outputs = cc->GetOutputs();
for(std::vector<std::string>::const_iterator o = outputs.begin();
o != outputs.end(); ++o)
{
depends.push_back(*o);
}
}
}
// Write the rule. // Write the rule.
this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0, this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
depMark.c_str(), depMark.c_str(),
@ -1024,23 +1041,6 @@ void cmMakefileTargetGenerator::WriteTargetDriverRule(const char* main_output,
{ {
// Setup the comment for the main build driver. // Setup the comment for the main build driver.
comment = "Rule to build all files generated by this target."; comment = "Rule to build all files generated by this target.";
// Make sure all custom command outputs in this target are built.
const std::vector<cmSourceFile*>& sources =
this->Target->GetSourceFiles();
for(std::vector<cmSourceFile*>::const_iterator source = sources.begin();
source != sources.end(); ++source)
{
if(cmCustomCommand* cc = (*source)->GetCustomCommand())
{
const std::vector<std::string>& outputs = cc->GetOutputs();
for(std::vector<std::string>::const_iterator o = outputs.begin();
o != outputs.end(); ++o)
{
depends.push_back(*o);
}
}
}
} }
// Write the driver rule. // Write the driver rule.