LukeMathWalker/cargo-chef

CARGO_BUILD_RUSTFLAGS not supported

lswith opened this issue · 12 comments

lswith commented

Hi Luke,
I'm trying to set the CARGO_BUILD_RUSTFLAGS environment variable when running chef cook but it doesn't seem like this flag is supported.

For context, we have the following flags set in our .cargo/config.toml file:

 rustflags = ["-Dclippy::pedantic", "-Dwarnings", "-Dmissing_docs"]

This errors when using your tool, as the -Dmissing_docs flag errors on the empty main function. To mitigate this issue, we are trying to set the RUSTFLAGS environment variable in the docker build so that we can explicitly set the flags we wish to build with.

One other option, is to make sure that the skeleton avoids any lints/warnings/docs issues, but I think being able to simply override this might be a better option here.

Can you share your Dockerfile please?

lswith commented
# Use Cached Deps
FROM lukemathwalker/cargo-chef:latest-rust-1.69.0 AS chef

FROM chef AS planner
COPY ./rust /rust
# Make sure we turn off lints for the build. Tracking issue: https://github.com/LukeMathWalker/cargo-chef/issues/219
RUN sed -i '1,2d' /rust/.cargo/config.toml
WORKDIR /rust
RUN cargo chef prepare --recipe-path recipe.json

FROM chef AS deps 
COPY --from=planner /rust/recipe.json /rust/recipe.json
RUN apt update && apt install -y protobuf-compiler
WORKDIR /rust
RUN cargo chef cook --release --recipe-path recipe.json

FROM deps AS builder
COPY ./rust /rust
# This is here because the .fingerprint files become dirty if the rust flags don't match
RUN sed -i '1,2d' /rust/.cargo/config.toml
WORKDIR /rust
RUN cargo build --release 
RUN cargo doc --no-deps

WORKDIR /app

FROM debian:bullseye AS runtime
RUN apt update && apt install -y ca-certificates

FROM runtime AS app
COPY --from=builder /rust/target/release/xxx /app/
ENTRYPOINT ["/app/xxx"]
lswith commented

The specific error with the build flags on:

> [deps 4/4] RUN cargo chef cook --release --recipe-path recipe.json:
#16 42.06   |
#16 42.06 1 | fn main() {}
#16 42.06   | ^^^^^^^^^^^^
#16 42.06   |
#16 42.06   = note: requested on the command line with `-D missing-docs`
#16 42.06 
#16 42.06 error: could not compile `xxx` due to previous error
#16 42.06 warning: build failed, waiting for other jobs to finish...
#16 76.67 thread 'main' panicked at 'Exited with status code: 101', /usr/local/cargo/registry/src/index.crates.io-6f17d22bba15001f/cargo-chef-0.1.61/src/recipe.rs:189:27
#16 76.67 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

Thanks! What does the version with CARGO_BUILD_RUSTFLAGS look like instead?

lswith commented

ah yep. The proposed Dockerfile would look like this:

# Use Cached Deps
FROM lukemathwalker/cargo-chef:latest-rust-1.69.0 AS chef

FROM chef AS planner
COPY ./rust /rust
# Make sure we turn off lints for the build. Tracking issue: https://github.com/LukeMathWalker/cargo-chef/issues/219
ENV CARGO_BUILD_RUSTFLAGS="-Dwarnings"
WORKDIR /rust
RUN cargo chef prepare --recipe-path recipe.json

FROM chef AS deps 
COPY --from=planner /rust/recipe.json /rust/recipe.json
RUN apt update && apt install -y protobuf-compiler
WORKDIR /rust
RUN cargo chef cook --release --recipe-path recipe.json

FROM deps AS builder
COPY ./rust /rust
# This is here because the .fingerprint files become dirty if the rust flags don't match
ENV CARGO_BUILD_RUSTFLAGS="-Dwarnings"
WORKDIR /rust
RUN cargo build --release 
RUN cargo doc --no-deps

WORKDIR /app

FROM debian:bullseye AS runtime
RUN apt update && apt install -y ca-certificates

FROM runtime AS app
COPY --from=builder /rust/target/release/xxx /app/
ENTRYPOINT ["/app/xxx"]

I think the issue here is that you are not setting the env variable when invoking cargo chef cook, which ends up running with different flags and indeed breaks caching.

Basically, this should work:

# Use Cached Deps
FROM lukemathwalker/cargo-chef:latest-rust-1.69.0 AS chef

FROM chef AS planner
COPY ./rust /rust
WORKDIR /rust
RUN cargo chef prepare --recipe-path recipe.json

