Imported Upstream version 3.17.5 upstream/3.17.5
authorDongHun Kwak <dh0128.kwak@samsung.com>
Fri, 8 Oct 2021 00:20:08 +0000 (09:20 +0900)
committerDongHun Kwak <dh0128.kwak@samsung.com>
Fri, 8 Oct 2021 00:20:08 +0000 (09:20 +0900)
25 files changed:
Help/prop_tgt/AUTOMOC_PATH_PREFIX.rst
Help/release/3.16.rst
Help/release/3.17.rst
Help/variable/CMAKE_AUTOMOC_PATH_PREFIX.rst
Modules/CMakeGenericSystem.cmake
Source/CMakeVersion.cmake
Source/cmNinjaNormalTargetGenerator.cxx
Source/cmQtAutoGenInitializer.cxx
Source/cmQtAutoMocUic.cxx
Tests/QtAutogen/MocIncludeSymlink/CMakeLists.txt
Tests/QtAutogen/RerunMocOnAddFile/CMakeLists.txt [new file with mode: 0644]
Tests/QtAutogen/RerunMocOnAddFile/MocOnAddFile/CMakeLists.txt.in [new file with mode: 0644]
Tests/QtAutogen/RerunMocOnAddFile/MocOnAddFile/anotherobject.cpp [new file with mode: 0644]
Tests/QtAutogen/RerunMocOnAddFile/MocOnAddFile/main.cpp.in [new file with mode: 0644]
Tests/QtAutogen/RerunMocOnAddFile/MocOnAddFile/myobject.cpp [new file with mode: 0644]
Tests/QtAutogen/RerunMocOnAddFile/MocOnAddFile/myobject.h [new file with mode: 0644]
Tests/QtAutogen/Tests.cmake
Tests/RunCMake/CMakeLists.txt
Tests/RunCMake/FindPkgConfig/RunCMakeTest.cmake
Tests/RunCMake/Ninja/Qt5AutoMocDeps.cmake [new file with mode: 0644]
Tests/RunCMake/Ninja/RunCMakeTest.cmake
Tests/RunCMake/Ninja/app.cpp [new file with mode: 0644]
Tests/RunCMake/Ninja/app_qt.cpp [new file with mode: 0644]
Tests/RunCMake/Ninja/simple_lib.cpp [new file with mode: 0644]
Utilities/std/cmext/memory

index 3e3059d..5ed504f 100644 (file)
@@ -13,7 +13,7 @@ the ``-p`` path prefix option.  ``moc`` usually generates a
 relative include path in that case.
 
 :prop_tgt:`AUTOMOC_PATH_PREFIX` is initialized from the variable
-:variable:`CMAKE_AUTOMOC_PATH_PREFIX`, which is ``ON`` by default.
+:variable:`CMAKE_AUTOMOC_PATH_PREFIX`, which is ``OFF`` by default.
 
 See the :manual:`cmake-qt(7)` manual for more information on using CMake
 with Qt.
@@ -24,8 +24,7 @@ Reproducible builds
 For reproducible builds it is recommended to keep headers that are ``moc``
 compiled in one of the target
 :command:`include directories <target_include_directories>` and set
-:prop_tgt:`AUTOMOC_PATH_PREFIX` to ``ON`` (which is the default).  This ensures
-that:
+:prop_tgt:`AUTOMOC_PATH_PREFIX` to ``ON``.  This ensures that:
 
 - ``moc`` output files are identical on different build setups,
 - ``moc`` output files will compile correctly when the source and/or
index f3fdb08..84d96cd 100644 (file)
@@ -178,17 +178,15 @@ Modules
 Autogen
 -------
 
-* When using :prop_tgt:`AUTOMOC`, CMake now generates the ``-p`` path prefix
+* When using :prop_tgt:`AUTOMOC`, the new :variable:`CMAKE_AUTOMOC_PATH_PREFIX`
+  variable or :prop_tgt:`AUTOMOC_PATH_PREFIX` target property may be enabled
+  to generate the ``-p`` path prefix
   option for ``moc``.  This ensures that ``moc`` output files are identical
   on different build setups (given, that the headers compiled by ``moc`` are
   in an :command:`include directory <target_include_directories>`).
   Also it ensures that ``moc`` output files will compile correctly when the
   source and/or build directory is a symbolic link.
 
