Merge topic 'AutomocIncludedDotMocFileHandling'

2d11951 Merge branch 'master' into AutomocIncludedDotMocFileHandling
1eca18f automoc: add documentation for CMAKE_AUTOMOC_STRICT_MODE
bc278ce automoc: fix line length
62e223e automoc: add variable CMAKE_AUTOMOC_STRICT_MODE, to enable strict parsing
40c5167 automoc: accept even more .moc files in non-strict mode
c207f5d automoc: also accept other files when .moc is included in non-strict mode
9c0df72 automoc: add a StrictParseCppFile(), which is only qmake-compatible
174bf35 automoc: move the code for finding headers into separate function
8507eae automoc: fix handling of included _p.moc files
7ada172 automoc: some more linebreaks for the warnings for better readability
3b93e26 automoc: add extra check whether the header contains Q_PRIVATE_SLOT
4745715 Add a test case for the use of Q_PRIVATE_SLOT.
bde4edb automoc: add special handling for including basename_p.moc, with test
74ab0f6 automoc: move some code from the big parsing loop into separate functions
bc7560e automoc: add test for including a moc_abc_p.cpp file
30fd8e6 automoc: add test for including the moc file from another header
...
This commit is contained in:
David Cole 2011-12-07 16:47:35 -05:00 committed by CMake Topic Stage
commit d050d6b58b
21 changed files with 795 additions and 78 deletions

View File

@ -13,3 +13,4 @@ set(AM_CMAKE_CURRENT_BINARY_DIR "@CMAKE_CURRENT_BINARY_DIR@/")
set(AM_QT_VERSION_MAJOR "@QT_VERSION_MAJOR@" )
set(AM_Qt5Core_VERSION_MAJOR "@Qt5Core_VERSION_MAJOR@" )
set(AM_TARGET_NAME "@_moc_target_name@")
set(AM_STRICT_MODE "@_moc_strict_mode@")

View File

@ -507,6 +507,20 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
false,
"Variables That Change Behavior");
cm->DefineProperty
("CMAKE_AUTOMOC_STRICT_MODE", cmProperty::VARIABLE,
"Switch between strict and relaxed automoc mode.",
"When TRUE, automoc behaves exactly as described in the documentation "
"of the AUTOMOC target property. "
"When set to FALSE, it accepts more input and tries to find the correct "
"input file for moc even if it differs from the documented behaviour. "
"In this mode it e.g. also checks whether a header file is intended to "
"be processed by moc when a \"foo.moc\" file has been included.\n"
"When using Qt4, CMAKE_AUTOMOC_STRICT_MODE is initialized to FALSE. "
"It also has to be set to FALSE for KDE4 compatibility.",
false,
"Variables That Change Behavior");
cm->DefineProperty
("CMAKE_FIND_LIBRARY_PREFIXES", cmProperty::VARIABLE,
"Prefixes to prepend when looking for libraries.",

View File

@ -17,11 +17,70 @@
#include "cmSourceFile.h"
#include "cmSystemTools.h"
# include <cmsys/Terminal.h>
#include <cmsys/Terminal.h>
#include <string.h>
#include "cmQtAutomoc.h"
static bool containsQ_OBJECT(const std::string& text)
{
// this simple check is much much faster than the regexp
if (strstr(text.c_str(), "Q_OBJECT") == NULL)
{
return false;
}
cmsys::RegularExpression qObjectRegExp("[\n][ \t]*Q_OBJECT[^a-zA-Z0-9_]");
return qObjectRegExp.find(text);
}
static std::string findMatchingHeader(const std::string& absPath,
const std::string& mocSubDir,
const std::string& basename,
const std::list<std::string>& headerExtensions)
{
std::string header;
for(std::list<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;
}
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;
}
cmQtAutomoc::cmQtAutomoc()
:Verbose(cmsys::SystemTools::GetEnv("VERBOSE") != 0)
,ColorOutput(true)
@ -60,6 +119,12 @@ void cmQtAutomoc::SetupAutomocTarget(cmTarget* target)
return;
}
bool strictMode = (qtMajorVersion == "5");
if (makefile->IsDefinitionSet("CMAKE_AUTOMOC_STRICT_MODE"))
{
strictMode = makefile->IsOn("CMAKE_AUTOMOC_STRICT_MODE");
}
// create a custom target for running automoc at buildtime:
std::string automocTargetName = targetName;
automocTargetName += "_automoc";
@ -148,6 +213,7 @@ void cmQtAutomoc::SetupAutomocTarget(cmTarget* target)
makefile->AddDefinition("_moc_options", _moc_options.c_str());
makefile->AddDefinition("_moc_files", _moc_files.c_str());
makefile->AddDefinition("_moc_headers", _moc_headers.c_str());
makefile->AddDefinition("_moc_strict_mode", strictMode ? "TRUE" : "FALSE");
const char* cmakeRoot = makefile->GetSafeDefinition("CMAKE_ROOT");
std::string inputFile = cmakeRoot;
@ -247,6 +313,8 @@ bool cmQtAutomoc::ReadAutomocInfoFile(cmMakefile* makefile,
this->ProjectSourceDir = makefile->GetSafeDefinition("AM_CMAKE_SOURCE_DIR");
this->TargetName = makefile->GetSafeDefinition("AM_TARGET_NAME");
this->StrictMode = makefile->IsOn("AM_STRICT_MODE");
return true;
}
@ -415,6 +483,23 @@ bool cmQtAutomoc::RunAutomoc()
std::vector<std::string> sourceFiles;
cmSystemTools::ExpandListArgument(this->Sources, sourceFiles);
std::list<std::string> headerExtensions;
headerExtensions.push_back(".h");
headerExtensions.push_back(".hpp");
headerExtensions.push_back(".hxx");
#if defined(_WIN32)
// not case sensitive, don't add ".H"
#elif defined(__APPLE__)
// detect case-sensitive filesystem
long caseSensitive = pathconf(this->Srcdir.c_str(), _PC_CASE_SENSITIVE);
if (caseSensitive == 1)
{
headerExtensions.push_back(".H");
}
#else
headerExtensions.push_back(".H");
#endif
for (std::vector<std::string>::const_iterator it = sourceFiles.begin();
it != sourceFiles.end();
++it)
@ -424,7 +509,15 @@ bool cmQtAutomoc::RunAutomoc()
{
std::cout << "AUTOMOC: Checking " << absFilename << std::endl;
}
this->ParseCppFile(absFilename, includedMocs, headerFiles);
if (this->StrictMode == false)
{
this->ParseCppFile(absFilename, headerExtensions, includedMocs);
}
else
{
this->StrictParseCppFile(absFilename, headerExtensions, includedMocs);
}
this->SearchHeadersForCppFile(absFilename, headerExtensions, headerFiles);
}
std::vector<std::string> headerFilesVec;
@ -505,40 +598,37 @@ bool cmQtAutomoc::RunAutomoc()
void cmQtAutomoc::ParseCppFile(const std::string& absFilename,
std::map<std::string, std::string>& includedMocs,
std::set<std::string>& absHeaders)
const std::list<std::string>& headerExtensions,
std::map<std::string, std::string>& includedMocs)
{
cmsys::RegularExpression mocIncludeRegExp(
"[\n][ \t]*#[ \t]*include[ \t]+"
"[\"<](([^ \">]+/)?moc_[^ \">/]+\\.cpp|[^ \">]+\\.moc)[\">]");
std::list<std::string> headerExtensions;
headerExtensions.push_back(".h");
headerExtensions.push_back(".hpp");
headerExtensions.push_back(".hxx");
#if defined(_WIN32)
// not case sensitive, don't add ".H"
#elif defined(__APPLE__)
// detect case-sensitive filesystem
long caseSensitive = pathconf(this->Srcdir.c_str(), _PC_CASE_SENSITIVE);
if (caseSensitive == 1)
{
headerExtensions.push_back(".H");
}
#else
headerExtensions.push_back(".H");
#endif
const std::string contentsString = this->ReadAll(absFilename);
if (contentsString.empty())
{
std::cerr << "AUTOMOC: empty source file: " << absFilename << std::endl;
std::cerr << "AUTOMOC: warning: " << absFilename << ": file is empty\n"
<< std::endl;
return;
}
const std::string absPath = cmsys::SystemTools::GetFilenamePath(
cmsys::SystemTools::GetRealPath(absFilename.c_str())) + '/';
const std::string scannedFileBasename = cmsys::SystemTools::
GetFilenameWithoutLastExtension(absFilename);
const bool cppContainsQ_OBJECT = containsQ_OBJECT(contentsString);
bool dotMocIncluded = false;
bool mocUnderscoreIncluded = false;
std::string ownMocUnderscoreFile;
std::string ownDotMocFile;
std::string ownMocHeaderFile;
std::string::size_type matchOffset = 0;
if (mocIncludeRegExp.find(contentsString.c_str()))
// first a simply 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") != NULL)
&& (mocIncludeRegExp.find(contentsString)))
{
// for every moc include in the file
do
@ -561,78 +651,248 @@ void cmQtAutomoc::ParseCppFile(const std::string& absFilename,
// 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);
bool headerFound = false;
for(std::list<std::string>::const_iterator ext =
headerExtensions.begin();
ext != headerExtensions.end();
++ext)
if (!headerToMoc.empty())
{
const std::string &sourceFilePath = absPath + basename + (*ext);
if (cmsys::SystemTools::FileExists(sourceFilePath.c_str()))
includedMocs[headerToMoc] = currentMoc;
if (basename == scannedFileBasename)
{
headerFound = true;
includedMocs[sourceFilePath] = currentMoc;
break;
mocUnderscoreIncluded = true;
ownMocUnderscoreFile = currentMoc;
ownMocHeaderFile = headerToMoc;
}
}
if (!headerFound)
else
{
// the moc file is in a subdir => look for the header in the
// same subdir
if (currentMoc.find_first_of('/') != std::string::npos)
std::cerr << "AUTOMOC: error: " << absFilename << " The file "
<< "includes the moc file \"" << currentMoc << "\", "
<< "but could not find header \"" << basename
<< '{' << this->Join(headerExtensions, ',') << "}\" ";
if (mocSubDir.empty())
{
const std::string &filepath = absPath
+ cmsys::SystemTools::GetFilenamePath(currentMoc)
+ '/' + basename;
std::cerr << "in " << absPath << "\n" << std::endl;
}
else
{
std::cerr << "neither in " << absPath
<< " nor in " << mocSubDir << "\n" << std::endl;
}
for(std::list<std::string>::const_iterator ext =
headerExtensions.begin();
ext != headerExtensions.end();
++ext)
{
const std::string &sourceFilePath = filepath + (*ext);
if (cmsys::SystemTools::FileExists(sourceFilePath.c_str()))
{
headerFound = true;
includedMocs[sourceFilePath] = currentMoc;
break;
}
}
if (!headerFound)
{
std::cerr << "AUTOMOC: The file \"" << absFilename
<< "\" includes the moc file \"" << currentMoc
<< "\", but neither \"" << absPath << basename
<< '{' << this->Join(headerExtensions, ',')
<< "}\" nor \"" << filepath << '{'
<< this->Join(headerExtensions, ',') << '}'
<< "\" exist." << std::endl;
::exit(EXIT_FAILURE);
}
}
else
{
std::cerr << "AUTOMOC: The file \"" << absFilename
<< "\" includes the moc file \"" << currentMoc
<< "\", but \"" << absPath << basename << '{'
<< this->Join(headerExtensions, ',') << '}'
<< "\" does not exist." << std::endl;
::exit(EXIT_FAILURE);
std::string fileToMoc = absFilename;
if ((basename != scannedFileBasename) || (cppContainsQ_OBJECT==false))
{
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 ((cppContainsQ_OBJECT==false) &&(basename==scannedFileBasename))
{
std::cerr << "AUTOMOC: warning: " << absFilename << ": The file "
"includes the moc file \"" << currentMoc <<
"\", but does not contain a Q_OBJECT macro. "
"Running moc on "
<< "\"" << headerToMoc << "\" ! Better include \"moc_"
<< basename << ".cpp\" for a robust build.\n"
<< std::endl;
}
else
{
std::cerr << "AUTOMOC: warning: " << absFilename << ": The file "
"includes the moc file \"" << currentMoc <<
"\" instead of \"moc_" << basename << ".cpp\". "
"Running moc on "
<< "\"" << headerToMoc << "\" ! Better include \"moc_"
<< basename << ".cpp\" for a robust build.\n"
<< std::endl;
}
}
else
{
std::cerr <<"AUTOMOC: 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;
::exit(EXIT_FAILURE);
}
}
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 == false) && (cppContainsQ_OBJECT == true))
{
if (mocUnderscoreIncluded == true)
{
// this is for KDE4 compatibility:
std::cerr << "AUTOMOC: warning: " << absFilename << ": The file "
<< "contains a Q_OBJECT macro, but does not include "
<< "\"" << scannedFileBasename << ".moc\", but instead "
"includes "
<< "\"" << ownMocUnderscoreFile << "\". Running moc on "
<< "\"" << absFilename << "\" ! Better include \""
<< scannedFileBasename << ".moc\" for a robust build.\n"
<< std::endl;
includedMocs[absFilename] = ownMocUnderscoreFile;
includedMocs.erase(ownMocHeaderFile);
}
else
{
// otherwise always error out since it will not compile:
std::cerr << "AUTOMOC: error: " << absFilename << ": The file "
<< "contains a Q_OBJECT macro, but does not include "
<< "\"" << scannedFileBasename << ".moc\" !\n"
<< std::endl;
::exit(EXIT_FAILURE);
}
}
}
void cmQtAutomoc::StrictParseCppFile(const std::string& absFilename,
const std::list<std::string>& headerExtensions,
std::map<std::string, std::string>& includedMocs)
{
cmsys::RegularExpression mocIncludeRegExp(
"[\n][ \t]*#[ \t]*include[ \t]+"
"[\"<](([^ \">]+/)?moc_[^ \">/]+\\.cpp|[^ \">]+\\.moc)[\">]");
const std::string contentsString = this->ReadAll(absFilename);
if (contentsString.empty())
{
std::cerr << "AUTOMOC: warning: " << absFilename << ": file is empty\n"
<< std::endl;
return;
}
const std::string absPath = cmsys::SystemTools::GetFilenamePath(
cmsys::SystemTools::GetRealPath(absFilename.c_str())) + '/';
const std::string scannedFileBasename = cmsys::SystemTools::
GetFilenameWithoutLastExtension(absFilename);
bool dotMocIncluded = false;
std::string::size_type matchOffset = 0;
// first a simply 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") != NULL)
&& (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 = this->StartsWith(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::cerr << "AUTOMOC: error: " << absFilename << " The file "
<< "includes the moc file \"" << currentMoc << "\", "
<< "but could not find header \"" << basename
<< '{' << this->Join(headerExtensions, ',') << "}\" ";
if (mocSubDir.empty())
{
std::cerr << "in " << absPath << "\n" << std::endl;
}
else
{
std::cerr << "neither in " << absPath
<< " nor in " << mocSubDir << "\n" << std::endl;
}
::exit(EXIT_FAILURE);
}
}
else
{
if (basename != scannedFileBasename)
{
std::cerr <<"AUTOMOC: 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;
::exit(EXIT_FAILURE);
}
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.
if ((dotMocIncluded == false) && (containsQ_OBJECT(contentsString)))
{
// otherwise always error out since it will not compile:
std::cerr << "AUTOMOC: error: " << absFilename << ": The file "
<< "contains a Q_OBJECT macro, but does not include "
<< "\"" << scannedFileBasename << ".moc\" !\n"
<< std::endl;
::exit(EXIT_FAILURE);
}
}
void cmQtAutomoc::SearchHeadersForCppFile(const std::string& absFilename,
const std::list<std::string>& headerExtensions,
std::set<std::string>& absHeaders)
{
// search for header files and private header files we may need to moc:
const std::string basename =
cmsys::SystemTools::GetFilenameWithoutLastExtension(absFilename);
const std::string absPath = cmsys::SystemTools::GetFilenamePath(
cmsys::SystemTools::GetRealPath(absFilename.c_str())) + '/';
for(std::list<std::string>::const_iterator ext = headerExtensions.begin();
ext != headerExtensions.end();
++ext)
@ -663,7 +923,6 @@ void cmQtAutomoc::ParseHeaders(const std::set<std::string>& absHeaders,
const std::map<std::string, std::string>& includedMocs,
std::map<std::string, std::string>& notIncludedMocs)
{
cmsys::RegularExpression qObjectRegExp("[\n][ \t]*Q_OBJECT[^a-zA-Z0-9_]");
for(std::set<std::string>::const_iterator hIt=absHeaders.begin();
hIt!=absHeaders.end();
++hIt)
@ -682,7 +941,7 @@ void cmQtAutomoc::ParseHeaders(const std::set<std::string>& absHeaders,
const std::string currentMoc = "moc_" + basename + ".cpp";
const std::string contents = this->ReadAll(headerName);
if (qObjectRegExp.find(contents))
if (containsQ_OBJECT(contents))
{
//std::cout << "header contains Q_OBJECT macro";
notIncludedMocs[headerName] = currentMoc;
@ -759,7 +1018,7 @@ bool cmQtAutomoc::GenerateMoc(const std::string& sourceFile,
bool result = cmSystemTools::RunSingleCommand(command, &output, &retVal);
if (!result || retVal)
{
std::cerr << "AUTOMOC: process for " << mocFilePath << " failed:\n"
std::cerr << "AUTOMOC: error: process for " << mocFilePath <<" failed:\n"
<< output << std::endl;
this->RunMocFailed = true;
cmSystemTools::RemoveFile(mocFilePath.c_str());

View File

@ -39,8 +39,15 @@ private:
bool GenerateMoc(const std::string& sourceFile,
const std::string& mocFileName);
void ParseCppFile(const std::string& absFilename,
std::map<std::string, std::string>& includedMocs,
const std::list<std::string>& headerExtensions,
std::map<std::string, std::string>& includedMocs);
void StrictParseCppFile(const std::string& absFilename,
const std::list<std::string>& headerExtensions,
std::map<std::string, std::string>& includedMocs);
void SearchHeadersForCppFile(const std::string& absFilename,
const std::list<std::string>& headerExtensions,
std::set<std::string>& absHeaders);
void ParseHeaders(const std::set<std::string>& absHeaders,
const std::map<std::string, std::string>& includedMocs,
std::map<std::string, std::string>& notIncludedMocs);
@ -78,6 +85,7 @@ private:
bool ColorOutput;
bool RunMocFailed;
bool GenerateAll;
bool StrictMode;
};

View File

@ -161,8 +161,10 @@ void cmTarget::DefineProperties(cmake *cm)
"This property is initialized by the value of the variable "
"CMAKE_AUTOMOC if it is set when a target is created.\n"
"Additional command line options for moc can be set via the "
"AUTOMOC_MOC_OPTIONS property."
);
"AUTOMOC_MOC_OPTIONS property.\n"
"By setting the CMAKE_AUTOMOC_STRICT_MODE variable to FALSE the rules "
"for searching the files which will be processed by moc can be relaxed. "
"See the documentation for this variable for more details.");
cm->DefineProperty
("AUTOMOC_MOC_OPTIONS", cmProperty::TARGET,

View File

@ -13,7 +13,7 @@ add_definitions(-DFOO)
# create an executable and a library target, both requiring automoc:
add_library(codeeditorLib STATIC codeeditor.cpp)
add_executable(foo main.cpp calwidget.cpp foo.cpp)
add_executable(foo main.cpp calwidget.cpp foo.cpp blub.cpp bar.cpp abc.cpp xyz.cpp yaf.cpp private_slot.cpp)
set_target_properties(foo codeeditorLib PROPERTIES AUTOMOC TRUE)

49
Tests/QtAutomoc/abc.cpp Normal file
View File

@ -0,0 +1,49 @@
/*============================================================================
CMake - Cross Platform Makefile Generator
Copyright 2004-2011 Kitware, Inc.
Copyright 2011 Alexander Neundorf (neundorf@kde.org)
Distributed under the OSI-approved BSD License (the "License");
see accompanying file Copyright.txt for details.
This software is distributed WITHOUT ANY WARRANTY; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the License for more information.
============================================================================*/
#include "abc.h"
#include "abc_p.h"
#include <stdio.h>
class PrintAbc : public QObject
{
Q_OBJECT
public:
PrintAbc():QObject() {}
public slots:
void print() const { printf("abc\n"); }
};
Abc::Abc()
:QObject()
{
}
void Abc::doAbc()
{
PrintAbc pa;
pa.print();
AbcP abcP;
abcP.doAbcP();
}
// check that including the moc file for the cpp file and the header works:
#include "abc.moc"
#include "moc_abc.cpp"
#include "moc_abc_p.cpp"
// check that including a moc file from another header works:
#include "moc_xyz.cpp"

28
Tests/QtAutomoc/abc.h Normal file
View File

@ -0,0 +1,28 @@
/*============================================================================
CMake - Cross Platform Makefile Generator
Copyright 2004-2011 Kitware, Inc.
Copyright 2011 Alexander Neundorf (neundorf@kde.org)
Distributed under the OSI-approved BSD License (the "License");
see accompanying file Copyright.txt for details.
This software is distributed WITHOUT ANY WARRANTY; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the License for more information.
============================================================================*/
#ifndef ABC_H
#define ABC_H
#include <QObject>
class Abc : public QObject
{
Q_OBJECT
public:
Abc();
public slots:
void doAbc();
};
#endif

30
Tests/QtAutomoc/abc_p.h Normal file
View File

@ -0,0 +1,30 @@
/*============================================================================
CMake - Cross Platform Makefile Generator
Copyright 2004-2011 Kitware, Inc.
Copyright 2011 Alexander Neundorf (neundorf@kde.org)
Distributed under the OSI-approved BSD License (the "License");
see accompanying file Copyright.txt for details.
This software is distributed WITHOUT ANY WARRANTY; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the License for more information.
============================================================================*/
#ifndef ABC_P_H
#define ABC_P_H
#include <QObject>
#include <stdio.h>
class AbcP : public QObject
{
Q_OBJECT
public:
AbcP() {}
public slots:
void doAbcP() { printf("I am private abc !\n"); }
};
#endif

28
Tests/QtAutomoc/bar.cpp Normal file
View File

@ -0,0 +1,28 @@
/*============================================================================
CMake - Cross Platform Makefile Generator
Copyright 2004-2011 Kitware, Inc.
Copyright 2011 Alexander Neundorf (neundorf@kde.org)
Distributed under the OSI-approved BSD License (the "License");
see accompanying file Copyright.txt for details.
This software is distributed WITHOUT ANY WARRANTY; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the License for more information.
============================================================================*/
#include "sub/bar.h"
#include <stdio.h>
Bar::Bar()
:QObject()
{
}
void Bar::doBar()
{
printf("Hello bar !\n");
}
#include "sub/moc_bar.cpp"

40
Tests/QtAutomoc/blub.cpp Normal file
View File

@ -0,0 +1,40 @@
/*============================================================================
CMake - Cross Platform Makefile Generator
Copyright 2004-2011 Kitware, Inc.
Copyright 2011 Alexander Neundorf (neundorf@kde.org)
Distributed under the OSI-approved BSD License (the "License");
see accompanying file Copyright.txt for details.
This software is distributed WITHOUT ANY WARRANTY; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the License for more information.
============================================================================*/
#include "blub.h"
#include <stdio.h>
class BlubBlub : public QObject
{
Q_OBJECT
public:
BlubBlub():QObject() {}
public slots:
int getValue() const { return 13; }
};
Blub::Blub()
{
}
void Blub::blubber()
{
BlubBlub bb;
printf("Blub blub %d ! \n", bb.getValue());
}
// test the case that the wrong moc-file is included, it should
// actually be "blub.moc"
#include "moc_blub.cpp"

26
Tests/QtAutomoc/blub.h Normal file
View File

@ -0,0 +1,26 @@
/*============================================================================
CMake - Cross Platform Makefile Generator
Copyright 2004-2011 Kitware, Inc.
Copyright 2011 Alexander Neundorf (neundorf@kde.org)
Distributed under the OSI-approved BSD License (the "License");
see accompanying file Copyright.txt for details.
This software is distributed WITHOUT ANY WARRANTY; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the License for more information.
============================================================================*/
#ifndef BLUB_H
#define BLUB_H
#include <QObject>
class Blub
{
public:
Blub();
void blubber();
};
#endif

View File

@ -43,6 +43,11 @@
#include "codeeditor.h"
#include "calwidget.h"
#include "foo.h"
#include "blub.h"
#include "sub/bar.h"
#include "abc.h"
#include "xyz.h"
#include "yaf.h"
int main(int argv, char **args)
{
@ -58,5 +63,20 @@ int main(int argv, char **args)
Foo foo;
foo.doFoo();
Blub b;
b.blubber();
Bar bar;
bar.doBar();
Abc abc;
abc.doAbc();
Xyz xyz;
xyz.doXyz();
Yaf yaf;
yaf.doYaf();
return app.exec();
}

View File

@ -0,0 +1,21 @@
#include "private_slot.h"
class PrivateSlotPrivate
{
public:
void privateSlot()
{
}
};
PrivateSlot::PrivateSlot(QObject *parent)
: QObject(parent),
d(new PrivateSlotPrivate)
{
}
#include "private_slot.moc"

View File

@ -0,0 +1,20 @@
#ifndef PRIVATE_SLOT_H
#define PRIVATE_SLOT_H
#include <QObject>
class PrivateSlotPrivate;
class PrivateSlot : public QObject
{
Q_OBJECT
public:
PrivateSlot(QObject *parent = 0);
private:
PrivateSlotPrivate * const d;
Q_PRIVATE_SLOT(d, void privateSlot())
};
#endif

28
Tests/QtAutomoc/sub/bar.h Normal file
View File

@ -0,0 +1,28 @@
/*============================================================================
CMake - Cross Platform Makefile Generator
Copyright 2004-2011 Kitware, Inc.
Copyright 2011 Alexander Neundorf (neundorf@kde.org)
Distributed under the OSI-approved BSD License (the "License");
see accompanying file Copyright.txt for details.
This software is distributed WITHOUT ANY WARRANTY; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the License for more information.
============================================================================*/
#ifndef BAR_H
#define BAR_H
#include <QObject>
class Bar : public QObject
{
Q_OBJECT
public:
Bar();
public slots:
void doBar();
};
#endif

28
Tests/QtAutomoc/xyz.cpp Normal file
View File

@ -0,0 +1,28 @@
/*============================================================================
CMake - Cross Platform Makefile Generator
Copyright 2004-2011 Kitware, Inc.
Copyright 2011 Alexander Neundorf (neundorf@kde.org)
Distributed under the OSI-approved BSD License (the "License");
see accompanying file Copyright.txt for details.
This software is distributed WITHOUT ANY WARRANTY; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the License for more information.
============================================================================*/
#include "xyz.h"
#include <stdio.h>
Xyz::Xyz()
:QObject()
{
}
void Xyz::doXyz()
{
printf("This is xyz !\n");
}

28
Tests/QtAutomoc/xyz.h Normal file
View File

@ -0,0 +1,28 @@
/*============================================================================
CMake - Cross Platform Makefile Generator
Copyright 2004-2011 Kitware, Inc.
Copyright 2011 Alexander Neundorf (neundorf@kde.org)
Distributed under the OSI-approved BSD License (the "License");
see accompanying file Copyright.txt for details.
This software is distributed WITHOUT ANY WARRANTY; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the License for more information.
============================================================================*/
#ifndef XYZ_H
#define XYZ_H
#include <QObject>
class Xyz : public QObject
{
Q_OBJECT
public:
Xyz();
public slots:
void doXyz();
};
#endif

32
Tests/QtAutomoc/yaf.cpp Normal file
View File

@ -0,0 +1,32 @@
/*============================================================================
CMake - Cross Platform Makefile Generator
Copyright 2004-2011 Kitware, Inc.
Copyright 2011 Alexander Neundorf (neundorf@kde.org)
Distributed under the OSI-approved BSD License (the "License");
see accompanying file Copyright.txt for details.
This software is distributed WITHOUT ANY WARRANTY; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the License for more information.
============================================================================*/
#include "yaf.h"
#include "yaf_p.h"
#include <stdio.h>
Yaf::Yaf()
{
}
void Yaf::doYaf()
{
YafP yafP;
yafP.doYafP();
}
// check that including a moc file from a private header the wrong way works:
#include "yaf_p.moc"

25
Tests/QtAutomoc/yaf.h Normal file
View File

@ -0,0 +1,25 @@
/*============================================================================
CMake - Cross Platform Makefile Generator
Copyright 2004-2011 Kitware, Inc.
Copyright 2011 Alexander Neundorf (neundorf@kde.org)
Distributed under the OSI-approved BSD License (the "License");
see accompanying file Copyright.txt for details.
This software is distributed WITHOUT ANY WARRANTY; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the License for more information.
============================================================================*/
#ifndef YAF_H
#define YAF_H
class Yaf
{
public:
Yaf();
public:
void doYaf();
};
#endif

30
Tests/QtAutomoc/yaf_p.h Normal file
View File

@ -0,0 +1,30 @@
/*============================================================================
CMake - Cross Platform Makefile Generator
Copyright 2004-2011 Kitware, Inc.
Copyright 2011 Alexander Neundorf (neundorf@kde.org)
Distributed under the OSI-approved BSD License (the "License");
see accompanying file Copyright.txt for details.
This software is distributed WITHOUT ANY WARRANTY; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the License for more information.
============================================================================*/
#ifndef YAF_P_H
#define YAF_P_H
#include <QObject>
#include <stdio.h>
class YafP : public QObject
{
Q_OBJECT
public:
YafP() {}
public slots:
void doYafP() { printf("I am yet another file !\n"); }
};
#endif