Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
84 commits
Select commit Hold shift + click to select a range
d8ce023
Add enable_android_sdk_checks option for Android emulator testing
marcprux Dec 12, 2025
b7d0a75
Update build flags
marcprux Dec 12, 2025
51883a5
Pull request enable_android_sdk_checks: true
marcprux Dec 12, 2025
427b18b
Fix script location
marcprux Dec 12, 2025
c082391
Fix script permissions
marcprux Dec 12, 2025
1d76ea7
Download the Android SDK
marcprux Dec 12, 2025
b7e9a5d
Update the Android SDK
marcprux Dec 12, 2025
1e9bf25
Install Android SDK using package manager
marcprux Dec 12, 2025
b19a2f9
Update the Android SDK
marcprux Dec 12, 2025
4312ece
Install Java
marcprux Dec 12, 2025
728894a
Install Java
marcprux Dec 12, 2025
cb08f99
Install commandline tools in correct directory
marcprux Dec 12, 2025
4d8249c
Update Android SDK
marcprux Dec 12, 2025
bad3c64
Update Android SDK
marcprux Dec 12, 2025
06d6ff7
Update Android SDK
marcprux Dec 12, 2025
3c29f25
Use different Android emulator device
marcprux Dec 12, 2025
988484d
Update path to Android emulator
marcprux Dec 12, 2025
cbf8812
Update path to Android emulator
marcprux Dec 12, 2025
3620be4
Update path to Android emulator
marcprux Dec 12, 2025
97923bd
Fix check for JAVA_HOME
marcprux Dec 12, 2025
0c52793
Install sudo
marcprux Dec 12, 2025
8b7cdf5
Better JAVA_HOME check
marcprux Dec 12, 2025
b363415
Try not enabling KVM
marcprux Dec 12, 2025
9c38d01
Try not enabling KVM
marcprux Dec 12, 2025
4031eee
Fix install path for Android AVD
marcprux Dec 12, 2025
560f60a
Try to install KVM
marcprux Dec 12, 2025
b09c11b
Try to install KVM
marcprux Dec 12, 2025
1ef5eb5
Just run tests on a single config
marcprux Dec 12, 2025
8362509
Try installing KVM
marcprux Dec 12, 2025
f0a2e91
Try installing KVM
marcprux Dec 12, 2025
c97c292
Try installing KVM
marcprux Dec 12, 2025
6932225
Try running emulator with -no-accel
marcprux Dec 13, 2025
88e55ce
Try running tests
marcprux Dec 13, 2025
dedd2a8
Try running tests
marcprux Dec 13, 2025
67efdb9
Try running tests
marcprux Dec 13, 2025
1889eba
Try freeing disk space
marcprux Dec 13, 2025
5c112a8
Try freeing disk space
marcprux Dec 13, 2025
8551570
Try freeing disk space
marcprux Dec 13, 2025
a714374
Try freeing disk space
marcprux Dec 14, 2025
1c088a2
Use x86_64-linux-android for test cases
marcprux Dec 14, 2025
345a468
Use x86_64-linux-android for test cases
marcprux Dec 14, 2025
c299a2d
Fix AVD partition size
marcprux Dec 14, 2025
8204a10
Fix AVD partition size
marcprux Dec 14, 2025
5b015d8
Fix AVD partition size
marcprux Dec 14, 2025
d0d4b4c
Fix location of libc++_shared.so
marcprux Dec 14, 2025
bf04475
Fix location of libc++_shared.so
marcprux Dec 14, 2025
b0b4595
Fix location of libc++_shared.so
marcprux Dec 14, 2025
b0fc274
Fix location of libc++_shared.so
marcprux Dec 14, 2025
6433df2
Fix location of libc++_shared.so
marcprux Dec 14, 2025
bbc4a12
Fix location of libc++_shared.so
marcprux Dec 14, 2025
4f6703e
Fix location of Swift SDK for Android
marcprux Dec 14, 2025
707adbd
Fix location of Swift SDK for Android
marcprux Dec 14, 2025
6cab1f3
Fix location of Swift SDK for Android
marcprux Dec 14, 2025
e910952
Fix location of Swift SDK for Android
marcprux Dec 14, 2025
6563fe6
Fix location of Swift SDK for Android
marcprux Dec 14, 2025
7d58ee6
Fix location of Swift SDK for Android
marcprux Dec 14, 2025
c705e86
Fix location of Swift SDK for Android
marcprux Dec 14, 2025
e56b090
Set AVD partition size
marcprux Dec 15, 2025
25c305b
Set AVD partition size
marcprux Dec 15, 2025
4a197ee
Set AVD partition size
marcprux Dec 15, 2025
6841907
Set AVD partition size
marcprux Dec 15, 2025
4a2a9c7
Set AVD partition size
marcprux Dec 15, 2025
a86bcba
Set AVD partition size
marcprux Dec 15, 2025
ca5f01d
Set AVD partition size
marcprux Dec 15, 2025
1add73b
Set AVD partition size
marcprux Dec 15, 2025
1ecdca9
Set AVD partition size
marcprux Dec 15, 2025
ea1eb0a
Run without a docker container
marcprux Dec 15, 2025
4411d7e
Run without a docker container
marcprux Dec 15, 2025
a0c6393
Run without a docker container
marcprux Dec 15, 2025
a5a207b
Run without a docker container
marcprux Dec 15, 2025
edb1240
Fix ANDROID_SDK_TRIPLE
marcprux Dec 15, 2025
77fd5d6
Fix ANDROID_AVD_HOME
marcprux Dec 15, 2025
4f63ef2
Fix ANDROID_AVD_HOME
marcprux Dec 15, 2025
fe29bf4
Cleanup copy of test resources and executables
marcprux Dec 15, 2025
0cc3112
Cleanup copy of test resources and executables
marcprux Dec 15, 2025
c09530d
Cleanup copy of test resources and executables
marcprux Dec 15, 2025
2f1c57f
Break up build and test run into two separate steps
marcprux Dec 15, 2025
614fb27
Add explicit --testing-library arg
marcprux Dec 15, 2025
5adabf6
Check with ANDROID_SDK_TRIPLES
marcprux Dec 15, 2025
4413049
Check with ANDROID_SDK_TRIPLES
marcprux Dec 15, 2025
89d7535
Cleanup
marcprux Dec 15, 2025
c0e37d7
Quote ANDROID_EMULATOR_TIMEOUT for shellcheck
marcprux Dec 15, 2025
15a740d
Add log message about which triple is under test
marcprux Dec 16, 2025
5f4d9bf
Add warning when Package.swift contains macros
marcprux Dec 17, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 1 addition & 5 deletions .github/workflows/pull_request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,6 @@ jobs:
wasm_sdk_pre_build_command: |
cd tests/TestPackage
enable_wasm_sdk_build: true
# Android
android_sdk_pre_build_command: |
cd tests/TestPackage
enable_android_sdk_build: true
# Windows
windows_build_command: |
cd tests/TestPackage
Expand All @@ -56,7 +52,7 @@ jobs:
# Android
android_sdk_pre_build_command: |
cd tests/TestPackage
enable_android_sdk_build: true
enable_android_sdk_checks: true
# Windows
windows_build_command: |
cd tests/TestPackage
Expand Down
146 changes: 146 additions & 0 deletions .github/workflows/scripts/android/android-emulator-tests.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
#!/bin/bash
##===----------------------------------------------------------------------===##
##
## This source file is part of the Swift.org open source project
##
## Copyright (c) 2025 Apple Inc. and the Swift project authors
## Licensed under Apache License v2.0 with Runtime Library Exception
##
## See https://swift.org/LICENSE.txt for license information
## See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
##
##===----------------------------------------------------------------------===##

set -euo pipefail

log() { printf -- "** %s\n" "$*" >&2; }
error() { printf -- "** ERROR: %s\n" "$*" >&2; }
fatal() { error "$@"; exit 1; }

ANDROID_PROFILE="Nexus 10"
ANDROID_EMULATOR_TIMEOUT=300

SWIFTPM_HOME="${XDG_CONFIG_HOME}"/swiftpm
# e.g., "${SWIFTPM_HOME}"/swift-sdks/swift-DEVELOPMENT-SNAPSHOT-2025-12-11-a_android.artifactbundle/
SWIFT_ANDROID_SDK_HOME=$(find "${SWIFTPM_HOME}"/swift-sdks -maxdepth 1 -name 'swift-*android.artifactbundle' | tail -n 1)

ANDROID_SDK_TRIPLE="x86_64-unknown-linux-android28"

while [[ $# -gt 0 ]]; do
case $1 in
--android-sdk-triple=*)
ANDROID_SDK_TRIPLE="${1#*=}"
shift
;;
--android-profile=*)
ANDROID_PROFILE="${1#*=}"
shift
;;
--android-emulator-timeout=*)
ANDROID_EMULATOR_TIMEOUT="${1#*=}"
shift
;;
-*)
fatal "Unknown option: $1"
;;
*)
if [[ -z "$SWIFT_VERSION_INPUT" ]]; then
SWIFT_VERSION_INPUT="$1"
else
fatal "Multiple Swift versions specified: $SWIFT_VERSION_INPUT and $1"
fi
shift
;;
esac
done