-  The ``moc`` path prefix generation behavior can be configured by setting
-  the new :variable:`CMAKE_AUTOMOC_PATH_PREFIX` variable and/or
-  :prop_tgt:`AUTOMOC_PATH_PREFIX` target property.
-
 CTest
 -----
 
@@ -316,3 +314,11 @@ Changes made since CMake 3.16.0 include the following.
   :prop_tgt:`INTERFACE_INCLUDE_DIRECTORIES` target properties.
   Previously they would be places in ``*_CFLAGS_OTHER`` variables and
   :prop_tgt:`INTERFACE_COMPILE_OPTIONS` target properties.
+
+3.16.9
+------
+
+* The default value of :variable:`CMAKE_AUTOMOC_PATH_PREFIX` was changed to
+  ``OFF`` because this feature can break existing projects that have
+  identically named header files in different include directories.
+  This restores compatibility with behavior of CMake 3.15 and below.
index b7c66d8..abd7463 100644 (file)
@@ -346,3 +346,12 @@ Changes made since CMake 3.17.0 include the following.
   :prop_tgt:`INTERFACE_INCLUDE_DIRECTORIES` target properties.
   Previously they would be places in ``*_CFLAGS_OTHER`` variables and
   :prop_tgt:`INTERFACE_COMPILE_OPTIONS` target properties.
+
+3.17.5
+------
+
+* The default value of :variable:`CMAKE_AUTOMOC_PATH_PREFIX` was changed to
+  ``OFF`` because this feature can break existing projects that have
+  identically named header files in different include directories.
+  This restores compatibility with behavior of CMake 3.15 and below.
+  The default was also changed to ``OFF`` in 3.16.9.
index dca0b06..1e9790f 100644 (file)
@@ -8,4 +8,4 @@ This variable is used to initialize the :prop_tgt:`AUTOMOC_PATH_PREFIX`
 property on all the targets.  See that target property for additional
 information.
 
-The default value is ``ON``.
+The default value is ``OFF``.
index f539b46..a773dcd 100644 (file)
@@ -26,7 +26,9 @@ set(CMAKE_FIND_LIBRARY_SUFFIXES ".so" ".a")
 
 set(CMAKE_AUTOGEN_ORIGIN_DEPENDS ON)
 set(CMAKE_AUTOMOC_COMPILER_PREDEFINES ON)
-set(CMAKE_AUTOMOC_PATH_PREFIX ON)
+if(NOT DEFINED CMAKE_AUTOMOC_PATH_PREFIX)
+  set(CMAKE_AUTOMOC_PATH_PREFIX OFF)
+endif()
 set(CMAKE_AUTOMOC_MACRO_NAMES "Q_OBJECT" "Q_GADGET" "Q_NAMESPACE" "Q_NAMESPACE_EXPORT")
 
 # basically all general purpose OSs support shared libs
index 1e82f54..661be10 100644 (file)
@@ -1,7 +1,7 @@
 # CMake version number components.
 set(CMake_VERSION_MAJOR 3)
 set(CMake_VERSION_MINOR 17)
-set(CMake_VERSION_PATCH 4)
+set(CMake_VERSION_PATCH 5)
 #set(CMake_VERSION_RC 0)
 set(CMake_VERSION_IS_DIRTY 0)
 
@@ -21,7 +21,7 @@ endif()
 
 if(NOT CMake_VERSION_NO_GIT)
   # If this source was exported by 'git archive', use its commit info.
