enprot 0.4.2

Engyon Protected Text (EPT) — confidentiality processor and capability ledger
name: ohos

# Cross-compile enprot + Botan for aarch64-linux-ohos (OpenHarmony).
# See TODO.finalize/51-ohos-build-target.md for the design.
#
# Until the cross-compilation is verified green on CI, this workflow
# is non-blocking (continue-on-error). Once stable, drop the
# continue-on-error flag and add `ohos` to required status checks.
#
# Reference impl: https://gist.github.com/ronaldtse/78b6b610cfa00ead8fb3b8f935afaa3b

on:
  pull_request:
  push:
    branches:
      - main
    tags:
      - '[0-9]+.[0-9]+.[0-9]+'
  workflow_dispatch:

concurrency:
  group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
  cancel-in-progress: true

env:
  RUST_BACKTRACE: full
  BOTAN_VERSION: "3.7.0"
  # Rust uses aarch64-unknown-linux-ohos (with vendor field); the NDK
  # clang binary also uses that form, but the sysroot path uses
  # aarch64-linux-ohos (no vendor). ci/setup-ohos-ndk.sh handles the
  # discrepancy.
  RUST_TARGET: aarch64-unknown-linux-ohos
  NDK_TRIPLE: aarch64-linux-ohos
  NDK_PREFIX: ext/ohos

jobs:
  build-aarch64-linux-ohos:
    name: Build aarch64-linux-ohos
    runs-on: ubuntu-latest
    continue-on-error: true
    timeout-minutes: 45
    steps:
      - uses: actions/checkout@v7

      - name: Install build deps
        run: |
          sudo apt-get update
          sudo apt-get install -y --no-install-recommends \
            cmake ninja-build zlib1g-dev \
            curl jq unzip python3 git g++ make

      - name: Install Rust target
        run: |
          rustup target add ${{ env.RUST_TARGET }}
          rustup toolchain list

      - name: Cache OHOS NDK
        id: cache-ndk
        uses: actions/cache@v4
        with:
          path: ${{ env.NDK_PREFIX }}
          key: ohos-ndk-${{ env.NDK_TRIPLE }}-${{ hashFiles('ci/setup-ohos-ndk.sh') }}

      - name: Setup OHOS NDK
        if: steps.cache-ndk.outputs.cache-hit != 'true'
        run: |
          bash ci/setup-ohos-ndk.sh --prefix ${{ env.NDK_PREFIX }} --ndk-triple ${{ env.NDK_TRIPLE }}

      - name: Cache Botan build
        id: cache-botan
        uses: actions/cache@v4
        with:
          path: |
            ${{ env.NDK_PREFIX }}/ohos-aarch64
            ${{ env.NDK_PREFIX }}/botan-build
          key: ohos-botan-${{ env.BOTAN_VERSION }}-${{ env.NDK_TRIPLE }}-${{ hashFiles('ci/build-botan-ohos.sh', 'ci/botan-modules') }}

      - name: Cross-compile Botan 3 (static)
        if: steps.cache-botan.outputs.cache-hit != 'true'
        run: |
          bash ci/build-botan-ohos.sh \
            --prefix ${{ env.NDK_PREFIX }} \
            --botan-version ${{ env.BOTAN_VERSION }} \
            --ndk-triple ${{ env.NDK_TRIPLE }}

      - name: Build enprot
        run: |
          # Resolve everything to absolute paths — pkg-config requires
          # absolute PKG_CONFIG_PATH.
          ROOT="$GITHUB_WORKSPACE"
          PREFIX="$ROOT/${{ env.NDK_PREFIX }}"
          SYSROOT="$PREFIX/llvm-19/sysroot/${{ env.NDK_TRIPLE }}"
          # NDK ships clang binaries as aarch64-unknown-linux-ohos-clang++.
          NDK_CLANGXX="$PREFIX/llvm-19/llvm/bin/aarch64-unknown-linux-ohos-clang++"
          export PKG_CONFIG_PATH="$PREFIX/ohos-aarch64/lib/pkgconfig"
          export PKG_CONFIG_ALLOW_CROSS=1
          # Do NOT set PKG_CONFIG_SYSROOT_DIR — Botan's .pc file already
          # contains absolute paths, and pkg-config would prepend the
          # sysroot to them, producing a broken concatenated path
          # (.../sysroot/aarch64-linux-ohos/home/runner/...).
          # botan-sys reads BOTAN_STATIC=1 to force static linking against
          # the .a we cross-compiled; otherwise it tries to link libbotan-3.so.
          export BOTAN_STATIC=1
          # Cargo env var name is uppercased RUST_TARGET with _ for -.
          export CARGO_TARGET_AARCH64_UNKNOWN_LINUX_OHOS_LINKER="$NDK_CLANGXX"
          # Link args:
          #   --target/--sysroot  → NDK clang picks the right runtime
          #   -L$PREFIX/ohos-aarch64/lib  → find libbotan-3.a
          #   -lc++ -lc++abi  → C++ runtime (Botan is C++/libc++; -lstdc++
          #                      would pull the wrong ABI).
          export CARGO_TARGET_AARCH64_UNKNOWN_LINUX_OHOS_RUSTFLAGS="-C link-arg=--target=${{ env.NDK_TRIPLE }} -C link-arg=--sysroot=$SYSROOT -C link-arg=-L$PREFIX/ohos-aarch64/lib -C link-arg=-lc++ -C link-arg=-lc++abi"
          echo "=== botan-3.pc location ==="
          ls -la "$PKG_CONFIG_PATH" || true
          echo "=== botan-3.pc contents ==="
          cat "$PKG_CONFIG_PATH/botan-3.pc" || true
          echo "=== libbotan-3.a location ==="
          ls -la "$PREFIX/ohos-aarch64/lib/" | grep -E 'botan|\.a' || true
          cargo build --target ${{ env.RUST_TARGET }} --release

      - name: Build smoke test
        run: |
          CLANG=${{ env.NDK_PREFIX }}/llvm-19/llvm/bin/aarch64-unknown-linux-ohos-clang
          BOTAN_LIB=${{ env.NDK_PREFIX }}/ohos-aarch64/lib/libbotan-3.a
          BOTAN_INC=${{ env.NDK_PREFIX }}/ohos-aarch64/include/botan-3
          SYSROOT=${{ env.NDK_PREFIX }}/llvm-19/sysroot/${{ env.NDK_TRIPLE }}
          mkdir -p ohos-verify
          "$CLANG" \
            --target=${{ env.NDK_TRIPLE }} --sysroot="$SYSROOT" \
            -O2 -I"$BOTAN_INC" \
            ci/ohos-smoke.c "$BOTAN_LIB" \
            -lc++ -lc++abi -lpthread -ldl \
            -o ohos-verify/ohos-smoke

      - name: Copy binary for verification
        run: |
          cp target/${{ env.RUST_TARGET }}/release/enprot ohos-verify/enprot

      - name: Verify in dockerharmony
        uses: addnab/docker-run-action@v3
        with:
          image: ghcr.io/hqzing/dockerharmony:latest
          options: -v ${{ github.workspace }}/ohos-verify:/work -w /work
          run: |
            echo "--- enprot --version ---"
            chmod +x ./enprot && ./enprot --version || true
            echo "--- smoke test ---"
            chmod +x ./ohos-smoke && ./ohos-smoke

      - name: Upload artifacts
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: enprot-${{ env.RUST_TARGET }}
          path: |
            target/${{ env.RUST_TARGET }}/release/enprot
            ohos-verify/