Skip to content

Cache latest Android NDK sysroot on the CI and update some Foundation patches #2128

Cache latest Android NDK sysroot on the CI and update some Foundation patches

Cache latest Android NDK sysroot on the CI and update some Foundation patches #2128

Workflow file for this run

name: SDKs
on:
pull_request:
schedule:
- cron: '0 9 * * *'
jobs:
get-latest-toolchain:
runs-on: ubuntu-latest
strategy:
matrix:
version: [release, devel, trunk]
outputs:
release-version: ${{ steps.check.outputs.release-tag }}
devel-version: ${{ steps.check.outputs.devel-tag }}
trunk-version: ${{ steps.check.outputs.trunk-tag }}
new-devel-tag: ${{ steps.download.outputs.devel-updated == 'true' }}
steps:
- name: Check for latest Swift ${{ matrix.version }} toolchain
id: check
run: |
if [ ${{ matrix.version }} = 'release' ]; then
LATEST_TOOLCHAIN_VERSION=$(curl -sL https://github.com/apple/swift/releases | grep -m1 swift-6.0 | cut -d- -f2)
SWIFT_TAG="swift-${LATEST_TOOLCHAIN_VERSION}-RELEASE"
echo "release-tag=$SWIFT_TAG" >> $GITHUB_OUTPUT
elif [ ${{ matrix.version }} = 'devel' ]; then
LATEST_TOOLCHAIN_VERSION=$(curl -sL https://github.com/apple/swift/tags | grep -m1 swift-6.0-DEV | cut -d- -f8-10)
SWIFT_TAG="swift-6.0-DEVELOPMENT-SNAPSHOT-${LATEST_TOOLCHAIN_VERSION}-a"
echo "devel-tag=$SWIFT_TAG" >> $GITHUB_OUTPUT
else
LATEST_TOOLCHAIN_VERSION=$(curl -sL https://github.com/apple/swift/tags | grep -m1 swift-DEV | cut -d- -f7-9)
SWIFT_TAG="swift-DEVELOPMENT-SNAPSHOT-${LATEST_TOOLCHAIN_VERSION}-a"
echo "trunk-tag=$SWIFT_TAG" >> $GITHUB_OUTPUT
fi
echo "latest-tag=$SWIFT_TAG" >> $GITHUB_OUTPUT
- name: Get cached Ubuntu toolchain
id: cache-toolchain-ubuntu
uses: actions/cache@v4
with:
path: ~/${{ steps.check.outputs.latest-tag }}-ubuntu22.04.tar.gz
key: swift-ubuntu-22.04-${{ steps.check.outputs.latest-tag }}-toolchain
lookup-only: true
- name: Get cached macOS toolchain
id: cache-toolchain-macos
uses: actions/cache@v4
with:
path: ~/${{ steps.check.outputs.latest-tag }}-osx.pkg
key: swift-macos-13-${{ steps.check.outputs.latest-tag }}-toolchain
lookup-only: true
- name: Download toolchain
id: download
if: ${{ steps.cache-toolchain-ubuntu.outputs.cache-hit != 'true' || steps.cache-toolchain-macos.outputs.cache-hit != 'true' }}
run: |
SWIFT_TAG="${{ steps.check.outputs.latest-tag }}"
if [ ${{ matrix.version }} = 'release' ]; then
SWIFT_BRANCH="swift-$(echo ${{ steps.check.outputs.release-tag }} | cut -d- -f2)-release"
elif [ ${{ matrix.version }} = 'devel' ]; then
SWIFT_BRANCH="swift-6.0-branch"
echo "devel-updated='true'" >> $GITHUB_OUTPUT
else
SWIFT_BRANCH="development"
fi
cd
if [[ "${{ steps.cache-toolchain-macos.outputs.cache-hit }}" != 'true' ]]; then
wget -q https://download.swift.org/$SWIFT_BRANCH/xcode/$SWIFT_TAG/$SWIFT_TAG-osx.pkg
echo "downloaded latest macOS toolchain: ${SWIFT_TAG}"
fi
if [[ "${{ steps.cache-toolchain-ubuntu.outputs.cache-hit }}" != 'true' ]]; then
wget -q https://download.swift.org/$SWIFT_BRANCH/ubuntu2204/$SWIFT_TAG/$SWIFT_TAG-ubuntu22.04.tar.gz
echo "downloaded latest Ubuntu toolchain: ${SWIFT_TAG}"
fi
- name: Get cached Android NDK sysroot and runtime libraries
id: cache-ndk
uses: actions/cache@v4
with:
path: ~/android-sysroot.tar.xz
key: android-ndk-27b
lookup-only: true
- name: Download Android NDK if not cached before
if: ${{ steps.cache-ndk.outputs.cache-hit != 'true' }}
run: |
wget -q https://dl.google.com/android/repository/android-ndk-r27b-linux.zip
if [ "$(sha1sum android-ndk-r27b-linux.zip | cut -f1 -d" ")" != '6fc476b2e57d7c01ac0c95817746b927035b9749' ]; then
echo "NDK checksum didn't match"
exit 1
fi
unzip -q android-ndk-r27b-linux.zip
mv android-ndk-r27b/toolchains/llvm/prebuilt/linux-x86_64/sysroot .
rm -r sysroot/usr/{include,lib}/{i686,riscv64}-linux-android
mv android-ndk-r27b/toolchains/llvm/prebuilt/linux-x86_64/lib/clang/*/lib/linux sysroot
rm -r sysroot/linux/*{i[36]86,riscv64}*
tar cJf ~/android-sysroot.tar.xz sysroot
build-sdk-and-tests:
runs-on: ${{ matrix.os }}
needs: get-latest-toolchain
strategy:
fail-fast: false
matrix:
version: [release, devel, trunk]
arch: [x86_64, aarch64, armv7]
os: [ubuntu-22.04, macos-13]
exclude:
- os: macos-13
version: trunk
- os: macos-13
version: ${{ needs.get-latest-toolchain.outputs.new-devel-tag == 'true' && 'devel' || 'none' }}
env:
ANDROID_API_LEVEL: 24
BUNDLE_VERSION: 0.1
NDK_VERSION: 27b
steps:
- name: Extract the latest version string
id: version
run: |
if [[ ${{ matrix.version }} = 'release' ]]; then
TAG="${{ needs.get-latest-toolchain.outputs.release-version }}"
elif [ ${{ matrix.version }} = 'devel' ]; then
TAG="${{ needs.get-latest-toolchain.outputs.devel-version }}"
else
TAG="${{ needs.get-latest-toolchain.outputs.trunk-version }}"
fi
echo "tag=$TAG" >> $GITHUB_OUTPUT
KEY="$TAG-${{ matrix.arch }}-ndk-${NDK_VERSION}-arch-sdk"
echo "arch-key=$KEY" >> $GITHUB_OUTPUT
echo "key=$TAG-ndk-${NDK_VERSION}-bundle" >> $GITHUB_OUTPUT
if ${{ matrix.arch == 'x86_64' }}; then
echo "aarch64-key=${KEY/x86_64/aarch64}" >> $GITHUB_OUTPUT
echo "arm-key=${KEY/x86_64/armv7}" >> $GITHUB_OUTPUT
fi
- name: Get cached SDK bundle
id: cache-bundle
uses: actions/cache@v4
if: ${{ matrix.version != 'trunk' }}
with:
path: ~/${{ steps.version.outputs.tag }}-android-${{ env.ANDROID_API_LEVEL }}-${{ env.BUNDLE_VERSION }}.artifactbundle.tar.gz
key: ${{ steps.version.outputs.key }}
- name: Get cached ${{ matrix.arch }} SDK otherwise
id: cache-sdk
uses: actions/cache/restore@v4
if: ${{ steps.cache-bundle.outputs.cache-hit != 'true' }}
with:
path: ~/swift-${{ matrix.version }}-android-${{ matrix.arch }}-*-sdk.tar.xz
key: ${{ steps.version.outputs.arch-key }}
- name: Clone
uses: actions/checkout@v4
with:
path: sdk-config
- name: Get cached ${{ matrix.os }} ${{ steps.version.outputs.tag }} toolchain
id: cache-toolchain
uses: actions/cache/restore@v4
with:
path: ~/${{ steps.version.outputs.tag }}-${{ startsWith(matrix.os, 'macos') && 'osx.pkg' || 'ubuntu22.04.tar.gz' }}
key: swift-${{ matrix.os }}-${{ steps.version.outputs.tag }}-toolchain
fail-on-cache-miss: true
- name: Setup Swift Toolchain
env:
SWIFT_TAG: ${{ steps.version.outputs.tag }}
run: |
set -x
cd sdk-config
if ${{ startsWith(matrix.os, 'macos') }}; then
mkdir ${SWIFT_TAG}
pushd ${SWIFT_TAG}
xar -x -C . -f ~/${SWIFT_TAG}-osx.pkg
tar xz -C . -f ${SWIFT_TAG}-osx-package.pkg/Payload
TOOLCHAIN=${PWD}/usr
popd
elif ${{ startsWith(matrix.os, 'ubuntu') }}; then
tar xf ~/$SWIFT_TAG-ubuntu22.04.tar.gz
TOOLCHAIN=${PWD}/$SWIFT_TAG-ubuntu22.04/usr
fi
if [ ${{ matrix.version }} == 'release' ]; then
perl -pi -e 's%canImport\(Bionic%canImport\(Android%' $TOOLCHAIN/bin/swift-package
perl -pi -e 's%import Bionic%import Android%' $TOOLCHAIN/bin/swift-package
perl -pi -e 's%TSCBasic, would be%TSCBasic, would %' $TOOLCHAIN/bin/swift-package
fi
echo "TOOLCHAIN=${TOOLCHAIN}" >> $GITHUB_ENV
${TOOLCHAIN}/bin/swift --version
- name: Build Swift ${{ matrix.version }} Android SDK if not the latest
# build-script currently only works on ubuntu
if: ${{ (steps.cache-bundle.outputs.cache-hit != 'true') && (steps.cache-sdk.outputs.cache-hit != 'true') && startsWith(matrix.os, 'ubuntu') }}
env:
SWIFT_TAG: ${{ steps.version.outputs.tag }}
ANDROID_ARCH: ${{ matrix.arch }}
run: |
set -x
if ${{ startsWith(matrix.os, 'macos') }}; then
brew install ninja patchelf
elif ${{ startsWith(matrix.os, 'ubuntu') }}; then
sudo apt install ninja-build
fi
cd sdk-config
BUILD_SWIFT_PM=1 ${TOOLCHAIN}/bin/swift get-packages-and-swift-source.swift
SDK_NAME=$(ls | grep swift-${{ matrix.version }}-android-${{ matrix.arch }})
SDK=`pwd`/$SDK_NAME
git apply swift-android.patch swift-android-foundation.patch swift-android-ci.patch swift-crypto.patch swift-system.patch
if [ ${{ matrix.version }} = 'trunk' ]; then
git apply swift-android-ci-trunk.patch swift-android-foundation-trunk.patch
else
git apply swift-android-ci-except-trunk.patch swift-android-foundation-except-trunk.patch
git apply -C1 swift-android-foundation-armv7-except-trunk.patch
if [ ${{ matrix.version }} = 'devel' ]; then
perl -pi -e 's%Musl%Bionic%g' swift-corelibs-foundation/Sources/Testing/Testing.swift
else
git apply swift-android-foundation-release.patch
fi
fi
perl -pi -e 's%r26%ndk/27%' swift/stdlib/cmake/modules/AddSwiftStdlib.cmake
perl -pi -e "s%/data/data/com.termux/files%$SDK%g" $SDK/usr/lib/pkgconfig/sqlite3.pc
perl -pi -e 's%String\(cString: getpass%\"fake\" //%' swiftpm/Sources/PackageRegistryCommand/PackageRegistryCommand+Auth.swift
./swift/utils/build-script -RA --skip-build-cmark --build-llvm=0 --android --android-ndk $ANDROID_NDK_LATEST_HOME --android-arch ${{ matrix.arch }} --android-api-level $ANDROID_API_LEVEL --build-swift-tools=0 --native-swift-tools-path=${TOOLCHAIN}/bin --native-clang-tools-path=${TOOLCHAIN}/bin --cross-compile-hosts=android-${{ matrix.arch }} --cross-compile-deps-path=$SDK --skip-local-build --build-swift-static-stdlib --xctest --skip-early-swift-driver --install-swift --install-libdispatch --install-foundation --install-xctest --install-destdir=$SDK --swift-install-components='clang-resource-dir-symlink;license;stdlib;sdk-overlay' --cross-compile-append-host-target-to-destdir=False -b -p --install-llbuild --sourcekit-lsp --skip-early-swiftsyntax
cp $ANDROID_NDK_LATEST_HOME/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/$(echo ${{ matrix.arch }} | sed "s/v7//")-linux-android*/libc++_shared.so $SDK/usr/lib
patchelf --set-rpath \$ORIGIN $SDK/usr/lib/swift/android/lib[dFXs]*.so
# Remove executables and unused toolchain headers/libraries
pushd $SDK_NAME/usr
rm -r bin lib/swift/pm lib/libsqlite3.so lib/lib{curses,ncurses}.so lib/terminfo share/{tabset,terminfo}
mv include/curl include/libxml2 include/spawn.h .
rm -r include/*
mv curl libxml2 spawn.h include/
popd
tar cJf ~/$SDK_NAME.tar.xz $SDK_NAME
rm -rf build/ $SDK_NAME llvm-project/
- name: Cache newly built ${{ matrix.version }} ${{ matrix.arch }} SDK on linux
if: ${{ (steps.cache-bundle.outputs.cache-hit != 'true') && (steps.cache-sdk.outputs.cache-hit != 'true') && startsWith(matrix.os, 'ubuntu') }}
uses: actions/cache/save@v4
with:
path: ~/swift-${{ matrix.version }}-android-${{ matrix.arch }}-*-sdk.tar.xz
key: ${{ steps.version.outputs.arch-key }}
- name: Setup Swift ${{ matrix.version }} Android SDK
id: sdk-setup
run: |
set -x
cd sdk-config
ARCH_TARGET="${{ matrix.arch }}-unknown-linux-android${ANDROID_API_LEVEL}"
if ${{ matrix.arch == 'armv7' }}; then
ARCH_TARGET="armv7-unknown-linux-androideabi${ANDROID_API_LEVEL}"
fi
if ${{ steps.cache-bundle.outputs.cache-hit != 'true' }}; then
SDK_PATH=$(basename ~/swift-${{ matrix.version }}-android-${{ matrix.arch }}*-sdk.tar.xz .tar.xz)
tar xf ~/$SDK_PATH.tar.xz
# fix the clang symlink
ls -la ${SDK_PATH}/usr/lib/swift/clang
rm -vf ${SDK_PATH}/usr/lib/swift/clang
# Swift 5.10: usr/lib/clang/15.0.0 Trunk and Devel: usr/lib/clang/17
${TOOLCHAIN}/bin/clang --version
ln -sfv ${TOOLCHAIN}/lib/clang/* ${SDK_PATH}/usr/lib/swift/clang
ls -l ${SDK_PATH}/usr/lib/swift/clang/lib/
ARCH_JSON="$PWD/android-${{ matrix.arch }}.json"
NDK_PREBUILT=${ANDROID_NDK_LATEST_HOME}/toolchains/llvm/prebuilt/${{ startsWith(matrix.os, 'macos') && 'darwin' || 'linux' }}-x86_64
if ${{ startsWith(matrix.os, 'macos') }}; then
cp -r ${NDK_PREBUILT}/lib/clang/*/lib/linux ${SDK_PATH}/usr/lib/swift/clang/lib
else
cp -r ${NDK_PREBUILT}/lib/clang/*/lib/linux/* ${SDK_PATH}/usr/lib/swift/clang/lib/linux
fi
cat > ${ARCH_JSON} << EOF
{
"schemaVersion": "4.0",
"targetTriples": {
"${ARCH_TARGET}": {
"sdkRootPath": "${NDK_PREBUILT}/sysroot",
"swiftResourcesPath": "${SDK_PATH}/usr/lib/swift",
}
}
}
EOF
cat ${ARCH_JSON}
FLAGS="--destination ${ARCH_JSON}"
if ${{ matrix.version == 'trunk' }}; then
ln -sf $PWD/$SDK_PATH/usr/lib/swift $NDK_PREBUILT/sysroot/usr/lib/swift
FLAGS="-Xswiftc -use-ld=lld --destination ${ARCH_JSON}"
fi
else
${TOOLCHAIN}/bin/swift sdk install ~/${{ steps.version.outputs.tag }}-android-*.artifactbundle.tar.gz
${TOOLCHAIN}/bin/swift sdk configure --show-configuration ${{ steps.version.outputs.tag }}-android-${ANDROID_API_LEVEL}-${BUNDLE_VERSION} $ARCH_TARGET
FLAGS="--swift-sdk ${ARCH_TARGET}"
fi
echo "SWIFTPM_FLAGS=${FLAGS}" >> $GITHUB_ENV
- name: Get Swift Argument Parser package
uses: actions/checkout@v4
with:
repository: apple/swift-argument-parser
path: swift-argument-parser
- name: Build Swift Argument Parser package
run: |
cd swift-argument-parser
rm Examples/count-lines/CountLines.swift Tools/changelog-authors/*.swift
${TOOLCHAIN}/bin/swift build --build-tests ${SWIFTPM_FLAGS}
- name: Get Swift crypto package
uses: actions/checkout@v4
with:
repository: apple/swift-crypto
path: swift-crypto
- name: Build Swift crypto package
run: |
git apply sdk-config/swift-crypto.patch
cd swift-crypto
perl -pi -e 's%\\\\(testsDirectory)/.*Vectors%/data/local/tmp/pack/crypto-vectors%' Tests/{Crypto,_CryptoExtras}Tests/Utils/{RFCVector,Wycheproof}.swift
perl -pi -e 's%#file%"/data/local/tmp/pack/crypto-vectors"%;s%../_CryptoExtrasVectors/%%' Tests/_CryptoExtrasTests/TestRSABlindSigning.swift
${TOOLCHAIN}/bin/swift build --build-tests ${SWIFTPM_FLAGS}
- name: Get Swift NIO package
uses: actions/checkout@v4
with:
repository: apple/swift-nio
path: swift-nio
- name: Build Swift NIO package
run: |
cd swift-nio
git apply ../sdk-config/swift-nio-disable-ecn-tests.patch ../sdk-config/swift-nio-filesystem.patch ../sdk-config/swift-nio-ndk27.patch
${TOOLCHAIN}/bin/swift package update
cd .build/checkouts/
patch -p1 < ../../../sdk-config/swift-system.patch
cd ../..
${TOOLCHAIN}/bin/swift build --build-tests ${SWIFTPM_FLAGS}
- name: Get Swift Numerics package
uses: actions/checkout@v4
with:
repository: apple/swift-numerics
path: swift-numerics
- name: Build Swift Numerics package
run: |
cd swift-numerics
${TOOLCHAIN}/bin/swift build --build-tests ${SWIFTPM_FLAGS}
- name: Get Swift System package
uses: actions/checkout@v4
with:
repository: apple/swift-system
path: swift-system
- name: Build Swift System package
run: |
git apply sdk-config/swift-system-tests.patch
cd swift-system
${TOOLCHAIN}/bin/swift build --build-tests ${SWIFTPM_FLAGS}
- name: Get Swift Collections package
uses: actions/checkout@v4
with:
repository: apple/swift-collections
path: swift-collections
- name: Build Swift Collections package
run: |
cd swift-collections
${TOOLCHAIN}/bin/swift build --build-tests ${SWIFTPM_FLAGS}
- name: Get Swift Atomics package
uses: actions/checkout@v4
with:
repository: apple/swift-atomics
path: swift-atomics
ref: 1.1.0
- name: Get Swift NIO SSH package
uses: actions/checkout@v4
with:
repository: apple/swift-nio-ssh
path: sns
- name: Build Swift NIO SSH package
run: |
cd sns
perl -pi -e 's%url: .*swift-([a-z]*)\.git.*$%path: \"../swift-\1\"),%g' Package.swift
${TOOLCHAIN}/bin/swift build --build-tests ${SWIFTPM_FLAGS}
- name: Get Swift NIO SSL package
uses: actions/checkout@v4
with:
repository: apple/swift-nio-ssl
path: snl
- name: Build Swift NIO SSL package
run: |
cd snl
git apply ../sdk-config/swift-nio-ssl-test.patch
SWIFTCI_USE_LOCAL_DEPS=1 ${TOOLCHAIN}/bin/swift build --build-tests ${SWIFTPM_FLAGS}
- name: Get Yams package
uses: actions/checkout@v4
with:
repository: jpsim/Yams
path: yams
- name: Build Yams package
run: |
cd yams
perl -pi -e 's% fixturesDirectory + \"/SourceKitten#289% \"/data/local/tmp/pack%' Tests/YamsTests/PerformanceTests.swift
${TOOLCHAIN}/bin/swift build --build-tests ${SWIFTPM_FLAGS}
- name: Get Swift NIO HTTP/2 package
uses: actions/checkout@v4
with:
repository: apple/swift-nio-http2
path: snh
- name: Build Swift NIO HTTP/2 package
if: ${{ matrix.arch != 'armv7' }}
run: |
cd snh
git apply ../sdk-config/swift-nio-http2-test.patch
perl -pi -e 's%url: .*swift-([a-z]*)\.git.*$%path: \"../swift-\1\"),%g' Package.swift
${TOOLCHAIN}/bin/swift build --build-tests ${SWIFTPM_FLAGS}
- name: Get Swift Algorithms package
uses: actions/checkout@v4
with:
repository: apple/swift-algorithms
path: sa
- name: Build Swift Algorithms package
run: |
cd sa
perl -pi -e 's%url: .*$%path: \"../swift-numerics\"),%' Package.swift
${TOOLCHAIN}/bin/swift build --build-tests ${SWIFTPM_FLAGS}
- name: Get cached Termux debug app for NIO tests
if: ${{ matrix.arch == 'x86_64' }}
id: cache-termux
uses: actions/cache@v4
with:
path: ~/termux-debug.apk
key: termux-app
- name: Get Termux debug app if not cached
if: ${{ (matrix.arch == 'x86_64') && (steps.cache-termux.outputs.cache-hit != 'true') }}
run: wget -O ~/termux-debug.apk https://github.com/termux/termux-app/releases/download/v0.118.0/termux-app_v0.118.0+github-debug_x86_64.apk
- name: Prepare Android emulator test package
if: ${{ matrix.arch == 'x86_64' }}
run: |
set -x
# create the test runner script
cat > ~/test-toolchain.sh << EOF
adb install ~/termux-debug.apk
adb push pack /data/local/tmp
adb shell "run-as com.termux mkdir /data/data/com.termux/pack"
adb shell "run-as com.termux cp /data/local/tmp/pack/{lib*.so,swift-nioPackageTests.xctest,FileHandleTests.swift} /data/data/com.termux/pack"
adb shell "run-as com.termux cp -r /data/local/tmp/pack/Test\ Data /data/data/com.termux/pack"
adb shell "run-as com.termux ln -s README.md /data/data/com.termux/pack/Test\ Data/README.md.symlink"
adb shell "run-as com.termux ln -s Foo /data/data/com.termux/pack/Test\ Data/Foo.symlink"
adb shell "run-as com.termux sh -c 'TMPDIR=/data/data/com.termux /data/data/com.termux/pack/swift-nioPackageTests.xctest'"
adb shell "TMPDIR=/data/local/tmp /data/local/tmp/pack/swift-systemPackageTests.xctest"
EOF
mkdir pack
TARGET="x86_64-unknown-linux-android$ANDROID_API_LEVEL"
cp swift-argument-parser/.build/$TARGET/debug/{generate-manual,math,repeat,roll,swift-argument-parserPackageTests.xctest} pack
echo 'adb shell /data/local/tmp/pack/swift-argument-parserPackageTests.xctest' >> ~/test-toolchain.sh
wget -q https://raw.githubusercontent.com/termux/termux-elf-cleaner/v2.1.1/elf-cleaner.cpp
wget -q https://raw.githubusercontent.com/termux/termux-elf-cleaner/v2.1.1/elf.h
wget -q https://raw.githubusercontent.com/termux/termux-elf-cleaner/v2.1.1/arghandling.h
wget -q https://raw.githubusercontent.com/termux/termux-elf-cleaner/v2.1.1/arghandling.c
clang -c arghandling.c
clang -o elf-cleaner arghandling.o elf-cleaner.cpp -DCOPYRIGHT=\"foo\" -DPACKAGE_NAME=\"termux-elf-cleaner\" -DPACKAGE_VERSION=\"2.2.1\"
./elf-cleaner --api-level $ANDROID_API_LEVEL pack/{generate-manual,math,repeat,roll} || true
cp swift-crypto/.build/$TARGET/debug/swift-cryptoPackageTests.xctest pack
echo 'adb shell /data/local/tmp/pack/swift-cryptoPackageTests.xctest' >> ~/test-toolchain.sh
cp swift-nio/.build/$TARGET/debug/swift-nioPackageTests.xctest pack
cp swift-numerics/.build/$TARGET/debug/swift-numericsPackageTests.xctest pack
echo 'adb shell /data/local/tmp/pack/swift-numericsPackageTests.xctest' >> ~/test-toolchain.sh
cp swift-system/.build/$TARGET/debug/swift-systemPackageTests.xctest pack
cp swift-collections/.build/$TARGET/debug/swift-collectionsPackageTests.xctest pack
echo 'adb shell /data/local/tmp/pack/swift-collectionsPackageTests.xctest' >> ~/test-toolchain.sh
cp sns/.build/$TARGET/debug/swift-nio-sshPackageTests.xctest pack
echo 'adb shell /data/local/tmp/pack/swift-nio-sshPackageTests.xctest' >> ~/test-toolchain.sh
cp snl/.build/$TARGET/debug/swift-nio-sslPackageTests.xctest pack
echo 'adb shell /data/local/tmp/pack/swift-nio-sslPackageTests.xctest' >> ~/test-toolchain.sh
cp snh/.build/$TARGET/debug/swift-nio-http2PackageTests.xctest pack
echo 'adb shell /data/local/tmp/pack/swift-nio-http2PackageTests.xctest' >> ~/test-toolchain.sh
cp yams/.build/$TARGET/debug/YamsPackageTests.xctest pack
echo 'adb shell /data/local/tmp/pack/YamsPackageTests.xctest' >> ~/test-toolchain.sh
cp sa/.build/$TARGET/debug/swift-algorithmsPackageTests.xctest pack
echo 'adb shell /data/local/tmp/pack/swift-algorithmsPackageTests.xctest' >> ~/test-toolchain.sh
mkdir pack/crypto-vectors pack/swift-crypto_CryptoTests.resources
cp swift-crypto/Tests/Test\ Vectors/* swift-crypto/Tests/_CryptoExtrasVectors/* pack/crypto-vectors
cp swift-crypto/Tests/CryptoTests/HPKE/hpke-test-vectors.json pack/swift-crypto_CryptoTests.resources
rm swift-nio/Tests/NIOFileSystemIntegrationTests/Test\ Data/*symlink
cp -r swift-nio/Tests/NIOFileSystemIntegrationTests/Test\ Data/ swift-nio/Tests/NIOFileSystemIntegrationTests/FileHandleTests.swift pack
cp yams/Tests/YamsTests/Fixtures/SourceKitten#289/debug.yaml pack
if ${{ steps.cache-bundle.outputs.cache-hit != 'true' }}; then
cp sdk-config/swift-*-android-x86_64-*${ANDROID_API_LEVEL}-sdk/usr/lib/lib*so pack
cp sdk-config/swift-*-android-x86_64-*${ANDROID_API_LEVEL}-sdk/usr/lib/swift/android/lib*so pack
else
cp ~/.${{ startsWith(matrix.os, 'ubuntu') && 'config/' || '' }}swiftpm/swift-sdks/${{ steps.version.outputs.tag }}-android-${ANDROID_API_LEVEL}-*.artifactbundle/swift*sdk/android*sysroot/usr/lib/$(echo ${{ matrix.arch }} | sed "s/v7//")-linux-android*/${ANDROID_API_LEVEL}/lib*so pack
rm pack/lib{c,dl,log,m}.so
fi
# need to free up some space or else the emulator fails to launch:
# ERROR | Not enough space to create userdata partition. Available: 6086.191406 MB at /home/runner/.android/avd/../avd/test.avd, need 7372.800000 MB.
rm -rf sdk-config/${{ steps.version.outputs.tag }}-ubuntu22.04/usr/{bin,lib/*swift*} */.build
chmod +x ~/test-toolchain.sh
echo "TEST SCRIPT:"
cat ~/test-toolchain.sh
if ${{ startsWith(matrix.os, 'ubuntu') }}; then
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: Run tests on Android x86_64 emulator
if: ${{ matrix.arch == 'x86_64' }}
uses: reactivecircus/android-emulator-runner@v2
with:
api-level: 29
arch: x86_64
script: ~/test-toolchain.sh
- name: Get cached aarch64 SDK on x86_64 runner
if: ${{ steps.cache-bundle.outputs.cache-hit != 'true' && startsWith(matrix.os, 'ubuntu') && matrix.arch == 'x86_64' }}
uses: actions/cache/restore@v4
with:
path: ~/swift-${{ matrix.version }}-android-aarch64-*-sdk.tar.xz
key: ${{ steps.version.outputs.aarch64-key }}
fail-on-cache-miss: true
- name: Get cached arm SDK on x86_64 runner
if: ${{ steps.cache-bundle.outputs.cache-hit != 'true' && startsWith(matrix.os, 'ubuntu') && matrix.arch == 'x86_64' }}
uses: actions/cache/restore@v4
with:
path: ~/swift-${{ matrix.version }}-android-armv7-*-sdk.tar.xz
key: ${{ steps.version.outputs.arm-key }}
fail-on-cache-miss: true
- name: Get previously cached Android NDK sysroot and runtime libraries
uses: actions/cache/restore@v4
with:
path: ~/android-sysroot.tar.xz
key: android-ndk-${{ env.NDK_VERSION }}
fail-on-cache-miss: true
- name: Assemble SDK bundle
if: ${{ steps.cache-bundle.outputs.cache-hit != 'true' && startsWith(matrix.os, 'ubuntu') && matrix.arch == 'x86_64' }}
run: |
set -x
ls -lah ~/swift-*-sdk.tar.xz
VERSION="$(echo ${{ steps.version.outputs.tag }} | cut -f1,2 -d-)-${{ matrix.version }}"
# e.g. swift-6.0.1-release-android-24-sdk
SDK_DIR=$VERSION-android-${ANDROID_API_LEVEL}-sdk
ROOT=android-${NDK_VERSION}-sysroot
SYSROOT=$SDK_DIR/$ROOT
mkdir ${SDK_DIR}
tar xf ~/android-sysroot.tar.xz
mv sysroot $SYSROOT
for SDK_PATH in ~/swift-*-sdk.tar.xz; do
MERGEDIR=$(basename $SDK_PATH .tar.xz)
tar xf ${SDK_PATH}
tree ${MERGEDIR}
pushd ${MERGEDIR}/usr
ARCH=$(ls lib/swift_static/android/*/swiftrt.o | cut -f 4 -d '/')
TRIPLE="${ARCH}-linux-android"
if [[ $ARCH == 'armv7' ]]; then
TRIPLE="arm-linux-androideabi"
fi
echo "Creating ${TRIPLE} from ${MERGEDIR}…"
mkdir -p lib/${TRIPLE}/${ANDROID_API_LEVEL}
mv lib/swift_static lib/swift_static-${ARCH}
mv lib/libandroid-spawn.a lib/swift_static-${ARCH}/android
patchelf --set-rpath \$ORIGIN:\$ORIGIN/termux-zlib lib/lib{curl,ssh2,xml2}.so
cp ../../$SYSROOT/usr/lib/$TRIPLE/libc++_shared.so lib
mv lib/lib[a-x]*.so lib/swift/android/lib*.so lib/${TRIPLE}/${ANDROID_API_LEVEL}
mv lib/pkgconfig lib/${TRIPLE}
mkdir lib/${TRIPLE}/${ANDROID_API_LEVEL}/termux-zlib
mv lib/libz.so lib/${TRIPLE}/${ANDROID_API_LEVEL}/termux-zlib
rm lib/swift{,_static-$ARCH}/clang
popd
# copy all the processed SDK files into the Android sysroot
rsync -ar ${MERGEDIR}/ $SYSROOT
done
# Copy necessary headers and libraries from the toolchain and NDK clang resource directories
mkdir -p $SYSROOT/usr/lib/swift/clang/lib
cp -r $TOOLCHAIN/lib/clang/*/include $SYSROOT/usr/lib/swift/clang
mv $SYSROOT/linux $SYSROOT/usr/lib/swift/clang/lib
ln -s ../swift/clang $SYSROOT/usr/lib/swift_static-aarch64/clang
ln -s ../swift/clang $SYSROOT/usr/lib/swift_static-armv7/clang
ln -s ../swift/clang $SYSROOT/usr/lib/swift_static-x86_64/clang
BUNDLE=${{ steps.version.outputs.tag }}-android-${ANDROID_API_LEVEL}-${BUNDLE_VERSION}
BUNDLE_DIR=$BUNDLE.artifactbundle
mkdir ${BUNDLE_DIR}
mv ${SDK_DIR} ${BUNDLE_DIR}
cat > $BUNDLE_DIR/info.json << EOF
{
"schemaVersion": "1.0",
"artifacts": {
"${BUNDLE}": {
"variants": [ { "path": "${SDK_DIR}" } ],
"version": "${BUNDLE_VERSION}",
"type": "swiftSDK"
}
}
}
EOF
cat > $BUNDLE_DIR/$SDK_DIR/swift-sdk.json << EOF
{
"schemaVersion": "4.0",
"targetTriples": {
"aarch64-unknown-linux-android24": {
"sdkRootPath": "${ROOT}",
"swiftResourcesPath": "${ROOT}/usr/lib/swift",
"swiftStaticResourcesPath": "${ROOT}/usr/lib/swift_static-aarch64"
},
"x86_64-unknown-linux-android24": {
"sdkRootPath": "${ROOT}",
"swiftResourcesPath": "${ROOT}/usr/lib/swift",
"swiftStaticResourcesPath": "${ROOT}/usr/lib/swift_static-x86_64"
},
"armv7-unknown-linux-androideabi24": {
"sdkRootPath": "${ROOT}",
"swiftResourcesPath": "${ROOT}/usr/lib/swift",
"swiftStaticResourcesPath": "${ROOT}/usr/lib/swift_static-armv7"
}
}
}
EOF
cat > $BUNDLE_DIR/$SYSROOT/SDKSettings.json << EOF
{
"DisplayName": "Android NDK ${NDK_VERSION} sysroot with ${VERSION} runtime libraries for API 24",
"Version": "27.1.12297006",
"VersionMap": {},
"CanonicalName": "${VERSION}-android24"
}
EOF
# output visualization of the SDK bundle file tree
tree $BUNDLE_DIR
du -skh "${BUNDLE_DIR}"
tar czf ~/${BUNDLE_DIR}.tar.gz "${BUNDLE_DIR}"
du -skh ~/${BUNDLE_DIR}.tar.gz
shasum -a 256 ~/${BUNDLE_DIR}.tar.gz
- name: Upload SDK bundle
if: ${{ startsWith(matrix.os, 'ubuntu') && matrix.arch == 'x86_64' }}
uses: actions/upload-artifact@v4
with:
name: ${{ steps.version.outputs.tag }}-android-${{ env.ANDROID_API_LEVEL }}-${{ env.BUNDLE_VERSION }}.artifactbundle.tar.gz
path: ~/${{ steps.version.outputs.tag }}-android-${{ env.ANDROID_API_LEVEL }}-${{ env.BUNDLE_VERSION }}.artifactbundle.tar.gz
compression-level: 0