From 3b93e266c0e6f0a58d813fc8ec7bc5810ace4827 Mon Sep 17 00:00:00 2001 From: Alex Neundorf Date: Tue, 29 Nov 2011 20:55:36 +0100 Subject: [PATCH] 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 --- Source/cmQtAutomoc.cxx | 51 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) diff --git a/Source/cmQtAutomoc.cxx b/Source/cmQtAutomoc.cxx index 9cb8f6385..095e8d05d 100644 --- a/Source/cmQtAutomoc.cxx +++ b/Source/cmQtAutomoc.cxx @@ -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);