Skip to content

Commit

Permalink
[Immediate] Workaround for loading merged frameworks in immediate mode
Browse files Browse the repository at this point in the history
Some frameworks that previously had a separate swift overlay have been
merged in macOS 14. This is causing symbols to not resolve if using the
new SDK but running on an older OS in immediate mode. Ideally we would
handle this automatically in JITLink as is done by the system linker,
but in the meantime add a workaround to load the correct libraries
manually.

rdar://110371405
  • Loading branch information
benlangmuir committed Jun 9, 2023
1 parent 7092e50 commit e759007
Showing 1 changed file with 46 additions and 17 deletions.
63 changes: 46 additions & 17 deletions lib/Immediate/Immediate.cpp
Expand Up @@ -191,6 +191,50 @@ bool swift::immediate::tryLoadLibraries(ArrayRef<LinkLibrary> LinkLibraries,
[](bool Value) { return Value; });
}

/// Workaround for rdar://94645534.
///
/// The framework layout of some frameworks have changed over time, causing
/// unresolved symbol errors in immediate mode when running on older OS versions
/// with a newer SDK. This workaround scans through the list of dependencies and
/// manually adds the right libraries as necessary.
///
/// FIXME: JITLink should emulate the Darwin linker's handling of ld$previous
/// mappings so this is handled automatically.
static void addMergedLibraries(SmallVectorImpl<LinkLibrary> &AllLinkLibraries,
const llvm::Triple &Target) {
assert(Target.isMacOSX());

struct MergedLibrary {
StringRef OldLibrary;
llvm::VersionTuple MovedIn;
};

using VersionTuple = llvm::VersionTuple;

static const llvm::StringMap<MergedLibrary> MergedLibs = {
// Merged in macOS 14.0
{"AppKit", {"libswiftAppKit.dylib", VersionTuple{14}}},
{"HealthKit", {"libswiftHealthKit.dylib", VersionTuple{14}}},
{"Network", {"libswiftNetwork.dylib", VersionTuple{14}}},
{"Photos", {"libswiftPhotos.dylib", VersionTuple{14}}},
{"PhotosUI", {"libswiftPhotosUI.dylib", VersionTuple{14}}},
{"SoundAnalysis", {"libswiftSoundAnalysis.dylib", VersionTuple{14}}},
{"Virtualization", {"libswiftVirtualization.dylib", VersionTuple{14}}},
// Merged in macOS 13.0
{"Foundation", {"libswiftFoundation.dylib", VersionTuple{13}}},
};

SmallVector<StringRef> NewLibs;
for (auto &Lib : AllLinkLibraries) {
auto I = MergedLibs.find(Lib.getName());
if (I != MergedLibs.end() && Target.getOSVersion() < I->second.MovedIn)
NewLibs.push_back(I->second.OldLibrary);
}

for (StringRef NewLib : NewLibs)
AllLinkLibraries.push_back(LinkLibrary(NewLib, LibraryKind::Library));
}

bool swift::immediate::autolinkImportedModules(ModuleDecl *M,
const IRGenOptions &IRGenOpts) {
// Perform autolinking.
Expand All @@ -201,24 +245,9 @@ bool swift::immediate::autolinkImportedModules(ModuleDecl *M,

M->collectLinkLibraries(addLinkLibrary);

// Workaround for rdar://94645534.
//
// The framework layout of Foundation has changed in 13.0, causing unresolved symbol
// errors to libswiftFoundation in immediate mode when running on older OS versions
// with a 13.0 SDK. This workaround scans through the list of dependencies and
// manually adds libswiftFoundation if necessary.
auto &Target = M->getASTContext().LangOpts.Target;
if (Target.isMacOSX() && Target.getOSMajorVersion() < 13) {
bool linksFoundation = std::any_of(AllLinkLibraries.begin(),
AllLinkLibraries.end(), [](auto &Lib) {
return Lib.getName() == "Foundation";
});

if (linksFoundation) {
AllLinkLibraries.push_back(LinkLibrary("libswiftFoundation.dylib",
LibraryKind::Library));
}
}
if (Target.isMacOSX())
addMergedLibraries(AllLinkLibraries, Target);

tryLoadLibraries(AllLinkLibraries, M->getASTContext().SearchPathOpts,
M->getASTContext().Diags);
Expand Down

0 comments on commit e759007

Please sign in to comment.