# extract the API level from the end of the triple
ANDROID_API="${ANDROID_SDK_TRIPLE/*-unknown-linux-android/}"
Copy link
Member

@finagolfin finagolfin Dec 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If multiple triples are passed in, what does this do, just grab the API level of the first one?


# extract the build arch from the beginning of the triple
ANDROID_EMULATOR_ARCH="${ANDROID_SDK_TRIPLE/-unknown-linux-android*/}"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If multiple triples are passed in, what does this do, just grab the arch of the first one? If we only support x86_64 right now, may be better to just hard-code this until we support testing on other arches, or it may fail if it attempts those.


# x86_64=x86_64, armv7=arm
ANDROID_EMULATOR_ARCH_TRIPLE="${ANDROID_EMULATOR_ARCH}"

log "Running tests for ${ANDROID_SDK_TRIPLE}"

EMULATOR_SPEC="system-images;android-${ANDROID_API};default;${ANDROID_EMULATOR_ARCH}"

log "SWIFT_ANDROID_SDK_HOME=${SWIFT_ANDROID_SDK_HOME}"

# install and start an Android emulator
log "Listing installed Android SDKs"
export PATH="${PATH}:$ANDROID_HOME/emulator:$ANDROID_HOME/tools:$ANDROID_HOME/build-tools/latest:$ANDROID_HOME/platform-tools:$ANDROID_HOME/cmdline-tools/latest/bin"
sdkmanager --list_installed

log "Updating Android SDK licenses"
yes | sdkmanager --licenses > /dev/null || true

log "Installing Android emulator"
sdkmanager --install "emulator" "platform-tools" "platforms;android-${ANDROID_API}" "${EMULATOR_SPEC}"

log "Creating Android emulator"
export ANDROID_AVD_HOME=${XDG_CONFIG_HOME:-$HOME}/.android/avd
ANDROID_EMULATOR_NAME="swiftemu"
avdmanager create avd --force -n "${ANDROID_EMULATOR_NAME}" --package "${EMULATOR_SPEC}" --device "${ANDROID_PROFILE}"

log "Configuring Android emulators"
emulator -list-avds

log "Check Hardware Acceleration (KVM)"
emulator -accel-check

log "Starting Android emulator"
# launch the emulator in the background
nohup emulator -no-metrics -partition-size 1024 -memory 4096 -wipe-data -no-window -no-snapshot -noaudio -no-boot-anim -avd "${ANDROID_EMULATOR_NAME}" &

log "Waiting for Android emulator startup"
timeout "${ANDROID_EMULATOR_TIMEOUT}" adb wait-for-any-device

