Files
agnos-builder/Dockerfile.alpine

178 lines
8.1 KiB
Docker

# check=error=true
# SPIKE: AGNOS on Alpine Linux (musl, runit, eudev, busybox). See userspace/alpine/.
# The adbd and graphics stages are the same Ubuntu stages as Dockerfile.agnos.
# ################## #
# ### Package ##### #
# ### Compilation ## #
# ################## #
FROM ubuntu:24.04 AS agnos-compiler
RUN apt-get update && apt-get install -yq --no-install-recommends build-essential
# ADB daemon using the Android libraries already installed for Ubuntu's adb client.
FROM agnos-compiler AS agnos-compiler-adbd
RUN apt-get update && apt-get install -yq --no-install-recommends \
ca-certificates curl clang android-libbase-dev android-libcutils-dev android-liblog-dev \
android-libboringssl-dev libbrotli-dev libcap-dev liblz4-dev libprotobuf-dev protobuf-compiler \
libsystemd-dev libzstd-dev
COPY ./userspace/build_adbd.sh ./userspace/adbd-linux.patch /tmp/agnos/
RUN /tmp/agnos/build_adbd.sh
# Qualcomm graphics without Wayland or OpenCL runtime dependencies
FROM agnos-compiler AS agnos-compiler-graphics
RUN apt-get update && apt-get install -yq --no-install-recommends patchelf
COPY ./userspace/graphics/ /tmp/agnos/graphics-src/
RUN mkdir -p /tmp/agnos/graphics && \
cp /tmp/agnos/graphics-src/libgbm.so /tmp/agnos/graphics/ && \
cp /tmp/agnos/graphics-src/libeglSubDriverWayland.so.patched /tmp/agnos/graphics/libeglSubDriverWayland.so && \
cd /tmp/agnos/graphics && \
gcc -shared -fPIC -Os -s -Wall -Wextra -Werror -Wl,-z,defs -Wl,-z,relro,-z,now \
-Wl,-soname,libagnos-wayland-stubs.so -o libagnos-wayland-stubs.so /tmp/agnos/graphics-src/stubs.c && \
gcc -shared -fPIC -Os -s -Wall -Wextra -Werror -Wl,-z,defs -Wl,-z,relro,-z,now \
-Wl,-soname,libCB.so -o libCB.so /tmp/agnos/graphics-src/opencl_stubs.c && \
nm -D --defined-only libagnos-wayland-stubs.so | \
awk '$3 ~ /^agnos_/ { name = $3; sub(/^agnos_/, "", name); print name, $3 }' > /tmp/agnos/graphics-symbols.map && \
for lib in libgbm.so libeglSubDriverWayland.so; do \
patchelf --rename-dynamic-symbols /tmp/agnos/graphics-symbols.map \
--remove-needed libwayland-client.so.0 --remove-needed libwayland-server.so.0 \
--remove-needed libwayland-egl.so.1 --remove-needed libffi.so.6 \
--add-needed libagnos-wayland-stubs.so "$lib" || exit 1; \
done
# The Qualcomm blobs, adbd and the Adreno libs are glibc binaries: collect the
# glibc runtime they need (the "glibc island", see userspace/alpine/glibc_island.sh)
FROM agnos-compiler-adbd AS agnos-glibc-island
RUN apt-get update && apt-get install -yq --no-install-recommends libglib2.0-0t64 zlib1g
COPY --from=agnos-compiler-graphics /tmp/agnos/graphics/ /tmp/agnos/graphics/
COPY ./userspace/alpine/glibc_island.sh /tmp/agnos/
RUN --mount=type=bind,source=userspace/root,target=/tmp/agnos/root \
/tmp/agnos/glibc_island.sh /tmp/agnos/root /tmp/agnos/island
# ################## #
# ###### Base ###### #
# ################## #
FROM scratch AS alpine-base
ARG ALPINE_ROOTFS
ADD ${ALPINE_ROOTFS} /
RUN mkdir -p /tmp/agnos
COPY ./userspace/alpine/base_setup.sh /tmp/agnos/alpine/
RUN /tmp/agnos/alpine/base_setup.sh
# Python 3.12 is Alpine's system Python, so the venv uses it (no uv-managed copy)
ARG XDG_DATA_HOME="/usr/local"
RUN uv venv $XDG_DATA_HOME/venv --seed --python-preference only-system --python=3.12
# ################### #
# ###### AGNOS ###### #
# ################### #
FROM alpine-base AS agnos
ARG USERNAME=comma
COPY --from=agnos-compiler-adbd /tmp/agnos/adbd /usr/comma/adbd
COPY --from=agnos-compiler-adbd /tmp/adbd-build/packages/modules/adb/NOTICE /usr/share/doc/adbd/NOTICE
COPY --from=agnos-compiler-graphics /tmp/agnos/graphics/ /usr/lib/aarch64-linux-gnu/
COPY --from=agnos-glibc-island /tmp/agnos/island/ /
ARG XDG_DATA_HOME="/usr/local"
# Install openpilot python packages. uv sync can't be used: 17 packages only
# publish manylinux wheels. SPIKE: those are installed from their manylinux
# wheels as a size stand-in (they need musllinux builds to run).
COPY ./userspace/uv /tmp/agnos/uv
COPY ./userspace/alpine/pick_wheels.py /tmp/agnos/alpine/
RUN cd /tmp/agnos/uv && \
uv export --frozen --no-hashes --no-emit-local --no-emit-project \
--no-emit-package msgq \
--no-emit-package opendbc \
--no-emit-package pandacan \
--no-emit-package rednose \
--no-emit-package teleoprtc \
--no-emit-package tinygrad > /tmp/agnos/export.txt && \
python3 /tmp/agnos/alpine/pick_wheels.py uv.lock /tmp/agnos/export.txt /tmp/agnos && \
export UV_NO_CACHE=1 MAKEFLAGS="-j$(nproc)" PY=$XDG_DATA_HOME/venv/bin/python && \
uv pip install --python $PY --no-deps --compile-bytecode -r /tmp/agnos/musl.txt && \
uv pip install --python $PY --no-deps --compile-bytecode -r /tmp/agnos/sdist.txt && \
uv pip install --python $PY --no-deps --compile-bytecode --python-platform aarch64-manylinux_2_39 -r /tmp/agnos/glibc.txt && \
test "$(uv pip list --python $PY --format freeze | wc -l)" -ge 90
# Root filesystem overlay, all files at their final paths (GNU tar, busybox's lacks --owner)
RUN --mount=type=bind,source=userspace/root,target=/tmp/agnos/root \
set -o pipefail && \
apk add --no-cache --virtual .overlay-tar tar && \
tar -C /tmp/agnos/root --owner=0 --group=0 --mode=go-w -cf - . | \
tar -C / --no-overwrite-dir -xf - && \
apk del .overlay-tar && \
rm -rf /etc/update-motd.d /etc/apt /etc/systemd /usr/lib/systemd
COPY ./userspace/root/home/$USERNAME/.config/ /root/.config
RUN chown -R $USERNAME: /home/$USERNAME
COPY ./output/linux-headers/include/ /usr/include/
COPY ./userspace/irsc_util.c /tmp/agnos/
RUN gcc -O2 -Wall -Wextra -Werror -o /usr/bin/irsc_util /tmp/agnos/irsc_util.c && rm /tmp/agnos/irsc_util.c
COPY ./userspace/power_burn/power_burn_max.c /tmp/agnos/
RUN gcc -O2 -o /home/$USERNAME/power_burn_max /tmp/agnos/power_burn_max.c \
-lpthread && rm /tmp/agnos/power_burn_max.c \
&& chown $USERNAME: /home/$USERNAME/power_burn_max
# Prefer ipv4 over ipv6 (musl ignores gai.conf, kept for parity)
RUN echo "precedence ::ffff:0:0/96 100" >> /etc/gai.conf
COPY ./userspace/alpine/ /tmp/agnos/alpine/
RUN /tmp/agnos/alpine/trim.sh
# SPIKE: SQUEEZE=1 for the size comparison, see userspace/squeeze.sh
ARG SQUEEZE
COPY ./userspace/squeeze.sh /tmp/agnos/
RUN if [ -n "$SQUEEZE" ]; then /tmp/agnos/squeeze.sh; fi
# Services, Alpine config fixups, read-only rootfs. Keep this last.
RUN /tmp/agnos/alpine/finalize.sh && rm -rf /tmp/agnos
COPY VERSION /VERSION
RUN rm -rf /usr/share/icons/* /usr/default/home/$USERNAME/.cache /root/.cache /usr/default/var/cache/apk
# ################## #
# ##### Image ###### #
# ################## #
# Build the system image in BuildKit, so only the sparse image leaves the builder.
FROM --platform=$BUILDPLATFORM ubuntu:20.04 AS agnos-image-tools
RUN apt-get update && \
apt-get install -yq --no-install-recommends \
android-sdk-libsparse-utils \
e2fsprogs \
libcap2-bin \
zstd \
&& rm -rf /var/lib/apt/lists/*
FROM agnos-image-tools AS agnos-image-build
# the partition is 10G, but openpilot's updater didn't always handle the full size
# openpilot fix, shipped in 0.9.8 (8/18/24): https://github.com/commaai/openpilot/pull/33320
ARG ROOTFS_IMAGE_SIZE=4500M
ARG GIT_HASH
ARG BUILD_DATETIME
# Compress the image for remote builders, where the download is the bottleneck
ARG ZSTD
# These files are bind mounted in containers, so they can only be set here.
RUN --mount=type=bind,from=agnos,target=/rootfs,rw \
cd /rootfs && \
ln -sf /proc/sys/kernel/hostname etc/hostname && \
printf "127.0.0.1 localhost.localdomain localhost\n127.0.0.1 comma\n" > etc/hosts && \
ln -sf /run/NetworkManager/resolv.conf etc/resolv.conf && \
for p in bin/ping usr/bin/ping; do if [ -f $p ] && [ ! -L $p ]; then setcap cap_net_raw+ep $p; fi; done && \
printf "%s\n%s\n" "$GIT_HASH" "$BUILD_DATETIME" > BUILD && \
mkdir /out && \
mkfs.ext4 -q -d /rootfs /tmp/system.img $ROOTFS_IMAGE_SIZE && \
img2simg /tmp/system.img /out/system.img && \
rm /tmp/system.img && \
if [ -n "$ZSTD" ]; then zstd -q -T0 -9 --rm /out/system.img; fi
FROM scratch AS agnos-image
COPY --from=agnos-image-build /out/ /