Xcode: Fix XCODE_EMBED_FRAMEWORKS when settings differ across targets

In commit 5651901c54 (Xcode: add support for embedding frameworks,
2020-10-24, v3.20.0-rc1~402^2) we incorrectly reused `PBXBuildFile`
instances when the same framework is embedded in multiple targets,
causing target-specific settings to conflict.

Fixes: #26438
This commit is contained in:
Aleksei Sapitskii
2024-12-02 10:38:05 +02:00
committed by Brad King
parent 8a2cdc6ada
commit 0282429c5a
8 changed files with 71 additions and 20 deletions

View File

@@ -810,7 +810,6 @@ void cmGlobalXCodeGenerator::ClearXCodeObjects()
this->TargetGroup.clear();
this->FileRefs.clear();
this->ExternalLibRefs.clear();
this->EmbeddedLibRefs.clear();
this->FileRefToBuildFileMap.clear();
this->FileRefToEmbedBuildFileMap.clear();
this->CommandsVisited.clear();
@@ -4245,24 +4244,18 @@ void cmGlobalXCodeGenerator::AddEmbeddedObjects(
cmSystemTools::IsPathToMacOSSharedLibrary(relFile) ||
cmSystemTools::FileIsDirectory(filePath)) {
// This is a regular string path - create file reference
auto it = this->EmbeddedLibRefs.find(relFile);
if (it == this->EmbeddedLibRefs.end()) {
cmXCodeObject* fileRef =
this->CreateXCodeFileReferenceFromPath(relFile, gt, "", nullptr);
if (fileRef) {
buildFile = this->CreateObject(cmXCodeObject::PBXBuildFile);
buildFile->SetComment(fileRef->GetComment());
buildFile->AddAttribute("fileRef",
this->CreateObjectReference(fileRef));
}
if (!buildFile) {
cmSystemTools::Error(
cmStrCat("Can't create build file for ", relFile));
continue;
}
this->EmbeddedLibRefs.emplace(filePath, buildFile);
} else {
buildFile = it->second;
cmXCodeObject* fileRef =
this->CreateXCodeFileReferenceFromPath(relFile, gt, "", nullptr);
if (fileRef) {
buildFile = this->CreateObject(cmXCodeObject::PBXBuildFile);
buildFile->SetComment(fileRef->GetComment());
buildFile->AddAttribute("fileRef",
this->CreateObjectReference(fileRef));
}
if (!buildFile) {
cmSystemTools::Error(
cmStrCat("Can't create build file for ", relFile));
continue;
}
}
if (!buildFile) {

View File

@@ -372,7 +372,6 @@ private:
std::map<std::string, cmXCodeObject*> TargetGroup;
std::map<std::string, cmXCodeObject*> FileRefs;
std::map<std::string, cmXCodeObject*> ExternalLibRefs;
std::map<std::string, cmXCodeObject*> EmbeddedLibRefs;
std::map<cmGeneratorTarget const*, cmXCodeObject*> XCodeObjectMap;
std::map<cmXCodeObject*, cmXCodeObject*> FileRefToBuildFileMap;
std::map<cmXCodeObject*, cmXCodeObject*> FileRefToEmbedBuildFileMap;

View File

@@ -0,0 +1,9 @@
set(in_app1 "${RunCMake_TEST_BINARY_DIR}/Debug/app1.app/Contents/Frameworks/TestLib.framework/Headers")
if(NOT EXISTS "${in_app1}")
string(APPEND RunCMake_TEST_FAILED "TestLib was embedded without Headers in:\n ${in_app1}\n")
endif()
set(in_app2 "${RunCMake_TEST_BINARY_DIR}/Debug/app2.app/Contents/Frameworks/TestLib.framework/Headers")
if(EXISTS "${in_app2}")
string(APPEND RunCMake_TEST_FAILED "TestLib was embedded with Headers in:\n ${in_app2}\n")
endif()

View File

@@ -0,0 +1,27 @@
set(CMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED "NO")
try_compile(TESTLIB_FRAMEWORK_COMPILED
PROJECT TestLib
SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/TestLib
BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/TestLib
)
if(NOT TESTLIB_FRAMEWORK_COMPILED)
message(FATAL_ERROR "TestLib.framework did not compile")
endif()
set(TestLib_framework "${CMAKE_CURRENT_BINARY_DIR}/TestLib/Debug/TestLib.framework")
if(NOT EXISTS "${TestLib_framework}/Headers/TestLib.h")
message(FATAL_ERROR "TestLib.framework did not build with header")
endif()
add_executable(app1 MACOSX_BUNDLE main.m)
add_executable(app2 MACOSX_BUNDLE main.m)
set_target_properties(app1 PROPERTIES
XCODE_EMBED_FRAMEWORKS "${CMAKE_CURRENT_BINARY_DIR}/TestLib/Debug/TestLib.framework"
XCODE_EMBED_FRAMEWORKS_REMOVE_HEADERS_ON_COPY OFF
)
set_target_properties(app2 PROPERTIES
XCODE_EMBED_FRAMEWORKS "${CMAKE_CURRENT_BINARY_DIR}/TestLib/Debug/TestLib.framework"
XCODE_EMBED_FRAMEWORKS_REMOVE_HEADERS_ON_COPY ON
)

View File

@@ -45,6 +45,18 @@ foreach(dependency ${externalFramework} ${externalDylib})
endforeach()
unset(RunCMake_TEST_OPTIONS)
block()
set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/EmbedFrameworksFlagsOffAndOn-build)
run_cmake(EmbedFrameworksFlagsOffAndOn)
set(RunCMake_TEST_NO_CLEAN 1)
run_cmake_command(EmbedFrameworksFlagsOffAndOn-build
${CMAKE_COMMAND} --build .
--config Debug
--target app1
--target app2
)
endblock()
function(TestAppExtension platform)
set(testName EmbedAppExtensions-${platform})
if(NOT platform STREQUAL "macOS")

View File

@@ -0,0 +1,7 @@
cmake_minimum_required(VERSION 3.30)
project(TestLib C)
add_library(TestLib SHARED TestLib.c TestLib.h)
set_target_properties(TestLib PROPERTIES
FRAMEWORK 1
PUBLIC_HEADER TestLib.h
)

View File

@@ -0,0 +1,3 @@
void TestLib(void)
{
}

View File

@@ -0,0 +1 @@
extern void TestLib(void);