From 988a93f5e776750cf8f80bee44c8f9c82423f0f3 Mon Sep 17 00:00:00 2001 From: Guillaume Deconinck Date: Sun, 24 May 2026 16:32:31 +0900 Subject: [PATCH 1/5] feat: use mold and cargo sonic --- .cargo/config.toml | 6 +++++ Cargo.toml | 12 ++++++---- README.md | 6 +++++ alpine.Dockerfile | 43 +++++++++++++++++---------------- alpineWithDD.Dockerfile | 51 ++++++++++++++++++++++------------------ debian.Dockerfile | 24 ++++++++++--------- debianWithDD.Dockerfile | 33 +++++++++++++------------- docs/deployment.md | 12 ++++++++++ scripts/build_release.sh | 36 ++++++++++++++++++++++++++++ 9 files changed, 148 insertions(+), 75 deletions(-) create mode 100755 scripts/build_release.sh diff --git a/.cargo/config.toml b/.cargo/config.toml index 2e822958..9547cfc0 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -2,3 +2,9 @@ [env] TS_RS_EXPORT_DIR = { value = "clients/javascript/lib/gen_types", relative = true } + +[target.x86_64-unknown-linux-gnu] +rustflags = ["-C", "link-arg=-fuse-ld=mold"] + +[target.aarch64-unknown-linux-gnu] +rustflags = ["-C", "link-arg=-fuse-ld=mold"] diff --git a/Cargo.toml b/Cargo.toml index ce2b62e7..aa99d7e2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,11 +21,13 @@ unwrap_used = "deny" expect_used = "deny" [profile.release] -# Can improve slightly the performance at the cost of increased compile time -# https://doc.rust-lang.org/cargo/reference/profiles.html#lto lto = "thin" -# https://doc.rust-lang.org/cargo/reference/profiles.html#codegen-units codegen-units = 1 -# Add basic debug information, at the cost of binary size -# See https://doc.rust-lang.org/cargo/reference/profiles.html#debug +strip = "symbols" + +[profile.release-dd] +inherits = "release" +lto = "thin" +codegen-units = 1 debug = 1 +strip = "none" diff --git a/README.md b/README.md index fac32950..4af9ed8c 100644 --- a/README.md +++ b/README.md @@ -44,6 +44,12 @@ This project uses [Just](https://github.com/casey/just) as a task manager. To in brew install just ``` +On Linux, including WSL, install [`mold`](https://github.com/rui314/mold) too. The repository Cargo config uses it as the linker for Linux builds. + +```sh +sudo apt install mold +``` + Once Rust and Just are installed, a few more utility tools can be installed by running ```sh diff --git a/alpine.Dockerfile b/alpine.Dockerfile index 8e12ce32..ceec37c3 100644 --- a/alpine.Dockerfile +++ b/alpine.Dockerfile @@ -1,38 +1,45 @@ # Usage: -# docker buildx build -f alpine.Dockerfile -t image:tag --build-arg='ARCH=x86_64' --platform linux/amd64 . -# docker buildx build -f alpine.Dockerfile -t image:tag --build-arg='ARCH=aarch64' --platform linux/arm64 . +# docker buildx build -f alpine.Dockerfile -t image:tag --platform linux/amd64 . +# docker buildx build -f alpine.Dockerfile -t image:tag --platform linux/arm64 . -ARG ARCH=x86_64 -FROM messense/rust-musl-cross:${ARCH}-musl AS builder +ARG TARGETARCH=amd64 + +FROM messense/rust-musl-cross:x86_64-musl AS builder-amd64 +ENV MUSL_TARGET=x86_64-unknown-linux-musl + +FROM messense/rust-musl-cross:aarch64-musl AS builder-arm64 +ENV MUSL_TARGET=aarch64-unknown-linux-musl + +FROM builder-${TARGETARCH} AS builder -ARG ARCH=x86_64 -ARG APP_NAME=nittei ARG RUST_VERSION=1.95.0 +ENV BUILD_PROFILE=release # Install and set the specific Rust version RUN rustup install ${RUST_VERSION} && rustup default ${RUST_VERSION} # Install the musl target for the correct architecture -RUN rustup target add ${ARCH}-unknown-linux-musl +RUN rustup target add ${MUSL_TARGET} # Verify the Rust and target setup RUN rustc --version && rustup show # Copy source code +COPY .cargo .cargo COPY ./Cargo.toml ./Cargo.lock ./ COPY ./crates ./crates COPY ./bins ./bins COPY ./clients/rust ./clients/rust -# Build application -RUN cargo build --release --target ${ARCH}-unknown-linux-musl && \ - cp ./target/${ARCH}-unknown-linux-musl/release/${APP_NAME} /${APP_NAME} +RUN cargo build --locked --profile ${BUILD_PROFILE} --target ${MUSL_TARGET} \ + --bin nittei \ + --bin nittei-migrate -# Build migrate binary -RUN cargo build --release --bin nittei-migrate --target ${ARCH}-unknown-linux-musl && \ - cp ./target/${ARCH}-unknown-linux-musl/release/nittei-migrate /nittei-migrate +RUN mkdir -p /out \ + && cp ./target/${MUSL_TARGET}/${BUILD_PROFILE}/nittei /out/nittei \ + && cp ./target/${MUSL_TARGET}/${BUILD_PROFILE}/nittei-migrate /out/nittei-migrate -#Create a new stage with a minimal image +# Create a new stage with a minimal image FROM alpine:3.23.4 # Set the git repository url and commit hash for DD @@ -47,10 +54,6 @@ ENV DD_SOURCE_CODE_PATH_MAPPING="/app/nittei/bins:/bins,/app/nittei/crates:/crat ARG RUST_BACKTRACE=1 ENV RUST_BACKTRACE=${RUST_BACKTRACE} -ARG APP_NAME=nittei -ENV APP_NAME=${APP_NAME} - -COPY --from=builder /${APP_NAME} /${APP_NAME} -COPY --from=builder /nittei-migrate /nittei-migrate +COPY --from=builder /out/ / -CMD ["/bin/sh", "-c", "exec /${APP_NAME}"] +CMD ["/nittei"] diff --git a/alpineWithDD.Dockerfile b/alpineWithDD.Dockerfile index e1258f43..15fb8c35 100644 --- a/alpineWithDD.Dockerfile +++ b/alpineWithDD.Dockerfile @@ -1,50 +1,59 @@ # This Dockerfile is based on the alpine.Dockerfile and adds the ddprof tool to the image. # # Usage: -# docker buildx build -f alpineWithDD.Dockerfile -t image:tag --build-arg='ARCH=x86_64' --platform linux/amd64 . -# docker buildx build -f alpineWithDD.Dockerfile -t image:tag --build-arg='ARCH=aarch64' --platform linux/arm64 . +# docker buildx build -f alpineWithDD.Dockerfile -t image:tag --platform linux/amd64 . +# docker buildx build -f alpineWithDD.Dockerfile -t image:tag --platform linux/arm64 . -ARG ARCH=x86_64 -FROM messense/rust-musl-cross:${ARCH}-musl AS builder +ARG TARGETARCH=amd64 -ARG ARCH=x86_64 -ARG APP_NAME=nittei +FROM messense/rust-musl-cross:x86_64-musl AS builder-amd64 +ENV MUSL_TARGET=x86_64-unknown-linux-musl + +FROM messense/rust-musl-cross:aarch64-musl AS builder-arm64 +ENV MUSL_TARGET=aarch64-unknown-linux-musl + +FROM builder-${TARGETARCH} AS builder + +ARG TARGETARCH ARG RUST_VERSION=1.95.0 +ENV BUILD_PROFILE=release-dd +ENV RUSTFLAGS="-C force-frame-pointers=yes" # Install and set the specific Rust version RUN rustup install ${RUST_VERSION} && rustup default ${RUST_VERSION} # Install the musl target for the correct architecture -RUN rustup target add ${ARCH}-unknown-linux-musl +RUN rustup target add ${MUSL_TARGET} # Verify the Rust and target setup RUN rustc --version && rustup show # Copy source code +COPY .cargo .cargo COPY ./Cargo.toml ./Cargo.lock ./ COPY ./crates ./crates COPY ./bins ./bins COPY ./clients/rust ./clients/rust -# Build application -RUN cargo build --release --target ${ARCH}-unknown-linux-musl && \ - cp ./target/${ARCH}-unknown-linux-musl/release/${APP_NAME} /${APP_NAME} +RUN cargo build --locked --profile ${BUILD_PROFILE} --target ${MUSL_TARGET} \ + --bin nittei \ + --bin nittei-migrate -# Build migrate binary -RUN cargo build --release --bin nittei-migrate --target ${ARCH}-unknown-linux-musl && \ - cp ./target/${ARCH}-unknown-linux-musl/release/nittei-migrate /nittei-migrate +RUN mkdir -p /out \ + && cp ./target/${MUSL_TARGET}/${BUILD_PROFILE}/nittei /out/nittei \ + && cp ./target/${MUSL_TARGET}/${BUILD_PROFILE}/nittei-migrate /out/nittei-migrate # Install ddprof -RUN ARCH_IN_URL=$(case "${ARCH}" in \ - x86_64) echo "amd64" ;; \ - aarch64) echo "arm64" ;; \ +RUN ARCH_IN_URL=$(case "${TARGETARCH}" in \ + amd64) echo "amd64" ;; \ + arm64) echo "arm64" ;; \ *) echo "unsupported-arch" && exit 1 ;; \ esac) && \ curl -Lo ddprof-linux.tar.xz https://github.com/DataDog/ddprof/releases/latest/download/ddprof-${ARCH_IN_URL}-linux.tar.xz && \ tar xvf ddprof-linux.tar.xz && \ mv ddprof/bin/ddprof /ddprof -#Create a new stage with a minimal image +# Create a new stage with a minimal image FROM alpine:3.23.4 # Set the git repository url and commit hash for DD @@ -59,11 +68,7 @@ ENV DD_SOURCE_CODE_PATH_MAPPING="/app/nittei/bins:/bins,/app/nittei/crates:/crat ARG RUST_BACKTRACE=1 ENV RUST_BACKTRACE=${RUST_BACKTRACE} -ARG APP_NAME=nittei -ENV APP_NAME=${APP_NAME} - -COPY --from=builder /${APP_NAME} /${APP_NAME} -COPY --from=builder /nittei-migrate /nittei-migrate +COPY --from=builder /out/ / COPY --from=builder /ddprof /ddprof -CMD ["/bin/sh", "-c", "exec /ddprof --preset cpu_live_heap /${APP_NAME}"] +CMD ["/ddprof", "--preset", "cpu_live_heap", "/nittei"] diff --git a/debian.Dockerfile b/debian.Dockerfile index df64f705..628574c1 100644 --- a/debian.Dockerfile +++ b/debian.Dockerfile @@ -1,25 +1,28 @@ # Usage: -# docker buildx build -f debian.Dockerfile -t image:tag --build-arg='ARCH=x86_64' --platform linux/amd64 . -# docker buildx build -f debian.Dockerfile -t image:tag --build-arg='ARCH=aarch64' --platform linux/arm64 . +# docker buildx build -f debian.Dockerfile -t image:tag --platform linux/amd64 . +# docker buildx build -f debian.Dockerfile -t image:tag --platform linux/arm64 . FROM rust:1.95.0-slim-trixie AS builder WORKDIR /app/nittei +ARG TARGETARCH +ENV BUILD_PROFILE=release RUN apt update \ - && apt install -y --no-install-recommends curl openssl ca-certificates pkg-config build-essential libssl-dev \ + && apt install -y --no-install-recommends curl openssl ca-certificates pkg-config build-essential libssl-dev mold \ && apt clean \ && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* -COPY ./Cargo.toml ./Cargo.lock .cargo ./ +RUN cargo install cargo-sonic --version 0.2.0 --locked + +COPY .cargo .cargo +COPY ./Cargo.toml ./Cargo.lock ./ COPY ./clients/rust ./clients/rust COPY ./crates ./crates COPY ./bins ./bins +COPY ./scripts ./scripts -RUN cargo build --locked --release && \ - cp ./target/release/nittei /nittei && \ - cargo build --locked --release --bin nittei-migrate && \ - cp ./target/release/nittei-migrate /nittei-migrate +RUN ./scripts/build_release.sh # Use the distroless base image for final image FROM gcr.io/distroless/cc-debian13 @@ -38,7 +41,6 @@ ENV RUST_BACKTRACE=${RUST_BACKTRACE} USER nonroot:nonroot -COPY --from=builder --chown=nonroot:nonroot /nittei /nittei -COPY --from=builder --chown=nonroot:nonroot /nittei-migrate /nittei-migrate +COPY --from=builder --chown=nonroot:nonroot /out/ / -CMD ["/nittei"] \ No newline at end of file +CMD ["/nittei"] diff --git a/debianWithDD.Dockerfile b/debianWithDD.Dockerfile index dc4de4b7..a63d7c37 100644 --- a/debianWithDD.Dockerfile +++ b/debianWithDD.Dockerfile @@ -1,35 +1,37 @@ # This Dockerfile is based on the debian.Dockerfile and adds the ddprof tool to the image. # Usage: -# docker buildx build -f debianWithDD.Dockerfile -t image:tag --build-arg='ARCH=x86_64' --platform linux/amd64 . -# docker buildx build -f debianWithDD.Dockerfile -t image:tag --build-arg='ARCH=aarch64' --platform linux/arm64 . +# docker buildx build -f debianWithDD.Dockerfile -t image:tag --platform linux/amd64 . +# docker buildx build -f debianWithDD.Dockerfile -t image:tag --platform linux/arm64 . FROM rust:1.95.0-slim-trixie AS builder WORKDIR /app/nittei -ARG ARCH=x86_64 - +ARG TARGETARCH +ENV BUILD_PROFILE=release-dd +ENV RUSTFLAGS="-C force-frame-pointers=yes -C link-arg=-fuse-ld=mold" RUN apt update \ - && apt install -y --no-install-recommends curl openssl ca-certificates pkg-config build-essential libssl-dev \ + && apt install -y --no-install-recommends curl openssl ca-certificates pkg-config build-essential libssl-dev mold \ && apt clean \ && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* -COPY ./Cargo.toml ./Cargo.lock .cargo ./ +RUN cargo install cargo-sonic --version 0.2.0 --locked + +COPY .cargo .cargo +COPY ./Cargo.toml ./Cargo.lock ./ COPY ./clients/rust ./clients/rust COPY ./crates ./crates COPY ./bins ./bins +COPY ./scripts ./scripts -RUN cargo build --locked --release && \ - cp ./target/release/nittei /nittei && \ - cargo build --locked --release --bin nittei-migrate && \ - cp ./target/release/nittei-migrate /nittei-migrate +RUN ./scripts/build_release.sh # Install ddprof -RUN ARCH_IN_URL=$(case "${ARCH}" in \ - x86_64) echo "amd64" ;; \ - aarch64) echo "arm64" ;; \ +RUN ARCH_IN_URL=$(case "${TARGETARCH:-$(uname -m)}" in \ + amd64|x86_64) echo "amd64" ;; \ + arm64|aarch64) echo "arm64" ;; \ *) echo "unsupported-arch" && exit 1 ;; \ esac) && \ curl -Lo ddprof-linux.tar.xz https://github.com/DataDog/ddprof/releases/latest/download/ddprof-${ARCH_IN_URL}-linux.tar.xz && \ @@ -53,8 +55,7 @@ ENV RUST_BACKTRACE=${RUST_BACKTRACE} USER nonroot:nonroot -COPY --from=builder --chown=nonroot:nonroot /nittei /nittei -COPY --from=builder --chown=nonroot:nonroot /nittei-migrate /nittei-migrate +COPY --from=builder --chown=nonroot:nonroot /out/ / COPY --from=builder --chown=nonroot:nonroot /ddprof /ddprof -CMD ["/ddprof", "--preset", "cpu_live_heap", "/nittei"] \ No newline at end of file +CMD ["/ddprof", "--preset", "cpu_live_heap", "/nittei"] diff --git a/docs/deployment.md b/docs/deployment.md index 5203bddf..13a661ab 100644 --- a/docs/deployment.md +++ b/docs/deployment.md @@ -8,6 +8,18 @@ Or build from source: cargo run --release ``` +### mold + +The production Docker builds install [`mold`](https://github.com/rui314/mold) and configure Rust to use it as the linker. This keeps release and profiling builds faster, especially when LTO is enabled. + +### cargo-sonic + +The Debian Docker images use [`cargo-sonic`](https://docs.rs/crate/cargo-sonic/latest) to build CPU-dispatched binaries. The image contains a baseline payload plus an optimized payload for the target architecture: `x86-64-v3` on `amd64`, and `neoverse-n1` on `arm64`. + +The build uses `--loader=bundle`, so the final image must include both the launcher binaries and their adjacent `.bundle` directories. + +### Database + Then set up a postgres db with the init script specified [here](../crates/infra/migrations/dbinit.sql). Lastly provide the following environment variables to the `nittei` server: diff --git a/scripts/build_release.sh b/scripts/build_release.sh new file mode 100755 index 00000000..12464888 --- /dev/null +++ b/scripts/build_release.sh @@ -0,0 +1,36 @@ +#!/usr/bin/env bash +set -euo pipefail + +profile="${BUILD_PROFILE:-release}" +arch="${TARGETARCH:-$(uname -m)}" +target_dir="${CARGO_TARGET_DIR:-target}" +out_dir="${OUT_DIR:-/out}" + +case "$arch" in + amd64|x86_64) + target_cpus="x86-64-v3" + ;; + arm64|aarch64) + target_cpus="neoverse-n1" + ;; + *) + echo "Unsupported architecture: $arch" >&2 + exit 1 + ;; +esac + +cargo sonic \ + --target-cpus="$target_cpus" \ + --loader=bundle \ + build --locked \ + --profile "$profile" \ + --bin nittei \ + --bin nittei-migrate + +mkdir -p "$out_dir" +find "$target_dir/sonic" -type f \( \ + -name 'nittei' -o \ + -name 'nittei-migrate' \ +\) -exec cp {} "$out_dir/" \; + +find "$target_dir/sonic" -type d -name '*.bundle' -exec cp -a {} "$out_dir/" \; From a97b374c605501ba184a70bfce8ee5c547db251e Mon Sep 17 00:00:00 2001 From: Guillaume Deconinck Date: Mon, 25 May 2026 09:13:00 +0900 Subject: [PATCH 2/5] ci: add mold --- .github/workflows/js-client-test.yml | 5 +++++ .github/workflows/server-code-coverage.yml | 5 +++++ .github/workflows/server-test.yml | 5 +++++ 3 files changed, 15 insertions(+) diff --git a/.github/workflows/js-client-test.yml b/.github/workflows/js-client-test.yml index eb6cef56..7f148459 100644 --- a/.github/workflows/js-client-test.yml +++ b/.github/workflows/js-client-test.yml @@ -44,6 +44,11 @@ jobs: with: toolchain: ${{ env.RUST_VERSION }} + - name: Install mold + run: | + sudo apt-get update + sudo apt-get install -y mold + - name: Setup Node.js ${{ matrix.node-version }} uses: actions/setup-node@v4 with: diff --git a/.github/workflows/server-code-coverage.yml b/.github/workflows/server-code-coverage.yml index de37db1d..08531f7a 100644 --- a/.github/workflows/server-code-coverage.yml +++ b/.github/workflows/server-code-coverage.yml @@ -23,6 +23,11 @@ jobs: - name: Checkout repository uses: actions/checkout@v2 + - name: Install mold + run: | + sudo apt-get update + sudo apt-get install -y mold + - uses: actions/cache@v2 with: path: | diff --git a/.github/workflows/server-test.yml b/.github/workflows/server-test.yml index 48b3851c..ffde433e 100644 --- a/.github/workflows/server-test.yml +++ b/.github/workflows/server-test.yml @@ -46,6 +46,11 @@ jobs: toolchain: ${{ env.RUST_VERSION }} components: clippy + - name: Install mold + run: | + sudo apt-get update + sudo apt-get install -y mold + - uses: actions/cache@v4 with: path: | From 7673c368c9343446e7c00fde13081d685ae09ef1 Mon Sep 17 00:00:00 2001 From: Guillaume Deconinck Date: Tue, 26 May 2026 09:26:01 +0900 Subject: [PATCH 3/5] fix: small fixes --- debian.Dockerfile | 4 ++ debianWithDD.Dockerfile | 5 +++ scripts/build_release.sh | 92 ++++++++++++++++++++++++++++------------ 3 files changed, 74 insertions(+), 27 deletions(-) diff --git a/debian.Dockerfile b/debian.Dockerfile index 628574c1..49fa107d 100644 --- a/debian.Dockerfile +++ b/debian.Dockerfile @@ -7,6 +7,10 @@ FROM rust:1.95.0-slim-trixie AS builder WORKDIR /app/nittei ARG TARGETARCH ENV BUILD_PROFILE=release +# cargo-sonic intentionally does not reuse payload RUSTFLAGS / CARGO_*_RUSTFLAGS +# for its small generated loader build. Tell it to use mold for the loader too, +# matching the payload link step configured in .cargo/config.toml. +ENV CARGO_SONIC_LOADER_RUSTFLAGS="-C link-arg=-fuse-ld=mold" RUN apt update \ && apt install -y --no-install-recommends curl openssl ca-certificates pkg-config build-essential libssl-dev mold \ diff --git a/debianWithDD.Dockerfile b/debianWithDD.Dockerfile index a63d7c37..a73d6131 100644 --- a/debianWithDD.Dockerfile +++ b/debianWithDD.Dockerfile @@ -11,6 +11,11 @@ WORKDIR /app/nittei ARG TARGETARCH ENV BUILD_PROFILE=release-dd ENV RUSTFLAGS="-C force-frame-pointers=yes -C link-arg=-fuse-ld=mold" +# cargo-sonic intentionally does not reuse payload RUSTFLAGS / CARGO_*_RUSTFLAGS +# for its small generated loader build. Tell it to use mold for the loader too, +# matching the payload link step. Frame pointers are not needed on the launcher +# (ddprof profiles the payload process, not the loader). +ENV CARGO_SONIC_LOADER_RUSTFLAGS="-C link-arg=-fuse-ld=mold" RUN apt update \ && apt install -y --no-install-recommends curl openssl ca-certificates pkg-config build-essential libssl-dev mold \ diff --git a/scripts/build_release.sh b/scripts/build_release.sh index 12464888..40c5dac7 100755 --- a/scripts/build_release.sh +++ b/scripts/build_release.sh @@ -2,35 +2,73 @@ set -euo pipefail profile="${BUILD_PROFILE:-release}" -arch="${TARGETARCH:-$(uname -m)}" target_dir="${CARGO_TARGET_DIR:-target}" out_dir="${OUT_DIR:-/out}" - -case "$arch" in - amd64|x86_64) - target_cpus="x86-64-v3" - ;; - arm64|aarch64) - target_cpus="neoverse-n1" - ;; - *) - echo "Unsupported architecture: $arch" >&2 - exit 1 - ;; -esac - -cargo sonic \ - --target-cpus="$target_cpus" \ - --loader=bundle \ - build --locked \ - --profile "$profile" \ - --bin nittei \ - --bin nittei-migrate +os="$(uname -s)" +parallelism="${CARGO_SONIC_PARALLELISM:-2}" mkdir -p "$out_dir" -find "$target_dir/sonic" -type f \( \ - -name 'nittei' -o \ - -name 'nittei-migrate' \ -\) -exec cp {} "$out_dir/" \; -find "$target_dir/sonic" -type d -name '*.bundle' -exec cp -a {} "$out_dir/" \; +if [[ "$os" == "Linux" ]]; then + arch="${TARGETARCH:-$(uname -m)}" + + # Non-baseline target CPUs to build payloads for. The architecture baseline + # (x86-64 / generic) is always built implicitly by cargo-sonic; do not list it. + # + # Each extra CPU is a full extra payload build, so size and build time scale + # linearly with the list. + case "$arch" in + amd64|x86_64) + # v3 = Haswell+/Zen+ (AVX2, BMI2). v4 = AVX-512 (Sapphire Rapids, Zen 4+). + target_cpus="x86-64-v3,x86-64-v4" + ;; + arm64|aarch64) + # n1 = AWS Graviton2 / Ampere Altra. v1 = AWS Graviton3 (SVE). + target_cpus="neoverse-n1,neoverse-v1" + ;; + *) + echo "Unsupported architecture: $arch" >&2 + exit 1 + ;; + esac + + # cargo-sonic builds a CPU-dispatched fat binary: a small launcher plus + # per-target-CPU payloads in an adjacent .bundle/ directory. + # NOTE: --release and --profile are mutually exclusive in modern cargo, so + # only --profile is passed (covers both `release` and `release-dd`). + cargo sonic \ + --target-cpus="$target_cpus" \ + --loader=bundle \ + --parallelism="$parallelism" \ + build \ + --package nittei \ + --bin nittei \ + --bin nittei-migrate \ + --locked \ + --profile "$profile" + + # Final launchers live at exactly: target/sonic/// + # Bundle dirs live alongside them as: target/sonic///.bundle/ + # Pin mindepth/maxdepth to avoid picking up intermediate per-payload artifacts. + find "$target_dir/sonic" -mindepth 3 -maxdepth 3 -type f \( \ + -name 'nittei' -o \ + -name 'nittei-migrate' \ + \) -exec cp {} "$out_dir/" \; + + find "$target_dir/sonic" -mindepth 3 -maxdepth 3 -type d -name '*.bundle' \ + -exec cp -a {} "$out_dir/" \; +else + # cargo-sonic only supports Linux x86_64/aarch64 (memfd_create + execveat). + # On other platforms (e.g. macOS for local dev), fall back to a plain build. + echo "Non-Linux host ($os) detected; falling back to plain 'cargo build' (cargo-sonic is Linux-only)." >&2 + + cargo build \ + --package nittei \ + --bin nittei \ + --bin nittei-migrate \ + --locked \ + --profile "$profile" + + cp "$target_dir/$profile/nittei" "$out_dir/nittei" + cp "$target_dir/$profile/nittei-migrate" "$out_dir/nittei-migrate" +fi From a07134c305168f331f9d197bf3276ae23ad40080 Mon Sep 17 00:00:00 2001 From: Guillaume Deconinck Date: Thu, 11 Jun 2026 11:29:22 +0900 Subject: [PATCH 4/5] fix: cargo sonic multiple --bin --- scripts/build_release.sh | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/scripts/build_release.sh b/scripts/build_release.sh index 40c5dac7..6a1afb20 100755 --- a/scripts/build_release.sh +++ b/scripts/build_release.sh @@ -36,16 +36,18 @@ if [[ "$os" == "Linux" ]]; then # per-target-CPU payloads in an adjacent .bundle/ directory. # NOTE: --release and --profile are mutually exclusive in modern cargo, so # only --profile is passed (covers both `release` and `release-dd`). - cargo sonic \ - --target-cpus="$target_cpus" \ - --loader=bundle \ - --parallelism="$parallelism" \ - build \ - --package nittei \ - --bin nittei \ - --bin nittei-migrate \ - --locked \ - --profile "$profile" + # cargo-sonic 0.2.0 only accepts a single --bin per invocation. + for bin in nittei nittei-migrate; do + cargo sonic \ + --target-cpus="$target_cpus" \ + --loader=bundle \ + --parallelism="$parallelism" \ + build \ + --package nittei \ + --bin "$bin" \ + --locked \ + --profile "$profile" + done # Final launchers live at exactly: target/sonic/// # Bundle dirs live alongside them as: target/sonic///.bundle/ From d1aae0a932048fb0c54ebcb113f0d60de598df68 Mon Sep 17 00:00:00 2001 From: Guillaume Deconinck Date: Thu, 11 Jun 2026 12:57:30 +0900 Subject: [PATCH 5/5] fix: don't use cargo-sonic for migrate binary --- debian.Dockerfile | 2 +- debianWithDD.Dockerfile | 2 +- scripts/build_release.sh | 40 +++++++++++++++++++++++----------------- 3 files changed, 25 insertions(+), 19 deletions(-) diff --git a/debian.Dockerfile b/debian.Dockerfile index 59246301..23ec0115 100644 --- a/debian.Dockerfile +++ b/debian.Dockerfile @@ -45,6 +45,6 @@ ENV RUST_BACKTRACE=${RUST_BACKTRACE} USER nonroot:nonroot -COPY --from=builder --chown=nonroot:nonroot /out/ / +COPY --from=builder --chown=nonroot:nonroot /tmp/nittei-build/ / CMD ["/nittei"] diff --git a/debianWithDD.Dockerfile b/debianWithDD.Dockerfile index 6757feb0..a7c0d6c9 100644 --- a/debianWithDD.Dockerfile +++ b/debianWithDD.Dockerfile @@ -60,7 +60,7 @@ ENV RUST_BACKTRACE=${RUST_BACKTRACE} USER nonroot:nonroot -COPY --from=builder --chown=nonroot:nonroot /out/ / +COPY --from=builder --chown=nonroot:nonroot /tmp/nittei-build/ / COPY --from=builder --chown=nonroot:nonroot /ddprof /ddprof CMD ["/ddprof", "--preset", "cpu_live_heap", "/nittei"] diff --git a/scripts/build_release.sh b/scripts/build_release.sh index 6a1afb20..b9c7a3cb 100755 --- a/scripts/build_release.sh +++ b/scripts/build_release.sh @@ -3,7 +3,7 @@ set -euo pipefail profile="${BUILD_PROFILE:-release}" target_dir="${CARGO_TARGET_DIR:-target}" -out_dir="${OUT_DIR:-/out}" +out_dir="${OUT_DIR:-/tmp/nittei-build}" os="$(uname -s)" parallelism="${CARGO_SONIC_PARALLELISM:-2}" @@ -36,29 +36,35 @@ if [[ "$os" == "Linux" ]]; then # per-target-CPU payloads in an adjacent .bundle/ directory. # NOTE: --release and --profile are mutually exclusive in modern cargo, so # only --profile is passed (covers both `release` and `release-dd`). - # cargo-sonic 0.2.0 only accepts a single --bin per invocation. - for bin in nittei nittei-migrate; do - cargo sonic \ - --target-cpus="$target_cpus" \ - --loader=bundle \ - --parallelism="$parallelism" \ - build \ - --package nittei \ - --bin "$bin" \ - --locked \ - --profile "$profile" - done + # Only the server binary benefits from CPU dispatch; the migration binary is + # a one-shot tool and is built with plain cargo to avoid artifact collisions + # in the sonic output directory. + cargo sonic \ + --target-cpus="$target_cpus" \ + --loader=bundle \ + --parallelism="$parallelism" \ + build \ + --package nittei \ + --bin nittei \ + --locked \ + --profile "$profile" + + cargo build \ + --package nittei \ + --bin nittei-migrate \ + --locked \ + --profile "$profile" # Final launchers live at exactly: target/sonic/// # Bundle dirs live alongside them as: target/sonic///.bundle/ # Pin mindepth/maxdepth to avoid picking up intermediate per-payload artifacts. - find "$target_dir/sonic" -mindepth 3 -maxdepth 3 -type f \( \ - -name 'nittei' -o \ - -name 'nittei-migrate' \ - \) -exec cp {} "$out_dir/" \; + find "$target_dir/sonic" -mindepth 3 -maxdepth 3 -type f -name 'nittei' \ + -exec cp {} "$out_dir/" \; find "$target_dir/sonic" -mindepth 3 -maxdepth 3 -type d -name '*.bundle' \ -exec cp -a {} "$out_dir/" \; + + cp "$target_dir/$profile/nittei-migrate" "$out_dir/nittei-migrate" else # cargo-sonic only supports Linux x86_64/aarch64 (memfd_create + execveat). # On other platforms (e.g. macOS for local dev), fall back to a plain build.