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

Merge topic 'xcode-object-ids' into release-3.19

b8b6573db8 Xcode: Use deterministic object ids for script build phases
2892228dc9 cmGlobalXCodeGenerator: Add infrastructure for deterministic object ids
d250b67722 cmGlobalXCodeGenerator: Adopt pbxproj object id generation

Acked-by: Kitware Robot <[email protected]>
Merge-request: !5671
Brad King 4 жил өмнө
parent
commit
48f5b36aee

+ 45 - 12
Source/cmGlobalXCodeGenerator.cxx

@@ -18,6 +18,7 @@
 #include "cmsys/RegularExpression.hxx"
 
 #include "cmComputeLinkInformation.h"
+#include "cmCryptoHash.h"
 #include "cmCustomCommand.h"
 #include "cmCustomCommandGenerator.h"
 #include "cmCustomCommandLines.h"
@@ -797,9 +798,10 @@ void cmGlobalXCodeGenerator::addObject(std::unique_ptr<cmXCodeObject> obj)
 }
 
 cmXCodeObject* cmGlobalXCodeGenerator::CreateObject(
-  cmXCodeObject::PBXType ptype)
+  cmXCodeObject::PBXType ptype, cm::string_view key)
 {
-  auto obj = cm::make_unique<cmXCode21Object>(ptype, cmXCodeObject::OBJECT);
+  auto obj = cm::make_unique<cmXCode21Object>(ptype, cmXCodeObject::OBJECT,
+                                              this->GetObjectId(ptype, key));
   auto ptr = obj.get();
   this->addObject(std::move(obj));
   return ptr;
@@ -807,7 +809,9 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateObject(
 
 cmXCodeObject* cmGlobalXCodeGenerator::CreateObject(cmXCodeObject::Type type)
 {
-  auto obj = cm::make_unique<cmXCodeObject>(cmXCodeObject::None, type);
+  auto obj = cm::make_unique<cmXCodeObject>(
+    cmXCodeObject::None, type,
+    "Temporary cmake object, should not be referred to in Xcode file");
   auto ptr = obj.get();
   this->addObject(std::move(obj));
   return ptr;
@@ -1725,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)) {
@@ -1859,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);
@@ -1918,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;
@@ -1941,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);
@@ -2909,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);
@@ -3138,6 +3145,32 @@ cmXCodeObject* cmGlobalXCodeGenerator::FindXCodeTarget(
   return i->second;
 }
 
+std::string cmGlobalXCodeGenerator::GetObjectId(cmXCodeObject::PBXType ptype,
+                                                cm::string_view key)
+{
+  std::string objectId;
+  if (!key.empty()) {
+    cmCryptoHash hash(cmCryptoHash::AlgoSHA256);
+    hash.Initialize();
+    hash.Append(&ptype, sizeof(ptype));
+    hash.Append(key);
+    objectId = cmSystemTools::UpperCase(hash.FinalizeHex().substr(0, 24));
+  } else {
+    char cUuid[40] = { 0 };
+    CFUUIDRef uuid = CFUUIDCreate(kCFAllocatorDefault);
+    CFStringRef s = CFUUIDCreateString(kCFAllocatorDefault, uuid);
+    CFStringGetCString(s, cUuid, sizeof(cUuid), kCFStringEncodingUTF8);
+    objectId = cUuid;
+    CFRelease(s);
+    CFRelease(uuid);
+    cmSystemTools::ReplaceString(objectId, "-", "");
+    if (objectId.size() > 24) {
+      objectId = objectId.substr(0, 24);
+    }
+  }
+  return objectId;
+}
+
 std::string cmGlobalXCodeGenerator::GetOrCreateId(const std::string& name,
                                                   const std::string& id)
 {

+ 7 - 2
Source/cmGlobalXCodeGenerator.h

@@ -11,6 +11,8 @@
 #include <string>
 #include <vector>
 
+#include <cm/string_view>
+
 #include "cmGlobalGenerator.h"
 #include "cmXCodeObject.h"
 
@@ -162,11 +164,13 @@ private:
                                  const std::string& configName);
 
   cmXCodeObject* FindXCodeTarget(const cmGeneratorTarget*);
