[Cmake-commits] CMake branch, next, updated. v3.8.0-rc1-373-g8e7033c

Brad King brad.king at kitware.com
Mon Feb 20 15:52:09 EST 2017


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "CMake".

The branch, next has been updated
       via  8e7033c85264288c840edff511a03643f167e09c (commit)
       via  a1b8afd2e4fd26d425f5dd197fd308cd8f8d853e (commit)
       via  11ad7564ba2834d170240d37883ffdd7b3327a65 (commit)
       via  ca386093ae307dfd25917a520dca68319ce861a3 (commit)
       via  359cfdc68c2d606c32c15c0a3a68f8dacf7834eb (commit)
       via  b0a44ed354fe3eea20fc7dbc7c467794ebea6593 (commit)
       via  928564fb8610e508448d5972c6dc83f4dfb64d7f (commit)
       via  aee6c5b3d38b7150a3276d69e28b2705dc20d586 (commit)
       via  917af10b53626fabe9a833546450ac5d6af8b3ea (commit)
       via  4be7c81272e559b1ff572df5f5b274234a04a286 (commit)
       via  0136d1354b5957a1d583526dfdb74f176939f56c (commit)
       via  1fc9fe74dab4276b22abfd1a79fc344945350227 (commit)
       via  698a94c0d95ac865d40ed5caaac1a5e10194adf4 (commit)
       via  58ac0c6209b627137636e0feac6f4d59321dae54 (commit)
       via  1508ed9c65f1515313bca00790710820974cd7cc (commit)
       via  e4f61a211b960d3eab0253a2986ac3aa705a2661 (commit)
       via  1224e67a0fd059aea194ad9a797e31a74d891618 (commit)
       via  20ed0f59e4bbd5850d1271f99b53dcaa22cac417 (commit)
       via  f8125e7bee39b4b853fb9ea650a397dfb984a5e0 (commit)
       via  58699513c2248da7277b968d729bef5ba3471677 (commit)
       via  d3980d2a959734370d2f7cf2f76d705ddf2da6e3 (commit)
       via  d26601ec0897eec870fe95413362d242202d7f2b (commit)
       via  c84bca1030332d23d0fc6d06050e7a174f39d78a (commit)
       via  78031e7cdcead6a348191158c674ec341fdd43be (commit)
       via  c7f3bdedde2a38c8f2e46ca42f47efbde6252f1d (commit)
       via  17a2cfbcdd41ee607556794e5210744b90005dfb (commit)
       via  7111b59f020c3b6fa01136b608ce6777969f92e7 (commit)
       via  82e0d0642a42b0592be27ed20efb43e34aaa2091 (commit)
      from  917c6f27af57d87800cdcd066350e4bdce16027c (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=8e7033c85264288c840edff511a03643f167e09c
commit 8e7033c85264288c840edff511a03643f167e09c
Merge: 917c6f2 a1b8afd
Author:     Brad King <brad.king at kitware.com>
AuthorDate: Mon Feb 20 15:52:07 2017 -0500
Commit:     CMake Topic Stage <kwrobot at kitware.com>
CommitDate: Mon Feb 20 15:52:07 2017 -0500

    Merge topic 'autogen_json' into next
    
    a1b8afd2 Autogen: Documentation update
    11ad7564 Autogen: Add release notes for Q_PLUGIN_METADATA support
    ca386093 Autogen: Tests: Set different compression levels in rcc test
    359cfdc6 Autogen: Overhaul and simplify AutogenInfo.cmake file generation
    b0a44ed3 Autogen: Optimize GetCompileDefinitionsAndDirectories function
    928564fb Autogen: Sort AutogenInfo.cmake.in
    aee6c5b3 Autogen: Tests: Add Q_PLUGIN_METADATA test
    917af10b Autogen: Tests: Add moc include tests
    4be7c812 Autogen: Tests: Clean comments
    0136d135 Autogen: Log simplifications
    1fc9fe74 Autogen: Only touch an unchanged moc_compilation.cpp
    698a94c0 Autogen: Rebuild moc when Q_PLUGIN_METADATA json file changes
    58ac0c62 Autogen: Use GetRealPath in central places only
    1508ed9c Autogen: Search moc includes in include directories
    e4f61a21 Autogen: Sort includes before composing include options
    1224e67a Autogen: Add FindInIncludeDirectories method
    ...


https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=a1b8afd2e4fd26d425f5dd197fd308cd8f8d853e
commit a1b8afd2e4fd26d425f5dd197fd308cd8f8d853e
Author:     Sebastian Holtermann <sebholt at xwmw.org>
AuthorDate: Sun Feb 19 20:11:18 2017 +0100
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Mon Feb 20 15:51:29 2017 -0500

    Autogen: Documentation update
    
    Closes #15254

diff --git a/Help/manual/cmake-qt.7.rst b/Help/manual/cmake-qt.7.rst
index 56d4ca7..e9da396 100644
--- a/Help/manual/cmake-qt.7.rst
+++ b/Help/manual/cmake-qt.7.rst
@@ -63,20 +63,24 @@ If a ``Q_OBJECT`` or ``Q_GADGET`` macro is found in a header file, ``moc``
 will be run on the file.  The result will be put into a file named according
 to ``moc_<basename>.cpp``.  If the macro is found in a C++ implementation
 file, the moc output will be put into a file named according to
-``<basename>.moc``, following the Qt conventions.  The ``moc file`` may be
-included by the user in the C++ implementation file with a preprocessor
-``#include``.  If it is not so included, it will be added to a separate file
-which is compiled into the target.
+``<basename>.moc``, following the Qt conventions.  The ``<basename>.moc`` must
+be included by the user in the C++ implementation file with a preprocessor
+``#include``.
 
-The ``moc`` command line will consume the :prop_tgt:`COMPILE_DEFINITIONS` and
-:prop_tgt:`INCLUDE_DIRECTORIES` target properties from the target it is being
-invoked for, and for the appropriate build configuration.
-
-The generated ``moc_*.cpp`` and ``*.moc`` files are placed in the
+Included ``moc_*.cpp`` and ``*.moc`` files will be generated in the
 ``<CMAKE_CURRENT_BINARY_DIR>/<TARGETNAME>_autogen/include`` directory which is
 automatically added to the target's :prop_tgt:`INCLUDE_DIRECTORIES`.
 (This differs from CMake 3.7 and below; see their documentation for details.)
 
+Not included ``moc_<basename>.cpp`` files will be generated in custom
+folders to avoid name collisions and included in a separate
+``<CMAKE_CURRENT_BINARY_DIR>/<TARGETNAME>_autogen/moc_compilation.cpp``
+file which is compiled into the target.
+
+The ``moc`` command line will consume the :prop_tgt:`COMPILE_DEFINITIONS` and
+:prop_tgt:`INCLUDE_DIRECTORIES` target properties from the target it is being
+invoked for, and for the appropriate build configuration.
+
 The :prop_tgt:`AUTOMOC` target property may be pre-set for all
 following targets by setting the :variable:`CMAKE_AUTOMOC` variable.  The
 :prop_tgt:`AUTOMOC_MOC_OPTIONS` target property may be populated to set
diff --git a/Help/prop_tgt/AUTOMOC.rst b/Help/prop_tgt/AUTOMOC.rst
index b42643f..4ac9b6e 100644
--- a/Help/prop_tgt/AUTOMOC.rst
+++ b/Help/prop_tgt/AUTOMOC.rst
@@ -8,31 +8,41 @@ preprocessor automatically, i.e.  without having to use the
 :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
+When this property is set ``ON``, CMake will scan the header and
 source files at build time and invoke moc accordingly.
 
-* If an ``#include`` statement like ``#include "moc_foo.cpp"`` is found,
-  the ``Q_OBJECT`` class declaration is expected in the header, and
-  ``moc`` is run on the header file.  A ``moc_foo.cpp`` file will be
-  generated from the source's header into the
-  ``<CMAKE_CURRENT_BINARY_DIR>/<TARGETNAME>_autogen/include``
-  directory which is automatically added to the target's
+* If an ``#include`` statement like ``#include "moc_<basename>.cpp"`` is found,
+  the ``Q_OBJECT`` or ``Q_GADGET`` macros are expected in an otherwise empty
+  line of the ``<basename>.h(xx)`` header file. ``moc`` is run on the header file to
+  generate ``moc_<basename>.cpp`` in the
+  ``<CMAKE_CURRENT_BINARY_DIR>/<TARGETNAME>_autogen/include`` directory
+  which is automatically added to the target's
   :prop_tgt:`INCLUDE_DIRECTORIES`.  This allows the compiler to find the
-  included ``moc_foo.cpp`` file regardless of the location the original source.
-  However, if multiple source files 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
-  ``moc_compilation.cpp`` file, which is compiled as part of the
-  target.
+  included ``moc_<basename>.cpp`` file regardless of the location the
+  original source.
+
+* If an ``#include`` statement like ``#include "<basename>.moc"`` is found,
+  then ``Q_OBJECT`` or ``Q_GADGET`` macros are expected in the current source
+  file and ``moc`` is run on the source file itself.
+
+* Header files that are not included by an ``#include "moc_<basename>.cpp"``
+  statement are nonetheless scanned for ``Q_OBJECT`` or ``Q_GADGET`` macros.
+  The resulting ``moc_<basename>.cpp`` files are generated in custom
+  directories and automatically included in the generated
+  ``<CMAKE_CURRENT_BINARY_DIR>/<TARGETNAME>_autogen/moc_compilation.cpp`` file,
+  which is compiled as part of the target. The custom directories help to
+  avoid name collisions for moc files with the same ``<basename>``.
+
+* Additionally, header files with the same base name as a source file,
+  (like ``<basename>.h``) or ``_p`` appended to the base name (like
+  ``<basename>_p.h``), are parsed for ``Q_OBJECT`` or ``Q_GADGET`` macros,
+  and if found, ``moc`` is also executed on those files.
+
+* ``AUTOMOC`` always checks multiple header alternative extensions,
+  such as ``hpp``, ``hxx``, etc. when searching for headers.
+
+* ``AUTOMOC`` looks for the ``Q_PLUGIN_METADATA`` macro and reruns the
+  ``moc`` when the file addressed by the ``FILE`` argument of the macro changes.
 
 This property is initialized by the value of the :variable:`CMAKE_AUTOMOC`
 variable if it is set when a target is created.

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=11ad7564ba2834d170240d37883ffdd7b3327a65
commit 11ad7564ba2834d170240d37883ffdd7b3327a65
Author:     Sebastian Holtermann <sebholt at xwmw.org>
AuthorDate: Sun Feb 19 18:35:40 2017 +0100
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Mon Feb 20 15:51:29 2017 -0500

    Autogen: Add release notes for Q_PLUGIN_METADATA support

diff --git a/Help/release/dev/Autogen_json.rst b/Help/release/dev/Autogen_json.rst
new file mode 100644
index 0000000..73bbdf1
--- /dev/null
+++ b/Help/release/dev/Autogen_json.rst
@@ -0,0 +1,10 @@
+AutoGen json
+------------
+
+* When using :prop_tgt:`AUTOMOC`, CMake scans for the presence of the
+  ``Q_PLUGIN_METADATA`` macro and reruns moc when the file from the
+  macro's ``FILE`` argument changes.
+
+* When :prop_tgt:`AUTOMOC` detects an include statement of the form
+  ``#include "moc_<basename>.cpp"`` the respective header file is searched
+  for in the :prop_tgt:`INCLUDE_DIRECTORIES` of the target as well.

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=ca386093ae307dfd25917a520dca68319ce861a3
commit ca386093ae307dfd25917a520dca68319ce861a3
Author:     Sebastian Holtermann <sebholt at xwmw.org>
AuthorDate: Sun Feb 19 17:24:30 2017 +0100
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Mon Feb 20 15:51:28 2017 -0500

    Autogen: Tests: Set different compression levels in rcc test

diff --git a/Tests/QtAutogen/sameName/CMakeLists.txt b/Tests/QtAutogen/sameName/CMakeLists.txt
index 9e47a3e..4d2dcd9 100644
--- a/Tests/QtAutogen/sameName/CMakeLists.txt
+++ b/Tests/QtAutogen/sameName/CMakeLists.txt
@@ -18,3 +18,14 @@ add_executable(sameName
 )
 target_link_libraries(sameName ${QT_LIBRARIES})
 set_target_properties(sameName PROPERTIES AUTOMOC TRUE AUTORCC TRUE)
+
+# Set different compression levels
+if (QT_TEST_VERSION STREQUAL 4)
+  set(rccCompress "-compress")
+else()
+  set(rccCompress "--compress")
+endif()
+set_target_properties(sameName PROPERTIES AUTORCC_OPTIONS "${rccCompress};0" )
+set_source_files_properties(aaa/data.qrc PROPERTIES AUTORCC_OPTIONS "${rccCompress};1" )
+set_source_files_properties(bbb/data.qrc PROPERTIES AUTORCC_OPTIONS "${rccCompress};2" )
+set_source_files_properties(ccc/data.qrc PROPERTIES AUTORCC_OPTIONS "${rccCompress};3" )

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=359cfdc68c2d606c32c15c0a3a68f8dacf7834eb
commit 359cfdc68c2d606c32c15c0a3a68f8dacf7834eb
Author:     Sebastian Holtermann <sebholt at xwmw.org>
AuthorDate: Sun Feb 19 16:46:47 2017 +0100
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Mon Feb 20 15:51:28 2017 -0500

    Autogen: Overhaul and simplify AutogenInfo.cmake file generation

diff --git a/Modules/AutogenInfo.cmake.in b/Modules/AutogenInfo.cmake.in
index 3135909..b647ecf 100644
--- a/Modules/AutogenInfo.cmake.in
+++ b/Modules/AutogenInfo.cmake.in
@@ -1,5 +1,5 @@
 # Target names
-set(AM_TARGET_NAME @_moc_target_name@)
+set(AM_TARGET_NAME @_autogen_target_name@)
 set(AM_ORIGIN_TARGET_NAME @_origin_target_name@)
 # Directories and files
 set(AM_CMAKE_BINARY_DIR "@CMAKE_BINARY_DIR@/")
@@ -10,16 +10,16 @@ set(AM_CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE "@CMAKE_INCLUDE_DIRECTORIES_PROJ
 set(AM_SOURCES @_sources@)
 set(AM_HEADERS @_headers@)
 # Qt environment
-set(AM_QT_VERSION_MAJOR "@_target_qt_version@")
-set(AM_QT_MOC_EXECUTABLE "@_qt_moc_executable@")
-set(AM_QT_UIC_EXECUTABLE "@_qt_uic_executable@")
-set(AM_QT_RCC_EXECUTABLE "@_qt_rcc_executable@")
+set(AM_QT_VERSION_MAJOR @_qt_version_major@)
+set(AM_QT_MOC_EXECUTABLE @_qt_moc_executable@)
+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_INCLUDES @_moc_incs@)
 set(AM_MOC_OPTIONS @_moc_options@)
-set(AM_MOC_RELAXED_MODE "@_moc_relaxed_mode@")
+set(AM_MOC_RELAXED_MODE @_moc_relaxed_mode@)
 # UIC settings
 set(AM_UIC_SKIP @_uic_skip@)
 set(AM_UIC_TARGET_OPTIONS @_uic_target_options@)
diff --git a/Source/cmQtAutoGeneratorInitializer.cxx b/Source/cmQtAutoGeneratorInitializer.cxx
index c201023..52112ff 100644
--- a/Source/cmQtAutoGeneratorInitializer.cxx
+++ b/Source/cmQtAutoGeneratorInitializer.cxx
@@ -22,7 +22,6 @@
 #endif
 
 #include <algorithm>
-#include <assert.h>
 #include <cmConfigure.h>
 #include <cmsys/FStream.hxx>
 #include <cmsys/RegularExpression.hxx>
@@ -55,6 +54,13 @@ static std::string utilStripCR(std::string const& line)
   return line;
 }
 
+static std::string GetSafeProperty(cmGeneratorTarget const* target,
+                                   const char* key)
+{
+  const char* tmp = target->GetProperty(key);
+  return std::string((tmp != CM_NULLPTR) ? tmp : "");
+}
+
 static std::string GetAutogenTargetName(cmGeneratorTarget const* target)
 {
   std::string autogenTargetName = target->GetName();
@@ -118,19 +124,33 @@ static void GetCompileDefinitionsAndDirectories(
   }
 }
 
