Skip to content

Commit

Permalink
Add a zig cc-based image.
Browse files Browse the repository at this point in the history
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. The feature can be enabled by providing `zig` as a table, bool, or string.

It supports custom glibc versions by passing the `zig.version` key, and `zig` can be separately enabled or disabled by providing `zig.enable`.

```
[target.x86_64-unknown-linux-gnu.zig]
enable = true       # enable use of the zig image
version = "2.17"    # glibc version to use
image = "ghcr.io/cross-rs/zig:local"    # custom image to use
```

If provided as a bool, it will use the default glibc version:

```
[target.x86_64-unknown-linux-gnu]
\# equivalent to { enable = true }
zig = true
```

If provided as a string, `zig` will be automatically enabled:

```
[target.x86_64-unknown-linux-gnu]
\# equivalent to { enable = true, version = "2.17" }
zig = "2.17"
```

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 cross-rs#860.
  • Loading branch information
Alexhuszagh committed Jun 30, 2022
1 parent 5d07ee6 commit e4d444a
Show file tree
Hide file tree
Showing 18 changed files with 634 additions and 61 deletions.
9 changes: 8 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,7 @@ jobs:
- { target: thumbv7em-none-eabi, os: ubuntu-latest, std: 1 }
- { target: thumbv7em-none-eabihf, os: ubuntu-latest, std: 1 }
- { target: thumbv7m-none-eabi, os: ubuntu-latest, std: 1 }
- { target: zig, os: ubuntu-latest }
build:
name: target (${{ matrix.pretty }},${{ matrix.os }})
Expand Down Expand Up @@ -283,7 +284,7 @@ jobs:
IMAGE: ${{ steps.build-docker-image.outputs.image }}
shell: bash
- name: Test Image
if: steps.prepare-meta.outputs.has-image
if: steps.prepare-meta.outputs.has-image && steps.prepare-meta.outputs.default-test
run: ./ci/test.sh
env:
TARGET: ${{ matrix.target }}
Expand All @@ -294,6 +295,12 @@ jobs:
RUN: ${{ matrix.run }}
RUNNERS: ${{ matrix.runners }}
shell: bash

- name: Test Zig Image
if: steps.prepare-meta.outputs.has-image && matrix.target == 'zig'
run: ./ci/test-zig-image.sh
shell: bash

- uses: ./.github/actions/cargo-install-upload-artifacts
if: matrix.deploy
with:
Expand Down
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ This project adheres to [Semantic Versioning](http://semver.org/).

## [Unreleased] - ReleaseDate

### Added

- #880 - added a zig-based image, allowing multiple targets to be built from the same image, using cargo-zigbuild.

### Changed

- #869 - ensure cargo configuration environment variable flags are passed to the docker container.
Expand Down
23 changes: 23 additions & 0 deletions ci/shared.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#!/usr/bin/env bash

function retry {
local tries="${TRIES-5}"
local timeout="${TIMEOUT-1}"
local try=0
local exit_code=0

while (( try < tries )); do
if "${@}"; then
return 0
else
exit_code=$?
fi

sleep "${timeout}"
echo "Retrying ..." 1>&2
try=$(( try + 1 ))
timeout=$(( timeout * 2 ))
done

return ${exit_code}
}
55 changes: 55 additions & 0 deletions ci/test-zig-image.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#!/usr/bin/env bash
# shellcheck disable=SC2086,SC1091,SC1090

set -x
set -eo pipefail

# NOTE: "${@}" is an unbound variable for bash 3.2, which is the
# installed version on macOS. likewise, "${var[@]}" is an unbound
# error if var is an empty array.

ci_dir=$(dirname "${BASH_SOURCE[0]}")
ci_dir=$(realpath "${ci_dir}")
project_home=$(dirname "${ci_dir}")
. "${ci_dir}"/shared.sh

# zig cc is very slow: only use a few targets.
TARGETS=(
"aarch64-unknown-linux-gnu"
"aarch64-unknown-linux-musl"
"i586-unknown-linux-gnu"
"i586-unknown-linux-musl"
)

# on CI, it sets `CROSS_TARGET_ZIG_IMAGE` rather than `CROSS_TARGET_ZIG_IMAGE`
if [[ -n "${CROSS_TARGET_ZIG_IMAGE}" ]]; then
export CROSS_BUILD_ZIG_IMAGE="${CROSS_TARGET_ZIG_IMAGE}"
unset CROSS_TARGET_ZIG_IMAGE
fi

main() {
export CROSS_BUILD_ZIG=1

local td=
local target=

retry cargo fetch
cargo build
export CROSS="${project_home}/target/debug/cross"

td="$(mktemp -d)"
git clone --depth 1 https://github.com/cross-rs/rust-cpp-hello-word "${td}"
pushd "${td}"

for target in "${TARGETS[@]}"; do
"${CROSS}" build --target "${target}" --verbose
# note: ensure #724 doesn't replicate during CI.
# https://github.com/cross-rs/cross/issues/724
cargo clean
done

popd
rm -rf "${td}"
}

main "${@}"
25 changes: 2 additions & 23 deletions ci/test.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/usr/bin/env bash
# shellcheck disable=SC2086
# shellcheck disable=SC2086,SC1091,SC1090

set -x
set -euo pipefail
Expand All @@ -10,30 +10,9 @@ set -euo pipefail

ci_dir=$(dirname "${BASH_SOURCE[0]}")
ci_dir=$(realpath "${ci_dir}")
. "${ci_dir}"/shared.sh
project_home=$(dirname "${ci_dir}")

function retry {
local tries="${TRIES-5}"
local timeout="${TIMEOUT-1}"
local try=0
local exit_code=0

while (( try < tries )); do
if "${@}"; then
return 0
else
exit_code=$?
fi

sleep "${timeout}"
echo "Retrying ..." 1>&2
try=$(( try + 1 ))
timeout=$(( timeout * 2 ))
done

return ${exit_code}
}

workspace_test() {
"${CROSS[@]}" build --target "${TARGET}" --workspace "$@" ${CROSS_FLAGS}
"${CROSS[@]}" run --target "${TARGET}" -p binary "$@" ${CROSS_FLAGS}
Expand Down
22 changes: 22 additions & 0 deletions docker/Dockerfile.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
FROM ubuntu:20.04
ARG DEBIAN_FRONTEND=noninteractive

COPY common.sh lib.sh /
RUN /common.sh

COPY cmake.sh /
RUN /cmake.sh

COPY xargo.sh /
RUN /xargo.sh

ARG TARGETPLATFORM
COPY zig.sh /
RUN /zig.sh $TARGETPLATFORM

# we don't export `BINDGEN_EXTRA_CLANG_ARGS`, `QEMU_LD_PREFIX`, or
# `PKG_CONFIG_PATH` since zig doesn't have a traditional sysroot structure,
# and we're not using standard, shared packages. none of the packages
# have runners either, since they do not ship with the required
# dynamic linker (`ld-linux-${arch}.so`).
ENV PATH=$PATH:/opt/zig
197 changes: 197 additions & 0 deletions docker/zig.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
#!/usr/bin/env bash

set -x
set -eo pipefail

# shellcheck disable=SC1091
. lib.sh

main() {
local platform="${1}"
install_packages ca-certificates curl xz-utils

install_zig "${platform}"
install_zigbuild "${platform}"

purge_packages
rm "${0}"
}

install_zig() {
local platform="${1}"
local version="0.9.1"
local dst="/opt/zig"
local arch=
local os=
local triple=

case "${platform}" in
'linux/386')
arch="i386"
os="linux"
;;
'linux/amd64')
arch="x86_64"
os="linux"
;;
'linux/arm64')
arch="aarch64"
os="linux"
;;
'linux/riscv64')
arch="riscv64"
os="linux"
;;
'linux/ppc64le')
triple="powerpc64le-linux-gnu"
;;
'linux/s390x')
triple="s390x-linux-gnu"
;;
'darwin/amd64')
arch="x86_64"
os="macos"
;;
'darwin/arm64')
arch="aarch64"
os="macos"
;;
# NOTE: explicitly don't support linux/arm/v6
*)
echo "Unsupported target platform '${platform}'" 1>&2
exit 1
;;
esac

