automoc: add extra check whether the header contains Q_PRIVATE_SLOT

This is again for KDE4 compatiblity. If foo.moc is included, in general
moc should run on foo.cpp. Usually this can't cause problems.
It can only cause problems if moc must run on the header, and the resulting
file must be included in the cpp file, which is the case with the
Q_PRIVATE_SLOT macro.
This makes the test added by Stephen pass.

Alex
This commit is contained in:
Alex Neundorf 2011-11-29 20:55:36 +01:00
parent 47457159c7
commit 3b93e266c0
1 changed files with 50 additions and 1 deletions

View File

@ -37,6 +37,20 @@ static bool containsQ_OBJECT(const std::string& text)
}
static bool containsQ_PRIVATE_SLOT(const std::string& text)
{
// this simple check is much much faster than the regexp
if (strstr(text.c_str(), "Q_PRIVATE_SLOT") == NULL)
{
return false;
}
cmsys::RegularExpression qPrivateSlotRegExp(
"[\n][ \t]*Q_PRIVATE_SLOT[^a-zA-Z0-9_]");
return qPrivateSlotRegExp.find(text);
}
static std::string findMatchingHeader(const std::string& absPath,
const std::string& mocSubDir,
const std::string& basename,
@ -583,6 +597,7 @@ void cmQtAutomoc::ParseCppFile(const std::string& absFilename,
bool dotMocIncluded = false;
bool mocUnderscoreIncluded = false;
std::string ownMocUnderscoreFile;
std::string ownDotMocFile;
std::string ownMocHeaderFile;
std::string::size_type matchOffset = 0;
@ -683,8 +698,12 @@ void cmQtAutomoc::ParseCppFile(const std::string& absFilename,
::exit(EXIT_FAILURE);
}
}
else
{
dotMocIncluded = true;
ownDotMocFile = currentMoc;
}
includedMocs[absFilename] = currentMoc;
dotMocIncluded = true;
}
matchOffset += mocIncludeRegExp.end();
} while(mocIncludeRegExp.find(contentsString.c_str() + matchOffset));
@ -721,6 +740,36 @@ void cmQtAutomoc::ParseCppFile(const std::string& absFilename,
}
}
// if only the .moc file is included and we are in compatibility mode,
// check whether maybe the header must actually be mocced, e.g. because it
// might use the Q_PRIVATE_SLOT macro:
if ((dotMocIncluded == true) && (mocUnderscoreIncluded == false)
&& (this->QtMajorVersion == "4"))
{
std::string ownHeader=findMatchingHeader(absPath, "", scannedFileBasename,
headerExtensions);
if (ownHeader.size() > 0)
{
const std::string ownHeaderContents = this->ReadAll(ownHeader);
if (containsQ_PRIVATE_SLOT(ownHeaderContents))
{
// this is for KDE4 compatibility:
std::cerr << "AUTOMOC: warning: " << absFilename << ": The file "
<< "includes \"" << ownDotMocFile << "\", but the "
<< "header \"" << ownHeader << "\" contains a "
<< "Q_PRIVATE_SLOT macro. "
<< "Running moc on " << "\"" << absFilename << "\" ! "
<< "Better include \"moc_" << scannedFileBasename << ".cpp\""
<< " for a robust build."
<< std::endl;
includedMocs[ownHeader] = ownDotMocFile;
includedMocs.erase(absFilename);
}
}
}
// search for header files and private header files we may need to moc:
const std::string basename =
cmsys::SystemTools::GetFilenameWithoutLastExtension(absFilename);