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.

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 cross-rs#860.
  • Loading branch information
Alexhuszagh committed Jun 29, 2022
1 parent 6c2226d commit 7f53e0d
Show file tree
Hide file tree
Showing 16 changed files with 349 additions and 70 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 && matrix.target != 'zig'
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.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.

### 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}
}
48 changes: 48 additions & 0 deletions ci/test-zig.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#!/usr/bin/env bash
# shellcheck disable=SC2086,SC1091,SC1090

set -x
set -euo 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"
)

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}"
# note: ensure #724 doesn't replicate during CI.
cargo clean
done

popd
rm -rf "${td}"
}

main "${@}"
26 changes: 4 additions & 22 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 @@ -8,27 +8,9 @@ set -euo pipefail
# installed version on macOS. likewise, "${var[@]}" is an unbound
# error if var is an empty array.

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}
}
ci_dir=$(dirname "${BASH_SOURCE[0]}")
ci_dir=$(realpath "${ci_dir}")
. "${ci_dir}"/shared.sh

workspace_test() {
"${CROSS[@]}" build --target "${TARGET}" --workspace "$@" ${CROSS_FLAGS}
Expand Down
30 changes: 30 additions & 0 deletions docker/Dockerfile.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
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

COPY zig.sh /
RUN /zig.sh

# needed for the zig cache, which tries to install a cache dir
# in the current users directory, relative to $HOME. if the user
# doesn't exist, it will try to install in the root directory,
# getting permission errors
RUN adduser --uid 1000 --disabled-password --gecos "" cross
RUN apt-get update && apt-get install --assume-yes --no-install-recommends \
qemu-system \
qemu-user
# 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`).
62 changes: 62 additions & 0 deletions docker/zig.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#!/usr/bin/env bash

set -x
set -euo pipefail

# shellcheck disable=SC1091
. lib.sh

main() {
install_packages ca-certificates curl xz-utils

install_zig
install_zigbuild

purge_packages
rm "${0}"
}

install_zig() {
local version="0.9.1"
local filename="zig-linux-x86_64-${version}.tar.xz"
local dst="/opt/zig"

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_zigbuild() {
local version=0.10.3

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 /usr/local

popd

rm -rf "${td}"
}

main "${@}"
2 changes: 2 additions & 0 deletions docs/cross_toml.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ The `build` key allows you to set global variables, e.g.:
[build]
xargo = true
build-std = true
zig = false
default-target = "x86_64-unknown-linux-gnu"
```

Expand All @@ -33,6 +34,7 @@ The `target` key allows you to specify parameters for specific compilation targe
[target.aarch64-unknown-linux-gnu]
xargo = false
build-std = false
zig = true
image = "test-image"
pre-build = ["apt-get update"]
runner = "custom-runner"
Expand Down
12 changes: 11 additions & 1 deletion src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@ impl Environment {
self.get_values_for("BUILD_STD", target, bool_from_envvar)
}

fn zig(&self, target: &Target) -> (Option<bool>, Option<bool>) {
self.get_values_for("ZIG", target, bool_from_envvar)
}

fn image(&self, target: &Target) -> Option<String> {
self.get_target_var(target, "IMAGE")
}
Expand Down Expand Up @@ -244,6 +248,10 @@ impl Config {
self.bool_from_config(target, Environment::build_std, CrossToml::build_std)
}

pub fn zig(&self, target: &Target) -> Option<bool> {
self.bool_from_config(target, Environment::zig, CrossToml::zig)
}

pub fn image(&self, target: &Target) -> Result<Option<String>> {
self.string_from_config(target, Environment::image, CrossToml::image)
}
Expand Down Expand Up @@ -382,16 +390,19 @@ mod tests {
let env = Environment::new(Some(map));
assert_eq!(env.xargo(&target()), (Some(true), None));
assert_eq!(env.build_std(&target()), (Some(false), None));
assert_eq!(env.zig(&target()), (None, None));
}

#[test]
pub fn build_and_target_set_returns_tuple() {
let mut map = std::collections::HashMap::new();
map.insert("CROSS_BUILD_XARGO", "true");
map.insert("CROSS_BUILD_ZIG", "false");
map.insert("CROSS_TARGET_AARCH64_UNKNOWN_LINUX_GNU_XARGO", "false");

let env = Environment::new(Some(map));
assert_eq!(env.xargo(&target()), (Some(true), Some(false)));
assert_eq!(env.zig(&target()), (Some(false), None));
}

#[test]
Expand Down Expand Up @@ -527,7 +538,6 @@ mod tests {
config.env_volumes(&target())?,
Some(vec![s!("VOLUME3"), s!("VOLUME4")])
);
// TODO(ahuszagh) Need volumes

Ok(())
}
Expand Down
Loading

0 comments on commit 7f53e0d

Please sign in to comment.