-
Notifications
You must be signed in to change notification settings - Fork 10.5k
Android NDK version needs to be visible in Swift #81402
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
You're right that continually added nullability annotations in each NDK causes us to have to keep changing our C function signatures to match. That said, I doubt that almost anyone will actually use this feature to target multiple NDKs in the same Swift codebase, so I think we should just espouse the best practice that all Swift code should match the current LTS NDK. If someone wants to build with some other NDK, it is up to them to patch all their Swift code to work. I'm not against adding this |
…nd NDK 28 (#3249) This change enables swift-nio to be compiled for Android against both NDK 27 and NDK 28 ### Motivation: Android's NDK had been adopting [nullability annotations](https://android.googlesource.com/platform/developers/docs/+/refs/heads/master/api-guidelines/ndk.md#nullability) in its C headers, and they have been changing them from release to release. The churn has mostly died down since the release of the NDK 27 (LTS), but one new change in NDK 28 affects the destructor argument for `pthread_create`, making the existing `ThreadDestructor` typealias invalid and leading to the following compile error when the [Android SDK bundle](https://github.com/skiptools/swift-android-toolchain/releases) is installed and linked to NDK 28: ``` $ swiftly run swift build --swift-sdk aarch64-unknown-linux-android28 +6.2-snapshot-2025-05-15-a Building for debugging... /opt/src/github/swift-everywhere/swift-nio/Sources/NIOPosix/ThreadPosix.swift:82:9: error: cannot convert value of type '@convention(c) (UnsafeMutableRawPointer?) -> UnsafeMutableRawPointer?' to expected argument type '@convention(c) (UnsafeMutableRawPointer) -> UnsafeMutableRawPointer' 80 | &handleLinux, 81 | nil, 82 | destructor, | `- error: cannot convert value of type '@convention(c) (UnsafeMutableRawPointer?) -> UnsafeMutableRawPointer?' to expected argument type '@convention(c) (UnsafeMutableRawPointer) -> UnsafeMutableRawPointer' 83 | args 84 | ) [4/21] Compiling NIOPosix ThreadPosix.swift ``` This change adapts the parameter we pass to that function to accommodate both NDK 27 and NDK 28. ### Modifications: There's currently no way to determine which version of the NDK is in use at compile time (see swiftlang/swift#81402), so this accommodation is implementing by having two functions named `coerceThreadDestructor` that return values that are suitable either NDK 27 or NDK 28 (using `unsafeBitCast`, but the layout of C functions doesn't know anything about nullability, so this is safe), and then let the type inference for `pthread_create` handle the rest. ### Result: swift-nio can be compiled against both NDK 27 and NDK 28 without errors.
The proposed Android SDK bundle (#80788) will depend on an external NDK being configured. The NDK changes various headers in between their releases, especially around nullability annotations being aded or removed, which affects Swift's view of the C functions and structures.
This means that in practice, some packages that rely on the definitions in the NDK headers will fail to build with earlier or later versions. For example,
swift-nio
builds successfully for Android with NDK 27, but fails for NDK 26 and 28:swift-nio failure for NDK 26
swift-nio failure for NDK 28
This is similar to needing to be able to check the Android API level described at #76671, except it is a build-time constant indicated by
__NDK_MAJOR__
that wouldn't affect anything at runtime. Android API levels and NDK versions are unrelated (e.g., you can build for API 34+NDK 26 or API 33+NDK 27 or API 29+NDK 28), and so the Android API level cannot be used as a proxy for the NDK version.The "just do it in C" solution might look like this:
A crude solution might be to have the Android SDK post-install script add per-NDK build variables for everything up to the current NDK, so that when building against NDK 26, swiftc would look like:
and when building against NDK 27, it would look like:
That way the Swift code could perform checks like:
A solution built into Swift might look like:
The text was updated successfully, but these errors were encountered: