third_party/nix: introduce toolchain bundle
This introduces a nix derivation that builds a musl amd64/aarch64
toolchain sysroot.
Change-Id: Iba082edb8fd1f2ab580020bb1c7339a76487f3c8
Reviewed-on: https://review.monogon.dev/c/monogon/+/4006
Reviewed-by: Lorenz Brun <lorenz@monogon.tech>
Tested-by: Jenkins CI
diff --git a/build/toolchain/README.md b/build/toolchain/README.md
new file mode 100644
index 0000000..99e673f
--- /dev/null
+++ b/build/toolchain/README.md
@@ -0,0 +1,11 @@
+# Toolchain Bundle (`toolchain-bundle/`)
+
+To ensure that tools like `make`, `nasm`, `qemu`, or `perl` are available in the Bazel build environment, we provide a `toolchain-bundle`. This bundle is pre-built and fetched as an external repository, allowing Bazel to use these tools without needing to install them on the host system. They are built for both `x86_64-unknown-linux-musl` and `aarch64-unknown-linux-musl` platforms with Nix.
+
+You can build these toolchains by invoking the `nix-build` via `nix-build build/toolchain/toolchain-bundle/default.nix`
+
+---
+
+# Rust EFI Toolchain (`rust-efi/`)
+
+The `rust-efi` directory configures a Rust toolchain for building EFI applications.
\ No newline at end of file
diff --git a/build/toolchain/toolchain-bundle/BUILD.bazel b/build/toolchain/toolchain-bundle/BUILD.bazel
new file mode 100644
index 0000000..1b26331
--- /dev/null
+++ b/build/toolchain/toolchain-bundle/BUILD.bazel
@@ -0,0 +1,11 @@
+load(":toolchain.bzl", "TOOLCHAINS", "toolchain_for")
+
+package(default_visibility = ["//visibility:public"])
+
+[
+ toolchain_for(
+ name = name,
+ config = config,
+ )
+ for name, config in TOOLCHAINS.items()
+]
diff --git a/build/toolchain/toolchain-bundle/default.nix b/build/toolchain/toolchain-bundle/default.nix
new file mode 100644
index 0000000..f59a6a8
--- /dev/null
+++ b/build/toolchain/toolchain-bundle/default.nix
@@ -0,0 +1,52 @@
+{ pkgs ? import ../../../third_party/nix/default.nix { } }: with pkgs;
+symlinkJoin {
+ name = "toolchain";
+ paths =
+ let
+ platforms = with pkgsCross; [
+ aarch64-multiplatform-musl
+ musl64
+ ];
+ in
+ map
+ (platform: (
+ let
+ merged = buildEnv {
+ name = "toolchain-env";
+ paths = with platform.pkgsStatic; [
+ gnumake
+ flex
+ bison
+ lz4
+ busybox
+ findutils
+ bc
+ util-linux-minimal # custom pkg
+ perl
+ nasm
+ acpica-tools
+ patch
+ diffutils
+ qemu-minimal # custom pkg
+ m4
+ strace
+ ];
+ };
+ in
+ stdenv.mkDerivation rec {
+ name = "toolchain-bundle";
+ buildInputs = [ gnutar zstd ];
+
+ phases = [ "buildPhase" "installPhase" ];
+ buildPhase = ''
+ tar --zstd --sort=name --hard-dereference -hcf bundle.tar.zst -C ${merged} .
+ '';
+
+ installPhase = ''
+ mkdir $out
+ mv bundle.tar.zst $out/${name}-${platform.hostPlatform.config}-${lib.version}.tar.zst
+ '';
+ }
+ ))
+ platforms;
+}
diff --git a/build/toolchain/toolchain-bundle/toolchain-bundle.bzl b/build/toolchain/toolchain-bundle/toolchain-bundle.bzl
new file mode 100644
index 0000000..6ac17fb
--- /dev/null
+++ b/build/toolchain/toolchain-bundle/toolchain-bundle.bzl
@@ -0,0 +1,453 @@
+package(default_visibility = ["//visibility:public"])
+
+exports_files(glob([
+ "**/*",
+]))
+
+# rules_perl expects all files as src entry, this does prevent us using
+# $(execpath) which is why we have another filegroup that uses this as
+# data dep.
+filegroup(
+ name = "perl_runtime",
+ srcs = [
+ ":bin/perl",
+ ":bin/xsubpp",
+ ] + glob([
+ "lib/perl5/**",
+ ]),
+)
+
+filegroup(
+ name = "perl",
+ srcs = [
+ ":bin/perl",
+ ],
+ data = [
+ ":perl_runtime",
+ ],
+)
+
+filegroup(
+ name = "bison",
+ srcs = [
+ ":bin/bison",
+ ],
+ data = glob([
+ "share/bison/**",
+ ]),
+)
+
+filegroup(
+ name = "qemu-kvm",
+ srcs = [
+ ":bin/qemu-kvm",
+ ],
+ data = glob([
+ "share/qemu-firmware/**",
+ "share/qemu/**",
+ ]),
+)
+
+filegroup(
+ name = "busybox",
+ srcs = [
+ ":bin/busybox",
+ ],
+ data = [
+ ":bin/[",
+ ":bin/[[",
+ ":bin/acpid",
+ ":bin/add-shell",
+ ":bin/addgroup",
+ ":bin/adduser",
+ ":bin/adjtimex",
+ ":bin/arch",
+ ":bin/arp",
+ ":bin/arping",
+ ":bin/ascii",
+ ":bin/ash",
+ ":bin/awk",
+ ":bin/base32",
+ ":bin/base64",
+ ":bin/basename",
+ ":bin/bc",
+ ":bin/beep",
+ ":bin/blkdiscard",
+ ":bin/blkid",
+ ":bin/blockdev",
+ ":bin/bootchartd",
+ ":bin/brctl",
+ ":bin/bunzip2",
+ ":bin/busybox",
+ ":bin/bzcat",
+ ":bin/bzip2",
+ ":bin/cal",
+ ":bin/cat",
+ ":bin/chat",
+ ":bin/chattr",
+ ":bin/chgrp",
+ ":bin/chmod",
+ ":bin/chown",
+ ":bin/chpasswd",
+ ":bin/chpst",
+ ":bin/chroot",
+ ":bin/chrt",
+ ":bin/chvt",
+ ":bin/cksum",
+ ":bin/clear",
+ ":bin/cmp",
+ ":bin/comm",
+ ":bin/conspy",
+ ":bin/cp",
+ ":bin/cpio",
+ ":bin/crc32",
+ ":bin/crond",
+ ":bin/crontab",
+ ":bin/cryptpw",
+ ":bin/cttyhack",
+ ":bin/cut",
+ ":bin/date",
+ ":bin/dc",
+ ":bin/dd",
+ ":bin/deallocvt",
+ ":bin/delgroup",
+ ":bin/deluser",
+ ":bin/depmod",
+ ":bin/devmem",
+ ":bin/df",
+ ":bin/dhcprelay",
+ ":bin/diff",
+ ":bin/dirname",
+ ":bin/dmesg",
+ ":bin/dnsd",
+ ":bin/dnsdomainname",
+ ":bin/dos2unix",
+ ":bin/dpkg",
+ ":bin/dpkg-deb",
+ ":bin/du",
+ ":bin/dumpkmap",
+ ":bin/dumpleases",
+ ":bin/echo",
+ ":bin/ed",
+ ":bin/egrep",
+ ":bin/eject",
+ ":bin/env",
+ ":bin/envdir",
+ ":bin/envuidgid",
+ ":bin/ether-wake",
+ ":bin/expand",
+ ":bin/expr",
+ ":bin/factor",
+ ":bin/fakeidentd",
+ ":bin/fallocate",
+ ":bin/false",
+ ":bin/fatattr",
+ ":bin/fbset",
+ ":bin/fbsplash",
+ ":bin/fdflush",
+ ":bin/fdformat",
+ ":bin/fdisk",
+ ":bin/fgconsole",
+ ":bin/fgrep",
+ ":bin/find",
+ ":bin/findfs",
+ ":bin/flock",
+ ":bin/fold",
+ ":bin/free",
+ ":bin/freeramdisk",
+ ":bin/fsck",
+ ":bin/fsck.minix",
+ ":bin/fsfreeze",
+ ":bin/fstrim",
+ ":bin/fsync",
+ ":bin/ftpd",
+ ":bin/ftpget",
+ ":bin/ftpput",
+ ":bin/fuser",
+ ":bin/getopt",
+ ":bin/getty",
+ ":bin/grep",
+ ":bin/groups",
+ ":bin/gunzip",
+ ":bin/gzip",
+ ":bin/halt",
+ ":bin/hd",
+ ":bin/hdparm",
+ ":bin/head",
+ ":bin/hexdump",
+ ":bin/hexedit",
+ ":bin/hostid",
+ ":bin/hostname",
+ ":bin/httpd",
+ ":bin/hush",
+ ":bin/hwclock",
+ ":bin/i2cdetect",
+ ":bin/i2cdump",
+ ":bin/i2cget",
+ ":bin/i2cset",
+ ":bin/i2ctransfer",
+ ":bin/id",
+ ":bin/ifconfig",
+ ":bin/ifdown",
+ ":bin/ifenslave",
+ ":bin/ifplugd",
+ ":bin/ifup",
+ ":bin/inetd",
+ ":bin/init",
+ ":bin/insmod",
+ ":bin/install",
+ ":bin/ionice",
+ ":bin/iostat",
+ ":bin/ip",
+ ":bin/ipaddr",
+ ":bin/ipcalc",
+ ":bin/ipcrm",
+ ":bin/ipcs",
+ ":bin/iplink",
+ ":bin/ipneigh",
+ ":bin/iproute",
+ ":bin/iprule",
+ ":bin/iptunnel",
+ ":bin/kbd_mode",
+ ":bin/kill",
+ ":bin/killall",
+ ":bin/killall5",
+ ":bin/klogd",
+ ":bin/less",
+ ":bin/link",
+ ":bin/linux32",
+ ":bin/linux64",
+ ":bin/ln",
+ ":bin/loadfont",
+ ":bin/loadkmap",
+ ":bin/logger",
+ ":bin/login",
+ ":bin/logname",
+ ":bin/logread",
+ ":bin/losetup",
+ ":bin/lpd",
+ ":bin/lpq",
+ ":bin/lpr",
+ ":bin/ls",
+ ":bin/lsattr",
+ ":bin/lsmod",
+ ":bin/lsof",
+ ":bin/lspci",
+ ":bin/lsscsi",
+ ":bin/lsusb",
+ ":bin/lzcat",
+ ":bin/lzma",
+ ":bin/lzop",
+ ":bin/makedevs",
+ ":bin/makemime",
+ ":bin/man",
+ ":bin/md5sum",
+ ":bin/mdev",
+ ":bin/mesg",
+ ":bin/microcom",
+ ":bin/mim",
+ ":bin/mkdir",
+ ":bin/mkdosfs",
+ ":bin/mke2fs",
+ ":bin/mkfifo",
+ ":bin/mkfs.ext2",
+ ":bin/mkfs.minix",
+ ":bin/mkfs.vfat",
+ ":bin/mknod",
+ ":bin/mkpasswd",
+ ":bin/mkswap",
+ ":bin/mktemp",
+ ":bin/modinfo",
+ ":bin/modprobe",
+ ":bin/more",
+ ":bin/mount",
+ ":bin/mountpoint",
+ ":bin/mpstat",
+ ":bin/mt",
+ ":bin/mv",
+ ":bin/nameif",
+ ":bin/nanddump",
+ ":bin/nandwrite",
+ ":bin/nbd-client",
+ ":bin/nc",
+ ":bin/netstat",
+ ":bin/nice",
+ ":bin/nl",
+ ":bin/nmeter",
+ ":bin/nohup",
+ ":bin/nologin",
+ ":bin/nproc",
+ ":bin/nsenter",
+ ":bin/nslookup",
+ ":bin/ntpd",
+ ":bin/od",
+ ":bin/openvt",
+ ":bin/partprobe",
+ ":bin/passwd",
+ ":bin/paste",
+ ":bin/patch",
+ ":bin/pgrep",
+ ":bin/pidof",
+ ":bin/ping",
+ ":bin/ping6",
+ ":bin/pipe_progress",
+ ":bin/pivot_root",
+ ":bin/pkill",
+ ":bin/pmap",
+ ":bin/popmaildir",
+ ":bin/poweroff",
+ ":bin/powertop",
+ ":bin/printenv",
+ ":bin/printf",
+ ":bin/ps",
+ ":bin/pscan",
+ ":bin/pstree",
+ ":bin/pwd",
+ ":bin/pwdx",
+ ":bin/raidautorun",
+ ":bin/rdate",
+ ":bin/rdev",
+ ":bin/readahead",
+ ":bin/readlink",
+ ":bin/readprofile",
+ ":bin/realpath",
+ ":bin/reboot",
+ ":bin/reformime",
+ ":bin/remove-shell",
+ ":bin/renice",
+ ":bin/reset",
+ ":bin/resize",
+ ":bin/resume",
+ ":bin/rev",
+ ":bin/rm",
+ ":bin/rmdir",
+ ":bin/rmmod",
+ ":bin/route",
+ ":bin/rpm",
+ ":bin/rpm2cpio",
+ ":bin/rtcwake",
+ ":bin/run-init",
+ ":bin/run-parts",
+ ":bin/runsv",
+ ":bin/runsvdir",
+ ":bin/rx",
+ ":bin/script",
+ ":bin/scriptreplay",
+ ":bin/sed",
+ ":bin/seedrng",
+ ":bin/sendmail",
+ ":bin/seq",
+ ":bin/setarch",
+ ":bin/setconsole",
+ ":bin/setfattr",
+ ":bin/setfont",
+ ":bin/setkeycodes",
+ ":bin/setlogcons",
+ ":bin/setpriv",
+ ":bin/setserial",
+ ":bin/setsid",
+ ":bin/setuidgid",
+ ":bin/sh",
+ ":bin/sha1sum",
+ ":bin/sha3sum",
+ ":bin/sha256sum",
+ ":bin/sha512sum",
+ ":bin/showkey",
+ ":bin/shred",
+ ":bin/shuf",
+ ":bin/slattach",
+ ":bin/sleep",
+ ":bin/smemcap",
+ ":bin/softlimit",
+ ":bin/sort",
+ ":bin/split",
+ ":bin/ssl_client",
+ ":bin/start-stop-daemon",
+ ":bin/stat",
+ ":bin/strings",
+ ":bin/stty",
+ ":bin/su",
+ ":bin/sulogin",
+ ":bin/sum",
+ ":bin/sv",
+ ":bin/svc",
+ ":bin/svlogd",
+ ":bin/svok",
+ ":bin/swapoff",
+ ":bin/swapon",
+ ":bin/switch_root",
+ ":bin/sync",
+ ":bin/sysctl",
+ ":bin/syslogd",
+ ":bin/tac",
+ ":bin/tail",
+ ":bin/tar",
+ ":bin/taskset",
+ ":bin/tcpsvd",
+ ":bin/tee",
+ ":bin/telnet",
+ ":bin/telnetd",
+ ":bin/test",
+ ":bin/tftp",
+ ":bin/tftpd",
+ ":bin/time",
+ ":bin/timeout",
+ ":bin/top",
+ ":bin/touch",
+ ":bin/tr",
+ ":bin/traceroute",
+ ":bin/traceroute6",
+ ":bin/tree",
+ ":bin/true",
+ ":bin/truncate",
+ ":bin/ts",
+ ":bin/tsort",
+ ":bin/tty",
+ ":bin/ttysize",
+ ":bin/tunctl",
+ ":bin/ubiattach",
+ ":bin/ubidetach",
+ ":bin/ubimkvol",
+ ":bin/ubirename",
+ ":bin/ubirmvol",
+ ":bin/ubirsvol",
+ ":bin/ubiupdatevol",
+ ":bin/udhcpc",
+ ":bin/udhcpc6",
+ ":bin/udhcpd",
+ ":bin/udpsvd",
+ ":bin/uevent",
+ ":bin/umount",
+ ":bin/uname",
+ ":bin/unexpand",
+ ":bin/uniq",
+ ":bin/unix2dos",
+ ":bin/unlink",
+ ":bin/unlzma",
+ ":bin/unshare",
+ ":bin/unxz",
+ ":bin/unzip",
+ ":bin/uptime",
+ ":bin/usleep",
+ ":bin/uudecode",
+ ":bin/uuencode",
+ ":bin/vconfig",
+ ":bin/vi",
+ ":bin/vlock",
+ ":bin/volname",
+ ":bin/watch",
+ ":bin/watchdog",
+ ":bin/wc",
+ ":bin/wget",
+ ":bin/which",
+ ":bin/whoami",
+ ":bin/whois",
+ ":bin/xargs",
+ ":bin/xxd",
+ ":bin/xz",
+ ":bin/xzcat",
+ ":bin/yes",
+ ":bin/zcat",
+ ":bin/zcip",
+ ],
+)
diff --git a/build/toolchain/toolchain-bundle/toolchain.bzl b/build/toolchain/toolchain-bundle/toolchain.bzl
new file mode 100644
index 0000000..a2b7df2
--- /dev/null
+++ b/build/toolchain/toolchain-bundle/toolchain.bzl
@@ -0,0 +1,188 @@
+load("@rules_foreign_cc//toolchains/native_tools:native_tools_toolchain.bzl", "native_tool_toolchain")
+
+# Copied from bazel-contrib/rules_foreign_cc licensed under Apache-2.0
+def _current_toolchain_impl(ctx):
+ toolchain = ctx.toolchains[ctx.attr._toolchain]
+
+ if toolchain.data.target:
+ return [
+ toolchain,
+ platform_common.TemplateVariableInfo(toolchain.data.env),
+ DefaultInfo(
+ files = toolchain.data.target.files,
+ runfiles = toolchain.data.target.default_runfiles,
+ ),
+ ]
+ return [
+ toolchain,
+ platform_common.TemplateVariableInfo(toolchain.data.env),
+ DefaultInfo(),
+ ]
+
+def current_toolchain(name):
+ return rule(
+ implementation = _current_toolchain_impl,
+ attrs = {
+ "_toolchain": attr.string(default = "//build/toolchain/toolchain-bundle:%s_toolchain" % name),
+ },
+ toolchains = [
+ "//build/toolchain/toolchain-bundle:%s_toolchain" % name,
+ ],
+ )
+
+def toolchain_for(name, config):
+ native.toolchain_type(
+ name = "%s_toolchain" % name,
+ )
+
+ config.current_toolchain_func(
+ name = name,
+ )
+
+ native.toolchain(
+ name = "%s_linux_x86_64_toolchain" % name,
+ exec_compatible_with = [
+ "@platforms//os:linux",
+ "@platforms//cpu:x86_64",
+ ],
+ toolchain = ":%s_linux_x86_64" % name,
+ toolchain_type = ":%s_toolchain" % name,
+ )
+
+ native.toolchain(
+ name = "%s_linux_aarch64_toolchain" % name,
+ exec_compatible_with = [
+ "@platforms//os:linux",
+ "@platforms//cpu:aarch64",
+ ],
+ toolchain = ":%s_linux_aarch64" % name,
+ toolchain_type = ":%s_toolchain" % name,
+ )
+
+ native_tool_toolchain(
+ name = "%s_linux_aarch64" % name,
+ env = {
+ name.upper(): "$(execpath @toolchain-bundle-aarch64-unknown-linux-musl//:%s)" % config.target,
+ },
+ target = "@toolchain-bundle-aarch64-unknown-linux-musl//:%s" % config.target,
+ )
+
+ native_tool_toolchain(
+ name = "%s_linux_x86_64" % name,
+ env = {
+ name.upper(): "$(execpath @toolchain-bundle-x86_64-unknown-linux-musl//:%s)" % config.target,
+ },
+ target = "@toolchain-bundle-x86_64-unknown-linux-musl//:%s" % config.target,
+ )
+
+current_qemu_img_toolchain = current_toolchain("qemu-img")
+current_qemu_kvm_toolchain = current_toolchain("qemu-kvm")
+current_make_toolchain = current_toolchain("make")
+current_strace_toolchain = current_toolchain("strace")
+current_nasm_toolchain = current_toolchain("nasm")
+current_bison_toolchain = current_toolchain("bison")
+current_flex_toolchain = current_toolchain("flex")
+current_m4_toolchain = current_toolchain("m4")
+current_bc_toolchain = current_toolchain("bc")
+current_busybox_toolchain = current_toolchain("busybox")
+current_diff_toolchain = current_toolchain("diff")
+current_perl_toolchain = current_toolchain("perl")
+current_iasl_toolchain = current_toolchain("iasl")
+current_lz4_toolchain = current_toolchain("lz4")
+
+TOOLCHAINS = {
+ "qemu-img": struct(
+ target = "bin/qemu-img",
+ current_toolchain_func = current_qemu_img_toolchain,
+ ),
+ "qemu-kvm": struct(
+ target = "qemu-kvm",
+ current_toolchain_func = current_qemu_kvm_toolchain,
+ ),
+ "make": struct(
+ target = "bin/make",
+ current_toolchain_func = current_make_toolchain,
+ ),
+ "strace": struct(
+ target = "bin/strace",
+ current_toolchain_func = current_strace_toolchain,
+ ),
+ "nasm": struct(
+ target = "bin/nasm",
+ current_toolchain_func = current_nasm_toolchain,
+ ),
+ "bison": struct(
+ target = "bison",
+ current_toolchain_func = current_bison_toolchain,
+ ),
+ "flex": struct(
+ target = "bin/flex",
+ current_toolchain_func = current_flex_toolchain,
+ ),
+ "m4": struct(
+ target = "bin/m4",
+ current_toolchain_func = current_m4_toolchain,
+ ),
+ "bc": struct(
+ target = "bin/bc",
+ current_toolchain_func = current_bc_toolchain,
+ ),
+ "diff": struct(
+ target = "bin/diff",
+ current_toolchain_func = current_diff_toolchain,
+ ),
+ "iasl": struct(
+ target = "bin/iasl",
+ current_toolchain_func = current_iasl_toolchain,
+ ),
+ "busybox": struct(
+ target = "busybox",
+ current_toolchain_func = current_busybox_toolchain,
+ ),
+ "perl": struct(
+ target = "perl",
+ current_toolchain_func = current_perl_toolchain,
+ ),
+ "lz4": struct(
+ target = "bin/lz4",
+ current_toolchain_func = current_lz4_toolchain,
+ ),
+}
+
+def build_toolchain_env(ctx, toolchains):
+ toolchain_info = [ctx.toolchains[t] for t in toolchains]
+ env = dict([(k, v) for t in toolchain_info for k, v in t.data.env.items()])
+ env = env | {"TOOL_PATH": ":".join([t.data.target.files.to_list()[0].path.rsplit("/", 1)[0] for t in toolchain_info])}
+
+ inputs = depset(transitive = [
+ depset(transitive = [t.data.target.files, t.data.target.default_runfiles.files])
+ for t in toolchain_info
+ ])
+
+ return env, inputs
+
+TOOLCHAIN_ENV_SETUP = """
+set -e
+
+# Iterate over all environment variables and expand paths that are
+# either external or bazel-out.
+for name in $(env | cut -d= -f1); do
+ val="${!name}"
+ [[ "$val" != *external/* && "$val" != *bazel-out/* ]] && continue # Quick skip
+
+ sep=' '; [[ $name == "TOOL_PATH" ]] && sep=':' # Set separator: : for PATH, space otherwise
+ IFS=$sep read -r -a items <<< "$val" # Split value into array using correct separator
+
+ for i in "${!items[@]}"; do
+ key="${items[i]%%=*}"; v="${items[i]#*=}" # Handle 'key=val' and standalone paths
+ if [[ ( $v == external/* || $v == bazel-out/* ) && -e "$v" ]]; then
+ [ "$key" = "$v" ] && items[i]=$(realpath -s "$v") || items[i]="$key=$(realpath -s "$v")"
+ fi
+ done
+ export "$name=$(IFS=$sep; echo "${items[*]}")" # Re-export with correct separator
+done
+
+# Add our now expanded TOOL_PATH to PATH
+PATH="$PATH:$TOOL_PATH"
+
+"""