Skip to content

Commit 2c71a22

Browse files
committed
Test Android cross compilation on Windows
This also fixes the Android support to recognize an NDK even when an SDK is not present, which might be the case for some installations not driven through Android Studio (for example, NDK as installed by the chocolatey package manager on Windows, or installed manually into some directory).
1 parent bbf6db0 commit 2c71a22

File tree

4 files changed

+25
-9
lines changed

4 files changed

+25
-9
lines changed

.github/scripts/windows_pre_build.ps1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ if ($InstallCMake) {
3030
}
3131

3232
if (-not $SkipAndroid) {
33-
choco install android-ndk
33+
choco install -y android-ndk
3434

3535
Import-Module $env:ChocolateyInstall\helpers\chocolateyProfile.psm1
3636
refreshenv

.github/workflows/pull_request.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ jobs:
1717
linux_pre_build_command: ./.github/scripts/linux_pre_build.sh
1818
linux_build_command: 'swift test --no-parallel'
1919
linux_swift_versions: '["nightly-main", "nightly-6.2"]'
20+
windows_pre_build_command: 'Invoke-Program .\.github\scripts\windows_pre_build.ps1'
2021
windows_swift_versions: '["nightly-main"]'
2122
windows_build_command: 'Invoke-Program swift test --no-parallel'
2223
enable_linux_static_sdk_build: true

Sources/SWBAndroidPlatform/AndroidSDK.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -266,16 +266,16 @@ public import Foundation
266266
}
267267
}
268268

269-
fileprivate extension AndroidSDK.NDK {
269+
extension AndroidSDK.NDK {
270270
/// The location of the Android NDK based on the `ANDROID_NDK_ROOT` environment variable (falling back to the deprecated but well known `ANDROID_NDK_HOME`).
271271
/// - seealso: [Configuring NDK Path](https://github.com/android/ndk-samples/wiki/Configure-NDK-Path#terminologies)
272-
static var environmentOverrideLocation: AbsolutePath? {
272+
internal static var environmentOverrideLocation: AbsolutePath? {
273273
(getEnvironmentVariable("ANDROID_NDK_ROOT") ?? getEnvironmentVariable("ANDROID_NDK_HOME"))?.nilIfEmpty.map { AbsolutePath($0) } ?? nil
274274
}
275275

276276
/// Location of the Android NDK installed by the `google-android-ndk-*-installer` family of packages available in Debian 13 "Trixie" and Ubuntu 24.04 "Noble".
277277
/// These packages are available in non-free / multiverse and multiple versions can be installed simultaneously.
278-
static var defaultDebianLocation: AbsolutePath? {
278+
fileprivate static var defaultDebianLocation: AbsolutePath? {
279279
AbsolutePath("/usr/lib/android-ndk")
280280
}
281281
}

Sources/SWBAndroidPlatform/Plugin.swift

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ public let initializePlugin: PluginInitializationFunction = { manager in
2626

2727
@_spi(Testing) public final class AndroidPlugin: Sendable {
2828
private let androidSDKInstallations = AsyncCache<OperatingSystem, [AndroidSDK]>()
29+
private let androidOverrideNDKInstallation = AsyncCache<OperatingSystem, AndroidSDK.NDK?>()
2930

3031
func cachedAndroidSDKInstallations(host: OperatingSystem) async throws -> [AndroidSDK] {
3132
try await androidSDKInstallations.value(forKey: host) {
@@ -34,8 +35,22 @@ public let initializePlugin: PluginInitializationFunction = { manager in
3435
}
3536
}
3637

37-
@_spi(Testing) public func effectiveInstallation(host: OperatingSystem) async throws -> (sdk: AndroidSDK, ndk: AndroidSDK.NDK)? {
38+
func cachedAndroidOverrideNDKInstallation(host: OperatingSystem) async throws -> AndroidSDK.NDK? {
39+
try await androidOverrideNDKInstallation.value(forKey: host) {
40+
if let overridePath = AndroidSDK.NDK.environmentOverrideLocation {
41+
return try AndroidSDK.NDK(host: host, path: overridePath, fs: localFS)
42+
}
43+
return nil
44+
}
45+
}
46+
47+
@_spi(Testing) public func effectiveInstallation(host: OperatingSystem) async throws -> (sdk: AndroidSDK?, ndk: AndroidSDK.NDK)? {
3848
guard let androidSdk = try? await cachedAndroidSDKInstallations(host: host).first else {
49+
// No SDK, but we might still have a standalone NDK from the env var override
50+
if let overrideNDK = try? await cachedAndroidOverrideNDKInstallation(host: host) {
51+
return (nil, overrideNDK)
52+
}
53+
3954
return nil
4055
}
4156

@@ -63,9 +78,9 @@ struct AndroidEnvironmentExtension: EnvironmentExtension {
6378
func additionalEnvironmentVariables(context: any EnvironmentExtensionAdditionalEnvironmentVariablesContext) async throws -> [String: String] {
6479
switch context.hostOperatingSystem {
6580
case .windows, .macOS, .linux:
66-
if let latest = try? await plugin.cachedAndroidSDKInstallations(host: context.hostOperatingSystem).first {
67-
let sdkPath = latest.path.path.str
68-
let ndkPath = latest.preferredNDK?.path.path.str
81+
if let (sdk, ndk) = try? await plugin.effectiveInstallation(host: context.hostOperatingSystem) {
82+
let sdkPath = sdk?.path.path.str
83+
let ndkPath = ndk.path.path.str
6984
return [
7085
"ANDROID_HOME": sdkPath,
7186
"ANDROID_SDK_ROOT": sdkPath,
@@ -220,7 +235,7 @@ struct AndroidToolchainRegistryExtension: ToolchainRegistryExtension {
220235
let plugin: AndroidPlugin
221236

222237
func additionalToolchains(context: any ToolchainRegistryExtensionAdditionalToolchainsContext) async throws -> [Toolchain] {
223-
guard let toolchainPath = try? await plugin.cachedAndroidSDKInstallations(host: context.hostOperatingSystem).first?.preferredNDK?.toolchainPath else {
238+
guard let toolchainPath = try? await plugin.effectiveInstallation(host: context.hostOperatingSystem)?.ndk.toolchainPath else {
224239
return []
225240
}
226241

0 commit comments

Comments
 (0)