Skip to content

Swift Android build 6.2 #2

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

Merged
merged 20 commits into from
May 1, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
50 changes: 23 additions & 27 deletions .github/workflows/pull_request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ env:
jobs:
build:
name: Build Docker images
# disabled for CI testing
if: false
runs-on: ubuntu-latest
steps:
- name: Checkout repository
Expand All @@ -24,6 +26,8 @@ jobs:

static-linux-build:
name: Build Static Linux image
# disabled for CI testing
if: false
runs-on: ubuntu-latest
steps:
- name: Checkout repository
Expand All @@ -33,7 +37,7 @@ jobs:
run: ./build

android-build:
name: Build Android ${{ matrix.arch }} SDK
name: Build Android ${{ matrix.swift-version }} ${{ matrix.arch }} SDK
strategy:
fail-fast: false
matrix:
Expand All @@ -43,8 +47,18 @@ jobs:
#arch: ['x86_64']
# build both the quick (x86_64) and complete (aarch64,x86_64,armv7) SDKs
arch: ['x86_64', '']
swift-version: ['release', 'devel', 'trunk']
runs-on: ubuntu-24.04
steps:
- name: Free Disk Space
run: |
df -h
# brings available space from 25G to 32G
# otherwise we sometimes run out of space during the build
sudo rm -rf /usr/share/miniconda /usr/share/az* /usr/share/glade* /usr/local/share/chromium /usr/local/share/powershell /usr/share/dotnet /opt/ghc /opt/hostedtoolcache/CodeQL
sudo docker image prune --all --force
sudo docker builder prune -a
df -h
- name: Checkout repository
uses: actions/checkout@v4
- name: Install Dependencies
Expand All @@ -53,7 +67,7 @@ jobs:
- name: Build Android SDK
working-directory: swift-ci/sdks/android
run: |
TARGET_ARCHS=${{ matrix.arch }} ./build
BUILD_VERSION=${{ matrix.swift-version }} TARGET_ARCHS=${{ matrix.arch }} ./build
- name: Get artifact info
id: info
shell: bash
Expand Down Expand Up @@ -82,28 +96,8 @@ jobs:
# swift-6.1-RELEASE_android-0.1-x86_64.artifactbundle.tar.gz.zip
echo "artifact-name=${ARTIFACT_NAME}" >> $GITHUB_OUTPUT

# validate some required paths in the artifactbundle
pushd ${ARTIFACT_BUILD}/*/*/usr
ls lib/swift/android
ls lib/swift/android/*
ls lib/swift/android/*/swiftrt.o
ls lib/*-linux-android/*/crtbegin_dynamic.o

ls lib/swift_static-*
ls lib/swift_static-*/android
ls lib/swift_static-*/android/libFoundationEssentials.a

ls lib/*-linux-android/libFoundationEssentials.so
ls lib/*-linux-android/libFoundationNetworking.so
ls lib/*-linux-android/libFoundationInternationalization.so
ls lib/*-linux-android/lib_FoundationICU.so
ls lib/*-linux-android/libFoundationXML.so
ls lib/*-linux-android/libTesting.so

ls lib/swift/clang/lib
ls lib/swift/clang/lib/linux
ls lib/swift/clang/lib/linux/*/libunwind.a
popd
# show an abridged tree
tree ${ARTIFACT_BUILD} --filesfirst --prune -P 'Android.swiftmodule' -P 'libswiftAndroid.*' -P 'libFoundation.*' -P 'swiftrt.o' -P 'swift*.json' -P 'info.json' -P 'api-level.h' -P 'android.modulemap' -P 'SwiftAndroidNDK.h' -P 'bridging.modulemap' -P 'linux' -P 'libclang*.a' -P 'libunwind.a' -P 'libclang_rt.builtins-*-android.a'
- name: Upload SDK artifactbundle
uses: actions/upload-artifact@v4
with:
Expand All @@ -113,7 +107,9 @@ jobs:
- name: Cleanup
run: |
# need to free up some space or else when installing we get: No space left on device
df -h
rm -rf ${{ runner.temp }}/swift-android-sdk/{build,src}
df -h
- name: Install artifactbundle
shell: bash
run: |
Expand All @@ -138,10 +134,10 @@ jobs:
echo 'import Dispatch' >> Sources/DemoProject/DemoProject.swift
echo 'import Android' >> Sources/DemoProject/DemoProject.swift
- name: Test Demo Project on Android
uses: skiptools/swift-android-action@v2
uses: skiptools/swift-android-action@main
with:
# only test for the complete arch SDK build to speed up CI
run-tests: ${{ matrix.arch == '' }}
#run-tests: ${{ matrix.arch == '' }}
package-path: ${{ runner.temp }}/DemoProject
installed-sdk: ${{ steps.info.outputs.sdk-id }}
installed-swift: ${{ steps.info.outputs.swift-root }}
Expand All @@ -152,7 +148,7 @@ jobs:
repository: apple/swift-algorithms
path: swift-algorithms
- name: Test swift-algorithms
uses: skiptools/swift-android-action@v2
uses: skiptools/swift-android-action@main
with:
run-tests: ${{ matrix.arch == '' }}
package-path: swift-algorithms
Expand Down
30 changes: 25 additions & 5 deletions swift-ci/sdks/android/build
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,28 @@ mkdir -p ${SDKROOT}
# Install a Swift host toolchain if it isn't already present
SWIFT_ROOT=${SDKROOT}/host-toolchain
HOST_OS=ubuntu$(lsb_release -sr)
SWIFT_VERSION=6.1
SWIFT_TAG="swift-${SWIFT_VERSION}-RELEASE"
SWIFT_BRANCH="swift-$(echo $SWIFT_TAG | cut -d- -f2)-release"

