130 lines
5.7 KiB
Bash
Executable File
130 lines
5.7 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
if [[ $# -ne 4 ]]; then
|
|
echo "usage: $0 CONFIG ARCHITECTURE VERSION OUTPUT_DIR" >&2
|
|
exit 2
|
|
fi
|
|
|
|
config=$1
|
|
architecture=$2
|
|
version=$3
|
|
output_dir=$4
|
|
repo_root=$(CDPATH= cd -- "$(dirname -- "$0")/../.." && pwd)
|
|
|
|
[[ $architecture =~ ^[a-zA-Z0-9_-]+$ ]] || { echo "invalid architecture name: $architecture" >&2; exit 2; }
|
|
[[ $version =~ ^(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)$ ]] || { echo "invalid semantic version: $version" >&2; exit 2; }
|
|
|
|
matches=$(jq --arg architecture "$architecture" '[.targets[] | select(.architecture == $architecture)] | length' "$config")
|
|
[[ $matches -eq 1 ]] || { echo "architecture must occur exactly once in $config: $architecture" >&2; exit 2; }
|
|
openwrt_release=$(jq -er '.openwrt_release' "$config")
|
|
target=$(jq -er --arg architecture "$architecture" '.targets[] | select(.architecture == $architecture) | .target' "$config")
|
|
subtarget=$(jq -er --arg architecture "$architecture" '.targets[] | select(.architecture == $architecture) | .subtarget' "$config")
|
|
|
|
download_base="https://downloads.openwrt.org/releases/${openwrt_release}/targets/${target}/${subtarget}"
|
|
sdk_archive=$(curl -fsSL "${download_base}/" | grep -o "openwrt-sdk-${openwrt_release}-[^\"]*\.tar\.zst" | head -n 1)
|
|
[[ -n $sdk_archive ]] || { echo "no SDK found at $download_base" >&2; exit 1; }
|
|
|
|
work_dir="${RUNNER_TEMP:-/tmp}/openunifi-${architecture}-${version}"
|
|
rm -rf -- "$work_dir"
|
|
mkdir -p -- "$work_dir" "$repo_root/$output_dir"
|
|
curl -fL --retry 3 --output "$work_dir/$sdk_archive" "$download_base/$sdk_archive"
|
|
expected_sha=$(curl -fsSL "$download_base/sha256sums" | awk -v archive="$sdk_archive" '{ name=$2; sub(/^\*/, "", name); if (name == archive) { print $1; exit } }')
|
|
[[ -n $expected_sha ]] || { echo "no checksum found for $sdk_archive" >&2; exit 1; }
|
|
printf '%s %s\n' "$expected_sha" "$work_dir/$sdk_archive" | sha256sum --check
|
|
|
|
tar --zstd -xf "$work_dir/$sdk_archive" -C "$work_dir"
|
|
sdk_dir=$(find "$work_dir" -mindepth 1 -maxdepth 1 -type d -name 'openwrt-sdk-*' -print -quit)
|
|
[[ -n $sdk_dir ]] || { echo "SDK directory was not extracted" >&2; exit 1; }
|
|
|
|
cd "$sdk_dir"
|
|
|
|
# OpenWrt publishes relocatable SDKs whose host tools are x86-64 binaries.
|
|
# On ARM runners, invoke the SDK's bundled x86-64 loader explicitly through
|
|
# QEMU. This works without privileged binfmt_misc registration on the host.
|
|
build_host=$(uname -m)
|
|
case $build_host in
|
|
x86_64|amd64)
|
|
;;
|
|
aarch64|arm64|armv7l|armv8l)
|
|
qemu_x86_64=$(command -v qemu-x86_64-static || command -v qemu-x86_64 || true)
|
|
[[ -n $qemu_x86_64 ]] || {
|
|
echo "ARM build host requires qemu-x86_64-static (install qemu-user-static)" >&2
|
|
exit 1
|
|
}
|
|
mapfile -d '' sdk_wrappers < <(
|
|
find staging_dir -type f -exec grep -IlZ 'ld-linux-x86-64\.so\.2' {} +
|
|
)
|
|
[[ ${#sdk_wrappers[@]} -gt 0 ]] || {
|
|
echo "no relocatable x86-64 SDK wrappers found" >&2
|
|
exit 1
|
|
}
|
|
sed -i -E \
|
|
-e 's|^export LD_PRELOAD=.*(\$dir/.*runas\.so)"$|sdk_preload="\1"|' \
|
|
-e "s|^exec (\"\\\$dir/.*ld-linux-x86-64\\.so\\.2\")|exec ${qemu_x86_64} \\1 --preload \"\\\$sdk_preload\"|" \
|
|
"${sdk_wrappers[@]}"
|
|
staging_dir/host/bin/sed --version >/dev/null
|
|
;;
|
|
*)
|
|
echo "unsupported build host architecture: $build_host" >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
|
|
# Install the package definitions needed by openuf. The feeds tool recursively
|
|
# installs their transitive package definitions; OpenWrt's build graph then
|
|
# compiles that dependency closure before openuf.
|
|
./scripts/feeds update base packages
|
|
./scripts/feeds install mbedtls uci usteer
|
|
|
|
# openuf needs the mbedTLS libraries, not its optional example/utility
|
|
# executables. Under x86 user emulation on ARM, linking those large programs is
|
|
# unreliable and unnecessary, so keep the library build and omit the programs.
|
|
mbedtls_makefile=feeds/base_root/package/libs/mbedtls/Makefile
|
|
[[ -f $mbedtls_makefile ]] || {
|
|
echo "mbedTLS feed Makefile not found: $mbedtls_makefile" >&2
|
|
exit 1
|
|
}
|
|
sed -i 's/-DENABLE_PROGRAMS:Bool=ON/-DENABLE_PROGRAMS:Bool=OFF/' "$mbedtls_makefile"
|
|
grep -q -- '-DENABLE_PROGRAMS:Bool=OFF' "$mbedtls_makefile"
|
|
|
|
mkdir -p package/openuf
|
|
(cd "$repo_root" && tar --exclude=.git --exclude="$output_dir" -cf - .) | (cd package/openuf && tar -xf -)
|
|
sed -i -E "s/^(PKG_VERSION[[:space:]]*:?=[[:space:]]*).*/\\1${version}/" package/openuf/Makefile
|
|
|
|
# Release SDKs remember the package set used to create the SDK. Neutralize
|
|
# those baked-in defaults so this job builds openuf and its dependency closure,
|
|
# rather than every package and kernel module available for the target.
|
|
sed -i -E '/^config PACKAGE_/,/^$/ s/^([[:space:]]*)default [ym]$/\1default n/' Config-build.in
|
|
for symbol in TARGET_MULTI_PROFILE TARGET_ALL_PROFILES TARGET_PER_DEVICE_ROOTFS ALL_NONSHARED ALL_KMODS ALL BUILDBOT; do
|
|
sed -i -E "/^config ${symbol}$/,/^$/ s/^([[:space:]]*)default y$/\\1default n/" Config.in Config-build.in
|
|
done
|
|
printf '%s\n' \
|
|
'# CONFIG_ALL is not set' \
|
|
'# CONFIG_ALL_KMODS is not set' \
|
|
'# CONFIG_ALL_NONSHARED is not set' \
|
|
'# CONFIG_TARGET_MULTI_PROFILE is not set' \
|
|
'# CONFIG_TARGET_ALL_PROFILES is not set' \
|
|
'CONFIG_PACKAGE_openuf=m' >.config
|
|
make defconfig
|
|
build_jobs=$(nproc)
|
|
case $build_host in
|
|
aarch64|arm64|armv7l|armv8l)
|
|
(( build_jobs <= 2 )) || build_jobs=2
|
|
;;
|
|
esac
|
|
if ! make -j"$build_jobs" package/openuf/compile; then
|
|
echo "parallel build failed; retrying serially with verbose diagnostics" >&2
|
|
make -j1 package/openuf/compile V=sc
|
|
fi
|
|
|
|
mapfile -t packages < <(find bin/packages -type f -name "openuf-${version}-*.apk")
|
|
if [[ ${#packages[@]} -ne 1 ]]; then
|
|
echo "expected one openuf package, found ${#packages[@]}" >&2
|
|
printf '%s\n' "${packages[@]}" >&2
|
|
exit 1
|
|
fi
|
|
asset="$repo_root/$output_dir/openUniFi-${architecture}-${version}.apk"
|
|
cp -- "${packages[0]}" "$asset"
|
|
sha256sum "$asset"
|