From 55f191c335897ebbc0d4248276b7c4fbb255b69f Mon Sep 17 00:00:00 2001 From: Jake Petroules Date: Mon, 19 May 2025 20:56:44 -0700 Subject: [PATCH] Add support for building Swift on Android targets Swift Build currently has support for building C/C++ code on Android; this extends it to Swift. Concretely, this fixes the position of the version number in the triple passed to swiftc for Android targets, and adds the relevant search paths to find Swift standard libraries and other content in the Swift SDK. The sysroot still comes from an Android NDK found on the system; the sysroot in the Swift SDK is ignored based on the intended direction around supporting Android targets in Swift. --- Sources/SWBAndroidPlatform/AndroidSDK.swift | 8 ++--- Sources/SWBAndroidPlatform/Plugin.swift | 33 ++++++++++++++++++++- 2 files changed, 36 insertions(+), 5 deletions(-) diff --git a/Sources/SWBAndroidPlatform/AndroidSDK.swift b/Sources/SWBAndroidPlatform/AndroidSDK.swift index ee3262b4..44b93114 100644 --- a/Sources/SWBAndroidPlatform/AndroidSDK.swift +++ b/Sources/SWBAndroidPlatform/AndroidSDK.swift @@ -57,10 +57,10 @@ struct AndroidSDK: Sendable { } struct LLVMTriple: Codable { - let arch: String - let vendor: String - let system: String - let environment: String + var arch: String + var vendor: String + var system: String + var environment: String var description: String { "\(arch)-\(vendor)-\(system)-\(environment)" diff --git a/Sources/SWBAndroidPlatform/Plugin.swift b/Sources/SWBAndroidPlatform/Plugin.swift index 8ffd0044..8b6c8d5a 100644 --- a/Sources/SWBAndroidPlatform/Plugin.swift +++ b/Sources/SWBAndroidPlatform/Plugin.swift @@ -116,6 +116,37 @@ struct AndroidSDKRegistryExtension: SDKRegistryExtension { return [] } + let allPossibleTriples = abis.values.flatMap { abi in + (max(deploymentTargetRange.min, abi.min_os_version)...deploymentTargetRange.max).map { deploymentTarget in + var triple = abi.llvm_triple + triple.vendor = "unknown" // Android NDK uses "none", Swift SDKs use "unknown" + triple.environment += "\(deploymentTarget)" + return triple + } + }.map(\.description) + + let androidSwiftSDKs = (try? SwiftSDK.findSDKs( + targetTriples: allPossibleTriples, + fs: context.fs, + hostOperatingSystem: context.hostOperatingSystem + )) ?? [] + + let swiftSettings: [String: PropertyListItem] + // FIXME: We need a way to narrow down the list, possibly by passing down a Swift SDK identifier from SwiftPM + // The resource path should be the same for all triples in an Android Swift SDK + if let androidSwiftSDK = androidSwiftSDKs.only, let swiftResourceDir = Set(androidSwiftSDK.targetTriples.values.map { tripleProperties in androidSwiftSDK.path.join(tripleProperties.swiftResourcesPath) }).only { + swiftSettings = [ + "SWIFT_LIBRARY_PATH": .plString(swiftResourceDir.join("android").str), + "SWIFT_RESOURCE_DIR": .plString(swiftResourceDir.str), + "SWIFT_TARGET_TRIPLE": .plString("$(CURRENT_ARCH)-unknown-$(SWIFT_PLATFORM_TARGET_PREFIX)$(LLVM_TARGET_TRIPLE_SUFFIX)"), + "LIBRARY_SEARCH_PATHS": "$(inherited) $(SWIFT_RESOURCE_DIR)/../$(__ANDROID_TRIPLE_$(CURRENT_ARCH))", + ].merging(abis.map { + ("__ANDROID_TRIPLE_\($0.value.llvm_triple.arch)", .plString($0.value.triple)) + }, uniquingKeysWith: { _, new in new }) + } else { + swiftSettings = [:] + } + return [(androidSdk.sysroot ?? .root, androidPlatform, [ "Type": .plString("SDK"), "Version": .plString("0.0.0"), @@ -129,7 +160,7 @@ struct AndroidSDKRegistryExtension: SDKRegistryExtension { // FIXME: Make this configurable in a better way so we don't need to push build settings at the SDK definition level "LLVM_TARGET_TRIPLE_OS_VERSION": .plString("linux"), "LLVM_TARGET_TRIPLE_SUFFIX": .plString("-android$(ANDROID_DEPLOYMENT_TARGET)"), - ]), + ].merging(swiftSettings, uniquingKeysWith: { _, new in new })), "SupportedTargets": .plDict([ "android": .plDict([ "Archs": .plArray(abis.map { .plString($0.value.llvm_triple.arch) }),