Merge topic 'autogen-updates'

84946c73 Tests: QtAutogen: Same source name in different directories test
9c6fa684 Autogen: Generate qrc_NAME.cpp files in subdirectories
488ea8c7 Autogen: Generate not included moc files in subdirectories (#12873)
66caae45 Autogen: Check added for name collisions of generated qrc_NAME.cpp files
663d093d Autogen: Check added for name collisions of generated ui_NAME.h files
8295d437 Autogen: Check added for name collisions of generated moc files
d350308a Help: Improve AUTOMOC documentation layout
This commit is contained in:
Brad King 2016-04-22 09:02:03 -04:00 committed by CMake Topic Stage
commit 76e793b9ad
24 changed files with 544 additions and 62 deletions

View File

@ -6,22 +6,35 @@ Should the target be processed with automoc (for Qt projects).
AUTOMOC is a boolean specifying whether CMake will handle the Qt ``moc`` AUTOMOC is a boolean specifying whether CMake will handle the Qt ``moc``
preprocessor automatically, i.e. without having to use the preprocessor automatically, i.e. without having to use the
:module:`QT4_WRAP_CPP() <FindQt4>` or QT5_WRAP_CPP() macro. Currently Qt4 and Qt5 are :module:`QT4_WRAP_CPP() <FindQt4>` or QT5_WRAP_CPP() macro. Currently Qt4 and Qt5 are
supported. When this property is set ``ON``, CMake will scan the supported.
source files at build time and invoke moc accordingly. If an ``#include``
statement like ``#include "moc_foo.cpp"`` is found, the ``Q_OBJECT`` class When this property is set ``ON``, CMake will scan the
declaration is expected in the header, and ``moc`` is run on the header source files at build time and invoke moc accordingly.
file. If an ``#include`` statement like ``#include "foo.moc"`` is found, then
a ``Q_OBJECT`` is expected in the current source file and ``moc`` is run on * If an ``#include`` statement like ``#include "moc_foo.cpp"`` is found,
the file itself. Additionally, header files with the same base name (like the ``Q_OBJECT`` class declaration is expected in the header, and
``foo.h``) or ``_p`` appended to the base name (like ``foo_p.h``) are parsed ``moc`` is run on the header file. A ``moc_foo.cpp`` file will be
for ``Q_OBJECT`` macros, and if found, ``moc`` is also executed on those files. generated from the source's header into the
``AUTOMOC`` checks multiple header alternative extensions, such as :variable:`CMAKE_CURRENT_BINARY_DIR` directory. This allows the
``hpp``, ``hxx`` etc when searching for headers. compiler to find the included ``moc_foo.cpp`` file regardless of the
The resulting moc files, which are not included as shown above in any location the original source. However, if multiple source files
of the source files are included in a generated in different directories do this then their generated moc files would
collide. In this case a diagnostic will be issued.
* If an ``#include`` statement like ``#include "foo.moc"`` is found,
then a ``Q_OBJECT`` is expected in the current source file and ``moc``
is run on the file itself. Additionally, header files with the same
base name (like ``foo.h``) or ``_p`` appended to the base name (like
``foo_p.h``) are parsed for ``Q_OBJECT`` macros, and if found, ``moc``
is also executed on those files. ``AUTOMOC`` checks multiple header
alternative extensions, such as ``hpp``, ``hxx`` etc when searching
for headers. The resulting moc files, which are not included as shown
above in any of the source files are included in a generated
``<targetname>_automoc.cpp`` file, which is compiled as part of the ``<targetname>_automoc.cpp`` file, which is compiled as part of the
target. This property is initialized by the value of the target.
:variable:`CMAKE_AUTOMOC` variable if it is set when a target is created.
This property is initialized by the value of the :variable:`CMAKE_AUTOMOC`
variable if it is set when a target is created.
Additional command line options for moc can be set via the Additional command line options for moc can be set via the
:prop_tgt:`AUTOMOC_MOC_OPTIONS` property. :prop_tgt:`AUTOMOC_MOC_OPTIONS` property.

View File

@ -0,0 +1,6 @@
automoc-diagnostics
-------------------
* :prop_tgt:`AUTOMOC` now diagnoses name collisions when multiple source
files in different directories use ``#include <moc_foo.cpp>`` with the
same name (because the generated ``moc_foo.cpp`` files would collide).

View File

@ -25,6 +25,87 @@
# include "cmGlobalVisualStudioGenerator.h" # include "cmGlobalVisualStudioGenerator.h"
#endif #endif
static std::string GetAutogenTargetName(
cmGeneratorTarget const* target)
{
std::string autogenTargetName = target->GetName();
autogenTargetName += "_automoc";
return autogenTargetName;
}
static std::string GetAutogenTargetDir(
cmGeneratorTarget const* target)
{
cmMakefile* makefile = target->Target->GetMakefile();
std::string targetDir = makefile->GetCurrentBinaryDirectory();
targetDir += makefile->GetCMakeInstance()->GetCMakeFilesDirectory();
targetDir += "/";
targetDir += GetAutogenTargetName(target);
targetDir += ".dir/";
return targetDir;
}
static std::string GetAutogenTargetBuildDir(
cmGeneratorTarget const* target)
{
cmMakefile* makefile = target->Target->GetMakefile();
std::string targetDir = makefile->GetCurrentBinaryDirectory();
targetDir += "/";
targetDir += GetAutogenTargetName(target);
targetDir += ".dir/";
return targetDir;
}
static std::string GetSourceRelativePath(
cmGeneratorTarget const* target,
const std::string& fileName)
{
std::string pathRel;
// Test if the file is child to any of the known directories
{
const std::string fileNameReal = cmsys::SystemTools::GetRealPath(fileName);
std::string parentDirectory;
bool match ( false );
{
std::string testDirs[4];
{
cmMakefile* makefile = target->Target->GetMakefile();
testDirs[0] = makefile->GetCurrentSourceDirectory();
testDirs[1] = makefile->GetCurrentBinaryDirectory();
testDirs[2] = makefile->GetHomeDirectory();
testDirs[3] = makefile->GetHomeOutputDirectory();
}
for(int ii=0; ii != sizeof(testDirs)/sizeof(std::string); ++ii )
{
const ::std::string testDir = cmsys::SystemTools::GetRealPath(
testDirs[ii]);
if (!testDir.empty()
&& cmsys::SystemTools::IsSubDirectory(fileNameReal, testDir) )
{
parentDirectory = testDir;
match = true;
break;
}
}
}
// Use root as fallback parent directory
if (!match)
{
cmsys::SystemTools::SplitPathRootComponent(fileNameReal,
&parentDirectory);
}
pathRel = cmsys::SystemTools::RelativePath(
parentDirectory, cmsys::SystemTools::GetParentDirectory(fileNameReal));
}
// Sanitize relative path
if (!pathRel.empty())
{
pathRel += '/';
cmSystemTools::ReplaceString(pathRel, "..", "__");
}
return pathRel;
}
static void SetupSourceFiles(cmGeneratorTarget const* target, static void SetupSourceFiles(cmGeneratorTarget const* target,
std::vector<std::string>& skipMoc, std::vector<std::string>& skipMoc,
std::vector<std::string>& mocSources, std::vector<std::string>& mocSources,
@ -61,13 +142,16 @@ static void SetupSourceFiles(cmGeneratorTarget const* target,
if (ext == "qrc" if (ext == "qrc"
&& !cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTORCC"))) && !cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTORCC")))
{ {
std::string rcc_output_dir = GetAutogenTargetBuildDir(target);
rcc_output_dir += GetSourceRelativePath(target,absFile);
cmSystemTools::MakeDirectory(rcc_output_dir.c_str());
std::string basename = cmsys::SystemTools:: std::string basename = cmsys::SystemTools::
GetFilenameWithoutLastExtension(absFile); GetFilenameWithoutLastExtension(absFile);
std::string rcc_output_dir = target->GetSupportDirectory();
cmSystemTools::MakeDirectory(rcc_output_dir.c_str());
std::string rcc_output_file = rcc_output_dir; std::string rcc_output_file = rcc_output_dir;
rcc_output_file += "/qrc_" + basename + ".cpp"; rcc_output_file += "qrc_" + basename + ".cpp";
makefile->AppendProperty("ADDITIONAL_MAKE_CLEAN_FILES", makefile->AppendProperty("ADDITIONAL_MAKE_CLEAN_FILES",
rcc_output_file.c_str(), false); rcc_output_file.c_str(), false);
makefile->GetOrCreateSource(rcc_output_file, true); makefile->GetOrCreateSource(rcc_output_file, true);
@ -433,26 +517,6 @@ static void MergeRccOptions(std::vector<std::string> &opts,
opts.insert(opts.end(), extraOpts.begin(), extraOpts.end()); opts.insert(opts.end(), extraOpts.begin(), extraOpts.end());
} }
std::string GetAutogenTargetName(
cmGeneratorTarget const* target)
{
std::string autogenTargetName = target->GetName();
autogenTargetName += "_automoc";
return autogenTargetName;
}
std::string GetAutogenTargetDir(
cmGeneratorTarget const* target)
{
cmMakefile* makefile = target->Target->GetMakefile();
std::string targetDir = makefile->GetCurrentBinaryDirectory();
targetDir += makefile->GetCMakeInstance()->GetCMakeFilesDirectory();
targetDir += "/";
targetDir += GetAutogenTargetName(target);
targetDir += ".dir/";
return targetDir;
}
static void copyTargetProperty(cmTarget* destinationTarget, static void copyTargetProperty(cmTarget* destinationTarget,
cmTarget* sourceTarget, cmTarget* sourceTarget,
const std::string& propertyName) const std::string& propertyName)
@ -858,14 +922,18 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget(
if (ext == "qrc" if (ext == "qrc"
&& !cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTORCC"))) && !cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTORCC")))
{ {
{
std::string rcc_output_dir = GetAutogenTargetBuildDir(target);
rcc_output_dir += GetSourceRelativePath(target,absFile);
cmSystemTools::MakeDirectory(rcc_output_dir.c_str());
std::string basename = cmsys::SystemTools:: std::string basename = cmsys::SystemTools::
GetFilenameWithoutLastExtension(absFile); GetFilenameWithoutLastExtension(absFile);
std::string rcc_output_dir = target->GetSupportDirectory();
cmSystemTools::MakeDirectory(rcc_output_dir.c_str());
std::string rcc_output_file = rcc_output_dir; std::string rcc_output_file = rcc_output_dir;
rcc_output_file += "/qrc_" + basename + ".cpp"; rcc_output_file += "qrc_" + basename + ".cpp";
rcc_output.push_back(rcc_output_file); rcc_output.push_back(rcc_output_file);
}
if (!cmSystemTools::IsOn(sf->GetPropertyForUser("GENERATED"))) if (!cmSystemTools::IsOn(sf->GetPropertyForUser("GENERATED")))
{ {

View File

@ -410,11 +410,12 @@ cmQtAutoGenerators::WriteOldMocDefinitionsFile(
void cmQtAutoGenerators::Init() void cmQtAutoGenerators::Init()
{ {
this->TargetBuildSubDir = this->TargetName;
this->TargetBuildSubDir += ".dir/";
this->OutMocCppFilenameRel = this->TargetName; this->OutMocCppFilenameRel = this->TargetName;
this->OutMocCppFilenameRel += ".cpp"; this->OutMocCppFilenameRel += ".cpp";
this->OutMocCppFilenameAbs = this->Builddir + this->OutMocCppFilenameRel;
this->OutMocCppFilename = this->Builddir;
this->OutMocCppFilename += this->OutMocCppFilenameRel;
std::vector<std::string> cdefList; std::vector<std::string> cdefList;
cmSystemTools::ExpandListArgument(this->MocCompileDefinitionsStr, cdefList); cmSystemTools::ExpandListArgument(this->MocCompileDefinitionsStr, cdefList);
@ -507,7 +508,7 @@ static std::string ReadAll(const std::string& filename)
bool cmQtAutoGenerators::RunAutogen(cmMakefile* makefile) bool cmQtAutoGenerators::RunAutogen(cmMakefile* makefile)
{ {
if (!cmsys::SystemTools::FileExists(this->OutMocCppFilename.c_str()) if (!cmsys::SystemTools::FileExists(this->OutMocCppFilenameAbs.c_str())
|| (this->OldCompileSettingsStr != this->CurrentCompileSettingsStr)) || (this->OldCompileSettingsStr != this->CurrentCompileSettingsStr))
{ {
this->GenerateAll = true; this->GenerateAll = true;
@ -1047,14 +1048,15 @@ void cmQtAutoGenerators::ParseHeaders(const std::set<std::string>& absHeaders,
std::cout << "AUTOGEN: Checking " << headerName << std::endl; std::cout << "AUTOGEN: Checking " << headerName << std::endl;
} }
const std::string basename = cmsys::SystemTools::
GetFilenameWithoutLastExtension(headerName);
const std::string currentMoc = "moc_" + basename + ".cpp";
std::string macroName; std::string macroName;
if (requiresMocing(contents, macroName)) if (requiresMocing(contents, macroName))
{ {
//std::cout << "header contains Q_OBJECT macro"; //std::cout << "header contains Q_OBJECT macro";
const std::string parentDir = this->TargetBuildSubDir
+ this->SourceRelativePath ( headerName );
const std::string basename = cmsys::SystemTools::
GetFilenameWithoutLastExtension(headerName);
const std::string currentMoc = parentDir + "moc_" + basename + ".cpp";
notIncludedMocs[headerName] = currentMoc; notIncludedMocs[headerName] = currentMoc;
} }
} }
@ -1067,6 +1069,26 @@ bool cmQtAutoGenerators::GenerateMocFiles(
const std::map<std::string, std::string>& includedMocs, const std::map<std::string, std::string>& includedMocs,
const std::map<std::string, std::string>& notIncludedMocs ) const std::map<std::string, std::string>& notIncludedMocs )
{ {
// look for name collisions
{
std::multimap<std::string, std::string> collisions;
// Test merged map of included and notIncluded
std::map<std::string, std::string> mergedMocs ( includedMocs );
mergedMocs.insert ( notIncludedMocs.begin(), notIncludedMocs.end() );
if( this->NameCollisionTest ( mergedMocs, collisions ) )
{
std::cerr <<
"AUTOGEN: error: "
"The same moc file will be generated "
"from different sources." << std::endl <<
"To avoid this error either" << std::endl <<
"- rename the source files or" << std::endl <<
"- do not include the (moc_NAME.cpp|NAME.moc) file" << std::endl;
this->NameCollisionLog ( collisions );
::exit(EXIT_FAILURE);
}
}
// generate moc files that are included by source files. // generate moc files that are included by source files.
for(std::map<std::string, std::string>::const_iterator for(std::map<std::string, std::string>::const_iterator
it = includedMocs.begin(); it != includedMocs.end(); ++it) it = includedMocs.begin(); it != includedMocs.end(); ++it)
@ -1125,7 +1147,7 @@ bool cmQtAutoGenerators::GenerateMocFiles(
if (!automocCppChanged) if (!automocCppChanged)
{ {
// compare contents of the _automoc.cpp file // compare contents of the _automoc.cpp file
const std::string oldContents = ReadAll(this->OutMocCppFilename); const std::string oldContents = ReadAll(this->OutMocCppFilenameAbs);
if (oldContents == automocSource) if (oldContents == automocSource)
{ {
// nothing changed: don't touch the _automoc.cpp file // nothing changed: don't touch the _automoc.cpp file
@ -1148,7 +1170,7 @@ bool cmQtAutoGenerators::GenerateMocFiles(
} }
{ {
cmsys::ofstream outfile; cmsys::ofstream outfile;
outfile.open(this->OutMocCppFilename.c_str(), outfile.open(this->OutMocCppFilenameAbs.c_str(),
std::ios::trunc); std::ios::trunc);
outfile << automocSource; outfile << automocSource;
outfile.close(); outfile.close();
@ -1223,6 +1245,7 @@ bool cmQtAutoGenerators::GenerateUiFiles(
{ {
// single map with input / output names // single map with input / output names
std::map<std::string, std::map<std::string, std::string> > uiGenMap; std::map<std::string, std::map<std::string, std::string> > uiGenMap;
std::map<std::string, std::string> testMap;
for(std::map<std::string, std::vector<std::string> >::const_iterator for(std::map<std::string, std::vector<std::string> >::const_iterator
it = includedUis.begin(); it != includedUis.end(); ++it) it = includedUis.begin(); it != includedUis.end(); ++it)
{ {
@ -1240,9 +1263,24 @@ bool cmQtAutoGenerators::GenerateUiFiles(
const std::string uiInputFile = sourcePath + uiFileName + ".ui"; const std::string uiInputFile = sourcePath + uiFileName + ".ui";
const std::string uiOutputFile = "ui_" + uiFileName + ".h"; const std::string uiOutputFile = "ui_" + uiFileName + ".h";
sourceMap[uiInputFile] = uiOutputFile; sourceMap[uiInputFile] = uiOutputFile;
testMap[uiInputFile] = uiOutputFile;
} }
} }
// look for name collisions
{
std::multimap<std::string, std::string> collisions;
if( this->NameCollisionTest ( testMap, collisions ) )
{
std::cerr << "AUTOGEN: error: The same ui_NAME.h file will be generated "
"from different sources." << std::endl
<< "To avoid this error rename the source files." << std::endl;
this->NameCollisionLog ( collisions );
::exit(EXIT_FAILURE);
}
}
testMap.clear();
// generate ui files // generate ui files
for(std::map<std::string, std::map<std::string, std::string> >:: for(std::map<std::string, std::map<std::string, std::string> >::
const_iterator it = uiGenMap.begin(); it != uiGenMap.end(); ++it) const_iterator it = uiGenMap.begin(); it != uiGenMap.end(); ++it)
@ -1361,12 +1399,29 @@ bool cmQtAutoGenerators::GenerateQrcFiles()
{ {
std::string basename = cmsys::SystemTools:: std::string basename = cmsys::SystemTools::
GetFilenameWithoutLastExtension(*si); GetFilenameWithoutLastExtension(*si);
std::string qrcOutputFile = "CMakeFiles/" + this->OriginTargetName std::string qrcOutputFile = this->TargetBuildSubDir
+ ".dir/qrc_" + basename + ".cpp"; + this->SourceRelativePath ( *si )
+ "qrc_" + basename + ".cpp";
//std::string qrcOutputFile = "CMakeFiles/" + this->OriginTargetName
// + ".dir/qrc_" + basename + ".cpp";
qrcGenMap[*si] = qrcOutputFile; qrcGenMap[*si] = qrcOutputFile;
} }
} }
// look for name collisions
{
std::multimap<std::string, std::string> collisions;
if( this->NameCollisionTest ( qrcGenMap, collisions ) )
{
std::cerr << "AUTOGEN: error: The same qrc_NAME.cpp file"
" will be generated from different sources." << std::endl
<< "To avoid this error rename the source .qrc files."
<< std::endl;
this->NameCollisionLog ( collisions );
::exit(EXIT_FAILURE);
}
}
// generate qrc files // generate qrc files
for(std::map<std::string, std::string>::const_iterator for(std::map<std::string, std::string>::const_iterator
si = qrcGenMap.begin(); si != qrcGenMap.end(); ++si) si = qrcGenMap.begin(); si != qrcGenMap.end(); ++si)
@ -1386,8 +1441,10 @@ bool cmQtAutoGenerators::GenerateQrc (
const std::string& qrcInputFile, const std::string& qrcInputFile,
const std::string& qrcOutputFile ) const std::string& qrcOutputFile )
{ {
const std::string basename = cmsys::SystemTools:: std::string relName = this->SourceRelativePath ( qrcInputFile );
GetFilenameWithoutLastExtension(qrcInputFile); cmSystemTools::ReplaceString(relName, "/", "_");
relName += cmsys::SystemTools::GetFilenameWithoutLastExtension(qrcInputFile);
const ::std::string qrcBuildFile = this->Builddir + qrcOutputFile; const ::std::string qrcBuildFile = this->Builddir + qrcOutputFile;
int sourceNewerThanQrc = 0; int sourceNewerThanQrc = 0;
@ -1417,7 +1474,7 @@ bool cmQtAutoGenerators::GenerateQrc (
} }
command.push_back("-name"); command.push_back("-name");
command.push_back(basename); command.push_back(relName);
command.push_back("-o"); command.push_back("-o");
command.push_back(qrcBuildFile); command.push_back(qrcBuildFile);
command.push_back(qrcInputFile); command.push_back(qrcInputFile);
@ -1442,6 +1499,102 @@ bool cmQtAutoGenerators::GenerateQrc (
return true; return true;
} }
std::string cmQtAutoGenerators::SourceRelativePath(const std::string& filename)
{
std::string pathRel;
// Test if the file is child to any of the known directories
{
std::string fileNameReal = cmsys::SystemTools::GetRealPath( filename );
std::string parentDirectory;
bool match ( false );
{
const ::std::string* testDirs[4];
testDirs[0] = &(this->Srcdir);
testDirs[1] = &(this->Builddir);
testDirs[2] = &(this->ProjectSourceDir);
testDirs[3] = &(this->ProjectBinaryDir);
for(int ii=0; ii != sizeof(testDirs)/sizeof(const ::std::string*); ++ii )
{
const ::std::string testDir = cmsys::SystemTools::GetRealPath(
*(testDirs[ii]));
if (cmsys::SystemTools::IsSubDirectory(fileNameReal,
testDir) )
{
parentDirectory = testDir;
match = true;
break;
}
}
}
// Use root as fallback parent directory
if ( !match )
{
cmsys::SystemTools::SplitPathRootComponent(fileNameReal,
&parentDirectory);
}
pathRel = cmsys::SystemTools::RelativePath(
parentDirectory, cmsys::SystemTools::GetParentDirectory(fileNameReal));
}
// Sanitize relative path
if (!pathRel.empty())
{
pathRel += '/';
cmSystemTools::ReplaceString(pathRel, "..", "__");
}
return pathRel;
}
/**
* @brief Collects name collisions as output/input pairs
* @return True if there were collisions
*/
bool cmQtAutoGenerators::NameCollisionTest(
const std::map<std::string, std::string >& genFiles,
std::multimap<std::string, std::string>& collisions)
{
typedef std::map<std::string, std::string>::const_iterator Iter;
typedef std::map<std::string, std::string>::value_type VType;
for(Iter ait = genFiles.begin(); ait != genFiles.end(); ++ait )
{
bool first_match ( true );
for (Iter bit = (++Iter(ait)); bit != genFiles.end(); ++bit)
{
if(ait->second == bit->second)
{
if (first_match)
{
if (collisions.find(ait->second) != collisions.end())
{
// We already know of this collision from before
break;
}
collisions.insert(VType(ait->second, ait->first));
first_match = false;
}
collisions.insert(VType(bit->second, bit->first));
}
}
}
return !collisions.empty();
}
void cmQtAutoGenerators::NameCollisionLog(
const std::multimap<std::string, std::string>& collisions)
{
typedef std::multimap<std::string, std::string>::const_iterator Iter;
std::stringstream sbuf;
for(Iter it = collisions.begin(); it != collisions.end(); ++it )
{
sbuf << it->first << " : " << it->second << std::endl;
}
sbuf.flush();
std::cerr << sbuf.str();
}
void cmQtAutoGenerators::LogCommand(const std::vector<std::string>& command) void cmQtAutoGenerators::LogCommand(const std::vector<std::string>& command)
{ {
std::stringstream sbuf; std::stringstream sbuf;

View File

@ -78,6 +78,13 @@ private:
void Init(); void Init();
std::string SourceRelativePath(const std::string& filename);
bool NameCollisionTest(const std::map<std::string, std::string >& genFiles,
std::multimap<std::string, std::string>& collisions );
void NameCollisionLog(
const std::multimap<std::string, std::string>& collisions );
void LogCommand(const std::vector<std::string>& command); void LogCommand(const std::vector<std::string>& command);
std::string JoinExts(const std::vector<std::string>& lst); std::string JoinExts(const std::vector<std::string>& lst);
@ -109,8 +116,9 @@ private:
std::string CurrentCompileSettingsStr; std::string CurrentCompileSettingsStr;
std::string OldCompileSettingsStr; std::string OldCompileSettingsStr;
std::string TargetBuildSubDir;
std::string OutMocCppFilenameRel; std::string OutMocCppFilenameRel;
std::string OutMocCppFilename; std::string OutMocCppFilenameAbs;
std::list<std::string> MocIncludes; std::list<std::string> MocIncludes;
std::list<std::string> MocDefinitions; std::list<std::string> MocDefinitions;
std::vector<std::string> MocOptions; std::vector<std::string> MocOptions;

View File

@ -110,6 +110,10 @@ set_target_properties(
AUTOMOC TRUE AUTOMOC TRUE
) )
# Test AUTOMOC and AUTORCC on source files with the same name
# but in different subdirectories
add_subdirectory(same_name)
include(GenerateExportHeader) include(GenerateExportHeader)
# The order is relevant here. B depends on A, and B headers depend on A # The order is relevant here. B depends on A, and B headers depend on A
# headers both subdirectories use CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE and we # headers both subdirectories use CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE and we

View File

@ -0,0 +1,20 @@
# Test AUTOMOC and AUTORCC on source files with the same name
# but in different subdirectories
add_executable(same_name
aaa/bbb/item.cpp
aaa/bbb/data.qrc
aaa/item.cpp
aaa/data.qrc
bbb/aaa/item.cpp
bbb/aaa/data.qrc
bbb/item.cpp
bbb/data.qrc
ccc/item.cpp
ccc/data.qrc
main.cpp
data.qrc
)
target_include_directories(same_name PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
target_link_libraries(same_name ${QT_LIBRARIES})
set_target_properties( same_name PROPERTIES AUTOMOC TRUE AUTORCC TRUE )

View File

@ -0,0 +1,6 @@
<!DOCTYPE RCC><RCC version="1.0">
<qresource prefix="aaa/bbb">
<file>item.hpp</file>
<file>item.cpp</file>
</qresource>
</RCC>

View File

@ -0,0 +1,12 @@
#include "item.hpp"
namespace aaa {
namespace bbb {
void
Item::go ( )
{
}
}
}

View File

@ -0,0 +1,19 @@
#ifndef SDA_SDB_ITEM_HPP
#define SDA_SDB_ITEM_HPP
#include <QObject>
namespace aaa {
namespace bbb {
class Item : public QObject
{
Q_OBJECT
Q_SLOT
void go ( );
};
}
}
#endif

View File

@ -0,0 +1,6 @@
<!DOCTYPE RCC><RCC version="1.0">
<qresource prefix="aaa/">
<file>item.hpp</file>
<file>item.cpp</file>
</qresource>
</RCC>

View File

@ -0,0 +1,10 @@
#include "item.hpp"
namespace aaa {
void
Item::go ( )
{
}
}

View File

@ -0,0 +1,17 @@
#ifndef SDA_ITEM_HPP
#define SDA_ITEM_HPP
#include <QObject>
namespace aaa {
class Item : public QObject
{
Q_OBJECT
Q_SLOT
void go ( );
};
}
#endif

View File

@ -0,0 +1,6 @@
<!DOCTYPE RCC><RCC version="1.0">
<qresource prefix="bbb/aaa/">
<file>item.hpp</file>
<file>item.cpp</file>
</qresource>
</RCC>

View File

@ -0,0 +1,12 @@
#include "item.hpp"
namespace bbb {
namespace aaa {
void
Item::go ( )
{
}
}
}

View File

@ -0,0 +1,19 @@
#ifndef SDB_SDA_ITEM_HPP
#define SDB_SDA_ITEM_HPP
#include <QObject>
namespace bbb {
namespace aaa {
class Item : public QObject
{
Q_OBJECT
Q_SLOT
void go ( );
};
}
}
#endif

View File

@ -0,0 +1,6 @@
<!DOCTYPE RCC><RCC version="1.0">
<qresource prefix="bbb/">
<file>item.hpp</file>
<file>item.cpp</file>
</qresource>
</RCC>

View File

@ -0,0 +1,10 @@
#include "item.hpp"
namespace bbb {
void
Item::go ( )
{
}
}

View File

@ -0,0 +1,17 @@
#ifndef SDB_ITEM_HPP
#define SDB_ITEM_HPP
#include <QObject>
namespace bbb {
class Item : public QObject
{
Q_OBJECT
Q_SLOT
void go ( );
};
}
#endif

View File

@ -0,0 +1,6 @@
<!DOCTYPE RCC><RCC version="1.0">
<qresource prefix="ccc/">
<file>item.hpp</file>
<file>item.cpp</file>
</qresource>
</RCC>

View File

@ -0,0 +1,26 @@
#include "item.hpp"
namespace ccc {
void
Item::go ( )
{
}
class MocTest : public QObject
{
Q_OBJECT;
Q_SLOT
void go ( );
};
void
MocTest::go()
{
}
}
// Include own moc files
#include "moc_item.cpp"
#include "item.moc"

View File

@ -0,0 +1,17 @@
#ifndef SDC_ITEM_HPP
#define SDC_ITEM_HPP
#include <QObject>
namespace ccc {
class Item : public QObject
{
Q_OBJECT
Q_SLOT
void go ( );
};
}
#endif

View File

@ -0,0 +1,5 @@
<!DOCTYPE RCC><RCC version="1.0">
<qresource>
<file>main.cpp</file>
</qresource>
</RCC>

View File

@ -0,0 +1,16 @@
#include "aaa/item.hpp"
#include "aaa/bbb/item.hpp"
#include "bbb/item.hpp"
#include "bbb/aaa/item.hpp"
#include "ccc/item.hpp"
int main(int argv, char **args)
{
// Object instances
::aaa::Item aaa_item;
::aaa::bbb::Item aaa_bbb_item;
::bbb::Item bbb_item;
::bbb::aaa::Item bbb_aaa_item;
::ccc::Item ccc_item;
return 0;
}