Merge topic 'xcode-object-ids'

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 <kwrobot@kitware.com>
Merge-request: !5671
This commit is contained in:
Brad King 2021-01-08 14:07:10 +00:00 committed by Kitware Robot
commit 38335f275f
9 changed files with 85 additions and 40 deletions

View File

@ -18,6 +18,7 @@
#include "cmsys/RegularExpression.hxx"
#include "cmComputeLinkInformation.h"
#include "cmCryptoHash.h"
#include "cmCustomCommand.h"
#include "cmCustomCommandGenerator.h"
#include "cmCustomCommandLines.h"
@ -798,9 +799,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;
@ -808,7 +810,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;
@ -1739,13 +1743,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->GetConfigCommonSourceFilesForXcode(classes)) {
@ -1877,7 +1881,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);
@ -1936,7 +1941,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;
@ -1959,7 +1965,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);
@ -2927,8 +2934,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);
@ -3156,6 +3163,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)
{

View File

@ -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*);
@ -256,7 +260,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);

View File

@ -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;
}

View File

@ -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);

View File

@ -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) {

View File

@ -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; }

View File

@ -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")

View File

@ -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)

View File

@ -79,6 +79,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