if [[ -n "${arch}" ]]; then
install_zig_tarball "${arch}" "${os}" "${version}" "${dst}"
else
install_zig_source "${triple}" "${version}" "${dst}"
fi
}

install_zig_tarball() {
local arch="${1}"
local os="${2}"
local version="${3}"
local dst="${4}"
local filename="zig-${os}-${arch}-${version}.tar.xz"

local td
td="$(mktemp -d)"

pushd "${td}"

curl --retry 3 -sSfL "https://ziglang.org/download/${version}/${filename}" -O
mkdir -p "${dst}"
tar --strip-components=1 -xJf "${filename}" --directory "${dst}"

popd

rm -rf "${td}"
}

install_zig_source() {
local triple="${1}"
local version="${2}"
local dst="${3}"
local filename="zig-bootstrap-${version}.tar.xz"

local td
td="$(mktemp -d)"

pushd "${td}"

curl --retry 3 -sSfL "https://ziglang.org/download/${version}/${filename}" -O
mkdir zig
tar --strip-components=1 -xJf "${filename}" --directory zig

pushd zig
install_packages python3 make g++
./build -j5 "${triple}" native
mv "out/zig-${triple}-native" /opt/zig

popd
popd

rm -rf "${td}"
}

install_zigbuild() {
local platform="${1}"
local version=0.11.0
local dst="/usr/local"
local triple=

# we don't know if `linux/arm/v7` is hard-float,
# and we don't know the the zigbuild `apple-darwin`
# target doesn't manually specify the architecture.
case "${platform}" in
'linux/386')
triple="i686-unknown-linux-musl"
;;
'linux/amd64')
triple="x86_64-unknown-linux-musl"
;;
'linux/arm64')
triple="aarch64-unknown-linux-musl"
;;
*)
;;
esac

if [[ -n "${triple}" ]]; then
install_zigbuild_tarball "${triple}" "${version}" "${dst}"
else
install_zigbuild_source "${version}" "${dst}"
fi
}

install_zigbuild_tarball() {
local triple="${1}"
local version="${2}"
local dst="${3}"
local repo="https://github.com/messense/cargo-zigbuild"
local filename="cargo-zigbuild-v${version}.${triple}.tar.gz"

local td
td="$(mktemp -d)"

pushd "${td}"

curl --retry 3 -sSfL "${repo}/releases/download/v${version}/${filename}" -O
mkdir -p "${dst}/bin"
tar -xzf "${filename}" --directory "${dst}/bin"

popd

rm -rf "${td}"
}

install_zigbuild_source() {
local version="${1}"
local dst="${2}"

local td
td="$(mktemp -d)"

pushd "${td}"

export RUSTUP_HOME="${td}/rustup"
export CARGO_HOME="${td}/cargo"

curl --retry 3 -sSfL https://sh.rustup.rs -o rustup-init.sh
sh rustup-init.sh -y --no-modify-path --profile minimal

PATH="${CARGO_HOME}/bin:${PATH}" \
cargo install cargo-zigbuild \
--version "${version}" \
--root "${dst}" \
--locked

popd

rm -rf "${td}"
}

main "${@}"
Loading

0 comments on commit e4d444a

Please sign in to comment.