Skip to content
Merged
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
76 changes: 38 additions & 38 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
# syntax=docker/dockerfile:1
FROM --platform=$BUILDPLATFORM rust:alpine AS chef
FROM --platform=$BUILDPLATFORM rust:latest AS chef
# TARGETARCH: auto-set by buildkit/buildah from host arch unless --platform is passed.
ARG TARGETARCH
RUN apk add --no-cache build-base bash pkgconf python3 py3-pip
RUN apt-get update && apt-get install -y pkg-config python3-pip && rm -rf /var/lib/apt/lists/*
RUN pip install ziglang --break-system-packages
RUN cargo install cargo-chef cargo-zigbuild
# cook must use --zigbuild too, or its fingerprint won't match the final build and everything recompiles twice.
Expand All @@ -18,44 +17,49 @@ RUN case "$TARGETARCH" in \
# which breaks zig's -target parser. Strip those flags via a wrapper so any
# future C dependency's buildsystem links correctly against musl.
#
# One wrapper PER triple (not a single script reading a shared /zig_target.txt):
# build scripts and proc-macro crates (e.g. sqlx-macros) always compile for the
# HOST triple (x86_64, since BUILDPLATFORM pins this stage to the native runner)
# regardless of the cross --target passed for the final binary. A single global
# target file can't distinguish "CC invoked because it's the host triple" from
# "CC invoked because it's the cross target" -- when cross-compiling to arm64 it
# wrongly compiled host-triple C code (e.g. libsqlite3-sys for sqlx-macros) for
# aarch64 too, which then failed to link into the host-native x86_64 proc-macro
# artifact ("file in wrong format").
RUN <<'SETUP'
set -eu
for pair in "x86_64:x86_64-linux-musl" "aarch64:aarch64-linux-musl"; do
rt="${pair%%:*}"; zt="${pair##*:}"
for tool in cc:cc g++:c++; do
name="musl-${tool%%:*}-${rt}"; zigcmd="${tool##*:}"
cat > "/usr/local/bin/${name}" <<WRAP
# Builder base must stay glibc (rust:latest), not Alpine: on a musl host,
# proc-macro crates (e.g. sqlx-macros) are broken by a long-standing
# cargo/rustc issue (rust-lang/cargo#7563) -- musl targets default to
# +crt-static, which is incompatible with dylib-style proc-macro loading.
# On a glibc host the host triple (x86_64-unknown-linux-gnu) never touches
# this wrapper or musl at all, so proc-macros just build natively -- only
# the actual --target musl artifacts go through zig.
RUN cat > /usr/local/bin/musl-cc <<'WRAP'
#!/bin/bash
zt=$(cat /zig_target.txt)
args=()
skip=0
for a in "\$@"; do
if [ "\$skip" = 1 ]; then skip=0; continue; fi
case "\$a" in
for a in "$@"; do
if [ "$skip" = 1 ]; then skip=0; continue; fi
case "$a" in
--target=*) continue ;;
-target) skip=1; continue ;;
esac
args+=("\$a")
args+=("$a")
done
exec python3 -m ziglang ${zigcmd} -target ${zt} "\${args[@]}"
exec python3 -m ziglang cc -target "$zt" "${args[@]}"
WRAP
chmod +x "/usr/local/bin/${name}"
done
RUN cat > /usr/local/bin/musl-g++ <<'WRAP'
#!/bin/bash
zt=$(cat /zig_target.txt)
args=()
skip=0
for a in "$@"; do
if [ "$skip" = 1 ]; then skip=0; continue; fi
case "$a" in
--target=*) continue ;;
-target) skip=1; continue ;;
esac
args+=("$a")
done
SETUP
ENV CC_x86_64_unknown_linux_musl=musl-cc-x86_64
ENV CXX_x86_64_unknown_linux_musl=musl-g++-x86_64
exec python3 -m ziglang c++ -target "$zt" "${args[@]}"
WRAP
RUN chmod +x /usr/local/bin/musl-cc /usr/local/bin/musl-g++
ENV CC_x86_64_unknown_linux_musl=musl-cc
ENV CXX_x86_64_unknown_linux_musl=musl-g++
ENV AR_x86_64_unknown_linux_musl=ar
ENV CC_aarch64_unknown_linux_musl=musl-cc-aarch64
ENV CXX_aarch64_unknown_linux_musl=musl-g++-aarch64
ENV CC_aarch64_unknown_linux_musl=musl-cc
ENV CXX_aarch64_unknown_linux_musl=musl-g++
ENV AR_aarch64_unknown_linux_musl=ar
WORKDIR /app

Expand All @@ -65,17 +69,13 @@ RUN cargo chef prepare --bin uc-server --recipe-path recipe.json

FROM chef AS builder
COPY --from=planner /app/recipe.json recipe.json
# Own target/ cache id (separate Cargo.lock from aispecs/operator); registry cache id is
# shared globally. The "-alpine" suffix ties this cache to the builder base image: compiled
# .rlib/.so artifacts are toolchain/ABI-specific, so reusing a cache built under a different
# base (e.g. glibc rust:latest) causes relocation failures like a missing __ubsan_handle_*
# symbol. Bump this suffix again if the builder base image changes.
# Own target/ cache id (separate Cargo.lock from aispecs/operator); registry cache id is shared globally.
RUN --mount=type=cache,target=/usr/local/cargo/registry,id=cargo-registry \
--mount=type=cache,target=/app/target,id=cargo-target-uc-alpine \
--mount=type=cache,target=/app/target,id=cargo-target-uc \
cargo chef cook --zigbuild --profile docker --bin uc-server --target "$(cat /rust_target.txt)" --recipe-path recipe.json
COPY . .
RUN --mount=type=cache,target=/usr/local/cargo/registry,id=cargo-registry \
--mount=type=cache,target=/app/target,id=cargo-target-uc-alpine \
--mount=type=cache,target=/app/target,id=cargo-target-uc \
cargo zigbuild --profile docker --target "$(cat /rust_target.txt)" -p uc-server && \
cp "/app/target/$(cat /rust_target.txt)/docker/uc-server" /uc-server-bin

Expand Down
Loading