+  std::string GetObjectId(cmXCodeObject::PBXType ptype, cm::string_view key);
   std::string GetOrCreateId(const std::string& name, const std::string& id);
 
   // create cmXCodeObject from these functions so that memory can be managed
   // correctly.  All objects created are stored in this->XCodeObjects.
-  cmXCodeObject* CreateObject(cmXCodeObject::PBXType ptype);
+  cmXCodeObject* CreateObject(cmXCodeObject::PBXType ptype,
+                              cm::string_view key = {});
   cmXCodeObject* CreateObject(cmXCodeObject::Type type);
   cmXCodeObject* CreateString(const std::string& s);
   cmXCodeObject* CreateObjectReference(cmXCodeObject*);
@@ -250,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);

+ 3 - 2
Source/cmXCode21Object.cxx

@@ -4,11 +4,12 @@
 
 #include <ostream>
 #include <string>
+#include <utility>
 
 #include "cmSystemTools.h"
 
-cmXCode21Object::cmXCode21Object(PBXType ptype, Type type)
-  : cmXCodeObject(ptype, type)
+cmXCode21Object::cmXCode21Object(PBXType ptype, Type type, std::string id)
+  : cmXCodeObject(ptype, type, std::move(id))
 {
   this->Version = 21;
 }

+ 1 - 1
Source/cmXCode21Object.h

@@ -13,7 +13,7 @@
 class cmXCode21Object : public cmXCodeObject
 {
 public:
-  cmXCode21Object(PBXType ptype, Type type);
+  cmXCode21Object(PBXType ptype, Type type, std::string id);
   void PrintComment(std::ostream&) override;
   static void PrintList(std::vector<std::unique_ptr<cmXCodeObject>> const&,
                         std::ostream& out, PBXType t);

+ 2 - 22
Source/cmXCodeObject.cxx

@@ -40,7 +40,7 @@ cmXCodeObject::~cmXCodeObject()
   this->Version = 15;
 }
 
-cmXCodeObject::cmXCodeObject(PBXType ptype, Type type)
+cmXCodeObject::cmXCodeObject(PBXType ptype, Type type, std::string id)
 {
   this->Version = 15;
   this->Target = nullptr;
@@ -48,27 +48,7 @@ cmXCodeObject::cmXCodeObject(PBXType ptype, Type type)
 
   this->IsA = ptype;
 
-  if (type == OBJECT) {
-    // Set the Id of an Xcode object to a unique string for each instance.
-    // However the Xcode user file references certain Ids: for those cases,
-    // override the generated Id using SetId().
-    //
-    char cUuid[40] = { 0 };
-    CFUUIDRef uuid = CFUUIDCreate(kCFAllocatorDefault);
-    CFStringRef s = CFUUIDCreateString(kCFAllocatorDefault, uuid);
-    CFStringGetCString(s, cUuid, sizeof(cUuid), kCFStringEncodingUTF8);
-    this->Id = cUuid;
-    CFRelease(s);
-    CFRelease(uuid);
-  } else {
-    this->Id =
-      "Temporary cmake object, should not be referred to in Xcode file";
-  }
-
-  cmSystemTools::ReplaceString(this->Id, "-", "");
-  if (this->Id.size() > 24) {
-    this->Id = this->Id.substr(0, 24);
-  }
+  this->Id = std::move(id);
 
   this->TypeValue = type;
   if (this->TypeValue == OBJECT) {

+ 1 - 1
Source/cmXCodeObject.h

@@ -57,7 +57,7 @@ public:
   };
   static const char* PBXTypeNames[];
   virtual ~cmXCodeObject();
-  cmXCodeObject(PBXType ptype, Type type);
+  cmXCodeObject(PBXType ptype, Type type, std::string id);
   Type GetType() const { return this->TypeValue; }
   PBXType GetIsA() const { return this->IsA; }
 

+ 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