1
0
Эх сурвалжийг харах

AutoGen: Fix regression in timestamps on multi-config generators

Since commit fddd0f0443 (Autogen: AUTO*_EXECUTABLE: add support for
per-config values, 2023-06-14) we do not correctly generate outputs
for one configuration after another configuration has been built.
Fix this:

- Revert some config based stuff for `Xcode` due to the `$<CONFIG>`
  genex usage limitation in source files with `Xcode`.
- For multi-config generators use a per-config `timestamp_$<CONFIG>`
  file instead of one `timestamp` file.

Fixes: #25261
Orkun Tokdemir 2 жил өмнө
parent
commit
bac468ddfd

+ 9 - 2
Source/cmQtAutoGenInitializer.cxx

@@ -1175,7 +1175,7 @@ bool cmQtAutoGenInitializer::InitScanFiles()
       // Path checksum
       qrc.QrcPathChecksum = this->PathCheckSum.getPart(qrc.QrcFile);
       // Output file name
-      if (this->CrossConfig) {
+      if (this->MultiConfig && !this->GlobalGen->IsXcode()) {
         qrc.OutputFile = cmStrCat(this->Dir.Build, '/', qrc.QrcPathChecksum,
                                   "_$<CONFIG>", "/qrc_", qrc.QrcName, ".cpp");
       } else {
@@ -1467,7 +1467,7 @@ bool cmQtAutoGenInitializer::InitAutogenTarget()
       std::string outputFile;
       std::string depFile;
       // Create the custom command that outputs the timestamp file.
-      if (this->MultiConfig && this->CrossConfig) {
+      if (this->MultiConfig) {
         // create timestamp file with $<CONFIG> in the name so that
         // every cmake_autogen target has its own timestamp file
         std::string const configView = "$<CONFIG>";
@@ -1577,6 +1577,12 @@ void cmQtAutoGenInitializer::AddCMakeProcessToCommandLines(
     commandLines.push_back(cmMakeCommandLine(
       { cmSystemTools::GetCMakeCommand(), "-E", processName, infoFile,
         "$<CONFIG>", "$<COMMAND_CONFIG:$<CONFIG>>" }));
+  } else if (this->MultiConfig && this->GlobalGen->IsXcode()) {
+    for (std::string const& config : this->ConfigsList) {
+      commandLines.push_back(
+        cmMakeCommandLine({ cmSystemTools::GetCMakeCommand(), "-E",
+                            processName, infoFile, config }));
+    }
   } else {
     std::string autoInfoFileConfig;
     if (this->MultiConfig) {
@@ -1934,6 +1940,7 @@ bool cmQtAutoGenInitializer::SetupWriteRccInfo()
     info.SetBool("MULTI_CONFIG", this->MultiConfig);
     info.SetBool("CROSS_CONFIG", this->CrossConfig);
     info.SetUInt("VERBOSITY", this->Verbosity);
+    info.Set("GENERATOR", this->GlobalGen->GetName());
 
     // Files
     info.Set("LOCK_FILE", qrc.LockFile);

+ 8 - 1
Source/cmQtAutoRcc.cxx

@@ -35,6 +35,11 @@ public:
 private:
   // -- Utility
   bool IsMultiConfig() const { return this->MultiConfig_; }
+  std::string const& GetGenerator() const { return this->Generator_; }
+  bool IsXcode() const
+  {
+    return this->GetGenerator().find("Xcode") != std::string::npos;
+  }
   std::string MultiConfigOutput() const;
 
   // -- Abstract processing interface
@@ -54,6 +59,7 @@ private:
   // -- Config settings
   bool MultiConfig_ = false;
   bool CrossConfig_ = false;
+  std::string Generator_;
   // -- Directories
   std::string AutogenBuildDir_;
   std::string IncludeDir_;
@@ -93,6 +99,7 @@ bool cmQtAutoRccT::InitFromInfo(InfoT const& info)
 {
   // -- Required settings
   if (!info.GetBool("MULTI_CONFIG", this->MultiConfig_, true) ||
+      !info.GetString("GENERATOR", this->Generator_, true) ||
       !info.GetBool("CROSS_CONFIG", this->CrossConfig_, true) ||
       !info.GetString("BUILD_DIR", this->AutogenBuildDir_, true) ||
       !info.GetStringConfig("INCLUDE_DIR", this->IncludeDir_, true) ||
@@ -122,7 +129,7 @@ bool cmQtAutoRccT::InitFromInfo(InfoT const& info)
   // -- Derive information
   this->QrcFileName_ = cmSystemTools::GetFilenameName(this->QrcFile_);
   this->QrcFileDir_ = cmSystemTools::GetFilenamePath(this->QrcFile_);
-  if (this->CrossConfig_) {
+  if (IsMultiConfig() && !this->IsXcode()) {
     this->RccFilePublic_ =
       cmStrCat(this->AutogenBuildDir_, '/', this->RccPathChecksum_, "_",
                this->InfoConfig(), '/', this->RccFileName_);

+ 149 - 42
Tests/RunCMake/Autogen/RunCMakeTest.cmake

@@ -126,50 +126,69 @@ if (DEFINED with_qt_version)
   if(RunCMake_GENERATOR MATCHES "Make|Ninja")
     block()
       if(QtCore_VERSION VERSION_GREATER_EQUAL 5.15.0)
-        set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/QtAutoMocDeps-build)
-        run_cmake(QtAutoMocDeps)
-        set(RunCMake_TEST_NO_CLEAN 1)
-        # Build the project.
-        run_cmake_command(QtAutoMocDeps-build ${CMAKE_COMMAND} --build . --verbose)
-        # Touch just the library source file, which shouldn't cause a rerun of AUTOMOC
-        # for app_with_qt target.
-        file(TOUCH "${RunCMake_SOURCE_DIR}/simple_lib.cpp")
-        set(RunCMake_TEST_NOT_EXPECT_stdout "Automatic MOC for target app_with_qt|\
+        if (RunCMake_GENERATOR MATCHES "Ninja Multi-Config")
+          set(config_list Debug Release RelWithDebInfo)
+        else()
+          set(config_list single-config)
+        endif()
+        foreach(config IN ITEMS ${config_list})
+          block()
+            if (config STREQUAL "single-config")
+              set(config_suffix "")
+            else()
+              set(config_suffix "_${config}")
+            endif()
+            set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/QtAutoMocDeps${config_suffix}-build)
+            run_cmake(QtAutoMocDeps)
+            set(RunCMake_TEST_NO_CLEAN 1)
+            # Build the project.
+            if (config STREQUAL "single-config")
+              set(config_param "")
+            else()
+              set(config_param "--config ${config}")
+            endif()
+            run_cmake_command(QtAutoMocDeps-build ${CMAKE_COMMAND} --build . --verbose ${config_param})
+            # Touch just the library source file, which shouldn't cause a rerun of AUTOMOC
+            # for app_with_qt target.
+            file(TOUCH "${RunCMake_SOURCE_DIR}/simple_lib.cpp")
+            set(RunCMake_TEST_NOT_EXPECT_stdout "Automatic MOC for target app_with_qt|\
 Automatic MOC for target sub_exe_1|\
 Automatic MOC for target sub_exe_2")
-        set(RunCMake_TEST_VARIANT_DESCRIPTION "-Don't execute AUTOMOC for 'app_with_qt', 'sub_exe_1' and 'sub_exe_2'")
-        # Build and assert that AUTOMOC was not run for app_with_qt, sub_exe_1 and sub_exe_2.
-        run_cmake_command(QtAutoMocDeps-build ${CMAKE_COMMAND} --build . --verbose)
-        unset(RunCMake_TEST_VARIANT_DESCRIPTION)
-        unset(RunCMake_TEST_NOT_EXPECT_stdout)
-
-        macro(check_file_exists file)
-          if (EXISTS "${file}")
-            set(check_result "PASSED")
-            set(message_type "STATUS")
-          else()
-            set(check_result "FAILED")
-            set(message_type "FATAL_ERROR")
-          endif()
-
-          message(${message_type} "QtAutoMocDeps-build-\"${file}\" was generated - ${check_result}")
-        endmacro()
-
-        check_file_exists("${RunCMake_TEST_BINARY_DIR}/app_with_qt_autogen/deps")
-        check_file_exists("${RunCMake_TEST_BINARY_DIR}/QtSubDir1/sub_exe_1_autogen/deps")
-        check_file_exists("${RunCMake_TEST_BINARY_DIR}/QtSubDir2/sub_exe_2_autogen/deps")
-
-        check_file_exists("${RunCMake_TEST_BINARY_DIR}/app_with_qt_autogen/timestamp")
-        check_file_exists("${RunCMake_TEST_BINARY_DIR}/QtSubDir1/sub_exe_1_autogen/timestamp")
-        check_file_exists("${RunCMake_TEST_BINARY_DIR}/QtSubDir2/sub_exe_2_autogen/timestamp")
-
-        # Touch a header file to make sure an automoc dependency cycle is not introduced.
-        file(TOUCH "${RunCMake_SOURCE_DIR}/MyWindow.h")
-        set(RunCMake_TEST_VARIANT_DESCRIPTION "-First build after touch to detect dependency cycle")
-        run_cmake_command(QtAutoMocDeps-build ${CMAKE_COMMAND} --build . --verbose)
-        # Need to run a second time to hit the dependency cycle.
-        set(RunCMake_TEST_VARIANT_DESCRIPTION "-Don't hit dependency cycle")
-        run_cmake_command(QtAutoMocDeps-build ${CMAKE_COMMAND} --build . --verbose)
+            set(RunCMake_TEST_VARIANT_DESCRIPTION "-Don't execute AUTOMOC for 'app_with_qt', 'sub_exe_1' and 'sub_exe_2'")
+            # Build and assert that AUTOMOC was not run for app_with_qt, sub_exe_1 and sub_exe_2.
+            run_cmake_command(QtAutoMocDeps-build ${CMAKE_COMMAND} --build . --verbose ${config_param})
+            unset(RunCMake_TEST_VARIANT_DESCRIPTION)
+            unset(RunCMake_TEST_NOT_EXPECT_stdout)
+
+            macro(check_file_exists file)
+              if (EXISTS "${file}")
+                set(check_result "PASSED")
+                set(message_type "STATUS")
+              else()
+                set(check_result "FAILED")
+                set(message_type "FATAL_ERROR")
+              endif()
+
+              message(${message_type} "QtAutoMocDeps-build-\"${file}\" was generated - ${check_result}")
+            endmacro()
+
+            check_file_exists("${RunCMake_TEST_BINARY_DIR}/app_with_qt_autogen/deps${config_suffix}")
+            check_file_exists("${RunCMake_TEST_BINARY_DIR}/QtSubDir1/sub_exe_1_autogen/deps${config_suffix}")
+            check_file_exists("${RunCMake_TEST_BINARY_DIR}/QtSubDir2/sub_exe_2_autogen/deps${config_suffix}")
+
+            check_file_exists("${RunCMake_TEST_BINARY_DIR}/app_with_qt_autogen/timestamp${config_suffix}")
+            check_file_exists("${RunCMake_TEST_BINARY_DIR}/QtSubDir1/sub_exe_1_autogen/timestamp${config_suffix}")
+            check_file_exists("${RunCMake_TEST_BINARY_DIR}/QtSubDir2/sub_exe_2_autogen/timestamp${config_suffix}")
+
+            # Touch a header file to make sure an automoc dependency cycle is not introduced.
+            file(TOUCH "${RunCMake_SOURCE_DIR}/MyWindow.h")
+            set(RunCMake_TEST_VARIANT_DESCRIPTION "-First build after touch to detect dependency cycle")
+            run_cmake_command(QtAutoMocDeps-build ${CMAKE_COMMAND} --build . --verbose)
+            # Need to run a second time to hit the dependency cycle.
+            set(RunCMake_TEST_VARIANT_DESCRIPTION "-Don't hit dependency cycle")
+            run_cmake_command(QtAutoMocDeps-build ${CMAKE_COMMAND} --build . --verbose)
+          endblock()
+        endforeach()
       endif()
     endblock()
   endif()
@@ -262,6 +281,27 @@ ${make_program_stderr}
   if (QtCore_VERSION VERSION_GREATER_EQUAL 5.15.0)
     foreach(exe IN ITEMS Moc Uic Rcc)
       if(RunCMake_GENERATOR MATCHES "Ninja Multi-Config")
+        block()
+          set(RunCMake_TEST_VARIANT_DESCRIPTION "-CMake-configure")
+          set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/Auto${exe}ExecutableConfig-multi-config-build)
+          run_cmake_with_options(Auto${exe}ExecutableConfig ${RunCMake_TEST_OPTIONS} -DCMAKE_AUTOGEN_VERBOSE=ON)
+          unset(RunCMake_TEST_VARIANT_DESCRIPTION)
+          set(RunCMake_TEST_NO_CLEAN 1)
+          foreach(config IN ITEMS Debug Release RelWithDebInfo)
+            block()
+              set(RunCMake_TEST_EXPECT_stdout ".*running_exe_${config}*")
+              set(RunCMake_TEST_VARIANT_DESCRIPTION "-${config}-expect_running_exe_${config}")
+              run_cmake_command(Auto${exe}ExecutableConfig-multi-config-build ${CMAKE_COMMAND} --build . --config ${config})
+            endblock()
+          endforeach()
+          set(RunCMake_TEST_EXPECT_stdout "ninja: no work to do")
+          foreach(config IN ITEMS Debug Release RelWithDebInfo)
+            block()
+            set(RunCMake_TEST_VARIANT_DESCRIPTION "-${config}-expect_no_work_to_do")
+              run_cmake_command(Auto${exe}ExecutableConfig-multi-config-build ${CMAKE_COMMAND} --build . --config ${config})
+            endblock()
+          endforeach()
+        endblock()
         block()
           set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/Auto${exe}ExecutableConfig-build)
           run_cmake_with_options(Auto${exe}ExecutableConfig ${RunCMake_TEST_OPTIONS} -DCMAKE_AUTOGEN_VERBOSE=ON)
@@ -347,4 +387,71 @@ ${make_program_stderr}
       endif()
     endforeach()
   endif()
+
+  # Visual Studio specific dependency tests
+  if (RunCMake_GENERATOR MATCHES "Visual Studio")
+      foreach(exe IN ITEMS Moc Uic Rcc)
+          block()
+            set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${exe}Example-build)
+            set(RunCMake_TEST_VARIANT_DESCRIPTION "-CMake-configure")
+            run_cmake_with_options(${exe}Example ${RunCMake_TEST_OPTIONS} -DCMAKE_AUTOGEN_VERBOSE=ON)
+            unset(RunCMake_TEST_VARIANT_DESCRIPTION)
+            set(RunCMake_TEST_NO_CLEAN 1)
+            foreach(config IN ITEMS Debug Release RelWithDebInfo)
+              block()
+                set(RunCMake_TEST_VARIANT_DESCRIPTION "-${config}-first-build")
+                run_cmake_command(${exe}Example-build ${CMAKE_COMMAND} --build . --config ${config})
+              endblock()
+            endforeach()
+            foreach(config IN ITEMS Debug Release RelWithDebInfo)
+              block()
+                if (exe STREQUAL "Moc" OR exe STREQUAL "Uic")
+                  set(RunCMake_TEST_NOT_EXPECT_stdout "Auto${exe}")
+                  set(not_expect_descripton "Auto${exe}")
+                else ()
+                  set(RunCMake_TEST_NOT_EXPECT_stdout "qrc_data.cpp|Auto${exe}")
+                  set(not_expect_descripton "qrc_data.cpp_and_Auto${exe}")
+                endif()
+                set(RunCMake_TEST_VARIANT_DESCRIPTION "-second-build-${config}_expect_no_${not_expect_descripton}")
+                run_cmake_command(${exe}Example-build ${CMAKE_COMMAND} --build . --config ${config})
+              endblock()
+            endforeach()
+          endblock()
+      endforeach()
+  endif()
+
+  if (RunCMake_GENERATOR MATCHES "Xcode")
+    foreach(exe IN ITEMS Moc Uic Rcc)
+      block()
+        set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${exe}Example-build)
+        set(RunCMake_TEST_VARIANT_DESCRIPTION "-CMake-configure")
+        set(RunCMake_TEST_EXPECT_stderr ".*")
+        run_cmake_with_options(${exe}Example ${RunCMake_TEST_OPTIONS} -DCMAKE_AUTOGEN_VERBOSE=ON)
+        set(RunCMake_TEST_NO_CLEAN 1)
+        set(RunCMake_MAKE_PROGRAM ${CMAKE_COMMAND})
+        run_make_program(${RunCMake_TEST_BINARY_DIR}  --build . --config Debug)
+        if (exe STREQUAL "Moc")
+          set(expected_count 16)
+        elseif (exe STREQUAL "Uic")
+          set(expected_count 4)
+        else()
+          set(expected_count 12)
+        endif()
+        expect_n_times("${make_program_stdout}" "Auto${exe}:" ${expected_count} "${exe}Example-build-Auto${exe}")
+        expect_n_times("${make_program_stdout}" "Auto${exe}:" ${expected_count} "${exe}Example-build-Auto${exe}")
+
+        if (exe STREQUAL "Moc" OR exe STREQUAL "Uic")
+          expect_n_times("${make_program_stdout}" "AutoGen:" 20 "${exe}Example-build-AutoGen:")
+        endif()
+
+        foreach(config IN ITEMS Debug Release RelWithDebInfo)
+          block()
+            run_make_program(${RunCMake_TEST_BINARY_DIR} --build . --config ${config})
+            not_expect("${make_program_stdout}" "Auto${exe}" "${exe}Example-${config}_Auto${exe}")
+            not_expect("${make_program_stdout}" "AutoGen:" "${exe}Example-${config}_AutoGen")
+          endblock()
+        endforeach()
+      endblock()
+    endforeach()
+  endif()
 endif ()