Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 91 additions & 0 deletions .github/workflows/android.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
# Android cross-build — core libdb for aarch64-linux-android (bionic libc).
#
# Dedicated workflow (does NOT touch ci.yml). Cross-compiles the core C
# library with the NDK's clang against the existing root meson.build and
# asserts that a real ARM aarch64 libdb.so is produced. This is a cross-BUILD
# test: no emulator or device is used or needed.
#
# The NDK clang is just a cross-compiler; meson's HAVE_* probes are all
# compile/link checks (which succeed cross) and sizeof/alignment resolve via
# compile-only probes, so no target execution is required and no db_config.h
# hand-patching is needed. As of this workflow the core library cross-builds
# clean with zero source changes.
#
# continue-on-error keeps the job advisory (Android is not yet a release
# target), but the cross-build + `file` assertion are a real signal: a
# regression that breaks the arm64 build turns the assert step red.

name: Android

on:
push:
branches: [master]
pull_request:
paths:
- 'src/**'
- 'meson.build'
- 'meson_options.txt'
- 'meson/**'
- 'dist/android/**'
- '.github/workflows/android.yml'
schedule:
# Weekly (Mon 04:23 UTC): catches NDK/toolchain drift on a low cadence.
- cron: '23 4 * * 1'
workflow_dispatch:
inputs:
api:
description: 'Android API level'
default: '24'

concurrency:
group: android-${{ github.ref }}
cancel-in-progress: true

permissions:
contents: read

jobs:
cross-aarch64:
name: cross-build aarch64-linux-android (API ${{ github.event.inputs.api || '24' }})
runs-on: ubuntu-latest
continue-on-error: true # advisory tier — Android is not yet a release target
steps:
- uses: actions/checkout@v4

- uses: actions/setup-python@v5
with:
python-version: '3.12'

- name: Install Meson + Ninja
run: python -m pip install --upgrade meson ninja

- name: Set up Android NDK
id: ndk
uses: nttld/setup-ndk@v1
with:
# r29 matches the nixpkgs ndk-bundle this path was validated against.
ndk-version: r29
local-cache: true

- name: Cross-build libdb.so (aarch64)
env:
ANDROID_NDK_ROOT: ${{ steps.ndk.outputs.ndk-path }}
run: |
dist/android/build_android.sh aarch64 "${{ github.event.inputs.api || 24 }}"

- name: Assert the artifact is an ARM aarch64 shared object
run: |
out=build-android/libdb.so
file "$out"
# Real gate: fail if it is not an AArch64 ELF shared object.
file "$out" | grep -q 'ELF 64-bit LSB shared object, ARM aarch64' \
|| { echo "::error title=Android build::libdb.so is not aarch64"; exit 1; }
echo "::notice title=Android build::core libdb cross-built for aarch64-linux-android"

- name: Upload libdb.so (arm64)
if: always()
uses: actions/upload-artifact@v4
with:
name: libdb-android-aarch64
path: build-android/libdb.so
if-no-files-found: ignore
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ test/sim/TESTDIR_sim_*/
# Meson/Ninja out-of-tree build dirs
build-meson/
build/
build-android/
build-android.cross.txt

# nix build output symlink
/result
Expand Down
85 changes: 85 additions & 0 deletions dist/android/build_android.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
#!/bin/sh
# Cross-compile the core libdb C library for Android via the NDK's clang and
# the existing root meson.build. Produces build-android/libdb.so (aarch64 by
# default). No emulator/device needed -- this is a cross-BUILD test.
#
# The NDK clang is just a cross-compiler: meson's HAVE_* probes are all
# compile/link checks (which work when cross-compiling) and sizeof/alignment
# are resolved by compile-only probes, so no target execution is required.
#
# Usage:
# ANDROID_NDK_ROOT=/path/to/ndk dist/android/build_android.sh [ABI] [API]
#
# ABI : android ABI -> aarch64 (default) | arm | x86_64 | x86
# API : android API level -> 24 (default)
#
# ANDROID_NDK_ROOT is exported by nttld/setup-ndk and android-actions/setup-android.
# ANDROID_NDK_HOME / NDK are accepted as fallbacks.
set -eu

ABI="${1:-aarch64}"
API="${2:-24}"

NDK="${ANDROID_NDK_ROOT:-${ANDROID_NDK_HOME:-${NDK:-}}}"
if [ -z "$NDK" ]; then
echo "error: set ANDROID_NDK_ROOT (or ANDROID_NDK_HOME / NDK) to the NDK root" >&2
exit 2
fi

# NDK layout: toolchains/llvm/prebuilt/<host>/bin/<triple><API>-clang
# nixpkgs' ndk-bundle nests the real NDK under libexec/android-sdk/ndk/<ver>/.
if [ ! -d "$NDK/toolchains" ]; then
nested=$(find "$NDK" -maxdepth 5 -type d -path '*/toolchains/llvm/prebuilt/*/bin' 2>/dev/null | head -1)
[ -n "$nested" ] && NDK=$(dirname "$(dirname "$(dirname "$(dirname "$(dirname "$nested")")")")")
fi

case "$(uname -s)" in
Linux) HOSTTAG=linux-x86_64 ;;
Darwin) HOSTTAG=darwin-x86_64 ;;
*) echo "error: unsupported build host $(uname -s)" >&2; exit 2 ;;
esac
BIN="$NDK/toolchains/llvm/prebuilt/$HOSTTAG/bin"

case "$ABI" in
aarch64) TRIPLE=aarch64-linux-android; CPUFAM=aarch64; CPU=aarch64 ;;
arm) TRIPLE=armv7a-linux-androideabi; CPUFAM=arm; CPU=armv7a ;;
x86_64) TRIPLE=x86_64-linux-android; CPUFAM=x86_64; CPU=x86_64 ;;
x86) TRIPLE=i686-linux-android; CPUFAM=x86; CPU=i686 ;;
*) echo "error: unknown ABI '$ABI' (aarch64|arm|x86_64|x86)" >&2; exit 2 ;;
esac

CC="$BIN/${TRIPLE}${API}-clang"
CXX="$BIN/${TRIPLE}${API}-clang++"
[ -x "$CC" ] || { echo "error: NDK compiler not found: $CC" >&2; exit 2; }

ROOT=$(cd "$(dirname "$0")/../.." && pwd)
BUILDDIR="${BUILDDIR:-$ROOT/build-android}"
CROSS="$BUILDDIR.cross.txt"
mkdir -p "$BUILDDIR"

cat > "$CROSS" <<EOF
# Generated by dist/android/build_android.sh -- do not commit.
[binaries]
c = '$CC'
cpp = '$CXX'
ar = '$BIN/llvm-ar'
strip = '$BIN/llvm-strip'
ranlib = '$BIN/llvm-ranlib'

[host_machine]
system = 'android'
cpu_family = '$CPUFAM'
cpu = '$CPU'
endian = 'little'
EOF

echo "== NDK: $NDK"
echo "== CC: $CC"
echo "== out: $BUILDDIR/libdb.so"

meson setup "$BUILDDIR" "$ROOT" --cross-file "$CROSS" --wipe 2>/dev/null \
|| meson setup "$BUILDDIR" "$ROOT" --cross-file "$CROSS"
ninja -C "$BUILDDIR"

"$BIN/llvm-strip" -o "$BUILDDIR/libdb.so.stripped" "$BUILDDIR/libdb.so" 2>/dev/null || true
file "$BUILDDIR/libdb.so"
Loading