diff options
author | Brad King <brad.king@kitware.com> | 2017-03-02 14:26:13 (GMT) |
---|---|---|
committer | CMake Topic Stage <kwrobot@kitware.com> | 2017-03-02 14:26:13 (GMT) |
commit | c1fb7213edaf512774eb74adb0a89b4984f88904 (patch) | |
tree | 98b0418a4773c045e257d20eac411db6be200c01 | |
parent | 6c332bd84ce320e4163130a052af7b9950b38318 (diff) | |
parent | 3bf28f5ed057b2fe4d90c601065188055bb052a1 (diff) | |
download | CMake-c1fb7213edaf512774eb74adb0a89b4984f88904.zip CMake-c1fb7213edaf512774eb74adb0a89b4984f88904.tar.gz CMake-c1fb7213edaf512774eb74adb0a89b4984f88904.tar.bz2 |
Merge topic 'autogen_uic_paths'
3bf28f5e Autogen: New short InfoGet functions
154d8339 Autogen: Parse enabled feature configuration only
ac77fa35 Autogen: Add missing return on error
662ad240 Autogen: Rename and merge moc related methods
5adf22bb Autogen: Add AUTOUIC_SEARCH_PATHS release notes
36fa535d Autogen: Add AUTOUIC_SEARCH_PATHS documentation
6d7c02db Autogen: Add AUTOUIC_SEARCH_PATHS test
1cdf7c1b Autogen: Add AUTOUIC_SEARCH_PATHS support
110c1bf4 Autogen: Add subDirPrefix function
db431ecf Autogen: Merge FindInIncludeDirectories into FindIncludeFile
-rw-r--r-- | Help/manual/cmake-properties.7.rst | 1 | ||||
-rw-r--r-- | Help/manual/cmake-qt.7.rst | 4 | ||||
-rw-r--r-- | Help/manual/cmake-variables.7.rst | 1 | ||||
-rw-r--r-- | Help/prop_tgt/AUTOUIC.rst | 9 | ||||
-rw-r--r-- | Help/prop_tgt/AUTOUIC_OPTIONS.rst | 2 | ||||
-rw-r--r-- | Help/prop_tgt/AUTOUIC_SEARCH_PATHS.rst | 12 | ||||
-rw-r--r-- | Help/release/dev/Autogen_uic_paths.rst | 10 | ||||
-rw-r--r-- | Help/variable/CMAKE_AUTOUIC_SEARCH_PATHS.rst | 11 | ||||
-rw-r--r-- | Modules/AutogenInfo.cmake.in | 3 | ||||
-rw-r--r-- | Source/cmQtAutoGeneratorInitializer.cxx | 15 | ||||
-rw-r--r-- | Source/cmQtAutoGenerators.cxx | 516 | ||||
-rw-r--r-- | Source/cmQtAutoGenerators.h | 18 | ||||
-rw-r--r-- | Source/cmTarget.cxx | 1 | ||||
-rw-r--r-- | Tests/QtAutogen/CMakeLists.txt | 4 | ||||
-rw-r--r-- | Tests/QtAutogen/uicInclude/CMakeLists.txt | 8 | ||||
-rw-r--r-- | Tests/QtAutogen/uicInclude/PageC.ui | 24 | ||||
-rw-r--r-- | Tests/QtAutogen/uicInclude/dirA/PageA.ui | 24 | ||||
-rw-r--r-- | Tests/QtAutogen/uicInclude/dirB/sub/PageB.ui | 24 | ||||
-rw-r--r-- | Tests/QtAutogen/uicInclude/main.cpp | 10 | ||||
-rw-r--r-- | Tests/QtAutogen/uicInclude/main.hpp | 6 |
20 files changed, 440 insertions, 263 deletions
diff --git a/Help/manual/cmake-properties.7.rst b/Help/manual/cmake-properties.7.rst index 58dda2b..5bd6365 100644 --- a/Help/manual/cmake-properties.7.rst +++ b/Help/manual/cmake-properties.7.rst @@ -121,6 +121,7 @@ Properties on Targets /prop_tgt/AUTOMOC /prop_tgt/AUTOUIC /prop_tgt/AUTOUIC_OPTIONS + /prop_tgt/AUTOUIC_SEARCH_PATHS /prop_tgt/AUTORCC /prop_tgt/AUTORCC_OPTIONS /prop_tgt/BINARY_DIR diff --git a/Help/manual/cmake-qt.7.rst b/Help/manual/cmake-qt.7.rst index 3b9931e..3b95b05 100644 --- a/Help/manual/cmake-qt.7.rst +++ b/Help/manual/cmake-qt.7.rst @@ -104,7 +104,9 @@ be run, and to create rules to execute ``uic`` at the appropriate time. If a preprocessor ``#include`` directive is found which matches ``ui_<basename>.h``, and a ``<basename>.ui`` file exists, then ``uic`` will -be executed to generate the appropriate file. +be executed to generate the appropriate file. The ``<basename>.ui`` file is +searched for first in the vicinity of including file and afterwards in the +optional :prop_tgt:`AUTOUIC_SEARCH_PATHS` of the target. The generated generated ``ui_*.h`` files are placed in the ``<CMAKE_CURRENT_BINARY_DIR>/<TARGETNAME>_autogen/include`` directory which is diff --git a/Help/manual/cmake-variables.7.rst b/Help/manual/cmake-variables.7.rst index a25efe7..79c7cd8 100644 --- a/Help/manual/cmake-variables.7.rst +++ b/Help/manual/cmake-variables.7.rst @@ -264,6 +264,7 @@ Variables that Control the Build /variable/CMAKE_AUTORCC_OPTIONS /variable/CMAKE_AUTOUIC /variable/CMAKE_AUTOUIC_OPTIONS + /variable/CMAKE_AUTOUIC_SEARCH_PATHS /variable/CMAKE_BUILD_RPATH /variable/CMAKE_BUILD_WITH_INSTALL_NAME_DIR /variable/CMAKE_BUILD_WITH_INSTALL_RPATH diff --git a/Help/prop_tgt/AUTOUIC.rst b/Help/prop_tgt/AUTOUIC.rst index fbf24c3..91d95e5 100644 --- a/Help/prop_tgt/AUTOUIC.rst +++ b/Help/prop_tgt/AUTOUIC.rst @@ -10,8 +10,13 @@ Qt4 and Qt5 are supported. When this property is ``ON``, CMake will scan the source files at build time and invoke ``uic`` accordingly. If an ``#include`` statement like -``#include "ui_foo.h"`` is found in ``foo.cpp``, a ``foo.ui`` file is -expected next to ``foo.cpp``, and ``uic`` is run on the ``foo.ui`` file. +``#include "ui_foo.h"`` is found in ``source.cpp``, a ``foo.ui`` file is +searched for first in the vicinity of ``source.cpp`` and afterwards in the +optional :prop_tgt:`AUTOUIC_SEARCH_PATHS` of the target. +``uic`` is run on the ``foo.ui`` file to generate ``ui_foo.h`` in the directory +``<CMAKE_CURRENT_BINARY_DIR>/<TARGETNAME>_autogen/include``, +which is added to the target's :prop_tgt:`INCLUDE_DIRECTORIES` automatically. + This property is initialized by the value of the :variable:`CMAKE_AUTOUIC` variable if it is set when a target is created. diff --git a/Help/prop_tgt/AUTOUIC_OPTIONS.rst b/Help/prop_tgt/AUTOUIC_OPTIONS.rst index dc3bee5..9fb042e 100644 --- a/Help/prop_tgt/AUTOUIC_OPTIONS.rst +++ b/Help/prop_tgt/AUTOUIC_OPTIONS.rst @@ -1,7 +1,7 @@ AUTOUIC_OPTIONS --------------- -Additional options for uic when using :prop_tgt:`AUTOUIC` +Additional options for ``uic`` when using :prop_tgt:`AUTOUIC` This property holds additional command line options which will be used when ``uic`` is executed during the build via :prop_tgt:`AUTOUIC`, i.e. it is diff --git a/Help/prop_tgt/AUTOUIC_SEARCH_PATHS.rst b/Help/prop_tgt/AUTOUIC_SEARCH_PATHS.rst new file mode 100644 index 0000000..96d9f89 --- /dev/null +++ b/Help/prop_tgt/AUTOUIC_SEARCH_PATHS.rst @@ -0,0 +1,12 @@ +AUTOUIC_SEARCH_PATHS +-------------------- + +Search path list used by :prop_tgt:`AUTOUIC` to find included +``.ui`` files. + +This property is initialized by the value of the +:variable:`CMAKE_AUTOUIC_SEARCH_PATHS` variable if it is set +when a target is created. Otherwise it is empty. + +See the :manual:`cmake-qt(7)` manual for more information on using CMake +with Qt. diff --git a/Help/release/dev/Autogen_uic_paths.rst b/Help/release/dev/Autogen_uic_paths.rst new file mode 100644 index 0000000..0893194 --- /dev/null +++ b/Help/release/dev/Autogen_uic_paths.rst @@ -0,0 +1,10 @@ +AutoGen uic paths +----------------- + +* Variable :variable:`CMAKE_AUTOUIC_SEARCH_PATHS` was introduced to + allow :variable:`CMAKE_AUTOUIC` to search for ``foo.ui`` in more + places than the vicinity of the ``ui_foo.h`` including file. + +* The new target property :prop_tgt:`AUTOUIC_SEARCH_PATHS` was introduced to + allow :prop_tgt:`AUTOUIC` to search for ``foo.ui`` in more + places than the vicinity of the ``ui_foo.h`` including file. diff --git a/Help/variable/CMAKE_AUTOUIC_SEARCH_PATHS.rst b/Help/variable/CMAKE_AUTOUIC_SEARCH_PATHS.rst new file mode 100644 index 0000000..aa132bf --- /dev/null +++ b/Help/variable/CMAKE_AUTOUIC_SEARCH_PATHS.rst @@ -0,0 +1,11 @@ +CMAKE_AUTOUIC_SEARCH_PATHS +-------------------------- + +Search path list used by :variable:`CMAKE_AUTOUIC` to find included +``.ui`` files. + +This variable is used to initialize the :prop_tgt:`AUTOUIC_SEARCH_PATHS` +property on all the targets. See that target property for additional +information. + +By default it is empty. diff --git a/Modules/AutogenInfo.cmake.in b/Modules/AutogenInfo.cmake.in index fc5024f..fcecb6c 100644 --- a/Modules/AutogenInfo.cmake.in +++ b/Modules/AutogenInfo.cmake.in @@ -16,7 +16,7 @@ set(AM_QT_UIC_EXECUTABLE @_qt_uic_executable@) set(AM_QT_RCC_EXECUTABLE @_qt_rcc_executable@) # MOC settings set(AM_MOC_SKIP @_moc_skip@) -set(AM_MOC_COMPILE_DEFINITIONS @_moc_compile_defs@) +set(AM_MOC_DEFINITIONS @_moc_compile_defs@) set(AM_MOC_INCLUDES @_moc_incs@) set(AM_MOC_OPTIONS @_moc_options@) set(AM_MOC_RELAXED_MODE @_moc_relaxed_mode@) @@ -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..a45b3d5 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<std::string> uicSearchPaths; + cmSystemTools::ExpandListArgument( + GetSafeProperty(target, "AUTOUIC_SEARCH_PATHS"), uicSearchPaths); + const std::string srcDir = makefile->GetCurrentSourceDirectory(); + for (std::vector<std::string>::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; @@ -959,7 +972,7 @@ void cmQtAutoGeneratorInitializer::SetupAutoGenerateTarget( it = configMocDefines.begin(), end = configMocDefines.end(); it != end; ++it) { - infoFile << "set(AM_MOC_COMPILE_DEFINITIONS_" << it->first << " " + infoFile << "set(AM_MOC_DEFINITIONS_" << it->first << " " << it->second << ")\n"; } } diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index e7e456a..c83f9a9 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -55,20 +55,38 @@ static std::string Quoted(const std::string& text) return res; } -static std::string GetConfigDefinition(cmMakefile* makefile, - const std::string& key, - const std::string& config) +static void InfoGet(cmMakefile* makefile, const char* key, std::string& value) { - std::string keyConf = key; - if (!config.empty()) { - keyConf += "_"; - keyConf += config; + value = makefile->GetSafeDefinition(key); +} + +static void InfoGet(cmMakefile* makefile, const char* key, bool& value) +{ + value = makefile->IsOn(key); +} + +static void InfoGet(cmMakefile* makefile, const char* key, + std::vector<std::string>& list) +{ + cmSystemTools::ExpandListArgument(makefile->GetSafeDefinition(key), list); +} + +static void InfoGet(cmMakefile* makefile, const char* key, + const std::string& config, std::vector<std::string>& list) +{ + const char* valueConf = CM_NULLPTR; + { + std::string keyConf = key; + if (!config.empty()) { + keyConf += "_"; + keyConf += config; + } + valueConf = makefile->GetDefinition(keyConf); } - const char* valueConf = makefile->GetDefinition(keyConf); - if (valueConf != CM_NULLPTR) { - return valueConf; + if (valueConf == CM_NULLPTR) { + valueConf = makefile->GetSafeDefinition(key); } - return makefile->GetSafeDefinition(key); + cmSystemTools::ExpandListArgument(valueConf, list); } static std::string SettingsFile(const std::string& targetDirectory) @@ -94,6 +112,15 @@ static void SettingWrite(std::ostream& ostr, const char* key, } } +std::string subDirPrefix(const std::string& fileName) +{ + std::string res(cmsys::SystemTools::GetFilenamePath(fileName)); + if (!res.empty()) { + res += '/'; + } + return res; +} + static bool FileNameIsUnique(const std::string& filePath, const std::map<std::string, std::string>& fileMap) { @@ -319,24 +346,27 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile( } // - Target names - this->OriginTargetName = - makefile->GetSafeDefinition("AM_ORIGIN_TARGET_NAME"); - this->AutogenTargetName = makefile->GetSafeDefinition("AM_TARGET_NAME"); - - // - Directories - this->ProjectSourceDir = makefile->GetSafeDefinition("AM_CMAKE_SOURCE_DIR"); - this->ProjectBinaryDir = makefile->GetSafeDefinition("AM_CMAKE_BINARY_DIR"); - this->CurrentSourceDir = - makefile->GetSafeDefinition("AM_CMAKE_CURRENT_SOURCE_DIR"); - this->CurrentBinaryDir = - makefile->GetSafeDefinition("AM_CMAKE_CURRENT_BINARY_DIR"); + InfoGet(makefile, "AM_TARGET_NAME", this->AutogenTargetName); + InfoGet(makefile, "AM_ORIGIN_TARGET_NAME", this->OriginTargetName); + + // - Files and directories + InfoGet(makefile, "AM_CMAKE_SOURCE_DIR", this->ProjectSourceDir); + InfoGet(makefile, "AM_CMAKE_BINARY_DIR", this->ProjectBinaryDir); + InfoGet(makefile, "AM_CMAKE_CURRENT_SOURCE_DIR", this->CurrentSourceDir); + InfoGet(makefile, "AM_CMAKE_CURRENT_BINARY_DIR", this->CurrentBinaryDir); + InfoGet(makefile, "AM_CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE", + this->IncludeProjectDirsBefore); + InfoGet(makefile, "AM_SOURCES", this->Sources); + InfoGet(makefile, "AM_HEADERS", this->Headers); // - Qt environment - this->QtMajorVersion = makefile->GetSafeDefinition("AM_QT_VERSION_MAJOR"); - if (this->QtMajorVersion == "") { - this->QtMajorVersion = - makefile->GetSafeDefinition("AM_Qt5Core_VERSION_MAJOR"); + InfoGet(makefile, "AM_QT_VERSION_MAJOR", this->QtMajorVersion); + if (this->QtMajorVersion.empty()) { + InfoGet(makefile, "AM_Qt5Core_VERSION_MAJOR", this->QtMajorVersion); } + InfoGet(makefile, "AM_QT_MOC_EXECUTABLE", this->MocExecutable); + InfoGet(makefile, "AM_QT_UIC_EXECUTABLE", this->UicExecutable); + InfoGet(makefile, "AM_QT_RCC_EXECUTABLE", this->RccExecutable); // Check Qt version if ((this->QtMajorVersion != "4") && (this->QtMajorVersion != "5")) { this->LogError("AutoGen: Error: Unsupported Qt version: " + @@ -344,132 +374,115 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile( return false; } - this->MocExecutable = makefile->GetSafeDefinition("AM_QT_MOC_EXECUTABLE"); - this->UicExecutable = makefile->GetSafeDefinition("AM_QT_UIC_EXECUTABLE"); - this->RccExecutable = makefile->GetSafeDefinition("AM_QT_RCC_EXECUTABLE"); - - // - File Lists - cmSystemTools::ExpandListArgument(makefile->GetSafeDefinition("AM_SOURCES"), - this->Sources); - cmSystemTools::ExpandListArgument(makefile->GetSafeDefinition("AM_HEADERS"), - this->Headers); - // - Moc - cmSystemTools::ExpandListArgument(makefile->GetSafeDefinition("AM_MOC_SKIP"), - this->MocSkipList); - cmSystemTools::ExpandListArgument( - GetConfigDefinition(makefile, "AM_MOC_COMPILE_DEFINITIONS", config), - this->MocDefinitions); - cmSystemTools::ExpandListArgument( - GetConfigDefinition(makefile, "AM_MOC_INCLUDES", config), - this->MocIncludePaths); - cmSystemTools::ExpandListArgument( - makefile->GetSafeDefinition("AM_MOC_OPTIONS"), this->MocOptions); - { - std::vector<std::string> mocDependFilters; - cmSystemTools::ExpandListArgument( - makefile->GetSafeDefinition("AM_MOC_DEPEND_FILTERS"), mocDependFilters); - // Insert Q_PLUGIN_METADATA dependency filter - if (this->QtMajorVersion != "4") { - this->MocDependFilterPush("Q_PLUGIN_METADATA", - "[\n][ \t]*Q_PLUGIN_METADATA[ \t]*\\(" - "[^\\)]*FILE[ \t]*\"([^\"]+)\""); - } - // Insert user defined dependency filters - if ((mocDependFilters.size() % 2) == 0) { - for (std::vector<std::string>::const_iterator dit = - mocDependFilters.begin(); - dit != mocDependFilters.end(); dit += 2) { - if (!this->MocDependFilterPush(*dit, *(dit + 1))) { - return false; + if (this->MocEnabled()) { + InfoGet(makefile, "AM_MOC_SKIP", this->MocSkipList); + InfoGet(makefile, "AM_MOC_DEFINITIONS", config, this->MocDefinitions); + InfoGet(makefile, "AM_MOC_INCLUDES", config, this->MocIncludePaths); + InfoGet(makefile, "AM_MOC_OPTIONS", this->MocOptions); + InfoGet(makefile, "AM_MOC_RELAXED_MODE", this->MocRelaxedMode); + { + std::vector<std::string> mocDependFilters; + InfoGet(makefile, "AM_MOC_DEPEND_FILTERS", mocDependFilters); + // Insert Q_PLUGIN_METADATA dependency filter + if (this->QtMajorVersion != "4") { + this->MocDependFilterPush("Q_PLUGIN_METADATA", + "[\n][ \t]*Q_PLUGIN_METADATA[ \t]*\\(" + "[^\\)]*FILE[ \t]*\"([^\"]+)\""); + } + // Insert user defined dependency filters + if ((mocDependFilters.size() % 2) == 0) { + for (std::vector<std::string>::const_iterator dit = + mocDependFilters.begin(); + dit != mocDependFilters.end(); dit += 2) { + if (!this->MocDependFilterPush(*dit, *(dit + 1))) { + return false; + } } + } else { + this->LogError( + "AutoMoc: Error: AUTOMOC_DEPEND_FILTERS list size is not " + "a multiple of 2"); + return false; } - } else { - this->LogError("AutoMoc: Error: AUTOMOC_DEPEND_FILTERS list size is not " - "a multiple of 2"); } } // - Uic - cmSystemTools::ExpandListArgument(makefile->GetSafeDefinition("AM_UIC_SKIP"), - this->UicSkipList); - cmSystemTools::ExpandListArgument( - GetConfigDefinition(makefile, "AM_UIC_TARGET_OPTIONS", config), - this->UicTargetOptions); - { - std::vector<std::string> uicFilesVec; - std::vector<std::string> uicOptionsVec; - cmSystemTools::ExpandListArgument( - makefile->GetSafeDefinition("AM_UIC_OPTIONS_FILES"), uicFilesVec); - cmSystemTools::ExpandListArgument( - makefile->GetSafeDefinition("AM_UIC_OPTIONS_OPTIONS"), uicOptionsVec); - if (uicFilesVec.size() != uicOptionsVec.size()) { - this->LogError( - "AutoGen: Error: Uic files/options lists size missmatch in: " + - filename); - return false; - } - for (std::vector<std::string>::iterator fileIt = uicFilesVec.begin(), - optionIt = uicOptionsVec.begin(); - fileIt != uicFilesVec.end(); ++fileIt, ++optionIt) { - cmSystemTools::ReplaceString(*optionIt, "@list_sep@", ";"); - this->UicOptions[*fileIt] = *optionIt; + if (this->UicEnabled()) { + InfoGet(makefile, "AM_UIC_SKIP", this->UicSkipList); + InfoGet(makefile, "AM_UIC_SEARCH_PATHS", this->UicSearchPaths); + InfoGet(makefile, "AM_UIC_TARGET_OPTIONS", config, this->UicTargetOptions); + { + std::vector<std::string> uicFilesVec; + std::vector<std::string> uicOptionsVec; + InfoGet(makefile, "AM_UIC_OPTIONS_FILES", uicFilesVec); + InfoGet(makefile, "AM_UIC_OPTIONS_OPTIONS", uicOptionsVec); + // Compare list sizes + if (uicFilesVec.size() == uicOptionsVec.size()) { + for (std::vector<std::string>::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; + } } } // - Rcc - cmSystemTools::ExpandListArgument( - makefile->GetSafeDefinition("AM_RCC_SOURCES"), this->RccSources); - { - std::vector<std::string> rccFilesVec; - std::vector<std::string> rccOptionsVec; - cmSystemTools::ExpandListArgument( - makefile->GetSafeDefinition("AM_RCC_OPTIONS_FILES"), rccFilesVec); - cmSystemTools::ExpandListArgument( - makefile->GetSafeDefinition("AM_RCC_OPTIONS_OPTIONS"), rccOptionsVec); - if (rccFilesVec.size() != rccOptionsVec.size()) { - this->LogError( - "AutoGen: Error: RCC files/options lists size missmatch in: " + - filename); - return false; - } - for (std::vector<std::string>::iterator fileIt = rccFilesVec.begin(), - optionIt = rccOptionsVec.begin(); - fileIt != rccFilesVec.end(); ++fileIt, ++optionIt) { - cmSystemTools::ReplaceString(*optionIt, "@list_sep@", ";"); - this->RccOptions[*fileIt] = *optionIt; - } - } - { - std::vector<std::string> rccInputLists; - cmSystemTools::ExpandListArgument( - makefile->GetSafeDefinition("AM_RCC_INPUTS"), rccInputLists); - - // qrc files in the end of the list may have been empty - if (rccInputLists.size() < this->RccSources.size()) { - rccInputLists.resize(this->RccSources.size()); - } - if (this->RccSources.size() != rccInputLists.size()) { - this->LogError( - "AutoGen: Error: RCC sources/inputs lists size missmatch in: " + - filename); - return false; + if (this->RccEnabled()) { + InfoGet(makefile, "AM_RCC_SOURCES", this->RccSources); + { + std::vector<std::string> rccFilesVec; + std::vector<std::string> rccOptionsVec; + InfoGet(makefile, "AM_RCC_OPTIONS_FILES", rccFilesVec); + InfoGet(makefile, "AM_RCC_OPTIONS_OPTIONS", rccOptionsVec); + if (rccFilesVec.size() != rccOptionsVec.size()) { + this->LogError( + "AutoGen: Error: RCC files/options lists size missmatch in: " + + filename); + return false; + } + for (std::vector<std::string>::iterator fileIt = rccFilesVec.begin(), + optionIt = rccOptionsVec.begin(); + fileIt != rccFilesVec.end(); ++fileIt, ++optionIt) { + cmSystemTools::ReplaceString(*optionIt, "@list_sep@", ";"); + this->RccOptions[*fileIt] = *optionIt; + } } - for (std::vector<std::string>::iterator fileIt = this->RccSources.begin(), - inputIt = rccInputLists.begin(); - fileIt != this->RccSources.end(); ++fileIt, ++inputIt) { - cmSystemTools::ReplaceString(*inputIt, "@list_sep@", ";"); - std::vector<std::string> rccInputFiles; - cmSystemTools::ExpandListArgument(*inputIt, rccInputFiles); - this->RccInputs[*fileIt] = rccInputFiles; + { + std::vector<std::string> rccInputLists; + InfoGet(makefile, "AM_RCC_INPUTS", rccInputLists); + + // qrc files in the end of the list may have been empty + if (rccInputLists.size() < this->RccSources.size()) { + rccInputLists.resize(this->RccSources.size()); + } + if (this->RccSources.size() != rccInputLists.size()) { + this->LogError( + "AutoGen: Error: RCC sources/inputs lists size missmatch in: " + + filename); + return false; + } + for (std::vector<std::string>::iterator + fileIt = this->RccSources.begin(), + inputIt = rccInputLists.begin(); + fileIt != this->RccSources.end(); ++fileIt, ++inputIt) { + cmSystemTools::ReplaceString(*inputIt, "@list_sep@", ";"); + std::vector<std::string> rccInputFiles; + cmSystemTools::ExpandListArgument(*inputIt, rccInputFiles); + this->RccInputs[*fileIt] = rccInputFiles; + } } } - // - Flags - this->IncludeProjectDirsBefore = - makefile->IsOn("AM_CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE"); - this->MocRelaxedMode = makefile->IsOn("AM_MOC_RELAXED_MODE"); - return true; } @@ -727,15 +740,15 @@ void cmQtAutoGenerators::MocFindDepends( // regular expression check if (contentText.find(filter.key) != std::string::npos) { // Run regular expression check loop + const std::string sourcePath = subDirPrefix(absFilename); const char* contentChars = contentText.c_str(); while (filter.regExp.find(contentChars)) { // Evaluate match const std::string match = filter.regExp.match(1); if (!match.empty()) { // Find the dependency file - const std::string incFile = - this->FindIncludedFile(absFilename, match); - if (!incFile.empty()) { + std::string incFile; + if (this->MocFindIncludedFile(incFile, sourcePath, match)) { mocDepends[absFilename].insert(incFile); if (this->Verbose) { this->LogInfo("AutoMoc: Found dependency:\n " + @@ -823,12 +836,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(); } } @@ -846,8 +854,7 @@ bool cmQtAutoGenerators::MocParseSourceContent( this->LogInfo("AutoMoc: Checking " + absFilename); } - const std::string scannedFileAbsPath = - cmsys::SystemTools::GetFilenamePath(absFilename) + '/'; + const std::string scannedFileAbsPath = subDirPrefix(absFilename); const std::string scannedFileBasename = cmsys::SystemTools::GetFilenameWithoutLastExtension(absFilename); @@ -866,13 +873,9 @@ bool cmQtAutoGenerators::MocParseSourceContent( while (this->RegExpMocInclude.find(contentChars)) { const std::string incString = this->RegExpMocInclude.match(1); // Basename of the moc include + const std::string incSubDir(subDirPrefix(incString)); const std::string incBasename = cmsys::SystemTools::GetFilenameWithoutLastExtension(incString); - std::string incSubDir; - if (incString.find_first_of('/') != std::string::npos) { - incSubDir = cmsys::SystemTools::GetFilenamePath(incString); - incSubDir += '/'; - } // If the moc include is of the moc_foo.cpp style we expect // the Q_OBJECT class declaration in a header file. @@ -884,7 +887,7 @@ bool cmQtAutoGenerators::MocParseSourceContent( // Remove the moc_ part const std::string incRealBasename = incBasename.substr(4); const std::string headerToMoc = - this->FindMocHeader(scannedFileAbsPath, incRealBasename, incSubDir); + this->MocFindHeader(scannedFileAbsPath, incSubDir + incRealBasename); if (!headerToMoc.empty()) { // Register moc job mocsIncluded[headerToMoc] = incString; @@ -917,7 +920,7 @@ bool cmQtAutoGenerators::MocParseSourceContent( } else { // In relaxed mode try to find a header instead but issue a warning const std::string headerToMoc = - this->FindMocHeader(scannedFileAbsPath, incBasename, incSubDir); + this->MocFindHeader(scannedFileAbsPath, incSubDir + incBasename); if (!headerToMoc.empty()) { // This is for KDE4 compatibility: fileToMoc = headerToMoc; @@ -1056,8 +1059,7 @@ void cmQtAutoGenerators::SearchHeadersForSourceFile( { std::string basepaths[2]; { - std::string bpath = cmsys::SystemTools::GetFilenamePath(absFilename); - bpath += '/'; + std::string bpath = subDirPrefix(absFilename); bpath += cmsys::SystemTools::GetFilenameWithoutLastExtension(absFilename); // search for default header files and private header files basepaths[0] = bpath; @@ -1235,14 +1237,14 @@ bool cmQtAutoGenerators::MocGenerateAll( */ bool cmQtAutoGenerators::MocGenerateFile( const std::string& sourceFile, const std::string& mocFileName, - const std::string& subDirPrefix, + const std::string& subDir, const std::map<std::string, std::set<std::string> >& mocDepends) { bool mocGenerated = false; bool generateMoc = this->GenerateAllMoc; const std::string mocFileRel = - this->AutogenBuildSubDir + subDirPrefix + mocFileName; + this->AutogenBuildSubDir + subDir + mocFileName; const std::string mocFileAbs = this->CurrentBinaryDir + mocFileRel; if (!generateMoc) { @@ -1323,6 +1325,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<std::string>::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<std::string, std::vector<std::string> >& uisIncluded) { @@ -1331,46 +1363,57 @@ bool cmQtAutoGenerators::UicGenerateAll( } // single map with input / output names - 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 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::string, std::string>(); - std::map<std::string, std::string>& sourceMap = uiGenMap[it->first]; - for (std::vector<std::string>::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<std::string, std::map<std::string, std::string> > sourceGenMap; { - std::multimap<std::string, std::string> 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<std::string, std::string> testMap; + // Compile maps + for (std::map<std::string, std::vector<std::string> >::const_iterator sit = + uisIncluded.begin(); + sit != uisIncluded.end(); ++sit) { + const std::string& source(sit->first); + const std::vector<std::string>& sourceIncs(sit->second); + // insert new source/destination map + std::map<std::string, std::string>& uiGenMap = sourceGenMap[source]; + for (std::vector<std::string>::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<std::string, std::string> 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<std::string, std::map<std::string, std::string> >::const_iterator it = - uiGenMap.begin(); - it != uiGenMap.end(); ++it) { + sourceGenMap.begin(); + it != sourceGenMap.end(); ++it) { for (std::map<std::string, std::string>::const_iterator sit = it->second.begin(); sit != it->second.end(); ++sit) { @@ -1413,15 +1456,15 @@ bool cmQtAutoGenerators::UicGenerateFile(const std::string& realName, std::vector<std::string> cmd; cmd.push_back(this->UicExecutable); { - std::vector<std::string> opts = this->UicTargetOptions; + std::vector<std::string> allOpts = this->UicTargetOptions; std::map<std::string, std::string>::const_iterator optionIt = this->UicOptions.find(uiInputFile); if (optionIt != this->UicOptions.end()) { std::vector<std::string> 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); @@ -1740,39 +1783,22 @@ bool cmQtAutoGenerators::FindHeader(std::string& header, return false; } -bool cmQtAutoGenerators::FindHeaderGlobal( - std::string& header, const std::string& testBasePath) const -{ - for (std::vector<std::string>::const_iterator iit = - this->MocIncludePaths.begin(); - iit != this->MocIncludePaths.end(); ++iit) { - const std::string fullPath = ((*iit) + '/' + testBasePath); - if (FindHeader(header, fullPath)) { - return true; - } - } - return false; -} - -std::string cmQtAutoGenerators::FindMocHeader(const std::string& basePath, - const std::string& baseName, - const std::string& subDir) const +std::string cmQtAutoGenerators::MocFindHeader( + const std::string& sourcePath, const std::string& includeBase) const { std::string header; - do { - if (!subDir.empty()) { - if (this->FindHeader(header, basePath + subDir + baseName)) { + // Search in vicinity of the source + if (!this->FindHeader(header, sourcePath + includeBase)) { + // Search in include directories + for (std::vector<std::string>::const_iterator iit = + this->MocIncludePaths.begin(); + iit != this->MocIncludePaths.end(); ++iit) { + const std::string fullPath = ((*iit) + '/' + includeBase); + if (FindHeader(header, fullPath)) { break; } } - if (this->FindHeader(header, basePath + baseName)) { - break; - } - // Try include directories - if (this->FindHeaderGlobal(header, subDir + baseName)) { - break; - } - } while (false); + } // Sanitize if (!header.empty()) { header = cmsys::SystemTools::GetRealPath(header); @@ -1780,40 +1806,34 @@ std::string cmQtAutoGenerators::FindMocHeader(const std::string& basePath, return header; } -std::string cmQtAutoGenerators::FindIncludedFile( - const std::string& sourceFile, const std::string& includeString) const +bool cmQtAutoGenerators::MocFindIncludedFile( + std::string& absFile, const std::string& sourcePath, + const std::string& includeString) const { + bool success = false; // Search in vicinity of the source { - std::string testPath = cmSystemTools::GetFilenamePath(sourceFile); - testPath += '/'; + std::string testPath = sourcePath; testPath += includeString; if (cmsys::SystemTools::FileExists(testPath.c_str())) { - return cmsys::SystemTools::GetRealPath(testPath); + absFile = cmsys::SystemTools::GetRealPath(testPath); + success = true; } } - // Search globally - return FindInIncludeDirectories(includeString); -} - -/** - * @brief Tries to find a file in the include directories - * @return True on success - */ -std::string cmQtAutoGenerators::FindInIncludeDirectories( - const std::string& includeString) const -{ - std::string res; - for (std::vector<std::string>::const_iterator iit = - this->MocIncludePaths.begin(); - iit != this->MocIncludePaths.end(); ++iit) { - const std::string fullPath = ((*iit) + '/' + includeString); - if (cmsys::SystemTools::FileExists(fullPath.c_str())) { - res = cmsys::SystemTools::GetRealPath(fullPath); - break; + // Search in include directories + if (!success) { + for (std::vector<std::string>::const_iterator iit = + this->MocIncludePaths.begin(); + iit != this->MocIncludePaths.end(); ++iit) { + const std::string fullPath = ((*iit) + '/' + includeString); + if (cmsys::SystemTools::FileExists(fullPath.c_str())) { + absFile = cmsys::SystemTools::GetRealPath(fullPath); + success = true; + break; + } } } - return res; + return success; } /** diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGenerators.h index e4b7f60..3bff2b2 100644 --- a/Source/cmQtAutoGenerators.h +++ b/Source/cmQtAutoGenerators.h @@ -107,10 +107,12 @@ private: const std::map<std::string, std::set<std::string> >& mocDepends); bool MocGenerateFile( const std::string& sourceFile, const std::string& mocFileName, - const std::string& subDirPrefix, + const std::string& subDir, const std::map<std::string, std::set<std::string> >& mocDepends); // - Uic file generation + bool UicFindIncludedFile(std::string& absFile, const std::string& sourceFile, + const std::string& includeString); bool UicGenerateAll( const std::map<std::string, std::vector<std::string> >& includedUis); bool UicGenerateFile(const std::string& realName, @@ -142,14 +144,11 @@ private: bool MakeParentDirectory(const std::string& filename) const; bool FindHeader(std::string& header, const std::string& testBasePath) const; - bool FindHeaderGlobal(std::string& header, - const std::string& testBasePath) const; - std::string FindMocHeader(const std::string& basePath, - const std::string& baseName, - const std::string& subDir) const; - std::string FindIncludedFile(const std::string& sourceFile, - const std::string& includeString) const; - std::string FindInIncludeDirectories(const std::string& includeString) const; + + std::string MocFindHeader(const std::string& sourcePath, + const std::string& includeBase) const; + bool MocFindIncludedFile(std::string& absFile, const std::string& sourceFile, + const std::string& includeString) const; // - Target names std::string OriginTargetName; @@ -185,6 +184,7 @@ private: std::vector<std::string> UicSkipList; std::vector<std::string> UicTargetOptions; std::map<std::string, std::string> UicOptions; + std::vector<std::string> UicSearchPaths; // - Rcc std::vector<std::string> RccSources; std::map<std::string, std::string> 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); diff --git a/Tests/QtAutogen/CMakeLists.txt b/Tests/QtAutogen/CMakeLists.txt index dc631c6..4960472 100644 --- a/Tests/QtAutogen/CMakeLists.txt +++ b/Tests/QtAutogen/CMakeLists.txt @@ -287,5 +287,9 @@ if (NOT QT_TEST_VERSION STREQUAL 4) endif() # -- Test +# Tests various .ui include directories +add_subdirectory(uicInclude) + +# -- Test # Complex test case add_subdirectory(complex) diff --git a/Tests/QtAutogen/uicInclude/CMakeLists.txt b/Tests/QtAutogen/uicInclude/CMakeLists.txt new file mode 100644 index 0000000..f62ebb0 --- /dev/null +++ b/Tests/QtAutogen/uicInclude/CMakeLists.txt @@ -0,0 +1,8 @@ +# Test moc include patterns + +set(CMAKE_AUTOUIC_SEARCH_PATHS "dirA") + +add_executable(uicInclude main.cpp) +target_link_libraries(uicInclude ${QT_LIBRARIES}) +set_target_properties(uicInclude PROPERTIES AUTOUIC ON) +set_property(TARGET uicInclude APPEND PROPERTY AUTOUIC_SEARCH_PATHS "dirB") diff --git a/Tests/QtAutogen/uicInclude/PageC.ui b/Tests/QtAutogen/uicInclude/PageC.ui new file mode 100644 index 0000000..bb2fb5e --- /dev/null +++ b/Tests/QtAutogen/uicInclude/PageC.ui @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>PageC</class> + <widget class="QWidget" name="PageC"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>400</width> + <height>300</height> + </rect> + </property> + <property name="windowTitle"> + <string>Form</string> + </property> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QTreeView" name="treeView"/> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui> diff --git a/Tests/QtAutogen/uicInclude/dirA/PageA.ui b/Tests/QtAutogen/uicInclude/dirA/PageA.ui new file mode 100644 index 0000000..dd81802 --- /dev/null +++ b/Tests/QtAutogen/uicInclude/dirA/PageA.ui @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>PageA</class> + <widget class="QWidget" name="PageA"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>400</width> + <height>300</height> + </rect> + </property> + <property name="windowTitle"> + <string>Form</string> + </property> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QTreeView" name="treeView"/> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui> diff --git a/Tests/QtAutogen/uicInclude/dirB/sub/PageB.ui b/Tests/QtAutogen/uicInclude/dirB/sub/PageB.ui new file mode 100644 index 0000000..fa6dfa6 --- /dev/null +++ b/Tests/QtAutogen/uicInclude/dirB/sub/PageB.ui @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>PageB</class> + <widget class="QWidget" name="PageB"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>400</width> + <height>300</height> + </rect> + </property> + <property name="windowTitle"> + <string>Form</string> + </property> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <widget class="QTreeView" name="treeView"/> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui> diff --git a/Tests/QtAutogen/uicInclude/main.cpp b/Tests/QtAutogen/uicInclude/main.cpp new file mode 100644 index 0000000..4ca66a7 --- /dev/null +++ b/Tests/QtAutogen/uicInclude/main.cpp @@ -0,0 +1,10 @@ + +#include "main.hpp" + +int main(int argv, char** args) +{ + return 0; +} + +#include "sub/ui_PageB.h" +#include "ui_PageC.h" diff --git a/Tests/QtAutogen/uicInclude/main.hpp b/Tests/QtAutogen/uicInclude/main.hpp new file mode 100644 index 0000000..58ddc26 --- /dev/null +++ b/Tests/QtAutogen/uicInclude/main.hpp @@ -0,0 +1,6 @@ +#ifndef MAIN_HPP +#define MAIN_HPP + +#include "ui_PageA.h" + +#endif |