Skip to content

Commit 3f60cc1

Browse files
Merge #880
880: Add a `zig cc`-based image. r=Emilgardis a=Alexhuszagh Uses cargo-zigbuild as a backend, and adds configuration options for zig under `[build.zig]` and `[target.(...).zig]`. If enabled, and an image override is not provided, `cross` will always use the `zig` image. It supports custom `glibc` versions by parsing the libc portion of the target, and extracting a the libc version if present. The target, if built-in, is then the triple/libc pair, otherwise, it's just the triple. The image does not provide runners, `bindgen` Clang args, or `pkg-config` paths, since `zig cc` does not provide the dynamic library loader (`ld-linux*.so`) required, meaning none of the binaries can be run. For `bindgen`, `zig cc` has an unusual directory structure, so there is no traditional sysroot with `usr`, `lib`, and `include` subdirectories. Finally, since we don't have system packages we can work with, exporting a `pkg-config` path makes little sense. Closes #860. Co-authored-by: Alex Huszagh <[email protected]>
2 parents 91e0377 + 95fe313 commit 3f60cc1

File tree

16 files changed

+729
-46
lines changed

16 files changed

+729
-46
lines changed

.changes/880.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"description": "added a zig-based image, allowing multiple targets to be built from the same image, using cargo-zigbuild.",
3+
"type": "added",
4+
"issues": [860]
5+
}

.github/workflows/ci.yml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,7 @@ jobs:
209209
- { target: thumbv7em-none-eabihf, os: ubuntu-latest, std: 1 }
210210
- { target: thumbv7m-none-eabi, os: ubuntu-latest, std: 1 }
211211
- { target: cross, os: ubuntu-latest }
212+
- { target: zig, os: ubuntu-latest }
212213
213214
build:
214215
name: target (${{ matrix.pretty }},${{ matrix.os }})
@@ -247,7 +248,7 @@ jobs:
247248
- name: LLVM instrument coverage
248249
id: cov
249250
uses: ./.github/actions/cargo-llvm-cov
250-
if: steps.prepare-meta.outputs.has-image
251+
if: steps.prepare-meta.outputs.has-image && steps.prepare-meta.outputs.test-variant != 'zig'
251252
with:
252253
name: cross-${{matrix.pretty}}
253254

@@ -302,6 +303,11 @@ jobs:
302303
target: ${{ matrix.target }}
303304
image: ${{ steps.build-docker-image.outputs.image }}
304305

306+
- name: Test Zig Image
307+
if: steps.prepare-meta.outputs.has-image && steps.prepare-meta.outputs.test-variant == 'zig'
308+
run: ./ci/test-zig-image.sh
309+
shell: bash
310+
305311
- name: Test Cross Image
306312
if: steps.prepare-meta.outputs.has-image && steps.prepare-meta.outputs.test-variant == 'cross'
307313
run: ./ci/test-cross-image.sh

ci/test-zig-image.sh

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
#!/usr/bin/env bash
2+
# shellcheck disable=SC2086,SC1091,SC1090
3+
4+
set -x
5+
set -eo pipefail
6+
7+
# NOTE: "${@}" is an unbound variable for bash 3.2, which is the
8+
# installed version on macOS. likewise, "${var[@]}" is an unbound
9+
# error if var is an empty array.
10+
11+
ci_dir=$(dirname "${BASH_SOURCE[0]}")
12+
ci_dir=$(realpath "${ci_dir}")
13+
. "${ci_dir}"/shared.sh
14+
15+
# zig cc is very slow: only use a few targets.
16+
TARGETS=(
17+
"aarch64-unknown-linux-gnu"
18+
"aarch64-unknown-linux-musl"
19+
"i586-unknown-linux-gnu"
20+
"i586-unknown-linux-musl"
21+
)
22+
23+
# on CI, it sets `CROSS_TARGET_ZIG_IMAGE` rather than `CROSS_TARGET_ZIG_IMAGE`
24+
if [[ -n "${CROSS_TARGET_ZIG_IMAGE}" ]]; then
25+
export CROSS_BUILD_ZIG_IMAGE="${CROSS_TARGET_ZIG_IMAGE}"
26+
unset CROSS_TARGET_ZIG_IMAGE
27+
fi
28+
29+
main() {
30+
export CROSS_BUILD_ZIG=1
31+
32+
local td=
33+
local target=
34+
35+
retry cargo fetch
36+
cargo build
37+
export CROSS="${PROJECT_HOME}/target/debug/cross"
38+
39+
td="$(mktemp -d)"
40+
git clone --depth 1 https://github.com/cross-rs/rust-cpp-hello-word "${td}"
41+
pushd "${td}"
42+
43+
for target in "${TARGETS[@]}"; do
44+
CROSS_CONTAINER_ENGINE="${CROSS_ENGINE}" "${CROSS}" build --target "${target}" --verbose
45+
# note: ensure #724 doesn't replicate during CI.
46+
# https://github.com/cross-rs/cross/issues/724
47+
cargo clean
48+
done
49+
50+
popd
51+
rm -rf "${td}"
52+
}
53+
54+
main "${@}"

