diff --git a/.github/scripts/android_test_driver.sh b/.github/scripts/android_test_driver.sh index 88d263f..f64462f 100644 --- a/.github/scripts/android_test_driver.sh +++ b/.github/scripts/android_test_driver.sh @@ -15,26 +15,28 @@ for BINARY in $BINARIES; do TOTAL=$((TOTAL + 1)) START_TIME=$(date +%s) - START_TIME_MS=$((START_TIME * 1000 + $(date +%N) / 1000000)) + # Busybox date does not support %N, so we can't get milliseconds this way + #START_TIME_MS=$((START_TIME * 1000 + $(date +%N) / 1000000)) OUTPUT=$("$BINARY" 2>&1) EXIT_CODE=$? END_TIME=$(date +%s) - END_TIME_MS=$((END_TIME * 1000 + $(date +%N) / 1000000)) - ELAPSED_TIME=$((END_TIME_MS - START_TIME_MS)) + #END_TIME_MS=$((END_TIME * 1000 + $(date +%N) / 1000000)) + #ELAPSED_TIME=$((END_TIME_MS - START_TIME_MS)) + ELAPSED_TIME=$((END_TIME - START_TIME)) BINARY_NAME=$(basename "$BINARY") if [ $EXIT_CODE -eq 0 ]; then PASS=$((PASS + 1)) - echo "PASSED ($EXIT_CODE): $BINARY_NAME (${ELAPSED_TIME}ms)" + echo "PASSED ($EXIT_CODE): $BINARY_NAME (${ELAPSED_TIME}s)" elif [ $EXIT_CODE -eq 77 ]; then SKIP=$((SKIP + 1)) echo "SKIPPED: $BINARY_NAME" else FAIL=$((FAIL + 1)) - echo "FAILED ($EXIT_CODE): $BINARY_NAME (${ELAPSED_TIME}ms)" + echo "FAILED ($EXIT_CODE): $BINARY_NAME (${ELAPSED_TIME}s)" if [ -z "$OUTPUT" ]; then echo "No output written to stdout." else diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 0f38959..1400c15 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -268,8 +268,20 @@ jobs: arch: - name: x86_64 triple: x86_64-linux-android - api-level: [ 26 ] - # Don't abort runners if a single one fails + emu-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none + - name: arm64-v8a + triple: aarch64-linux-android + # Google broke ARM64 emulation on x86_64 hosts. A workaround is to overwrite the qemu machine type. + emu-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none -accel off -qemu -machine virt + api-level: [ 27, 33 ] + # Please note that: + # - arm64-v8a emulation on a x86_64 host currently is only possible up to API level 27 Oreo + # - armeabi-v7a is only supported up to API level 24 + exclude: + - api-level: 33 + arch: + name: arm64-v8a + # Don't abort runners if a single one fails fail-fast: false runs-on: ${{ matrix.os }} name: Android ${{ matrix.build-type }} ${{ matrix.arch.name }} API-${{ matrix.api-level }} @@ -279,13 +291,31 @@ jobs: run: | sudo apt-get update -y sudo apt-get install patchelf ninja-build -y - - uses: nttld/setup-ndk@v1 - id: setup-ndk + - name: Enable KVM + run: | + 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 + - name: AVD cache + uses: actions/cache@v4 + id: avd-cache + with: + path: | + ~/.android/avd/* + ~/.android/adb* + key: avd-${{ matrix.api-level }}-${{ matrix.arch.name }} + - name: Create AVD and Snapshot for Caching + if: steps.avd-cache.outputs.cache-hit != 'true' + uses: hmelder/android-emulator-runner@v2.33.2 with: - ndk-version: r26d + api-level: ${{ matrix.api-level }} + arch: ${{ matrix.arch.name }} + force-avd-creation: false + emulator-options: ${{ matrix.arch.emu-options }} + disable-animations: true + script: echo "Generated AVD snapshot for caching." + # We are using the default NDK from the GitHub Actions runner. - name: Configure CMake - env: - ANDROID_NDK_HOME: ${{ steps.setup-ndk.outputs.ndk-path }} run: | export TOOLCHAIN=$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64 export CCPREFIX=$TOOLCHAIN/bin/${{ matrix.arch.triple }}${{ matrix.api-level }} @@ -321,13 +351,14 @@ jobs: run: | NINJA_STATUS="%p [%f:%s/%t] %o/s, %es" ninja -v - name: Test - uses: reactivecircus/android-emulator-runner@v2 - env: - ANDROID_NDK_HOME: ${{ steps.setup-ndk.outputs.ndk-path }} + uses: hmelder/android-emulator-runner@v2.33.2 with: api-level: ${{ matrix.api-level }} - target: default arch: ${{ matrix.arch.name }} + force-avd-creation: false + emulator-options: ${{ matrix.arch.emu-options }} + disable-animations: true + target: default script: | ${{github.workspace}}/.github/scripts/android_test_main.sh ${{github.workspace}}/build ${ANDROID_NDK_HOME}/toolchains/llvm/prebuilt/linux-x86_64/sysroot ${{ matrix.arch.triple }} diff --git a/prepare_android_env.sh b/prepare_android_env.sh new file mode 100644 index 0000000..d4d3aae --- /dev/null +++ b/prepare_android_env.sh @@ -0,0 +1,32 @@ +#!/bin/sh + +export ANDROID_NDK_HOME=~/Library/Android/sdk/ndk/24.0.8215888 +export TOOLCHAIN=$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/darwin-x86_64 +export CCPREFIX=$TOOLCHAIN/bin/aarch64-linux-android24 +export CC="$CCPREFIX-clang" +export CXX="$CCPREFIX-clang++" +export OBJC="$CCPREFIX-clang" +export OBJCXX="$CCPREFIX-clang++" +export AS="$CCPREFIX-clang" +export LD="$TOOLCHAIN/bin/ld.lld" +export AR="$TOOLCHAIN/bin/llvm-ar" +export RANLIB="$TOOLCHAIN/bin/llvm-ranlib" +export STRIP="$TOOLCHAIN/bin/llvm-strip" +export NM="$TOOLCHAIN/bin/llvm-nm" +export OBJDUMP="$TOOLCHAIN/bin/llvm-objdump" +export LDFLAGS="-fuse-ld=lld" +export LIBS="-lc++_shared" + +cmake -B build \ + -DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK_HOME/build/cmake/android.toolchain.cmake \ + -DANDROID_ABI=arm64-v8a \ + -DANDROID_NDK=$ANDROID_NDK_HOME \ + -DANDROID_STL=c++_shared \ + -DCMAKE_FIND_USE_CMAKE_PATH=false \ + -DCMAKE_C_COMPILER=$CC \ + -DCMAKE_CXX_COMPILER=$CXX \ + -DCMAKE_ASM_COMPILER=$AS \ + -DCMAKE_BUILD_TYPE=Debug \ + -DTESTS=ON \ + -DANDROID_PLATFORM=android-24 \ + -G Ninja