#BUILD_VERSION='release'
#BUILD_VERSION='trunk'
BUILD_VERSION=${BUILD_VERSION:-'devel'}

if [ "${BUILD_VERSION}" = 'release' ]; then
LATEST_TOOLCHAIN_VERSION=$(curl -sL https://github.com/apple/swift/releases | grep -m1 swift-6.1 | cut -d- -f2)
SWIFT_TAG="swift-${LATEST_TOOLCHAIN_VERSION}-RELEASE"
SWIFT_BRANCH="swift-$(echo $SWIFT_TAG | cut -d- -f2)-release"
elif [ "${BUILD_VERSION}" = 'devel' ]; then
LATEST_TOOLCHAIN_VERSION=$(curl -sL https://github.com/apple/swift/tags | grep -m1 swift-6.2-DEV | cut -d- -f8-10)
SWIFT_TAG="swift-6.2-DEVELOPMENT-SNAPSHOT-${LATEST_TOOLCHAIN_VERSION}-a"
SWIFT_BRANCH="swift-$(echo $SWIFT_TAG | cut -d- -f2)-branch"
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"
SWIFT_BRANCH="development"
fi

SWIFT_BASE=$SWIFT_TAG-$HOST_OS

if [[ ! -d $SWIFT_ROOT ]]; then
if [[ ! -d "$SWIFT_ROOT/$SWIFT_BASE" ]]; then
mkdir -p $SWIFT_ROOT
pushd $SWIFT_ROOT

Expand Down Expand Up @@ -75,7 +91,11 @@ if [[ ! -d ${PATCHDIR} ]]; then
# swift-android-ci.patch is not needed, since it is only used for llbuild, etc.
#git apply -C1 $PATCHDIR/swift-android-ci.patch
#git apply -v $PATCHDIR/swift-android-ci-release.patch
git apply -v $PATCHDIR/swift-android-testing-release.patch
if [ "${BUILD_VERSION}" = 'release' ]; then
git apply -v $PATCHDIR/swift-android-testing-release.patch
else
git apply -v $PATCHDIR/swift-android-testing-except-release.patch
fi

perl -pi -e 's%String\(cString: getpass%\"fake\" //%' swiftpm/Sources/PackageRegistryCommand/PackageRegistryCommand+Auth.swift
# disable backtrace() for Android (needs either API33+ or libandroid-execinfo, or to manually add in backtrace backport)
Expand Down
103 changes: 75 additions & 28 deletions swift-ci/sdks/android/scripts/build.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
#!/bin/bash
# Swift SDK for Android: Build Script
set -e
set -ex

# temporary for splitting out NDK installation from the rest of the SDK
#NDK_LOCATION=${NDK_LOCATION:-"merged"}
NDK_LOCATION=${NDK_LOCATION:-"external"}

# Docker sets TERM to xterm if using a pty; we probably want
# xterm-256color, otherwise we only get eight colors
Expand Down Expand Up @@ -188,7 +192,7 @@ if [[ $swift_version == swift-* ]]; then
fi

if [[ -z "$sdk_name" ]]; then
sdk_name=swift-${swift_version}_android-${android_sdk_version}
sdk_name=swift-${swift_version}-android-${android_sdk_version}
fi

libxml2_version=$(versionFromTag ${source_dir}/libxml2)
Expand All @@ -212,14 +216,13 @@ header "Swift Android SDK build script"
swift_dir=$(realpath $(dirname "$swiftc")/..)
HOST=linux-x86_64
#HOST=$(uname -s -m | tr '[:upper:]' '[:lower:]' | tr ' ' '-')
ndk_toolchain=$ndk_home/toolchains/llvm/prebuilt/$HOST

ndk_installation=$ndk_home/toolchains/llvm/prebuilt/$HOST

echo "Swift found at ${swift_dir}"
echo "Host toolchain found at ${host_toolchain}"
${host_toolchain}/bin/swift --version
echo "Android NDK found at ${ndk_home}"
${ndk_toolchain}/bin/clang --version
${ndk_installation}/bin/clang --version
echo "Building for ${archs}"
echo "Sources are in ${source_dir}"
echo "Build will happen in ${build_dir}"
Expand Down Expand Up @@ -387,7 +390,7 @@ for arch in $archs; do
# need to remove symlink that gets created in the NDK to the previous arch's build
# or else we get errors like:
# error: could not find module '_Builtin_float' for target 'x86_64-unknown-linux-android'; found: aarch64-unknown-linux-android, at: /home/runner/work/_temp/swift-android-sdk/ndk/android-ndk-r27c/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/lib/swift/android/_Builtin_float.swiftmodule
rm -f $ndk_toolchain/sysroot/usr/lib/swift
rm -f $ndk_installation/sysroot/usr/lib/swift
quiet_popd
groupend
done
Expand Down Expand Up @@ -425,12 +428,22 @@ EOF
mkdir -p $sdk_base
quiet_pushd $sdk_base

#sysroot_path="ndk-sysroot"
#sysroot_path="android-27c-sysroot"
sysroot_path="sysroot"
cp -a ${ndk_toolchain}/sysroot ${sysroot_path}
cp -a ${build_dir}/sdk_root ${sdk_staging}

if [ "${NDK_LOCATION}" = "external" ]; then
swift_res_root="swift-resources"
ndk_sysroot="ndk-sysroot"
cp -a ${ndk_installation}/sysroot ${ndk_sysroot}
else
merged_sysroot_path="sysroot"
swift_res_root=${merged_sysroot_path}
ndk_sysroot=${merged_sysroot_path}
cp -a ${ndk_installation}/sysroot ${ndk_sysroot}
fi

cat > $sysroot_path/SDKSettings.json <<EOF
mkdir -p ${swift_res_root}

cat > $swift_res_root/SDKSettings.json <<EOF
{
"DisplayName": "Swift Android SDK",
"Version": "${android_sdk_version}",
Expand All @@ -439,10 +452,10 @@ cat > $sysroot_path/SDKSettings.json <<EOF
}
EOF

cp -a ${build_dir}/sdk_root ${sdk_staging}
# Copy necessary headers and libraries from the toolchain and NDK clang resource directories
mkdir -p $sysroot_path/usr/lib/swift/clang/lib
cp -r $host_toolchain/lib/clang/*/include $sysroot_path/usr/lib/swift/clang
mkdir -p $swift_res_root/usr/lib/swift/clang/lib
cp -r $host_toolchain/lib/clang/*/include $swift_res_root/usr/lib/swift/clang


for arch in $archs; do
quiet_pushd ${sdk_staging}/${arch}/usr
Expand All @@ -455,26 +468,50 @@ for arch in $archs; do
arch_triple="arm-linux-androideabi"
fi

mkdir lib/${arch_triple}
mv lib/pkgconfig lib/swift/android/lib*.{a,so} lib/${arch_triple}
rm -r lib/swift{,_static}/clang
if [ "${NDK_LOCATION}" = "external" ]; then
#mkdir lib/swift-$arch
#mv lib/pkgconfig lib/swift/android/lib*.{a,so} lib/swift-$arch
mv lib/swift lib/swift-$arch
ln -s ../swift/clang lib/swift-$arch/clang
else
mkdir lib/${arch_triple}
mv lib/pkgconfig lib/swift/android/lib*.{a,so} lib/${arch_triple}
fi

mv lib/swift_static lib/swift_static-$arch
mv lib/lib*.a lib/swift_static-$arch/android

rm -r lib/swift{,_static-$arch}/clang
ln -sv ../swift/clang lib/swift_static-$arch/clang

mkdir -p lib/swift/clang/lib
cp -a ${ndk_toolchain}/lib/clang/*/lib/linux lib/swift/clang/lib
ln -s ../swift/clang lib/swift_static-$arch/clang
# copy the clang libraries that we need to build for each architecture
aarch=${arch/armv7/arm}
mkdir -p lib/swift/clang/lib/linux/${aarch}

# match clang version 21, 22, etc.
cp -av ${ndk_installation}/lib/clang/[0-9]*/lib/linux/libclang_rt.builtins-${aarch}-android.a lib/swift/clang/lib/linux/
cp -av ${ndk_installation}/lib/clang/[0-9]*/lib/linux/${aarch}/libunwind.a lib/swift/clang/lib/linux/${aarch}/
quiet_popd

# now sync the massaged sdk_root into the sysroot_path
rsync -a ${sdk_staging}/${arch}/usr ${sysroot_path}
# now sync the massaged sdk_root into the swift_res_root
rsync -a ${sdk_staging}/${arch}/usr ${swift_res_root}
done

rm -r ${sysroot_path}/usr/share/{doc,man}
rm -r ${sysroot_path}/usr/{include,lib}/{i686,riscv64}-linux-android
rm -r ${sysroot_path}/usr/lib/swift/clang/lib/linux/*{i[36]86,riscv64}*
if [ "${NDK_LOCATION}" = "external" ]; then
# need to manually copy over swiftrt.o or else:
# error: link command failed with exit code 1 (use -v to see invocation)
# clang: error: no such file or directory: '${HOME}/.swiftpm/swift-sdks/swift-6.2-DEVELOPMENT-SNAPSHOT-2025-04-24-a-android-0.1.artifactbundle/swift-android/ndk-sysroot/usr/lib/swift/android/x86_64/swiftrt.o'
# see: https://github.com/swiftlang/swift-driver/pull/1822#issuecomment-2762811807
for arch in $archs; do
mkdir -p ${ndk_sysroot}/usr/lib/swift/android/${arch}
ln -srv ${swift_res_root}/usr/lib/swift-${arch}/android/${arch}/swiftrt.o ${ndk_sysroot}/usr/lib/swift/android/${arch}/swiftrt.o
done
else
rm -r ${swift_res_root}/usr/{include,lib}/{i686,riscv64}-linux-android
rm -r ${swift_res_root}/usr/lib/swift/clang/lib/linux/*{i[36]86,riscv64}*
fi

rm -r ${swift_res_root}/usr/share/{doc,man}
rm -r ${sdk_staging}

cat > swift-sdk.json <<EOF
Expand All @@ -497,13 +534,23 @@ for api in $(eval echo "{$android_api..36}"); do
},
EOF
fi

if [ "${NDK_LOCATION}" = "external" ]; then
SWIFT_RES_DIR="swift-${arch}"
else
SWIFT_RES_DIR="swift"
fi
SWIFT_STATIC_RES_DIR="swift_static-${arch}"

cat >> swift-sdk.json <<EOF
"${arch}-unknown-linux-android${api}": {
"sdkRootPath": "${sysroot_path}",
"swiftResourcesPath": "${sysroot_path}/usr/lib/swift",
"swiftStaticResourcesPath": "${sysroot_path}/usr/lib/swift_static-${arch}",
"sdkRootPath": "${ndk_sysroot}",
"swiftResourcesPath": "${swift_res_root}/usr/lib/${SWIFT_RES_DIR}",
"swiftStaticResourcesPath": "${swift_res_root}/usr/lib/${SWIFT_STATIC_RES_DIR}",
"toolsetPaths": [ "swift-toolset.json" ]
EOF
#"librarySearchPaths": [ "${swift_res_root}/usr/lib/swift-x86_64/android/x86_64" ],
#"includeSearchPaths": [ "${ndk_sysroot}/usr/include" ],
done
done

Expand Down