-  set(git_info [==[103d6faed9 CMake 3.17.4]==])
+  set(git_info [==[566e96d42d CMake 3.17.5]==])
 
   # Otherwise, try to identify the current development source version.
   if(NOT git_info MATCHES "^([0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]?[0-9a-f]?)[0-9a-f]* "
index eed463d..ba2ea5b 100644 (file)
@@ -748,12 +748,8 @@ void cmNinjaNormalTargetGenerator::WriteDeviceLinkStatement(
     static_cast<int>(cmSystemTools::CalculateCommandLineLengthLimit()) -
     globalGen->GetRuleCmdLength(this->LanguageLinkerDeviceRule(config));
 
-  std::string path = localGen.GetHomeRelativeOutputPath();
-  if (!path.empty()) {
-    path += '/';
-  }
   build.RspFile = this->ConvertToNinjaPath(
-    cmStrCat(path, "CMakeFiles/", genTarget->GetName(),
+    cmStrCat("CMakeFiles/", genTarget->GetName(),
              globalGen->IsMultiConfig() ? cmStrCat('.', config) : "", ".rsp"));
 
   // Gather order-only dependencies.
@@ -1162,12 +1158,8 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement(
       globalGen->GetRuleCmdLength(linkBuild.Rule);
   }
 
-  std::string path = localGen.GetHomeRelativeOutputPath();
-  if (!path.empty()) {
-    path += '/';
-  }
   linkBuild.RspFile = this->ConvertToNinjaPath(
-    cmStrCat(path, "CMakeFiles/", gt->GetName(),
+    cmStrCat("CMakeFiles/", gt->GetName(),
              globalGen->IsMultiConfig() ? cmStrCat('.', config) : "", ".rsp"));
 
   // Gather order-only dependencies.
index 629367d..d8b9100 100644 (file)
@@ -1180,11 +1180,54 @@ bool cmQtAutoGenInitializer::InitAutogenTarget()
     if (useNinjaDepfile) {
       // Create a custom command that generates a timestamp file and
       // has a depfile assigned. The depfile is created by JobDepFilesMergeT.
-
-      // Add additional autogen target dependencies
+      //
+      // Also create an additional '_autogen_timestamp_deps' that the custom
+      // command will depend on. It will have no sources or commands to
+      // execute, but it will have dependencies that would originally be
+      // assigned to the pre-Qt 5.15 'autogen' target. These dependencies will
+      // serve as a list of order-only dependencies for the custom command,
+      // without forcing the custom command to re-execute.
+      //
+      // The dependency tree would then look like
+      // '_autogen_timestamp_deps (order-only)' <- '/timestamp' file <-
+      // '_autogen' target.
+      const auto timestampTargetName =
+        cmStrCat(this->GenTarget->GetName(), "_autogen_timestamp_deps");
+      std::vector<std::string> timestampTargetProvides;
+      cmCustomCommandLines timestampTargetCommandLines;
+
+      // Add additional autogen target dependencies to
+      // '_autogen_timestamp_deps'.
       for (const cmTarget* t : this->AutogenTarget.DependTargets) {
         dependencies.push_back(t->GetName());
       }
+
+      cmTarget* timestampTarget = this->LocalGen->AddUtilityCommand(
+        timestampTargetName, true, this->Dir.Work.c_str(),
+        /*byproducts=*/timestampTargetProvides,
+        /*depends=*/dependencies, timestampTargetCommandLines, false, nullptr);
+      this->LocalGen->AddGeneratorTarget(
+        cm::make_unique<cmGeneratorTarget>(timestampTarget, this->LocalGen));
+
+      // Set FOLDER property on the timestamp target, so it appears in the
+      // appropriate folder in an IDE or in the file api.
+      if (!this->TargetsFolder.empty()) {
+        timestampTarget->SetProperty("FOLDER", this->TargetsFolder);
+      }
+
+      // Make '/timestamp' file depend on '_autogen_timestamp_deps' and on the
+      // moc and uic executables (whichever are enabled).
+      dependencies.clear();
+      dependencies.push_back(timestampTargetName);
+
+      if (this->Moc.ExecutableTarget != nullptr) {
+        dependencies.push_back(this->Moc.ExecutableTarget->Target->GetName());
+      }
+      if (this->Uic.ExecutableTarget != nullptr) {
+        dependencies.push_back(this->Uic.ExecutableTarget->Target->GetName());
+      }
+
+      // Create the custom command that outputs the timestamp file.
       const char timestampFileName[] = "timestamp";
       const std::string outputFile =
         cmStrCat(this->Dir.Build, "/", timestampFileName);
@@ -1465,6 +1508,7 @@ bool cmQtAutoGenInitializer::SetupWriteAutogenInfo()
   info.SetConfig("PARSE_CACHE_FILE", this->AutogenTarget.ParseCacheFile);
   info.Set("DEP_FILE", this->AutogenTarget.DepFile);
   info.Set("DEP_FILE_RULE_NAME", this->AutogenTarget.DepFileRuleName);
+  info.SetArray("CMAKE_LIST_FILES", this->Makefile->GetListFiles());
   info.SetArray("HEADER_EXTENSIONS",
                 this->Makefile->GetCMakeInstance()->GetHeaderExtensions());
   info.SetArrayArray(
index 893bd6b..49eb018 100644 (file)
@@ -184,6 +184,7 @@ public:
     std::string DepFile;
     std::string DepFileRuleName;
     std::vector<std::string> HeaderExtensions;
+    std::vector<std::string> ListFiles;
   };
 
   /** Shared common variables.  */
@@ -2163,7 +2164,9 @@ std::string escapeDependencyPath(cm::string_view path)
 void cmQtAutoMocUicT::JobDepFilesMergeT::Process()
 {
   if (Log().Verbose()) {
-    Log().Info(GenT::MOC, "Merging MOC dependencies");
+    Log().Info(GenT::MOC,
+               cmStrCat("Merging MOC dependencies into ",
+                        MessagePath(BaseConst().DepFile.c_str())));
   }
   auto processDepFile =
     [](const std::string& mocOutputFile) -> std::vector<std::string> {
@@ -2174,7 +2177,7 @@ void cmQtAutoMocUicT::JobDepFilesMergeT::Process()
     return dependenciesFromDepFile(f.c_str());
   };
 
-  std::vector<std::string> dependencies;
+  std::vector<std::string> dependencies = BaseConst().ListFiles;
   ParseCacheT& parseCache = BaseEval().ParseCache;
   auto processMappingEntry = [&](const MappingMapT::value_type& m) {
     auto cacheEntry = parseCache.GetOrInsert(m.first);
@@ -2256,6 +2259,7 @@ bool cmQtAutoMocUicT::InitFromInfo(InfoT const& info)
       !info.GetString("DEP_FILE_RULE_NAME", BaseConst_.DepFileRuleName,
                       false) ||
       !info.GetStringConfig("SETTINGS_FILE", SettingsFile_, true) ||
+      !info.GetArray("CMAKE_LIST_FILES", BaseConst_.ListFiles, true) ||
       !info.GetArray("HEADER_EXTENSIONS", BaseConst_.HeaderExtensions, true) ||
       !info.GetString("QT_MOC_EXECUTABLE", MocConst_.Executable, false) ||
       !info.GetString("QT_UIC_EXECUTABLE", UicConst_.Executable, false)) {
index 1627b39..8b11b46 100644 (file)
@@ -61,6 +61,7 @@ macro(buildMocInclude sourceDir binaryDir)
     "${sourceDir}"
     MocInclude
     CMAKE_FLAGS "-DQT_TEST_VERSION=${QT_TEST_VERSION}"
+                "-DCMAKE_AUTOMOC_PATH_PREFIX=ON"
                 "-DCMAKE_AUTOGEN_VERBOSE=${CMAKE_AUTOGEN_VERBOSE}"
                 "-DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}"
     OUTPUT_VARIABLE output
diff --git a/Tests/QtAutogen/RerunMocOnAddFile/CMakeLists.txt b/Tests/QtAutogen/RerunMocOnAddFile/CMakeLists.txt
new file mode 100644 (file)
index 0000000..2677659
--- /dev/null
@@ -0,0 +1,96 @@
+# This test checks whether adding a source file to the project triggers an AUTOMOC re-run.
+
+cmake_minimum_required(VERSION 3.10)
+project(RerunMocOnAddFile)
+include("../AutogenCoreTest.cmake")
+
+# Create an executable to generate a clean target
+set(main_source "${CMAKE_CURRENT_BINARY_DIR}/generated_main.cpp")
+file(WRITE "${main_source}" "int main() {}")
+add_executable(exe "${main_source}")
+
+# Utility variables
+set(timeformat "%Y.%j.%H.%M%S")
+set(testProjectTemplateDir "${CMAKE_CURRENT_SOURCE_DIR}/MocOnAddFile")
+set(testProjectSrc "${CMAKE_CURRENT_BINARY_DIR}/MocOnAddFile")
+set(testProjectBinDir "${CMAKE_CURRENT_BINARY_DIR}/MocOnAddFile-build")
+
+# Utility macros
+macro(sleep)
+  message(STATUS "Sleeping for a few seconds.")
+  execute_process(COMMAND "${CMAKE_COMMAND}" -E sleep 1)
+endmacro()
+
+macro(acquire_timestamp When)
+  file(TIMESTAMP "${mocBasicBin}" time${When} "${timeformat}")
+endmacro()
+
+macro(rebuild buildName)
+  message(STATUS "Starting build ${buildName}.")
+  execute_process(COMMAND "${CMAKE_COMMAND}" --build . WORKING_DIRECTORY "${testProjectBinDir}" RESULT_VARIABLE result)
+  if (result)
+    message(FATAL_ERROR "Build ${buildName} failed.")
+  else()
+    message(STATUS "Build ${buildName} finished.")
+  endif()
+endmacro()
+
+macro(require_change)
+  if (timeAfter VERSION_GREATER timeBefore)
+    message(STATUS "As expected the file ${mocBasicBin} changed.")
+  else()
+    message(SEND_ERROR "Unexpectedly the file ${mocBasicBin} did not change!\nTimestamp pre: ${timeBefore}\nTimestamp aft: ${timeAfter}\n")
+  endif()
+endmacro()
+
+macro(require_change_not)
+  if (timeAfter VERSION_GREATER timeBefore)
+    message(SEND_ERROR "Unexpectedly the file ${mocBasicBin} changed!\nTimestamp pre: ${timeBefore}\nTimestamp aft: ${timeAfter}\n")
+  else()
+    message(STATUS "As expected the file ${mocBasicBin} did not change.")
+  endif()
+endmacro()
+
+# Create the test project from the template
+unset(additional_project_sources)
+unset(main_cpp_includes)
+configure_file("${testProjectTemplateDir}/CMakeLists.txt.in" "${testProjectSrc}/CMakeLists.txt")
+configure_file("${testProjectTemplateDir}/main.cpp.in" "${testProjectSrc}/main.cpp")
+
+# Initial build
+try_compile(MOC_RERUN
+  "${testProjectBinDir}"
+  "${testProjectSrc}"
+  MocOnAddFile
+  CMAKE_FLAGS "-DQT_TEST_VERSION=${QT_TEST_VERSION}"
+              "-DCMAKE_AUTOGEN_VERBOSE=${CMAKE_AUTOGEN_VERBOSE}"
+              "-DQT_QMAKE_EXECUTABLE:FILEPATH=${QT_QMAKE_EXECUTABLE}"
+  OUTPUT_VARIABLE output
+)
+if (NOT MOC_RERUN)
+  message(FATAL_ERROR "Initial build of mocOnAddFile failed. Output: ${output}")
+endif()
+
+# Sleep to ensure new timestamps
+sleep()
+
+# Add a QObject class (defined in header) to the project and build
+set(additional_project_sources myobject.cpp)
+set(main_cpp_includes "#include \"myobject.h\"")
+configure_file("${testProjectTemplateDir}/CMakeLists.txt.in" "${testProjectSrc}/CMakeLists.txt"
+    @ONLY)
+configure_file("${testProjectTemplateDir}/main.cpp.in" "${testProjectSrc}/main.cpp" @ONLY)
+configure_file("${testProjectTemplateDir}/myobject.h" "${testProjectSrc}/myobject.h" COPYONLY)
+configure_file("${testProjectTemplateDir}/myobject.cpp" "${testProjectSrc}/myobject.cpp" COPYONLY)
+rebuild(2)
+
+# Sleep to ensure new timestamps
+sleep()
+
+# Add a QObject class (defined in source) to the project and build
+set(additional_project_sources myobject.cpp anotherobject.cpp)
+configure_file("${testProjectTemplateDir}/CMakeLists.txt.in" "${testProjectSrc}/CMakeLists.txt"
+    @ONLY)
+configure_file("${testProjectTemplateDir}/anotherobject.cpp" "${testProjectSrc}/anotherobject.cpp"
+    COPYONLY)
+rebuild(3)
diff --git a/Tests/QtAutogen/RerunMocOnAddFile/MocOnAddFile/CMakeLists.txt.in b/Tests/QtAutogen/RerunMocOnAddFile/MocOnAddFile/CMakeLists.txt.in
new file mode 100644 (file)
index 0000000..9e5e21c
--- /dev/null
@@ -0,0 +1,9 @@
+cmake_minimum_required(VERSION 3.10)
+project(MocOnAddFile)
+include("@CMAKE_CURRENT_LIST_DIR@/../AutogenCoreTest.cmake")
+
+set(CMAKE_AUTOMOC ON)
+set(CMAKE_AUTORCC ON)
+
+add_executable(mocOnAddFile main.cpp @additional_project_sources@)
+target_link_libraries(mocOnAddFile ${QT_QTCORE_TARGET})
diff --git a/Tests/QtAutogen/RerunMocOnAddFile/MocOnAddFile/anotherobject.cpp b/Tests/QtAutogen/RerunMocOnAddFile/MocOnAddFile/anotherobject.cpp
new file mode 100644 (file)
index 0000000..45c5af6
--- /dev/null
@@ -0,0 +1,15 @@
+#include <qobject.h>
+
+class AnotherObject : public QObject
+{
+  Q_OBJECT
+public:
+  AnotherObject() {}
+};
+
+AnotherObject* createAnotherObject()
+{
+  return new AnotherObject();
+}
+
+#include "anotherobject.moc"
diff --git a/Tests/QtAutogen/RerunMocOnAddFile/MocOnAddFile/main.cpp.in b/Tests/QtAutogen/RerunMocOnAddFile/MocOnAddFile/main.cpp.in
new file mode 100644 (file)
index 0000000..f62027a
--- /dev/null
@@ -0,0 +1,6 @@
+@main_cpp_includes@
+
+int main(int argc, char *argv[])
+{
+    return 0;
+}
diff --git a/Tests/QtAutogen/RerunMocOnAddFile/MocOnAddFile/myobject.cpp b/Tests/QtAutogen/RerunMocOnAddFile/MocOnAddFile/myobject.cpp
new file mode 100644 (file)
index 0000000..7a15300
--- /dev/null
@@ -0,0 +1,6 @@
+#include "myobject.h"
+
+MyObject::MyObject(QObject* parent)
+  : QObject(parent)
+{
+}
diff --git a/Tests/QtAutogen/RerunMocOnAddFile/MocOnAddFile/myobject.h b/Tests/QtAutogen/RerunMocOnAddFile/MocOnAddFile/myobject.h
new file mode 100644 (file)
index 0000000..e373ee8
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef MYOBJECT_H
+#define MYOBJECT_H
+
+#include <qobject.h>
+
+class MyObject : public QObject
+{
+  Q_OBJECT
+public:
+  MyObject(QObject* parent = 0);
+};
+
+#endif
index a19a9ae..97efa72 100644 (file)
@@ -20,6 +20,7 @@ ADD_AUTOGEN_TEST(RccOffMocLibrary)
 ADD_AUTOGEN_TEST(RccOnly rccOnly)
 ADD_AUTOGEN_TEST(RccSkipSource)
 ADD_AUTOGEN_TEST(RerunMocBasic)
+ADD_AUTOGEN_TEST(RerunMocOnAddFile)
 ADD_AUTOGEN_TEST(RerunRccConfigChange)
 ADD_AUTOGEN_TEST(RerunRccDepends)
 ADD_AUTOGEN_TEST(SameName sameName)
index e9f8bca..0b2ef6a 100644 (file)
@@ -134,6 +134,9 @@ if(CMAKE_GENERATOR MATCHES "Ninja")
   if(CMAKE_Fortran_COMPILER)
     list(APPEND Ninja_ARGS -DTEST_Fortran=1)
   endif()
+  if(CMake_TEST_Qt5 AND Qt5Core_FOUND)
+    list(APPEND Ninja_ARGS -DCMake_TEST_Qt5=1 -DCMAKE_TEST_Qt5Core_Version=${Qt5Core_VERSION})
+  endif()
   add_RunCMake_test(Ninja)
   set(NinjaMultiConfig_ARGS
     -DCYGWIN=${CYGWIN}
index b77bb54..7b479f1 100644 (file)
@@ -1,5 +1,10 @@
 include(RunCMake)
 
+# Isolate test cases from caller's environment.
+set(ENV{CMAKE_PREFIX_PATH} "")
+set(ENV{CMAKE_APPBUNDLE_PATH} "")
+set(ENV{CMAKE_FRAMEWORK_PATH} "")
+
 run_cmake(FindPkgConfig_NO_PKGCONFIG_PATH)
 run_cmake(FindPkgConfig_PKGCONFIG_PATH)
 run_cmake(FindPkgConfig_PKGCONFIG_PATH_NO_CMAKE_PATH)
diff --git a/Tests/RunCMake/Ninja/Qt5AutoMocDeps.cmake b/Tests/RunCMake/Ninja/Qt5AutoMocDeps.cmake
new file mode 100644 (file)
index 0000000..d69a119
--- /dev/null
@@ -0,0 +1,9 @@
+enable_language(CXX)
+
+find_package(Qt5Core REQUIRED)
+
+set(CMAKE_AUTOMOC ON)
+
+add_library(simple_lib SHARED simple_lib.cpp)
+add_executable(app_with_qt app.cpp app_qt.cpp)
+target_link_libraries(app_with_qt PRIVATE simple_lib Qt5::Core)
index 0eada08..c1f6346 100644 (file)
@@ -132,6 +132,7 @@ ${ninja_stderr}
     message(FATAL_ERROR
       "top ninja build failed exited with status ${ninja_result}")
   endif()
+  set(ninja_stdout "${ninja_stdout}" PARENT_SCOPE)
 endfunction(run_ninja)
 
 function (run_LooseObjectDepends)
@@ -316,3 +317,23 @@ function (run_ChangeBuildType)
   run_ninja("${RunCMake_TEST_BINARY_DIR}" -w dupbuild=err)
 endfunction()
 run_ChangeBuildType()
+
+function(run_Qt5AutoMocDeps)
+  if(CMake_TEST_Qt5 AND CMAKE_TEST_Qt5Core_Version VERSION_GREATER_EQUAL 5.15.0)
+    set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/Qt5AutoMocDeps-build)
+    run_cmake(Qt5AutoMocDeps)
+    unset(RunCMake_TEST_OPTIONS)
+    # Build the project.
+    run_ninja("${RunCMake_TEST_BINARY_DIR}")
+    # Touch just the library source file, which shouldn't cause a rerun of AUTOMOC
+    # for app_with_qt target.
+    touch("${RunCMake_SOURCE_DIR}/simple_lib.cpp")
+    # Build and assert that AUTOMOC was not run for app_with_qt.
+    run_ninja("${RunCMake_TEST_BINARY_DIR}")
+    if(ninja_stdout MATCHES "Automatic MOC for target app_with_qt")
+        message(FATAL_ERROR
+               "AUTOMOC should not have executed for 'app_with_qt' target:\nstdout:\n${ninja_stdout}")
+    endif()
+  endif()
+endfunction()
+run_Qt5AutoMocDeps()
diff --git a/Tests/RunCMake/Ninja/app.cpp b/Tests/RunCMake/Ninja/app.cpp
new file mode 100644 (file)
index 0000000..57380e4
--- /dev/null
@@ -0,0 +1,6 @@
+int main(int argc, char* argv[])
+{
+  (void)argc;
+  (void)argv;
+  return 0;
+}
diff --git a/Tests/RunCMake/Ninja/app_qt.cpp b/Tests/RunCMake/Ninja/app_qt.cpp
new file mode 100644 (file)
index 0000000..302c672
--- /dev/null
@@ -0,0 +1,11 @@
+#include <QObject>
+
+class Mango : public QObject
+{
+  Q_OBJECT
+public:
+Q_SIGNALS:
+  void eatFruit();
+};
+
+#include "app_qt.moc"
diff --git a/Tests/RunCMake/Ninja/simple_lib.cpp b/Tests/RunCMake/Ninja/simple_lib.cpp
new file mode 100644 (file)
index 0000000..cf8d689
--- /dev/null
@@ -0,0 +1,6 @@
+#ifdef _WIN32
+__declspec(dllexport)
+#endif
+  void dummy_symbol()
+{
+}
index 50e79df..fa326f0 100644 (file)
 
 namespace cm {
 
-template <typename T, typename O,
-          cm::enable_if_t<
-            std::is_pointer<cm::invoke_result_t<decltype(&O::get), O>>::value,
-            int> = 0>
+template <
+  typename T, typename O,
+  cm::enable_if_t<std::is_pointer<decltype(std::declval<O>().get())>::value,
+                  int> = 0>
 T& static_reference_cast(O& item)
 {
   return *(static_cast<T*>(item.get()));
 }
-template <typename T, typename O,
-          cm::enable_if_t<
-            std::is_pointer<cm::invoke_result_t<decltype(&O::get), O>>::value,
-            int> = 0>
+
+template <
+  typename T, typename O,
+  cm::enable_if_t<std::is_pointer<decltype(std::declval<O>().get())>::value,
+                  int> = 0>
 T& dynamic_reference_cast(O& item)
 {
   auto p = dynamic_cast<T*>(item.get());