[lld] handle re-exports for full framework paths (#137989)

Framework load paths can be either the top level framework name, or
subpaths of the framework bundle pointing to specific framework binary
versions. Extend the framework lookup logic to handle the latter case.
This commit is contained in:
Richard Howell
2025-05-02 09:15:53 -07:00
committed by GitHub
parent 39e6e888a8
commit 58addfbbcc
2 changed files with 129 additions and 5 deletions

View File

@@ -1580,14 +1580,19 @@ static DylibFile *findDylib(StringRef path, DylibFile *umbrella,
// Search order:
// 1. Install name basename in -F / -L directories.
{
// Framework names can be in multiple formats:
// - Foo.framework/Foo
// - Foo.framework/Versions/A/Foo
StringRef stem = path::stem(path);
SmallString<128> frameworkName;
path::append(frameworkName, path::Style::posix, stem + ".framework", stem);
bool isFramework = path.ends_with(frameworkName);
if (isFramework) {
SmallString<128> frameworkName("/");
frameworkName += stem;
frameworkName += ".framework/";
size_t i = path.rfind(frameworkName);
if (i != StringRef::npos) {
StringRef frameworkPath = path.substr(i + 1);
for (StringRef dir : config->frameworkSearchPaths) {
SmallString<128> candidate = dir;
path::append(candidate, frameworkName);
path::append(candidate, frameworkPath);
if (std::optional<StringRef> dylibPath =
resolveDylibPath(candidate.str()))
return loadDylib(*dylibPath, umbrella);

View File

@@ -0,0 +1,119 @@
# REQUIRES: aarch64, shell
# RUN: rm -rf %t; split-file %s %t
# RUN: ln -s Versions/A/Developer %t/Developer/Library/Frameworks/Developer.framework/
# RUN: ln -s Versions/A/DeveloperCore %t/Developer/Library/PrivateFrameworks/DeveloperCore.framework/
# RUN: llvm-mc -filetype obj -triple arm64-apple-macos11.0 %t/test.s -o %t/test.o
# RUN: %lld -arch arm64 -platform_version macos 11.0 11.0 -o %t/test -framework Developer -F %t/Developer/Library/Frameworks -L %t/Developer/usr/lib %t/test.o
# RUN: llvm-objdump --bind --no-show-raw-insn -d %t/test | FileCheck %s
# CHECK: Bind table:
# CHECK-DAG: __DATA __data {{.*}} pointer 0 Developer _funcPublic
# CHECK-DAG: __DATA __data {{.*}} pointer 0 Developer _funcCore
# CHECK-DAG: __DATA __data {{.*}} pointer 0 libDeveloperSupport _funcSupport
#--- Developer/Library/Frameworks/Developer.framework/Versions/A/Developer
{
"tapi_tbd_version": 5,
"main_library": {
"target_info": [
{
"target": "arm64-macos"
}
],
"install_names": [
{
"name": "@rpath/Developer.framework/Versions/A/Developer"
}
],
"rpaths": [
{
"paths": [
"@loader_path/../../../../PrivateFrameworks/"
]
}
],
"reexported_libraries": [
{
"names": [
"@rpath/DeveloperCore.framework/Versions/A/DeveloperCore"
]
}
],
"exported_symbols": [
{
"text": {
"global": ["_funcPublic"]
}
}
]
}
}
#--- Developer/Library/PrivateFrameworks/DeveloperCore.framework/Versions/A/DeveloperCore
{
"tapi_tbd_version": 5,
"main_library": {
"target_info": [
{
"target": "arm64-macos"
}
],
"install_names": [
{
"name": "@rpath/DeveloperCore.framework/Versions/A/DeveloperCore"
}
],
"allowable_clients": [
{
"clients": ["Developer"]
}
],
"exported_symbols": [
{
"text": {
"global": ["_funcCore"]
}
}
]
}
}
#--- Developer/usr/lib/libDeveloperSupport.tbd
{
"tapi_tbd_version": 5,
"main_library": {
"target_info": [
{
"target": "arm64-macos"
}
],
"install_names": [
{
"name": "@rpath/libDeveloperSupport.dylib"
}
],
"reexported_libraries": [
{
"names": [
"@rpath/Developer.framework/Versions/A/Developer"
]
}
],
"exported_symbols": [
{
"text": {
"global": ["_funcSupport"]
}
}
]
}
}
#--- test.s
.text
.globl _main
.linker_option "-lDeveloperSupport"
_main:
ret
.data
.quad _funcPublic
.quad _funcCore
.quad _funcSupport