Przeglądaj źródła

Xcode: Use deterministic object ids for script build phases

The Xcode "new build system" only considers a script build phase up to
date if it has run before, even if outputs are newer than inputs.  Use a
deterministic object id for script build phases associated with custom
commands so that they do not need to re-run after CMake re-generates the
project.

Fixes: #21669
Brad King 4 lat temu
rodzic
commit
b8b6573db8

+ 12 - 9
Source/cmGlobalXCodeGenerator.cxx

@@ -1729,13 +1729,13 @@ void cmGlobalXCodeGenerator::CreateCustomCommands(
   if (this->XcodeBuildSystem >= BuildSystem::Twelve) {
     // create prebuild phase
     preBuildPhase =
-      this->CreateRunScriptBuildPhase("CMake PreBuild Rules", prebuild);
+      this->CreateRunScriptBuildPhase("CMake PreBuild Rules", gtgt, prebuild);
     // create prelink phase
     preLinkPhase =
-      this->CreateRunScriptBuildPhase("CMake PreLink Rules", prelink);
+      this->CreateRunScriptBuildPhase("CMake PreLink Rules", gtgt, prelink);
     // create postbuild phase
-    postBuildPhase =
-      this->CreateRunScriptBuildPhase("CMake PostBuild Rules", postbuild);
+    postBuildPhase = this->CreateRunScriptBuildPhase("CMake PostBuild Rules",
+                                                     gtgt, postbuild);
   } else {
     std::vector<cmSourceFile*> classes;
     if (!gtgt->GetConfigCommonSourceFiles(classes)) {
@@ -1863,7 +1863,8 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateRunScriptBuildPhase(
   }
 
   cmXCodeObject* buildPhase =
-    this->CreateObject(cmXCodeObject::PBXShellScriptBuildPhase);
+    this->CreateObject(cmXCodeObject::PBXShellScriptBuildPhase,
+                       cmStrCat(gt->GetName(), ':', sf->GetFullPath()));
   buildPhase->AddAttribute("buildActionMask",
                            this->CreateString("2147483647"));
   cmXCodeObject* buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST);
@@ -1922,7 +1923,8 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateRunScriptBuildPhase(
 }
 
 cmXCodeObject* cmGlobalXCodeGenerator::CreateRunScriptBuildPhase(
-  std::string const& name, std::vector<cmCustomCommand> const& commands)
+  std::string const& name, cmGeneratorTarget const* gt,
+  std::vector<cmCustomCommand> const& commands)
 {
   if (commands.empty()) {
     return nullptr;
@@ -1945,7 +1947,8 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateRunScriptBuildPhase(
   }
 
   cmXCodeObject* buildPhase =
-    this->CreateObject(cmXCodeObject::PBXShellScriptBuildPhase);
+    this->CreateObject(cmXCodeObject::PBXShellScriptBuildPhase,
+                       cmStrCat(gt->GetName(), ':', name));
   buildPhase->AddAttribute("buildActionMask",
                            this->CreateString("2147483647"));
   cmXCodeObject* buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST);
@@ -2913,8 +2916,8 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
 cmXCodeObject* cmGlobalXCodeGenerator::CreateUtilityTarget(
   cmGeneratorTarget* gtgt)
 {
-  cmXCodeObject* shellBuildPhase =
-    this->CreateObject(cmXCodeObject::PBXShellScriptBuildPhase);
+  cmXCodeObject* shellBuildPhase = this->CreateObject(
+    cmXCodeObject::PBXShellScriptBuildPhase, gtgt->GetName());
   shellBuildPhase->AddAttribute("buildActionMask",
                                 this->CreateString("2147483647"));
   cmXCodeObject* buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST);

+ 2 - 1
Source/cmGlobalXCodeGenerator.h

@@ -254,7 +254,8 @@ private:
                                            cmGeneratorTarget const* gt,
                                            cmCustomCommand const& cc);
   cmXCodeObject* CreateRunScriptBuildPhase(
-    std::string const& name, std::vector<cmCustomCommand> const& commands);
+    std::string const& name, cmGeneratorTarget const* gt,
+    std::vector<cmCustomCommand> const& commands);
   std::string ConstructScript(cmCustomCommandGenerator const& ccg);
   void CreateReRunCMakeFile(cmLocalGenerator* root,
                             std::vector<cmLocalGenerator*> const& gens);

+ 4 - 0
Tests/RunCMake/BuildDepends/RepeatCMake-Custom-Script.cmake

@@ -0,0 +1,4 @@
+if(EXISTS "${CMAKE_CURRENT_BINARY_DIR}/exists-for-build2")
+  message(FATAL_ERROR "Custom command incorrectly re-ran after CMake re-ran!")
+endif()
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/out.txt")

+ 5 - 0
Tests/RunCMake/BuildDepends/RepeatCMake-Custom.cmake

@@ -0,0 +1,5 @@
+add_custom_command(OUTPUT out.txt
+  COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_LIST_DIR}/RepeatCMake-Custom-Script.cmake
+  DEPENDS ${CMAKE_CURRENT_LIST_DIR}/RepeatCMake-Custom-Script.cmake
+  )
+add_custom_target(drive ALL DEPENDS out.txt)

+ 17 - 0
Tests/RunCMake/BuildDepends/RunCMakeTest.cmake

@@ -70,6 +70,23 @@ if(RunCMake_GENERATOR MATCHES "Make")
   endif()
 endif()
 
+function(run_RepeatCMake CASE)
+  set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${CASE}-build)
+  if(RunCMake_GENERATOR_IS_MULTI_CONFIG)
+    set(RunCMake_TEST_OPTIONS -DCMAKE_CONFIGURATION_TYPES=Debug)
+  else()
+    set(RunCMake_TEST_OPTIONS -DCMAKE_BUILD_TYPE=Debug)
+  endif()
+  run_cmake(${CASE})
+  set(RunCMake_TEST_NO_CLEAN 1)
+  run_cmake_command(${CASE}-build1 ${CMAKE_COMMAND} --build . --config Debug)
+  run_cmake_command(${CASE}-rerun1 ${CMAKE_COMMAND} .)
+  file(WRITE ${RunCMake_TEST_BINARY_DIR}/exists-for-build2 "")
+  run_cmake_command(${CASE}-build2 ${CMAKE_COMMAND} --build . --config Debug)
+endfunction()
+
+run_RepeatCMake(RepeatCMake-Custom)
+
 function(run_ReGeneration)
   # test re-generation of project even if CMakeLists.txt files disappeared