diff --git a/examples/cross_compilation/android_app/Sources/Greeter/Greeter.swift b/examples/cross_compilation/android_app/Sources/Greeter/Greeter.swift index 349660d4b..8da83183c 100644 --- a/examples/cross_compilation/android_app/Sources/Greeter/Greeter.swift +++ b/examples/cross_compilation/android_app/Sources/Greeter/Greeter.swift @@ -8,4 +8,13 @@ public struct Greeter { public func greeting() -> String { return "Hello from Swift, \(subject)!" } + + // Swift Concurrency: async code pulls in the concurrency runtime, whose + // global executor lives on libdispatch. This exists so the example is a + // link-time regression test for the `-ldispatch -lBlocksRuntime` linkopts + // in the generated Android toolchain — without them, linking any `async` + // Swift fails with `undefined symbol: dispatch_main` (and friends). + public func greetingAsync() async -> String { + return greeting() + } } diff --git a/examples/cross_compilation/android_app/Sources/SwiftJNI/SwiftJNI.swift b/examples/cross_compilation/android_app/Sources/SwiftJNI/SwiftJNI.swift index ea6d6f472..187b5108c 100644 --- a/examples/cross_compilation/android_app/Sources/SwiftJNI/SwiftJNI.swift +++ b/examples/cross_compilation/android_app/Sources/SwiftJNI/SwiftJNI.swift @@ -6,6 +6,11 @@ import Greeter // symbol name that `NativeBridge.greetingFromSwift()` binds to. @_cdecl("Java_com_example_swiftjni_NativeBridge_greetingFromSwift") public func greetingFromSwift(_ env: UnsafeMutablePointer, _ clazz: jclass) -> jstring? { + // Exercise Swift Concurrency so the example links (and runs) the async + // runtime — see Greeter.greetingAsync(). + Task { + _ = await Greeter(subject: "Android").greetingAsync() + } let message = Greeter(subject: "Android").greeting() return message.withCString { cString in env.pointee!.pointee.NewStringUTF(env, cString) diff --git a/swift/internal/extensions/swift_sdks.bzl b/swift/internal/extensions/swift_sdks.bzl index 084b95137..1ccad94d4 100644 --- a/swift/internal/extensions/swift_sdks.bzl +++ b/swift/internal/extensions/swift_sdks.bzl @@ -293,6 +293,14 @@ def _swift_android_sdk_impl(repository_ctx): "-L{}/android".format(resource_dir), "-llog", "-lswiftCore", + # Swift Concurrency's global executor lives on libdispatch, + # but the dependency comes from C++ objects inside + # libswift_Concurrency.a, so it is never autolinked. Link it + # (and its BlocksRuntime) explicitly from the same SDK + # directory; lld only extracts referenced members, so this is + # free for binaries that don't use concurrency. + "-ldispatch", + "-lBlocksRuntime", "-Wl,-export-dynamic", "-Wl,--exclude-libs,ALL", # TODO: Remove once https://github.com/bazelbuild/rules_android_ndk/commit/efc0c191796477c540e87e0f6bb5d88d6a58cc1f is in a release