FROM chef AS deps 
# This is here because the .fingerprint files become dirty if the rust flags don't match
ENV CARGO_BUILD_RUSTFLAGS="-Dwarnings"
WORKDIR /rust
COPY --from=planner /rust/recipe.json recipe.json
RUN apt update && apt install -y protobuf-compiler
RUN cargo chef cook --release --recipe-path recipe.json
COPY ./rust .
RUN cargo build --release 
RUN cargo doc --no-deps

WORKDIR /app

FROM debian:bullseye AS runtime
RUN apt update && apt install -y ca-certificates

FROM runtime AS app
COPY --from=builder /rust/target/release/xxx /app/
ENTRYPOINT ["/app/xxx"]
lswith commented

using this Dockerfile errors out:

# Use Cached Deps
FROM lukemathwalker/cargo-chef:latest-rust-1.69.0 AS chef

FROM chef AS planner
COPY ./rust /rust
# Make sure we turn off lints for the build. Tracking issue: https://github.com/LukeMathWalker/cargo-chef/issues/219
# RUN sed -i '1,2d' /rust/.cargo/config.toml
ENV CARGO_BUILD_RUSTFLAGS="-Dwarnings"
WORKDIR /rust
RUN cargo chef prepare --recipe-path recipe.json

FROM chef AS deps 
COPY --from=planner /rust/recipe.json /rust/recipe.json
RUN apt update && apt install -y protobuf-compiler
WORKDIR /rust
ENV CARGO_BUILD_RUSTFLAGS="-Dwarnings"
RUN cargo chef cook --release --recipe-path recipe.json

FROM deps AS builder
COPY ./rust /rust
# RUN sed -i '1,2d' /rust/.cargo/config.toml
ENV CARGO_BUILD_RUSTFLAGS="-Dwarnings"
WORKDIR /rust
RUN cargo build --release 
RUN cargo doc --no-deps

WORKDIR /app

FROM debian:bullseye AS runtime
RUN apt update && apt install -y ca-certificates

FROM runtime AS app
COPY --from=builder /rust/target/release/xxx /app/
ENTRYPOINT ["/app/xxx"]
> [deps 4/4] RUN cargo chef cook --release --recipe-path recipe.json:
#16 40.97   |
#16 40.97 1 | fn main() {}
#16 40.97   | ^^^^^^^^^^^^
#16 40.97   |
#16 40.97   = note: requested on the command line with `-D missing-docs`
#16 40.97 
#16 40.98 error: could not compile `proto` due to previous error
#16 40.98 warning: build failed, waiting for other jobs to finish...
#16 74.66 thread 'main' panicked at 'Exited with status code: 101', /usr/local/cargo/registry/src/index.crates.io-6f17d22bba15001f/cargo-chef-0.1.61/src/recipe.rs:189:27
#16 74.66 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
------
Dockerfile:18
--------------------
  16 |     WORKDIR /rust
  17 |     ENV CARGO_BUILD_RUSTFLAGS="-Dwarnings"
  18 | >>> RUN cargo chef cook --release --recipe-path recipe.json
  19 |     
  20 |     FROM ghcr.io/fl0zone/rust-deps:latest AS builder
--------------------
ERROR: failed to solve: process "/bin/sh -c cargo chef cook --release --recipe-path recipe.json" did not complete successfully: exit code: 101

For more context, it seems the CARGO_BUILD_RUSTFLAGS will overwrite the rustflags in the config file.
From the docs: https://doc.rust-lang.org/cargo/reference/config.html#buildrustflags

There are four mutually exclusive sources of extra flags. They are checked in order, with the first one being used:

  1. CARGO_ENCODED_RUSTFLAGS environment variable.
  2. RUSTFLAGS environment variable.
  3. All matching target..rustflags and target..rustflags config entries joined together.
  4. build.rustflags config value.

I think that the cargo chef cook command is not capturing the environment variable and sending it to cargo, but I haven't dug into the code to be confident.

All env variables are forwarded:

.envs(std::env::vars())

Can you please provide a minimal reproduction of this problem that I can actually tinker with?

lswith commented

https://github.com/lswith/oom-app/blob/master/Dockerfile

For context, this is an app that is meant to OOM if run. The build will compile with listing and has enough docs to pass the -D missing-docs.

This has something to do with how cargo resolves configuration: if you rename CARGO_BUILD_RUSTFLAGS with RUSTFLAGS in the Dockerfile everything works as expected 🤷🏻
Probably worth opening an issue against the cargo repo to get clarifications.

lswith commented

For reference: rust-lang/cargo#12257