PoC: zig based cross-compiling

I made .nix file that allows you to cross-compile packages in nixpkgs using zig.
This is useful as zig doesn’t need heavy bootsrapping, and can compile to various targets out of the box.
I’m using this personally right now, there’s few issues that are mostly upstream bugs however.
I might turn this into more fleshed out project that provides also overlay and support scripts for fetching nix binary releases.
(I was aware of zicross, but it does not integrate into stdenv as I do here)

Example usage:

{ pkgs ? import <nixpkgs> {} }: 
let
   cross = import ./zig-stdenv.nix { 
      inherit pkgs; 
      target = "aarch64-unknown-linux-musl"; 
   };
in cross.pkgs.bzip2;

EDIT: Project here now GitHub - Cloudef/nix-zig-stdenv: cross-compile nixpkgs with zig

12 Likes

Wait, zig has a C/C++ compiler?

Yes, `zig cc`: a Powerful Drop-In Replacement for GCC/Clang - Andrew Kelley

2 Likes

Can you spell out some more your gauging of the benefits of “doesn’t need heavy boostrapping”? This is an interesting lead, but I just have too little context at this moment to really kick off my fantasy.

Moved the project from gist to own git repo now

There’s github action that updates the zig-binaries.json automatically. I also want to automate automatic tests that will catch the most broken targets and track them. I think this would help upstream as well.

This is what current master produces for “iniparser”, I chose this package for initial testing as it does not use autotools nor autotools deps so it doesn’t have to spend ages checking for the most useless things before actually compiling some code.

/nix/store/mskf7j2aawchs3calx021fv2lviqgzw0-iniparser-aarch64-unknown-linux-gnu-4.1
/nix/store/00nl3bg3lqdxx2d3yx2q8r1h7kci7kd6-iniparser-aarch64-unknown-linux-musl-4.1
/nix/store/ky0nfpd4xrshjmzs4vp08z09wq2qbwqi-iniparser-aarch64-w64-mingw32-4.1
/nix/store/4yz501sd2m99csjybvdnxvzi0kvj19pc-iniparser-arm-unknown-linux-musleabi-4.1
/nix/store/l3858z2jaggi7jhjzvxvgnvz2lm13h8x-iniparser-arm-unknown-linux-musleabihf-4.1
/nix/store/ar5747dqg27caq2hqgfppplwmam32dhr-iniparser-mips-unknown-linux-gnueabi-4.1
/nix/store/2z4bsy79fjimyxywl7cgdf729g31aph7-iniparser-mips-unknown-linux-gnueabihf-4.1
/nix/store/0ghjjpmdgw5a9lkn59phm12hmljzvkg8-iniparser-mips-unknown-linux-musl-4.1
/nix/store/q7csnhwd2g5bjzlz6ny55dl6z96snywk-iniparser-mipsel-unknown-linux-gnueabi-4.1
/nix/store/3ibxkhrh7dhf47cqva9mips891jdr0sx-iniparser-mipsel-unknown-linux-gnueabihf-4.1
/nix/store/mgvy8b6bj2blmh17jvbli57da1zdl8j9-iniparser-mipsel-unknown-linux-musl-4.1
/nix/store/z12lgwsri3jci3scbikws2fzcrq98mcs-iniparser-powerpc-unknown-linux-gnueabi-4.1
/nix/store/a09qh7g2a1s6hlxwdcpggdnh5q50ydsy-iniparser-powerpc-unknown-linux-gnueabihf-4.1
/nix/store/f21ah2l1m3d8ag9lwx77nqahfady63as-iniparser-powerpc-unknown-linux-musl-4.1
/nix/store/s55n0jnaq5b3niclwcn3sqx5gbbd96bs-iniparser-powerpc64-unknown-linux-gnuabi64-4.1
/nix/store/2xc9c241irfscjfga3zw4yp42mcvq9l8-iniparser-powerpc64-unknown-linux-muslabi64-4.1
/nix/store/8ix8gmlpyhhfxnq2kjjksjy66qs34djz-iniparser-riscv64-unknown-linux-musl-4.1
/nix/store/fsc1rpx358xq62iw5zpqxd8zl2k476q5-iniparser-static-wasm32-unknown-wasi-4.1
/nix/store/34vm2pmppl3ggqhb6s0h1318s6xls5xc-iniparser-4.1
/nix/store/97ysy0pzn5sl336g8895mchddqwjpdi0-iniparser-x86_64-unknown-linux-musl-4.1
/nix/store/3pxyq6nwyxfcww9c411j8dggxd5xl9pc-iniparser-x86_64-w64-mingw32-4.1

In addition I’m using this to cross-compile rust code to aarch64 AWS lambdas as static musl binaries.

@blaggacao
The idea is that zig provides C/C++ compiler for major platforms that can cross-compile to different targets out of the box. This means you don’t have to bootstrap every combination of cross-compiler toolchains (binutils, libc, libstdc++, etc…) from scratch each time, which can take quite a bit of time. It might save time for people, or perhaps make nix cross-compilation better in future regards of shared binary cache.

1 Like

oh, I see. How may (or may not?) zig’s cross-compiler shorten the path to full boostrapping? Or is that still a few layers down?

If you read the blog post linked above, you’ll know that it’s built on top of clang.

It looks useful for cross-compilation as it does many things better than other compiler front-ends in this regard but perhaps not too interesting for bootstrapping Nixpkgs as you’d still need clang to build this and at that point we might as well bootstrap on clang.

Got ya! Thank’s for the high level overview. I’m not too familiar with the intricacies.

Major milestone, deno / rusty_v8 / v8 builds on linux. Though arguably with help of binfmt and qemu-static-user for those few pesky binaries the build system wants to execute. Needlessly said, gn is not my favorite build system :slight_smile:

Anyhow, there’s some promise here. However zig is still fresh so there’s bunch of stuff that needs to be fixed upstream.

/nix/store/zqik2z7dxn57z66kqf0qymjbfb8smmlz-hello-world-0.1.0-aarch64-unknown-linux-musl/bin/lambda-hello-world: ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV), statically linked, not stripped
[130] void@voidlinux> ./result/bin/lambda-hello-world   
v8 version: 10.8.168.4
thread 'main' panicked at 'Missing AWS_LAMBDA_FUNCTION_NAME env var: NotPresent', /sources/lambda_runtime-0.7.0/src/lib.rs:62:65
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
qemu: uncaught target signal 6 (Aborted) - core dumped

There is now basic framework for testing builds:

While this will be important for this project for various reasons such as automatic metadata generation, automatic github workflow generation, and regression testing, it may provide good resource for zig developers as well, so I might talk to them later.

I made a sketchpad folder for building various things nix-zig-stdenv/default.nix at 2fd28e7983baddc4728a9f3de3b46da29e67a24e · Cloudef/nix-zig-stdenv · GitHub one of the problematic packages to build is rusty_v8, while it’s still not clean, this simplifies the process quite a bit.

Context in this thread: Release musl builds · Issue #3711 · denoland/deno · GitHub

Hosted by Flying Circus.