feat: support android platform cross build#90
Conversation
| runs-on: ubuntu-22.04 | ||
| strategy: | ||
| fail-fast: false | ||
| matrix: | ||
| abi: [arm64-v8a] | ||
| api: [30] # arm64 emulator 建议 >= 30,21 常见拉不到/不稳定 | ||
|
|
||
| steps: | ||
| - name: Checkout | ||
| uses: actions/checkout@v4 | ||
|
|
||
| - name: Cache dependencies | ||
| uses: actions/cache@v3 | ||
| with: | ||
| path: | | ||
| ~/.ccache | ||
| key: ${{ runner.os }}-dependencies-cache-${{ hashFiles('**/CMakeLists.txt', 'thirdparty/**') }}-stl-fix | ||
| restore-keys: | | ||
| ${{ runner.os }}-dependencies-cache- | ||
|
|
||
| - name: Install dependencies | ||
| run: | | ||
| sudo apt-get update | ||
| sudo apt-get install -y --no-install-recommends \ | ||
| cmake ninja-build git ca-certificates python3 \ | ||
| build-essential make ccache | ||
|
|
||
| - name: Setup Java 17 | ||
| uses: actions/setup-java@v4 | ||
| with: | ||
| distribution: temurin | ||
| java-version: '17' | ||
|
|
||
| - name: Setup Android SDK | ||
| uses: android-actions/setup-android@v3 | ||
|
|
||
| - name: Install NDK (side by side) | ||
| shell: bash | ||
| run: | | ||
| sdkmanager "ndk;26.1.10909125" | ||
|
|
||
| - name: Cache host protoc build | ||
| uses: actions/cache@v3 | ||
| with: | ||
| path: build-host | ||
| key: ${{ runner.os }}-host-protoc-${{ hashFiles('src/**', 'CMakeLists.txt') }}-stl-fix | ||
| restore-keys: | | ||
| ${{ runner.os }}-host-protoc- | ||
|
|
||
| - name: Use host env to compile protoc | ||
| shell: bash | ||
| run: | | ||
| git submodule update --init | ||
| if [ ! -d "build-host" ]; then | ||
| export CCACHE_BASEDIR="$GITHUB_WORKSPACE" | ||
| export CCACHE_NOHASHDIR=1 | ||
| export CCACHE_SLOPPINESS=clang_index_store,file_stat_matches,include_file_mtime,locale,time_macros | ||
|
|
||
| cmake -S . -B build-host -G Ninja \ | ||
| -DCMAKE_C_COMPILER_LAUNCHER=ccache \ | ||
| -DCMAKE_CXX_COMPILER_LAUNCHER=ccache | ||
| cmake --build build-host --target protoc --parallel | ||
| else | ||
| echo "Using cached host protoc build" | ||
| fi | ||
|
|
||
| - name: Cache Android build | ||
| uses: actions/cache@v3 | ||
| with: | ||
| path: build-android-${{ matrix.abi }} | ||
| key: ${{ runner.os }}-android-build-${{ matrix.abi }}-${{ hashFiles('src/**', 'CMakeLists.txt', 'cmake/**', 'thirdparty/**') }}-stl-fix-2 | ||
|
|
||
| - name: Configure and Build | ||
| shell: bash | ||
| run: | | ||
| git submodule foreach --recursive 'git stash --include-untracked' | ||
|
|
||
| export ANDROID_SDK_ROOT="$ANDROID_HOME" | ||
| export ANDROID_NDK_HOME="$ANDROID_SDK_ROOT/ndk/26.1.10909125" | ||
|
|
||
| export CCACHE_BASEDIR="$GITHUB_WORKSPACE" | ||
| export CCACHE_NOHASHDIR=1 | ||
| export CCACHE_SLOPPINESS=clang_index_store,file_stat_matches,include_file_mtime,locale,time_macros | ||
|
|
||
| if [ ! -d "build-android-${{ matrix.abi }}" ]; then | ||
| cmake -S . -B build-android-${{ matrix.abi }} -G Ninja \ | ||
| -DCMAKE_BUILD_TYPE=Release \ | ||
| -DCMAKE_TOOLCHAIN_FILE="$ANDROID_NDK_HOME/build/cmake/android.toolchain.cmake" \ | ||
| -DANDROID_ABI=${{ matrix.abi }} \ | ||
| -DANDROID_PLATFORM=android-${{ matrix.api }} \ | ||
| -DANDROID_STL=c++_static \ | ||
| -DBUILD_PYTHON_BINDINGS=OFF \ | ||
| -DBUILD_TOOLS=OFF \ | ||
| -DGLOBAL_CC_PROTOBUF_PROTOC="$GITHUB_WORKSPACE/build-host/bin/protoc" \ | ||
| -DCMAKE_C_COMPILER_LAUNCHER=ccache \ | ||
| -DCMAKE_CXX_COMPILER_LAUNCHER=ccache | ||
| cmake --build build-android-${{ matrix.abi }} --parallel | ||
| else | ||
| echo "Using cached Android build directory" | ||
| fi | ||
|
|
||
| - name: Cache examples build | ||
| uses: actions/cache@v3 | ||
| with: | ||
| path: examples/c++/build-android-examples-${{ matrix.abi }} | ||
| key: ${{ runner.os }}-examples-build-${{ matrix.abi }}-${{ hashFiles('examples/c++/**', 'CMakeLists.txt', 'src/**') }}-stl-fix-2 | ||
|
|
||
| - name: Build examples | ||
| shell: bash | ||
| run: | | ||
| export ANDROID_SDK_ROOT="$ANDROID_HOME" | ||
| export ANDROID_NDK_HOME="$ANDROID_SDK_ROOT/ndk/26.1.10909125" | ||
|
|
||
| if [ ! -d "examples/c++/build-android-examples-${{ matrix.abi }}" ]; then | ||
| cmake -S examples/c++ -B examples/c++/build-android-examples-${{ matrix.abi }} -G Ninja \ | ||
| -DCMAKE_TOOLCHAIN_FILE="$ANDROID_NDK_HOME/build/cmake/android.toolchain.cmake" \ | ||
| -DANDROID_ABI=${{ matrix.abi }} \ | ||
| -DANDROID_PLATFORM=android-${{ matrix.api }} \ | ||
| -DANDROID_STL=c++_static \ | ||
| -DCMAKE_BUILD_TYPE=Release \ | ||
| -DCMAKE_INTERPROCEDURAL_OPTIMIZATION=ON \ | ||
| -DHOST_BUILD_DIR="build-android-${{ matrix.abi }}" \ | ||
| -DCMAKE_C_COMPILER_LAUNCHER=ccache \ | ||
| -DCMAKE_CXX_COMPILER_LAUNCHER=ccache | ||
| cmake --build examples/c++/build-android-examples-${{ matrix.abi }} --parallel | ||
| else | ||
| echo "Using cached examples build" | ||
| fi | ||
|
|
||
| # 注意:emulator-runner 的 arch 需要 "arm64"(不是 arm64-v8a) | ||
| - name: Run on Android emulator (arm64) and verify | ||
| uses: reactivecircus/android-emulator-runner@v2 | ||
| with: | ||
| api-level: ${{ matrix.api }} | ||
| arch: arm64 | ||
| target: google_apis | ||
| emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -netdelay none -netspeed full | ||
| disable-animations: true | ||
| script: | | ||
| set -euxo pipefail | ||
|
|
||
| adb wait-for-device | ||
|
|
||
| echo "Device ABI:" | ||
| adb shell getprop ro.product.cpu.abi | ||
| adb shell getprop ro.product.cpu.abilist | ||
|
|
||
| echo "Checking binary sizes:" | ||
| ls -lah examples/c++/build-android-examples-${{ matrix.abi }}/ | ||
|
|
||
| # Push executables to device | ||
| adb push examples/c++/build-android-examples-${{ matrix.abi }}/ailego-example /data/local/tmp/ | ||
| adb push examples/c++/build-android-examples-${{ matrix.abi }}/core-example /data/local/tmp/ | ||
| adb push examples/c++/build-android-examples-${{ matrix.abi }}/db-example /data/local/tmp/ | ||
|
|
||
| adb shell chmod 755 /data/local/tmp/ailego-example | ||
| adb shell chmod 755 /data/local/tmp/core-example | ||
| adb shell chmod 755 /data/local/tmp/db-example | ||
|
|
||
| echo "File info on device:" | ||
| adb shell ls -la /data/local/tmp/ailego-example | ||
| adb shell ls -la /data/local/tmp/core-example | ||
| adb shell ls -la /data/local/tmp/db-example | ||
|
|
||
| echo "Running ailego example:" | ||
| adb shell 'cd /data/local/tmp && ./ailego-example' | ||
|
|
||
| echo "Running core example:" | ||
| adb shell 'cd /data/local/tmp && ./core-example' | ||
|
|
||
| echo "Running db example:" | ||
| adb shell 'cd /data/local/tmp && ./db-example' |
Check warning
Code scanning / CodeQL
Workflow does not contain permissions Medium
Show autofix suggestion
Hide autofix suggestion
Copilot Autofix
AI about 8 hours ago
To fix the problem, explicitly declare least-privilege GITHUB_TOKEN permissions for this workflow. Since the job only needs to read repository contents (for actions/checkout) and interact with caches (which do not require repository write access), contents: read is sufficient as a minimal baseline. We can place a permissions: block at the root of the workflow, so it applies to all jobs, and keep it minimal.
The best fix without changing functionality is:
- Add a root-level
permissions:block aftername:(or afteron:) settingcontents: read. - No job seems to require writes to pull requests, issues, or other resources, so we do not grant them.
Concretely, in .github/workflows/android_build.yml, add:
permissions:
contents: readright after the name: android-cross-build line. No additional imports or methods are needed since this is pure workflow configuration.
| @@ -1,5 +1,8 @@ | ||
| name: android-cross-build | ||
|
|
||
| permissions: | ||
| contents: read | ||
|
|
||
| on: | ||
| push: | ||
| branches: [ "main" ] |
resolve #93