mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Merge pull request #75594 from benlangmuir/script-load-foundation-early
[immediate] Load Foundation early enough for bridging
This commit is contained in:
@@ -115,6 +115,8 @@ ERROR(error_immediate_mode_missing_library,none,
|
||||
(unsigned, StringRef))
|
||||
ERROR(error_immediate_mode_primary_file,none,
|
||||
"immediate mode is incompatible with -primary-file", ())
|
||||
WARNING(warning_immediate_mode_cannot_load_foundation,none,
|
||||
"immediate mode failed to load Foundation: %0", (StringRef))
|
||||
ERROR(error_missing_frontend_action,none,
|
||||
"no frontend action was selected", ())
|
||||
ERROR(error_invalid_source_location_str,none,
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
namespace swift {
|
||||
class CompilerInstance;
|
||||
class DiagnosticEngine;
|
||||
class IRGenOptions;
|
||||
class SILOptions;
|
||||
class SILModule;
|
||||
@@ -44,6 +45,9 @@ namespace swift {
|
||||
|
||||
int RunImmediatelyFromAST(CompilerInstance &CI);
|
||||
|
||||
/// On platforms that support ObjC bridging from the Foundation framework,
|
||||
/// ensure that Foundation is loaded early enough. Otherwise does nothing.
|
||||
void loadFoundationIfNeeded(DiagnosticEngine &Diags);
|
||||
} // end namespace swift
|
||||
|
||||
#endif // SWIFT_IMMEDIATE_IMMEDIATE_H
|
||||
|
||||
@@ -1955,6 +1955,13 @@ int swift::performFrontend(ArrayRef<const char *> Args,
|
||||
return finishDiagProcessing(1, /*verifierEnabled*/ false);
|
||||
}
|
||||
|
||||
// Scripts that use the Foundation framework need it loaded early for bridging
|
||||
// to work correctly on Darwin platforms. On other platforms this is a no-op.
|
||||
if (Invocation.getFrontendOptions().RequestedAction ==
|
||||
FrontendOptions::ActionType::Immediate) {
|
||||
loadFoundationIfNeeded(Instance->getDiags());
|
||||
}
|
||||
|
||||
// Don't ask clients to report bugs when running a script in immediate mode.
|
||||
// When a script asserts the compiler reports the error with the same
|
||||
// stacktrace as a compiler crash. From here we can't tell which is which,
|
||||
|
||||
@@ -432,3 +432,30 @@ int swift::RunImmediatelyFromAST(CompilerInstance &CI) {
|
||||
|
||||
return *Result;
|
||||
}
|
||||
|
||||
void swift::loadFoundationIfNeeded(DiagnosticEngine &Diags) {
|
||||
#if defined(__APPLE__)
|
||||
const char *FoundationPath =
|
||||
"/System/Library/Frameworks/Foundation.framework/Foundation";
|
||||
void *handle = dlopen(FoundationPath, RTLD_NOLOAD);
|
||||
if (handle) {
|
||||
// Foundation is already loaded. Use dlclose to release the ref-count that
|
||||
// was incremented by dlopen and return.
|
||||
dlclose(handle);
|
||||
return;
|
||||
} else {
|
||||
// Foundation is not yet loaded. Load it now and leak the handle.
|
||||
// FIXME: it is fragile to load here, as there is no guarantee the swift
|
||||
// runtime has not initialized already. As the compiler adds more swift code
|
||||
// we may need to move this or find another solution.
|
||||
handle = dlopen(FoundationPath, RTLD_LAZY | RTLD_GLOBAL);
|
||||
if (!handle)
|
||||
Diags.diagnose(SourceLoc(),
|
||||
diag::warning_immediate_mode_cannot_load_foundation,
|
||||
dlerror());
|
||||
}
|
||||
|
||||
#else
|
||||
// Nothing to do.
|
||||
#endif
|
||||
}
|
||||
|
||||
25
test/Interpreter/foundation-bridge-error.swift
Normal file
25
test/Interpreter/foundation-bridge-error.swift
Normal file
@@ -0,0 +1,25 @@
|
||||
// Check that we can access localizedDescription, which crashes in the runtime
|
||||
// if Foundation is loaded after the runtime is already initialized on Darwin.
|
||||
|
||||
// REQUIRES: executable_test
|
||||
// REQUIRES: objc_interop
|
||||
// REQUIRES: OS=macosx
|
||||
|
||||
// FIXME: There's a separate bridging error with the just-built stdlib on CI
|
||||
// nodes.
|
||||
// REQUIRES: use_os_stdlib
|
||||
|
||||
// RUN: %target-jit-run %s
|
||||
// RUN: DYLD_INSERT_LIBRARIES=/System/Library/Frameworks/Foundation.framework/Foundation %target-jit-run %s
|
||||
|
||||
import Foundation
|
||||
|
||||
print("Insert Libraries: \(ProcessInfo.processInfo.environment["DYLD_INSERT_LIBRARIES"] ?? "<nil>")")
|
||||
|
||||
enum SomeError: LocalizedError {
|
||||
case fail
|
||||
}
|
||||
|
||||
let err = SomeError.fail
|
||||
let path = (#file as NSString).lastPathComponent
|
||||
let desc = err.localizedDescription
|
||||
Reference in New Issue
Block a user