-
Notifications
You must be signed in to change notification settings - Fork 33
Add enable_android_sdk_checks option for Android emulator testing #215
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
Changes from all commits
d8ce023
b7d0a75
51883a5
427b18b
c082391
1d76ea7
b7e9a5d
1e9bf25
b19a2f9
4312ece
728894a
cb08f99
4d8249c
bad3c64
06d6ff7
3c29f25
988484d
cbf8812
3620be4
97923bd
0c52793
8b7cdf5
b363415
9c38d01
4031eee
560f60a
b09c11b
1ef5eb5
8362509
f0a2e91
c97c292
6932225
88e55ce
dedd2a8
67efdb9
1889eba
5c112a8
8551570
a714374
1c088a2
345a468
c299a2d
8204a10
5b015d8
d0d4b4c
bf04475
b0b4595
b0fc274
6433df2
bbc4a12
4f6703e
707adbd
6cab1f3
e910952
6563fe6
7d58ee6
c705e86
e56b090
25c305b
4a197ee
6841907
4a2a9c7
a86bcba
ca5f01d
1add73b
1ecdca9
ea1eb0a
4411d7e
a0c6393
a5a207b
edb1240
77fd5d6
4f63ef2
fe29bf4
0cc3112
c09530d
2f1c57f
614fb27
5adabf6
4413049
89d7535
c0e37d7
15a740d
5f4d9bf
2eb42fe
8a7fc1c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| 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/}" | ||
|
|
||
| # extract the build arch from the beginning of the triple | ||
| ANDROID_EMULATOR_ARCH="${ANDROID_SDK_TRIPLE/-unknown-linux-android*/}" | ||
marcprux marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| # x86_64=x86_64, armv7=arm | ||
| ANDROID_EMULATOR_ARCH_TRIPLE="${ANDROID_EMULATOR_ARCH}" | ||
|
|
||
marcprux marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| 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 -lq '\.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" | ||
|
|
||
| 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 ]" | ||
marcprux marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| log "Run Swift package tests" | ||
|
|
||
| # run the test executable | ||
| adb shell "${TEST_SHELL}" | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -149,7 +149,7 @@ on: | |
| default: "swift build" | ||
| android_sdk_triples: | ||
| type: string | ||
| description: "The triples to use when building with the Swift SDK for Android" | ||
| description: "The triples to use when building with the Swift SDK for Android. The final triple in the list will be used for the emulator testing and should match the host architecture." | ||
| default: "[\"aarch64-unknown-linux-android28\", \"x86_64-unknown-linux-android28\"]" | ||
| android_ndk_versions: | ||
| type: string | ||
|
|
@@ -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" | ||
|
|
@@ -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 | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Don't we lose some level of coverage here by removing all the SDK builds from docker? Previously we were testing the static SDK builds on a number of different OS's using docker (whatever the repo owner specified with Admittedly I'm not Sure how much value that created, maybe that coverage was minimal?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I feel like it was overkill, since we are cross-compiling to a different target. It is theoretically possible that some host toolchain issue might get caught by this, but I figured that all the other host toolchains matrix variants that are running in Docker (including the cross-compilation provided by the static SDK) would catch these build issues. Besides, we can't run the Android emulator tests in Docker due to nested virtualization, so we'd only be able to see if the package builds, not if it passes the tests. |
||
| 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: | | ||
|
|
@@ -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 }}) | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.