Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

xx-cargo: rename to --print-target-triple #91

Merged
merged 2 commits into from
Jan 10, 2023
Merged
Show file tree
Hide file tree
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
106 changes: 68 additions & 38 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -345,22 +345,70 @@ The wrapper supports rust installed via [`rustup`](https://rustup.rs/)

```dockerfile
# syntax=docker/dockerfile:1
# official rust image
FROM --platform=$BUILDPLATFORM rust:alpine
RUN apk add clang lld
# ...
RUN --mount=type=cache,target=/usr/local/cargo/git/db \
--mount=type=cache,target=/usr/local/cargo/registry/cache \
--mount=type=cache,target=/usr/local/cargo/registry/index \
cargo fetch
ARG TARGETPLATFORM
RUN xx-cargo build --release --target-dir ./build && \
xx-verify ./build/$(xx-cargo --print-target)/release/hello_cargo
xx-verify ./build/$(xx-cargo --print-target-triple)/release/hello_cargo
```

Cargo binary can also be called directly with `--target` flag if you don't want
to use the wrapper. `--print-target-triple` is a built-in flag that can be used
to set the correct target:

```dockerfile
# syntax=docker/dockerfile:1
FROM --platform=$BUILDPLATFORM rust:alpine
RUN apk add clang lld
# ...
ARG TARGETPLATFORM
RUN cargo build --target=$(xx-cargo --print-target-triple) --release --target-dir ./build && \
xx-verify ./build/$(xx-cargo --print-target-triple)/release/hello_cargo
```
crazy-max marked this conversation as resolved.
Show resolved Hide resolved

> **Note**
>
> `xx-cargo --print-target-triple` does not always have the same value as
> `xx-clang --print-target-triple`. This is because prebuilt Rust and C
> libraries sometimes use a different value.

The first invocation of `xx-cargo` will install the standard library for Rust
matching the target if not already installed.

To fetch dependencies from crates.io you can use `cargo fetch` before building:
crazy-max marked this conversation as resolved.
Show resolved Hide resolved

```dockerfile
# syntax=docker/dockerfile:1
FROM --platform=$BUILDPLATFORM rust:alpine
RUN apk add clang lld
# ...
RUN --mount=type=cache,target=/root/.cargo/git/db \
--mount=type=cache,target=/root/.cargo/registry/cache \
--mount=type=cache,target=/root/.cargo/registry/index \
cargo fetch
ARG TARGETPLATFORM
RUN --mount=type=cache,target=/root/.cargo/git/db \
--mount=type=cache,target=/root/.cargo/registry/cache \
--mount=type=cache,target=/root/.cargo/registry/index \
xx-cargo build --release --target-dir ./build && \
xx-verify ./build/$(xx-cargo --print-target-triple)/release/hello_cargo
```

> **Note**
>
> By calling `cargo fetch` before `ARG TARGETPLATFORM` your packages are
> fetched only once for the whole build while the building happens separately
> for each target architecture.

To avoid redownloading dependencies on every build, you can use cache mounts
to store [Git sources with packages and metadata of crate registries](https://doc.rust-lang.org/cargo/guide/cargo-home.html#directories).

If you don't want to use the official Rust image, you can install `rustup`
manually:

```dockerfile
# syntax=docker/dockerfile:1
# rustup
FROM --platform=$BUILDPLATFORM alpine AS rustup
RUN apk add curl
RUN curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain stable --no-modify-path --profile minimal
Expand All @@ -369,51 +417,41 @@ ENV PATH="/root/.cargo/bin:$PATH"
FROM rustup
RUN apk add clang lld
# ...
RUN --mount=type=cache,target=/root/.cargo/git/db \
--mount=type=cache,target=/root/.cargo/registry/cache \
--mount=type=cache,target=/root/.cargo/registry/index \
cargo fetch
ARG TARGETPLATFORM
RUN xx-cargo build --release --target-dir ./build && \
xx-verify ./build/$(xx-cargo --print-target)/release/hello_cargo
xx-verify ./build/$(xx-cargo --print-target-triple)/release/hello_cargo
```

If you install rust using distribution packages, `rustup` will not be available:

```dockerfile
# syntax=docker/dockerfile:1
# packages
FROM --platform=$BUILDPLATFORM alpine
RUN apk add clang lld rust cargo
# ...
RUN --mount=type=cache,target=/root/.cargo/git/db \
--mount=type=cache,target=/root/.cargo/registry/cache \
--mount=type=cache,target=/root/.cargo/registry/index \
cargo fetch
ARG TARGETPLATFORM
RUN xx-apk add xx-c-essentials
RUN xx-cargo build --release --target-dir ./build && \
xx-verify ./build/$(xx-cargo --print-target)/release/hello_cargo
xx-verify ./build/$(xx-cargo --print-target-triple)/release/hello_cargo
```

In this case, you need to also install minimum necessary packages using `xx-apk`.

### Building on Debian

Building on Debian/Ubuntu is very similar. If you are using `rustup`:

```dockerfile
# syntax=docker/dockerfile:1
# official rust image
FROM --platform=$BUILDPLATFORM rust:bullseye
RUN apt-get update && apt-get install -y clang lld
# ...
RUN --mount=type=cache,target=/usr/local/cargo/git/db \
--mount=type=cache,target=/usr/local/cargo/registry/cache \
--mount=type=cache,target=/usr/local/cargo/registry/index \
cargo fetch
ARG TARGETPLATFORM
RUN xx-cargo build --release --target-dir ./build && \
xx-verify ./build/$(xx-cargo --print-target)/release/hello_cargo
xx-verify ./build/$(xx-cargo --print-target-triple)/release/hello_cargo
```

```dockerfile
# syntax=docker/dockerfile:1
# rustup
FROM --platform=$BUILDPLATFORM debian:bullseye AS rustup
RUN apt-get update && apt-get install -y curl ca-certificates
RUN curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain stable --no-modify-path --profile minimal
Expand All @@ -422,29 +460,21 @@ ENV PATH="/root/.cargo/bin:$PATH"
FROM rustup
RUN apt-get update && apt-get install -y clang lld
# ...
RUN --mount=type=cache,target=/root/.cargo/git/db \
--mount=type=cache,target=/root/.cargo/registry/cache \
--mount=type=cache,target=/root/.cargo/registry/index \
cargo fetch
ARG TARGETPLATFORM
RUN xx-cargo build --release --target-dir ./build && \
xx-verify ./build/$(xx-cargo --print-target)/release/hello_cargo
xx-verify ./build/$(xx-cargo --print-target-triple)/release/hello_cargo
```

Or distribution packages:

```dockerfile
# syntax=docker/dockerfile:1
# packages
FROM --platform=$BUILDPLATFORM debian:bullseye
RUN apt-get update && apt-get install -y clang lld cargo
# ...
RUN --mount=type=cache,target=/root/.cargo/git/db \
--mount=type=cache,target=/root/.cargo/registry/cache \
--mount=type=cache,target=/root/.cargo/registry/index \
cargo fetch
ARG TARGETPLATFORM
RUN xx-apt-get install xx-c-essentials
RUN xx-cargo build --release --target-dir ./build && \
xx-verify ./build/$(xx-cargo --print-target)/release/hello_cargo
xx-verify ./build/$(xx-cargo --print-target-triple)/release/hello_cargo
```

## External SDK support
Expand Down
4 changes: 2 additions & 2 deletions base/test-cargo.bats
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ testHelloCargo() {
assert_success
run xx-cargo build --verbose --color=never --manifest-path=./fixtures/hello_cargo/Cargo.toml --release --target-dir /tmp/cargobuild
assert_success
xx-verify /tmp/cargobuild/$(xx-cargo --print-target)/release/hello_cargo
xx-verify /tmp/cargobuild/$(xx-cargo --print-target-triple)/release/hello_cargo
if ! xx-info is-cross; then
run /tmp/cargobuild/$(xx-cargo --print-target)/release/hello_cargo
run /tmp/cargobuild/$(xx-cargo --print-target-triple)/release/hello_cargo
assert_success
assert_output "hello cargo"
fi
Expand Down
2 changes: 1 addition & 1 deletion base/xx-cargo
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ for a in "$@"; do
"--setup-target-triple")
setuponly=1
;;
"--print-target")
"--print-target-triple")
printtarget=1
;;
*)
Expand Down