docker/Dockerfile.zig

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
FROM ubuntu:20.04
2+
ARG DEBIAN_FRONTEND=noninteractive
3+
4+
COPY common.sh lib.sh /
5+
RUN /common.sh
6+
7+
COPY cmake.sh /
8+
RUN /cmake.sh
9+
10+
COPY xargo.sh /
11+
RUN /xargo.sh
12+
13+
ARG TARGETPLATFORM
14+
COPY zig.sh /
15+
RUN /zig.sh $TARGETPLATFORM
16+
17+
# we don't export `BINDGEN_EXTRA_CLANG_ARGS`, `QEMU_LD_PREFIX`, or
18+
# `PKG_CONFIG_PATH` since zig doesn't have a traditional sysroot structure,
19+
# and we're not using standard, shared packages. none of the packages
20+
# have runners either, since they do not ship with the required
21+
# dynamic linker (`ld-linux-${arch}.so`).
22+
ENV PATH=$PATH:/opt/zig

docker/zig.sh

Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
#!/usr/bin/env bash
2+
3+
set -x
4+
set -eo pipefail
5+
6+
# shellcheck disable=SC1091
7+
. lib.sh
8+
9+
main() {
10+
local platform="${1}"
11+
install_packages ca-certificates curl xz-utils
12+
13+
install_zig "${platform}"
14+
install_zigbuild "${platform}"
15+
16+
purge_packages
17+
rm "${0}"
18+
}
19+
20+
install_zig() {
21+
local platform="${1}"
22+
local version="0.9.1"
23+
local dst="/opt/zig"
24+
local arch=
25+
local os=
26+
local triple=
27+
28+
case "${platform}" in
29+
'linux/386')
30+
arch="i386"
31+
os="linux"
32+
;;
33+
'linux/amd64')
34+
arch="x86_64"
35+
os="linux"
36+
;;
37+
'linux/arm64')
38+
arch="aarch64"
39+
os="linux"
40+
;;
41+
'linux/riscv64')
42+
arch="riscv64"
43+
os="linux"
44+
;;
45+
'linux/ppc64le')
46+
triple="powerpc64le-linux-gnu"
47+
;;
48+
'linux/s390x')
49+
triple="s390x-linux-gnu"
50+
;;
51+
'darwin/amd64')
52+
arch="x86_64"
53+
os="macos"
54+
;;
55+
'darwin/arm64')
56+
arch="aarch64"
57+
os="macos"
58+
;;
59+
# NOTE: explicitly don't support linux/arm/v6
60+
*)
61+
echo "Unsupported target platform '${platform}'" 1>&2
62+
exit 1
63+
;;
64+
esac
65+
66+
if [[ -n "${arch}" ]]; then
67+
install_zig_tarball "${arch}" "${os}" "${version}" "${dst}"
68+
else
69+
install_zig_source "${triple}" "${version}" "${dst}"
70+
fi
71+
}
72+
73+
install_zig_tarball() {
74+
local arch="${1}"
75+
local os="${2}"
76+
local version="${3}"
77+
local dst="${4}"
78+
local filename="zig-${os}-${arch}-${version}.tar.xz"
79+
80+
local td
81+
td="$(mktemp -d)"
82+
83+
pushd "${td}"
84+
85+
curl --retry 3 -sSfL "https://ziglang.org/download/${version}/${filename}" -O
86+
mkdir -p "${dst}"
87+
tar --strip-components=1 -xJf "${filename}" --directory "${dst}"
88+
89+
popd
90+
91+
rm -rf "${td}"
92+
}
93+
94+
install_zig_source() {
95+
local triple="${1}"
96+
local version="${2}"
97+
local dst="${3}"
98+
local filename="zig-bootstrap-${version}.tar.xz"
99+
100+
local td
101+
td="$(mktemp -d)"
102+
103+
pushd "${td}"
104+
105+
curl --retry 3 -sSfL "https://ziglang.org/download/${version}/${filename}" -O
106+
mkdir zig
107+
tar --strip-components=1 -xJf "${filename}" --directory zig
108+
109+
pushd zig
110+
install_packages python3 make g++
111+
./build -j5 "${triple}" native
112+
mv "out/zig-${triple}-native" /opt/zig
113+
114+
popd
115+
popd
116+
117+
rm -rf "${td}"
118+
}
119+
120+
install_zigbuild() {
121+
local platform="${1}"
122+
local version=0.11.0
123+
local dst="/usr/local"
124+
local triple=
125+
126+
# we don't know if `linux/arm/v7` is hard-float,
127+
# and we don't know the the zigbuild `apple-darwin`
128+
# target doesn't manually specify the architecture.
129+
case "${platform}" in
130+
'linux/386')
131+
triple="i686-unknown-linux-musl"
132+
;;
133+
'linux/amd64')
134+
triple="x86_64-unknown-linux-musl"
135+
;;
136+
'linux/arm64')
137+
triple="aarch64-unknown-linux-musl"
138+
;;
139+
*)
140+
;;
141+
esac
142+
143+
if [[ -n "${triple}" ]]; then
144+
install_zigbuild_tarball "${triple}" "${version}" "${dst}"
145+
else
146+
install_zigbuild_source "${version}" "${dst}"
147+
fi
148+
}
149+
150+
install_zigbuild_tarball() {
151+
local triple="${1}"
152+
local version="${2}"
153+
local dst="${3}"
154+
local repo="https://github.com/messense/cargo-zigbuild"
155+
local filename="cargo-zigbuild-v${version}.${triple}.tar.gz"
156+
157+
local td
158+
td="$(mktemp -d)"
159+
160+
pushd "${td}"
161+
162+
curl --retry 3 -sSfL "${repo}/releases/download/v${version}/${filename}" -O
163+
mkdir -p "${dst}/bin"
164+
tar -xzf "${filename}" --directory "${dst}/bin"
165+
166+
popd
167+
168+
rm -rf "${td}"
169+
}
170+
171+
install_zigbuild_source() {
172+
local version="${1}"
173+
local dst="${2}"
174+
175+
local td
176+
td="$(mktemp -d)"
177+
178+
pushd "${td}"
179+
180+
export RUSTUP_HOME="${td}/rustup"
181+
export CARGO_HOME="${td}/cargo"
182+
183+
curl --retry 3 -sSfL https://sh.rustup.rs -o rustup-init.sh
184+
sh rustup-init.sh -y --no-modify-path --profile minimal
185+
186+
PATH="${CARGO_HOME}/bin:${PATH}" \
187+
cargo install cargo-zigbuild \
188+
--version "${version}" \
189+
--root "${dst}" \
190+
--locked
191+
192+
popd
193+
194+
rm -rf "${td}"
195+
}
196+
197+
main "${@}"

docs/cross_toml.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ The `target` key allows you to specify parameters for specific compilation targe
3333
[target.aarch64-unknown-linux-gnu]
3434
xargo = false
3535
build-std = false
36+
zig = "2.17"
3637
image = "test-image"
3738
pre-build = ["apt-get update"] # can also be the path to a file to run
3839
runner = "custom-runner"
@@ -92,3 +93,26 @@ also supports
9293
[target.x86_64-unknown-linux-gnu]
9394
dockerfile = "./Dockerfile"
9495
```
96+
97+
# `target.TARGET.zig`
98+
99+
```toml
100+
[target.x86_64-unknown-linux-gnu.zig]
101+
enable = true # enable use of the zig image
102+
version = "2.17" # glibc version to use
103+
image = "zig:local" # custom zig image to use
104+
```
105+
106+
also supports
107+
108+
```toml
109+
[target.x86_64-unknown-linux-gnu]
110+
zig = true
111+
```
112+
113+
or
114+
115+
```toml
116+
[target.x86_64-unknown-linux-gnu]
117+
zig = "2.17"
118+
```

0 commit comments

Comments
 (0)