diff --git a/.github/workflows/scripts/android/android-emulator-tests.sh b/.github/workflows/scripts/android/android-emulator-tests.sh index 1cd32a30..5318bad5 100755 --- a/.github/workflows/scripts/android/android-emulator-tests.sh +++ b/.github/workflows/scripts/android/android-emulator-tests.sh @@ -21,8 +21,18 @@ ANDROID_PROFILE="Nexus 10" ANDROID_EMULATOR_TIMEOUT=300 SWIFTPM_HOME="${XDG_CONFIG_HOME}"/swiftpm +# Prefer the bundle name exported by install-and-build-with-sdk.sh so that we +# pick the SDK matching the requested swift_version (release, snapshot, or main), +# rather than whichever happens to sort last on disk. # 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) +if [[ -n "${SWIFT_ANDROID_SDK_BUNDLE:-}" ]]; then + SWIFT_ANDROID_SDK_HOME="${SWIFTPM_HOME}/swift-sdks/${SWIFT_ANDROID_SDK_BUNDLE}" + if [[ ! -d "${SWIFT_ANDROID_SDK_HOME}" ]]; then + fatal "Android Swift SDK bundle not found at: ${SWIFT_ANDROID_SDK_HOME}" + fi +else + SWIFT_ANDROID_SDK_HOME=$(find "${SWIFTPM_HOME}"/swift-sdks -maxdepth 1 -name 'swift-*android.artifactbundle' | tail -n 1) +fi ANDROID_SDK_TRIPLE="x86_64-unknown-linux-android28" @@ -122,10 +132,14 @@ STAGING_DIR="swift-android-test" rm -rf "${STAGING_DIR}" mkdir "${STAGING_DIR}" -BUILD_DIR=.build/"${ANDROID_SDK_TRIPLE}"/debug +_swift_bin_dir="$(dirname "$SWIFT_EXECUTABLE_FOR_ANDROID_SDK")" +export PATH="$_swift_bin_dir:$PATH" +unset _swift_bin_dir -find "${BUILD_DIR}" -name '*.xctest' -exec cp -av {} "${STAGING_DIR}" \; -find "${BUILD_DIR}" -name '*.resources' -exec cp -av {} "${STAGING_DIR}" \; +SWIFT_SDK_ID=$(basename "${SWIFT_ANDROID_SDK_HOME}" .artifactbundle) +BUILD_DIR=$(swift build --show-bin-path --swift-sdk "${SWIFT_SDK_ID}" --triple "${ANDROID_SDK_TRIPLE}") + +find "${BUILD_DIR}" \( -name '*.xctest' -o -name '*.resources' -o -name '*-test-runner' -o -name '*.so' \) -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}" @@ -146,7 +160,10 @@ 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_CMD="./*-test-runner" +if ! find "${STAGING_DIR}" -name '*-test-runner' -maxdepth 1 | grep -q .; then + TEST_CMD="./*.xctest" +fi TEST_SHELL="cd ${ANDROID_TMP_FOLDER}" TEST_SHELL="${TEST_SHELL} && ${TEST_CMD} --testing-library xctest" diff --git a/.github/workflows/scripts/install-and-build-with-sdk.sh b/.github/workflows/scripts/install-and-build-with-sdk.sh index 6c337e0c..6f35a212 100755 --- a/.github/workflows/scripts/install-and-build-with-sdk.sh +++ b/.github/workflows/scripts/install-and-build-with-sdk.sh @@ -350,7 +350,6 @@ find_latest_sdk_snapshot() { SWIFT_VERSION_BRANCH="" ANDROID_SDK_TAG="" ANDROID_SDK_CHECKSUM="" -ANDROID_SDK_PATH_SEP="-" STATIC_LINUX_SDK_TAG="" STATIC_LINUX_SDK_CHECKSUM="" @@ -621,6 +620,17 @@ if [[ "$INSTALL_ANDROID" == true ]]; then exit 0 fi fi + + # Export the resolved Android SDK tag so subsequent workflow steps + # (e.g. android-emulator-tests.sh) pick the same SDK we just installed + # rather than guessing via 'find ... | tail -n 1' + if [[ -n "${GITHUB_ENV:-}" ]]; then + { + echo "SWIFT_EXECUTABLE_FOR_ANDROID_SDK=${SWIFT_EXECUTABLE_FOR_ANDROID_SDK}" + echo "SWIFT_ANDROID_SDK_TAG=${ANDROID_SDK_TAG}" + echo "SWIFT_ANDROID_SDK_BUNDLE=${ANDROID_SDK_TAG}_android.artifactbundle" + } >> "$GITHUB_ENV" + fi fi if [[ "$INSTALL_STATIC_LINUX" == true ]]; then @@ -687,8 +697,14 @@ install_android_sdk() { rm -f "${sdk_url}" - # now setup the link to the local ANDROID_NDK_HOME - swift sdk configure --show-configuration "$(swift sdk list | grep android | tail -n 1)" + # now setup the link to the local ANDROID_NDK_HOME, using the matched + # toolchain so its sdk subcommand and config files agree with what we just installed + local installed_sdk_name + installed_sdk_name=$("$SWIFT_EXECUTABLE_FOR_ANDROID_SDK" sdk list | grep "^${ANDROID_SDK_TAG}.*android" | tail -n 1) + if [[ -z "$installed_sdk_name" ]]; then + fatal "Could not find newly installed Android Swift SDK matching tag ${ANDROID_SDK_TAG}" + fi + "$SWIFT_EXECUTABLE_FOR_ANDROID_SDK" sdk configure --show-configuration "$installed_sdk_name" # guess some common places where the swift-sdks file lives cd ~/Library/org.swift.swiftpm || cd ~/.config/swiftpm || cd ~/.local/swiftpm || cd ~/.swiftpm || cd /root/.swiftpm @@ -717,7 +733,16 @@ install_android_sdk() { fi fi - ./swift-sdks/"${android_sdk_bundle_name}"/swift-android/scripts/setup-android-sdk.sh + # run the bundled setup script with the matched toolchain in front of PATH + # so any 'swift' it invokes resolves to the version that matches the SDK + local toolchain_bin_dir + toolchain_bin_dir="$(dirname "$SWIFT_EXECUTABLE_FOR_ANDROID_SDK")" + local setup_script="./swift-sdks/${android_sdk_bundle_name}/swift-android/scripts/setup-android-sdk.sh" + if [[ -x "$setup_script" ]]; then + PATH="${toolchain_bin_dir}:${PATH}" "$setup_script" + else + log "Skipping Android SDK setup script (not found): $setup_script" + fi cd - } @@ -783,20 +808,30 @@ build() { if [[ "$INSTALL_ANDROID" == true ]]; then log "Running Swift build with Android Swift SDK" + log "Host toolchain for Android build: ${SWIFT_EXECUTABLE_FOR_ANDROID_SDK}" + "$SWIFT_EXECUTABLE_FOR_ANDROID_SDK" --version || true - local sdk_name="${ANDROID_SDK_TAG}${ANDROID_SDK_PATH_SEP}android" + local sdk_name="${ANDROID_SDK_TAG}_android" alias swift='$SWIFT_EXECUTABLE_FOR_ANDROID_SDK' # This can become a single invocation in the future when `swift build` supports multiple Android triples at once for android_sdk_triple in "${ANDROID_SDK_TRIPLES[@]}" ; do - local build_command="$SWIFT_BUILD_COMMAND --swift-sdk ${android_sdk_triple}" + if [[ "$SWIFT_VERSION_INPUT" == "6.3" || "$SWIFT_VERSION_INPUT" == "nightly-6.3" ]]; then + local build_command="$SWIFT_BUILD_COMMAND --swift-sdk ${android_sdk_triple}" + else + local build_command="$SWIFT_BUILD_COMMAND --swift-sdk ${sdk_name} --triple ${android_sdk_triple}" + fi if [[ -n "$SWIFT_BUILD_FLAGS" ]]; then build_command="$build_command $SWIFT_BUILD_FLAGS" fi log "Running: $build_command" + local _swift_bin_dir + _swift_bin_dir="$(dirname "$SWIFT_EXECUTABLE_FOR_ANDROID_SDK")" + export PATH="$_swift_bin_dir:$PATH" + if eval "$build_command"; then log "✅ Swift build with Android Swift SDK completed successfully" else diff --git a/.github/workflows/swift_package_test.yml b/.github/workflows/swift_package_test.yml index 6c29d825..69b072f2 100644 --- a/.github/workflows/swift_package_test.yml +++ b/.github/workflows/swift_package_test.yml @@ -171,8 +171,7 @@ on: android_sdk_build_command: type: string description: "Command to use when building the package with the Swift SDK for Android" - # Temporarily use native build system on Android due to https://github.com/swiftlang/swift/issues/88282 - default: "swift build --build-system native" + default: "swift build" android_sdk_triples: type: string 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." @@ -673,10 +672,13 @@ jobs: exclude: - ${{ fromJson(inputs.android_exclude_swift_versions) }} steps: - - name: Swift version - run: swift --version - - name: Clang version - run: clang --version + # https://github.com/actions/runner-images/blob/main/images/ubuntu/scripts/build/install-swift.sh + - name: Remove Swift + run: | + sudo rm /usr/local/bin/swift + sudo rm /usr/local/bin/swiftc + sudo rm /usr/local/lib/libsourcekitdInProc.so + sudo rm -r /usr/share/swift - name: Checkout repository uses: actions/checkout@v4 - name: Checkout swiftlang/github-workflows repository