mirror of
https://github.com/ruuda/rcl.git
synced 2025-12-23 04:47:19 +00:00
This is a squash and rebase of a lot of messy work over the past few evenings. In the end the diff doesn't look so bad, but the path to get there ... == THE GOAL == I want to publish the Python module to Pypi, and include a wheel. I want to automate building it with Nix, so that it's a *single* step, and it can run on every commit. Building a wheel that is widely compatible, is somewhat challenging. One way to achieve it is to build in a container, using an image of some ancient Linux distro. I don't want Docker in my build process, I want a single command that builds anything and that always works. Fortunately, when using Zig as the linker, we can build a manylinux compatible wheel, and Maturin supports that. So we want to call Maturin from inside Nix to build the wheel, that's the goal. == CONSTRAINTS == The Nixpkgs snapshot I was using shipped Maturin 1.1. Maturin versions before 1.9.2 contain a bug where the set the author metadata incorrectly. So I need 1.9.2. We can't *just* override it though, because Maturin 1.9.2 depends on a library that only compiles with Rust 1.73.0. So we need to update Rust too. Now we have two choices: update the Nixpkgs snapshot to one with Rust 1.73 or later, or take Rust from the binary overlay. I explored both, backtracked, backtracked again, and reverted, but in the end, using the binary was infeasible. Why? Because the coverage build needs LLVM tools that we take from Nixpkgs, and the version needs to be compatible. So we bump the Rust toolchain, see below for the version rationale. It may be possible to get LLVM tools from the binaries overlay, but the component that is shipped by rustup does not include the coverage binaries, and the outlook started looking more and more bleak, taking them from Nixpkgs just works, and though it adds some constraints, it sidesteps many problems. Another place where we take tools from Nixpkgs, is the WASM build. This requires a nightly compiler. That compiler needs to be recent enough to be compatible, but because we include rust-src dependencies in our lockfile to be able to build that component in Nix, the dependencies can't be *that* recent that they require Rust Edition 2021, because that is not supported by Rust 1.75. So finding the right nightly was a challenge too. The nightly that coincides with 1.75 is already too new, but one 6 weeks prior worked. Wthe new Nixpkgs snapshot, aside from the WASM tools, we also get a new version of Tree-sitter. Which of course broke things, but they were relatively easy to repair. There are also additional warnings now, but those can be fixed later. == RUST VERSION == Pick Rust 1.75, because that is the version that is currently shipped in Ubuntu 22.04 Jammy, which is the oldest supported Ubuntu LTS at this time. I would like to consider Debian oldstable (Bookworm at this time) as well, but it ships rustc 1.63, which is already older than the version RCL was using anyway. Debian stable (Trixie) ships 1.85 at this time. So I think 1.75 is a safe bet for wide compatibility, without being ancient. == ZIG CACHE DIR == I don't want Docker in my build process. Fortunately, Maturin features this --zig mode to build a manylinux wheel. Calling it from Nix turned out to be ... possible, but not trivial. I spent about two hours debugging an AccessDenied error, which turned out to be due to [1]. When you read that one, in hindsight it makes sense, but the lengths I had to go through to figure out *what* was printing AccessDenied and why ... [1]: github ziglang zig issue 6810 == NIXPKGS & CARGO AUDITABLE == In the process of sorting this out, I first got things working with the older Nixpkgs snapshot, and the Maturin and Zig in there. But when I needed a newer version of Maturin, things broke. Maturin's manylinux wheel build with --zig worked in the older version of Nixpkgs, but then in a newer release it started using a linker flag (--undefined) that Zig did not understand. After several more hours of debugging, I learned that that flag is injected by cargo-auditable [2], which despite not being used by Maturin or cargo-zigbuild, is being used because Nixpkgs silently replaces cargo with cargo-auditable by default. After learning that, it was easy enough to turn off. Also just one line, but the effort to discover that one line ... [2]: github rust-cross cargo-zigbuild issue 162 == WASM == At some point in the process, I was using a later nightly to build the WASM binary, and I needed to add the --enable-bulk-memory to wasm-opt. == MATURIN 1.9.3 == With Maturin updated, the author metadata is fixed, but it introduced a new regression: recent versions stop tagging the manylinux wheel properly. It would get tagged as linux_x86_64, rather than the right manylinux tags. Fortunately, the Python 'auditwheel' package can fix this. So I added that one to the build, at that point still from a more recent Nixpkgs snapshot. Then I pinned Nixpkgs to one with Rust 1.75, which downgraded auditwheel, and that broke the command line: the newer version automatically detects compatibility, but the older one needs an explicit target with --plat. That could be fixed, but then the older version would still build wheels that contained an unnecessary (and empty) lib dir, so just pin it to a newer version too. == VERSION BUMPS SUMMARY == * Rust 1.70.0 -> 1.75.0. * Nixpkgs goes along to one with Rust 1.75.0. * Rust nightly to 2023-11-09, and Cargo.lock to update the dependencies of rust-std along with it. * Wasm-bindgen 0.2.84 -> 0.2.89 due to the Nixpkgs bump. * Tree-sitter update due to the Nixpkgs bump. == RESULT == With all of this in place, we can now nix build .#pyrcl-wheel, and we get a portable manylinux wheel that can be used directly with uv, and can be uploaded to Pypi!
48 lines
1.1 KiB
JSON
48 lines
1.1 KiB
JSON
{
|
|
"nodes": {
|
|
"nixpkgs": {
|
|
"locked": {
|
|
"lastModified": 1708815994,
|
|
"narHash": "sha256-hL7N/ut2Xu0NaDxDMsw2HagAjgDskToGiyZOWriiLYM=",
|
|
"owner": "NixOS",
|
|
"repo": "nixpkgs",
|
|
"rev": "9a9dae8f6319600fa9aebde37f340975cab4b8c0",
|
|
"type": "github"
|
|
},
|
|
"original": {
|
|
"id": "nixpkgs",
|
|
"rev": "9a9dae8f6319600fa9aebde37f340975cab4b8c0",
|
|
"type": "indirect"
|
|
}
|
|
},
|
|
"root": {
|
|
"inputs": {
|
|
"nixpkgs": "nixpkgs",
|
|
"rust-overlay": "rust-overlay"
|
|
}
|
|
},
|
|
"rust-overlay": {
|
|
"inputs": {
|
|
"nixpkgs": [
|
|
"nixpkgs"
|
|
]
|
|
},
|
|
"locked": {
|
|
"lastModified": 1735525800,
|
|
"narHash": "sha256-pcN8LAL021zdC99a9F7iEiFCI1wmrE4DpIYUgKpB/jY=",
|
|
"owner": "oxalica",
|
|
"repo": "rust-overlay",
|
|
"rev": "10faa81b4c0135a04716cbd1649260d82b2890cd",
|
|
"type": "github"
|
|
},
|
|
"original": {
|
|
"owner": "oxalica",
|
|
"repo": "rust-overlay",
|
|
"rev": "10faa81b4c0135a04716cbd1649260d82b2890cd",
|
|
"type": "github"
|
|
}
|
|
}
|
|
},
|
|
"root": "root",
|
|
"version": 7
|
|
}
|