Sorry for the noise.
I've stumbled over bug
https://cmake.org/Bug/view.php?id=12873
a few times now since I like to use same named data/view classes.
I've prepared a fix that generates all moc_xxx.cpp files
in the foo_automoc.dir subdirectory.
Here is an improved patch that calculates header relative paths
in the following parent directory lookup order
- CMAKE_CURRENT_SOURCE_DIR
- CMAKE_CURRENT_BINARY_DIR
- CMAKE_SOURCE_DIR
- CMAKE_BINARY_DIR
Also std::cout debugging was removed ;)
Kind regards,
Sebastian Holtermann
>From 7d8191f70232a89453be127f64603970a08c96d8 Mon Sep 17 00:00:00 2001
From: Sebastian Holtermann <[email protected]>
Date: Tue, 12 Apr 2016 13:33:21 +0200
Subject: [PATCH] Automoc: Create moc files below foo_automoc.dir with respect
to the source header project relative path
---
Source/cmQtAutoGenerators.cxx | 102 ++++++++++++++++++++++++++++++++++++------
Source/cmQtAutoGenerators.h | 3 ++
2 files changed, 92 insertions(+), 13 deletions(-)
diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx
index ebe08b0..1c02411 100644
--- a/Source/cmQtAutoGenerators.cxx
+++ b/Source/cmQtAutoGenerators.cxx
@@ -414,6 +414,9 @@ void cmQtAutoGenerators::Init()
this->OutMocCppFilename += this->TargetName;
this->OutMocCppFilename += ".cpp";
+ this->OutMocDirname += this->TargetName;
+ this->OutMocDirname += ".dir";
+
std::vector<std::string> cdefList;
cmSystemTools::ExpandListArgument(this->MocCompileDefinitionsStr, cdefList);
for(std::vector<std::string>::const_iterator it = cdefList.begin();
@@ -637,7 +640,7 @@ bool cmQtAutoGenerators::RunAutogen(cmMakefile* makefile)
{
automocCppChanged = true;
}
- outStream << "#include \"" << it->second << "\"\n";
+ outStream << "#include \"" << MocPathBuildRel ( it->second ) << "\"\n";
}
}
@@ -749,7 +752,7 @@ void cmQtAutoGenerators::ParseCppFile(const std::string& absFilename,
if (!headerToMoc.empty())
{
- includedMocs[headerToMoc] = currentMoc;
+ includedMocs[headerToMoc] = MocPathIncluderRel ( absFilename, currentMoc );
if (basename == scannedFileBasename)
{
mocUnderscoreIncluded = true;
@@ -826,7 +829,7 @@ void cmQtAutoGenerators::ParseCppFile(const std::string& absFilename,
dotMocIncluded = true;
ownDotMocFile = currentMoc;
}
- includedMocs[fileToMoc] = currentMoc;
+ includedMocs[fileToMoc] = MocPathIncluderRel ( absFilename, currentMoc );
}
matchOffset += mocIncludeRegExp.end();
} while(mocIncludeRegExp.find(contentsString.c_str() + matchOffset));
@@ -851,7 +854,7 @@ void cmQtAutoGenerators::ParseCppFile(const std::string& absFilename,
<< scannedFileBasename << ".moc\" for compatibility with "
"strict mode (see CMAKE_AUTOMOC_RELAXED_MODE).\n"
<< std::endl;
- includedMocs[absFilename] = ownMocUnderscoreFile;
+ includedMocs[absFilename] = MocPathIncluderRel ( absFilename, ownMocUnderscoreFile );
includedMocs.erase(ownMocHeaderFile);
}
else
@@ -930,7 +933,7 @@ void cmQtAutoGenerators::StrictParseCppFile(const std::string& absFilename,
if (!headerToMoc.empty())
{
- includedMocs[headerToMoc] = currentMoc;
+ includedMocs[headerToMoc] = MocPathIncluderRel ( absFilename, currentMoc );
}
else
{
@@ -964,7 +967,7 @@ void cmQtAutoGenerators::StrictParseCppFile(const std::string& absFilename,
::exit(EXIT_FAILURE);
}
dotMocIncluded = true;
- includedMocs[absFilename] = currentMoc;
+ includedMocs[absFilename] = MocPathIncluderRel ( absFilename, currentMoc );
}
matchOffset += mocIncludeRegExp.end();
} while(mocIncludeRegExp.find(contentsString.c_str() + matchOffset));
@@ -1104,15 +1107,14 @@ void cmQtAutoGenerators::ParseHeaders(const std::set<std::string>& absHeaders,
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;
if (requiresMocing(contents, macroName))
{
//std::cout << "header contains Q_OBJECT macro";
- notIncludedMocs[headerName] = currentMoc;
+ const std::string basename = cmsys::SystemTools::
+ GetFilenameWithoutLastExtension(headerName);
+ const std::string currentMoc = "moc_" + basename + ".cpp";
+ notIncludedMocs[headerName] = MocPathIncluderRel ( headerName, currentMoc );
}
}
this->ParseForUic(headerName, contents, includedUis);
@@ -1122,7 +1124,10 @@ void cmQtAutoGenerators::ParseHeaders(const std::set<std::string>& absHeaders,
bool cmQtAutoGenerators::GenerateMoc(const std::string& sourceFile,
const std::string& mocFileName)
{
- const std::string mocFilePath = this->Builddir + mocFileName;
+ //std::cout << "GenerateMoc: sourceFile " << sourceFile << std::endl;
+ //std::cout << "GenerateMoc: mocFileName " << mocFileName << std::endl;
+ const std::string mocFileRel = this->MocPathBuildRel ( mocFileName );
+ const std::string mocFilePath = this->Builddir + mocFileRel;
int sourceNewerThanMoc = 0;
bool success = cmsys::SystemTools::FileTimeCompare(sourceFile,
mocFilePath,
@@ -1137,7 +1142,7 @@ bool cmQtAutoGenerators::GenerateMoc(const std::string& sourceFile,
}
std::string msg = "Generating ";
- msg += mocFileName;
+ msg += mocFileRel;
cmSystemTools::MakefileColorEcho(cmsysTerminal_Color_ForegroundBlue
|cmsysTerminal_Color_ForegroundBold,
msg.c_str(), true, this->ColorOutput);
@@ -1347,6 +1352,77 @@ bool cmQtAutoGenerators::GenerateQrc()
return true;
}
+/**
+ * Checks if headerName file is below ProjectSource or ProjectBinary
+ * and calculates the relative path plus mocFile
+ */
+std::string cmQtAutoGenerators::MocPathIncluderRel(const std::string & headerName,
+ const std::string & mocFile)
+{
+ //std::cout << "MocPathIncluderRel: headerName " << headerName << std::endl;
+ //std::cout << "MocPathIncluderRel: mocFile " << mocFile << std::endl;
+
+ std::string headerDirectory;
+
+ // headerName comes with symlinks removed but this->ProjectSourceDir and
+ // this->ProjectBinaryDir may still contain symlinks
+ {
+ bool match ( false );
+ ::std::string test_dirs[4];
+ test_dirs[0] = cmsys::SystemTools::
+ GetRealPath( this->Srcdir );
+ test_dirs[1] = cmsys::SystemTools::
+ GetRealPath( this->Builddir );
+ test_dirs[2] = cmsys::SystemTools::
+ GetRealPath( this->ProjectSourceDir );
+ test_dirs[3] = cmsys::SystemTools::
+ GetRealPath( this->ProjectBinaryDir );
+
+ // Test if the header is child to any of the known directories
+ for ( int ii=0; ii != sizeof ( test_dirs ) / sizeof ( ::std::string ); ++ii )
+ {
+ ::std::string & testDir ( test_dirs[ii] );
+ if (cmsys::SystemTools::IsSubDirectory(headerName,
+ testDir) )
+ {
+ match = true;
+ headerDirectory = testDir;
+ break;
+ }
+ }
+ // Use root as fallback parent directory
+ if ( !match )
+ {
+ cmsys::SystemTools::SplitPathRootComponent(headerName,
+ &headerDirectory);
+ }
+ }
+
+ headerDirectory = cmsys::SystemTools::RelativePath(
+ headerDirectory, cmsys::SystemTools::GetParentDirectory(headerName));
+
+ std::string path = headerDirectory;
+ if (!path.empty())
+ {
+ path += "/";
+ }
+ path += mocFile;
+ cmSystemTools::ReplaceString(path, "..", "__");
+ //std::cout << "MocPathIncluderRel: path " << path << std::endl;
+ return path;
+}
+
+std::string cmQtAutoGenerators::MocPathBuildRel(const std::string & mocFile)
+{
+ std::string path ( this->OutMocDirname );
+ if (!path.empty())
+ {
+ path += "/";
+ }
+ path += mocFile;
+ return path;
+}
+
std::string cmQtAutoGenerators::Join(const std::vector<std::string>& lst,
char separator)
{
diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGenerators.h
index ab7b6ed..b7af2cb 100644
--- a/Source/cmQtAutoGenerators.h
+++ b/Source/cmQtAutoGenerators.h
@@ -73,6 +73,8 @@ private:
bool EndsWith(const std::string& str, const std::string& with);
bool StartsWith(const std::string& str, const std::string& with);
+ std::string MocPathIncluderRel(const std::string & headerName, const std::string & mocFile);
+ std::string MocPathBuildRel(const std::string & mocFile);
static void MergeUicOptions(std::vector<std::string> &opts,
const std::vector<std::string> &fileOpts, bool isQt5);
@@ -102,6 +104,7 @@ private:
std::string OldCompileSettingsStr;
std::string OutMocCppFilename;
+ std::string OutMocDirname;
std::list<std::string> MocIncludes;
std::list<std::string> MocDefinitions;
std::vector<std::string> MocOptions;
--
2.8.0.rc3
--
Powered by www.kitware.com
Please keep messages on-topic and check the CMake FAQ at:
http://www.cmake.org/Wiki/CMake_FAQ
Kitware offers various services to support the CMake community. For more
information on each offering, please visit:
CMake Support: http://cmake.org/cmake/help/support.html
CMake Consulting: http://cmake.org/cmake/help/consulting.html
CMake Training Courses: http://cmake.org/cmake/help/training.html
Visit other Kitware open-source projects at
http://www.kitware.com/opensource/opensource.html
Follow this link to subscribe/unsubscribe:
http://public.kitware.com/mailman/listinfo/cmake-developers