Skip to content

Attempt to re-use existing Android emulator configuration #340

Attempt to re-use existing Android emulator configuration

Attempt to re-use existing Android emulator configuration #340

Workflow file for this run

name: sdk-install-demo ci
on:
push:
branches: [ main ]
workflow_dispatch:
pull_request:
schedule:
- cron: '0 13 * * *'
jobs:
install-sdk:
strategy:
fail-fast: false
matrix:
include:
- name: 'macOS 15 X64 API 28'
os: 'macos-15-intel'
ANDROID_API: 28
NDK_VERSION: 'r27d'
EMULATOR_ARCH: 'x86_64'
EMULATOR_ARCH_TRIPLE: 'x86_64'
- name: 'Ubuntu X64 API 28'
os: 'ubuntu-latest'
ANDROID_API: 28
NDK_VERSION: 'r28c'
EMULATOR_ARCH: 'x86_64'
EMULATOR_ARCH_TRIPLE: 'x86_64'
- name: 'macOS 15 X64 API 30'
os: 'macos-15-intel'
ANDROID_API: 30
NDK_VERSION: 'r27d'
EMULATOR_ARCH: 'x86_64'
EMULATOR_ARCH_TRIPLE: 'x86_64'
- name: 'Ubuntu X64 API 35'
os: 'ubuntu-latest'
ANDROID_API: 35
NDK_VERSION: 'r29'
EMULATOR_ARCH: 'x86_64'
EMULATOR_ARCH_TRIPLE: 'x86_64'
# Android SDK for Linux is only x86_64
#- name: 'Ubuntu ARM API 28'
# os: 'ubuntu-24.04-arm'
# ANDROID_API: 28
# EMULATOR_ARCH: 'arm64-v8a'
# EMULATOR_ARCH_TRIPLE: 'aarch64'
# Cannot test on ARM macOS because Android emulator required nested
# virtualization
#- name: 'macOS 15 ARM'
# os: 'macos-15'
# ANDROID_API: 28
# EMULATOR_ARCH: 'arm64-v8a'
# EMULATOR_ARCH_TRIPLE: 'aarch64'
runs-on: ${{ matrix.os }}
steps:
- name: Free Disk Space
if: runner.os == 'Linux'
run: |
sudo rm -rf /usr/share/dotnet
sudo rm -rf /opt/ghc
sudo rm -rf "/usr/local/share/boost"
sudo rm -rf "$AGENT_TOOLSDIRECTORY"
- name: Setup Android Environment
run: |
echo "$ANDROID_HOME/cmdline-tools/latest/bin" >> $GITHUB_PATH
echo "$ANDROID_HOME/platform-tools" >> $GITHUB_PATH
echo "$ANDROID_HOME/build-tools/latest" >> $GITHUB_PATH
echo "$ANDROID_HOME/tools" >> $GITHUB_PATH
echo "$ANDROID_HOME/emulator" >> $GITHUB_PATH
echo "ANDROID_API=${{ matrix.ANDROID_API }}" >> $GITHUB_ENV
echo "ANDROID_EMULATOR_ARCH=${{ matrix.EMULATOR_ARCH }}" >> $GITHUB_ENV
echo "ANDROID_EMULATOR_ARCH_TRIPLE=${{ matrix.EMULATOR_ARCH_TRIPLE }}" >> $GITHUB_ENV
echo "ANDROID_TARGET=default" >> $GITHUB_ENV
#echo "ANDROID_PROFILE=Pixel 6" >> $GITHUB_ENV
echo "ANDROID_PROFILE=Nexus 10" >> $GITHUB_ENV
echo "ANDROID_CHANNEL=3" >> $GITHUB_ENV
echo "ANDROID_NDK_VERSION=${{ matrix.NDK_VERSION }}" >> $GITHUB_ENV
if [[ "${RUNNER_OS}" == "Linux" ]]; then
# needed for Linux or else the emulator will be created in
# ~/.android/avd but it will be sought in ~/.config/.android/avd
echo "ANDROID_AVD_HOME=${XDG_CONFIG_HOME:-$HOME}/.android/avd" >> $GITHUB_ENV
# enable KVM on Linux, 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
fi
- name: Create and Launch Android Emulator
run: |
EMULATOR_SPEC="system-images;android-${ANDROID_API};default;${ANDROID_EMULATOR_ARCH}"
EMULATOR_NAME="swiftemu"
sdkmanager --list_installed
yes | sdkmanager --licenses > /dev/null
sdkmanager --install "${EMULATOR_SPEC}" "emulator" "platform-tools" "platforms;android-${ANDROID_API}"
avdmanager create avd -n "${EMULATOR_NAME}" -k "${EMULATOR_SPEC}" --device "${ANDROID_PROFILE}"
emulator -list-avds
# launch the emulator in the background; we will cat the logs at the end
nohup emulator -memory 4096 -avd "${EMULATOR_NAME}" -wipe-data -no-window -no-snapshot -noaudio -no-boot-anim 2>&1 > emulator.log &
adb logcat 2>&1 > logcat.log &
- name: Install Prerequisites
run: |
if [[ "${RUNNER_OS}" == "Linux" ]]; then
# libcurl4-openssl-dev needed for host toolchain
sudo apt-get -y install libcurl4-openssl-dev
fi
# swiftly install instructions from https://www.swift.org/install/linux/
- name: Install Swiftly
run: |
if [[ "${RUNNER_OS}" == "macOS" ]]; then
curl -fsSL -O https://download.swift.org/swiftly/darwin/swiftly.pkg
installer -pkg swiftly.pkg -target CurrentUserHomeDirectory
~/.swiftly/bin/swiftly init --quiet-shell-followup --skip-install
. "${SWIFTLY_HOME_DIR:-$HOME/.swiftly}/env.sh"
elif [[ "${RUNNER_OS}" == "Linux" ]]; then
curl -fsSL -O https://download.swift.org/swiftly/linux/swiftly-$(uname -m).tar.gz
tar zxf swiftly-$(uname -m).tar.gz
./swiftly init --quiet-shell-followup --skip-install
. "${SWIFTLY_HOME_DIR:-$HOME/.local/share/swiftly}/env.sh"
else
echo "Error: unsupported OS: ${RUNNER_OS}"
exit 1
fi
hash -r
echo "${SWIFTLY_BIN_DIR}" >> "${GITHUB_PATH}"
- name: Get Latest Toolchain Info
run: |
sdk_json=$(curl -fsSL "https://www.swift.org/api/v1/install/dev/main/android-sdk.json") || fatal "Failed to fetch android-sdk development snapshots"
download=$(echo "$sdk_json" | jq -r '.[0].download')
snapshot_tag=$(echo "$sdk_json" | jq -r '.[0].dir')
checksum=$(echo "$sdk_json" | jq -r '.[0].checksum')
echo "SWIFT_TOOLCHAIN_VERSION=${snapshot_tag}" >> ${GITHUB_ENV}
echo "SWIFT_ANDROID_SDK_VERSION=${snapshot_tag}" >> ${GITHUB_ENV}
echo "SWIFT_ANDROID_SDK_DOWNLOAD=${download}" >> ${GITHUB_ENV}
echo "SWIFT_ANDROID_SDK_CHECKSUM=${checksum}" >> ${GITHUB_ENV}
- name: Install Swift Host Toolchain
run: swiftly install --use "${SWIFT_TOOLCHAIN_VERSION}"
- name: Install Swift SDK for Android
run: swiftly run swift sdk install https://download.swift.org/development/android-sdk/${SWIFT_ANDROID_SDK_VERSION}/${SWIFT_ANDROID_SDK_DOWNLOAD} --checksum ${SWIFT_ANDROID_SDK_CHECKSUM}
- name: List Swift SDKs
run: |
swiftly run swift sdk list
swiftly run swift --version
swiftly run swift --version +"${SWIFT_TOOLCHAIN_VERSION}"
- name: Setup Android NDK
run: |
# Only install the NDK if it is overridden
# Otherwise use the runner-installed NDK
if [[ ! -z "${ANDROID_NDK_VERSION}" ]]; then
mkdir ~/android-ndk
cd ~/android-ndk
curl -fsSLO https://dl.google.com/android/repository/android-ndk-${ANDROID_NDK_VERSION}-$(uname -s).zip
unzip -q android-ndk-${ANDROID_NDK_VERSION}-*.zip
echo "ANDROID_NDK_HOME=${PWD}/android-ndk-${ANDROID_NDK_VERSION}" >> $GITHUB_ENV
fi
# note that we must *not* have ANDROID_NDK_ROOT set!
# https://github.com/swiftlang/swift-driver/pull/1879
echo "ANDROID_NDK_ROOT=" >> $GITHUB_ENV
- name: Setup Swift SDK for Android
run: |
cd ~/Library/org.swift.swiftpm || cd ${XDG_CONFIG_HOME}/swiftpm || cd ~/.local/swiftpm || cd ~/.swiftpm
./swift-sdks/${SWIFT_ANDROID_SDK_VERSION}*.artifactbundle/swift-android/scripts/setup-android-sdk.sh
cd ./swift-sdks/${SWIFT_ANDROID_SDK_VERSION}*.artifactbundle
echo "SWIFT_ANDROID_SDK_HOME=${PWD}" >> $GITHUB_ENV
- name: Build Swift Executable for Android
run: |
mkdir hello
cd hello
swiftly run swift package init --type executable
swiftly run swift build --swift-sdk "${ANDROID_EMULATOR_ARCH_TRIPLE}-unknown-linux-android${ANDROID_API}" --static-swift-stdlib
file .build/debug/hello
- name: Wait for Android Emulator
run: adb wait-for-any-device
timeout-minutes: 5
- name: Check Android Emulator
run: adb shell 'echo Hello Android!'
- name: Run Swift Executable on Android Emulator
run: |
cd hello
adb push .build/debug/hello /data/local/tmp
adb push $ANDROID_NDK_HOME/toolchains/llvm/prebuilt/*/sysroot/usr/lib/${ANDROID_EMULATOR_ARCH_TRIPLE}-linux-android/libc++_shared.so /data/local/tmp/
adb shell /data/local/tmp/hello
- name: Create run-tests script
run: |
cat > run-tests.sh << "EOF"
#!/bin/bash -ex
ORG=$(echo "${1}" | cut -d '/' -f 1)
PACKAGE=$(echo "${1}" | cut -d '/' -f 2)
git clone https://github.com/${ORG}/${PACKAGE}
cd ${PACKAGE}
TRIPLE="${ANDROID_EMULATOR_ARCH_TRIPLE}-unknown-linux-android${ANDROID_API}"
swiftly run swift build --swift-sdk "${TRIPLE}" --build-tests +"${SWIFT_TOOLCHAIN_VERSION}"
STAGING=".build/android-test-${PACKAGE}/"
rm -rf "${STAGING}"
mkdir "${STAGING}"
cp -a .build/"${TRIPLE}"/"${PACKAGE}"PackageTests.xctest "${STAGING}"
cp -a .build/"${TRIPLE}"/*.resources "${STAGING}"
# for the common case of tests referencing their own resources
cp -a Tests "${STAGING}"
cp -a $ANDROID_NDK_HOME/toolchains/llvm/prebuilt/*/sysroot/usr/lib/${ANDROID_EMULATOR_ARCH_TRIPLE}-linux-android/libc++_shared.so "${STAGING}"
cp -a "${SWIFT_ANDROID_SDK_HOME}"/swift-android/swift-resources/usr/lib/swift-${ANDROID_EMULATOR_ARCH_TRIPLE}/android/*.so /data/local/tmp/
cd .build/
STAGING_BASE=$(basename "${STAGING}")
zip -r "${STAGING_BASE}.zip" "${STAGING_BASE}"
adb push "${STAGING_BASE}.zip" /data/local/tmp/
adb shell unzip -d /data/local/tmp/ /data/local/tmp/"${STAGING_BASE}.zip"
adb shell /data/local/tmp/"${STAGING_BASE}"/"${PACKAGE}"PackageTests.xctest
EOF
chmod +x run-tests.sh
cat run-tests.sh
- name: Run swift-collections tests
# too slow
if: false
run: ./run-tests.sh apple/swift-collections
- name: Run swift-numerics tests
run: ./run-tests.sh apple/swift-numerics
- name: Run swift-algorithms tests
run: ./run-tests.sh apple/swift-algorithms
- name: Run swift-atomics tests
run: ./run-tests.sh apple/swift-atomics
- name: Run swift-system tests
run: ./run-tests.sh apple/swift-system
- name: Run swift-crypto tests
run: ./run-tests.sh apple/swift-crypto
- name: Run swift-nio tests
if: false
run: ./run-tests.sh apple/swift-nio
- name: Run swift-argument-parser tests
# needs local files:
# error: MathExampleTests.testMath_AddHelp : failed - No executable at '/data/local/tmp/math'.
if: false
run: ./run-tests.sh apple/swift-argument-parser
- name: Show Android Emulator Log
if: always()
run: cat emulator.log
- name: Show Android Logcat Output
if: always()
run: cat logcat.log