Xcode: Don't add bare-name framework items to the link build phase

XCODE_LINK_BUILD_PHASE_MODE KNOWN_LOCATION moves non-target library
items with a known path into the "Link Binary With Libraries" build
phase, requiring a valid PBXFileReference. Framework items specified
without a directory component (e.g. $<LINK_LIBRARY:FRAMEWORK,Foundation>)
are stored as ItemIsPath::Yes in cmComputeLinkInformation, but their
value is just a bare name. This caused CreateXCodeFileReferenceFromPath
to CollapseFullPath the bare name against the current working directory,
producing a broken reference to a non-existent path that Xcode shows
as a missing file, and that results in failure to link the project.

We now check that a non-target framework item has a non-empty directory
component before allowing it into the link phase. Without a concrete
path we can't produce a valid PBXFileReference, so we fall back to
OTHER_LDFLAGS where the item is already correctly formatted as
-framework Name.
This commit is contained in:
Tor Arne Vestbø
2026-05-07 14:05:32 +02:00
parent 46410ea189
commit 41f8011d61
5 changed files with 18 additions and 5 deletions

View File

@@ -3907,6 +3907,10 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target)
if (!IsLinkPhaseLibraryExtension(libExt)) {
canUseLinkPhase = false;
}
// We can't add non-absolute PBXFileReferences to the link phase
if (!cmSystemTools::FileIsFullPath(libItem.Value.Value)) {
canUseLinkPhase = false;
}
}
}
if (canUseLinkPhase) {

View File

@@ -14,6 +14,8 @@ int func7();
]])
set(prototypes_objc [[
#import <CoreFoundation/CoreFoundation.h>
#import <CoreGraphics/CoreGraphics.h>
#import <CoreAudio/CoreAudio.h>
]])
set(impl [[
{
@@ -25,6 +27,7 @@ set(impl_objc [[
{
CFStringRef cfStr = CFSTR("This is a string");
printf("%p %p %ld\n", compress, res_close, (long)CFStringGetLength(cfStr));
printf("%p %llu\n", (void *)CGColorSpaceCreateDeviceRGB, (unsigned long long)AudioGetCurrentHostTime());
return func1() + func2() + func3() + func4() + func5() + func6() + func7();
}
]])
@@ -137,6 +140,8 @@ set(linkToThings
imported2
${libresolv}
${CoreFoundation}
"$<LINK_LIBRARY:FRAMEWORK,CoreGraphics>"
"$<LINK_LIBRARY:FRAMEWORK,CoreAudio.framework>"
"${CMAKE_CURRENT_BINARY_DIR}/ExternalFrameworks/build/Debug/sharedFrameworkExt.framework"
"${CMAKE_CURRENT_BINARY_DIR}/ExternalFrameworks/build/Debug/staticFrameworkExt.framework"
)
@@ -157,6 +162,8 @@ set(linkToThings
imported2
${libresolv}
${CoreFoundation}
"$<LINK_LIBRARY:FRAMEWORK,CoreGraphics>"
"$<LINK_LIBRARY:FRAMEWORK,CoreAudio.framework>"
"$<LINK_LIBRARY:WEAK_FRAMEWORK,${CMAKE_CURRENT_BINARY_DIR}/ExternalFrameworks/build/Debug/sharedFrameworkExt.framework>"
"${CMAKE_CURRENT_BINARY_DIR}/ExternalFrameworks/build/Debug/staticFrameworkExt.framework"
)
@@ -177,6 +184,8 @@ set(linkToThings
imported2
${libresolv}
${CoreFoundation}
"$<LINK_LIBRARY:FRAMEWORK,CoreGraphics>"
"$<LINK_LIBRARY:FRAMEWORK,CoreAudio.framework>"
"$<LINK_LIBRARY:REEXPORT_FRAMEWORK,${CMAKE_CURRENT_BINARY_DIR}/ExternalFrameworks/build/Debug/sharedFrameworkExt.framework>"
"${CMAKE_CURRENT_BINARY_DIR}/ExternalFrameworks/build/Debug/staticFrameworkExt.framework"
)

View File

@@ -6,14 +6,14 @@ include(${RunCMake_TEST_BINARY_DIR}/foundLibs.cmake)
foreach(mainTarget IN ITEMS app1 app2 shared1 shared3 module1 sharedFramework1)
checkFlags(OTHER_LDFLAGS ${mainTarget}
"obj2;${libz};${libresolv};CoreFoundation;sharedFrameworkExt;staticFrameworkExt"
"obj2;${libz};${libresolv};CoreFoundation;-framework CoreGraphics;-framework CoreAudio;sharedFrameworkExt;staticFrameworkExt"
"static2;shared2;staticFramework2;sharedFramework2"
)
endforeach()
foreach(mainTarget IN ITEMS app3 shared4)
checkFlags(OTHER_LDFLAGS ${mainTarget}
"obj2;${libz};${libresolv};CoreFoundation;sharedFrameworkExt;staticFrameworkExt;shared2;sharedFramework2"
"obj2;${libz};${libresolv};CoreFoundation;-framework CoreGraphics;-framework CoreAudio;sharedFrameworkExt;staticFrameworkExt;shared2;sharedFramework2"
"static2;staticFramework2"
)
endforeach()

View File

@@ -6,14 +6,14 @@ include(${RunCMake_TEST_BINARY_DIR}/foundLibs.cmake)
foreach(mainTarget IN ITEMS app1 app2 shared1 shared3 module1 sharedFramework1)
checkFlags(OTHER_LDFLAGS ${mainTarget}
"obj2"
"obj2;-framework CoreGraphics;-framework CoreAudio"
"static2;shared2;staticFramework2;sharedFramework2;${libz};${libresolv};CoreFoundation;sharedFrameworkExt;staticFrameworkExt"
)
endforeach()
foreach(mainTarget IN ITEMS app3 shared4)
checkFlags(OTHER_LDFLAGS ${mainTarget}
"obj2;shared2;sharedFramework2;sharedFrameworkExt"
"obj2;shared2;sharedFramework2;sharedFrameworkExt;-framework CoreGraphics;-framework CoreAudio"
"static2;staticFramework2;${libz};${libresolv};CoreFoundation;staticFrameworkExt"
)
endforeach()

View File

@@ -6,7 +6,7 @@ include(${RunCMake_TEST_BINARY_DIR}/foundLibs.cmake)
foreach(mainTarget IN ITEMS app1 app2 app3 shared1 shared3 shared4 module1 sharedFramework1)
checkFlags(OTHER_LDFLAGS ${mainTarget}
"static2;shared2;staticFramework2;sharedFramework2;obj2;${libz};${libresolv};CoreFoundation;sharedFrameworkExt;staticFrameworkExt"
"static2;shared2;staticFramework2;sharedFramework2;obj2;${libz};${libresolv};CoreFoundation;-framework CoreGraphics;-framework CoreAudio;sharedFrameworkExt;staticFrameworkExt"
""
)
endforeach()