mirror of
https://github.com/Kitware/CMake.git
synced 2026-04-22 14:23:10 -05:00
Autogen: Overhaul FindMatchingHeader function
This commit is contained in:
committed by
Brad King
parent
3270091210
commit
815a05cf12
@@ -74,42 +74,6 @@ static void SettingWrite(std::ostream& ostr, const char* key,
|
||||
}
|
||||
}
|
||||
|
||||
static std::string FindMatchingHeader(
|
||||
const std::string& absPath, const std::string& mocSubDir,
|
||||
const std::string& basename,
|
||||
const std::vector<std::string>& headerExtensions)
|
||||
{
|
||||
std::string header;
|
||||
for (std::vector<std::string>::const_iterator ext = headerExtensions.begin();
|
||||
ext != headerExtensions.end(); ++ext) {
|
||||
std::string sourceFilePath = absPath + basename + "." + (*ext);
|
||||
if (cmsys::SystemTools::FileExists(sourceFilePath.c_str())) {
|
||||
header = sourceFilePath;
|
||||
break;
|
||||
}
|
||||
// Try subdirectory instead
|
||||
if (!mocSubDir.empty()) {
|
||||
sourceFilePath = mocSubDir + basename + "." + (*ext);
|
||||
if (cmsys::SystemTools::FileExists(sourceFilePath.c_str())) {
|
||||
header = sourceFilePath;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return header;
|
||||
}
|
||||
|
||||
static std::string ExtractSubDir(const std::string& absPath,
|
||||
const std::string& currentMoc)
|
||||
{
|
||||
std::string subDir;
|
||||
if (currentMoc.find_first_of('/') != std::string::npos) {
|
||||
subDir = absPath + cmsys::SystemTools::GetFilenamePath(currentMoc) + '/';
|
||||
}
|
||||
return subDir;
|
||||
}
|
||||
|
||||
static bool FileNameIsUnique(const std::string& filePath,
|
||||
const std::map<std::string, std::string>& fileMap)
|
||||
{
|
||||
@@ -807,38 +771,38 @@ bool cmQtAutoGenerators::ParseContentForMoc(
|
||||
if (strstr(contentChars, "moc") != CM_NULLPTR) {
|
||||
// Iterate over all included moc files
|
||||
while (this->RegExpMocInclude.find(contentChars)) {
|
||||
const std::string currentMoc = this->RegExpMocInclude.match(1);
|
||||
// Basename of the current moc include
|
||||
std::string basename =
|
||||
cmsys::SystemTools::GetFilenameWithoutLastExtension(currentMoc);
|
||||
const std::string incString = this->RegExpMocInclude.match(1);
|
||||
// Basename of the moc include
|
||||
const std::string incBasename =
|
||||
cmsys::SystemTools::GetFilenameWithoutLastExtension(incString);
|
||||
std::string incSubDir;
|
||||
if (incString.find_first_of('/') != std::string::npos) {
|
||||
incSubDir = cmsys::SystemTools::GetFilenamePath(incString) + '/';
|
||||
}
|
||||
|
||||
// If the moc include is of the moc_foo.cpp style we expect
|
||||
// the Q_OBJECT class declaration in a header file.
|
||||
// If the moc include is of the foo.moc style we need to look for
|
||||
// a Q_OBJECT macro in the current source file, if it contains the
|
||||
// macro we generate the moc file from the source file.
|
||||
if (cmHasLiteralPrefix(basename, "moc_")) {
|
||||
if (cmHasLiteralPrefix(incBasename, "moc_")) {
|
||||
// Include: moc_FOO.cxx
|
||||
// basename should be the part of the moc filename used for
|
||||
// finding the correct header, so we need to remove the moc_ part
|
||||
basename = basename.substr(4);
|
||||
const std::string mocSubDir =
|
||||
ExtractSubDir(scannedFileAbsPath, currentMoc);
|
||||
// Remove the moc_ part
|
||||
const std::string incRealBasename = incBasename.substr(4);
|
||||
const std::string headerToMoc = FindMatchingHeader(
|
||||
scannedFileAbsPath, mocSubDir, basename, headerExtensions);
|
||||
|
||||
scannedFileAbsPath, incRealBasename, incSubDir, headerExtensions);
|
||||
if (!headerToMoc.empty()) {
|
||||
mocsIncluded[headerToMoc] = currentMoc;
|
||||
if (relaxed && (basename == scannedFileBasename)) {
|
||||
mocsIncluded[headerToMoc] = incString;
|
||||
if (relaxed && (incRealBasename == scannedFileBasename)) {
|
||||
ownMocUnderscoreIncluded = true;
|
||||
ownMocUnderscoreFile = currentMoc;
|
||||
ownMocUnderscoreFile = incString;
|
||||
ownMocHeaderFile = headerToMoc;
|
||||
}
|
||||
} else {
|
||||
std::ostringstream err;
|
||||
err << "AutoMoc: Error: " << absFilename << "\n"
|
||||
<< "The file includes the moc file \"" << currentMoc
|
||||
<< "\", but could not find header \"" << basename << '{'
|
||||
<< "The file includes the moc file \"" << incString
|
||||
<< "\", but could not find header \"" << incRealBasename << '{'
|
||||
<< JoinExts(headerExtensions) << "}\"\n";
|
||||
this->LogError(err.str());
|
||||
return false;
|
||||
@@ -848,31 +812,31 @@ bool cmQtAutoGenerators::ParseContentForMoc(
|
||||
std::string fileToMoc;
|
||||
if (relaxed) {
|
||||
// Mode: Relaxed
|
||||
if (!requiresMoc || basename != scannedFileBasename) {
|
||||
const std::string mocSubDir =
|
||||
ExtractSubDir(scannedFileAbsPath, currentMoc);
|
||||
if (!requiresMoc || (incBasename != scannedFileBasename)) {
|
||||
const std::string headerToMoc = FindMatchingHeader(
|
||||
scannedFileAbsPath, mocSubDir, basename, headerExtensions);
|
||||
scannedFileAbsPath, incBasename, incSubDir, headerExtensions);
|
||||
if (!headerToMoc.empty()) {
|
||||
// This is for KDE4 compatibility:
|
||||
fileToMoc = headerToMoc;
|
||||
if (!requiresMoc && basename == scannedFileBasename) {
|
||||
if (!requiresMoc && (incBasename == scannedFileBasename)) {
|
||||
std::ostringstream err;
|
||||
err << "AutoMoc: Warning: " << absFilename << "\n"
|
||||
<< "The file includes the moc file \"" << currentMoc
|
||||
<< "The file includes the moc file \"" << incString
|
||||
<< "\", but does not contain a " << macroName
|
||||
<< " macro. Running moc on "
|
||||
<< "\"" << headerToMoc << "\" ! Include \"moc_" << basename
|
||||
<< "\"" << headerToMoc << "\" ! Include \"moc_"
|
||||
<< incBasename
|
||||
<< ".cpp\" for a compatibility with "
|
||||
"strict mode (see CMAKE_AUTOMOC_RELAXED_MODE).\n";
|
||||
this->LogWarning(err.str());
|
||||
} else {
|
||||
std::ostringstream err;
|
||||
err << "AutoMoc: Warning: " << absFilename << "\n"
|
||||
<< "The file includes the moc file \"" << currentMoc
|
||||
<< "\" instead of \"moc_" << basename
|
||||
<< "The file includes the moc file \"" << incString
|
||||
<< "\" instead of \"moc_" << incBasename
|
||||
<< ".cpp\". Running moc on "
|
||||
<< "\"" << headerToMoc << "\" ! Include \"moc_" << basename
|
||||
<< "\"" << headerToMoc << "\" ! Include \"moc_"
|
||||
<< incBasename
|
||||
<< ".cpp\" for compatibility with "
|
||||
"strict mode (see CMAKE_AUTOMOC_RELAXED_MODE).\n";
|
||||
this->LogWarning(err.str());
|
||||
@@ -880,7 +844,7 @@ bool cmQtAutoGenerators::ParseContentForMoc(
|
||||
} else {
|
||||
std::ostringstream err;
|
||||
err << "AutoMoc: Error: " << absFilename << "\n"
|
||||
<< "The file includes the moc file \"" << currentMoc
|
||||
<< "The file includes the moc file \"" << incString
|
||||
<< "\", which seems to be the moc file from a different "
|
||||
"source file. CMake also could not find a matching "
|
||||
"header.\n";
|
||||
@@ -894,7 +858,7 @@ bool cmQtAutoGenerators::ParseContentForMoc(
|
||||
}
|
||||
} else {
|
||||
// Mode: Strict
|
||||
if (basename == scannedFileBasename) {
|
||||
if (incBasename == scannedFileBasename) {
|
||||
// Include self
|
||||
fileToMoc = absFilename;
|
||||
ownDotMocIncluded = true;
|
||||
@@ -902,7 +866,7 @@ bool cmQtAutoGenerators::ParseContentForMoc(
|
||||
// Don't allow FOO.moc include other than self in strict mode
|
||||
std::ostringstream err;
|
||||
err << "AutoMoc: Error: " << absFilename << "\n"
|
||||
<< "The file includes the moc file \"" << currentMoc
|
||||
<< "The file includes the moc file \"" << incString
|
||||
<< "\", which seems to be the moc file from a different "
|
||||
"source file. This is not supported. Include \""
|
||||
<< scannedFileBasename
|
||||
@@ -912,7 +876,7 @@ bool cmQtAutoGenerators::ParseContentForMoc(
|
||||
}
|
||||
}
|
||||
if (!fileToMoc.empty()) {
|
||||
mocsIncluded[fileToMoc] = currentMoc;
|
||||
mocsIncluded[fileToMoc] = incString;
|
||||
}
|
||||
}
|
||||
// Forward content pointer
|
||||
@@ -920,11 +884,11 @@ bool cmQtAutoGenerators::ParseContentForMoc(
|
||||
}
|
||||
}
|
||||
|
||||
// In this case, check whether the scanned file itself contains a Q_OBJECT.
|
||||
// If this is the case, the moc_foo.cpp should probably be generated from
|
||||
// foo.cpp instead of foo.h, because otherwise it won't build.
|
||||
// But warn, since this is not how it is supposed to be used.
|
||||
if (requiresMoc && !ownDotMocIncluded) {
|
||||
// In this case, check whether the scanned file itself contains a Q_OBJECT.
|
||||
// If this is the case, the moc_foo.cpp should probably be generated from
|
||||
// foo.cpp instead of foo.h, because otherwise it won't build.
|
||||
// But warn, since this is not how it is supposed to be used.
|
||||
if (relaxed && ownMocUnderscoreIncluded) {
|
||||
// This is for KDE4 compatibility:
|
||||
std::ostringstream err;
|
||||
@@ -1619,6 +1583,47 @@ std::string cmQtAutoGenerators::ChecksumedPath(const std::string& sourceFile,
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Tries to find the header file to the given file base path by
|
||||
* appending different header extensions
|
||||
* @return True on success
|
||||
*/
|
||||
bool cmQtAutoGenerators::FindHeader(
|
||||
std::string& header, const std::string& testBasePath,
|
||||
const std::vector<std::string>& headerExtensions) const
|
||||
{
|
||||
for (std::vector<std::string>::const_iterator ext = headerExtensions.begin();
|
||||
ext != headerExtensions.end(); ++ext) {
|
||||
std::string testFilePath(testBasePath);
|
||||
testFilePath += '.';
|
||||
testFilePath += (*ext);
|
||||
if (cmsys::SystemTools::FileExists(testFilePath.c_str())) {
|
||||
header = testFilePath;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string cmQtAutoGenerators::FindMatchingHeader(
|
||||
const std::string& basePath, const std::string& baseName,
|
||||
const std::string& subDir,
|
||||
const std::vector<std::string>& headerExtensions) const
|
||||
{
|
||||
std::string header;
|
||||
do {
|
||||
if (!subDir.empty()) {
|
||||
if (FindHeader(header, basePath + subDir + baseName, headerExtensions)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (FindHeader(header, basePath + baseName, headerExtensions)) {
|
||||
break;
|
||||
}
|
||||
} while (false);
|
||||
return header;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Generates the parent directory of the given file on demand
|
||||
* @return True on success
|
||||
|
||||
@@ -119,6 +119,13 @@ private:
|
||||
const char* baseSuffix) const;
|
||||
bool MakeParentDirectory(const std::string& filename);
|
||||
|
||||
bool FindHeader(std::string& header, const std::string& testBasePath,
|
||||
const std::vector<std::string>& headerExtensions) const;
|
||||
std::string FindMatchingHeader(
|
||||
const std::string& basePath, const std::string& baseName,
|
||||
const std::string& subDir,
|
||||
const std::vector<std::string>& headerExtensions) const;
|
||||
|
||||
// - Target names
|
||||
std::string OriginTargetName;
|
||||
std::string AutogenTargetName;
|
||||
|
||||
Reference in New Issue
Block a user