Proof of concept mechanical port of ircnet/ircd to Rust as part of a bit about C being insecure for network services
1#!/usr/bin/env bash
2#
3# generate-release-assets.sh — build leveva for x86_64 + aarch64 and emit
4# .deb and .rpm packages for each architecture.
5#
6# Cross-compilation is handled by cargo-zigbuild (zig as the linker/sysroot),
7# so no per-arch C toolchain is required. Both targets are static musl builds.
8# Packaging is pure-Rust: cargo-deb and cargo-generate-rpm read the
9# [package.metadata.deb] / [package.metadata.generate-rpm] tables in
10# leveva/Cargo.toml. Passing --target to each rewrites the `target/release/`
11# asset prefix to `target/<triple>/release/`, so they pick up the cross binary.
12#
13# The architecture set is the one leveva ships images for — the platforms in
14# docker-bake.hcl / docker/Dockerfile.leveva (amd64, arm64, ppc64le, ppc64,
15# riscv64), mapped to their musl triples below.
16#
17# Outputs (relative to the workspace root):
18# target/<triple>/debian/leveva_<ver>_<arch>.deb
19# target/<triple>/generate-rpm/leveva-<ver>-1.<arch>.rpm
20# and a copy of every artifact collected under var/dist/leveva-<ver>/, where
21# <ver> is leveva's package version from leveva/Cargo.toml.
22set -euo pipefail
23
24# Resolve the workspace root (parent of this script's directory) so the script
25# works regardless of the caller's cwd; cargo-deb/-rpm resolve asset paths
26# relative to it.
27SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
28ROOT_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)"
29cd "${ROOT_DIR}"
30
31# One musl triple per docker-bake.hcl platform:
32# linux/amd64 -> x86_64-unknown-linux-musl
33# linux/arm64 -> aarch64-unknown-linux-musl
34# linux/riscv64 -> riscv64gc-unknown-linux-musl
35# linux/ppc64le -> powerpc64le-unknown-linux-musl
36# linux/ppc64 -> powerpc64-unknown-linux-musl
37TARGETS=(
38 x86_64-unknown-linux-musl
39 aarch64-unknown-linux-musl
40 riscv64gc-unknown-linux-musl
41 powerpc64le-unknown-linux-musl
42 powerpc64-unknown-linux-musl
43)
44
45# Derive the version from leveva's package manifest (the first `version = "..."`
46# line, which sits directly under [package]) so the output dir tracks the crate.
47VERSION="$(sed -n 's/^version = "\(.*\)"/\1/p' "${ROOT_DIR}/leveva/Cargo.toml" | head -n1)"
48if [ -z "${VERSION}" ]; then
49 echo "error: could not parse package version from leveva/Cargo.toml" >&2
50 exit 1
51fi
52
53OUT_DIR="${ROOT_DIR}/var/dist/leveva-${VERSION}"
54
55require() {
56 command -v "$1" >/dev/null 2>&1 || {
57 echo "error: required tool '$1' not found in PATH" >&2
58 echo " install with: $2" >&2
59 exit 1
60 }
61}
62
63require cargo "https://rustup.rs"
64require zig "https://ziglang.org/download/ (or: brew install zig)"
65require cargo-zigbuild "cargo install cargo-zigbuild"
66require cargo-deb "cargo install cargo-deb"
67require cargo-generate-rpm "cargo install cargo-generate-rpm"
68
69# Ensure the rustup std component is present for each target; zigbuild links the
70# objects but rustc still needs the precompiled std for the triple.
71for triple in "${TARGETS[@]}"; do
72 if ! rustup target list --installed 2>/dev/null | grep -qx "${triple}"; then
73 echo ">> adding rust target ${triple}"
74 rustup target add "${triple}"
75 fi
76done
77
78mkdir -p "${OUT_DIR}"
79
80for triple in "${TARGETS[@]}"; do
81 echo
82 echo "==> ${triple}"
83
84 echo ">> cargo zigbuild --release"
85 cargo zigbuild --quiet --release --target "${triple}" -p leveva
86
87 # --no-build: reuse the zigbuild artifact above (cargo-deb would otherwise
88 # invoke a plain `cargo build` that lacks the zig cross linker).
89 # --no-strip: the host `strip` can't process a foreign-arch binary; the
90 # musl release binary is already lean enough to ship unstripped.
91 echo ">> cargo deb"
92 cargo deb -p leveva --target "${triple}" --no-build --no-strip
93
94 echo ">> cargo generate-rpm"
95 cargo generate-rpm -p leveva --target "${triple}"
96
97 # Collect the artifacts into one place for convenience.
98 cp -v "target/${triple}/debian/"*.deb "${OUT_DIR}/"
99 cp -v "target/${triple}/generate-rpm/"*.rpm "${OUT_DIR}/"
100done
101
102echo
103echo "==> release assets collected in ${OUT_DIR}:"
104ls -1 "${OUT_DIR}"