From 1cdf7c1be24f87e2854204aa5bc7de4dc22af1a3 Mon Sep 17 00:00:00 2001 From: Sebastian Holtermann Date: Thu, 23 Feb 2017 19:35:48 +0100 Subject: Autogen: Add AUTOUIC_SEARCH_PATHS support Closes #15227 --- Modules/AutogenInfo.cmake.in | 1 + Source/cmQtAutoGeneratorInitializer.cxx | 13 +++ Source/cmQtAutoGenerators.cxx | 138 ++++++++++++++++++++------------ Source/cmQtAutoGenerators.h | 3 + Source/cmTarget.cxx | 1 + 5 files changed, 107 insertions(+), 49 deletions(-) diff --git a/Modules/AutogenInfo.cmake.in b/Modules/AutogenInfo.cmake.in index fc5024f..f8ffe91 100644 --- a/Modules/AutogenInfo.cmake.in +++ b/Modules/AutogenInfo.cmake.in @@ -26,6 +26,7 @@ set(AM_UIC_SKIP @_uic_skip@) set(AM_UIC_TARGET_OPTIONS @_uic_target_options@) set(AM_UIC_OPTIONS_FILES @_qt_uic_options_files@) set(AM_UIC_OPTIONS_OPTIONS @_qt_uic_options_options@) +set(AM_UIC_SEARCH_PATHS @_uic_search_paths@) # RCC settings set(AM_RCC_SOURCES @_rcc_files@ ) set(AM_RCC_INPUTS @_rcc_inputs@) diff --git a/Source/cmQtAutoGeneratorInitializer.cxx b/Source/cmQtAutoGeneratorInitializer.cxx index de18265..5460f73 100644 --- a/Source/cmQtAutoGeneratorInitializer.cxx +++ b/Source/cmQtAutoGeneratorInitializer.cxx @@ -306,6 +306,19 @@ static void UicSetupAutoTarget( AddDefinitionEscaped(makefile, "_uic_skip", uicSkipList); + // Uic search paths + { + std::vector uicSearchPaths; + cmSystemTools::ExpandListArgument( + GetSafeProperty(target, "AUTOUIC_SEARCH_PATHS"), uicSearchPaths); + const std::string srcDir = makefile->GetCurrentSourceDirectory(); + for (std::vector::iterator it = uicSearchPaths.begin(); + it != uicSearchPaths.end(); ++it) { + *it = cmSystemTools::CollapseFullPath(*it, srcDir); + } + AddDefinitionEscaped(makefile, "_uic_search_paths", uicSearchPaths); + } + // Uic target options { std::string _uic_opts; diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index ea7fe0f..d9e95ff 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -412,19 +412,23 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile( makefile->GetSafeDefinition("AM_UIC_OPTIONS_FILES"), uicFilesVec); cmSystemTools::ExpandListArgument( makefile->GetSafeDefinition("AM_UIC_OPTIONS_OPTIONS"), uicOptionsVec); - if (uicFilesVec.size() != uicOptionsVec.size()) { + // Compare list sizes + if (uicFilesVec.size() == uicOptionsVec.size()) { + for (std::vector::iterator fileIt = uicFilesVec.begin(), + optionIt = uicOptionsVec.begin(); + fileIt != uicFilesVec.end(); ++fileIt, ++optionIt) { + cmSystemTools::ReplaceString(*optionIt, "@list_sep@", ";"); + this->UicOptions[*fileIt] = *optionIt; + } + } else { this->LogError( "AutoGen: Error: Uic files/options lists size missmatch in: " + filename); return false; } - for (std::vector::iterator fileIt = uicFilesVec.begin(), - optionIt = uicOptionsVec.begin(); - fileIt != uicFilesVec.end(); ++fileIt, ++optionIt) { - cmSystemTools::ReplaceString(*optionIt, "@list_sep@", ";"); - this->UicOptions[*fileIt] = *optionIt; - } } + cmSystemTools::ExpandListArgument( + makefile->GetSafeDefinition("AM_UIC_SEARCH_PATHS"), this->UicSearchPaths); // - Rcc cmSystemTools::ExpandListArgument( @@ -831,12 +835,7 @@ void cmQtAutoGenerators::UicParseContent( const char* contentChars = contentText.c_str(); if (strstr(contentChars, "ui_") != CM_NULLPTR) { while (this->RegExpUicInclude.find(contentChars)) { - const std::string currentUi = this->RegExpUicInclude.match(1); - const std::string basename = - cmsys::SystemTools::GetFilenameWithoutLastExtension(currentUi); - // basename should be the part of the ui filename used for - // finding the correct header, so we need to remove the ui_ part - uisIncluded[absFilename].push_back(basename.substr(3)); + uisIncluded[absFilename].push_back(this->RegExpUicInclude.match(1)); contentChars += this->RegExpUicInclude.end(); } } @@ -1325,6 +1324,36 @@ bool cmQtAutoGenerators::MocGenerateFile( return mocGenerated; } +bool cmQtAutoGenerators::UicFindIncludedFile(std::string& absFile, + const std::string& sourceFile, + const std::string& includeString) +{ + bool success = false; + // Search in vicinity of the source + { + std::string testPath = subDirPrefix(sourceFile); + testPath += includeString; + if (cmsys::SystemTools::FileExists(testPath.c_str())) { + absFile = cmsys::SystemTools::GetRealPath(testPath); + success = true; + } + } + // Search in include directories + if (!success) { + for (std::vector::const_iterator iit = + this->UicSearchPaths.begin(); + iit != this->UicSearchPaths.end(); ++iit) { + const std::string fullPath = ((*iit) + '/' + includeString); + if (cmsys::SystemTools::FileExists(fullPath.c_str())) { + absFile = cmsys::SystemTools::GetRealPath(fullPath); + success = true; + break; + } + } + } + return success; +} + bool cmQtAutoGenerators::UicGenerateAll( const std::map >& uisIncluded) { @@ -1333,46 +1362,57 @@ bool cmQtAutoGenerators::UicGenerateAll( } // single map with input / output names - std::map > uiGenMap; - std::map testMap; - for (std::map >::const_iterator it = - uisIncluded.begin(); - it != uisIncluded.end(); ++it) { - // source file path - std::string sourcePath = cmsys::SystemTools::GetFilenamePath(it->first); - sourcePath += '/'; - // insert new map for source file an use new reference - uiGenMap[it->first] = std::map(); - std::map& sourceMap = uiGenMap[it->first]; - for (std::vector::const_iterator sit = it->second.begin(); - sit != it->second.end(); ++sit) { - const std::string& uiFileName = *sit; - const std::string uiInputFile = sourcePath + uiFileName + ".ui"; - const std::string uiOutputFile = "ui_" + uiFileName + ".h"; - sourceMap[uiInputFile] = uiOutputFile; - testMap[uiInputFile] = uiOutputFile; - } - } - - // look for name collisions + std::map > sourceGenMap; { - std::multimap collisions; - if (this->NameCollisionTest(testMap, collisions)) { - std::ostringstream ost; - ost << "AutoUic: Error: The same ui_NAME.h file will be generated " - "from different sources.\n" - "To avoid this error rename the source files.\n"; - this->LogErrorNameCollision(ost.str(), collisions); - return false; + // Collision lookup map + std::map testMap; + // Compile maps + for (std::map >::const_iterator sit = + uisIncluded.begin(); + sit != uisIncluded.end(); ++sit) { + const std::string& source(sit->first); + const std::vector& sourceIncs(sit->second); + // insert new source/destination map + std::map& uiGenMap = sourceGenMap[source]; + for (std::vector::const_iterator uit = sourceIncs.begin(); + uit != sourceIncs.end(); ++uit) { + // Remove ui_ from the begin filename by substr() + const std::string uiBasePath = subDirPrefix(*uit); + const std::string uiBaseName = + cmsys::SystemTools::GetFilenameWithoutLastExtension(*uit).substr(3); + const std::string searchFileName = uiBasePath + uiBaseName + ".ui"; + std::string uiInputFile; + if (UicFindIncludedFile(uiInputFile, source, searchFileName)) { + std::string uiOutputFile = uiBasePath + "ui_" + uiBaseName + ".h"; + cmSystemTools::ReplaceString(uiOutputFile, "..", "__"); + uiGenMap[uiInputFile] = uiOutputFile; + testMap[uiInputFile] = uiOutputFile; + } else { + this->LogError("AutoUic: Error: " + Quoted(sit->first) + + "\nCould not find " + Quoted(searchFileName)); + return false; + } + } + } + // look for name collisions + { + std::multimap collisions; + if (this->NameCollisionTest(testMap, collisions)) { + std::ostringstream ost; + ost << "AutoUic: Error: The same ui_NAME.h file will be generated " + "from different sources.\n" + "To avoid this error rename the source files.\n"; + this->LogErrorNameCollision(ost.str(), collisions); + return false; + } } } - testMap.clear(); // generate ui files for (std::map >::const_iterator it = - uiGenMap.begin(); - it != uiGenMap.end(); ++it) { + sourceGenMap.begin(); + it != sourceGenMap.end(); ++it) { for (std::map::const_iterator sit = it->second.begin(); sit != it->second.end(); ++sit) { @@ -1415,15 +1455,15 @@ bool cmQtAutoGenerators::UicGenerateFile(const std::string& realName, std::vector cmd; cmd.push_back(this->UicExecutable); { - std::vector opts = this->UicTargetOptions; + std::vector allOpts = this->UicTargetOptions; std::map::const_iterator optionIt = this->UicOptions.find(uiInputFile); if (optionIt != this->UicOptions.end()) { std::vector fileOpts; cmSystemTools::ExpandListArgument(optionIt->second, fileOpts); - UicMergeOptions(opts, fileOpts, (this->QtMajorVersion == "5")); + UicMergeOptions(allOpts, fileOpts, (this->QtMajorVersion == "5")); } - cmd.insert(cmd.end(), opts.begin(), opts.end()); + cmd.insert(cmd.end(), allOpts.begin(), allOpts.end()); } cmd.push_back("-o"); cmd.push_back(uicFileAbs); diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGenerators.h index f9b9083..46c86ff 100644 --- a/Source/cmQtAutoGenerators.h +++ b/Source/cmQtAutoGenerators.h @@ -111,6 +111,8 @@ private: const std::map >& mocDepends); // - Uic file generation + bool UicFindIncludedFile(std::string& absFile, const std::string& sourceFile, + const std::string& includeString); bool UicGenerateAll( const std::map >& includedUis); bool UicGenerateFile(const std::string& realName, @@ -184,6 +186,7 @@ private: std::vector UicSkipList; std::vector UicTargetOptions; std::map UicOptions; + std::vector UicSearchPaths; // - Rcc std::vector RccSources; std::map RccOptions; diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 0f3d91b..c360c19 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -248,6 +248,7 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, this->SetPropertyDefault("AUTOMOC_DEPEND_FILTERS", CM_NULLPTR); this->SetPropertyDefault("AUTOMOC_MOC_OPTIONS", CM_NULLPTR); this->SetPropertyDefault("AUTOUIC_OPTIONS", CM_NULLPTR); + this->SetPropertyDefault("AUTOUIC_SEARCH_PATHS", CM_NULLPTR); this->SetPropertyDefault("AUTORCC_OPTIONS", CM_NULLPTR); this->SetPropertyDefault("LINK_DEPENDS_NO_SHARED", CM_NULLPTR); this->SetPropertyDefault("LINK_INTERFACE_LIBRARIES", CM_NULLPTR); -- cgit v0.12