diff --git a/Dockerfile b/Dockerfile index 867e9c9..420da4f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -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. @@ -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}" < /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 @@ -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