+static void AddDefinitionEscaped(cmMakefile* makefile, const char* key,
+                                 const std::string& value)
+{
+  makefile->AddDefinition(key,
+                          cmOutputConverter::EscapeForCMake(value).c_str());
+}
+
+static void AddDefinitionEscaped(cmMakefile* makefile, const char* key,
+                                 const std::vector<std::string>& values)
+{
+  makefile->AddDefinition(
+    key, cmOutputConverter::EscapeForCMake(cmJoin(values, ";")).c_str());
+}
+
 static void SetupSourceFiles(cmGeneratorTarget const* target,
                              std::vector<std::string>& mocUicSources,
                              std::vector<std::string>& mocUicHeaders,
-                             std::vector<std::string>& skipMocList,
-                             std::vector<std::string>& skipUicList)
+                             std::vector<std::string>& mocSkipList,
+                             std::vector<std::string>& uicSkipList)
 {
   cmMakefile* makefile = target->Target->GetMakefile();
 
   std::vector<cmSourceFile*> srcFiles;
   target->GetConfigCommonSourceFiles(srcFiles);
 
-  const bool targetMoc = target->GetPropertyAsBool("AUTOMOC");
-  const bool targetUic = target->GetPropertyAsBool("AUTOUIC");
+  const bool mocTarget = target->GetPropertyAsBool("AUTOMOC");
+  const bool uicTarget = target->GetPropertyAsBool("AUTOUIC");
 
   cmFilePathChecksum fpathCheckSum(makefile);
   for (std::vector<cmSourceFile*>::const_iterator fileIt = srcFiles.begin();
@@ -151,22 +171,22 @@ static void SetupSourceFiles(cmGeneratorTarget const* target,
     // Skip flags
     const bool skipAll =
       cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTOGEN"));
-    const bool skipMoc =
+    const bool mocSkip =
       skipAll || cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTOMOC"));
-    const bool skipUic =
+    const bool uicSkip =
       skipAll || cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTOUIC"));
     // Add file name to skip lists.
     // Do this even when the file is not added to the sources/headers lists
     // because the file name may be extracted from an other file when
     // processing
-    if (skipMoc) {
-      skipMocList.push_back(absFile);
+    if (mocSkip) {
+      mocSkipList.push_back(absFile);
     }
-    if (skipUic) {
-      skipUicList.push_back(absFile);
+    if (uicSkip) {
+      uicSkipList.push_back(absFile);
     }
 
-    if ((targetMoc && !skipMoc) || (targetUic && !skipUic)) {
+    if ((mocTarget && !mocSkip) || (uicTarget && !uicSkip)) {
       // Add file name to sources or headers list
       switch (fileType) {
         case cmSystemTools::CXX_FILE_FORMAT:
@@ -184,80 +204,85 @@ static void SetupSourceFiles(cmGeneratorTarget const* target,
 
 static void MocSetupAutoTarget(
   cmGeneratorTarget const* target, const std::string& autogenTargetName,
-  std::vector<std::string> const& skipMoc,
+  const std::string& qtMajorVersion,
+  std::vector<std::string> const& mocSkipList,
   std::map<std::string, std::string>& configIncludes,
   std::map<std::string, std::string>& configDefines)
 {
   cmLocalGenerator* lg = target->GetLocalGenerator();
   cmMakefile* makefile = target->Target->GetMakefile();
 
-  const char* tmp = target->GetProperty("AUTOMOC_MOC_OPTIONS");
-  std::string _moc_options = (tmp != CM_NULLPTR ? tmp : "");
-  makefile->AddDefinition(
-    "_moc_options", cmOutputConverter::EscapeForCMake(_moc_options).c_str());
-  makefile->AddDefinition(
-    "_moc_skip",
-    cmOutputConverter::EscapeForCMake(cmJoin(skipMoc, ";")).c_str());
-  bool relaxedMode = makefile->IsOn("CMAKE_AUTOMOC_RELAXED_MODE");
-  makefile->AddDefinition("_moc_relaxed_mode", relaxedMode ? "TRUE" : "FALSE");
-
-  std::string _moc_incs;
-  std::string _moc_compile_defs;
-  std::vector<std::string> configs;
-  const std::string& config = makefile->GetConfigurations(configs);
-  GetCompileDefinitionsAndDirectories(target, config, _moc_incs,
-                                      _moc_compile_defs);
+  AddDefinitionEscaped(makefile, "_moc_options",
+                       GetSafeProperty(target, "AUTOMOC_MOC_OPTIONS"));
+  AddDefinitionEscaped(makefile, "_moc_skip", mocSkipList);
+  AddDefinitionEscaped(makefile, "_moc_relaxed_mode",
+                       makefile->IsOn("CMAKE_AUTOMOC_RELAXED_MODE") ? "TRUE"
+                                                                    : "FALSE");
 
-  makefile->AddDefinition(
-    "_moc_incs", cmOutputConverter::EscapeForCMake(_moc_incs).c_str());
-  makefile->AddDefinition(
-    "_moc_compile_defs",
-    cmOutputConverter::EscapeForCMake(_moc_compile_defs).c_str());
-
-  for (std::vector<std::string>::const_iterator li = configs.begin();
-       li != configs.end(); ++li) {
-    std::string config_moc_incs;
-    std::string config_moc_compile_defs;
-    GetCompileDefinitionsAndDirectories(target, *li, config_moc_incs,
-                                        config_moc_compile_defs);
-    if (config_moc_incs != _moc_incs) {
-      configIncludes[*li] = cmOutputConverter::EscapeForCMake(config_moc_incs);
-      if (_moc_incs.empty()) {
-        _moc_incs = config_moc_incs;
+  // Moc includes and compile definitions
+  {
+    std::string _moc_incs;
+    std::string _moc_compile_defs;
+    std::vector<std::string> configs;
+    {
+      const std::string& config = makefile->GetConfigurations(configs);
+      GetCompileDefinitionsAndDirectories(target, config, _moc_incs,
+                                          _moc_compile_defs);
+      AddDefinitionEscaped(makefile, "_moc_incs", _moc_incs);
+      AddDefinitionEscaped(makefile, "_moc_compile_defs", _moc_compile_defs);
+    }
+    for (std::vector<std::string>::const_iterator li = configs.begin();
+         li != configs.end(); ++li) {
+      std::string config_moc_incs;
+      std::string config_moc_compile_defs;
+      GetCompileDefinitionsAndDirectories(target, *li, config_moc_incs,
+                                          config_moc_compile_defs);
+      if (config_moc_incs != _moc_incs) {
+        configIncludes[*li] =
+          cmOutputConverter::EscapeForCMake(config_moc_incs);
+        if (_moc_incs.empty()) {
+          _moc_incs = config_moc_incs;
+        }
       }
-    }
-    if (config_moc_compile_defs != _moc_compile_defs) {
-      configDefines[*li] =
-        cmOutputConverter::EscapeForCMake(config_moc_compile_defs);
-      if (_moc_compile_defs.empty()) {
-        _moc_compile_defs = config_moc_compile_defs;
+      if (config_moc_compile_defs != _moc_compile_defs) {
+        configDefines[*li] =
+          cmOutputConverter::EscapeForCMake(config_moc_compile_defs);
+        if (_moc_compile_defs.empty()) {
+          _moc_compile_defs = config_moc_compile_defs;
+        }
       }
     }
   }
 
-  const char* qtVersion = makefile->GetDefinition("_target_qt_version");
-  if (strcmp(qtVersion, "5") == 0) {
-    cmGeneratorTarget* qt5Moc = lg->FindGeneratorTargetToUse("Qt5::moc");
-    if (!qt5Moc) {
-      cmSystemTools::Error("Qt5::moc target not found ",
-                           autogenTargetName.c_str());
-      return;
+  // Moc executable
+  {
+    std::string err;
+    const char* mocExec = CM_NULLPTR;
+    if (qtMajorVersion == "5") {
+      cmGeneratorTarget* qt5Moc = lg->FindGeneratorTargetToUse("Qt5::moc");
+      if (qt5Moc != CM_NULLPTR) {
+        mocExec = qt5Moc->ImportedGetLocation("");
+      } else {
+        err = "Qt5::moc target not found " + autogenTargetName;
+      }
+    } else if (qtMajorVersion == "4") {
+      cmGeneratorTarget* qt4Moc = lg->FindGeneratorTargetToUse("Qt4::moc");
+      if (qt4Moc != CM_NULLPTR) {
+        mocExec = qt4Moc->ImportedGetLocation("");
+      } else {
+        err = "Qt4::moc target not found " + autogenTargetName;
+      }
+    } else {
+      err = "The CMAKE_AUTOMOC feature supports only Qt 4 and Qt 5 ";
+      err += autogenTargetName;
     }
-    makefile->AddDefinition("_qt_moc_executable",
-                            qt5Moc->ImportedGetLocation(""));
-  } else if (strcmp(qtVersion, "4") == 0) {
-    cmGeneratorTarget* qt4Moc = lg->FindGeneratorTargetToUse("Qt4::moc");
-    if (!qt4Moc) {
-      cmSystemTools::Error("Qt4::moc target not found ",
-                           autogenTargetName.c_str());
-      return;
+    // Add definition or error
+    if (err.empty()) {
+      AddDefinitionEscaped(makefile, "_qt_moc_executable",
+                           mocExec ? mocExec : "");
+    } else {
+      cmSystemTools::Error(err.c_str());
     }
-    makefile->AddDefinition("_qt_moc_executable",
-                            qt4Moc->ImportedGetLocation(""));
-  } else {
-    cmSystemTools::Error("The CMAKE_AUTOMOC feature supports only Qt 4 and "
-                         "Qt 5 ",
-                         autogenTargetName.c_str());
   }
 }
 
@@ -270,126 +295,126 @@ static void UicGetOpts(cmGeneratorTarget const* target,
 }
 
 static void UicSetupAutoTarget(
-  cmGeneratorTarget const* target, std::vector<std::string> const& skipUic,
+  cmGeneratorTarget const* target, const std::string& qtMajorVersion,
+  std::vector<std::string> const& uicSkipList,
   std::map<std::string, std::string>& configUicOptions)
 {
   cmLocalGenerator* lg = target->GetLocalGenerator();
   cmMakefile* makefile = target->Target->GetMakefile();
 
-  std::set<std::string> skipped;
-  skipped.insert(skipUic.begin(), skipUic.end());
+  AddDefinitionEscaped(makefile, "_uic_skip", uicSkipList);
 
-  makefile->AddDefinition(
-    "_uic_skip",
-    cmOutputConverter::EscapeForCMake(cmJoin(skipUic, ";")).c_str());
-
-  std::vector<cmSourceFile*> uiFilesWithOptions =
-    makefile->GetQtUiFilesWithOptions();
-
-  const char* qtVersion = makefile->GetDefinition("_target_qt_version");
-
-  std::string _uic_opts;
-  std::vector<std::string> configs;
-  const std::string& config = makefile->GetConfigurations(configs);
-  UicGetOpts(target, config, _uic_opts);
-
-  if (!_uic_opts.empty()) {
-    _uic_opts = cmOutputConverter::EscapeForCMake(_uic_opts);
-    makefile->AddDefinition("_uic_target_options", _uic_opts.c_str());
-  }
-  for (std::vector<std::string>::const_iterator li = configs.begin();
-       li != configs.end(); ++li) {
-    std::string config_uic_opts;
-    UicGetOpts(target, *li, config_uic_opts);
-    if (config_uic_opts != _uic_opts) {
-      configUicOptions[*li] =
-        cmOutputConverter::EscapeForCMake(config_uic_opts);
-      if (_uic_opts.empty()) {
-        _uic_opts = config_uic_opts;
+  // Uic target options
+  {
+    std::string _uic_opts;
+    std::vector<std::string> configs;
+    UicGetOpts(target, makefile->GetConfigurations(configs), _uic_opts);
+
+    AddDefinitionEscaped(makefile, "_uic_target_options", _uic_opts);
+
+    for (std::vector<std::string>::const_iterator li = configs.begin();
+         li != configs.end(); ++li) {
+      std::string config_uic_opts;
+      UicGetOpts(target, *li, config_uic_opts);
+      if (config_uic_opts != _uic_opts) {
+        configUicOptions[*li] =
+          cmOutputConverter::EscapeForCMake(config_uic_opts);
+        if (_uic_opts.empty()) {
+          _uic_opts = config_uic_opts;
+        }
       }
     }
   }
-
-  std::string uiFileFiles;
-  std::string uiFileOptions;
-  const char* sep = "";
-
-  for (std::vector<cmSourceFile*>::const_iterator fileIt =
-         uiFilesWithOptions.begin();
-       fileIt != uiFilesWithOptions.end(); ++fileIt) {
-    cmSourceFile* sf = *fileIt;
-    std::string absFile = cmsys::SystemTools::GetRealPath(sf->GetFullPath());
-
-    if (!skipped.insert(absFile).second) {
-      continue;
+  // Uic files options
+  {
+    std::vector<std::string> uiFileFiles;
+    std::vector<std::string> uiFileOptions;
+    {
+      std::set<std::string> skipped;
+      skipped.insert(uicSkipList.begin(), uicSkipList.end());
+
+      const std::vector<cmSourceFile*> uiFilesWithOptions =
+        makefile->GetQtUiFilesWithOptions();
+      for (std::vector<cmSourceFile*>::const_iterator fileIt =
+             uiFilesWithOptions.begin();
+           fileIt != uiFilesWithOptions.end(); ++fileIt) {
+        cmSourceFile* sf = *fileIt;
+        const std::string absFile =
+          cmsys::SystemTools::GetRealPath(sf->GetFullPath());
+        if (skipped.insert(absFile).second) {
+          // The file wasn't skipped
+          uiFileFiles.push_back(absFile);
+          {
+            std::string opts = sf->GetProperty("AUTOUIC_OPTIONS");
+            cmSystemTools::ReplaceString(opts, ";", "@list_sep@");
+            uiFileOptions.push_back(opts);
+          }
+        }
+      }
     }
-    uiFileFiles += sep;
-    uiFileFiles += absFile;
-    uiFileOptions += sep;
-    std::string opts = sf->GetProperty("AUTOUIC_OPTIONS");
-    cmSystemTools::ReplaceString(opts, ";", "@list_sep@");
-    uiFileOptions += opts;
-    sep = ";";
+    AddDefinitionEscaped(makefile, "_qt_uic_options_files", uiFileFiles);
+    AddDefinitionEscaped(makefile, "_qt_uic_options_options", uiFileOptions);
   }
 
-  makefile->AddDefinition(
-    "_qt_uic_options_files",
-    cmOutputConverter::EscapeForCMake(uiFileFiles).c_str());
-  makefile->AddDefinition(
-    "_qt_uic_options_options",
-    cmOutputConverter::EscapeForCMake(uiFileOptions).c_str());
-
-  std::string targetName = target->GetName();
-  if (strcmp(qtVersion, "5") == 0) {
-    cmGeneratorTarget* qt5Uic = lg->FindGeneratorTargetToUse("Qt5::uic");
-    if (!qt5Uic) {
-      // Project does not use Qt5Widgets, but has AUTOUIC ON anyway
+  // Uic executable
+  {
+    std::string err;
+    const char* uicExec = CM_NULLPTR;
+    if (qtMajorVersion == "5") {
+      cmGeneratorTarget* qt5Uic = lg->FindGeneratorTargetToUse("Qt5::uic");
+      if (qt5Uic != CM_NULLPTR) {
+        uicExec = qt5Uic->ImportedGetLocation("");
+      } else {
+        // Project does not use Qt5Widgets, but has AUTOUIC ON anyway
+      }
+    } else if (qtMajorVersion == "4") {
+      cmGeneratorTarget* qt4Uic = lg->FindGeneratorTargetToUse("Qt4::uic");
+      if (qt4Uic != CM_NULLPTR) {
+        uicExec = qt4Uic->ImportedGetLocation("");
+      } else {
+        err = "Qt4::uic target not found " + target->GetName();
+      }
     } else {
-      makefile->AddDefinition("_qt_uic_executable",
-                              qt5Uic->ImportedGetLocation(""));
+      err = "The CMAKE_AUTOUIC feature supports only Qt 4 and Qt 5 ";
+      err += target->GetName();
     }
-  } else if (strcmp(qtVersion, "4") == 0) {
-    cmGeneratorTarget* qt4Uic = lg->FindGeneratorTargetToUse("Qt4::uic");
-    if (!qt4Uic) {
-      cmSystemTools::Error("Qt4::uic target not found ", targetName.c_str());
-      return;
+    // Add definition or error
+    if (err.empty()) {
+      AddDefinitionEscaped(makefile, "_qt_uic_executable",
+                           uicExec ? uicExec : "");
+    } else {
+      cmSystemTools::Error(err.c_str());
     }
-    makefile->AddDefinition("_qt_uic_executable",
-                            qt4Uic->ImportedGetLocation(""));
-  } else {
-    cmSystemTools::Error("The CMAKE_AUTOUIC feature supports only Qt 4 and "
-                         "Qt 5 ",
-                         targetName.c_str());
   }
 }
 
 static std::string RccGetExecutable(cmGeneratorTarget const* target,
                                     const std::string& qtMajorVersion)
 {
+  std::string rccExec;
   cmLocalGenerator* lg = target->GetLocalGenerator();
-
-  std::string const& targetName = target->GetName();
   if (qtMajorVersion == "5") {
     cmGeneratorTarget* qt5Rcc = lg->FindGeneratorTargetToUse("Qt5::rcc");
-    if (!qt5Rcc) {
-      cmSystemTools::Error("Qt5::rcc target not found ", targetName.c_str());
-      return std::string();
+    if (qt5Rcc != CM_NULLPTR) {
+      rccExec = qt5Rcc->ImportedGetLocation("");
+    } else {
+      cmSystemTools::Error("Qt5::rcc target not found ",
+                           target->GetName().c_str());
     }
-    return qt5Rcc->ImportedGetLocation("");
-  }
-  if (qtMajorVersion == "4") {
+  } else if (qtMajorVersion == "4") {
     cmGeneratorTarget* qt4Rcc = lg->FindGeneratorTargetToUse("Qt4::rcc");
-    if (!qt4Rcc) {
-      cmSystemTools::Error("Qt4::rcc target not found ", targetName.c_str());
-      return std::string();
+    if (qt4Rcc != CM_NULLPTR) {
+      rccExec = qt4Rcc->ImportedGetLocation("");
+    } else {
+      cmSystemTools::Error("Qt4::rcc target not found ",
+                           target->GetName().c_str());
     }
-    return qt4Rcc->ImportedGetLocation("");
+  } else {
+    cmSystemTools::Error(
+      "The CMAKE_AUTORCC feature supports only Qt 4 and Qt 5 ",
+      target->GetName().c_str());
   }
-
-  cmSystemTools::Error("The CMAKE_AUTORCC feature supports only Qt 4 and "
-                       "Qt 5 ",
-                       targetName.c_str());
-  return std::string();
+  return rccExec;
 }
 
 static void RccMergeOptions(std::vector<std::string>& opts,
@@ -399,26 +424,31 @@ static void RccMergeOptions(std::vector<std::string>& opts,
   static const char* valueOptions[] = { "name", "root", "compress",
                                         "threshold" };
   std::vector<std::string> extraOpts;
-  for (std::vector<std::string>::const_iterator it = fileOpts.begin();
-       it != fileOpts.end(); ++it) {
+  for (std::vector<std::string>::const_iterator fit = fileOpts.begin();
+       fit != fileOpts.end(); ++fit) {
     std::vector<std::string>::iterator existingIt =
-      std::find(opts.begin(), opts.end(), *it);
+      std::find(opts.begin(), opts.end(), *fit);
     if (existingIt != opts.end()) {
-      const char* o = it->c_str();
-      if (*o == '-') {
-        ++o;
-      }
-      if (isQt5 && *o == '-') {
-        ++o;
+      const char* optName = fit->c_str();
+      if (*optName == '-') {
+        ++optName;
+        if (isQt5 && *optName == '-') {
+          ++optName;
+        }
       }
-      if (std::find_if(cmArrayBegin(valueOptions), cmArrayEnd(valueOptions),
-                       cmStrCmp(*it)) != cmArrayEnd(valueOptions)) {
-        assert(existingIt + 1 != opts.end());
-        *(existingIt + 1) = *(it + 1);
-        ++it;
+      // Test if this is a value option and change the existing value
+      if ((optName != fit->c_str()) &&
+          std::find_if(cmArrayBegin(valueOptions), cmArrayEnd(valueOptions),
+                       cmStrCmp(optName)) != cmArrayEnd(valueOptions)) {
+        const std::vector<std::string>::iterator existValueIt(existingIt + 1);
+        const std::vector<std::string>::const_iterator fileValueIt(fit + 1);
+        if ((existValueIt != opts.end()) && (fileValueIt != fileOpts.end())) {
+          *existValueIt = *fileValueIt;
+          ++fit;
+        }
       }
     } else {
-      extraOpts.push_back(*it);
+      extraOpts.push_back(*fit);
     }
   }
   opts.insert(opts.end(), extraOpts.begin(), extraOpts.end());
@@ -528,23 +558,20 @@ static bool RccListInputsQt4(cmSourceFile* sf,
   }
 
   cmsys::RegularExpression fileMatchRegex("(<file[^<]+)");
+  cmsys::RegularExpression fileReplaceRegex("(^<file[^>]*>)");
 
   size_t offset = 0;
   while (fileMatchRegex.find(qrcContents.c_str() + offset)) {
     std::string qrcEntry = fileMatchRegex.match(1);
-
     offset += qrcEntry.size();
-
-    cmsys::RegularExpression fileReplaceRegex("(^<file[^>]*>)");
-    fileReplaceRegex.find(qrcEntry);
-    std::string tag = fileReplaceRegex.match(1);
-
-    qrcEntry = qrcEntry.substr(tag.size());
-
+    {
+      fileReplaceRegex.find(qrcEntry);
+      std::string tag = fileReplaceRegex.match(1);
+      qrcEntry = qrcEntry.substr(tag.size());
+    }
     if (!cmSystemTools::FileIsFullPath(qrcEntry.c_str())) {
       qrcEntry = sf->GetLocation().GetDirectory() + "/" + qrcEntry;
     }
-
     depends.push_back(qrcEntry);
   }
   return true;
@@ -565,89 +592,69 @@ static bool RccListInputs(const std::string& qtMajorVersion, cmSourceFile* sf,
 static void RccSetupAutoTarget(cmGeneratorTarget const* target,
                                const std::string& qtMajorVersion)
 {
-  std::string _rcc_files;
-  const char* sepRccFiles = "";
   cmMakefile* makefile = target->Target->GetMakefile();
-
-  std::vector<cmSourceFile*> srcFiles;
-  target->GetConfigCommonSourceFiles(srcFiles);
-
-  std::string qrcInputs;
-  const char* qrcInputsSep = "";
-
-  std::string rccFileFiles;
-  std::string rccFileOptions;
-  const char* optionSep = "";
-
   const bool qtMajorVersion5 = (qtMajorVersion == "5");
-
-  std::vector<std::string> rccOptions;
+  std::vector<std::string> _rcc_files;
+  std::vector<std::string> _rcc_inputs;
+  std::vector<std::string> rccFileFiles;
+  std::vector<std::string> rccFileOptions;
+  std::vector<std::string> rccOptionsTarget;
   if (const char* opts = target->GetProperty("AUTORCC_OPTIONS")) {
-    cmSystemTools::ExpandListArgument(opts, rccOptions);
+    cmSystemTools::ExpandListArgument(opts, rccOptionsTarget);
   }
 
+  std::vector<cmSourceFile*> srcFiles;
+  target->GetConfigCommonSourceFiles(srcFiles);
   for (std::vector<cmSourceFile*>::const_iterator fileIt = srcFiles.begin();
        fileIt != srcFiles.end(); ++fileIt) {
     cmSourceFile* sf = *fileIt;
-    std::string ext = sf->GetExtension();
-    if (ext == "qrc") {
-      std::string absFile = cmsys::SystemTools::GetRealPath(sf->GetFullPath());
+    if (sf->GetExtension() == "qrc") {
       const bool skip =
         cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTOGEN")) ||
         cmSystemTools::IsOn(sf->GetPropertyForUser("SKIP_AUTORCC"));
-
       if (!skip) {
-        _rcc_files += sepRccFiles;
-        _rcc_files += absFile;
-        sepRccFiles = ";";
-
-        if (const char* prop = sf->GetProperty("AUTORCC_OPTIONS")) {
-          std::vector<std::string> optsVec;
-          cmSystemTools::ExpandListArgument(prop, optsVec);
-          RccMergeOptions(rccOptions, optsVec, qtMajorVersion5);
-        }
-
-        if (!rccOptions.empty()) {
-          rccFileFiles += optionSep;
-          rccFileFiles += absFile;
-          rccFileOptions += optionSep;
-        }
-        const char* listSep = "";
-        for (std::vector<std::string>::const_iterator it = rccOptions.begin();
-             it != rccOptions.end(); ++it) {
-          rccFileOptions += listSep;
-          rccFileOptions += *it;
-          listSep = "@list_sep@";
+        const std::string absFile =
+          cmsys::SystemTools::GetRealPath(sf->GetFullPath());
+        // qrc file
+        _rcc_files.push_back(absFile);
+        // qrc file entries
+        {
+          std::string entriesList;
+          if (!cmSystemTools::IsOn(sf->GetPropertyForUser("GENERATED"))) {
+            std::vector<std::string> depends;
+            if (RccListInputs(qtMajorVersion, sf, target, depends)) {
+              entriesList = cmJoin(depends, "@list_sep@");
+            } else {
+              return;
+            }
+          }
+          _rcc_inputs.push_back(entriesList);
         }
-        optionSep = ";";
-
-        std::string entriesList;
-        if (!cmSystemTools::IsOn(sf->GetPropertyForUser("GENERATED"))) {
-          std::vector<std::string> depends;
-          if (RccListInputs(qtMajorVersion, sf, target, depends)) {
-            entriesList = cmJoin(depends, "@list_sep@");
-          } else {
-            return;
+        // rcc options for this qrc file
+        {
+          // Merged target and file options
+          std::vector<std::string> rccOptions(rccOptionsTarget);
+          if (const char* prop = sf->GetProperty("AUTORCC_OPTIONS")) {
+            std::vector<std::string> optsVec;
+            cmSystemTools::ExpandListArgument(prop, optsVec);
+            RccMergeOptions(rccOptions, optsVec, qtMajorVersion5);
+          }
+          // Only store non empty options lists
+          if (!rccOptions.empty()) {
+            rccFileFiles.push_back(absFile);
+            rccFileOptions.push_back(cmJoin(rccOptions, "@list_sep@"));
           }
         }
-        qrcInputs += qrcInputsSep;
-        qrcInputs += entriesList;
-        qrcInputsSep = ";";
       }
     }
   }
-  makefile->AddDefinition(
-    "_rcc_inputs", cmOutputConverter::EscapeForCMake(qrcInputs).c_str());
-  makefile->AddDefinition(
-    "_rcc_files", cmOutputConverter::EscapeForCMake(_rcc_files).c_str());
-  makefile->AddDefinition(
-    "_rcc_options_files",
-    cmOutputConverter::EscapeForCMake(rccFileFiles).c_str());
-  makefile->AddDefinition(
-    "_rcc_options_options",
-    cmOutputConverter::EscapeForCMake(rccFileOptions).c_str());
-  makefile->AddDefinition("_qt_rcc_executable",
-                          RccGetExecutable(target, qtMajorVersion).c_str());
+
+  AddDefinitionEscaped(makefile, "_rcc_files", _rcc_files);
+  AddDefinitionEscaped(makefile, "_rcc_inputs", _rcc_inputs);
+  AddDefinitionEscaped(makefile, "_rcc_options_files", rccFileFiles);
+  AddDefinitionEscaped(makefile, "_rcc_options_options", rccFileOptions);
+  AddDefinitionEscaped(makefile, "_qt_rcc_executable",
+                       RccGetExecutable(target, qtMajorVersion));
 }
 
 void cmQtAutoGeneratorInitializer::InitializeAutogenSources(
@@ -874,47 +881,42 @@ void cmQtAutoGeneratorInitializer::SetupAutoGenerateTarget(
   cmMakefile::ScopePushPop varScope(makefile);
   static_cast<void>(varScope);
 
-  // create a custom target for running generators at buildtime:
-  const std::string autogenTargetName = GetAutogenTargetName(target);
-  const std::string qtMajorVersion = GetQtMajorVersion(target);
-
-  makefile->AddDefinition(
-    "_moc_target_name",
-    cmOutputConverter::EscapeForCMake(autogenTargetName).c_str());
-  makefile->AddDefinition(
-    "_origin_target_name",
-    cmOutputConverter::EscapeForCMake(target->GetName()).c_str());
-  makefile->AddDefinition("_target_qt_version", qtMajorVersion.c_str());
-
-  std::vector<std::string> mocUicSources;
-  std::vector<std::string> mocUicHeaders;
-  std::vector<std::string> skipMoc;
-  std::vector<std::string> skipUic;
   std::map<std::string, std::string> configMocIncludes;
   std::map<std::string, std::string> configMocDefines;
   std::map<std::string, std::string> configUicOptions;
+  {
+    // create a custom target for running generators at buildtime:
+    const std::string autogenTargetName = GetAutogenTargetName(target);
+    const std::string qtMajorVersion = GetQtMajorVersion(target);
 
-  if (target->GetPropertyAsBool("AUTOMOC") ||
-      target->GetPropertyAsBool("AUTOUIC") ||
-      target->GetPropertyAsBool("AUTORCC")) {
-    SetupSourceFiles(target, mocUicSources, mocUicHeaders, skipMoc, skipUic);
-  }
-  makefile->AddDefinition(
-    "_sources",
-    cmOutputConverter::EscapeForCMake(cmJoin(mocUicSources, ";")).c_str());
-  makefile->AddDefinition(
-    "_headers",
-    cmOutputConverter::EscapeForCMake(cmJoin(mocUicHeaders, ";")).c_str());
+    AddDefinitionEscaped(makefile, "_autogen_target_name", autogenTargetName);
+    AddDefinitionEscaped(makefile, "_origin_target_name", target->GetName());
+    AddDefinitionEscaped(makefile, "_qt_version_major", qtMajorVersion);
 
-  if (target->GetPropertyAsBool("AUTOMOC")) {
-    MocSetupAutoTarget(target, autogenTargetName, skipMoc, configMocIncludes,
-                       configMocDefines);
-  }
-  if (target->GetPropertyAsBool("AUTOUIC")) {
-    UicSetupAutoTarget(target, skipUic, configUicOptions);
-  }
-  if (target->GetPropertyAsBool("AUTORCC")) {
-    RccSetupAutoTarget(target, qtMajorVersion);
+    std::vector<std::string> _sources;
+    std::vector<std::string> _headers;
+    std::vector<std::string> mocSkipList;
+    std::vector<std::string> uicSkipList;
+
+    if (target->GetPropertyAsBool("AUTOMOC") ||
+        target->GetPropertyAsBool("AUTOUIC") ||
+        target->GetPropertyAsBool("AUTORCC")) {
+      SetupSourceFiles(target, _sources, _headers, mocSkipList, uicSkipList);
+    }
+    AddDefinitionEscaped(makefile, "_sources", _sources);
+    AddDefinitionEscaped(makefile, "_headers", _headers);
+
+    if (target->GetPropertyAsBool("AUTOMOC")) {
+      MocSetupAutoTarget(target, autogenTargetName, qtMajorVersion,
+                         mocSkipList, configMocIncludes, configMocDefines);
+    }
+    if (target->GetPropertyAsBool("AUTOUIC")) {
+      UicSetupAutoTarget(target, qtMajorVersion, uicSkipList,
+                         configUicOptions);
+    }
+    if (target->GetPropertyAsBool("AUTORCC")) {
+      RccSetupAutoTarget(target, qtMajorVersion);
+    }
   }
 
   // Generate config file
@@ -926,7 +928,7 @@ void cmQtAutoGeneratorInitializer::SetupAutoGenerateTarget(
   makefile->ConfigureFile(inputFile.c_str(), outputFile.c_str(), false, true,
                           false);
 
-  // Append custom definitions to config file
+  // Append custom config definitions to info file
   if (!configMocDefines.empty() || !configMocIncludes.empty() ||
       !configUicOptions.empty()) {
 
@@ -948,33 +950,34 @@ void cmQtAutoGeneratorInitializer::SetupAutoGenerateTarget(
       error += outputFile;
       error += " for writing.";
       cmSystemTools::Error(error.c_str());
-      return;
-    }
-    if (!configMocDefines.empty()) {
-      for (std::map<std::string, std::string>::iterator
-             it = configMocDefines.begin(),
-             end = configMocDefines.end();
-           it != end; ++it) {
-        infoFile << "set(AM_MOC_COMPILE_DEFINITIONS_" << it->first << " "
-                 << it->second << ")\n";
+    } else {
+      infoFile << "# Configuration specific options\n";
+      if (!configMocDefines.empty()) {
+        for (std::map<std::string, std::string>::iterator
+               it = configMocDefines.begin(),
+               end = configMocDefines.end();
+             it != end; ++it) {
+          infoFile << "set(AM_MOC_COMPILE_DEFINITIONS_" << it->first << " "
+                   << it->second << ")\n";
+        }
       }
-    }
-    if (!configMocIncludes.empty()) {
-      for (std::map<std::string, std::string>::iterator
-             it = configMocIncludes.begin(),
-             end = configMocIncludes.end();
-           it != end; ++it) {
-        infoFile << "set(AM_MOC_INCLUDES_" << it->first << " " << it->second
-                 << ")\n";
+      if (!configMocIncludes.empty()) {
+        for (std::map<std::string, std::string>::iterator
+               it = configMocIncludes.begin(),
+               end = configMocIncludes.end();
+             it != end; ++it) {
+          infoFile << "set(AM_MOC_INCLUDES_" << it->first << " " << it->second
+                   << ")\n";
+        }
       }
-    }
-    if (!configUicOptions.empty()) {
-      for (std::map<std::string, std::string>::iterator
-             it = configUicOptions.begin(),
-             end = configUicOptions.end();
-           it != end; ++it) {
-        infoFile << "set(AM_UIC_TARGET_OPTIONS_" << it->first << " "
-                 << it->second << ")\n";
+      if (!configUicOptions.empty()) {
+        for (std::map<std::string, std::string>::iterator
+               it = configUicOptions.begin(),
+               end = configUicOptions.end();
+             it != end; ++it) {
+          infoFile << "set(AM_UIC_TARGET_OPTIONS_" << it->first << " "
+                   << it->second << ")\n";
+        }
       }
     }
   }

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=b0a44ed354fe3eea20fc7dbc7c467794ebea6593
commit b0a44ed354fe3eea20fc7dbc7c467794ebea6593
Author:     Sebastian Holtermann <sebholt at xwmw.org>
AuthorDate: Sun Feb 19 13:17:42 2017 +0100
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Mon Feb 20 15:51:27 2017 -0500

    Autogen: Optimize GetCompileDefinitionsAndDirectories function

diff --git a/Source/cmQtAutoGeneratorInitializer.cxx b/Source/cmQtAutoGeneratorInitializer.cxx
index d17faf6..c201023 100644
--- a/Source/cmQtAutoGeneratorInitializer.cxx
+++ b/Source/cmQtAutoGeneratorInitializer.cxx
@@ -98,6 +98,26 @@ static std::string GetQtMajorVersion(cmGeneratorTarget const* target)
   return qtMajorVersion;
 }
 
+static void GetCompileDefinitionsAndDirectories(
+  cmGeneratorTarget const* target, const std::string& config,
+  std::string& incs, std::string& defs)
+{
+  cmLocalGenerator* localGen = target->GetLocalGenerator();
+  {
+    std::vector<std::string> includeDirs;
+    // Get the include dirs for this target, without stripping the implicit
+    // include dirs off, see
+    // https://gitlab.kitware.com/cmake/cmake/issues/13667
+    localGen->GetIncludeDirectories(includeDirs, target, "CXX", config, false);
+    incs = cmJoin(includeDirs, ";");
+  }
+  {
+    std::set<std::string> defines;
+    localGen->AddCompileDefinitions(defines, target, config, "CXX");
+    defs += cmJoin(defines, ";");
+  }
+}
+
 static void SetupSourceFiles(cmGeneratorTarget const* target,
                              std::vector<std::string>& mocUicSources,
                              std::vector<std::string>& mocUicHeaders,
@@ -162,24 +182,6 @@ static void SetupSourceFiles(cmGeneratorTarget const* target,
   }
 }
 
-static void GetCompileDefinitionsAndDirectories(
-  cmGeneratorTarget const* target, const std::string& config,
-  std::string& incs, std::string& defs)
-{
-  std::vector<std::string> includeDirs;
-  cmLocalGenerator* localGen = target->GetLocalGenerator();
-  // Get the include dirs for this target, without stripping the implicit
-  // include dirs off, see https://gitlab.kitware.com/cmake/cmake/issues/13667
-  localGen->GetIncludeDirectories(includeDirs, target, "CXX", config, false);
-
-  incs = cmJoin(includeDirs, ";");
-
-  std::set<std::string> defines;
-  localGen->AddCompileDefinitions(defines, target, config, "CXX");
-
-  defs += cmJoin(defines, ";");
-}
-
 static void MocSetupAutoTarget(
   cmGeneratorTarget const* target, const std::string& autogenTargetName,
   std::vector<std::string> const& skipMoc,

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=928564fb8610e508448d5972c6dc83f4dfb64d7f
commit 928564fb8610e508448d5972c6dc83f4dfb64d7f
Author:     Sebastian Holtermann <sebholt at xwmw.org>
AuthorDate: Sun Feb 19 12:57:47 2017 +0100
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Mon Feb 20 15:51:27 2017 -0500

    Autogen: Sort AutogenInfo.cmake.in
    
    Also rename AM_SKIP_MOC to AM_MOC_SKIP
    and AM_SKIP_UIC to AM_UIC_SKIP

diff --git a/Modules/AutogenInfo.cmake.in b/Modules/AutogenInfo.cmake.in
index 3fafaff..3135909 100644
--- a/Modules/AutogenInfo.cmake.in
+++ b/Modules/AutogenInfo.cmake.in
@@ -1,25 +1,31 @@
-set(AM_SOURCES @_moc_uic_sources@)
-set(AM_HEADERS @_moc_uic_headers@)
-set(AM_SKIP_MOC @_skip_moc@)
-set(AM_SKIP_UIC @_skip_uic@)
-set(AM_MOC_COMPILE_DEFINITIONS @_moc_compile_defs@)
-set(AM_MOC_INCLUDES @_moc_incs@)
-set(AM_MOC_OPTIONS @_moc_options@)
-set(AM_MOC_RELAXED_MODE "@_moc_relaxed_mode@")
-set(AM_CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE "@CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE@")
+# Target names
+set(AM_TARGET_NAME @_moc_target_name@)
+set(AM_ORIGIN_TARGET_NAME @_origin_target_name@)
+# Directories and files
 set(AM_CMAKE_BINARY_DIR "@CMAKE_BINARY_DIR@/")
 set(AM_CMAKE_SOURCE_DIR "@CMAKE_SOURCE_DIR@/")
-set(AM_QT_MOC_EXECUTABLE "@_qt_moc_executable@")
-set(AM_QT_UIC_EXECUTABLE "@_qt_uic_executable@")
-set(AM_QT_RCC_EXECUTABLE "@_qt_rcc_executable@")
 set(AM_CMAKE_CURRENT_SOURCE_DIR "@CMAKE_CURRENT_SOURCE_DIR@/")
 set(AM_CMAKE_CURRENT_BINARY_DIR "@CMAKE_CURRENT_BINARY_DIR@/")
+set(AM_CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE "@CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE@")
+set(AM_SOURCES @_sources@)
+set(AM_HEADERS @_headers@)
+# Qt environment
 set(AM_QT_VERSION_MAJOR "@_target_qt_version@")
-set(AM_TARGET_NAME @_moc_target_name@)
-set(AM_ORIGIN_TARGET_NAME @_origin_target_name@)
+set(AM_QT_MOC_EXECUTABLE "@_qt_moc_executable@")
+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_INCLUDES @_moc_incs@)
+set(AM_MOC_OPTIONS @_moc_options@)
+set(AM_MOC_RELAXED_MODE "@_moc_relaxed_mode@")
+# UIC settings
+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@)
+# RCC settings
 set(AM_RCC_SOURCES @_rcc_files@ )
 set(AM_RCC_INPUTS @_rcc_inputs@)
 set(AM_RCC_OPTIONS_FILES @_rcc_options_files@)
diff --git a/Source/cmQtAutoGeneratorInitializer.cxx b/Source/cmQtAutoGeneratorInitializer.cxx
index 825eba0..d17faf6 100644
--- a/Source/cmQtAutoGeneratorInitializer.cxx
+++ b/Source/cmQtAutoGeneratorInitializer.cxx
@@ -194,7 +194,7 @@ static void MocSetupAutoTarget(
   makefile->AddDefinition(
     "_moc_options", cmOutputConverter::EscapeForCMake(_moc_options).c_str());
   makefile->AddDefinition(
-    "_skip_moc",
+    "_moc_skip",
     cmOutputConverter::EscapeForCMake(cmJoin(skipMoc, ";")).c_str());
   bool relaxedMode = makefile->IsOn("CMAKE_AUTOMOC_RELAXED_MODE");
   makefile->AddDefinition("_moc_relaxed_mode", relaxedMode ? "TRUE" : "FALSE");
@@ -278,7 +278,7 @@ static void UicSetupAutoTarget(
   skipped.insert(skipUic.begin(), skipUic.end());
 
   makefile->AddDefinition(
-    "_skip_uic",
+    "_uic_skip",
     cmOutputConverter::EscapeForCMake(cmJoin(skipUic, ";")).c_str());
 
   std::vector<cmSourceFile*> uiFilesWithOptions =
@@ -898,10 +898,10 @@ void cmQtAutoGeneratorInitializer::SetupAutoGenerateTarget(
     SetupSourceFiles(target, mocUicSources, mocUicHeaders, skipMoc, skipUic);
   }
   makefile->AddDefinition(
-    "_moc_uic_sources",
+    "_sources",
     cmOutputConverter::EscapeForCMake(cmJoin(mocUicSources, ";")).c_str());
   makefile->AddDefinition(
-    "_moc_uic_headers",
+    "_headers",
     cmOutputConverter::EscapeForCMake(cmJoin(mocUicHeaders, ";")).c_str());
 
   if (target->GetPropertyAsBool("AUTOMOC")) {
diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx
index 199e5cc..1d120d7 100644
--- a/Source/cmQtAutoGenerators.cxx
+++ b/Source/cmQtAutoGenerators.cxx
@@ -306,7 +306,7 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile(
                                     this->Headers);
 
   // - Moc
-  cmSystemTools::ExpandListArgument(makefile->GetSafeDefinition("AM_SKIP_MOC"),
+  cmSystemTools::ExpandListArgument(makefile->GetSafeDefinition("AM_MOC_SKIP"),
                                     this->MocSkipList);
   cmSystemTools::ExpandListArgument(
     GetConfigDefinition(makefile, "AM_MOC_COMPILE_DEFINITIONS", config),
@@ -318,7 +318,7 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile(
     makefile->GetSafeDefinition("AM_MOC_OPTIONS"), this->MocOptions);
 
   // - Uic
-  cmSystemTools::ExpandListArgument(makefile->GetSafeDefinition("AM_SKIP_UIC"),
+  cmSystemTools::ExpandListArgument(makefile->GetSafeDefinition("AM_UIC_SKIP"),
                                     this->UicSkipList);
   cmSystemTools::ExpandListArgument(
     GetConfigDefinition(makefile, "AM_UIC_TARGET_OPTIONS", config),

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=aee6c5b3d38b7150a3276d69e28b2705dc20d586
commit aee6c5b3d38b7150a3276d69e28b2705dc20d586
Author:     Sebastian Holtermann <sebholt at xwmw.org>
AuthorDate: Fri Feb 17 13:50:33 2017 +0100
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Mon Feb 20 15:51:27 2017 -0500

    Autogen: Tests: Add Q_PLUGIN_METADATA test

diff --git a/Tests/QtAutogen/CMakeLists.txt b/Tests/QtAutogen/CMakeLists.txt
index 40c23fa..260331b 100644
--- a/Tests/QtAutogen/CMakeLists.txt
+++ b/Tests/QtAutogen/CMakeLists.txt
@@ -86,7 +86,8 @@ try_compile(RCC_DEPENDS
   "${CMAKE_CURRENT_BINARY_DIR}/autorcc_depends"
   "${CMAKE_CURRENT_SOURCE_DIR}/autorcc_depends"
   autorcc_depends
-  CMAKE_FLAGS "-DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}" "-DQT_TEST_VERSION=${QT_TEST_VERSION}"
+  CMAKE_FLAGS "-DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}"
+              "-DQT_TEST_VERSION=${QT_TEST_VERSION}"
               "-DCMAKE_PREFIX_PATH=${Qt_PREFIX_DIR}"
   OUTPUT_VARIABLE output
 )
@@ -121,7 +122,8 @@ try_compile(MOC_RERUN
   "${CMAKE_CURRENT_BINARY_DIR}/automoc_rerun"
   "${CMAKE_CURRENT_SOURCE_DIR}/automoc_rerun"
   automoc_rerun
-  CMAKE_FLAGS "-DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}" "-DQT_TEST_VERSION=${QT_TEST_VERSION}"
+  CMAKE_FLAGS "-DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}"
+              "-DQT_TEST_VERSION=${QT_TEST_VERSION}"
               "-DCMAKE_PREFIX_PATH=${Qt_PREFIX_DIR}"
   OUTPUT_VARIABLE output
 )
@@ -215,5 +217,60 @@ add_subdirectory(mocIncludeStrict)
 add_subdirectory(mocIncludeRelaxed)
 
 # -- Test
+# Tests Q_PLUGIN_METADATA json file change detection
+if (NOT QT_TEST_VERSION STREQUAL 4)
+  try_compile(MOC_PLUGIN
+    "${CMAKE_CURRENT_BINARY_DIR}/mocPlugin"
+    "${CMAKE_CURRENT_SOURCE_DIR}/mocPlugin"
+    mocPlugin
+    CMAKE_FLAGS "-DQT_TEST_VERSION=${QT_TEST_VERSION}"
+                "-DCMAKE_PREFIX_PATH=${Qt_PREFIX_DIR}"
+    OUTPUT_VARIABLE output
+  )
+  if (NOT MOC_PLUGIN)
+    message(SEND_ERROR "Initial build of mocPlugin failed. Output: ${output}")
+  endif()
+
+  set(timeformat "%Y%j%H%M%S")
+  set(mocPluginBinDir "${CMAKE_CURRENT_BINARY_DIR}/mocPlugin")
+  find_library(style_a_file "PluginStyleA" "${mocPluginBinDir}")
+  find_library(style_b_file "PluginStyleB" "${mocPluginBinDir}")
+  find_library(style_c_file "PluginStyleC" "${mocPluginBinDir}")
+  find_library(style_d_file "PluginStyleD" "${mocPluginBinDir}")
+
+  file(TIMESTAMP "${style_a_file}" style_a_before "${timeformat}")
+  file(TIMESTAMP "${style_b_file}" style_b_before "${timeformat}")
+  file(TIMESTAMP "${style_c_file}" style_c_before "${timeformat}")
+  file(TIMESTAMP "${style_d_file}" style_d_before "${timeformat}")
+
+  # Ensure that the timestamp will change and touch the json files
+  execute_process(COMMAND "${CMAKE_COMMAND}" -E sleep 1)
+  execute_process(COMMAND "${CMAKE_COMMAND}" -E touch "${mocPluginBinDir}/jsonFiles/StyleC.json")
+  execute_process(COMMAND "${CMAKE_COMMAND}" -E touch "${mocPluginBinDir}/jsonFiles/sub/StyleD.json")
+
+  execute_process(COMMAND "${CMAKE_COMMAND}" --build .
+    WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/mocPlugin"
+  )
+
+  file(TIMESTAMP "${style_a_file}" style_a_after "${timeformat}")
+  file(TIMESTAMP "${style_b_file}" style_b_after "${timeformat}")
+  file(TIMESTAMP "${style_c_file}" style_c_after "${timeformat}")
+  file(TIMESTAMP "${style_d_file}" style_d_after "${timeformat}")
+
+  if (style_a_after GREATER style_a_before)
+    message(SEND_ERROR "file (${style_a_file}) should not have changed!")
+  endif()
+  if (style_b_after GREATER style_b_before)
+    message(SEND_ERROR "file (${style_b_file}) should not have changed!")
+  endif()
+  if (NOT style_c_after GREATER style_c_before)
+    message(SEND_ERROR "file (${style_c_file}) should have changed!")
+  endif()
+  if (NOT style_d_after GREATER style_d_before)
+    message(SEND_ERROR "file (${style_d_file}) should have changed!")
+  endif()
+endif()
+
+# -- Test
 # Complex test case
 add_subdirectory(complex)
diff --git a/Tests/QtAutogen/mocPlugin/CMakeLists.txt b/Tests/QtAutogen/mocPlugin/CMakeLists.txt
new file mode 100644
index 0000000..eed7d39
--- /dev/null
+++ b/Tests/QtAutogen/mocPlugin/CMakeLists.txt
@@ -0,0 +1,25 @@
+cmake_minimum_required(VERSION 3.8)
+
+if (NOT QT_TEST_VERSION STREQUAL 5)
+  message(SEND_ERROR "Invalid Qt version specified.")
+endif()
+find_package(Qt5Widgets REQUIRED)
+
+if(Qt5_POSITION_INDEPENDENT_CODE AND CMAKE_CXX_COMPILE_OPTIONS_PIC)
+  add_definitions(${CMAKE_CXX_COMPILE_OPTIONS_PIC})
+endif()
+
+configure_file(jsonIn/StyleC.json jsonFiles/StyleC.json @ONLY)
+configure_file(jsonIn/StyleD.json jsonFiles/sub/StyleD.json @ONLY)
+
+# Enable automoc
+set(CMAKE_AUTOMOC TRUE)
+
+include_directories("${CMAKE_CURRENT_BINARY_DIR}/jsonFiles")
+link_libraries(Qt5::Widgets)
+
+add_library(PluginStyleA MODULE StyleA.cpp)
+add_library(PluginStyleB MODULE StyleB.cpp)
+add_library(PluginStyleC MODULE StyleC.cpp)
+add_library(PluginStyleD MODULE StyleD.cpp)
+add_library(PluginStyleE MODULE StyleE.cpp)
diff --git a/Tests/QtAutogen/mocPlugin/StyleA.cpp b/Tests/QtAutogen/mocPlugin/StyleA.cpp
new file mode 100644
index 0000000..b5e8753
--- /dev/null
+++ b/Tests/QtAutogen/mocPlugin/StyleA.cpp
@@ -0,0 +1,6 @@
+#include "StyleA.hpp"
+
+QStyle* StyleA::create(const QString& key)
+{
+  return 0;
+}
diff --git a/Tests/QtAutogen/mocPlugin/StyleA.hpp b/Tests/QtAutogen/mocPlugin/StyleA.hpp
new file mode 100644
index 0000000..b105b02
--- /dev/null
+++ b/Tests/QtAutogen/mocPlugin/StyleA.hpp
@@ -0,0 +1,15 @@
+#ifndef STYLEA_HPP
+#define STYLEA_HPP
+
+#include <QStylePlugin>
+
+class StyleA : public QStylePlugin
+{
+  Q_OBJECT
+  // Json file in local directory
+  Q_PLUGIN_METADATA(IID "org.styles.A" FILE "StyleA.json")
+public:
+  QStyle* create(const QString& key);
+};
+
+#endif
diff --git a/Tests/QtAutogen/mocPlugin/StyleA.json b/Tests/QtAutogen/mocPlugin/StyleA.json
new file mode 100644
index 0000000..cc33953
--- /dev/null
+++ b/Tests/QtAutogen/mocPlugin/StyleA.json
@@ -0,0 +1 @@
+{ "Keys": [ "Rocket", "Starbuster" ] }
diff --git a/Tests/QtAutogen/mocPlugin/StyleB.cpp b/Tests/QtAutogen/mocPlugin/StyleB.cpp
new file mode 100644
index 0000000..17d4400
--- /dev/null
+++ b/Tests/QtAutogen/mocPlugin/StyleB.cpp
@@ -0,0 +1,6 @@
+#include "StyleB.hpp"
+
+QStyle* StyleB::create(const QString& key)
+{
+  return 0;
+}
diff --git a/Tests/QtAutogen/mocPlugin/StyleB.hpp b/Tests/QtAutogen/mocPlugin/StyleB.hpp
new file mode 100644
index 0000000..ba89127
--- /dev/null
+++ b/Tests/QtAutogen/mocPlugin/StyleB.hpp
@@ -0,0 +1,15 @@
+#ifndef STYLEB_HPP
+#define STYLEB_HPP
+
+#include <QStylePlugin>
+
+class StyleB : public QStylePlugin
+{
+  Q_OBJECT
+  // Json file in local subdirectory
+  Q_PLUGIN_METADATA(IID "org.styles.B" FILE "jsonIn/StyleB.json")
+public:
+  QStyle* create(const QString& key);
+};
+
+#endif
diff --git a/Tests/QtAutogen/mocPlugin/StyleC.cpp b/Tests/QtAutogen/mocPlugin/StyleC.cpp
new file mode 100644
index 0000000..37e7564
--- /dev/null
+++ b/Tests/QtAutogen/mocPlugin/StyleC.cpp
@@ -0,0 +1,6 @@
+#include "StyleC.hpp"
+
+QStyle* StyleC::create(const QString& key)
+{
+  return 0;
+}
diff --git a/Tests/QtAutogen/mocPlugin/StyleC.hpp b/Tests/QtAutogen/mocPlugin/StyleC.hpp
new file mode 100644
index 0000000..9f71d75
--- /dev/null
+++ b/Tests/QtAutogen/mocPlugin/StyleC.hpp
@@ -0,0 +1,15 @@
+#ifndef STYLEC_HPP
+#define STYLEC_HPP
+
+#include <QStylePlugin>
+
+class StyleC : public QStylePlugin
+{
+  Q_OBJECT
+  // Json file in global root directory
+  Q_PLUGIN_METADATA(IID "org.styles.C" FILE "StyleC.json")
+public:
+  QStyle* create(const QString& key);
+};
+
+#endif
diff --git a/Tests/QtAutogen/mocPlugin/StyleD.cpp b/Tests/QtAutogen/mocPlugin/StyleD.cpp
new file mode 100644
index 0000000..48398bb
--- /dev/null
+++ b/Tests/QtAutogen/mocPlugin/StyleD.cpp
@@ -0,0 +1,17 @@
+#include "StyleD.hpp"
+
+class StyleD : public QStylePlugin
+{
+  Q_OBJECT
+  // Json file in global sub director
+  Q_PLUGIN_METADATA(IID "org.styles.D" FILE "sub/StyleD.json")
+public:
+  QStyle* create(const QString& key);
+};
+
+QStyle* StyleD::create(const QString& key)
+{
+  return 0;
+}
+
+#include "StyleD.moc"
diff --git a/Tests/QtAutogen/mocPlugin/StyleD.hpp b/Tests/QtAutogen/mocPlugin/StyleD.hpp
new file mode 100644
index 0000000..2afe055
--- /dev/null
+++ b/Tests/QtAutogen/mocPlugin/StyleD.hpp
@@ -0,0 +1,8 @@
+#ifndef STYLED_HPP
+#define STYLED_HPP
+
+#include <QStylePlugin>
+
+class StyleD;
+
+#endif
diff --git a/Tests/QtAutogen/mocPlugin/StyleE.cpp b/Tests/QtAutogen/mocPlugin/StyleE.cpp
new file mode 100644
index 0000000..8fc9a7f
--- /dev/null
+++ b/Tests/QtAutogen/mocPlugin/StyleE.cpp
@@ -0,0 +1,6 @@
+#include "StyleE.hpp"
+
+QStyle* StyleE::create(const QString& key)
+{
+  return 0;
+}
diff --git a/Tests/QtAutogen/mocPlugin/StyleE.hpp b/Tests/QtAutogen/mocPlugin/StyleE.hpp
new file mode 100644
index 0000000..80e0b79
--- /dev/null
+++ b/Tests/QtAutogen/mocPlugin/StyleE.hpp
@@ -0,0 +1,15 @@
+#ifndef STYLEE_HPP
+#define STYLEE_HPP
+
+#include <QStylePlugin>
+
+class StyleE : public QStylePlugin
+{
+  Q_OBJECT
+  // No Json file
+  Q_PLUGIN_METADATA(IID "org.styles.E")
+public:
+  QStyle* create(const QString& key);
+};
+
+#endif
diff --git a/Tests/QtAutogen/mocPlugin/jsonIn/StyleB.json b/Tests/QtAutogen/mocPlugin/jsonIn/StyleB.json
new file mode 100644
index 0000000..129cac4
--- /dev/null
+++ b/Tests/QtAutogen/mocPlugin/jsonIn/StyleB.json
@@ -0,0 +1 @@
+{ "Keys": [ "Rocket", "StarbusterB" ] }
diff --git a/Tests/QtAutogen/mocPlugin/jsonIn/StyleC.json b/Tests/QtAutogen/mocPlugin/jsonIn/StyleC.json
new file mode 100644
index 0000000..bf17580
--- /dev/null
+++ b/Tests/QtAutogen/mocPlugin/jsonIn/StyleC.json
@@ -0,0 +1 @@
+{ "Keys": [ "Rocket", "StarbusterC" ] }
diff --git a/Tests/QtAutogen/mocPlugin/jsonIn/StyleD.json b/Tests/QtAutogen/mocPlugin/jsonIn/StyleD.json
new file mode 100644
index 0000000..f7fcc19
--- /dev/null
+++ b/Tests/QtAutogen/mocPlugin/jsonIn/StyleD.json
@@ -0,0 +1 @@
+{ "Keys": [ "Rocket", "StarbusterD" ] }
diff --git a/Tests/QtAutogen/mocPlugin/main.cpp b/Tests/QtAutogen/mocPlugin/main.cpp
new file mode 100644
index 0000000..3ba2ddc
--- /dev/null
+++ b/Tests/QtAutogen/mocPlugin/main.cpp
@@ -0,0 +1,6 @@
+#include "StyleA.hpp"
+
+int main(int argv, char** args)
+{
+  return 0;
+}

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=917af10b53626fabe9a833546450ac5d6af8b3ea
commit 917af10b53626fabe9a833546450ac5d6af8b3ea
Author:     Sebastian Holtermann <sebholt at xwmw.org>
AuthorDate: Thu Feb 16 15:59:56 2017 +0100
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Mon Feb 20 15:51:26 2017 -0500

    Autogen: Tests: Add moc include tests

diff --git a/Tests/QtAutogen/CMakeLists.txt b/Tests/QtAutogen/CMakeLists.txt
index c1cdee2..40c23fa 100644
--- a/Tests/QtAutogen/CMakeLists.txt
+++ b/Tests/QtAutogen/CMakeLists.txt
@@ -207,5 +207,13 @@ target_link_libraries(skipRccB ${QT_LIBRARIES})
 add_subdirectory(sameName)
 
 # -- Test
+# Tests various include moc patterns
+add_subdirectory(mocIncludeStrict)
+
+# -- Test
+# Tests various include moc patterns
+add_subdirectory(mocIncludeRelaxed)
+
+# -- Test
 # Complex test case
 add_subdirectory(complex)
diff --git a/Tests/QtAutogen/mocInclude/ObjA.cpp b/Tests/QtAutogen/mocInclude/ObjA.cpp
new file mode 100644
index 0000000..2ee47ec
--- /dev/null
+++ b/Tests/QtAutogen/mocInclude/ObjA.cpp
@@ -0,0 +1,24 @@
+#include "ObjA.hpp"
+
+class SubObjA : public QObject
+{
+  Q_OBJECT
+
+public:
+  SubObjA() = default;
+  ~SubObjA() = default;
+
+  Q_SLOT
+  void aSlot();
+};
+
+void SubObjA::aSlot()
+{
+}
+
+void ObjA::go()
+{
+  SubObjA subObj;
+}
+
+#include "ObjA.moc"
diff --git a/Tests/QtAutogen/mocInclude/ObjA.hpp b/Tests/QtAutogen/mocInclude/ObjA.hpp
new file mode 100644
index 0000000..281e90d
--- /dev/null
+++ b/Tests/QtAutogen/mocInclude/ObjA.hpp
@@ -0,0 +1,13 @@
+#ifndef OBJA_HPP
+#define OBJA_HPP
+
+#include <QObject>
+
+class ObjA : public QObject
+{
+  Q_OBJECT
+  Q_SLOT
+  void go();
+};
+
+#endif
diff --git a/Tests/QtAutogen/mocInclude/ObjB.cpp b/Tests/QtAutogen/mocInclude/ObjB.cpp
new file mode 100644
index 0000000..abec06a
--- /dev/null
+++ b/Tests/QtAutogen/mocInclude/ObjB.cpp
@@ -0,0 +1,25 @@
+#include "ObjB.hpp"
+
+class SubObjB : public QObject
+{
+  Q_OBJECT
+
+public:
+  SubObjB() = default;
+  ~SubObjB() = default;
+
+  Q_SLOT
+  void aSlot();
+};
+
+void SubObjB::aSlot()
+{
+}
+
+void ObjB::go()
+{
+  SubObjB subObj;
+}
+
+#include "ObjB.moc"
+#include "moc_ObjB.cpp"
diff --git a/Tests/QtAutogen/mocInclude/ObjB.hpp b/Tests/QtAutogen/mocInclude/ObjB.hpp
new file mode 100644
index 0000000..94f3d49
--- /dev/null
+++ b/Tests/QtAutogen/mocInclude/ObjB.hpp
@@ -0,0 +1,13 @@
+#ifndef OBJB_HPP
+#define OBJB_HPP
+
+#include <QObject>
+
+class ObjB : public QObject
+{
+  Q_OBJECT
+  Q_SLOT
+  void go();
+};
+
+#endif
diff --git a/Tests/QtAutogen/mocInclude/ObjC.cpp b/Tests/QtAutogen/mocInclude/ObjC.cpp
new file mode 100644
index 0000000..bdcdb13
--- /dev/null
+++ b/Tests/QtAutogen/mocInclude/ObjC.cpp
@@ -0,0 +1,26 @@
+#include "ObjC.hpp"
+
+class SubObjC : public QObject
+{
+  Q_OBJECT
+
+public:
+  SubObjC() = default;
+  ~SubObjC() = default;
+
+  Q_SLOT
+  void aSlot();
+};
+
+void SubObjC::aSlot()
+{
+}
+
+void ObjC::go()
+{
+  SubObjC subObj;
+}
+
+#include "ObjC.moc"
+// Not the own header
+#include "moc_ObjD.cpp"
diff --git a/Tests/QtAutogen/mocInclude/ObjC.hpp b/Tests/QtAutogen/mocInclude/ObjC.hpp
new file mode 100644
index 0000000..a8e98eb
--- /dev/null
+++ b/Tests/QtAutogen/mocInclude/ObjC.hpp
@@ -0,0 +1,13 @@
+#ifndef OBJC_HPP
+#define OBJC_HPP
+
+#include <QObject>
+
+class ObjC : public QObject
+{
+  Q_OBJECT
+  Q_SLOT
+  void go();
+};
+
+#endif
diff --git a/Tests/QtAutogen/mocInclude/ObjD.cpp b/Tests/QtAutogen/mocInclude/ObjD.cpp
new file mode 100644
index 0000000..9145ba3
--- /dev/null
+++ b/Tests/QtAutogen/mocInclude/ObjD.cpp
@@ -0,0 +1,26 @@
+#include "ObjD.hpp"
+
+class SubObjD : public QObject
+{
+  Q_OBJECT
+
+public:
+  SubObjD() = default;
+  ~SubObjD() = default;
+
+  Q_SLOT
+  void aSlot();
+};
+
+void SubObjD::aSlot()
+{
+}
+
+void ObjD::go()
+{
+  SubObjD subObj;
+}
+
+#include "ObjD.moc"
+// Header in subdirectory
+#include "subA/moc_SubObjA.cpp"
diff --git a/Tests/QtAutogen/mocInclude/ObjD.hpp b/Tests/QtAutogen/mocInclude/ObjD.hpp
new file mode 100644
index 0000000..b6ee098
--- /dev/null
+++ b/Tests/QtAutogen/mocInclude/ObjD.hpp
@@ -0,0 +1,13 @@
+#ifndef OBJD_HPP
+#define OBJD_HPP
+
+#include <QObject>
+
+class ObjD : public QObject
+{
+  Q_OBJECT
+  Q_SLOT
+  void go();
+};
+
+#endif
diff --git a/Tests/QtAutogen/mocInclude/subA/SubObjA.cpp b/Tests/QtAutogen/mocInclude/subA/SubObjA.cpp
new file mode 100644
index 0000000..d780942
--- /dev/null
+++ b/Tests/QtAutogen/mocInclude/subA/SubObjA.cpp
@@ -0,0 +1,27 @@
+#include "SubObjA.hpp"
+
+namespace subA {
+
+class SubObjA : public QObject
+{
+  Q_OBJECT
+
+public:
+  SubObjA() = default;
+  ~SubObjA() = default;
+
+  Q_SLOT
+  void aSlot();
+};
+
+void SubObjA::aSlot()
+{
+}
+
+void ObjA::go()
+{
+  SubObjA subObj;
+}
+}
+
+#include "SubObjA.moc"
diff --git a/Tests/QtAutogen/mocInclude/subA/SubObjA.hpp b/Tests/QtAutogen/mocInclude/subA/SubObjA.hpp
new file mode 100644
index 0000000..31a18b6
--- /dev/null
+++ b/Tests/QtAutogen/mocInclude/subA/SubObjA.hpp
@@ -0,0 +1,16 @@
+#ifndef SUBOBJA_HPP
+#define SUBOBJA_HPP
+
+#include <QObject>
+
+namespace subA {
+
+class ObjA : public QObject
+{
+  Q_OBJECT
+  Q_SLOT
+  void go();
+};
+}
+
+#endif
diff --git a/Tests/QtAutogen/mocInclude/subB/SubObjB.cpp b/Tests/QtAutogen/mocInclude/subB/SubObjB.cpp
new file mode 100644
index 0000000..e602e06
--- /dev/null
+++ b/Tests/QtAutogen/mocInclude/subB/SubObjB.cpp
@@ -0,0 +1,27 @@
+#include "SubObjB.hpp"
+
+namespace subB {
+
+class SubObjB : public QObject
+{
+  Q_OBJECT
+
+public:
+  SubObjB() = default;
+  ~SubObjB() = default;
+
+  Q_SLOT
+  void aSlot();
+};
+
+void SubObjB::aSlot()
+{
+}
+
+void ObjB::go()
+{
+  SubObjB subObj;
+}
+}
+
+#include "SubObjB.moc"
diff --git a/Tests/QtAutogen/mocInclude/subB/SubObjB.hpp b/Tests/QtAutogen/mocInclude/subB/SubObjB.hpp
new file mode 100644
index 0000000..3f29fa2
--- /dev/null
+++ b/Tests/QtAutogen/mocInclude/subB/SubObjB.hpp
@@ -0,0 +1,16 @@
+#ifndef SUBOBJB_HPP
+#define SUBOBJB_HPP
+
+#include <QObject>
+
+namespace subB {
+
+class ObjB : public QObject
+{
+  Q_OBJECT
+  Q_SLOT
+  void go();
+};
+}
+
+#endif
diff --git a/Tests/QtAutogen/mocInclude/subC/SubObjC.cpp b/Tests/QtAutogen/mocInclude/subC/SubObjC.cpp
new file mode 100644
index 0000000..fb2d1ec
--- /dev/null
+++ b/Tests/QtAutogen/mocInclude/subC/SubObjC.cpp
@@ -0,0 +1,27 @@
+#include "SubObjC.hpp"
+
+namespace subC {
+
+class SubObjC : public QObject
+{
+  Q_OBJECT
+
+public:
+  SubObjC() = default;
+  ~SubObjC() = default;
+
+  Q_SLOT
+  void aSlot();
+};
+
+void SubObjC::aSlot()
+{
+}
+
+void ObjC::go()
+{
+  SubObjC subObj;
+}
+}
+
+#include "SubObjC.moc"
diff --git a/Tests/QtAutogen/mocInclude/subC/SubObjC.hpp b/Tests/QtAutogen/mocInclude/subC/SubObjC.hpp
new file mode 100644
index 0000000..dc251fd
--- /dev/null
+++ b/Tests/QtAutogen/mocInclude/subC/SubObjC.hpp
@@ -0,0 +1,16 @@
+#ifndef SUBOBJC_HPP
+#define SUBOBJC_HPP
+
+#include <QObject>
+
+namespace subC {
+
+class ObjC : public QObject
+{
+  Q_OBJECT
+  Q_SLOT
+  void go();
+};
+}
+
+#endif
diff --git a/Tests/QtAutogen/mocIncludeRelaxed/CMakeLists.txt b/Tests/QtAutogen/mocIncludeRelaxed/CMakeLists.txt
new file mode 100644
index 0000000..6a0829d
--- /dev/null
+++ b/Tests/QtAutogen/mocIncludeRelaxed/CMakeLists.txt
@@ -0,0 +1,18 @@
+# Test moc include patterns
+
+set(CMAKE_AUTOMOC_RELAXED_MODE TRUE)
+
+include_directories("../mocInclude")
+
+add_executable(mocIncludeRelaxed
+  ../mocInclude/ObjA.cpp
+  ../mocInclude/ObjB.cpp
+  ../mocInclude/ObjC.cpp
+  ../mocInclude/ObjD.cpp
+  ../mocInclude/subA/SubObjA.cpp
+  ../mocInclude/subB/SubObjB.cpp
+  ../mocInclude/subC/SubObjC.cpp
+  main.cpp
+)
+target_link_libraries(mocIncludeRelaxed ${QT_LIBRARIES})
+set_target_properties(mocIncludeRelaxed PROPERTIES AUTOMOC ON)
diff --git a/Tests/QtAutogen/mocIncludeRelaxed/main.cpp b/Tests/QtAutogen/mocIncludeRelaxed/main.cpp
new file mode 100644
index 0000000..142d59e
--- /dev/null
+++ b/Tests/QtAutogen/mocIncludeRelaxed/main.cpp
@@ -0,0 +1,14 @@
+#include "ObjA.hpp"
+#include "ObjB.hpp"
+#include "ObjC.hpp"
+
+int main(int argv, char** args)
+{
+  ObjA objA;
+  ObjB objB;
+  ObjC objC;
+  return 0;
+}
+
+// Header in global subdirectory
+#include "subB/moc_SubObjB.cpp"
diff --git a/Tests/QtAutogen/mocIncludeStrict/CMakeLists.txt b/Tests/QtAutogen/mocIncludeStrict/CMakeLists.txt
new file mode 100644
index 0000000..22e93a8
--- /dev/null
+++ b/Tests/QtAutogen/mocIncludeStrict/CMakeLists.txt
@@ -0,0 +1,18 @@
+# Test moc include patterns
+
+set(CMAKE_AUTOMOC_RELAXED_MODE FALSE)
+
+include_directories("../mocInclude")
+
+add_executable(mocIncludeStrict
+  ../mocInclude/ObjA.cpp
+  ../mocInclude/ObjB.cpp
+  ../mocInclude/ObjC.cpp
+  ../mocInclude/ObjD.cpp
+  ../mocInclude/subA/SubObjA.cpp
+  ../mocInclude/subB/SubObjB.cpp
+  ../mocInclude/subC/SubObjC.cpp
+  main.cpp
+)
+target_link_libraries(mocIncludeStrict ${QT_LIBRARIES})
+set_target_properties(mocIncludeStrict PROPERTIES AUTOMOC ON)
diff --git a/Tests/QtAutogen/mocIncludeStrict/main.cpp b/Tests/QtAutogen/mocIncludeStrict/main.cpp
new file mode 100644
index 0000000..142d59e
--- /dev/null
+++ b/Tests/QtAutogen/mocIncludeStrict/main.cpp
@@ -0,0 +1,14 @@
+#include "ObjA.hpp"
+#include "ObjB.hpp"
+#include "ObjC.hpp"
+
+int main(int argv, char** args)
+{
+  ObjA objA;
+  ObjB objB;
+  ObjC objC;
+  return 0;
+}
+
+// Header in global subdirectory
+#include "subB/moc_SubObjB.cpp"

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=4be7c81272e559b1ff572df5f5b274234a04a286
commit 4be7c81272e559b1ff572df5f5b274234a04a286
Author:     Sebastian Holtermann <sebholt at xwmw.org>
AuthorDate: Thu Feb 16 15:05:11 2017 +0100
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Mon Feb 20 15:51:26 2017 -0500

    Autogen: Tests: Clean comments

diff --git a/Tests/QtAutogen/CMakeLists.txt b/Tests/QtAutogen/CMakeLists.txt
index 4b90ad8..c1cdee2 100644
--- a/Tests/QtAutogen/CMakeLists.txt
+++ b/Tests/QtAutogen/CMakeLists.txt
@@ -46,26 +46,26 @@ endif()
 
 get_property(QT_COMPILE_FEATURES TARGET ${QT_QTCORE_TARGET} PROPERTY INTERFACE_COMPILE_FEATURES)
 
-# -- Test: AUTORCC
+# -- Test
 # RCC only
 add_executable(rccOnly rccOnly.cpp rccOnlyRes.qrc)
 set_property(TARGET rccOnly PROPERTY AUTORCC ON)
 target_link_libraries(rccOnly ${QT_QTCORE_TARGET})
 
-# -- Test: AUTORCC
+# -- Test
 # RCC empty
 add_executable(rccEmpty rccEmpty.cpp rccEmptyRes.qrc)
 set_property(TARGET rccEmpty PROPERTY AUTORCC ON)
 target_link_libraries(rccEmpty ${QT_QTCORE_TARGET})
 
-# -- Test: AUTOUIC
+# -- Test
 # UIC only
 qtx_wrap_cpp(uicOnlyMoc uicOnlySource/uiconly.h)
 add_executable(uicOnly uicOnlySource/uiconly.cpp ${uicOnlyMoc})
 set_property(TARGET uicOnly PROPERTY AUTOUIC ON)
 target_link_libraries(uicOnly ${QT_LIBRARIES})
 
-# -- Test: AUTOMOC, AUTORCC
+# -- Test
 # Add not_generated_file.qrc to the source list to get the file-level
 # dependency, but don't generate a c++ file from it.  Disable the AUTORCC
 # feature for this target.  This tests that qrc files in the sources don't
@@ -80,7 +80,7 @@ set_target_properties(no_link_language PROPERTIES AUTOMOC TRUE)
 target_compile_features(no_link_language PRIVATE ${QT_COMPILE_FEATURES})
 target_compile_features(empty PRIVATE ${QT_COMPILE_FEATURES})
 
-# -- Test: AUTORCC
+# -- Test
 # When a file listed in a .qrc file changes the target must be rebuilt
 try_compile(RCC_DEPENDS
   "${CMAKE_CURRENT_BINARY_DIR}/autorcc_depends"
@@ -115,7 +115,7 @@ if (NOT file1_step1 GREATER file1_before)
   message(SEND_ERROR "file1 (${qrc_file1}) should have changed in the first step!")
 endif()
 
-# -- Test: AUTOMOC
+# -- Test
 # Ensure a repeated build succeeds when a header containing a QObject changes
 try_compile(MOC_RERUN
   "${CMAKE_CURRENT_BINARY_DIR}/automoc_rerun"
@@ -139,7 +139,7 @@ if (automoc_rerun_result)
   message(SEND_ERROR "Second build of automoc_rerun failed.")
 endif()
 
-# -- Test: AUTOMOC, SKIP_AUTOMOC
+# -- Test
 # Test for SKIP_AUTOMOC and SKIP_AUTOGEN on an AUTOMOC enabled target
 qtx_wrap_cpp(skipMocWrapMoc
   skipSource/qItemA.hpp
@@ -161,7 +161,7 @@ set_property(TARGET skipMocB PROPERTY AUTOMOC ON)
 set_property(TARGET skipMocB PROPERTY AUTOUIC ON)
 target_link_libraries(skipMocB ${QT_LIBRARIES})
 
-# -- Test: AUTOUIC, SKIP_AUTOUIC
+# -- Test
 # Test for SKIP_AUTOUIC and SKIP_AUTOGEN on an AUTOUIC enabled target
 set(skipUicSources
   skipUic.cpp
@@ -181,7 +181,7 @@ set_property(TARGET skipUicB PROPERTY AUTOUIC ON)
 set_property(TARGET skipUicB PROPERTY AUTOMOC ON)
 target_link_libraries(skipUicB ${QT_LIBRARIES})
 
-# -- Test: AUTORCC, SKIP_AUTORCC
+# -- Test
 # Test for SKIP_AUTORCC and SKIP_AUTOGEN on an AUTORCC enabled target
 set(skipRccSources
   skipRcc.cpp
@@ -202,10 +202,10 @@ set_property(TARGET skipRccB PROPERTY AUTOUIC ON)
 set_property(TARGET skipRccB PROPERTY AUTOMOC ON)
 target_link_libraries(skipRccB ${QT_LIBRARIES})
 
-# -- Test: AUTOMOC AUTORCC
+# -- Test
 # Source files with the same basename in different subdirectories
 add_subdirectory(sameName)
 
-# -- Test: AUTOMOC AUTORCC AUTOUIC
+# -- Test
 # Complex test case
 add_subdirectory(complex)

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=0136d1354b5957a1d583526dfdb74f176939f56c
commit 0136d1354b5957a1d583526dfdb74f176939f56c
Author:     Sebastian Holtermann <sebholt at xwmw.org>
AuthorDate: Fri Feb 17 18:44:10 2017 +0100
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Mon Feb 20 15:51:26 2017 -0500

    Autogen: Log simplifications
    
    The logging methods now automatically add an end-of-line
    to the message if it is missing.

diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx
index 7c7ad83..199e5cc 100644
--- a/Source/cmQtAutoGenerators.cxx
+++ b/Source/cmQtAutoGenerators.cxx
@@ -464,9 +464,7 @@ bool cmQtAutoGenerators::SettingsFileWrite(const std::string& targetDirectory)
   if (this->GenerateAllAny()) {
     const std::string filename = SettingsFile(targetDirectory);
     if (this->Verbose) {
-      std::ostringstream err;
-      err << "AutoGen: Writing settings file " << filename << "\n";
-      this->LogInfo(err.str());
+      this->LogInfo("AutoGen: Writing settings file " + filename);
     }
     cmsys::ofstream outfile;
     outfile.open(filename.c_str(), std::ios::trunc);
@@ -482,8 +480,8 @@ bool cmQtAutoGenerators::SettingsFileWrite(const std::string& targetDirectory)
       cmSystemTools::RemoveFile(filename);
       {
         std::ostringstream err;
-        err << "AutoGen: Error: Writing old settings file failed: " << filename
-            << std::endl;
+        err << "AutoGen: Error: Writing old settings file failed: "
+            << filename;
         this->LogError(err.str());
       }
     }
@@ -685,12 +683,12 @@ void cmQtAutoGenerators::MocFindDepends(
             mocDepends[absFilename].insert(incFile);
             if (this->Verbose) {
               this->LogInfo("AutoMoc: Found dependency:\n  \"" + absFilename +
-                            "\"\n  \"" + incFile + "\"\n");
+                            "\"\n  \"" + incFile + "\"");
             }
           } else {
             this->LogWarning("AutoMoc: Warning: \"" + absFilename + "\"\n" +
                              "Could not find dependency file \"" + match +
-                             "\"\n");
+                             "\"");
           }
         }
         contentChars += filter.regExp.end();
@@ -740,10 +738,10 @@ bool cmQtAutoGenerators::ParseSourceFile(
   bool success = true;
   const std::string contentText = ReadAll(absFilename);
   if (contentText.empty()) {
-    std::ostringstream err;
-    err << "AutoGen: Warning: " << absFilename << "\n"
+    std::ostringstream ost;
+    ost << "AutoGen: Warning: " << absFilename << "\n"
         << "The file is empty\n";
-    this->LogWarning(err.str());
+    this->LogWarning(ost.str());
   } else {
     // Parse source contents for MOC
     if (success && !this->MocSkip(absFilename)) {
@@ -763,9 +761,7 @@ void cmQtAutoGenerators::UicParseContent(
   std::map<std::string, std::vector<std::string> >& uisIncluded)
 {
   if (this->Verbose) {
-    std::ostringstream err;
-    err << "AutoUic: Checking " << absFilename << "\n";
-    this->LogInfo(err.str());
+    this->LogInfo("AutoUic: Checking " + absFilename);
   }
 
   const char* contentChars = contentText.c_str();
@@ -791,9 +787,7 @@ bool cmQtAutoGenerators::MocParseSourceContent(
   std::map<std::string, std::set<std::string> >& mocDepends, bool relaxed)
 {
   if (this->Verbose) {
-    std::ostringstream err;
-    err << "AutoMoc: Checking " << absFilename << "\n";
-    this->LogInfo(err.str());
+    this->LogInfo("AutoMoc: Checking " + absFilename);
   }
 
   const std::string scannedFileAbsPath =
@@ -845,12 +839,12 @@ bool cmQtAutoGenerators::MocParseSourceContent(
             ownMocUnderscoreHeader = headerToMoc;
           }
         } else {
-          std::ostringstream err;
-          err << "AutoMoc: Error: " << absFilename << "\n"
+          std::ostringstream ost;
+          ost << "AutoMoc: Error: " << absFilename << "\n"
               << "The file includes the moc file \"" << incString
               << "\", but could not find header \"" << incRealBasename << '{'
               << JoinExts(this->HeaderExtensions) << "}\"\n";
-          this->LogError(err.str());
+          this->LogError(ost.str());
           return false;
         }
       } else {
@@ -870,34 +864,34 @@ bool cmQtAutoGenerators::MocParseSourceContent(
               // This is for KDE4 compatibility:
               fileToMoc = headerToMoc;
               if (!requiresMoc && (incBasename == scannedFileBasename)) {
-                std::ostringstream err;
-                err << "AutoMoc: Warning: " << absFilename << "\n"
+                std::ostringstream ost;
+                ost << "AutoMoc: Warning: " << absFilename << "\n"
                     << "The file includes the moc file \"" << incString << "\""
                     << ", but does not contain a Q_OBJECT or Q_GADGET macro.\n"
                     << "Running moc on \"" << headerToMoc << "\"!\n"
                     << "Include \"moc_" << incBasename
                     << ".cpp\" for a compatibility with "
                        "strict mode (see CMAKE_AUTOMOC_RELAXED_MODE).\n";
-                this->LogWarning(err.str());
+                this->LogWarning(ost.str());
               } else {
-                std::ostringstream err;
-                err << "AutoMoc: Warning: " << absFilename << "\n"
+                std::ostringstream ost;
+                ost << "AutoMoc: Warning: " << absFilename << "\n"
                     << "The file includes the moc file \"" << incString
                     << "\" instead of \"moc_" << incBasename << ".cpp\".\n"
                     << "Running moc on \"" << headerToMoc << "\"!\n"
                     << "Include \"moc_" << incBasename
                     << ".cpp\" for compatibility with "
                        "strict mode (see CMAKE_AUTOMOC_RELAXED_MODE).\n";
-                this->LogWarning(err.str());
+                this->LogWarning(ost.str());
               }
             } else {
-              std::ostringstream err;
-              err << "AutoMoc: Error: " << absFilename << "\n"
+              std::ostringstream ost;
+              ost << "AutoMoc: Error: " << absFilename << "\n"
                   << "The file includes the moc file \"" << incString
                   << "\", which seems to be the moc file from a different "
                      "source file. CMake also could not find a matching "
                      "header.\n";
-              this->LogError(err.str());
+              this->LogError(ost.str());
               return false;
             }
           }
@@ -909,23 +903,23 @@ bool cmQtAutoGenerators::MocParseSourceContent(
             ownDotMocIncluded = true;
             // Accept but issue a warning if moc isn't required
             if (!requiresMoc) {
-              std::ostringstream err;
-              err << "AutoMoc: Error: " << absFilename << "\n"
+              std::ostringstream ost;
+              ost << "AutoMoc: Error: " << absFilename << "\n"
                   << "The file includes the moc file \"" << incString << "\""
                   << ", but does not contain a Q_OBJECT or Q_GADGET "
                      "macro.\n";
-              this->LogWarning(err.str());
+              this->LogWarning(ost.str());
             }
           } else {
             // Don't allow FOO.moc include other than self in strict mode
-            std::ostringstream err;
-            err << "AutoMoc: Error: " << absFilename << "\n"
+            std::ostringstream ost;
+            ost << "AutoMoc: Error: " << absFilename << "\n"
                 << "The file includes the moc file \"" << incString
                 << "\", which seems to be the moc file from a different "
                    "source file. This is not supported. Include \""
                 << scannedFileBasename
                 << ".moc\" to run moc on this source file.\n";
-            this->LogError(err.str());
+            this->LogError(ost.str());
             return false;
           }
         }
@@ -946,8 +940,8 @@ bool cmQtAutoGenerators::MocParseSourceContent(
     // But warn, since this is not how it is supposed to be used.
     if (relaxed && !ownMocUnderscoreInclude.empty()) {
       // This is for KDE4 compatibility:
-      std::ostringstream err;
-      err << "AutoMoc: Warning: " << absFilename << "\n"
+      std::ostringstream ost;
+      ost << "AutoMoc: Warning: " << absFilename << "\n"
           << "The file contains a " << macroName
           << " macro, but does not include "
           << "\"" << scannedFileBasename << ".moc\", but instead includes "
@@ -956,7 +950,7 @@ bool cmQtAutoGenerators::MocParseSourceContent(
           << "Better include \"" << scannedFileBasename
           << ".moc\" for compatibility with "
              "strict mode (see CMAKE_AUTOMOC_RELAXED_MODE).\n";
-      this->LogWarning(err.str());
+      this->LogWarning(ost.str());
 
       // Use scanned source file instead of scanned header file as moc source
       mocsIncluded[absFilename] = ownMocUnderscoreInclude;
@@ -965,12 +959,12 @@ bool cmQtAutoGenerators::MocParseSourceContent(
       mocsIncluded.erase(ownMocUnderscoreHeader);
     } else {
       // Otherwise always error out since it will not compile:
-      std::ostringstream err;
-      err << "AutoMoc: Error: " << absFilename << "\n"
+      std::ostringstream ost;
+      ost << "AutoMoc: Error: " << absFilename << "\n"
           << "The file contains a " << macroName
           << " macro, but does not include "
           << "\"" << scannedFileBasename << ".moc\"!\n";
-      this->LogError(err.str());
+      this->LogError(ost.str());
       return false;
     }
   }
@@ -985,9 +979,7 @@ void cmQtAutoGenerators::MocParseHeaderContent(
 {
   // Log
   if (this->Verbose) {
-    std::ostringstream err;
-    err << "AutoMoc: Checking " << absFilename << "\n";
-    this->LogInfo(err.str());
+    this->LogInfo("AutoMoc: Checking " + absFilename);
   }
   if (this->MocRequired(contentText)) {
     // Register moc job
@@ -1079,15 +1071,14 @@ bool cmQtAutoGenerators::MocGenerateAll(
     std::map<std::string, std::string> mergedMocs(mocsIncluded);
     mergedMocs.insert(mocsNotIncluded.begin(), mocsNotIncluded.end());
     if (this->NameCollisionTest(mergedMocs, collisions)) {
-      std::ostringstream err;
-      err << "AutoMoc: Error: "
+      std::ostringstream ost;
+      ost << "AutoMoc: 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->LogErrorNameCollision(err.str(), collisions);
+             "from different sources.\n"
+             "To avoid this error either\n"
+             "- rename the source files or\n"
+             "- do not include the (moc_NAME.cpp|NAME.moc) file";
+      this->LogErrorNameCollision(ost.str(), collisions);
       return false;
     }
   }
@@ -1123,21 +1114,20 @@ bool cmQtAutoGenerators::MocGenerateAll(
   // Compose moc_compilation.cpp content
   std::string automocSource;
   {
-    std::ostringstream outStream;
-    outStream << "/* This file is autogenerated, do not edit*/\n";
+    std::ostringstream ost;
+    ost << "/* This file is autogenerated, do not edit*/\n";
     if (mocsNotIncluded.empty()) {
       // Dummy content
-      outStream << "enum some_compilers { need_more_than_nothing };\n";
+      ost << "enum some_compilers { need_more_than_nothing };\n";
     } else {
       // Valid content
       for (std::map<std::string, std::string>::const_iterator it =
              mocsNotIncluded.begin();
            it != mocsNotIncluded.end(); ++it) {
-        outStream << "#include \"" << it->second << "\"\n";
+        ost << "#include \"" << it->second << "\"\n";
       }
     }
-    outStream.flush();
-    automocSource = outStream.str();
+    automocSource = ost.str();
   }
 
   // Check if the content of moc_compilation.cpp changed
@@ -1158,25 +1148,20 @@ bool cmQtAutoGenerators::MocGenerateAll(
       outfile.open(this->MocCppFilenameAbs.c_str(), std::ios::trunc);
       if (!outfile) {
         success = false;
-        std::ostringstream err;
-        err << "AutoMoc: error opening " << this->MocCppFilenameAbs << "\n";
-        this->LogError(err.str());
+        this->LogError("AutoMoc: error opening " + this->MocCppFilenameAbs);
       } else {
         outfile << automocSource;
         // Check for write errors
         if (!outfile.good()) {
           success = false;
-          std::ostringstream err;
-          err << "AutoMoc: error writing " << this->MocCppFilenameAbs << "\n";
-          this->LogError(err.str());
+          this->LogError("AutoMoc: error writing " + this->MocCppFilenameAbs);
         }
       }
     }
   } else if (mocCompFileGenerated) {
     // Only touch moc_compilation.cpp
     if (this->Verbose) {
-      this->LogInfo("Touching MOC compilation " + this->MocCppFilenameRel +
-                    "\n");
+      this->LogInfo("Touching MOC compilation " + this->MocCppFilenameRel);
     }
     cmSystemTools::Touch(this->MocCppFilenameAbs, false);
   }
@@ -1256,12 +1241,12 @@ bool cmQtAutoGenerators::MocGenerateFile(
       if (!res || (retVal != 0)) {
         // Command failed
         {
-          std::ostringstream err;
-          err << "AutoMoc: Error: moc process failed for\n";
-          err << "\"" << mocFileRel << "\"\n";
-          err << "AutoMoc: Command:\n" << cmJoin(cmd, " ") << "\n";
-          err << "AutoMoc: Command output:\n" << output << "\n";
-          this->LogError(err.str());
+          std::ostringstream ost;
+          ost << "AutoMoc: Error: moc process failed for\n";
+          ost << "\"" << mocFileRel << "\"\n";
+          ost << "AutoMoc: Command:\n" << cmJoin(cmd, " ") << "\n";
+          ost << "AutoMoc: Command output:\n" << output << "\n";
+          this->LogError(ost.str());
         }
         cmSystemTools::RemoveFile(mocFileAbs);
         this->RunMocFailed = true;
@@ -1310,12 +1295,11 @@ bool cmQtAutoGenerators::UicGenerateAll(
   {
     std::multimap<std::string, std::string> collisions;
     if (this->NameCollisionTest(testMap, collisions)) {
-      std::ostringstream err;
-      err << "AutoUic: 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->LogErrorNameCollision(err.str(), 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;
     }
   }
@@ -1396,13 +1380,13 @@ bool cmQtAutoGenerators::UicGenerateFile(const std::string& realName,
       if (!res || (retVal != 0)) {
         // Command failed
         {
-          std::ostringstream err;
-          err << "AutoUic: Error: uic process failed for\n";
-          err << "\"" << uicFileRel << "\" needed by\n";
-          err << "\"" << realName << "\"\n";
-          err << "AutoUic: Command:\n" << cmJoin(cmd, " ") << "\n";
-          err << "AutoUic: Command output:\n" << output << "\n";
-          this->LogError(err.str());
+          std::ostringstream ost;
+          ost << "AutoUic: Error: uic process failed for\n";
+          ost << "\"" << uicFileRel << "\" needed by\n";
+          ost << "\"" << realName << "\"\n";
+          ost << "AutoUic: Command:\n" << cmJoin(cmd, " ") << "\n";
+          ost << "AutoUic: Command output:\n" << output << "\n";
+          this->LogError(ost.str());
         }
         cmSystemTools::RemoveFile(uicFileAbs);
         this->RunUicFailed = true;
@@ -1439,12 +1423,11 @@ bool cmQtAutoGenerators::RccGenerateAll()
   {
     std::multimap<std::string, std::string> collisions;
     if (this->NameCollisionTest(qrcGenMap, collisions)) {
-      std::ostringstream err;
-      err << "AutoRcc: 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->LogErrorNameCollision(err.str(), collisions);
+      std::ostringstream ost;
+      ost << "AutoRcc: Error: The same qrc_NAME.cpp file"
+             " will be generated from different sources.\n"
+             "To avoid this error rename the source .qrc files.\n";
+      this->LogErrorNameCollision(ost.str(), collisions);
       return false;
     }
   }
@@ -1536,12 +1519,12 @@ bool cmQtAutoGenerators::RccGenerateFile(const std::string& rccInputFile,
       if (!res || (retVal != 0)) {
         // Command failed
         {
-          std::ostringstream err;
-          err << "AutoRcc: Error: rcc process failed for\n";
-          err << "\"" << rccOutputFile << "\"\n";
-          err << "AutoRcc: Command:\n" << cmJoin(cmd, " ") << "\n";
-          err << "AutoRcc: Command output:\n" << output << "\n";
-          this->LogError(err.str());
+          std::ostringstream ost;
+          ost << "AutoRcc: Error: rcc process failed for\n";
+          ost << "\"" << rccOutputFile << "\"\n";
+          ost << "AutoRcc: Command:\n" << cmJoin(cmd, " ") << "\n";
+          ost << "AutoRcc: Command output:\n" << output << "\n";
+          this->LogError(ost.str());
         }
         cmSystemTools::RemoveFile(rccBuildFile);
         this->RunRccFailed = true;
@@ -1559,18 +1542,23 @@ bool cmQtAutoGenerators::RccGenerateFile(const std::string& rccInputFile,
 
 void cmQtAutoGenerators::LogErrorNameCollision(
   const std::string& message,
-  const std::multimap<std::string, std::string>& collisions)
+  const std::multimap<std::string, std::string>& collisions) const
 {
   typedef std::multimap<std::string, std::string>::const_iterator Iter;
 
-  std::ostringstream err;
+  std::ostringstream ost;
   // Add message
-  err << message;
+  if (!message.empty()) {
+    ost << message;
+    if (message[message.size() - 1] != '\n') {
+      ost << '\n';
+    }
+  }
   // Append collision list
   for (Iter it = collisions.begin(); it != collisions.end(); ++it) {
-    err << it->first << " : " << it->second << std::endl;
+    ost << it->first << " : " << it->second << '\n';
   }
-  this->LogError(err.str());
+  this->LogError(ost.str());
 }
 
 void cmQtAutoGenerators::LogBold(const std::string& message) const
@@ -1582,38 +1570,45 @@ void cmQtAutoGenerators::LogBold(const std::string& message) const
 
 void cmQtAutoGenerators::LogInfo(const std::string& message) const
 {
-  cmSystemTools::Stdout(message.c_str(), message.size());
+  std::string msg(message);
+  if (!msg.empty()) {
+    if (msg[msg.size() - 1] != '\n') {
+      msg.push_back('\n');
+    }
+    cmSystemTools::Stdout(msg.c_str(), msg.size());
+  }
 }
 
 void cmQtAutoGenerators::LogWarning(const std::string& message) const
 {
   std::string msg(message);
-  msg += "\n";
-  cmSystemTools::Stdout(msg.c_str(), msg.size());
+  if (!msg.empty()) {
+    if (msg[msg.size() - 1] != '\n') {
+      msg.push_back('\n');
+    }
+    // Append empty line
+    msg.push_back('\n');
+    cmSystemTools::Stdout(msg.c_str(), msg.size());
+  }
 }
 
 void cmQtAutoGenerators::LogError(const std::string& message) const
 {
   std::string msg(message);
-  msg += "\n";
-  cmSystemTools::Stderr(msg.c_str(), msg.size());
+  if (!msg.empty()) {
+    if (msg[msg.size() - 1] != '\n') {
+      msg.push_back('\n');
+    }
+    // Append empty line
+    msg.push_back('\n');
+    cmSystemTools::Stderr(msg.c_str(), msg.size());
+  }
 }
 
 void cmQtAutoGenerators::LogCommand(
   const std::vector<std::string>& command) const
 {
-  std::ostringstream sbuf;
-  for (std::vector<std::string>::const_iterator cmdIt = command.begin();
-       cmdIt != command.end(); ++cmdIt) {
-    if (cmdIt != command.begin()) {
-      sbuf << " ";
-    }
-    sbuf << *cmdIt;
-  }
-  if (!sbuf.str().empty()) {
-    sbuf << std::endl;
-    this->LogInfo(sbuf.str());
-  }
+  this->LogInfo(cmJoin(command, " "));
 }
 
 /**
@@ -1736,7 +1731,7 @@ std::string cmQtAutoGenerators::FindIncludedFile(
       return cmsys::SystemTools::GetRealPath(testPath);
     }
   }
-  // Search globaly
+  // Search globally
   return FindInIncludeDirectories(includeString);
 }
 
@@ -1764,16 +1759,14 @@ std::string cmQtAutoGenerators::FindInIncludeDirectories(
  * @brief Generates the parent directory of the given file on demand
  * @return True on success
  */
-bool cmQtAutoGenerators::MakeParentDirectory(const std::string& filename)
+bool cmQtAutoGenerators::MakeParentDirectory(const std::string& filename) const
 {
   bool success = true;
   const std::string dirName = cmSystemTools::GetFilenamePath(filename);
   if (!dirName.empty()) {
     success = cmsys::SystemTools::MakeDirectory(dirName);
     if (!success) {
-      std::ostringstream err;
-      err << "AutoGen: Directory creation failed: " << dirName << std::endl;
-      this->LogError(err.str());
+      this->LogError("AutoGen: Directory creation failed: " + dirName);
     }
   }
   return success;
diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGenerators.h
index 9fd5c58..236d4c5 100644
--- a/Source/cmQtAutoGenerators.h
+++ b/Source/cmQtAutoGenerators.h
@@ -123,7 +123,7 @@ private:
   // - Logging
   void LogErrorNameCollision(
     const std::string& message,
-    const std::multimap<std::string, std::string>& collisions);
+    const std::multimap<std::string, std::string>& collisions) const;
   void LogBold(const std::string& message) const;
   void LogInfo(const std::string& message) const;
   void LogWarning(const std::string& message) const;
@@ -137,7 +137,7 @@ private:
   std::string ChecksumedPath(const std::string& sourceFile,
                              const char* basePrefix,
                              const char* baseSuffix) const;
-  bool MakeParentDirectory(const std::string& filename);
+  bool MakeParentDirectory(const std::string& filename) const;
 
   bool FindHeader(std::string& header, const std::string& testBasePath) const;
   bool FindHeaderGlobal(std::string& header,

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=1fc9fe74dab4276b22abfd1a79fc344945350227
commit 1fc9fe74dab4276b22abfd1a79fc344945350227
Author:     Sebastian Holtermann <sebholt at xwmw.org>
AuthorDate: Fri Feb 17 14:47:20 2017 +0100
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Mon Feb 20 15:51:25 2017 -0500

    Autogen: Only touch an unchanged moc_compilation.cpp

diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx
index e0e6d61..7c7ad83 100644
--- a/Source/cmQtAutoGenerators.cxx
+++ b/Source/cmQtAutoGenerators.cxx
@@ -1069,6 +1069,9 @@ bool cmQtAutoGenerators::MocGenerateAll(
     return true;
   }
 
+  bool mocCompFileGenerated = false;
+  bool mocCompChanged = false;
+
   // look for name collisions
   {
     std::multimap<std::string, std::string> collisions;
@@ -1088,8 +1091,7 @@ bool cmQtAutoGenerators::MocGenerateAll(
       return false;
     }
   }
-
-  // generate moc files that are included by source files.
+  // Generate moc files that are included by source files.
   {
     const std::string subDir = "include/";
     for (std::map<std::string, std::string>::const_iterator it =
@@ -1102,16 +1104,14 @@ bool cmQtAutoGenerators::MocGenerateAll(
       }
     }
   }
-
-  // generate moc files that are _not_ included by source files.
-  bool automocCppChanged = false;
+  // Generate moc files that are _not_ included by source files.
   {
     const std::string subDir;
     for (std::map<std::string, std::string>::const_iterator it =
            mocsNotIncluded.begin();
          it != mocsNotIncluded.end(); ++it) {
       if (this->MocGenerateFile(it->first, it->second, subDir, mocDepends)) {
-        automocCppChanged = true;
+        mocCompFileGenerated = true;
       } else {
         if (this->RunMocFailed) {
           return false;
@@ -1140,46 +1140,47 @@ bool cmQtAutoGenerators::MocGenerateAll(
     automocSource = outStream.str();
   }
 
-  // Check if we even need to update moc_compilation.cpp
-  if (!automocCppChanged) {
-    // compare contents of the moc_compilation.cpp file
+  // Check if the content of moc_compilation.cpp changed
+  {
     const std::string oldContents = ReadAll(this->MocCppFilenameAbs);
-    if (oldContents == automocSource) {
-      // nothing changed: don't touch the moc_compilation.cpp file
-      if (this->Verbose) {
-        std::ostringstream err;
-        err << "AutoMoc: " << this->MocCppFilenameRel << " still up to date"
-            << std::endl;
-        this->LogInfo(err.str());
-      }
-      return true;
-    }
+    mocCompChanged = (oldContents != automocSource);
   }
 
-  // Actually write moc_compilation.cpp
-  this->LogBold("Generating MOC compilation " + this->MocCppFilenameRel);
+  bool success = true;
+  if (mocCompChanged) {
+    // Actually write moc_compilation.cpp
+    this->LogBold("Generating MOC compilation " + this->MocCppFilenameRel);
 
-  // Make sure the parent directory exists
-  bool success = this->MakeParentDirectory(this->MocCppFilenameAbs);
-  if (success) {
-    cmsys::ofstream outfile;
-    outfile.open(this->MocCppFilenameAbs.c_str(), std::ios::trunc);
-    if (!outfile) {
-      success = false;
-      std::ostringstream err;
-      err << "AutoMoc: error opening " << this->MocCppFilenameAbs << "\n";
-      this->LogError(err.str());
-    } else {
-      outfile << automocSource;
-      // Check for write errors
-      if (!outfile.good()) {
+    // Make sure the parent directory exists
+    success = this->MakeParentDirectory(this->MocCppFilenameAbs);
+    if (success) {
+      cmsys::ofstream outfile;
+      outfile.open(this->MocCppFilenameAbs.c_str(), std::ios::trunc);
+      if (!outfile) {
         success = false;
         std::ostringstream err;
-        err << "AutoMoc: error writing " << this->MocCppFilenameAbs << "\n";
+        err << "AutoMoc: error opening " << this->MocCppFilenameAbs << "\n";
         this->LogError(err.str());
+      } else {
+        outfile << automocSource;
+        // Check for write errors
+        if (!outfile.good()) {
+          success = false;
+          std::ostringstream err;
+          err << "AutoMoc: error writing " << this->MocCppFilenameAbs << "\n";
+          this->LogError(err.str());
+        }
       }
     }
+  } else if (mocCompFileGenerated) {
+    // Only touch moc_compilation.cpp
+    if (this->Verbose) {
+      this->LogInfo("Touching MOC compilation " + this->MocCppFilenameRel +
+                    "\n");
+    }
+    cmSystemTools::Touch(this->MocCppFilenameAbs, false);
   }
+
   return success;
 }
 

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=698a94c0d95ac865d40ed5caaac1a5e10194adf4
commit 698a94c0d95ac865d40ed5caaac1a5e10194adf4
Author:     Sebastian Holtermann <sebholt at xwmw.org>
AuthorDate: Fri Feb 17 11:56:02 2017 +0100
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Mon Feb 20 15:51:25 2017 -0500

    Autogen: Rebuild moc when Q_PLUGIN_METADATA json file changes
    
    Closes #15419

diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx
index e2d5f9b..e0e6d61 100644
--- a/Source/cmQtAutoGenerators.cxx
+++ b/Source/cmQtAutoGenerators.cxx
@@ -564,6 +564,16 @@ void cmQtAutoGenerators::Init(cmMakefile* makefile)
       this->MocIncludes.push_back(*it);
     }
   }
+
+  // Insert MocDependFilter for Q_PLUGIN_METADATA
+  if (QtMajorVersion != "4") {
+    MocDependFilter filter;
+    filter.key = "Q_PLUGIN_METADATA";
+    filter.regExp.compile("[\n][ \t]*"
+                          "Q_PLUGIN_METADATA[ \t]*\\("
+                          "[^\\)]*FILE[ \t]*\"([^\"]+)\"");
+    this->MocDependFilters.push_back(filter);
+  }
 }
 
 bool cmQtAutoGenerators::RunAutogen()
@@ -579,6 +589,7 @@ bool cmQtAutoGenerators::RunAutogen()
   // key = moc source filepath, value = moc output filepath
   std::map<std::string, std::string> mocsIncluded;
   std::map<std::string, std::string> mocsNotIncluded;
+  std::map<std::string, std::set<std::string> > mocDepends;
   std::map<std::string, std::vector<std::string> > uisIncluded;
   // collects all headers which may need to be mocced
   std::set<std::string> mocHeaderFiles;
@@ -589,8 +600,8 @@ bool cmQtAutoGenerators::RunAutogen()
        it != this->Sources.end(); ++it) {
     const std::string& absFilename = cmsys::SystemTools::GetRealPath(*it);
     // Parse source file for MOC/UIC
-    if (!this->ParseSourceFile(absFilename, mocsIncluded, uisIncluded,
-                               this->MocRelaxedMode)) {
+    if (!this->ParseSourceFile(absFilename, mocsIncluded, mocDepends,
+                               uisIncluded, this->MocRelaxedMode)) {
       return false;
     }
     // Find additional headers
@@ -610,10 +621,10 @@ bool cmQtAutoGenerators::RunAutogen()
     }
   }
   this->ParseHeaders(mocHeaderFiles, uicHeaderFiles, mocsIncluded,
-                     mocsNotIncluded, uisIncluded);
+                     mocsNotIncluded, mocDepends, uisIncluded);
 
   // Generate files
-  if (!this->MocGenerateAll(mocsIncluded, mocsNotIncluded)) {
+  if (!this->MocGenerateAll(mocsIncluded, mocsNotIncluded, mocDepends)) {
     return false;
   }
   if (!this->UicGenerateAll(uisIncluded)) {
@@ -630,17 +641,18 @@ bool cmQtAutoGenerators::RunAutogen()
  * @brief Tests if the C++ content requires moc processing
  * @return True if moc is required
  */
-bool cmQtAutoGenerators::MocRequired(const std::string& text,
+bool cmQtAutoGenerators::MocRequired(const std::string& contentText,
                                      std::string* macroName)
 {
   for (unsigned int ii = 0; ii != cmArraySize(this->MacroFilters); ++ii) {
-    MacroFilter& macroFilter = this->MacroFilters[ii];
-    // Run a simple check before an expensive regular expression check
-    if (text.find(macroFilter.first) != std::string::npos) {
-      if (macroFilter.second.find(text)) {
+    MacroFilter& filter = this->MacroFilters[ii];
+    // Run a simple find string operation before the expensive
+    // regular expression check
+    if (contentText.find(filter.first) != std::string::npos) {
+      if (filter.second.find(contentText)) {
         // Return macro name on demand
         if (macroName != CM_NULLPTR) {
-          *macroName = macroFilter.first;
+          *macroName = filter.first;
         }
         return true;
       }
@@ -649,6 +661,44 @@ bool cmQtAutoGenerators::MocRequired(const std::string& text,
   return false;
 }
 
+void cmQtAutoGenerators::MocFindDepends(
+  const std::string& absFilename, const std::string& contentText,
+  std::map<std::string, std::set<std::string> >& mocDepends)
+{
+  for (std::vector<MocDependFilter>::iterator fit =
+         this->MocDependFilters.begin();
+       fit != this->MocDependFilters.end(); ++fit) {
+    MocDependFilter& filter = *fit;
+    // Run a simple find string operation before the expensive
+    // regular expression check
+    if (contentText.find(filter.key) != std::string::npos) {
+      // Run regular expression check loop
+      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()) {
+            mocDepends[absFilename].insert(incFile);
+            if (this->Verbose) {
+              this->LogInfo("AutoMoc: Found dependency:\n  \"" + absFilename +
+                            "\"\n  \"" + incFile + "\"\n");
+            }
+          } else {
+            this->LogWarning("AutoMoc: Warning: \"" + absFilename + "\"\n" +
+                             "Could not find dependency file \"" + match +
+                             "\"\n");
+          }
+        }
+        contentChars += filter.regExp.end();
+      }
+    }
+  }
+}
+
 /**
  * @brief Tests if the file should be ignored for moc scanning
  * @return True if the file should be ignored
@@ -684,11 +734,12 @@ bool cmQtAutoGenerators::UicSkip(const std::string& absFilename) const
 bool cmQtAutoGenerators::ParseSourceFile(
   const std::string& absFilename,
   std::map<std::string, std::string>& mocsIncluded,
+  std::map<std::string, std::set<std::string> >& mocDepends,
   std::map<std::string, std::vector<std::string> >& uisIncluded, bool relaxed)
 {
   bool success = true;
-  const std::string contentsString = ReadAll(absFilename);
-  if (contentsString.empty()) {
+  const std::string contentText = ReadAll(absFilename);
+  if (contentText.empty()) {
     std::ostringstream err;
     err << "AutoGen: Warning: " << absFilename << "\n"
         << "The file is empty\n";
@@ -696,19 +747,19 @@ bool cmQtAutoGenerators::ParseSourceFile(
   } else {
     // Parse source contents for MOC
     if (success && !this->MocSkip(absFilename)) {
-      success = this->ParseContentForMoc(absFilename, contentsString,
-                                         mocsIncluded, relaxed);
+      success = this->MocParseSourceContent(absFilename, contentText,
+                                            mocsIncluded, mocDepends, relaxed);
     }
     // Parse source contents for UIC
     if (success && !this->UicSkip(absFilename)) {
-      this->ParseContentForUic(absFilename, contentsString, uisIncluded);
+      this->UicParseContent(absFilename, contentText, uisIncluded);
     }
   }
   return success;
 }
 
-void cmQtAutoGenerators::ParseContentForUic(
-  const std::string& absFilename, const std::string& contentsString,
+void cmQtAutoGenerators::UicParseContent(
+  const std::string& absFilename, const std::string& contentText,
   std::map<std::string, std::vector<std::string> >& uisIncluded)
 {
   if (this->Verbose) {
@@ -717,7 +768,7 @@ void cmQtAutoGenerators::ParseContentForUic(
     this->LogInfo(err.str());
   }
 
-  const char* contentChars = contentsString.c_str();
+  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);
@@ -734,9 +785,10 @@ void cmQtAutoGenerators::ParseContentForUic(
 /**
  * @return True on success
  */
-bool cmQtAutoGenerators::ParseContentForMoc(
-  const std::string& absFilename, const std::string& contentsString,
-  std::map<std::string, std::string>& mocsIncluded, bool relaxed)
+bool cmQtAutoGenerators::MocParseSourceContent(
+  const std::string& absFilename, const std::string& contentText,
+  std::map<std::string, std::string>& mocsIncluded,
+  std::map<std::string, std::set<std::string> >& mocDepends, bool relaxed)
 {
   if (this->Verbose) {
     std::ostringstream err;
@@ -750,16 +802,15 @@ bool cmQtAutoGenerators::ParseContentForMoc(
     cmsys::SystemTools::GetFilenameWithoutLastExtension(absFilename);
 
   std::string macroName;
-  const bool requiresMoc = this->MocRequired(contentsString, &macroName);
+  const bool requiresMoc = this->MocRequired(contentText, &macroName);
   bool ownDotMocIncluded = false;
-  bool ownMocUnderscoreIncluded = false;
-  std::string ownMocUnderscoreFile;
-  std::string ownMocHeaderFile;
+  std::string ownMocUnderscoreInclude;
+  std::string ownMocUnderscoreHeader;
 
   // first a simple string check for "moc" is *much* faster than the regexp,
   // and if the string search already fails, we don't have to try the
   // expensive regexp
-  const char* contentChars = contentsString.c_str();
+  const char* contentChars = contentText.c_str();
   if (strstr(contentChars, "moc") != CM_NULLPTR) {
     // Iterate over all included moc files
     while (this->RegExpMocInclude.find(contentChars)) {
@@ -785,11 +836,13 @@ bool cmQtAutoGenerators::ParseContentForMoc(
         const std::string headerToMoc =
           this->FindMocHeader(scannedFileAbsPath, incRealBasename, incSubDir);
         if (!headerToMoc.empty()) {
+          // Register moc job
           mocsIncluded[headerToMoc] = incString;
+          this->MocFindDepends(headerToMoc, contentText, mocDepends);
+          // Store meta information for relaxed mode
           if (relaxed && (incRealBasename == scannedFileBasename)) {
-            ownMocUnderscoreIncluded = true;
-            ownMocUnderscoreFile = incString;
-            ownMocHeaderFile = headerToMoc;
+            ownMocUnderscoreInclude = incString;
+            ownMocUnderscoreHeader = headerToMoc;
           }
         } else {
           std::ostringstream err;
@@ -878,6 +931,7 @@ bool cmQtAutoGenerators::ParseContentForMoc(
         }
         if (!fileToMoc.empty()) {
           mocsIncluded[fileToMoc] = incString;
+          this->MocFindDepends(fileToMoc, contentText, mocDepends);
         }
       }
       // Forward content pointer
@@ -890,14 +944,14 @@ bool cmQtAutoGenerators::ParseContentForMoc(
     // If this is the case, the moc_foo.cpp should probably be generated from
     // foo.cpp instead of foo.h, because otherwise it won't build.
     // But warn, since this is not how it is supposed to be used.
-    if (relaxed && ownMocUnderscoreIncluded) {
+    if (relaxed && !ownMocUnderscoreInclude.empty()) {
       // This is for KDE4 compatibility:
       std::ostringstream err;
       err << "AutoMoc: Warning: " << absFilename << "\n"
           << "The file contains a " << macroName
           << " macro, but does not include "
           << "\"" << scannedFileBasename << ".moc\", but instead includes "
-          << "\"" << ownMocUnderscoreFile << "\".\n"
+          << "\"" << ownMocUnderscoreInclude << "\".\n"
           << "Running moc on \"" << absFilename << "\"!\n"
           << "Better include \"" << scannedFileBasename
           << ".moc\" for compatibility with "
@@ -905,8 +959,10 @@ bool cmQtAutoGenerators::ParseContentForMoc(
       this->LogWarning(err.str());
 
       // Use scanned source file instead of scanned header file as moc source
-      mocsIncluded[absFilename] = ownMocUnderscoreFile;
-      mocsIncluded.erase(ownMocHeaderFile);
+      mocsIncluded[absFilename] = ownMocUnderscoreInclude;
+      this->MocFindDepends(absFilename, contentText, mocDepends);
+      // Remove
+      mocsIncluded.erase(ownMocUnderscoreHeader);
     } else {
       // Otherwise always error out since it will not compile:
       std::ostringstream err;
@@ -922,6 +978,25 @@ bool cmQtAutoGenerators::ParseContentForMoc(
   return true;
 }
 
+void cmQtAutoGenerators::MocParseHeaderContent(
+  const std::string& absFilename, const std::string& contentText,
+  std::map<std::string, std::string>& mocsNotIncluded,
+  std::map<std::string, std::set<std::string> >& mocDepends)
+{
+  // Log
+  if (this->Verbose) {
+    std::ostringstream err;
+    err << "AutoMoc: Checking " << absFilename << "\n";
+    this->LogInfo(err.str());
+  }
+  if (this->MocRequired(contentText)) {
+    // Register moc job
+    mocsNotIncluded[absFilename] =
+      this->ChecksumedPath(absFilename, "moc_", ".cpp");
+    this->MocFindDepends(absFilename, contentText, mocDepends);
+  }
+}
+
 void cmQtAutoGenerators::SearchHeadersForSourceFile(
   const std::string& absFilename, std::set<std::string>& mocHeaderFiles,
   std::set<std::string>& uicHeaderFiles) const
@@ -958,6 +1033,7 @@ void cmQtAutoGenerators::ParseHeaders(
   const std::set<std::string>& uicHeaderFiles,
   const std::map<std::string, std::string>& mocsIncluded,
   std::map<std::string, std::string>& mocsNotIncluded,
+  std::map<std::string, std::set<std::string> >& mocDepends,
   std::map<std::string, std::vector<std::string> >& uisIncluded)
 {
   // Merged header files list to read files only once
@@ -968,33 +1044,26 @@ void cmQtAutoGenerators::ParseHeaders(
   for (std::set<std::string>::const_iterator hIt = headerFiles.begin();
        hIt != headerFiles.end(); ++hIt) {
     const std::string& headerName = *hIt;
-    const std::string contents = ReadAll(headerName);
+    const std::string contentText = ReadAll(headerName);
 
     // Parse header content for MOC
     if ((mocHeaderFiles.find(headerName) != mocHeaderFiles.end()) &&
         (mocsIncluded.find(headerName) == mocsIncluded.end())) {
-      // Log
-      if (this->Verbose) {
-        std::ostringstream err;
-        err << "AutoMoc: Checking " << headerName << "\n";
-        this->LogInfo(err.str());
-      }
-      if (this->MocRequired(contents)) {
-        mocsNotIncluded[headerName] =
-          this->ChecksumedPath(headerName, "moc_", ".cpp");
-      }
+      this->MocParseHeaderContent(headerName, contentText, mocsNotIncluded,
+                                  mocDepends);
     }
 
     // Parse header content for UIC
     if (uicHeaderFiles.find(headerName) != uicHeaderFiles.end()) {
-      this->ParseContentForUic(headerName, contents, uisIncluded);
+      this->UicParseContent(headerName, contentText, uisIncluded);
     }
   }
 }
 
 bool cmQtAutoGenerators::MocGenerateAll(
   const std::map<std::string, std::string>& mocsIncluded,
-  const std::map<std::string, std::string>& mocsNotIncluded)
+  const std::map<std::string, std::string>& mocsNotIncluded,
+  const std::map<std::string, std::set<std::string> >& mocDepends)
 {
   if (!this->MocEnabled()) {
     return true;
@@ -1022,11 +1091,11 @@ bool cmQtAutoGenerators::MocGenerateAll(
 
   // generate moc files that are included by source files.
   {
-    const std::string subDirPrefix = "include/";
+    const std::string subDir = "include/";
     for (std::map<std::string, std::string>::const_iterator it =
            mocsIncluded.begin();
          it != mocsIncluded.end(); ++it) {
-      if (!this->MocGenerateFile(it->first, it->second, subDirPrefix)) {
+      if (!this->MocGenerateFile(it->first, it->second, subDir, mocDepends)) {
         if (this->RunMocFailed) {
           return false;
         }
@@ -1037,11 +1106,11 @@ bool cmQtAutoGenerators::MocGenerateAll(
   // generate moc files that are _not_ included by source files.
   bool automocCppChanged = false;
   {
-    const std::string subDirPrefix;
+    const std::string subDir;
     for (std::map<std::string, std::string>::const_iterator it =
            mocsNotIncluded.begin();
          it != mocsNotIncluded.end(); ++it) {
-      if (this->MocGenerateFile(it->first, it->second, subDirPrefix)) {
+      if (this->MocGenerateFile(it->first, it->second, subDir, mocDepends)) {
         automocCppChanged = true;
       } else {
         if (this->RunMocFailed) {
@@ -1117,9 +1186,10 @@ bool cmQtAutoGenerators::MocGenerateAll(
 /**
  * @return True if a moc file was created. False may indicate an error.
  */
-bool cmQtAutoGenerators::MocGenerateFile(const std::string& sourceFile,
-                                         const std::string& mocFileName,
-                                         const std::string& subDirPrefix)
+bool cmQtAutoGenerators::MocGenerateFile(
+  const std::string& sourceFile, const std::string& mocFileName,
+  const std::string& subDirPrefix,
+  const std::map<std::string, std::set<std::string> >& mocDepends)
 {
   bool mocGenerated = false;
   bool generateMoc = this->GenerateAllMoc;
@@ -1131,6 +1201,20 @@ bool cmQtAutoGenerators::MocGenerateFile(const std::string& sourceFile,
   if (!generateMoc) {
     // Test if the source file is newer that the build file
     generateMoc = FileAbsentOrOlder(mocFileAbs, sourceFile);
+    if (!generateMoc) {
+      // Test if a dependency file changed
+      std::map<std::string, std::set<std::string> >::const_iterator dit =
+        mocDepends.find(sourceFile);
+      if (dit != mocDepends.end()) {
+        for (std::set<std::string>::const_iterator fit = dit->second.begin();
+             fit != dit->second.end(); ++fit) {
+          if (FileAbsentOrOlder(mocFileAbs, *fit)) {
+            generateMoc = true;
+            break;
+          }
+        }
+      }
+    }
   }
   if (generateMoc) {
     // Log
@@ -1488,33 +1572,34 @@ void cmQtAutoGenerators::LogErrorNameCollision(
   this->LogError(err.str());
 }
 
-void cmQtAutoGenerators::LogBold(const std::string& message)
+void cmQtAutoGenerators::LogBold(const std::string& message) const
 {
   cmSystemTools::MakefileColorEcho(cmsysTerminal_Color_ForegroundBlue |
                                      cmsysTerminal_Color_ForegroundBold,
                                    message.c_str(), true, this->ColorOutput);
 }
 
-void cmQtAutoGenerators::LogInfo(const std::string& message)
+void cmQtAutoGenerators::LogInfo(const std::string& message) const
 {
   cmSystemTools::Stdout(message.c_str(), message.size());
 }
 
-void cmQtAutoGenerators::LogWarning(const std::string& message)
+void cmQtAutoGenerators::LogWarning(const std::string& message) const
 {
   std::string msg(message);
   msg += "\n";
   cmSystemTools::Stdout(msg.c_str(), msg.size());
 }
 
-void cmQtAutoGenerators::LogError(const std::string& message)
+void cmQtAutoGenerators::LogError(const std::string& message) const
 {
   std::string msg(message);
   msg += "\n";
   cmSystemTools::Stderr(msg.c_str(), msg.size());
 }
 
-void cmQtAutoGenerators::LogCommand(const std::vector<std::string>& command)
+void cmQtAutoGenerators::LogCommand(
+  const std::vector<std::string>& command) const
 {
   std::ostringstream sbuf;
   for (std::vector<std::string>::const_iterator cmdIt = command.begin();
@@ -1638,23 +1723,40 @@ std::string cmQtAutoGenerators::FindMocHeader(const std::string& basePath,
   return header;
 }
 
+std::string cmQtAutoGenerators::FindIncludedFile(
+  const std::string& sourceFile, const std::string& includeString) const
+{
+  // Search in vicinity of the source
+  {
+    std::string testPath = cmSystemTools::GetFilenamePath(sourceFile);
+    testPath += '/';
+    testPath += includeString;
+    if (cmsys::SystemTools::FileExists(testPath.c_str())) {
+      return cmsys::SystemTools::GetRealPath(testPath);
+    }
+  }
+  // Search globaly
+  return FindInIncludeDirectories(includeString);
+}
+
 /**
  * @brief Tries to find a file in the include directories
  * @return True on success
  */
-bool cmQtAutoGenerators::FindInIncludeDirectories(
-  std::string& file_n, const std::string& searchString) const
+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) + '/' + searchString);
+    const std::string fullPath = ((*iit) + '/' + includeString);
     if (cmsys::SystemTools::FileExists(fullPath.c_str())) {
-      file_n = fullPath;
-      return true;
+      res = cmsys::SystemTools::GetRealPath(fullPath);
+      break;
     }
   }
-  return false;
+  return res;
 }
 
 /**
diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGenerators.h
index 66f11c5..9fd5c58 100644
--- a/Source/cmQtAutoGenerators.h
+++ b/Source/cmQtAutoGenerators.h
@@ -21,6 +21,16 @@ public:
   bool Run(const std::string& targetDirectory, const std::string& config);
 
 private:
+  // - Types
+
+  /// @brief Used to extract additional dependencies from content text
+  struct MocDependFilter
+  {
+    std::string key;
+    cmsys::RegularExpression regExp;
+  };
+  typedef std::pair<std::string, cmsys::RegularExpression> MacroFilter;
+
   // - Configuration
   bool ReadAutogenInfoFile(cmMakefile* makefile,
                            const std::string& targetDirectory,
@@ -46,14 +56,19 @@ private:
   bool RunAutogen();
 
   // - Content analysis
-  bool MocRequired(const std::string& text,
+  bool MocRequired(const std::string& contentText,
                    std::string* macroName = CM_NULLPTR);
+  void MocFindDepends(
+    const std::string& absFilename, const std::string& contentText,
+    std::map<std::string, std::set<std::string> >& mocDepends);
+
   bool MocSkip(const std::string& absFilename) const;
   bool UicSkip(const std::string& absFilename) const;
 
   bool ParseSourceFile(
     const std::string& absFilename,
     std::map<std::string, std::string>& mocsIncluded,
+    std::map<std::string, std::set<std::string> >& mocDepends,
     std::map<std::string, std::vector<std::string> >& includedUis,
     bool relaxed);
 
@@ -66,24 +81,32 @@ private:
     const std::set<std::string>& uicHeaderFiles,
     const std::map<std::string, std::string>& mocsIncluded,
     std::map<std::string, std::string>& mocsNotIncluded,
+    std::map<std::string, std::set<std::string> >& mocDepends,
     std::map<std::string, std::vector<std::string> >& includedUis);
 
-  void ParseContentForUic(
-    const std::string& fileName, const std::string& contentsString,
+  void UicParseContent(
+    const std::string& fileName, const std::string& contentText,
     std::map<std::string, std::vector<std::string> >& includedUis);
 
-  bool ParseContentForMoc(const std::string& absFilename,
-                          const std::string& contentsString,
-                          std::map<std::string, std::string>& mocsIncluded,
-                          bool relaxed);
+  bool MocParseSourceContent(
+    const std::string& absFilename, const std::string& contentText,
+    std::map<std::string, std::string>& mocsIncluded,
+    std::map<std::string, std::set<std::string> >& mocDepends, bool relaxed);
+
+  void MocParseHeaderContent(
+    const std::string& absFilename, const std::string& contentText,
+    std::map<std::string, std::string>& mocsNotIncluded,
+    std::map<std::string, std::set<std::string> >& mocDepends);
 
   // - Moc file generation
   bool MocGenerateAll(
     const std::map<std::string, std::string>& mocsIncluded,
-    const std::map<std::string, std::string>& mocsNotIncluded);
-  bool MocGenerateFile(const std::string& sourceFile,
-                       const std::string& mocFileName,
-                       const std::string& subDirPrefix);
+    const std::map<std::string, std::string>& mocsNotIncluded,
+    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::map<std::string, std::set<std::string> >& mocDepends);
 
   // - Uic file generation
   bool UicGenerateAll(
@@ -101,11 +124,11 @@ private:
   void LogErrorNameCollision(
     const std::string& message,
     const std::multimap<std::string, std::string>& collisions);
-  void LogBold(const std::string& message);
-  void LogInfo(const std::string& message);
-  void LogWarning(const std::string& message);
-  void LogError(const std::string& message);
-  void LogCommand(const std::vector<std::string>& command);
+  void LogBold(const std::string& message) const;
+  void LogInfo(const std::string& message) const;
+  void LogWarning(const std::string& message) const;
+  void LogError(const std::string& message) const;
+  void LogCommand(const std::vector<std::string>& command) const;
 
   // - Utility
   bool NameCollisionTest(
@@ -122,8 +145,9 @@ private:
   std::string FindMocHeader(const std::string& basePath,
                             const std::string& baseName,
                             const std::string& subDir) const;
-  bool FindInIncludeDirectories(std::string& file_n,
-                                const std::string& searchString) const;
+  std::string FindIncludedFile(const std::string& sourceFile,
+                               const std::string& includeString) const;
+  std::string FindInIncludeDirectories(const std::string& includeString) const;
 
   // - Target names
   std::string OriginTargetName;
@@ -154,6 +178,7 @@ private:
   std::vector<std::string> MocIncludes;
   std::vector<std::string> MocDefinitions;
   std::vector<std::string> MocOptions;
+  std::vector<MocDependFilter> MocDependFilters;
   // - Uic
   std::vector<std::string> UicSkipList;
   std::vector<std::string> UicTargetOptions;
@@ -165,7 +190,6 @@ private:
   // - Utility
   cmFilePathChecksum fpathCheckSum;
   std::vector<std::string> HeaderExtensions;
-  typedef std::pair<std::string, cmsys::RegularExpression> MacroFilter;
   MacroFilter MacroFilters[2];
   cmsys::RegularExpression RegExpMocInclude;
   cmsys::RegularExpression RegExpUicInclude;

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=58ac0c6209b627137636e0feac6f4d59321dae54
commit 58ac0c6209b627137636e0feac6f4d59321dae54
Author:     Sebastian Holtermann <sebholt at xwmw.org>
AuthorDate: Thu Feb 16 23:55:59 2017 +0100
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Mon Feb 20 15:51:25 2017 -0500

    Autogen: Use GetRealPath in central places only

diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx
index a0cac68..e2d5f9b 100644
--- a/Source/cmQtAutoGenerators.cxx
+++ b/Source/cmQtAutoGenerators.cxx
@@ -587,7 +587,7 @@ bool cmQtAutoGenerators::RunAutogen()
   // Parse sources
   for (std::vector<std::string>::const_iterator it = this->Sources.begin();
        it != this->Sources.end(); ++it) {
-    const std::string& absFilename = *it;
+    const std::string& absFilename = cmsys::SystemTools::GetRealPath(*it);
     // Parse source file for MOC/UIC
     if (!this->ParseSourceFile(absFilename, mocsIncluded, uisIncluded,
                                this->MocRelaxedMode)) {
@@ -601,7 +601,7 @@ bool cmQtAutoGenerators::RunAutogen()
   // Parse headers
   for (std::vector<std::string>::const_iterator it = this->Headers.begin();
        it != this->Headers.end(); ++it) {
-    const std::string& headerName = *it;
+    const std::string& headerName = cmsys::SystemTools::GetRealPath(*it);
     if (!this->MocSkip(headerName)) {
       mocHeaderFiles.insert(headerName);
     }
@@ -717,7 +717,6 @@ void cmQtAutoGenerators::ParseContentForUic(
     this->LogInfo(err.str());
   }
 
-  const std::string realName = cmsys::SystemTools::GetRealPath(absFilename);
   const char* contentChars = contentsString.c_str();
   if (strstr(contentChars, "ui_") != CM_NULLPTR) {
     while (this->RegExpUicInclude.find(contentChars)) {
@@ -726,7 +725,7 @@ void cmQtAutoGenerators::ParseContentForUic(
         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[realName].push_back(basename.substr(3));
+      uisIncluded[absFilename].push_back(basename.substr(3));
       contentChars += this->RegExpUicInclude.end();
     }
   }
@@ -746,9 +745,7 @@ bool cmQtAutoGenerators::ParseContentForMoc(
   }
 
   const std::string scannedFileAbsPath =
-    cmsys::SystemTools::GetFilenamePath(
-      cmsys::SystemTools::GetRealPath(absFilename)) +
-    '/';
+    cmsys::SystemTools::GetFilenamePath(absFilename) + '/';
   const std::string scannedFileBasename =
     cmsys::SystemTools::GetFilenameWithoutLastExtension(absFilename);
 
@@ -931,33 +928,27 @@ void cmQtAutoGenerators::SearchHeadersForSourceFile(
 {
   std::string basepaths[2];
   {
-    std::string bpath = cmsys::SystemTools::GetFilenamePath(
-      cmsys::SystemTools::GetRealPath(absFilename));
+    std::string bpath = cmsys::SystemTools::GetFilenamePath(absFilename);
     bpath += '/';
     bpath += cmsys::SystemTools::GetFilenameWithoutLastExtension(absFilename);
-
     // search for default header files and private header files
-    basepaths[0] = (bpath + ".");
-    basepaths[1] = (bpath + "_p.");
+    basepaths[0] = bpath;
+    basepaths[1] = bpath + "_p";
   }
 
   for (const std::string* bpit = cmArrayBegin(basepaths);
        bpit != cmArrayEnd(basepaths); ++bpit) {
-    for (std::vector<std::string>::const_iterator heit =
-           this->HeaderExtensions.begin();
-         heit != this->HeaderExtensions.end(); ++heit) {
-      const std::string hname = (*bpit) + (*heit);
-      if (cmsys::SystemTools::FileExists(hname.c_str())) {
-        // Moc headers
-        if (!this->MocSkip(absFilename) && !this->MocSkip(hname)) {
-          mocHeaderFiles.insert(hname);
-        }
-        // Uic headers
-        if (!this->UicSkip(absFilename) && !this->UicSkip(hname)) {
-          uicHeaderFiles.insert(hname);
-        }
-        break;
+    std::string headerName;
+    if (this->FindHeader(headerName, *bpit)) {
+      // Moc headers
+      if (!this->MocSkip(absFilename) && !this->MocSkip(headerName)) {
+        mocHeaderFiles.insert(headerName);
+      }
+      // Uic headers
+      if (!this->UicSkip(absFilename) && !this->UicSkip(headerName)) {
+        uicHeaderFiles.insert(headerName);
       }
+      break;
     }
   }
 }
@@ -1642,7 +1633,7 @@ std::string cmQtAutoGenerators::FindMocHeader(const std::string& basePath,
   } while (false);
   // Sanitize
   if (!header.empty()) {
-    header = cmSystemTools::CollapseFullPath(header);
+    header = cmsys::SystemTools::GetRealPath(header);
   }
   return header;
 }

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=1508ed9c65f1515313bca00790710820974cd7cc
commit 1508ed9c65f1515313bca00790710820974cd7cc
Author:     Sebastian Holtermann <sebholt at xwmw.org>
AuthorDate: Thu Feb 16 22:03:43 2017 +0100
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Mon Feb 20 15:51:24 2017 -0500

    Autogen: Search moc includes in include directories

diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx
index a98ae09..a0cac68 100644
--- a/Source/cmQtAutoGenerators.cxx
+++ b/Source/cmQtAutoGenerators.cxx
@@ -772,7 +772,8 @@ bool cmQtAutoGenerators::ParseContentForMoc(
         cmsys::SystemTools::GetFilenameWithoutLastExtension(incString);
       std::string incSubDir;
       if (incString.find_first_of('/') != std::string::npos) {
-        incSubDir = cmsys::SystemTools::GetFilenamePath(incString) + '/';
+        incSubDir = cmsys::SystemTools::GetFilenamePath(incString);
+        incSubDir += '/';
       }
 
       // If the moc include is of the moc_foo.cpp style we expect
@@ -784,8 +785,8 @@ bool cmQtAutoGenerators::ParseContentForMoc(
         // Include: moc_FOO.cxx
         // Remove the moc_ part
         const std::string incRealBasename = incBasename.substr(4);
-        const std::string headerToMoc = this->FindMatchingHeader(
-          scannedFileAbsPath, incRealBasename, incSubDir);
+        const std::string headerToMoc =
+          this->FindMocHeader(scannedFileAbsPath, incRealBasename, incSubDir);
         if (!headerToMoc.empty()) {
           mocsIncluded[headerToMoc] = incString;
           if (relaxed && (incRealBasename == scannedFileBasename)) {
@@ -813,8 +814,8 @@ bool cmQtAutoGenerators::ParseContentForMoc(
             ownDotMocIncluded = true;
           } else {
             // In relaxed mode try to find a header instead but issue a warning
-            const std::string headerToMoc = this->FindMatchingHeader(
-              scannedFileAbsPath, incBasename, incSubDir);
+            const std::string headerToMoc =
+              this->FindMocHeader(scannedFileAbsPath, incBasename, incSubDir);
             if (!headerToMoc.empty()) {
               // This is for KDE4 compatibility:
               fileToMoc = headerToMoc;
@@ -1606,9 +1607,23 @@ bool cmQtAutoGenerators::FindHeader(std::string& header,
   return false;
 }
 
-std::string cmQtAutoGenerators::FindMatchingHeader(
-  const std::string& basePath, const std::string& baseName,
-  const std::string& subDir) const
+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 header;
   do {
@@ -1620,7 +1635,15 @@ std::string cmQtAutoGenerators::FindMatchingHeader(
     if (this->FindHeader(header, basePath + baseName)) {
       break;
     }
+    // Try include directories
+    if (this->FindHeaderGlobal(header, subDir + baseName)) {
+      break;
+    }
   } while (false);
+  // Sanitize
+  if (!header.empty()) {
+    header = cmSystemTools::CollapseFullPath(header);
+  }
   return header;
 }
 
diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGenerators.h
index 1ab205d..66f11c5 100644
--- a/Source/cmQtAutoGenerators.h
+++ b/Source/cmQtAutoGenerators.h
@@ -117,9 +117,11 @@ private:
   bool MakeParentDirectory(const std::string& filename);
 
   bool FindHeader(std::string& header, const std::string& testBasePath) const;
-  std::string FindMatchingHeader(const std::string& basePath,
-                                 const std::string& baseName,
-                                 const std::string& subDir) 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;
   bool FindInIncludeDirectories(std::string& file_n,
                                 const std::string& searchString) const;
 

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=e4f61a211b960d3eab0253a2986ac3aa705a2661
commit e4f61a211b960d3eab0253a2986ac3aa705a2661
Author:     Sebastian Holtermann <sebholt at xwmw.org>
AuthorDate: Thu Feb 16 21:09:04 2017 +0100
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Mon Feb 20 15:51:24 2017 -0500

    Autogen: Sort includes before composing include options

diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx
index 444acdb..a98ae09 100644
--- a/Source/cmQtAutoGenerators.cxx
+++ b/Source/cmQtAutoGenerators.cxx
@@ -509,15 +509,44 @@ void cmQtAutoGenerators::Init(cmMakefile* makefile)
   // Acquire header extensions
   this->HeaderExtensions = makefile->GetCMakeInstance()->GetHeaderExtensions();
 
+  // Sort include directories on demand
+  if (this->IncludeProjectDirsBefore) {
+    // Move strings to temporary list
+    std::list<std::string> includes;
+    includes.insert(includes.end(), this->MocIncludePaths.begin(),
+                    this->MocIncludePaths.end());
+    this->MocIncludePaths.clear();
+    this->MocIncludePaths.reserve(includes.size());
+    // Append project directories only
+    {
+      const char* movePaths[2] = { this->ProjectBinaryDir.c_str(),
+                                   this->ProjectSourceDir.c_str() };
+      for (const char* const* mpit = cmArrayBegin(movePaths);
+           mpit != cmArrayEnd(movePaths); ++mpit) {
+        std::list<std::string>::iterator it = includes.begin();
+        while (it != includes.end()) {
+          const std::string& path = *it;
+          if (cmsys::SystemTools::StringStartsWith(path, *mpit)) {
+            this->MocIncludePaths.push_back(path);
+            it = includes.erase(it);
+          } else {
+            ++it;
+          }
+        }
+      }
+    }
+    // Append remaining directories
+    this->MocIncludePaths.insert(this->MocIncludePaths.end(), includes.begin(),
+                                 includes.end());
+  }
   // Compose moc includes list
-  std::list<std::string> mocIncludes;
   {
     std::set<std::string> frameworkPaths;
     for (std::vector<std::string>::const_iterator it =
            this->MocIncludePaths.begin();
          it != this->MocIncludePaths.end(); ++it) {
       const std::string& path = *it;
-      mocIncludes.push_back("-I" + path);
+      this->MocIncludes.push_back("-I" + path);
       // Extract framework path
       if (cmHasLiteralSuffix(path, ".framework/Headers")) {
         // Go up twice to get to the framework root
@@ -531,40 +560,10 @@ void cmQtAutoGenerators::Init(cmMakefile* makefile)
     // Append framework includes
     for (std::set<std::string>::const_iterator it = frameworkPaths.begin();
          it != frameworkPaths.end(); ++it) {
-      mocIncludes.push_back("-F");
-      mocIncludes.push_back(*it);
+      this->MocIncludes.push_back("-F");
+      this->MocIncludes.push_back(*it);
     }
   }
-  if (this->IncludeProjectDirsBefore) {
-    // Extract project includes
-    std::vector<std::string> mocSortedIncludes;
-    {
-      std::vector<std::string> movePaths;
-      movePaths.push_back("-I" + this->ProjectBinaryDir);
-      movePaths.push_back("-I" + this->ProjectSourceDir);
-
-      for (std::vector<std::string>::const_iterator mpit = movePaths.begin();
-           mpit != movePaths.end(); ++mpit) {
-        std::list<std::string>::iterator it = mocIncludes.begin();
-        while (it != mocIncludes.end()) {
-          const std::string& path = *it;
-          if (cmsys::SystemTools::StringStartsWith(path, mpit->c_str())) {
-            mocSortedIncludes.push_back(path);
-            it = mocIncludes.erase(it);
-          } else {
-            ++it;
-          }
-        }
-      }
-    }
-    // Place extracted includes at the begin
-    this->MocIncludes.insert(this->MocIncludes.end(),
-                             mocSortedIncludes.begin(),
-                             mocSortedIncludes.end());
-  }
-  // Append remaining includes
-  this->MocIncludes.insert(this->MocIncludes.end(), mocIncludes.begin(),
-                           mocIncludes.end());
 }
 
 bool cmQtAutoGenerators::RunAutogen()

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=1224e67a0fd059aea194ad9a797e31a74d891618
commit 1224e67a0fd059aea194ad9a797e31a74d891618
Author:     Sebastian Holtermann <sebholt at xwmw.org>
AuthorDate: Thu Feb 16 19:47:40 2017 +0100
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Mon Feb 20 15:51:24 2017 -0500

    Autogen: Add FindInIncludeDirectories method

diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx
index 8db7754..444acdb 100644
--- a/Source/cmQtAutoGenerators.cxx
+++ b/Source/cmQtAutoGenerators.cxx
@@ -1626,6 +1626,25 @@ std::string cmQtAutoGenerators::FindMatchingHeader(
 }
 
 /**
+ * @brief Tries to find a file in the include directories
+ * @return True on success
+ */
+bool cmQtAutoGenerators::FindInIncludeDirectories(
+  std::string& file_n, const std::string& searchString) const
+{
+  for (std::vector<std::string>::const_iterator iit =
+         this->MocIncludePaths.begin();
+       iit != this->MocIncludePaths.end(); ++iit) {
+    const std::string fullPath = ((*iit) + '/' + searchString);
+    if (cmsys::SystemTools::FileExists(fullPath.c_str())) {
+      file_n = fullPath;
+      return true;
+    }
+  }
+  return false;
+}
+
+/**
  * @brief Generates the parent directory of the given file on demand
  * @return True on success
  */
diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGenerators.h
index df555ad..1ab205d 100644
--- a/Source/cmQtAutoGenerators.h
+++ b/Source/cmQtAutoGenerators.h
@@ -120,6 +120,8 @@ private:
   std::string FindMatchingHeader(const std::string& basePath,
                                  const std::string& baseName,
                                  const std::string& subDir) const;
+  bool FindInIncludeDirectories(std::string& file_n,
+                                const std::string& searchString) const;
 
   // - Target names
   std::string OriginTargetName;

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=20ed0f59e4bbd5850d1271f99b53dcaa22cac417
commit 20ed0f59e4bbd5850d1271f99b53dcaa22cac417
Author:     Sebastian Holtermann <sebholt at xwmw.org>
AuthorDate: Thu Feb 16 17:53:19 2017 +0100
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Mon Feb 20 15:51:23 2017 -0500

    Autogen: Synchronize header/source argument names

diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGenerators.h
index 94be95e..df555ad 100644
--- a/Source/cmQtAutoGenerators.h
+++ b/Source/cmQtAutoGenerators.h
@@ -53,19 +53,19 @@ private:
 
   bool ParseSourceFile(
     const std::string& absFilename,
-    std::map<std::string, std::string>& includedMocs,
+    std::map<std::string, std::string>& mocsIncluded,
     std::map<std::string, std::vector<std::string> >& includedUis,
     bool relaxed);
 
   void SearchHeadersForSourceFile(const std::string& absFilename,
-                                  std::set<std::string>& absHeadersMoc,
-                                  std::set<std::string>& absHeadersUic) const;
+                                  std::set<std::string>& mocHeaderFiles,
+                                  std::set<std::string>& uicHeaderFiles) const;
 
   void ParseHeaders(
-    const std::set<std::string>& absHeadersMoc,
-    const std::set<std::string>& absHeadersUic,
-    const std::map<std::string, std::string>& includedMocs,
-    std::map<std::string, std::string>& notIncludedMocs,
+    const std::set<std::string>& mocHeaderFiles,
+    const std::set<std::string>& uicHeaderFiles,
+    const std::map<std::string, std::string>& mocsIncluded,
+    std::map<std::string, std::string>& mocsNotIncluded,
     std::map<std::string, std::vector<std::string> >& includedUis);
 
   void ParseContentForUic(
@@ -74,13 +74,13 @@ private:
 
   bool ParseContentForMoc(const std::string& absFilename,
                           const std::string& contentsString,
-                          std::map<std::string, std::string>& includedMocs,
+                          std::map<std::string, std::string>& mocsIncluded,
                           bool relaxed);
 
   // - Moc file generation
   bool MocGenerateAll(
-    const std::map<std::string, std::string>& includedMocs,
-    const std::map<std::string, std::string>& notIncludedMocs);
+    const std::map<std::string, std::string>& mocsIncluded,
+    const std::map<std::string, std::string>& mocsNotIncluded);
   bool MocGenerateFile(const std::string& sourceFile,
                        const std::string& mocFileName,
                        const std::string& subDirPrefix);

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=f8125e7bee39b4b853fb9ea650a397dfb984a5e0
commit f8125e7bee39b4b853fb9ea650a397dfb984a5e0
Author:     Sebastian Holtermann <sebholt at xwmw.org>
AuthorDate: Thu Feb 16 11:10:46 2017 +0100
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Mon Feb 20 15:51:23 2017 -0500

    Autogen: Split moc include paths on info reading

diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx
index 8daf4c1..8db7754 100644
--- a/Source/cmQtAutoGenerators.cxx
+++ b/Source/cmQtAutoGenerators.cxx
@@ -311,8 +311,9 @@ bool cmQtAutoGenerators::ReadAutogenInfoFile(
   cmSystemTools::ExpandListArgument(
     GetConfigDefinition(makefile, "AM_MOC_COMPILE_DEFINITIONS", config),
     this->MocDefinitions);
-  this->MocInfoIncludes =
-    GetConfigDefinition(makefile, "AM_MOC_INCLUDES", config);
+  cmSystemTools::ExpandListArgument(
+    GetConfigDefinition(makefile, "AM_MOC_INCLUDES", config),
+    this->MocIncludePaths);
   cmSystemTools::ExpandListArgument(
     makefile->GetSafeDefinition("AM_MOC_OPTIONS"), this->MocOptions);
 
@@ -410,7 +411,7 @@ void cmQtAutoGenerators::SettingsFileRead(cmMakefile* makefile,
     std::string& str = this->SettingsStringMoc;
     str += JoinOptionsList(this->MocDefinitions);
     str += " ~~~ ";
-    str += this->MocInfoIncludes;
+    str += JoinOptionsList(this->MocIncludePaths);
     str += " ~~~ ";
     str += JoinOptionsList(this->MocOptions);
     str += " ~~~ ";
@@ -512,22 +513,19 @@ void cmQtAutoGenerators::Init(cmMakefile* makefile)
   std::list<std::string> mocIncludes;
   {
     std::set<std::string> frameworkPaths;
-    {
-      std::vector<std::string> incPaths;
-      cmSystemTools::ExpandListArgument(this->MocInfoIncludes, incPaths);
-      for (std::vector<std::string>::const_iterator it = incPaths.begin();
-           it != incPaths.end(); ++it) {
-        const std::string& path = *it;
-        mocIncludes.push_back("-I" + path);
-        // Extract framework path
-        if (cmHasLiteralSuffix(path, ".framework/Headers")) {
-          // Go up twice to get to the framework root
-          std::vector<std::string> pathComponents;
-          cmsys::SystemTools::SplitPath(path, pathComponents);
-          std::string frameworkPath = cmsys::SystemTools::JoinPath(
-            pathComponents.begin(), pathComponents.end() - 2);
-          frameworkPaths.insert(frameworkPath);
-        }
+    for (std::vector<std::string>::const_iterator it =
+           this->MocIncludePaths.begin();
+         it != this->MocIncludePaths.end(); ++it) {
+      const std::string& path = *it;
+      mocIncludes.push_back("-I" + path);
+      // Extract framework path
+      if (cmHasLiteralSuffix(path, ".framework/Headers")) {
+        // Go up twice to get to the framework root
+        std::vector<std::string> pathComponents;
+        cmsys::SystemTools::SplitPath(path, pathComponents);
+        std::string frameworkPath = cmsys::SystemTools::JoinPath(
+          pathComponents.begin(), pathComponents.end() - 2);
+        frameworkPaths.insert(frameworkPath);
       }
     }
     // Append framework includes
diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGenerators.h
index 12710b0..94be95e 100644
--- a/Source/cmQtAutoGenerators.h
+++ b/Source/cmQtAutoGenerators.h
@@ -143,10 +143,10 @@ private:
   std::string SettingsStringUic;
   std::string SettingsStringRcc;
   // - Moc
-  std::string MocInfoIncludes;
   std::string MocCppFilenameRel;
   std::string MocCppFilenameAbs;
   std::vector<std::string> MocSkipList;
+  std::vector<std::string> MocIncludePaths;
   std::vector<std::string> MocIncludes;
   std::vector<std::string> MocDefinitions;
   std::vector<std::string> MocOptions;

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=58699513c2248da7277b968d729bef5ba3471677
commit 58699513c2248da7277b968d729bef5ba3471677
Author:     Sebastian Holtermann <sebholt at xwmw.org>
AuthorDate: Thu Feb 16 10:31:03 2017 +0100
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Mon Feb 20 15:51:23 2017 -0500

    Autogen: Loop based macro detection instead of code duplication

diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx
index 27b99af..8daf4c1 100644
--- a/Source/cmQtAutoGenerators.cxx
+++ b/Source/cmQtAutoGenerators.cxx
@@ -213,9 +213,12 @@ cmQtAutoGenerators::cmQtAutoGenerators()
     }
   }
 
+  this->MacroFilters[0].first = "Q_OBJECT";
+  this->MacroFilters[0].second.compile("[\n][ \t]*Q_OBJECT[^a-zA-Z0-9_]");
+  this->MacroFilters[1].first = "Q_GADGET";
+  this->MacroFilters[1].second.compile("[\n][ \t]*Q_GADGET[^a-zA-Z0-9_]");
+
   // Precompile regular expressions
-  this->RegExpQObject.compile("[\n][ \t]*Q_OBJECT[^a-zA-Z0-9_]");
-  this->RegExpQGadget.compile("[\n][ \t]*Q_GADGET[^a-zA-Z0-9_]");
   this->RegExpMocInclude.compile(
     "[\n][ \t]*#[ \t]*include[ \t]+"
     "[\"<](([^ \">]+/)?moc_[^ \">/]+\\.cpp|[^ \">]+\\.moc)[\">]");
@@ -631,19 +634,19 @@ bool cmQtAutoGenerators::RunAutogen()
  * @return True if moc is required
  */
 bool cmQtAutoGenerators::MocRequired(const std::string& text,
-                                     std::string& macroName)
+                                     std::string* macroName)
 {
-  // Run a simple check before an expensive regular expression check
-  if (strstr(text.c_str(), "Q_OBJECT") != CM_NULLPTR) {
-    if (this->RegExpQObject.find(text)) {
-      macroName = "Q_OBJECT";
-      return true;
-    }
-  }
-  if (strstr(text.c_str(), "Q_GADGET") != CM_NULLPTR) {
-    if (this->RegExpQGadget.find(text)) {
-      macroName = "Q_GADGET";
-      return true;
+  for (unsigned int ii = 0; ii != cmArraySize(this->MacroFilters); ++ii) {
+    MacroFilter& macroFilter = this->MacroFilters[ii];
+    // Run a simple check before an expensive regular expression check
+    if (text.find(macroFilter.first) != std::string::npos) {
+      if (macroFilter.second.find(text)) {
+        // Return macro name on demand
+        if (macroName != CM_NULLPTR) {
+          *macroName = macroFilter.first;
+        }
+        return true;
+      }
     }
   }
   return false;
@@ -753,7 +756,7 @@ bool cmQtAutoGenerators::ParseContentForMoc(
     cmsys::SystemTools::GetFilenameWithoutLastExtension(absFilename);
 
   std::string macroName;
-  const bool requiresMoc = this->MocRequired(contentsString, macroName);
+  const bool requiresMoc = this->MocRequired(contentsString, &macroName);
   bool ownDotMocIncluded = false;
   bool ownMocUnderscoreIncluded = false;
   std::string ownMocUnderscoreFile;
@@ -987,8 +990,7 @@ void cmQtAutoGenerators::ParseHeaders(
         err << "AutoMoc: Checking " << headerName << "\n";
         this->LogInfo(err.str());
       }
-      std::string macroName;
-      if (this->MocRequired(contents, macroName)) {
+      if (this->MocRequired(contents)) {
         mocsNotIncluded[headerName] =
           this->ChecksumedPath(headerName, "moc_", ".cpp");
       }
diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGenerators.h
index e6f9160..12710b0 100644
--- a/Source/cmQtAutoGenerators.h
+++ b/Source/cmQtAutoGenerators.h
@@ -46,7 +46,8 @@ private:
   bool RunAutogen();
 
   // - Content analysis
-  bool MocRequired(const std::string& text, std::string& macroName);
+  bool MocRequired(const std::string& text,
+                   std::string* macroName = CM_NULLPTR);
   bool MocSkip(const std::string& absFilename) const;
   bool UicSkip(const std::string& absFilename) const;
 
@@ -160,8 +161,8 @@ private:
   // - Utility
   cmFilePathChecksum fpathCheckSum;
   std::vector<std::string> HeaderExtensions;
-  cmsys::RegularExpression RegExpQObject;
-  cmsys::RegularExpression RegExpQGadget;
+  typedef std::pair<std::string, cmsys::RegularExpression> MacroFilter;
+  MacroFilter MacroFilters[2];
   cmsys::RegularExpression RegExpMocInclude;
   cmsys::RegularExpression RegExpUicInclude;
   // - Flags

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=d3980d2a959734370d2f7cf2f76d705ddf2da6e3
commit d3980d2a959734370d2f7cf2f76d705ddf2da6e3
Author:     Sebastian Holtermann <sebholt at xwmw.org>
AuthorDate: Wed Feb 15 20:47:58 2017 +0100
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Mon Feb 20 15:51:23 2017 -0500

    Autogen: Issue a warning if moc isn't required in strict mode

diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx
index f86a24b..27b99af 100644
--- a/Source/cmQtAutoGenerators.cxx
+++ b/Source/cmQtAutoGenerators.cxx
@@ -856,6 +856,15 @@ bool cmQtAutoGenerators::ParseContentForMoc(
             // Include self
             fileToMoc = absFilename;
             ownDotMocIncluded = true;
+            // Accept but issue a warning if moc isn't required
+            if (!requiresMoc) {
+              std::ostringstream err;
+              err << "AutoMoc: Error: " << absFilename << "\n"
+                  << "The file includes the moc file \"" << incString << "\""
+                  << ", but does not contain a Q_OBJECT or Q_GADGET "
+                     "macro.\n";
+              this->LogWarning(err.str());
+            }
           } else {
             // Don't allow FOO.moc include other than self in strict mode
             std::ostringstream err;

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=d26601ec0897eec870fe95413362d242202d7f2b
commit d26601ec0897eec870fe95413362d242202d7f2b
Author:     Sebastian Holtermann <sebholt at xwmw.org>
AuthorDate: Wed Feb 15 20:36:39 2017 +0100
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Mon Feb 20 15:51:22 2017 -0500

    Autogen: Error message tweaks

diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx
index 7fb7bfb..f86a24b 100644
--- a/Source/cmQtAutoGenerators.cxx
+++ b/Source/cmQtAutoGenerators.cxx
@@ -807,7 +807,12 @@ bool cmQtAutoGenerators::ParseContentForMoc(
         std::string fileToMoc;
         if (relaxed) {
           // Mode: Relaxed
-          if (!requiresMoc || (incBasename != scannedFileBasename)) {
+          if (requiresMoc && (incBasename == scannedFileBasename)) {
+            // Include self
+            fileToMoc = absFilename;
+            ownDotMocIncluded = true;
+          } else {
+            // In relaxed mode try to find a header instead but issue a warning
             const std::string headerToMoc = this->FindMatchingHeader(
               scannedFileAbsPath, incBasename, incSubDir);
             if (!headerToMoc.empty()) {
@@ -816,11 +821,10 @@ bool cmQtAutoGenerators::ParseContentForMoc(
               if (!requiresMoc && (incBasename == scannedFileBasename)) {
                 std::ostringstream err;
                 err << "AutoMoc: Warning: " << absFilename << "\n"
-                    << "The file includes the moc file \"" << incString
-                    << "\", but does not contain a " << macroName
-                    << " macro. Running moc on "
-                    << "\"" << headerToMoc << "\" ! Include \"moc_"
-                    << incBasename
+                    << "The file includes the moc file \"" << incString << "\""
+                    << ", but does not contain a Q_OBJECT or Q_GADGET macro.\n"
+                    << "Running moc on \"" << headerToMoc << "\"!\n"
+                    << "Include \"moc_" << incBasename
                     << ".cpp\" for a compatibility with "
                        "strict mode (see CMAKE_AUTOMOC_RELAXED_MODE).\n";
                 this->LogWarning(err.str());
@@ -828,10 +832,9 @@ bool cmQtAutoGenerators::ParseContentForMoc(
                 std::ostringstream err;
                 err << "AutoMoc: Warning: " << absFilename << "\n"
                     << "The file includes the moc file \"" << incString
-                    << "\" instead of \"moc_" << incBasename
-                    << ".cpp\". Running moc on "
-                    << "\"" << headerToMoc << "\" ! Include \"moc_"
-                    << incBasename
+                    << "\" instead of \"moc_" << incBasename << ".cpp\".\n"
+                    << "Running moc on \"" << headerToMoc << "\"!\n"
+                    << "Include \"moc_" << incBasename
                     << ".cpp\" for compatibility with "
                        "strict mode (see CMAKE_AUTOMOC_RELAXED_MODE).\n";
                 this->LogWarning(err.str());
@@ -846,10 +849,6 @@ bool cmQtAutoGenerators::ParseContentForMoc(
               this->LogError(err.str());
               return false;
             }
-          } else {
-            // Include self
-            fileToMoc = absFilename;
-            ownDotMocIncluded = true;
           }
         } else {
           // Mode: Strict
@@ -891,9 +890,9 @@ bool cmQtAutoGenerators::ParseContentForMoc(
           << "The file contains a " << macroName
           << " macro, but does not include "
           << "\"" << scannedFileBasename << ".moc\", but instead includes "
-          << "\"" << ownMocUnderscoreFile << "\". Running moc on "
-          << "\"" << absFilename << "\" ! Better include \""
-          << scannedFileBasename
+          << "\"" << ownMocUnderscoreFile << "\".\n"
+          << "Running moc on \"" << absFilename << "\"!\n"
+          << "Better include \"" << scannedFileBasename
           << ".moc\" for compatibility with "
              "strict mode (see CMAKE_AUTOMOC_RELAXED_MODE).\n";
       this->LogWarning(err.str());
@@ -907,7 +906,7 @@ bool cmQtAutoGenerators::ParseContentForMoc(
       err << "AutoMoc: Error: " << absFilename << "\n"
           << "The file contains a " << macroName
           << " macro, but does not include "
-          << "\"" << scannedFileBasename << ".moc\" !\n";
+          << "\"" << scannedFileBasename << ".moc\"!\n";
       this->LogError(err.str());
       return false;
     }

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=c84bca1030332d23d0fc6d06050e7a174f39d78a
commit c84bca1030332d23d0fc6d06050e7a174f39d78a
Author:     Sebastian Holtermann <sebholt at xwmw.org>
AuthorDate: Wed Feb 15 19:30:08 2017 +0100
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Mon Feb 20 15:51:22 2017 -0500

    Autogen: Acquire and store header extensions in Init()

diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx
index 129a04e..7fb7bfb 100644
--- a/Source/cmQtAutoGenerators.cxx
+++ b/Source/cmQtAutoGenerators.cxx
@@ -245,9 +245,9 @@ bool cmQtAutoGenerators::Run(const std::string& targetDirectory,
   // Read old settings
   this->SettingsFileRead(mf.get(), targetDirectory);
   // Init and run
-  this->Init();
+  this->Init(mf.get());
   if (this->QtMajorVersion == "4" || this->QtMajorVersion == "5") {
-    if (!this->RunAutogen(mf.get())) {
+    if (!this->RunAutogen()) {
       return false;
     }
   }
@@ -487,7 +487,7 @@ bool cmQtAutoGenerators::SettingsFileWrite(const std::string& targetDirectory)
   return success;
 }
 
-void cmQtAutoGenerators::Init()
+void cmQtAutoGenerators::Init(cmMakefile* makefile)
 {
   this->AutogenBuildSubDir = this->AutogenTargetName;
   this->AutogenBuildSubDir += "/";
@@ -502,6 +502,9 @@ void cmQtAutoGenerators::Init()
                                 this->ProjectSourceDir,
                                 this->ProjectBinaryDir);
 
+  // Acquire header extensions
+  this->HeaderExtensions = makefile->GetCMakeInstance()->GetHeaderExtensions();
+
   // Compose moc includes list
   std::list<std::string> mocIncludes;
   {
@@ -563,7 +566,7 @@ void cmQtAutoGenerators::Init()
                            mocIncludes.end());
 }
 
-bool cmQtAutoGenerators::RunAutogen(cmMakefile* makefile)
+bool cmQtAutoGenerators::RunAutogen()
 {
   // the program goes through all .cpp files to see which moc files are
   // included. It is not really interesting how the moc file is named, but
@@ -582,22 +585,17 @@ bool cmQtAutoGenerators::RunAutogen(cmMakefile* makefile)
   std::set<std::string> uicHeaderFiles;
 
   // Parse sources
-  {
-    const std::vector<std::string>& headerExtensions =
-      makefile->GetCMakeInstance()->GetHeaderExtensions();
-
-    for (std::vector<std::string>::const_iterator it = this->Sources.begin();
-         it != this->Sources.end(); ++it) {
-      const std::string& absFilename = *it;
-      // Parse source file for MOC/UIC
-      if (!this->ParseSourceFile(absFilename, headerExtensions, mocsIncluded,
-                                 uisIncluded, this->MocRelaxedMode)) {
-        return false;
-      }
-      // Find additional headers
-      this->SearchHeadersForSourceFile(absFilename, headerExtensions,
-                                       mocHeaderFiles, uicHeaderFiles);
+  for (std::vector<std::string>::const_iterator it = this->Sources.begin();
+       it != this->Sources.end(); ++it) {
+    const std::string& absFilename = *it;
+    // Parse source file for MOC/UIC
+    if (!this->ParseSourceFile(absFilename, mocsIncluded, uisIncluded,
+                               this->MocRelaxedMode)) {
+      return false;
     }
+    // Find additional headers
+    this->SearchHeadersForSourceFile(absFilename, mocHeaderFiles,
+                                     uicHeaderFiles);
   }
 
   // Parse headers
@@ -655,7 +653,7 @@ bool cmQtAutoGenerators::MocRequired(const std::string& text,
  * @brief Tests if the file should be ignored for moc scanning
  * @return True if the file should be ignored
  */
-bool cmQtAutoGenerators::MocSkip(const std::string& absFilename)
+bool cmQtAutoGenerators::MocSkip(const std::string& absFilename) const
 {
   if (this->MocEnabled()) {
     // Test if the file name is on the skip list
@@ -669,7 +667,7 @@ bool cmQtAutoGenerators::MocSkip(const std::string& absFilename)
 /**
  * @brief Tests if the file name is in the skip list
  */
-bool cmQtAutoGenerators::UicSkip(const std::string& absFilename)
+bool cmQtAutoGenerators::UicSkip(const std::string& absFilename) const
 {
   if (this->UicEnabled()) {
     // Test if the file name is on the skip list
@@ -685,7 +683,6 @@ bool cmQtAutoGenerators::UicSkip(const std::string& absFilename)
  */
 bool cmQtAutoGenerators::ParseSourceFile(
   const std::string& absFilename,
-  const std::vector<std::string>& headerExtensions,
   std::map<std::string, std::string>& mocsIncluded,
   std::map<std::string, std::vector<std::string> >& uisIncluded, bool relaxed)
 {
@@ -699,8 +696,8 @@ bool cmQtAutoGenerators::ParseSourceFile(
   } else {
     // Parse source contents for MOC
     if (success && !this->MocSkip(absFilename)) {
-      success = this->ParseContentForMoc(
-        absFilename, contentsString, headerExtensions, mocsIncluded, relaxed);
+      success = this->ParseContentForMoc(absFilename, contentsString,
+                                         mocsIncluded, relaxed);
     }
     // Parse source contents for UIC
     if (success && !this->UicSkip(absFilename)) {
@@ -740,7 +737,6 @@ void cmQtAutoGenerators::ParseContentForUic(
  */
 bool cmQtAutoGenerators::ParseContentForMoc(
   const std::string& absFilename, const std::string& contentsString,
-  const std::vector<std::string>& headerExtensions,
   std::map<std::string, std::string>& mocsIncluded, bool relaxed)
 {
   if (this->Verbose) {
@@ -788,8 +784,8 @@ bool cmQtAutoGenerators::ParseContentForMoc(
         // Include: moc_FOO.cxx
         // Remove the moc_ part
         const std::string incRealBasename = incBasename.substr(4);
-        const std::string headerToMoc = FindMatchingHeader(
-          scannedFileAbsPath, incRealBasename, incSubDir, headerExtensions);
+        const std::string headerToMoc = this->FindMatchingHeader(
+          scannedFileAbsPath, incRealBasename, incSubDir);
         if (!headerToMoc.empty()) {
           mocsIncluded[headerToMoc] = incString;
           if (relaxed && (incRealBasename == scannedFileBasename)) {
@@ -802,7 +798,7 @@ bool cmQtAutoGenerators::ParseContentForMoc(
           err << "AutoMoc: Error: " << absFilename << "\n"
               << "The file includes the moc file \"" << incString
               << "\", but could not find header \"" << incRealBasename << '{'
-              << JoinExts(headerExtensions) << "}\"\n";
+              << JoinExts(this->HeaderExtensions) << "}\"\n";
           this->LogError(err.str());
           return false;
         }
@@ -812,8 +808,8 @@ bool cmQtAutoGenerators::ParseContentForMoc(
         if (relaxed) {
           // Mode: Relaxed
           if (!requiresMoc || (incBasename != scannedFileBasename)) {
-            const std::string headerToMoc = FindMatchingHeader(
-              scannedFileAbsPath, incBasename, incSubDir, headerExtensions);
+            const std::string headerToMoc = this->FindMatchingHeader(
+              scannedFileAbsPath, incBasename, incSubDir);
             if (!headerToMoc.empty()) {
               // This is for KDE4 compatibility:
               fileToMoc = headerToMoc;
@@ -921,9 +917,8 @@ bool cmQtAutoGenerators::ParseContentForMoc(
 }
 
 void cmQtAutoGenerators::SearchHeadersForSourceFile(
-  const std::string& absFilename,
-  const std::vector<std::string>& headerExtensions,
-  std::set<std::string>& mocHeaderFiles, std::set<std::string>& uicHeaderFiles)
+  const std::string& absFilename, std::set<std::string>& mocHeaderFiles,
+  std::set<std::string>& uicHeaderFiles) const
 {
   std::string basepaths[2];
   {
@@ -940,8 +935,8 @@ void cmQtAutoGenerators::SearchHeadersForSourceFile(
   for (const std::string* bpit = cmArrayBegin(basepaths);
        bpit != cmArrayEnd(basepaths); ++bpit) {
     for (std::vector<std::string>::const_iterator heit =
-           headerExtensions.begin();
-         heit != headerExtensions.end(); ++heit) {
+           this->HeaderExtensions.begin();
+         heit != this->HeaderExtensions.end(); ++heit) {
       const std::string hname = (*bpit) + (*heit);
       if (cmsys::SystemTools::FileExists(hname.c_str())) {
         // Moc headers
@@ -1587,12 +1582,12 @@ std::string cmQtAutoGenerators::ChecksumedPath(const std::string& sourceFile,
  * appending different header extensions
  * @return True on success
  */
-bool cmQtAutoGenerators::FindHeader(
-  std::string& header, const std::string& testBasePath,
-  const std::vector<std::string>& headerExtensions) const
+bool cmQtAutoGenerators::FindHeader(std::string& header,
+                                    const std::string& testBasePath) const
 {
-  for (std::vector<std::string>::const_iterator ext = headerExtensions.begin();
-       ext != headerExtensions.end(); ++ext) {
+  for (std::vector<std::string>::const_iterator ext =
+         this->HeaderExtensions.begin();
+       ext != this->HeaderExtensions.end(); ++ext) {
     std::string testFilePath(testBasePath);
     testFilePath += '.';
     testFilePath += (*ext);
@@ -1606,17 +1601,16 @@ bool cmQtAutoGenerators::FindHeader(
 
 std::string cmQtAutoGenerators::FindMatchingHeader(
   const std::string& basePath, const std::string& baseName,
-  const std::string& subDir,
-  const std::vector<std::string>& headerExtensions) const
+  const std::string& subDir) const
 {
   std::string header;
   do {
     if (!subDir.empty()) {
-      if (FindHeader(header, basePath + subDir + baseName, headerExtensions)) {
+      if (this->FindHeader(header, basePath + subDir + baseName)) {
         break;
       }
     }
-    if (FindHeader(header, basePath + baseName, headerExtensions)) {
+    if (this->FindHeader(header, basePath + baseName)) {
       break;
     }
   } while (false);
diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGenerators.h
index 50df9f8..e6f9160 100644
--- a/Source/cmQtAutoGenerators.h
+++ b/Source/cmQtAutoGenerators.h
@@ -42,26 +42,23 @@ private:
   }
 
   // - Init and run
-  void Init();
-  bool RunAutogen(cmMakefile* makefile);
+  void Init(cmMakefile* makefile);
+  bool RunAutogen();
 
   // - Content analysis
   bool MocRequired(const std::string& text, std::string& macroName);
-  bool MocSkip(const std::string& absFilename);
-  bool UicSkip(const std::string& absFilename);
+  bool MocSkip(const std::string& absFilename) const;
+  bool UicSkip(const std::string& absFilename) const;
 
   bool ParseSourceFile(
     const std::string& absFilename,
-    const std::vector<std::string>& headerExtensions,
     std::map<std::string, std::string>& includedMocs,
     std::map<std::string, std::vector<std::string> >& includedUis,
     bool relaxed);
 
-  void SearchHeadersForSourceFile(
-    const std::string& absFilename,
-    const std::vector<std::string>& headerExtensions,
-    std::set<std::string>& absHeadersMoc,
-    std::set<std::string>& absHeadersUic);
+  void SearchHeadersForSourceFile(const std::string& absFilename,
+                                  std::set<std::string>& absHeadersMoc,
+                                  std::set<std::string>& absHeadersUic) const;
 
   void ParseHeaders(
     const std::set<std::string>& absHeadersMoc,
@@ -76,7 +73,6 @@ private:
 
   bool ParseContentForMoc(const std::string& absFilename,
                           const std::string& contentsString,
-                          const std::vector<std::string>& headerExtensions,
                           std::map<std::string, std::string>& includedMocs,
                           bool relaxed);
 
@@ -119,12 +115,10 @@ private:
                              const char* baseSuffix) const;
   bool MakeParentDirectory(const std::string& filename);
 
-  bool FindHeader(std::string& header, const std::string& testBasePath,
-                  const std::vector<std::string>& headerExtensions) const;
-  std::string FindMatchingHeader(
-    const std::string& basePath, const std::string& baseName,
-    const std::string& subDir,
-    const std::vector<std::string>& headerExtensions) const;
+  bool FindHeader(std::string& header, const std::string& testBasePath) const;
+  std::string FindMatchingHeader(const std::string& basePath,
+                                 const std::string& baseName,
+                                 const std::string& subDir) const;
 
   // - Target names
   std::string OriginTargetName;
@@ -165,6 +159,7 @@ private:
   std::map<std::string, std::vector<std::string> > RccInputs;
   // - Utility
   cmFilePathChecksum fpathCheckSum;
+  std::vector<std::string> HeaderExtensions;
   cmsys::RegularExpression RegExpQObject;
   cmsys::RegularExpression RegExpQGadget;
   cmsys::RegularExpression RegExpMocInclude;

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=78031e7cdcead6a348191158c674ec341fdd43be
commit 78031e7cdcead6a348191158c674ec341fdd43be
Author:     Sebastian Holtermann <sebholt at xwmw.org>
AuthorDate: Wed Feb 15 19:19:37 2017 +0100
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Mon Feb 20 15:51:22 2017 -0500

    Autogen: Overhaul FindMatchingHeader function

diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx
index 0605418..129a04e 100644
--- a/Source/cmQtAutoGenerators.cxx
+++ b/Source/cmQtAutoGenerators.cxx
@@ -73,42 +73,6 @@ static void SettingWrite(std::ostream& ostr, const char* key,
   }
 }
 
-static std::string FindMatchingHeader(
-  const std::string& absPath, const std::string& mocSubDir,
-  const std::string& basename,
-  const std::vector<std::string>& headerExtensions)
-{
-  std::string header;
-  for (std::vector<std::string>::const_iterator ext = headerExtensions.begin();
-       ext != headerExtensions.end(); ++ext) {
-    std::string sourceFilePath = absPath + basename + "." + (*ext);
-    if (cmsys::SystemTools::FileExists(sourceFilePath.c_str())) {
-      header = sourceFilePath;
-      break;
-    }
-    // Try subdirectory instead
-    if (!mocSubDir.empty()) {
-      sourceFilePath = mocSubDir + basename + "." + (*ext);
-      if (cmsys::SystemTools::FileExists(sourceFilePath.c_str())) {
-        header = sourceFilePath;
-        break;
-      }
-    }
-  }
-
-  return header;
-}
-
-static std::string ExtractSubDir(const std::string& absPath,
-                                 const std::string& currentMoc)
-{
-  std::string subDir;
-  if (currentMoc.find_first_of('/') != std::string::npos) {
-    subDir = absPath + cmsys::SystemTools::GetFilenamePath(currentMoc) + '/';
-  }
-  return subDir;
-}
-
 static bool FileNameIsUnique(const std::string& filePath,
                              const std::map<std::string, std::string>& fileMap)
 {
@@ -806,38 +770,38 @@ bool cmQtAutoGenerators::ParseContentForMoc(
   if (strstr(contentChars, "moc") != CM_NULLPTR) {
     // Iterate over all included moc files
     while (this->RegExpMocInclude.find(contentChars)) {
-      const std::string currentMoc = this->RegExpMocInclude.match(1);
-      // Basename of the current moc include
-      std::string basename =
-        cmsys::SystemTools::GetFilenameWithoutLastExtension(currentMoc);
+      const std::string incString = this->RegExpMocInclude.match(1);
+      // Basename of the moc include
+      const std::string incBasename =
+        cmsys::SystemTools::GetFilenameWithoutLastExtension(incString);
+      std::string incSubDir;
+      if (incString.find_first_of('/') != std::string::npos) {
+        incSubDir = cmsys::SystemTools::GetFilenamePath(incString) + '/';
+      }
 
       // If the moc include is of the moc_foo.cpp style we expect
       // the Q_OBJECT class declaration in a header file.
       // If the moc include is of the foo.moc style we need to look for
       // a Q_OBJECT macro in the current source file, if it contains the
       // macro we generate the moc file from the source file.
-      if (cmHasLiteralPrefix(basename, "moc_")) {
+      if (cmHasLiteralPrefix(incBasename, "moc_")) {
         // Include: moc_FOO.cxx
-        // basename should be the part of the moc filename used for
-        // finding the correct header, so we need to remove the moc_ part
-        basename = basename.substr(4);
-        const std::string mocSubDir =
-          ExtractSubDir(scannedFileAbsPath, currentMoc);
+        // Remove the moc_ part
+        const std::string incRealBasename = incBasename.substr(4);
         const std::string headerToMoc = FindMatchingHeader(
-          scannedFileAbsPath, mocSubDir, basename, headerExtensions);
-
+          scannedFileAbsPath, incRealBasename, incSubDir, headerExtensions);
         if (!headerToMoc.empty()) {
-          mocsIncluded[headerToMoc] = currentMoc;
-          if (relaxed && (basename == scannedFileBasename)) {
+          mocsIncluded[headerToMoc] = incString;
+          if (relaxed && (incRealBasename == scannedFileBasename)) {
             ownMocUnderscoreIncluded = true;
-            ownMocUnderscoreFile = currentMoc;
+            ownMocUnderscoreFile = incString;
             ownMocHeaderFile = headerToMoc;
           }
         } else {
           std::ostringstream err;
           err << "AutoMoc: Error: " << absFilename << "\n"
-              << "The file includes the moc file \"" << currentMoc
-              << "\", but could not find header \"" << basename << '{'
+              << "The file includes the moc file \"" << incString
+              << "\", but could not find header \"" << incRealBasename << '{'
               << JoinExts(headerExtensions) << "}\"\n";
           this->LogError(err.str());
           return false;
@@ -847,31 +811,31 @@ bool cmQtAutoGenerators::ParseContentForMoc(
         std::string fileToMoc;
         if (relaxed) {
           // Mode: Relaxed
-          if (!requiresMoc || basename != scannedFileBasename) {
-            const std::string mocSubDir =
-              ExtractSubDir(scannedFileAbsPath, currentMoc);
+          if (!requiresMoc || (incBasename != scannedFileBasename)) {
             const std::string headerToMoc = FindMatchingHeader(
-              scannedFileAbsPath, mocSubDir, basename, headerExtensions);
+              scannedFileAbsPath, incBasename, incSubDir, headerExtensions);
             if (!headerToMoc.empty()) {
               // This is for KDE4 compatibility:
               fileToMoc = headerToMoc;
-              if (!requiresMoc && basename == scannedFileBasename) {
+              if (!requiresMoc && (incBasename == scannedFileBasename)) {
                 std::ostringstream err;
                 err << "AutoMoc: Warning: " << absFilename << "\n"
-                    << "The file includes the moc file \"" << currentMoc
+                    << "The file includes the moc file \"" << incString
                     << "\", but does not contain a " << macroName
                     << " macro. Running moc on "
-                    << "\"" << headerToMoc << "\" ! Include \"moc_" << basename
+                    << "\"" << headerToMoc << "\" ! Include \"moc_"
+                    << incBasename
                     << ".cpp\" for a compatibility with "
                        "strict mode (see CMAKE_AUTOMOC_RELAXED_MODE).\n";
                 this->LogWarning(err.str());
               } else {
                 std::ostringstream err;
                 err << "AutoMoc: Warning: " << absFilename << "\n"
-                    << "The file includes the moc file \"" << currentMoc
-                    << "\" instead of \"moc_" << basename
+                    << "The file includes the moc file \"" << incString
+                    << "\" instead of \"moc_" << incBasename
                     << ".cpp\". Running moc on "
-                    << "\"" << headerToMoc << "\" ! Include \"moc_" << basename
+                    << "\"" << headerToMoc << "\" ! Include \"moc_"
+                    << incBasename
                     << ".cpp\" for compatibility with "
                        "strict mode (see CMAKE_AUTOMOC_RELAXED_MODE).\n";
                 this->LogWarning(err.str());
@@ -879,7 +843,7 @@ bool cmQtAutoGenerators::ParseContentForMoc(
             } else {
               std::ostringstream err;
               err << "AutoMoc: Error: " << absFilename << "\n"
-                  << "The file includes the moc file \"" << currentMoc
+                  << "The file includes the moc file \"" << incString
                   << "\", which seems to be the moc file from a different "
                      "source file. CMake also could not find a matching "
                      "header.\n";
@@ -893,7 +857,7 @@ bool cmQtAutoGenerators::ParseContentForMoc(
           }
         } else {
           // Mode: Strict
-          if (basename == scannedFileBasename) {
+          if (incBasename == scannedFileBasename) {
             // Include self
             fileToMoc = absFilename;
             ownDotMocIncluded = true;
@@ -901,7 +865,7 @@ bool cmQtAutoGenerators::ParseContentForMoc(
             // Don't allow FOO.moc include other than self in strict mode
             std::ostringstream err;
             err << "AutoMoc: Error: " << absFilename << "\n"
-                << "The file includes the moc file \"" << currentMoc
+                << "The file includes the moc file \"" << incString
                 << "\", which seems to be the moc file from a different "
                    "source file. This is not supported. Include \""
                 << scannedFileBasename
@@ -911,7 +875,7 @@ bool cmQtAutoGenerators::ParseContentForMoc(
           }
         }
         if (!fileToMoc.empty()) {
-          mocsIncluded[fileToMoc] = currentMoc;
+          mocsIncluded[fileToMoc] = incString;
         }
       }
       // Forward content pointer
@@ -919,11 +883,11 @@ bool cmQtAutoGenerators::ParseContentForMoc(
     }
   }
 
-  // In this case, check whether the scanned file itself contains a Q_OBJECT.
-  // If this is the case, the moc_foo.cpp should probably be generated from
-  // foo.cpp instead of foo.h, because otherwise it won't build.
-  // But warn, since this is not how it is supposed to be used.
   if (requiresMoc && !ownDotMocIncluded) {
+    // In this case, check whether the scanned file itself contains a Q_OBJECT.
+    // If this is the case, the moc_foo.cpp should probably be generated from
+    // foo.cpp instead of foo.h, because otherwise it won't build.
+    // But warn, since this is not how it is supposed to be used.
     if (relaxed && ownMocUnderscoreIncluded) {
       // This is for KDE4 compatibility:
       std::ostringstream err;
@@ -1619,6 +1583,47 @@ std::string cmQtAutoGenerators::ChecksumedPath(const std::string& sourceFile,
 }
 
 /**
+ * @brief Tries to find the header file to the given file base path by
+ * appending different header extensions
+ * @return True on success
+ */
+bool cmQtAutoGenerators::FindHeader(
+  std::string& header, const std::string& testBasePath,
+  const std::vector<std::string>& headerExtensions) const
+{
+  for (std::vector<std::string>::const_iterator ext = headerExtensions.begin();
+       ext != headerExtensions.end(); ++ext) {
+    std::string testFilePath(testBasePath);
+    testFilePath += '.';
+    testFilePath += (*ext);
+    if (cmsys::SystemTools::FileExists(testFilePath.c_str())) {
+      header = testFilePath;
+      return true;
+    }
+  }
+  return false;
+}
+
+std::string cmQtAutoGenerators::FindMatchingHeader(
+  const std::string& basePath, const std::string& baseName,
+  const std::string& subDir,
+  const std::vector<std::string>& headerExtensions) const
+{
+  std::string header;
+  do {
+    if (!subDir.empty()) {
+      if (FindHeader(header, basePath + subDir + baseName, headerExtensions)) {
+        break;
+      }
+    }
+    if (FindHeader(header, basePath + baseName, headerExtensions)) {
+      break;
+    }
+  } while (false);
+  return header;
+}
+
+/**
  * @brief Generates the parent directory of the given file on demand
  * @return True on success
  */
diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGenerators.h
index a466b77..50df9f8 100644
--- a/Source/cmQtAutoGenerators.h
+++ b/Source/cmQtAutoGenerators.h
@@ -119,6 +119,13 @@ private:
                              const char* baseSuffix) const;
   bool MakeParentDirectory(const std::string& filename);
 
+  bool FindHeader(std::string& header, const std::string& testBasePath,
+                  const std::vector<std::string>& headerExtensions) const;
+  std::string FindMatchingHeader(
+    const std::string& basePath, const std::string& baseName,
+    const std::string& subDir,
+    const std::vector<std::string>& headerExtensions) const;
+
   // - Target names
   std::string OriginTargetName;
   std::string AutogenTargetName;

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=c7f3bdedde2a38c8f2e46ca42f47efbde6252f1d
commit c7f3bdedde2a38c8f2e46ca42f47efbde6252f1d
Author:     Sebastian Holtermann <sebholt at xwmw.org>
AuthorDate: Wed Feb 15 17:36:58 2017 +0100
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Mon Feb 20 15:51:21 2017 -0500

    Autogen: Don't list all search paths in error message

diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx
index ebe9f28..0605418 100644
--- a/Source/cmQtAutoGenerators.cxx
+++ b/Source/cmQtAutoGenerators.cxx
@@ -838,13 +838,7 @@ bool cmQtAutoGenerators::ParseContentForMoc(
           err << "AutoMoc: Error: " << absFilename << "\n"
               << "The file includes the moc file \"" << currentMoc
               << "\", but could not find header \"" << basename << '{'
-              << JoinExts(headerExtensions) << "}\" ";
-          if (mocSubDir.empty()) {
-            err << "in " << scannedFileAbsPath << "\n";
-          } else {
-            err << "neither in " << scannedFileAbsPath << " nor in "
-                << mocSubDir << "\n";
-          }
+              << JoinExts(headerExtensions) << "}\"\n";
           this->LogError(err.str());
           return false;
         }

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=17a2cfbcdd41ee607556794e5210744b90005dfb
commit 17a2cfbcdd41ee607556794e5210744b90005dfb
Author:     Sebastian Holtermann <sebholt at xwmw.org>
AuthorDate: Wed Feb 15 13:43:19 2017 +0100
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Mon Feb 20 15:51:21 2017 -0500

    Autogen: Indentation fix

diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx
index 1453711..ebe9f28 100644
--- a/Source/cmQtAutoGenerators.cxx
+++ b/Source/cmQtAutoGenerators.cxx
@@ -607,8 +607,7 @@ bool cmQtAutoGenerators::RunAutogen(cmMakefile* makefile)
   // may not be included in the moc_compilation.cpp file anymore. OTOH if
   // there's a header containing Q_OBJECT where no corresponding moc file
   // is included anywhere a moc_<filename>.cpp file is created and included
-  // in
-  // the moc_compilation.cpp file.
+  // in the moc_compilation.cpp file.
 
   // key = moc source filepath, value = moc output filepath
   std::map<std::string, std::string> mocsIncluded;

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=7111b59f020c3b6fa01136b608ce6777969f92e7
commit 7111b59f020c3b6fa01136b608ce6777969f92e7
Author:     Sebastian Holtermann <sebholt at xwmw.org>
AuthorDate: Wed Feb 15 13:23:27 2017 +0100
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Mon Feb 20 15:51:21 2017 -0500

    Autogen: Rename moc related variables

diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx
index f2a4174..1453711 100644
--- a/Source/cmQtAutoGenerators.cxx
+++ b/Source/cmQtAutoGenerators.cxx
@@ -528,11 +528,10 @@ void cmQtAutoGenerators::Init()
   this->AutogenBuildSubDir = this->AutogenTargetName;
   this->AutogenBuildSubDir += "/";
 
-  this->OutMocCppFilenameRel = this->AutogenBuildSubDir;
-  this->OutMocCppFilenameRel += "moc_compilation.cpp";
+  this->MocCppFilenameRel = this->AutogenBuildSubDir;
+  this->MocCppFilenameRel += "moc_compilation.cpp";
 
-  this->OutMocCppFilenameAbs =
-    this->CurrentBinaryDir + this->OutMocCppFilenameRel;
+  this->MocCppFilenameAbs = this->CurrentBinaryDir + this->MocCppFilenameRel;
 
   // Init file path checksum generator
   fpathCheckSum.setupParentDirs(this->CurrentSourceDir, this->CurrentBinaryDir,
@@ -1124,12 +1123,12 @@ bool cmQtAutoGenerators::MocGenerateAll(
   // Check if we even need to update moc_compilation.cpp
   if (!automocCppChanged) {
     // compare contents of the moc_compilation.cpp file
-    const std::string oldContents = ReadAll(this->OutMocCppFilenameAbs);
+    const std::string oldContents = ReadAll(this->MocCppFilenameAbs);
     if (oldContents == automocSource) {
       // nothing changed: don't touch the moc_compilation.cpp file
       if (this->Verbose) {
         std::ostringstream err;
-        err << "AutoMoc: " << this->OutMocCppFilenameRel << " still up to date"
+        err << "AutoMoc: " << this->MocCppFilenameRel << " still up to date"
             << std::endl;
         this->LogInfo(err.str());
       }
@@ -1138,17 +1137,17 @@ bool cmQtAutoGenerators::MocGenerateAll(
   }
 
   // Actually write moc_compilation.cpp
-  this->LogBold("Generating MOC compilation " + this->OutMocCppFilenameRel);
+  this->LogBold("Generating MOC compilation " + this->MocCppFilenameRel);
 
   // Make sure the parent directory exists
-  bool success = this->MakeParentDirectory(this->OutMocCppFilenameAbs);
+  bool success = this->MakeParentDirectory(this->MocCppFilenameAbs);
   if (success) {
     cmsys::ofstream outfile;
-    outfile.open(this->OutMocCppFilenameAbs.c_str(), std::ios::trunc);
+    outfile.open(this->MocCppFilenameAbs.c_str(), std::ios::trunc);
     if (!outfile) {
       success = false;
       std::ostringstream err;
-      err << "AutoMoc: error opening " << this->OutMocCppFilenameAbs << "\n";
+      err << "AutoMoc: error opening " << this->MocCppFilenameAbs << "\n";
       this->LogError(err.str());
     } else {
       outfile << automocSource;
@@ -1156,7 +1155,7 @@ bool cmQtAutoGenerators::MocGenerateAll(
       if (!outfile.good()) {
         success = false;
         std::ostringstream err;
-        err << "AutoMoc: error writing " << this->OutMocCppFilenameAbs << "\n";
+        err << "AutoMoc: error writing " << this->MocCppFilenameAbs << "\n";
         this->LogError(err.str());
       }
     }
diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGenerators.h
index f6caed9..a466b77 100644
--- a/Source/cmQtAutoGenerators.h
+++ b/Source/cmQtAutoGenerators.h
@@ -141,10 +141,10 @@ private:
   std::string SettingsStringUic;
   std::string SettingsStringRcc;
   // - Moc
-  std::vector<std::string> MocSkipList;
   std::string MocInfoIncludes;
-  std::string OutMocCppFilenameRel;
-  std::string OutMocCppFilenameAbs;
+  std::string MocCppFilenameRel;
+  std::string MocCppFilenameAbs;
+  std::vector<std::string> MocSkipList;
   std::vector<std::string> MocIncludes;
   std::vector<std::string> MocDefinitions;
   std::vector<std::string> MocOptions;

https://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=82e0d0642a42b0592be27ed20efb43e34aaa2091
commit 82e0d0642a42b0592be27ed20efb43e34aaa2091
Author:     Sebastian Holtermann <sebholt at xwmw.org>
AuthorDate: Wed Feb 15 12:53:39 2017 +0100
Commit:     Brad King <brad.king at kitware.com>
CommitDate: Mon Feb 20 15:51:20 2017 -0500

    Autogen: Overhaul moc include list generation

diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx
index a167705..f2a4174 100644
--- a/Source/cmQtAutoGenerators.cxx
+++ b/Source/cmQtAutoGenerators.cxx
@@ -539,58 +539,65 @@ void cmQtAutoGenerators::Init()
                                 this->ProjectSourceDir,
                                 this->ProjectBinaryDir);
 
-  std::vector<std::string> incPaths;
-  cmSystemTools::ExpandListArgument(this->MocInfoIncludes, incPaths);
-
-  std::set<std::string> frameworkPaths;
-  for (std::vector<std::string>::const_iterator it = incPaths.begin();
-       it != incPaths.end(); ++it) {
-    const std::string& path = *it;
-    this->MocIncludes.push_back("-I" + path);
-    if (cmHasLiteralSuffix(path, ".framework/Headers")) {
-      // Go up twice to get to the framework root
-      std::vector<std::string> pathComponents;
-      cmsys::SystemTools::SplitPath(path, pathComponents);
-      std::string frameworkPath = cmsys::SystemTools::JoinPath(
-        pathComponents.begin(), pathComponents.end() - 2);
-      frameworkPaths.insert(frameworkPath);
+  // Compose moc includes list
+  std::list<std::string> mocIncludes;
+  {
+    std::set<std::string> frameworkPaths;
+    {
+      std::vector<std::string> incPaths;
+      cmSystemTools::ExpandListArgument(this->MocInfoIncludes, incPaths);
+      for (std::vector<std::string>::const_iterator it = incPaths.begin();
+           it != incPaths.end(); ++it) {
+        const std::string& path = *it;
+        mocIncludes.push_back("-I" + path);
+        // Extract framework path
+        if (cmHasLiteralSuffix(path, ".framework/Headers")) {
+          // Go up twice to get to the framework root
+          std::vector<std::string> pathComponents;
+          cmsys::SystemTools::SplitPath(path, pathComponents);
+          std::string frameworkPath = cmsys::SystemTools::JoinPath(
+            pathComponents.begin(), pathComponents.end() - 2);
+          frameworkPaths.insert(frameworkPath);
+        }
+      }
+    }
+    // Append framework includes
+    for (std::set<std::string>::const_iterator it = frameworkPaths.begin();
+         it != frameworkPaths.end(); ++it) {
+      mocIncludes.push_back("-F");
+      mocIncludes.push_back(*it);
     }
   }
-
-  for (std::set<std::string>::const_iterator it = frameworkPaths.begin();
-       it != frameworkPaths.end(); ++it) {
-    this->MocIncludes.push_back("-F");
-    this->MocIncludes.push_back(*it);
-  }
-
   if (this->IncludeProjectDirsBefore) {
-    const std::string binDir = "-I" + this->ProjectBinaryDir;
-    const std::string srcDir = "-I" + this->ProjectSourceDir;
-
-    std::list<std::string> sortedMocIncludes;
-    std::list<std::string>::iterator it = this->MocIncludes.begin();
-    while (it != this->MocIncludes.end()) {
-      if (cmsys::SystemTools::StringStartsWith(*it, binDir.c_str())) {
-        sortedMocIncludes.push_back(*it);
-        it = this->MocIncludes.erase(it);
-      } else {
-        ++it;
-      }
-    }
-    it = this->MocIncludes.begin();
-    while (it != this->MocIncludes.end()) {
-      if (cmsys::SystemTools::StringStartsWith(*it, srcDir.c_str())) {
-        sortedMocIncludes.push_back(*it);
-        it = this->MocIncludes.erase(it);
-      } else {
-        ++it;
+    // Extract project includes
+    std::vector<std::string> mocSortedIncludes;
+    {
+      std::vector<std::string> movePaths;
+      movePaths.push_back("-I" + this->ProjectBinaryDir);
+      movePaths.push_back("-I" + this->ProjectSourceDir);
+
+      for (std::vector<std::string>::const_iterator mpit = movePaths.begin();
+           mpit != movePaths.end(); ++mpit) {
+        std::list<std::string>::iterator it = mocIncludes.begin();
+        while (it != mocIncludes.end()) {
+          const std::string& path = *it;
+          if (cmsys::SystemTools::StringStartsWith(path, mpit->c_str())) {
+            mocSortedIncludes.push_back(path);
+            it = mocIncludes.erase(it);
+          } else {
+            ++it;
+          }
+        }
       }
     }
-    sortedMocIncludes.insert(sortedMocIncludes.end(),
-                             this->MocIncludes.begin(),
-                             this->MocIncludes.end());
-    this->MocIncludes = sortedMocIncludes;
-  }
+    // Place extracted includes at the begin
+    this->MocIncludes.insert(this->MocIncludes.end(),
+                             mocSortedIncludes.begin(),
+                             mocSortedIncludes.end());
+  }
+  // Append remaining includes
+  this->MocIncludes.insert(this->MocIncludes.end(), mocIncludes.begin(),
+                           mocIncludes.end());
 }
 
 bool cmQtAutoGenerators::RunAutogen(cmMakefile* makefile)
diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGenerators.h
index e60320b..f6caed9 100644
--- a/Source/cmQtAutoGenerators.h
+++ b/Source/cmQtAutoGenerators.h
@@ -7,7 +7,6 @@
 #include <cmFilePathChecksum.h>
 #include <cmsys/RegularExpression.hxx>
 
-#include <list>
 #include <map>
 #include <set>
 #include <string>
@@ -146,7 +145,7 @@ private:
   std::string MocInfoIncludes;
   std::string OutMocCppFilenameRel;
   std::string OutMocCppFilenameAbs;
-  std::list<std::string> MocIncludes;
+  std::vector<std::string> MocIncludes;
   std::vector<std::string> MocDefinitions;
   std::vector<std::string> MocOptions;
   // - Uic

-----------------------------------------------------------------------

Summary of changes:


hooks/post-receive
-- 
CMake


More information about the Cmake-commits mailing list