log "Prepare Swift test package"
# create a staging folder where we copy the test executable
# and all the dependent libraries to copy over to the emulator
STAGING_DIR="swift-android-test"
rm -rf "${STAGING_DIR}"
mkdir "${STAGING_DIR}"

BUILD_DIR=.build/"${ANDROID_SDK_TRIPLE}"/debug

find "${BUILD_DIR}" -name '*.xctest' -exec cp -av {} "${STAGING_DIR}" \;
find "${BUILD_DIR}" -name '*.resources' -exec cp -av {} "${STAGING_DIR}" \;

# copy over the required library dependencies
cp -av "${SWIFT_ANDROID_SDK_HOME}"/swift-android/swift-resources/usr/lib/swift-"${ANDROID_EMULATOR_ARCH_TRIPLE}"/android/*.so "${STAGING_DIR}"
cp -av "${SWIFT_ANDROID_SDK_HOME}"/swift-android/ndk-sysroot/usr/lib/"${ANDROID_EMULATOR_ARCH_TRIPLE}"-linux-android/libc++_shared.so "${STAGING_DIR}"

# for the common case of tests referencing
# their own files as hardwired paths instead of resources
if [[ -d Tests ]]; then
cp -a Tests "${STAGING_DIR}"
fi

# warn about macros in packages, as per
# https://github.com/swiftlang/github-workflows/pull/215#discussion_r2621335245
grep -q '\.macro(' Package.swift && log "WARNING: Packages with macros are known to have issues with cross-compilation: https://github.com/swiftlang/swift-package-manager/issues/8094" || true

log "Copy Swift test package to emulator"

ANDROID_TMP_FOLDER="/data/local/tmp/${STAGING_DIR}"
adb push "${STAGING_DIR}" "${ANDROID_TMP_FOLDER}"

TEST_CMD="./*.xctest"
TEST_SHELL="cd ${ANDROID_TMP_FOLDER}"
TEST_SHELL="${TEST_SHELL} && ${TEST_CMD} --testing-library xctest"

# Run test cases a second time with the Swift Testing library
# We additionally need to handle the special exit code
# EXIT_NO_TESTS_FOUND (69 on Android), which can happen
# when the tests link to Testing, but no tests are executed
# see: https://github.com/swiftlang/swift-package-manager/blob/main/Sources/Commands/SwiftTestCommand.swift#L1571
TEST_SHELL="${TEST_SHELL} && ${TEST_CMD} --testing-library swift-testing && [ \$? -eq 0 ] || [ \$? -eq 69 ]"

log "Run Swift package tests"

# run the test executable
adb shell "${TEST_SHELL}"
47 changes: 27 additions & 20 deletions .github/workflows/swift_package_test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,10 @@ on:
type: boolean
description: "Boolean to enable building with the Swift SDK for Android. Defaults to false"
default: false
enable_android_sdk_checks:
type: boolean
description: "Boolean to enable testing with the Swift SDK for Android. Defaults to false"
default: false
enable_macos_checks:
type: boolean
description: "Boolean to enable macOS testing. Defaults to false"
Expand Down Expand Up @@ -582,45 +586,29 @@ jobs:
${{ steps.script_path.outputs.root }}/.github/workflows/scripts/install-and-build-with-sdk.sh --embedded-wasm --flags="$BUILD_FLAGS" ${{ matrix.swift_version }}

android-sdk-build:
name: Swift SDK for Android Build (${{ matrix.swift_version }} - ${{ matrix.os_version }} - NDK ${{ matrix.ndk_version }})
name: Swift SDK for Android Build (${{ matrix.swift_version }} - NDK ${{ matrix.ndk_version }})
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
swift_version: ${{ fromJson(inputs.android_sdk_versions) }}
ndk_version: ${{ fromJson(inputs.android_ndk_versions) }}
os_version: ${{ fromJson(inputs.linux_os_versions) }}
exclude:
- ${{ fromJson(inputs.android_exclude_swift_versions) }}
- ${{ fromJson((!inputs.enable_android_sdk_build && inputs.android_sdk_versions) || '[]') }}
- ${{ fromJson((!inputs.enable_android_sdk_build && inputs.android_ndk_versions) || '[]') }}
- ${{ fromJson((!inputs.enable_android_sdk_build && inputs.linux_os_versions) || '[]') }}
container:
image: ${{ (contains(matrix.swift_version, 'nightly') && 'swiftlang/swift') || 'swift' }}:${{ matrix.swift_version }}-${{ matrix.os_version }}
- ${{ fromJson((!(inputs.enable_android_sdk_build || inputs.enable_android_sdk_checks) && inputs.android_sdk_versions) || '[]') }}
- ${{ fromJson((!(inputs.enable_android_sdk_build || inputs.enable_android_sdk_checks) && inputs.android_ndk_versions) || '[]') }}
steps:
- name: Swift version
run: swift --version
- name: Clang version
run: clang --version
- name: Checkout repository
uses: actions/checkout@v4
if: ${{ matrix.os_version != 'amazonlinux2' }}
- name: Checkout repository
uses: actions/checkout@v1
if: ${{ matrix.os_version == 'amazonlinux2' }}
- name: Checkout swiftlang/github-workflows repository
if: ${{ matrix.os_version != 'amazonlinux2' && github.repository != 'swiftlang/github-workflows' }}
uses: actions/checkout@v4
with:
repository: swiftlang/github-workflows
path: github-workflows
- name: Checkout swiftlang/github-workflows repository
if: ${{ matrix.os_version == 'amazonlinux2' && github.repository != 'swiftlang/github-workflows' }}
uses: actions/checkout@v1
with:
repository: swiftlang/github-workflows
path: ${{ github.event.repository.name }}/github-workflows
ref: main
- name: Determine script-root path
id: script_path
run: |
Expand All @@ -644,10 +632,29 @@ jobs:
run: ${{ inputs.linux_pre_build_command }}
- name: Install Swift SDK for Android and build
env:
BUILD_FLAGS: ${{ (contains(matrix.swift_version, 'nightly') && inputs.swift_nightly_flags) || inputs.swift_flags }}
BUILD_FLAGS: ${{ inputs.enable_android_sdk_checks && '--build-tests' }} ${{ (contains(matrix.swift_version, 'nightly') && inputs.swift_nightly_flags) || inputs.swift_flags }}
shell: bash
run: |
${{ inputs.android_sdk_pre_build_command }}
${{ steps.script_path.outputs.root }}/.github/workflows/scripts/install-and-build-with-sdk.sh --android --flags="$BUILD_FLAGS" --build-command="${{ inputs.android_sdk_build_command }}" --android-sdk-triple=${{ join(fromJson(inputs.android_sdk_triples), ' --android-sdk-triple=') }} --android-ndk-version="${{ matrix.ndk_version }}" ${{ matrix.swift_version }}
- name: Enable KVM and free disk space
if: ${{ inputs.enable_android_sdk_checks }}
run: |
# enable KVM on Linux for tests, else error on emulator launch:
# CPU acceleration status: This user doesn't have permissions to use KVM (/dev/kvm).
echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules
sudo udevadm control --reload-rules
sudo udevadm trigger --name-match=kvm

# need to free space or the emulator runs out
sudo rm -rf /opt/microsoft /opt/google /opt/az /opt/ghc /usr/share/dotnet /usr/local/share/boost /opt/hostedtoolcache /usr/local/share/chromium
df -h
- name: Install Android Emulator and run tests
if: ${{ inputs.enable_android_sdk_checks }}
shell: bash
run: |
${{ inputs.android_sdk_pre_build_command }}
${{ steps.script_path.outputs.root }}/.github/workflows/scripts/android/android-emulator-tests.sh --android-sdk-triple=${{ join(fromJson(inputs.android_sdk_triples), ' --android-sdk-triple=') }}

windows-build:
name: Windows (${{ matrix.swift_version }} - ${{ matrix.os_version }})
Expand Down
Loading