@@ -18,6 +18,7 @@ error() { printf -- "** ERROR: %s\n" "$*" >&2; }
1818fatal () { error " $@ " ; exit 1; }
1919
2020# Parse command line options
21+ INSTALL_ANDROID=false
2122INSTALL_STATIC_LINUX=false
2223INSTALL_WASM=false
2324BUILD_EMBEDDED_WASM=false
@@ -27,6 +28,18 @@ SWIFT_BUILD_COMMAND="swift build"
2728
2829while [[ $# -gt 0 ]]; do
2930 case $1 in
31+ --android)
32+ INSTALL_ANDROID=true
33+ shift
34+ ;;
35+ --android-ndk-version=* )
36+ ANDROID_NDK_VERSION=" ${1#* =} "
37+ shift
38+ ;;
39+ --android-sdk-triple=* )
40+ ANDROID_SDK_TRIPLE=" ${1#* =} "
41+ shift
42+ ;;
3043 --static)
3144 INSTALL_STATIC_LINUX=true
3245 shift
6477
6578# Validate arguments
6679if [[ -z " $SWIFT_VERSION_INPUT " ]]; then
67- fatal " Usage: $0 [--static] [--wasm] [--flags=\" <build-flags>\" ] [--build-command=\" <build-command>\" ] <swift-version>"
80+ fatal " Usage: $0 [--android] [-- static] [--wasm] [--flags=\" <build-flags>\" ] [--build-command=\" <build-command>\" ] <swift-version>"
6881fi
6982
70- if [[ " $INSTALL_STATIC_LINUX " == false && " $INSTALL_WASM " == false ]]; then
71- fatal " At least one of --static or --wasm must be specified"
83+ if [[ " $INSTALL_ANDROID " == false && " $ INSTALL_STATIC_LINUX" == false && " $INSTALL_WASM " == false ]]; then
84+ fatal " At least one of --android or -- static or --wasm must be specified"
7285fi
7386
7487log " Requested Swift version: $SWIFT_VERSION_INPUT "
88+ log " Install Android Swift SDK: $INSTALL_ANDROID "
7589log " Install Static Linux Swift SDK: $INSTALL_STATIC_LINUX "
7690log " Install Wasm Swift SDK: $INSTALL_WASM "
7791if [[ -n " $SWIFT_BUILD_FLAGS " ]]; then
7892 log " Additional build flags: $SWIFT_BUILD_FLAGS "
7993fi
8094
81- # Detect package manager
82- if command -v apt > /dev/null 2>&1 ; then
83- INSTALL_PACKAGE_COMMAND=" apt update -q && apt install -yq"
84- elif command -v dnf > /dev/null 2>&1 ; then
85- INSTALL_PACKAGE_COMMAND=" dnf install -y"
86- elif command -v yum > /dev/null 2>&1 ; then
87- INSTALL_PACKAGE_COMMAND=" yum install -y"
88- else
89- fatal " No supported package manager found"
90- fi
91-
9295install_package () {
96+ # Detect package manager
97+ if command -v apt > /dev/null 2>&1 ; then
98+ INSTALL_PACKAGE_COMMAND=" apt update -q && apt install -yq"
99+ elif command -v dnf > /dev/null 2>&1 ; then
100+ INSTALL_PACKAGE_COMMAND=" dnf install -y"
101+ elif command -v yum > /dev/null 2>&1 ; then
102+ INSTALL_PACKAGE_COMMAND=" yum install -y"
103+ else
104+ fatal " No supported package manager found"
105+ fi
93106 eval " $INSTALL_PACKAGE_COMMAND $1 "
94107}
95108
@@ -103,7 +116,7 @@ SWIFT_API_INSTALL_ROOT="https://www.swift.org/api/v1/install"
103116# and gets the checksum for the patch version's Static Linux and/or Wasm Swift SDK.
104117#
105118# $1 (string): A minor Swift version, e.g. "6.1"
106- # Output: A string of the form "<patch-version>|<static-checksum>|<wasm-checksum>
119+ # Output: A string of the form "<patch-version>|<android-checksum>|< static-checksum>|<wasm-checksum>
107120find_latest_swift_version () {
108121 local minor_version=" $1 "
109122
@@ -128,6 +141,23 @@ find_latest_swift_version() {
128141
129142 log " Found latest patch version: $latest_version "
130143
144+ local android_sdk_checksum=" "
145+ if [[ " $INSTALL_ANDROID " == true ]]; then
146+ android_sdk_checksum=$( echo " $releases_json " | jq -r --arg version " $latest_version " '
147+ .[]
148+ | select(.name == $version)
149+ | .platforms[]
150+ | select(.platform == "android")
151+ | .checksum
152+ ' )
153+
154+ if [[ -z " $android_sdk_checksum " ]]; then
155+ fatal " No Android Swift SDK checksum found for Swift $latest_version "
156+ fi
157+
158+ log " Found Android Swift SDK checksum: ${android_sdk_checksum: 0: 12} ..."
159+ fi
160+
131161 local static_linux_sdk_checksum=" "
132162 if [[ " $INSTALL_STATIC_LINUX " == true ]]; then
133163 static_linux_sdk_checksum=$( echo " $releases_json " | jq -r --arg version " $latest_version " '
@@ -162,14 +192,15 @@ find_latest_swift_version() {
162192 log " Found Swift SDK for Wasm checksum: ${wasm_sdk_checksum: 0: 12} ..."
163193 fi
164194
165- echo " ${latest_version} |${static_linux_sdk_checksum} |${wasm_sdk_checksum} "
195+ echo " ${latest_version} |${android_sdk_checksum} | ${ static_linux_sdk_checksum} |${wasm_sdk_checksum} "
166196}
167197
168- # Finds the latest Static Linux or Wasm Swift SDK development snapshot
169- # for the inputted Swift version and its checksum.
198+ # Finds the latest Android or Static Linux or Wasm
199+ # Swift SDK development snapshot for the inputted
200+ # Swift version and its checksum.
170201#
171202# $1 (string): Nightly Swift version, e.g. "6.2" or "main"
172- # $2 (string): "static" or "wasm"
203+ # $2 (string): "android" or " static" or "wasm"
173204# Output: A string of the form "<snapshot>|<sdk-checksum>",
174205# e.g. "swift-6.2-DEVELOPMENT-SNAPSHOT-2025-07-29-a|<sdk-checksum>"
175206find_latest_sdk_snapshot () {
@@ -206,6 +237,12 @@ find_latest_sdk_snapshot() {
206237}
207238
208239SWIFT_VERSION_BRANCH=" "
240+ ANDROID_SDK_TAG=" "
241+ ANDROID_SDK_CHECKSUM=" "
242+ # TODO: we will be removing the "-0.1" suffix in a future nightly
243+ ANDROID_SDK_PATH_SUFFIX=" -0.1"
244+ ANDROID_SDK_PATH_SEP=" -"
245+
209246STATIC_LINUX_SDK_TAG=" "
210247STATIC_LINUX_SDK_CHECKSUM=" "
211248WASM_SDK_TAG=" "
@@ -220,6 +257,13 @@ if [[ "$SWIFT_VERSION_INPUT" == nightly-* ]]; then
220257 SWIFT_VERSION_BRANCH=" swift-${version} -branch"
221258 fi
222259
260+ if [[ " $INSTALL_ANDROID " == true ]]; then
261+ android_sdk_info=$( find_latest_sdk_snapshot " $version " " android" )
262+
263+ ANDROID_SDK_TAG=$( echo " $android_sdk_info " | cut -d' |' -f1)
264+ ANDROID_SDK_CHECKSUM=$( echo " $android_sdk_info " | cut -d' |' -f2)
265+ fi
266+
223267 if [[ " $INSTALL_STATIC_LINUX " == true ]]; then
224268 static_linux_sdk_info=$( find_latest_sdk_snapshot " $version " " static" )
225269
@@ -239,14 +283,21 @@ else
239283 latest_version=$( echo " $latest_version_info " | cut -d' |' -f1)
240284 SWIFT_VERSION_BRANCH=" swift-${latest_version} -release"
241285
286+ ANDROID_SDK_TAG=" swift-${latest_version} -RELEASE"
287+ ANDROID_SDK_CHECKSUM=$( echo " $latest_version_info " | cut -d' |' -f2)
288+
242289 STATIC_LINUX_SDK_TAG=" swift-${latest_version} -RELEASE"
243- STATIC_LINUX_SDK_CHECKSUM=$( echo " $latest_version_info " | cut -d' |' -f2 )
290+ STATIC_LINUX_SDK_CHECKSUM=$( echo " $latest_version_info " | cut -d' |' -f3 )
244291
245292 WASM_SDK_TAG=" swift-${latest_version} -RELEASE"
246- WASM_SDK_CHECKSUM=$( echo " $latest_version_info " | cut -d' |' -f3 )
293+ WASM_SDK_CHECKSUM=$( echo " $latest_version_info " | cut -d' |' -f4 )
247294fi
248295
249296# Validate that required Swift SDK tags are set
297+ if [[ " $INSTALL_ANDROID " == true && -z " $ANDROID_SDK_TAG " ]]; then
298+ fatal " ANDROID_SDK_TAG is not set but Android Swift SDK installation was requested"
299+ fi
300+
250301if [[ " $INSTALL_STATIC_LINUX " == true && -z " $STATIC_LINUX_SDK_TAG " ]]; then
251302 fatal " STATIC_LINUX_SDK_TAG is not set but Static Linux Swift SDK installation was requested"
252303fi
@@ -439,9 +490,25 @@ download_and_extract_toolchain() {
439490}
440491
441492INSTALLED_SWIFT_TAG=$( get_installed_swift_tag)
493+ SWIFT_EXECUTABLE_FOR_ANDROID_SDK=" "
442494SWIFT_EXECUTABLE_FOR_STATIC_LINUX_SDK=" "
443495SWIFT_EXECUTABLE_FOR_WASM_SDK=" "
444496
497+ if [[ " $INSTALL_ANDROID " == true ]]; then
498+ if [[ " $INSTALLED_SWIFT_TAG " == " $ANDROID_SDK_TAG " ]]; then
499+ log " Current toolchain matches Android Swift SDK snapshot: $ANDROID_SDK_TAG "
500+ SWIFT_EXECUTABLE_FOR_ANDROID_SDK=" swift"
501+ else
502+ log " Installing Swift toolchain to match Android Swift SDK snapshot: $ANDROID_SDK_TAG "
503+ initialize_os_info
504+ SWIFT_EXECUTABLE_FOR_ANDROID_SDK=$( download_and_extract_toolchain " $ANDROID_SDK_TAG " )
505+ if [[ $? -eq $EXIT_TOOLCHAIN_NOT_FOUND ]]; then
506+ # Don't fail the workflow if we can't find the right toolchain
507+ exit 0
508+ fi
509+ fi
510+ fi
511+
445512if [[ " $INSTALL_STATIC_LINUX " == true ]]; then
446513 if [[ " $INSTALLED_SWIFT_TAG " == " $STATIC_LINUX_SDK_TAG " ]]; then
447514 log " Current toolchain matches Static Linux Swift SDK snapshot: $STATIC_LINUX_SDK_TAG "
@@ -472,9 +539,57 @@ if [[ "$INSTALL_WASM" == true ]]; then
472539 fi
473540fi
474541
542+ ANDROID_SDK_DOWNLOAD_ROOT=" ${SWIFT_DOWNLOAD_ROOT} /${SWIFT_VERSION_BRANCH} /android-sdk"
475543STATIC_LINUX_SDK_DOWNLOAD_ROOT=" ${SWIFT_DOWNLOAD_ROOT} /${SWIFT_VERSION_BRANCH} /static-sdk"
476544WASM_SDK_DOWNLOAD_ROOT=" ${SWIFT_DOWNLOAD_ROOT} /${SWIFT_VERSION_BRANCH} /wasm-sdk"
477545
546+ install_android_sdk () {
547+ # Check if the Android Swift SDK is already installed
548+ if " $SWIFT_EXECUTABLE_FOR_ANDROID_SDK " sdk list 2> /dev/null | grep -q " ^${ANDROID_SDK_TAG} _android" ; then
549+ log " ✅ Android Swift SDK ${ANDROID_SDK_TAG} is already installed, skipping installation"
550+ return 0
551+ fi
552+
553+ log " Installing Android Swift SDK: $ANDROID_SDK_TAG "
554+
555+ local android_sdk_name=" ${ANDROID_SDK_TAG} _android${ANDROID_SDK_PATH_SUFFIX} "
556+ local android_sdk_bundle_name=" ${android_sdk_name} .artifactbundle"
557+ # TODO: remove once the next nightly changes the "-" to "_" in the name
558+ local android_sdk_bundle_dir=" ${android_sdk_bundle_name// _android/ ${ANDROID_SDK_PATH_SEP} android} "
559+ local android_sdk_filename=" ${android_sdk_bundle_name} .tar.gz"
560+ local sdk_url=" ${ANDROID_SDK_DOWNLOAD_ROOT} /${ANDROID_SDK_TAG} /${android_sdk_filename} "
561+
562+ log " Running: ${SWIFT_EXECUTABLE_FOR_ANDROID_SDK} sdk install ${sdk_url} --checksum ${ANDROID_SDK_CHECKSUM} "
563+
564+ if " $SWIFT_EXECUTABLE_FOR_ANDROID_SDK " sdk install " $sdk_url " --checksum " $ANDROID_SDK_CHECKSUM " ; then
565+ log " ✅ Android Swift SDK installed successfully"
566+ else
567+ fatal " Failed to install Android Swift SDK"
568+ fi
569+
570+ # now setup the link to the local ANDROID_NDK_HOME
571+ swift sdk configure --show-configuration " $( swift sdk list | grep android | tail -n 1) "
572+
573+ # guess some common places where the swift-sdks file lives
574+ cd ~ /Library/org.swift.swiftpm || cd ~ /.config/swiftpm || cd ~ /.local/swiftpm || cd ~ /.swiftpm || cd /root/.swiftpm
575+
576+ # Download and install the Android NDK.
577+ # Note that we could use the system package manager, but it is
578+ # named different things for different distributions
579+ # (e.g., "google-android-ndk-r26-installer" on Debian)
580+ if [[ ! -d " ${ANDROID_NDK_HOME:- } " ]]; then
581+ # permit the "--android-ndk" flag to override the default
582+ local android_ndk_version=" ${ANDROID_NDK_VERSION:- r27d} "
583+ curl -fsSL -o ndk.zip --retry 3 https://dl.google.com/android/repository/android-ndk-" ${android_ndk_version} " -" $( uname -s) " .zip
584+ unzip -q ndk.zip
585+ rm ndk.zip
586+ export ANDROID_NDK_HOME=" ${PWD} " /android-ndk-" ${android_ndk_version} "
587+ fi
588+
589+ ./swift-sdks/" ${android_sdk_bundle_dir} " /swift-android/scripts/setup-android-sdk.sh
590+ cd -
591+ }
592+
478593install_static_linux_sdk () {
479594 # Check if the Static Linux Swift SDK is already installed
480595 if " $SWIFT_EXECUTABLE_FOR_STATIC_LINUX_SDK " sdk list 2> /dev/null | grep -q " ^${STATIC_LINUX_SDK_TAG} _static-linux-0.0.1" ; then
@@ -518,6 +633,11 @@ install_wasm_sdk() {
518633}
519634
520635install_sdks () {
636+ if [[ " $INSTALL_ANDROID " == true ]]; then
637+ log " Starting install of Swift ${SWIFT_VERSION_INPUT} Android Swift SDK"
638+ install_android_sdk
639+ fi
640+
521641 if [[ " $INSTALL_STATIC_LINUX " == true ]]; then
522642 log " Starting install of Swift ${SWIFT_VERSION_INPUT} Static Linux Swift SDK"
523643 install_static_linux_sdk
@@ -533,6 +653,31 @@ build() {
533653 # Enable alias expansion to use a 'swift' alias for the executable path
534654 shopt -s expand_aliases
535655
656+ if [[ " $INSTALL_ANDROID " == true ]]; then
657+ log " Running Swift build with Android Swift SDK"
658+
659+ local sdk_name=" ${ANDROID_SDK_TAG}${ANDROID_SDK_PATH_SEP} android${ANDROID_SDK_PATH_SUFFIX} "
660+
661+ alias swift=' $SWIFT_EXECUTABLE_FOR_ANDROID_SDK'
662+ local build_command=" $SWIFT_BUILD_COMMAND --swift-sdk ${ANDROID_SDK_TRIPLE:- $sdk_name } "
663+ if [[ -n " $SWIFT_BUILD_FLAGS " ]]; then
664+ build_command=" $build_command $SWIFT_BUILD_FLAGS "
665+ fi
666+
667+ log " Running: $build_command "
668+
669+ # clear the ANDROID_NDK_ROOT environment variable if it is set
670+ # due to https://github.com/swiftlang/swift-driver/pull/1879
671+ # otherwise build error: missing required module 'SwiftAndroid'
672+ export ANDROID_NDK_ROOT=" "
673+
674+ if eval " $build_command " ; then
675+ log " ✅ Swift build with Android Swift SDK completed successfully"
676+ else
677+ fatal " Swift build with Android Swift SDK failed"
678+ fi
679+ fi
680+
536681 if [[ " $INSTALL_STATIC_LINUX " == true ]]; then
537682 log " Running Swift build with Static Linux Swift SDK"
538683
0 commit comments