diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7cfdd0f..32a8413 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -5,7 +5,7 @@ on: workflow_dispatch: pull_request: schedule: - - cron: '0 1,7,13,20 * * *' + - cron: '0 13 * * *' jobs: install-sdk: @@ -27,6 +27,13 @@ jobs: 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 @@ -50,19 +57,9 @@ jobs: # EMULATOR_ARCH_TRIPLE: 'aarch64' runs-on: ${{ matrix.os }} - env: - ANDROID_API: ${{ matrix.ANDROID_API }} - ANDROID_EMULATOR_ARCH: ${{ matrix.EMULATOR_ARCH }} - ANDROID_EMULATOR_ARCH_TRIPLE: ${{ matrix.EMULATOR_ARCH_TRIPLE }} - ANDROID_TARGET: 'default' - #ANDROID_BUILD_TOOLS_VERSION: 36.0.0 - ANDROID_BUILD_TOOLS_VERSION: 'latest' - BUILD_TOOLS_VERSION: "35.0.0" - ANDROID_EMULATOR_NAME: 'demo' - ANDROID_PROFILE: "Nexus 10" - ANDROID_CHANNEL: "3" - ANDROID_NDK_VERSION: "${{ matrix.NDK_VERSION }}" steps: + - uses: actions/checkout@v4 + - name: Free Disk Space if: runner.os == 'Linux' run: | @@ -71,6 +68,48 @@ jobs: 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 @@ -138,19 +177,12 @@ jobs: # https://github.com/swiftlang/swift-driver/pull/1879 echo "ANDROID_NDK_ROOT=" >> $GITHUB_ENV - - name: Setup Android Environment - run: | - echo "$ANDROID_HOME/cmdline-tools/latest/bin:$ANDROID_HOME/emulator:$ANDROID_HOME/tools:$ANDROID_HOME/platform-tools:$ANDROID_HOME/build-tools/${{ env.ANDROID_BUILD_TOOLS_VERSION }}" >> $GITHUB_PATH - # needed for Linux or else the emulator will be created in - # ~/.android/avd but it will be sought in ~/.config/.android/avd - if [[ "${RUNNER_OS}" == "Linux" ]]; then - echo "ANDROID_AVD_HOME=${XDG_CONFIG_HOME:-$HOME}/.android/avd" >> $GITHUB_ENV - fi - - 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: | @@ -160,55 +192,12 @@ jobs: swiftly run swift build --swift-sdk "${ANDROID_EMULATOR_ARCH_TRIPLE}-unknown-linux-android${ANDROID_API}" --static-swift-stdlib file .build/debug/hello - - name: Enable KVM - if: runner.os == 'Linux' - run: | - if [[ "${RUNNER_ARCH}" == "X64" ]]; 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: Android SDKs - list installed SDKs - run: sdkmanager --list_installed - - - name: Android SDKs - setup environment - run: yes y | sdkmanager --licenses > /dev/null - - - name: Android SKDs - setup build tools - run: sdkmanager --install "build-tools;${BUILD_TOOLS_VERSION}" platform-tools "platforms;android-${ANDROID_API}" --channel="${ANDROID_CHANNEL}" - - - name: Android SKDs - setup emulator - run: sdkmanager --install emulator --channel="${ANDROID_CHANNEL}" - - - name: Android Emulator - download required images - run: sdkmanager --install "system-images;android-${ANDROID_API};${ANDROID_TARGET};${ANDROID_EMULATOR_ARCH}" --channel="${ANDROID_CHANNEL}" - - - name: Android Emulator - Create - run: avdmanager --verbose create avd --force -n "${ANDROID_EMULATOR_NAME}" --device "${ANDROID_PROFILE}" --abi "${ANDROID_TARGET}/${ANDROID_EMULATOR_ARCH}" --package "system-images;android-${ANDROID_API};${ANDROID_TARGET};${ANDROID_EMULATOR_ARCH}" --sdcard 512M - - #- name: Android - Find AVDs - # run: find ~/ -type d -name '*.avd' - - #- name: Android - List AVDs - # run: emulator -list-avds - - - name: Android - Boot - run: nohup emulator -memory 4096 -avd "${ANDROID_EMULATOR_NAME}" -wipe-data -no-window -no-snapshot -noaudio -no-boot-anim 2>&1 > emulator.log & - - - name: ADB Wait For Device + - name: Wait for Android Emulator run: adb wait-for-any-device timeout-minutes: 5 - - name: Pause briefly - run: sleep 30 - - #- name: ADB Press Power Button - # run: adb shell input keyevent 82 - - name: Check Android Emulator - run: | - adb shell 'echo Hello Android!' + run: adb shell 'echo Hello Android!' - name: Run Swift Executable on Android Emulator run: | @@ -217,72 +206,47 @@ jobs: 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} - - swiftly run swift build --swift-sdk "${ANDROID_EMULATOR_ARCH_TRIPLE}-unknown-linux-android${ANDROID_API}" --build-tests +"${SWIFT_TOOLCHAIN_VERSION}" - - adb push .build/debug/${PACKAGE}PackageTests.xctest /data/local/tmp/ - # copy up any test resources - adb push .build/debug/*.resources /data/local/tmp/ || true + - run: ./android-ci.sh test apple/swift-numerics - # push potential dependent libraries - adb push $ANDROID_NDK_HOME/toolchains/llvm/prebuilt/*/sysroot/usr/lib/${ANDROID_EMULATOR_ARCH_TRIPLE}-linux-android/libc++_shared.so /data/local/tmp/ + - run: ./android-ci.sh test apple/swift-algorithms - # Since we are building with --static-swift-stdlib, we don't - # need to copy any of the other libraries - cd ~/Library/org.swift.swiftpm || cd ${XDG_CONFIG_HOME}/swiftpm || cd ~/.local/swiftpm || cd ~/.swiftpm - adb push swift-sdks/${SWIFT_ANDROID_SDK_VERSION}*.artifactbundle/swift-android/swift-resources/usr/lib/swift-${ANDROID_EMULATOR_ARCH_TRIPLE}/android/*.so /data/local/tmp/ - cd - + - run: ./android-ci.sh test apple/swift-atomics - adb shell ls /data/local/tmp/ + - run: ./android-ci.sh build swiftlang/swift-subprocess - adb shell /data/local/tmp/${PACKAGE}PackageTests.xctest - EOF + # build-only because it uses hardwired StringLiteralRepresentedLiteralValueTests.swift + - run: ./android-ci.sh build swiftlang/swift-syntax - chmod +x run-tests.sh - cat run-tests.sh + # build-only because tests crash in NetrcTests.testNoErrorMixedAccount + # and tests use abslute file paths + - run: ./android-ci.sh build swiftlang/swift-tools-support-core - - name: Run swift-collections tests - # too slow - if: false - run: ./run-tests.sh apple/swift-collections + # build-only because it tries to write to "/tmp/old.txt" and "/tmp/" does not exist + - run: ./android-ci.sh build swiftlang/swift-markdown - - name: Run swift-numerics tests - run: ./run-tests.sh apple/swift-numerics + # no tests in swift-toolchain-sqlite + - run: ./android-ci.sh build swiftlang/swift-toolchain-sqlite - - name: Run swift-algorithms tests - run: ./run-tests.sh apple/swift-algorithms + # build-only: tests work, but they take a very long time + - run: ./android-ci.sh build apple/swift-collections - - name: Run swift-atomics tests - run: ./run-tests.sh apple/swift-atomics + # build-only: https://github.com/apple/swift-system/pull/272 + - run: ./android-ci.sh build apple/swift-system - - name: Run swift-system tests - run: ./run-tests.sh apple/swift-system + # build-only: tests references Tests/ file paths by absolute filename + - run: ./android-ci.sh build apple/swift-crypto - - name: Run swift-crypto tests - # needs: Tests/CryptoExtrasVectors/rfc-7914-scrypt.txt - if: false - run: ./run-tests.sh apple/swift-crypto + - run: ./android-ci.sh build apple/swift-nio - - name: Run swift-nio tests - if: false - run: ./run-tests.sh apple/swift-nio + # build-only, since tests needs local files: + # error: MathExampleTests.testMath_AddHelp : failed - No executable at '/data/local/tmp/math'. + #- run: ./android-ci.sh build apple/swift-argument-parser - - 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: Android - Show Emulator Log + - name: Show Android Logcat Output if: always() - run: cat emulator.log || true + run: cat logcat.log diff --git a/android-ci.sh b/android-ci.sh new file mode 100755 index 0000000..e600ee6 --- /dev/null +++ b/android-ci.sh @@ -0,0 +1,59 @@ +#!/bin/bash -ex + +if [[ -z "${2}" ]]; then + echo "$0: Usage: $0 build/test org/package" + exit 1 +fi + +ACT=${1} +ORG=$(echo "${2}" | cut -d '/' -f 1) +PACKAGE=$(echo "${2}" | 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}" + +if [[ "${ACT}" == "build" ]]; then + # build-only, not test, so we are done + exit 0 +fi + +if [[ "${ACT}" != "test" ]]; then + # build-only, not test + echo "$0: Usage: $0 build/test org/package" + exit 1 +fi + +STAGING="android-test-${PACKAGE}" +rm -rf .build/"${STAGING}" +mkdir .build/"${STAGING}" + +# for the common case of tests referencing their own files as hardwired resource paths +if [[ -d Tests ]]; then + cp -a Tests .build/"${STAGING}" +fi + +cd .build/ +cp -a debug/*.xctest "${STAGING}" +cp -a debug/*.resources "${STAGING}" || true +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 "${STAGING}" + +adb push ${STAGING} /data/local/tmp/ + +cd - + +TEST_CMD="./${PACKAGE}PackageTests.xctest" +TEST_SHELL="cd /data/local/tmp/${STAGING}" +TEST_SHELL="${TEST_SHELL} && ${TEST_CMD}" + +# Run 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/1b593469e8ad3daf2cc10e798340bd2de68c402d/Sources/Commands/SwiftTestCommand.swift#L1542 +TEST_SHELL="${TEST_SHELL} && ${TEST_CMD} --testing-library swift-testing && [ \$? -eq 0 ] || [ \$? -eq 69 ]" + +adb shell "${TEST_SHELL}" +