mirror of
https://github.com/commaai/agnos-builder.git
synced 2026-04-06 06:43:53 +08:00
143 lines
4.6 KiB
Bash
Executable File
143 lines
4.6 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -e
|
|
|
|
UBUNTU_BASE_URL="https://cdimage.ubuntu.com/ubuntu-base/releases/24.04/release/"
|
|
UBUNTU_FILE="ubuntu-base-24.04.3-base-arm64.tar.gz"
|
|
UBUNTU_FILE_CHECKSUM="7b2dced6dd56ad5e4a813fa25c8de307b655fdabc6ea9213175a92c48dabb048"
|
|
|
|
# Make sure we're in the correct spot
|
|
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null && pwd)"
|
|
cd $DIR
|
|
|
|
BUILD_DIR="$DIR/build"
|
|
OUTPUT_DIR="$DIR/output"
|
|
|
|
ROOTFS_DIR="$BUILD_DIR/agnos-rootfs"
|
|
ROOTFS_IMAGE="$BUILD_DIR/system.img"
|
|
OUT_IMAGE="$OUTPUT_DIR/system.img"
|
|
|
|
# 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
|
|
ROOTFS_IMAGE_SIZE=4500M
|
|
|
|
# Create temp dir if non-existent
|
|
mkdir -p $BUILD_DIR $OUTPUT_DIR
|
|
|
|
# Download Ubuntu Base if not done already
|
|
if [ ! -f $UBUNTU_FILE ]; then
|
|
echo -e "Downloading Ubuntu Base: $UBUNTU_FILE"
|
|
if ! curl -C - -o $UBUNTU_FILE $UBUNTU_BASE_URL/$UBUNTU_FILE --silent --remote-time --fail; then
|
|
echo "Download failed, please check Ubuntu releases: $UBUNTU_BASE_URL"
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
# Check SHA256 sum
|
|
if [ "$(shasum -a 256 "$UBUNTU_FILE" | awk '{print $1}')" != "$UBUNTU_FILE_CHECKSUM" ]; then
|
|
echo "Checksum mismatch, please check Ubuntu releases: $UBUNTU_BASE_URL"
|
|
exit 1
|
|
fi
|
|
|
|
# Setup qemu multiarch
|
|
if [ "$(uname -m)" = "x86_64" ]; then
|
|
echo "Registering qemu-user-static"
|
|
docker run --rm --privileged multiarch/qemu-user-static --reset -p yes > /dev/null
|
|
fi
|
|
|
|
# Check agnos-builder Dockerfile
|
|
export DOCKER_BUILDKIT=1
|
|
docker buildx build -f Dockerfile.agnos --check $DIR
|
|
|
|
# Start build and create container
|
|
echo "Building agnos-builder docker image"
|
|
BUILD="docker buildx build --load"
|
|
if [ ! -z "$NS" ]; then
|
|
BUILD="nsc build --load"
|
|
fi
|
|
$BUILD -f Dockerfile.agnos -t agnos-builder $DIR --build-arg UBUNTU_BASE_IMAGE=$UBUNTU_FILE --platform=linux/arm64
|
|
echo "Creating agnos-builder container"
|
|
CONTAINER_ID=$(docker container create --entrypoint /bin/bash agnos-builder:latest)
|
|
|
|
# Check agnos-meta-builder Dockerfile
|
|
docker buildx build --load -f Dockerfile.builder --check $DIR \
|
|
--build-arg UNAME=$(id -nu) \
|
|
--build-arg UID=$(id -u) \
|
|
--build-arg GID=$(id -g)
|
|
|
|
# Setup mount container for macOS and CI support (namespace.so)
|
|
echo "Building agnos-meta-builder docker image"
|
|
docker buildx build --load -f Dockerfile.builder -t agnos-meta-builder $DIR \
|
|
--build-arg UNAME=$(id -nu) \
|
|
--build-arg UID=$(id -u) \
|
|
--build-arg GID=$(id -g)
|
|
echo "Starting agnos-meta-builder container"
|
|
MOUNT_CONTAINER_ID=$(docker run -d --privileged -v $DIR:$DIR agnos-meta-builder)
|
|
|
|
# Cleanup containers on possible exit
|
|
trap "echo \"Cleaning up containers:\"; \
|
|
docker container rm -f $CONTAINER_ID $MOUNT_CONTAINER_ID" EXIT
|
|
|
|
# Define functions for docker execution
|
|
exec_as_user() {
|
|
docker exec -u $(id -nu) $MOUNT_CONTAINER_ID "$@"
|
|
}
|
|
|
|
exec_as_root() {
|
|
docker exec $MOUNT_CONTAINER_ID "$@"
|
|
}
|
|
|
|
# Create filesystem ext4 image
|
|
echo "Creating empty filesystem"
|
|
exec_as_user fallocate -l $ROOTFS_IMAGE_SIZE $ROOTFS_IMAGE
|
|
exec_as_user mkfs.ext4 $ROOTFS_IMAGE &> /dev/null
|
|
|
|
# Mount filesystem
|
|
echo "Mounting empty filesystem"
|
|
exec_as_root mkdir -p $ROOTFS_DIR
|
|
exec_as_root mount $ROOTFS_IMAGE $ROOTFS_DIR
|
|
|
|
# Also unmount filesystem (overwrite previous trap)
|
|
trap "exec_as_root umount -l $ROOTFS_DIR &> /dev/null || true; \
|
|
echo \"Cleaning up containers:\"; \
|
|
docker container rm -f $CONTAINER_ID $MOUNT_CONTAINER_ID" EXIT
|
|
|
|
# Extract image
|
|
echo "Extracting docker image"
|
|
docker container export -o $BUILD_DIR/filesystem.tar $CONTAINER_ID
|
|
exec_as_root tar -xf $BUILD_DIR/filesystem.tar -C $ROOTFS_DIR > /dev/null
|
|
|
|
# Avoid detecting as container
|
|
echo "Removing .dockerenv file"
|
|
exec_as_root rm -f $ROOTFS_DIR/.dockerenv
|
|
|
|
echo "Setting network stuff"
|
|
set_network_stuff() {
|
|
cd $ROOTFS_DIR
|
|
# Add hostname and hosts. This cannot be done in the docker container...
|
|
HOST=comma
|
|
bash -c "ln -sf /proc/sys/kernel/hostname etc/hostname"
|
|
bash -c "echo \"127.0.0.1 localhost.localdomain localhost\" > etc/hosts"
|
|
bash -c "echo \"127.0.0.1 $HOST\" >> etc/hosts"
|
|
|
|
# Fix resolv config
|
|
bash -c "ln -sf /run/systemd/resolve/stub-resolv.conf etc/resolv.conf"
|
|
|
|
# Set capability for ping
|
|
bash -c "setcap cap_net_raw+ep bin/ping"
|
|
|
|
# Write build info
|
|
DATETIME=$(date '+%Y-%m-%dT%H:%M:%S')
|
|
bash -c "printf \"$GIT_HASH\n$DATETIME\n\" > BUILD"
|
|
}
|
|
GIT_HASH=${GIT_HASH:-$(git --git-dir=$DIR/.git rev-parse HEAD)}
|
|
exec_as_root bash -c "set -e; export ROOTFS_DIR=$ROOTFS_DIR GIT_HASH=$GIT_HASH; $(declare -f set_network_stuff); set_network_stuff"
|
|
|
|
# Unmount image
|
|
echo "Unmount filesystem"
|
|
exec_as_root umount -l $ROOTFS_DIR
|
|
|
|
# Sparsify system image
|
|
exec_as_user img2simg $ROOTFS_IMAGE $OUT_IMAGE
|
|
|
|
echo "Done!"
|