|
|
@@ -537,17 +537,12 @@ bool cmQtAutoGenerators::RunAutogen(cmMakefile* makefile)
|
|
|
err << "AUTOGEN: Checking " << absFilename << std::endl;
|
|
|
this->LogInfo(err.str());
|
|
|
}
|
|
|
- if (this->MocRelaxedMode) {
|
|
|
- if (!this->ParseCppFile(absFilename, headerExtensions, includedMocs,
|
|
|
- uiFiles)) {
|
|
|
- return false;
|
|
|
- }
|
|
|
- } else {
|
|
|
- if (!this->StrictParseCppFile(absFilename, headerExtensions,
|
|
|
- includedMocs, uiFiles)) {
|
|
|
- return false;
|
|
|
- }
|
|
|
+ // Parse source file for MOC/UIC
|
|
|
+ if (!this->ParseSourceFile(absFilename, headerExtensions, includedMocs,
|
|
|
+ uiFiles, this->MocRelaxedMode)) {
|
|
|
+ return false;
|
|
|
}
|
|
|
+ // Find additional headers
|
|
|
this->SearchHeadersForCppFile(absFilename, headerExtensions, headerFiles);
|
|
|
}
|
|
|
|
|
|
@@ -596,311 +591,6 @@ bool cmQtAutoGenerators::RunAutogen(cmMakefile* makefile)
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
-/**
|
|
|
- * @return True on success
|
|
|
- */
|
|
|
-bool cmQtAutoGenerators::ParseCppFile(
|
|
|
- const std::string& absFilename,
|
|
|
- const std::vector<std::string>& headerExtensions,
|
|
|
- std::map<std::string, std::string>& includedMocs,
|
|
|
- std::map<std::string, std::vector<std::string> >& includedUis)
|
|
|
-{
|
|
|
- cmsys::RegularExpression mocIncludeRegExp(
|
|
|
- "[\n][ \t]*#[ \t]*include[ \t]+"
|
|
|
- "[\"<](([^ \">]+/)?moc_[^ \">/]+\\.cpp|[^ \">]+\\.moc)[\">]");
|
|
|
-
|
|
|
- const std::string contentsString = ReadAll(absFilename);
|
|
|
- if (contentsString.empty()) {
|
|
|
- std::ostringstream err;
|
|
|
- err << "AUTOGEN: warning: " << absFilename << ": file is empty\n"
|
|
|
- << std::endl;
|
|
|
- this->LogWarning(err.str());
|
|
|
- return true;
|
|
|
- }
|
|
|
- this->ParseForUic(absFilename, contentsString, includedUis);
|
|
|
- if (this->MocExecutable.empty()) {
|
|
|
- return true;
|
|
|
- }
|
|
|
-
|
|
|
- const std::string absPath = cmsys::SystemTools::GetFilenamePath(
|
|
|
- cmsys::SystemTools::GetRealPath(absFilename)) +
|
|
|
- '/';
|
|
|
- const std::string scannedFileBasename =
|
|
|
- cmsys::SystemTools::GetFilenameWithoutLastExtension(absFilename);
|
|
|
- std::string macroName;
|
|
|
- const bool requiresMoc = requiresMocing(contentsString, macroName);
|
|
|
- bool dotMocIncluded = false;
|
|
|
- bool mocUnderscoreIncluded = false;
|
|
|
- std::string ownMocUnderscoreFile;
|
|
|
- std::string ownDotMocFile;
|
|
|
- std::string ownMocHeaderFile;
|
|
|
-
|
|
|
- std::string::size_type matchOffset = 0;
|
|
|
- // first a simple string check for "moc" is *much* faster than the regexp,
|
|
|
- // and if the string search already fails, we don't have to try the
|
|
|
- // expensive regexp
|
|
|
- if ((strstr(contentsString.c_str(), "moc") != CM_NULLPTR) &&
|
|
|
- (mocIncludeRegExp.find(contentsString))) {
|
|
|
- // for every moc include in the file
|
|
|
- do {
|
|
|
- const std::string currentMoc = mocIncludeRegExp.match(1);
|
|
|
-
|
|
|
- std::string basename =
|
|
|
- cmsys::SystemTools::GetFilenameWithoutLastExtension(currentMoc);
|
|
|
- const bool mocUnderscoreStyle = cmHasLiteralPrefix(basename, "moc_");
|
|
|
-
|
|
|
- // 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 (mocUnderscoreStyle) {
|
|
|
- // 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);
|
|
|
- std::string mocSubDir = extractSubDir(absPath, currentMoc);
|
|
|
- std::string headerToMoc =
|
|
|
- findMatchingHeader(absPath, mocSubDir, basename, headerExtensions);
|
|
|
-
|
|
|
- if (!headerToMoc.empty()) {
|
|
|
- includedMocs[headerToMoc] = currentMoc;
|
|
|
- if (basename == scannedFileBasename) {
|
|
|
- mocUnderscoreIncluded = true;
|
|
|
- ownMocUnderscoreFile = currentMoc;
|
|
|
- ownMocHeaderFile = headerToMoc;
|
|
|
- }
|
|
|
- } else {
|
|
|
- std::ostringstream err;
|
|
|
- err << "AUTOGEN: error: " << absFilename << ": The file "
|
|
|
- << "includes the moc file \"" << currentMoc << "\", "
|
|
|
- << "but could not find header \"" << basename << '{'
|
|
|
- << this->JoinExts(headerExtensions) << "}\" ";
|
|
|
- if (mocSubDir.empty()) {
|
|
|
- err << "in " << absPath << "\n" << std::endl;
|
|
|
- } else {
|
|
|
- err << "neither in " << absPath << " nor in " << mocSubDir << "\n"
|
|
|
- << std::endl;
|
|
|
- }
|
|
|
- this->LogError(err.str());
|
|
|
- return false;
|
|
|
- }
|
|
|
- } else {
|
|
|
- std::string fileToMoc = absFilename;
|
|
|
- if (!requiresMoc || basename != scannedFileBasename) {
|
|
|
- std::string mocSubDir = extractSubDir(absPath, currentMoc);
|
|
|
- std::string headerToMoc =
|
|
|
- findMatchingHeader(absPath, mocSubDir, basename, headerExtensions);
|
|
|
- if (!headerToMoc.empty()) {
|
|
|
- // this is for KDE4 compatibility:
|
|
|
- fileToMoc = headerToMoc;
|
|
|
- if (!requiresMoc && basename == scannedFileBasename) {
|
|
|
- std::ostringstream err;
|
|
|
- err << "AUTOGEN: warning: " << absFilename
|
|
|
- << ": The file "
|
|
|
- "includes the moc file \""
|
|
|
- << currentMoc << "\", but does not contain a " << macroName
|
|
|
- << " macro. Running moc on "
|
|
|
- << "\"" << headerToMoc << "\" ! Include \"moc_" << basename
|
|
|
- << ".cpp\" for a compatibility with "
|
|
|
- "strict mode (see CMAKE_AUTOMOC_RELAXED_MODE).\n"
|
|
|
- << std::endl;
|
|
|
- this->LogWarning(err.str());
|
|
|
- } else {
|
|
|
- std::ostringstream err;
|
|
|
- err << "AUTOGEN: warning: " << absFilename
|
|
|
- << ": The file "
|
|
|
- "includes the moc file \""
|
|
|
- << currentMoc << "\" instead of \"moc_" << basename
|
|
|
- << ".cpp\". "
|
|
|
- "Running moc on "
|
|
|
- << "\"" << headerToMoc << "\" ! Include \"moc_" << basename
|
|
|
- << ".cpp\" for compatibility with "
|
|
|
- "strict mode (see CMAKE_AUTOMOC_RELAXED_MODE).\n"
|
|
|
- << std::endl;
|
|
|
- this->LogWarning(err.str());
|
|
|
- }
|
|
|
- } else {
|
|
|
- std::ostringstream err;
|
|
|
- err << "AUTOGEN: error: " << absFilename
|
|
|
- << ": The file "
|
|
|
- "includes the moc file \""
|
|
|
- << currentMoc
|
|
|
- << "\", which seems to be the moc file from a different "
|
|
|
- "source file. CMake also could not find a matching "
|
|
|
- "header.\n"
|
|
|
- << std::endl;
|
|
|
- this->LogError(err.str());
|
|
|
- return false;
|
|
|
- }
|
|
|
- } else {
|
|
|
- dotMocIncluded = true;
|
|
|
- ownDotMocFile = currentMoc;
|
|
|
- }
|
|
|
- includedMocs[fileToMoc] = currentMoc;
|
|
|
- }
|
|
|
- matchOffset += mocIncludeRegExp.end();
|
|
|
- } while (mocIncludeRegExp.find(contentsString.c_str() + matchOffset));
|
|
|
- }
|
|
|
-
|
|
|
- // 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 (!dotMocIncluded && requiresMoc) {
|
|
|
- if (mocUnderscoreIncluded) {
|
|
|
- // this is for KDE4 compatibility:
|
|
|
- std::ostringstream err;
|
|
|
- err << "AUTOGEN: warning: " << absFilename << ": The file "
|
|
|
- << "contains a " << macroName << " macro, but does not "
|
|
|
- "include "
|
|
|
- << "\"" << scannedFileBasename << ".moc\", but instead "
|
|
|
- "includes "
|
|
|
- << "\"" << ownMocUnderscoreFile << "\". Running moc on "
|
|
|
- << "\"" << absFilename << "\" ! Better include \""
|
|
|
- << scannedFileBasename
|
|
|
- << ".moc\" for compatibility with "
|
|
|
- "strict mode (see CMAKE_AUTOMOC_RELAXED_MODE).\n"
|
|
|
- << std::endl;
|
|
|
- this->LogWarning(err.str());
|
|
|
-
|
|
|
- includedMocs[absFilename] = ownMocUnderscoreFile;
|
|
|
- includedMocs.erase(ownMocHeaderFile);
|
|
|
- } else {
|
|
|
- // otherwise always error out since it will not compile:
|
|
|
- std::ostringstream err;
|
|
|
- err << "AUTOGEN: error: " << absFilename << ": The file "
|
|
|
- << "contains a " << macroName << " macro, but does not "
|
|
|
- "include "
|
|
|
- << "\"" << scannedFileBasename << ".moc\" !\n"
|
|
|
- << std::endl;
|
|
|
- this->LogError(err.str());
|
|
|
- return false;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return true;
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * @return True on success
|
|
|
- */
|
|
|
-bool cmQtAutoGenerators::StrictParseCppFile(
|
|
|
- const std::string& absFilename,
|
|
|
- const std::vector<std::string>& headerExtensions,
|
|
|
- std::map<std::string, std::string>& includedMocs,
|
|
|
- std::map<std::string, std::vector<std::string> >& includedUis)
|
|
|
-{
|
|
|
- cmsys::RegularExpression mocIncludeRegExp(
|
|
|
- "[\n][ \t]*#[ \t]*include[ \t]+"
|
|
|
- "[\"<](([^ \">]+/)?moc_[^ \">/]+\\.cpp|[^ \">]+\\.moc)[\">]");
|
|
|
-
|
|
|
- const std::string contentsString = ReadAll(absFilename);
|
|
|
- if (contentsString.empty()) {
|
|
|
- std::ostringstream err;
|
|
|
- err << "AUTOGEN: warning: " << absFilename << ": file is empty\n"
|
|
|
- << std::endl;
|
|
|
- this->LogWarning(err.str());
|
|
|
- return true;
|
|
|
- }
|
|
|
- this->ParseForUic(absFilename, contentsString, includedUis);
|
|
|
- if (this->MocExecutable.empty()) {
|
|
|
- return true;
|
|
|
- }
|
|
|
-
|
|
|
- const std::string absPath = cmsys::SystemTools::GetFilenamePath(
|
|
|
- cmsys::SystemTools::GetRealPath(absFilename)) +
|
|
|
- '/';
|
|
|
- const std::string scannedFileBasename =
|
|
|
- cmsys::SystemTools::GetFilenameWithoutLastExtension(absFilename);
|
|
|
-
|
|
|
- bool dotMocIncluded = false;
|
|
|
-
|
|
|
- std::string::size_type matchOffset = 0;
|
|
|
- // first a simple string check for "moc" is *much* faster than the regexp,
|
|
|
- // and if the string search already fails, we don't have to try the
|
|
|
- // expensive regexp
|
|
|
- if ((strstr(contentsString.c_str(), "moc") != CM_NULLPTR) &&
|
|
|
- (mocIncludeRegExp.find(contentsString))) {
|
|
|
- // for every moc include in the file
|
|
|
- do {
|
|
|
- const std::string currentMoc = mocIncludeRegExp.match(1);
|
|
|
-
|
|
|
- std::string basename =
|
|
|
- cmsys::SystemTools::GetFilenameWithoutLastExtension(currentMoc);
|
|
|
- const bool mocUnderscoreStyle = cmHasLiteralPrefix(basename, "moc_");
|
|
|
-
|
|
|
- // 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 (mocUnderscoreStyle) {
|
|
|
- // 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);
|
|
|
- std::string mocSubDir = extractSubDir(absPath, currentMoc);
|
|
|
- std::string headerToMoc =
|
|
|
- findMatchingHeader(absPath, mocSubDir, basename, headerExtensions);
|
|
|
-
|
|
|
- if (!headerToMoc.empty()) {
|
|
|
- includedMocs[headerToMoc] = currentMoc;
|
|
|
- } else {
|
|
|
- std::ostringstream err;
|
|
|
- err << "AUTOGEN: error: " << absFilename << " The file "
|
|
|
- << "includes the moc file \"" << currentMoc << "\", "
|
|
|
- << "but could not find header \"" << basename << '{'
|
|
|
- << this->JoinExts(headerExtensions) << "}\" ";
|
|
|
- if (mocSubDir.empty()) {
|
|
|
- err << "in " << absPath << "\n" << std::endl;
|
|
|
- } else {
|
|
|
- err << "neither in " << absPath << " nor in " << mocSubDir << "\n"
|
|
|
- << std::endl;
|
|
|
- }
|
|
|
- this->LogError(err.str());
|
|
|
- return false;
|
|
|
- }
|
|
|
- } else {
|
|
|
- if (basename != scannedFileBasename) {
|
|
|
- std::ostringstream err;
|
|
|
- err << "AUTOGEN: error: " << absFilename
|
|
|
- << ": The file "
|
|
|
- "includes the moc file \""
|
|
|
- << currentMoc
|
|
|
- << "\", which seems to be the moc file from a different "
|
|
|
- "source file. This is not supported. "
|
|
|
- "Include \""
|
|
|
- << scannedFileBasename << ".moc\" to run "
|
|
|
- "moc on this source file.\n"
|
|
|
- << std::endl;
|
|
|
- this->LogError(err.str());
|
|
|
- return false;
|
|
|
- }
|
|
|
- dotMocIncluded = true;
|
|
|
- includedMocs[absFilename] = currentMoc;
|
|
|
- }
|
|
|
- matchOffset += mocIncludeRegExp.end();
|
|
|
- } while (mocIncludeRegExp.find(contentsString.c_str() + matchOffset));
|
|
|
- }
|
|
|
-
|
|
|
- // 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.
|
|
|
- std::string macroName;
|
|
|
- if (!dotMocIncluded && requiresMocing(contentsString, macroName)) {
|
|
|
- // otherwise always error out since it will not compile:
|
|
|
- std::ostringstream err;
|
|
|
- err << "AUTOGEN: error: " << absFilename << ": The file "
|
|
|
- << "contains a " << macroName << " macro, but does not include "
|
|
|
- << "\"" << scannedFileBasename << ".moc\" !\n"
|
|
|
- << std::endl;
|
|
|
- this->LogError(err.str());
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
- return true;
|
|
|
-}
|
|
|
-
|
|
|
/**
|
|
|
* @return True on success
|
|
|
*/
|