From 5ff6ac07e8f2a43f51c673f42dee0d974daeb531 Mon Sep 17 00:00:00 2001 From: halx99 Date: Sat, 23 May 2026 16:23:29 +0800 Subject: [PATCH] Xcode: Fix target-name embedding overriding code-sign attributes Multiple targets embedding the same internal framework dependency with different code-signing attributes should not overwrite each other in the generated `PBXBuildFile`. Extend commit 0282429c5a (Xcode: Fix XCODE_EMBED_FRAMEWORKS when settings differ across targets, 2024-12-02, v4.0.0-rc1~358^2) to cover target names. Remove `FileRefToEmbedBuildFileMap` entirely, forcing CMake to instantiate a brand-new `PBXBuildFile` reference object with a unique ref value for every separate target embedding action, matching Xcode's native multi-target configuration behavior. Fixes: #27850 --- Source/cmGlobalXCodeGenerator.cxx | 12 +++------ Source/cmGlobalXCodeGenerator.h | 1 - .../EmbedFrameworksMultiTargets-check.cmake | 3 +++ .../EmbedFrameworksMultiTargets.cmake | 20 ++++++++++++++ .../XcodeProject-Embed/RunCMakeTest.cmake | 13 ++++++++++ .../XcodeProject-Embed/findAttribute.cmake | 26 +++++++++++-------- 6 files changed, 54 insertions(+), 21 deletions(-) create mode 100644 Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksMultiTargets-check.cmake create mode 100644 Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksMultiTargets.cmake diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index 40e9534e9f..0a58f06ce9 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -930,7 +930,6 @@ void cmGlobalXCodeGenerator::ClearXCodeObjects() this->FileRefs.clear(); this->ExternalLibRefs.clear(); this->FileRefToBuildFileMap.clear(); - this->FileRefToEmbedBuildFileMap.clear(); this->CommandsVisited.clear(); } @@ -4428,14 +4427,9 @@ void cmGlobalXCodeGenerator::AddEmbeddedObjects( " is missing product reference")); continue; } - auto it = this->FileRefToEmbedBuildFileMap.find(fileRefObject); - if (it == this->FileRefToEmbedBuildFileMap.end()) { - buildFile = this->CreateObject(cmXCodeObject::PBXBuildFile); - buildFile->AddAttribute("fileRef", fileRefObject); - this->FileRefToEmbedBuildFileMap[fileRefObject] = buildFile; - } else { - buildFile = it->second; - } + buildFile = this->CreateObject(cmXCodeObject::PBXBuildFile); + buildFile->SetComment(xcTarget->GetComment()); + buildFile->AddAttribute("fileRef", fileRefObject); } else if (cmSystemTools::IsPathToFramework(relFile) || cmSystemTools::IsPathToMacOSSharedLibrary(relFile) || cmSystemTools::FileIsDirectory(filePath)) { diff --git a/Source/cmGlobalXCodeGenerator.h b/Source/cmGlobalXCodeGenerator.h index 114caec4ee..908dc7bf89 100644 --- a/Source/cmGlobalXCodeGenerator.h +++ b/Source/cmGlobalXCodeGenerator.h @@ -381,7 +381,6 @@ private: std::map ExternalLibRefs; std::map XCodeObjectMap; std::map FileRefToBuildFileMap; - std::map FileRefToEmbedBuildFileMap; std::vector Architectures; std::string ObjectDirArchDefault; std::string ObjectDirArch; diff --git a/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksMultiTargets-check.cmake b/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksMultiTargets-check.cmake new file mode 100644 index 0000000000..1d2ee361fb --- /dev/null +++ b/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksMultiTargets-check.cmake @@ -0,0 +1,3 @@ +include(${CMAKE_CURRENT_LIST_DIR}/findAttribute.cmake) + +findAttribute(${test} "CodeSignOnCopy" TRUE 2) diff --git a/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksMultiTargets.cmake b/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksMultiTargets.cmake new file mode 100644 index 0000000000..3ab035a7a7 --- /dev/null +++ b/Tests/RunCMake/XcodeProject-Embed/EmbedFrameworksMultiTargets.cmake @@ -0,0 +1,20 @@ +set(CMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED "NO") + +add_library(MTestLib SHARED TestLib/TestLib.c TestLib/TestLib.h) +set_target_properties(MTestLib PROPERTIES + FRAMEWORK 1 + PUBLIC_HEADER TestLib/TestLib.h + ) + +add_executable(mapp1 MACOSX_BUNDLE main.m) +add_executable(mapp2 MACOSX_BUNDLE main.m) + +set_target_properties(mapp1 PROPERTIES + XCODE_EMBED_FRAMEWORKS MTestLib + XCODE_EMBED_FRAMEWORKS_CODE_SIGN_ON_COPY ON +) + +set_target_properties(mapp2 PROPERTIES + XCODE_EMBED_FRAMEWORKS MTestLib + XCODE_EMBED_FRAMEWORKS_CODE_SIGN_ON_COPY ON +) diff --git a/Tests/RunCMake/XcodeProject-Embed/RunCMakeTest.cmake b/Tests/RunCMake/XcodeProject-Embed/RunCMakeTest.cmake index 26749cd5c9..70b74b87ad 100644 --- a/Tests/RunCMake/XcodeProject-Embed/RunCMakeTest.cmake +++ b/Tests/RunCMake/XcodeProject-Embed/RunCMakeTest.cmake @@ -57,6 +57,19 @@ block() ) endblock() +block() + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/EmbedFrameworksMultiTargets-build) + run_cmake(EmbedFrameworksMultiTargets) + set(RunCMake_TEST_NO_CLEAN 1) + run_cmake_command(EmbedFrameworksMultiTargets-build + ${CMAKE_COMMAND} --build . + --config Debug + --target MTestLib + --target mapp1 + --target mapp2 + ) +endblock() + function(TestAppExtension platform) set(testName EmbedAppExtensions-${platform}) if(NOT platform STREQUAL "macOS") diff --git a/Tests/RunCMake/XcodeProject-Embed/findAttribute.cmake b/Tests/RunCMake/XcodeProject-Embed/findAttribute.cmake index b1963e248b..770532ef5c 100644 --- a/Tests/RunCMake/XcodeProject-Embed/findAttribute.cmake +++ b/Tests/RunCMake/XcodeProject-Embed/findAttribute.cmake @@ -1,19 +1,23 @@ cmake_policy(VERSION 3.1...3.20) function(findAttribute project attr expectPresent) + set(expectCount ${ARGV3}) + + if(NOT expectPresent) + set(expectCount 0) + endif() + execute_process( - COMMAND grep ${attr} ${RunCMake_TEST_BINARY_DIR}/${project}.xcodeproj/project.pbxproj - OUTPUT_VARIABLE output_var - RESULT_VARIABLE result_var + COMMAND grep -c ${attr} ${RunCMake_TEST_BINARY_DIR}/${project}.xcodeproj/project.pbxproj + OUTPUT_VARIABLE actualCount + OUTPUT_STRIP_TRAILING_WHITESPACE ) - if(${expectPresent}) - if(result_var) - set(RunCMake_TEST_FAILED "${attr} attribute is not set" PARENT_SCOPE) - endif() - else() - if(NOT result_var) - set(RunCMake_TEST_FAILED "${attr} attribute is set" PARENT_SCOPE) - endif() + if(NOT actualCount MATCHES "^[0-9]+$") + set(actualCount 0) + endif() + + if(NOT ("${expectCount}" STREQUAL "") AND NOT (actualCount EQUAL expectCount)) + set(RunCMake_TEST_FAILED "${attr} expected ${expectCount} matches, but found ${actualCount}" PARENT_SCOPE) endif() endfunction()