Hi, 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. For the attached test case you end up with foo_automoc.cpp -- As before but includes sources below foo_automoc.dir/data/moc_item.cpp foo_automoc.dir/view/moc_item.cpp foo_automoc.dir/item.cpp This solves the same output moc problem. What remains though is that including "moc_foo.cpp" does not work because of missing INCLUDE_DIRECTORIES. Kind regards, Sebastian Holtermann
>From cf51dcf0af4744fbb40e3bb5ad253d2514325148 Mon Sep 17 00:00:00 2001 From: Sebastian Holtermann <sebh...@xwmw.org> Date: Tue, 12 Apr 2016 10:47:49 +0200 Subject: [PATCH] Automoc: Create moc files below foo_automoc.dir with respect to the source header project relative path --- Source/cmQtAutoGenerators.cxx | 90 ++++++++++++++++++++++++++++++++++++------- Source/cmQtAutoGenerators.h | 3 ++ 2 files changed, 80 insertions(+), 13 deletions(-) diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index ebe08b0..69b1e3d 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,11 @@ 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 mocFilePath = this->Builddir + mocFileName; + 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 +1143,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 +1353,64 @@ 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 + ::std::string source_dir_abs = cmsys::SystemTools:: + GetRealPath( this->ProjectSourceDir ); + ::std::string project_dir_abs = cmsys::SystemTools:: + GetRealPath( this->ProjectBinaryDir ); + + if (cmsys::SystemTools::IsSubDirectory(headerName, + source_dir_abs) ) + { + headerDirectory = source_dir_abs; + } + else if (cmsys::SystemTools::IsSubDirectory(headerName, + project_dir_abs) ) + { + headerDirectory = project_dir_abs; + } + else + { + cmsys::SystemTools::SplitPathRootComponent(headerName, + &headerDirectory); + } + headerDirectory = cmsys::SystemTools::RelativePath( + headerDirectory, cmsys::SystemTools::GetParentDirectory(headerName)); + + std::string path = headerDirectory; + if (!path.empty()) + { + path += "/"; + } + path += mocFile; + 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
cmake_automoc_test-2016-04-12-1.tar.gz
Description: application/gzip
-- 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