ENH: Implemented support for include/complain regular expressions for dependency scanning. This now includes the possibility that scanning will return failure and the build will stop.
This commit is contained in:
parent
c44e6d30e5
commit
337ad802c6
|
@ -42,7 +42,7 @@ cmDepends::~cmDepends()
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
void cmDepends::Write()
|
bool cmDepends::Write()
|
||||||
{
|
{
|
||||||
// Try to generate dependencies for the target file.
|
// Try to generate dependencies for the target file.
|
||||||
cmGeneratedFileStream fout(m_DependsMakeFile.c_str());
|
cmGeneratedFileStream fout(m_DependsMakeFile.c_str());
|
||||||
|
@ -52,6 +52,11 @@ void cmDepends::Write()
|
||||||
// Dependencies were generated. Touch the mark file.
|
// Dependencies were generated. Touch the mark file.
|
||||||
std::ofstream fmark(m_DependsMarkFile.c_str());
|
std::ofstream fmark(m_DependsMarkFile.c_str());
|
||||||
fmark << "Dependencies updated for " << m_TargetFile.c_str() << std::endl;
|
fmark << "Dependencies updated for " << m_TargetFile.c_str() << std::endl;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,7 @@ public:
|
||||||
virtual ~cmDepends();
|
virtual ~cmDepends();
|
||||||
|
|
||||||
/** Write dependencies for the target file. */
|
/** Write dependencies for the target file. */
|
||||||
void Write();
|
bool Write();
|
||||||
|
|
||||||
/** Check dependencies for the target file. */
|
/** Check dependencies for the target file. */
|
||||||
void Check();
|
void Check();
|
||||||
|
|
|
@ -23,18 +23,23 @@ cmDependsC::cmDependsC(const char* dir, const char* targetFile):
|
||||||
cmDepends(dir, targetFile),
|
cmDepends(dir, targetFile),
|
||||||
m_SourceFile(),
|
m_SourceFile(),
|
||||||
m_IncludePath(0),
|
m_IncludePath(0),
|
||||||
m_IncludeLineRegex()
|
m_IncludeRegexLine(),
|
||||||
|
m_IncludeRegexScan(),
|
||||||
|
m_IncludeRegexComplain()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
cmDependsC::cmDependsC(const char* dir, const char* targetFile,
|
cmDependsC::cmDependsC(const char* dir, const char* targetFile,
|
||||||
const char* sourceFile,
|
const char* sourceFile,
|
||||||
std::vector<std::string> const& includes):
|
std::vector<std::string> const& includes,
|
||||||
|
const char* scanRegex, const char* complainRegex):
|
||||||
cmDepends(dir, targetFile),
|
cmDepends(dir, targetFile),
|
||||||
m_SourceFile(sourceFile),
|
m_SourceFile(sourceFile),
|
||||||
m_IncludePath(&includes),
|
m_IncludePath(&includes),
|
||||||
m_IncludeLineRegex("^[ \t]*#[ \t]*include[ \t]*[<\"]([^\">]+)[\">]")
|
m_IncludeRegexLine("^[ \t]*#[ \t]*include[ \t]*[<\"]([^\">]+)[\">]"),
|
||||||
|
m_IncludeRegexScan(scanRegex),
|
||||||
|
m_IncludeRegexComplain(complainRegex)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,6 +66,7 @@ bool cmDependsC::WriteDependencies(std::ostream& os)
|
||||||
// Walk the dependency graph starting with the source file.
|
// Walk the dependency graph starting with the source file.
|
||||||
bool first = true;
|
bool first = true;
|
||||||
m_Unscanned.push(m_SourceFile);
|
m_Unscanned.push(m_SourceFile);
|
||||||
|
m_Encountered.clear();
|
||||||
m_Encountered.insert(m_SourceFile);
|
m_Encountered.insert(m_SourceFile);
|
||||||
std::set<cmStdString> dependencies;
|
std::set<cmStdString> dependencies;
|
||||||
std::set<cmStdString> scanned;
|
std::set<cmStdString> scanned;
|
||||||
|
@ -74,7 +80,10 @@ bool cmDependsC::WriteDependencies(std::ostream& os)
|
||||||
std::string fullName;
|
std::string fullName;
|
||||||
if(first || cmSystemTools::FileIsFullPath(fname.c_str()))
|
if(first || cmSystemTools::FileIsFullPath(fname.c_str()))
|
||||||
{
|
{
|
||||||
fullName = fname;
|
if(cmSystemTools::FileExists(fname.c_str()))
|
||||||
|
{
|
||||||
|
fullName = fname;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -92,8 +101,16 @@ bool cmDependsC::WriteDependencies(std::ostream& os)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Complain if the file cannot be found and matches the complain
|
||||||
|
// regex.
|
||||||
|
if(fullName.empty() && m_IncludeRegexComplain.find(fname.c_str()))
|
||||||
|
{
|
||||||
|
cmSystemTools::Error("Cannot find file \"", fname.c_str(), "\".");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Scan the file if it was found and has not been scanned already.
|
// Scan the file if it was found and has not been scanned already.
|
||||||
if(fullName.size() && (scanned.find(fullName) == scanned.end()))
|
if(!fullName.empty() && (scanned.find(fullName) == scanned.end()))
|
||||||
{
|
{
|
||||||
// Record scanned files.
|
// Record scanned files.
|
||||||
scanned.insert(fullName);
|
scanned.insert(fullName);
|
||||||
|
@ -113,7 +130,6 @@ bool cmDependsC::WriteDependencies(std::ostream& os)
|
||||||
|
|
||||||
first = false;
|
first = false;
|
||||||
}
|
}
|
||||||
m_Encountered.clear();
|
|
||||||
|
|
||||||
// Write the dependencies to the output stream.
|
// Write the dependencies to the output stream.
|
||||||
for(std::set<cmStdString>::iterator i=dependencies.begin();
|
for(std::set<cmStdString>::iterator i=dependencies.begin();
|
||||||
|
@ -228,16 +244,16 @@ void cmDependsC::Scan(std::istream& is)
|
||||||
std::string line;
|
std::string line;
|
||||||
while(cmSystemTools::GetLineFromStream(is, line))
|
while(cmSystemTools::GetLineFromStream(is, line))
|
||||||
{
|
{
|
||||||
// Match include directives. TODO: Support include regex and
|
// Match include directives.
|
||||||
// ignore regex. Possibly also support directory-based inclusion
|
if(m_IncludeRegexLine.find(line.c_str()))
|
||||||
// in dependencies.
|
|
||||||
if(m_IncludeLineRegex.find(line.c_str()))
|
|
||||||
{
|
{
|
||||||
// Get the file being included.
|
// Get the file being included.
|
||||||
std::string includeFile = m_IncludeLineRegex.match(1);
|
std::string includeFile = m_IncludeRegexLine.match(1);
|
||||||
|
|
||||||
// Queue the file if it has not yet been encountered.
|
// Queue the file if it has not yet been encountered and it
|
||||||
if(m_Encountered.find(includeFile) == m_Encountered.end())
|
// matches the regular expression for recursive scanning.
|
||||||
|
if(m_Encountered.find(includeFile) == m_Encountered.end() &&
|
||||||
|
m_IncludeRegexScan.find(includeFile.c_str()))
|
||||||
{
|
{
|
||||||
m_Encountered.insert(includeFile);
|
m_Encountered.insert(includeFile);
|
||||||
m_Unscanned.push(includeFile);
|
m_Unscanned.push(includeFile);
|
||||||
|
|
|
@ -34,9 +34,10 @@ public:
|
||||||
/** Scanning need to know the build directory name, the relative
|
/** Scanning need to know the build directory name, the relative
|
||||||
path from the build directory to the target file, the source
|
path from the build directory to the target file, the source
|
||||||
file from which to start scanning, and the include file search
|
file from which to start scanning, and the include file search
|
||||||
path. */
|
path. It also uses the include file regular expressions. */
|
||||||
cmDependsC(const char* dir, const char* targetFile,
|
cmDependsC(const char* dir, const char* targetFile,
|
||||||
const char* sourceFile, std::vector<std::string> const& includes);
|
const char* sourceFile, std::vector<std::string> const& includes,
|
||||||
|
const char* scanRegex, const char* complainRegex);
|
||||||
|
|
||||||
/** Virtual destructor to cleanup subclasses properly. */
|
/** Virtual destructor to cleanup subclasses properly. */
|
||||||
virtual ~cmDependsC();
|
virtual ~cmDependsC();
|
||||||
|
@ -56,7 +57,12 @@ protected:
|
||||||
std::vector<std::string> const* m_IncludePath;
|
std::vector<std::string> const* m_IncludePath;
|
||||||
|
|
||||||
// Regular expression to identify C preprocessor include directives.
|
// Regular expression to identify C preprocessor include directives.
|
||||||
cmsys::RegularExpression m_IncludeLineRegex;
|
cmsys::RegularExpression m_IncludeRegexLine;
|
||||||
|
|
||||||
|
// Regular expressions to choose which include files to scan
|
||||||
|
// recursively and which to complain about not finding.
|
||||||
|
cmsys::RegularExpression m_IncludeRegexScan;
|
||||||
|
cmsys::RegularExpression m_IncludeRegexComplain;
|
||||||
|
|
||||||
// Data structures for dependency graph walk.
|
// Data structures for dependency graph walk.
|
||||||
std::set<cmStdString> m_Encountered;
|
std::set<cmStdString> m_Encountered;
|
||||||
|
|
|
@ -234,6 +234,7 @@ void cmLocalUnixMakefileGenerator2::GenerateCMakefile()
|
||||||
<< "SET(CMAKE_MAKEFILE_OUTPUTS\n"
|
<< "SET(CMAKE_MAKEFILE_OUTPUTS\n"
|
||||||
<< " \"" << this->ConvertToRelativePath(makefileName.c_str()).c_str() << "\"\n"
|
<< " \"" << this->ConvertToRelativePath(makefileName.c_str()).c_str() << "\"\n"
|
||||||
<< " \"" << this->ConvertToRelativePath(check.c_str()).c_str() << "\"\n"
|
<< " \"" << this->ConvertToRelativePath(check.c_str()).c_str() << "\"\n"
|
||||||
|
<< " \"CMakeDirectoryInformation.cmake\"\n"
|
||||||
<< " )\n\n";
|
<< " )\n\n";
|
||||||
|
|
||||||
// Set the set of files to check for dependency integrity.
|
// Set the set of files to check for dependency integrity.
|
||||||
|
@ -525,8 +526,7 @@ cmLocalUnixMakefileGenerator2
|
||||||
// touch the corresponding depends file after scanning dependencies.
|
// touch the corresponding depends file after scanning dependencies.
|
||||||
cmOStringStream depCmd;
|
cmOStringStream depCmd;
|
||||||
// TODO: Account for source file properties and directory-level
|
// TODO: Account for source file properties and directory-level
|
||||||
// definitions when scanning for dependencies. Also account for
|
// definitions when scanning for dependencies.
|
||||||
// include/ignore regular expressions.
|
|
||||||
depCmd << "$(CMAKE_COMMAND) -E cmake_depends " << lang << " "
|
depCmd << "$(CMAKE_COMMAND) -E cmake_depends " << lang << " "
|
||||||
<< this->ConvertToRelativeOutputPath(obj.c_str()) << " "
|
<< this->ConvertToRelativeOutputPath(obj.c_str()) << " "
|
||||||
<< this->ConvertToRelativeOutputPath(source.GetFullPath().c_str());
|
<< this->ConvertToRelativeOutputPath(source.GetFullPath().c_str());
|
||||||
|
@ -2854,20 +2854,41 @@ cmLocalUnixMakefileGenerator2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get the include file regular expression.
|
||||||
|
std::string includeRegexScan = "^.*$";
|
||||||
|
std::string includeRegexComplain = "^$";
|
||||||
|
if(haveDirectoryInfo)
|
||||||
|
{
|
||||||
|
std::string scanRegexVar = "CMAKE_";
|
||||||
|
scanRegexVar += lang;
|
||||||
|
scanRegexVar += "_INCLUDE_REGEX_SCAN";
|
||||||
|
if(const char* scanRegex = mf->GetDefinition(scanRegexVar.c_str()))
|
||||||
|
{
|
||||||
|
includeRegexScan = scanRegex;
|
||||||
|
}
|
||||||
|
std::string complainRegexVar = "CMAKE_";
|
||||||
|
complainRegexVar += lang;
|
||||||
|
complainRegexVar += "_INCLUDE_REGEX_COMPLAIN";
|
||||||
|
if(const char* complainRegex = mf->GetDefinition(complainRegexVar.c_str()))
|
||||||
|
{
|
||||||
|
includeRegexComplain = complainRegex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Dispatch the scan for each language.
|
// Dispatch the scan for each language.
|
||||||
if(lang == "C" || lang == "CXX" || lang == "RC")
|
if(lang == "C" || lang == "CXX" || lang == "RC")
|
||||||
{
|
{
|
||||||
// TODO: Handle RC (resource files) dependencies correctly.
|
// TODO: Handle RC (resource files) dependencies correctly.
|
||||||
cmDependsC scanner(".", objFile, srcFile, includes);
|
cmDependsC scanner(".", objFile, srcFile, includes,
|
||||||
scanner.Write();
|
includeRegexScan.c_str(), includeRegexComplain.c_str());
|
||||||
return true;
|
return scanner.Write();
|
||||||
|
true;
|
||||||
}
|
}
|
||||||
#ifdef CMAKE_BUILD_WITH_CMAKE
|
#ifdef CMAKE_BUILD_WITH_CMAKE
|
||||||
else if(lang == "Fortran")
|
else if(lang == "Fortran")
|
||||||
{
|
{
|
||||||
cmDependsFortran scanner(".", objFile, srcFile, includes);
|
cmDependsFortran scanner(".", objFile, srcFile, includes);
|
||||||
scanner.Write();
|
return scanner.Write();
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
return false;
|
return false;
|
||||||
|
|
Loading…
Reference in New Issue