From f7cc4fb3bb8ec1bfc39ccb89e770c809d5708343 Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Wed, 24 Jan 2024 22:24:34 -0800 Subject: [PATCH 01/18] state artifacts' targets and rename artifacts This will make it more obvious what's what and be more internally consistent. --- .gitlab-ci.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 48fe6244..53fd73f9 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -34,19 +34,19 @@ ci: - target - .gitlab-ci.d -docker: +oci-image:x86_64-unknown-linux-gnu: stage: artifacts image: nixos/nix:2.19.2 script: - nix build .#oci-image # Make the output less difficult to find - - cp result docker-image.tar.gz + - cp result oci-image.tar.gz artifacts: paths: - - docker-image.tar.gz + - oci-image.tar.gz -debian: +debian:x86_64-unknown-linux-gnu: stage: artifacts image: rust:1.70.0 script: @@ -55,10 +55,10 @@ debian: - cargo deb # Make the output less difficult to find - - mv target/debian/*.deb . + - mv target/debian/*.deb conduit.deb artifacts: paths: - - "*.deb" + - conduit.deb cache: key: debian paths: From bd2b146d5da633eb3ec80033a317feea87d23c64 Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Wed, 24 Jan 2024 22:16:29 -0800 Subject: [PATCH 02/18] add crane binary cache This way we don't need to build e.g. crane-utils every time. --- .gitlab-ci.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 53fd73f9..deacb811 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -10,6 +10,10 @@ before_script: # Enable nix-command and flakes - if command -v nix > /dev/null; then echo "experimental-features = nix-command flakes" >> /etc/nix/nix.conf; fi + # Add crane binary cache + - if command -v nix > /dev/null; then echo "extra-substituters = https://crane.cachix.org" >> /etc/nix/nix.conf; fi + - if command -v nix > /dev/null; then echo "extra-trusted-public-keys = crane.cachix.org-1:8Scfpmn9w+hGdXH/Q9tTLiYAE/2dnJYRJP7kl80GuRk=" >> /etc/nix/nix.conf; fi + # Add nix-community binary cache - if command -v nix > /dev/null; then echo "extra-substituters = https://nix-community.cachix.org" >> /etc/nix/nix.conf; fi - if command -v nix > /dev/null; then echo "extra-trusted-public-keys = nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs=" >> /etc/nix/nix.conf; fi From 6ae776218cc2da4e46fb587bd08b5164b24c41ce Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Wed, 24 Jan 2024 22:20:48 -0800 Subject: [PATCH 03/18] add our own binary cache The machine I'm hosting this on doesn't have incredible upload speeds but it should be good enough? --- .gitlab-ci.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index deacb811..746641c8 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -10,6 +10,10 @@ before_script: # Enable nix-command and flakes - if command -v nix > /dev/null; then echo "experimental-features = nix-command flakes" >> /etc/nix/nix.conf; fi + # Add our own binary cache + - if command -v nix > /dev/null; then echo "extra-substituters = https://nix.computer.surgery/conduit" >> /etc/nix/nix.conf; fi + - if command -v nix > /dev/null; then echo "extra-trusted-public-keys = conduit:ZGAf6P6LhNvnoJJ3Me3PRg7tlLSrPxcQ2RiE5LIppjo=" >> /etc/nix/nix.conf; fi + # Add crane binary cache - if command -v nix > /dev/null; then echo "extra-substituters = https://crane.cachix.org" >> /etc/nix/nix.conf; fi - if command -v nix > /dev/null; then echo "extra-trusted-public-keys = crane.cachix.org-1:8Scfpmn9w+hGdXH/Q9tTLiYAE/2dnJYRJP7kl80GuRk=" >> /etc/nix/nix.conf; fi From bdc46f63929f19ddc124f0ed4a78885b1514343c Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Thu, 25 Jan 2024 11:34:46 -0800 Subject: [PATCH 04/18] add script to build and push to binary cache This is even useful for local development, as you can pre-populate the binary cache before running CI (assuming you have the token). Also, it being in a script makes it easier to test. We've added attic as a flake input even though the flake itself doesn't use it so that we can use `--inputs-from .` in Nix commands to reference a locked version of attic. This helps with reproducibility and caching, and to makes it easy to update attic because it's part of the normal flake lifecycle. --- .envrc | 2 + flake.lock | 114 +++++++++++++++++++++++++++++++++++++++++++++++++++-- flake.nix | 2 + 3 files changed, 115 insertions(+), 3 deletions(-) diff --git a/.envrc b/.envrc index b9238c3b..403a9bdf 100644 --- a/.envrc +++ b/.envrc @@ -1,3 +1,5 @@ #!/usr/bin/env bash use flake + +PATH_add bin diff --git a/flake.lock b/flake.lock index 128539bb..acad901c 100644 --- a/flake.lock +++ b/flake.lock @@ -1,6 +1,50 @@ { "nodes": { + "attic": { + "inputs": { + "crane": "crane", + "flake-compat": "flake-compat", + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs", + "nixpkgs-stable": "nixpkgs-stable" + }, + "locked": { + "lastModified": 1705617092, + "narHash": "sha256-n9PK4O4X4S1JkwpkMuYm1wHZYJzRqif8g3RuVIPD+rY=", + "owner": "zhaofengli", + "repo": "attic", + "rev": "fbe252a5c21febbe920c025560cbd63b20e24f3b", + "type": "github" + }, + "original": { + "owner": "zhaofengli", + "ref": "main", + "repo": "attic", + "type": "github" + } + }, "crane": { + "inputs": { + "nixpkgs": [ + "attic", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1702918879, + "narHash": "sha256-tWJqzajIvYcaRWxn+cLUB9L9Pv4dQ3Bfit/YjU5ze3g=", + "owner": "ipetkov", + "repo": "crane", + "rev": "7195c00c272fdd92fc74e7d5a0a2844b9fadb2fb", + "type": "github" + }, + "original": { + "owner": "ipetkov", + "repo": "crane", + "type": "github" + } + }, + "crane_2": { "inputs": { "nixpkgs": [ "nixpkgs" @@ -41,7 +85,38 @@ "type": "github" } }, + "flake-compat": { + "flake": false, + "locked": { + "lastModified": 1673956053, + "narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, "flake-utils": { + "locked": { + "lastModified": 1667395993, + "narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_2": { "inputs": { "systems": "systems" }, @@ -75,6 +150,38 @@ } }, "nixpkgs": { + "locked": { + "lastModified": 1702539185, + "narHash": "sha256-KnIRG5NMdLIpEkZTnN5zovNYc0hhXjAgv6pfd5Z4c7U=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "aa9d4729cbc99dabacb50e3994dcefb3ea0f7447", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-stable": { + "locked": { + "lastModified": 1702780907, + "narHash": "sha256-blbrBBXjjZt6OKTcYX1jpe9SRof2P9ZYWPzq22tzXAA=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "1e2e384c5b7c50dbf8e9c441a9e58d85f408b01f", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-23.11", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_2": { "locked": { "lastModified": 1705496572, "narHash": "sha256-rPIe9G5EBLXdBdn9ilGc0nq082lzQd0xGGe092R/5QE=", @@ -92,11 +199,12 @@ }, "root": { "inputs": { - "crane": "crane", + "attic": "attic", + "crane": "crane_2", "fenix": "fenix", - "flake-utils": "flake-utils", + "flake-utils": "flake-utils_2", "nix-filter": "nix-filter", - "nixpkgs": "nixpkgs" + "nixpkgs": "nixpkgs_2" } }, "rust-analyzer-src": { diff --git a/flake.nix b/flake.nix index b4a32d0a..51148bad 100644 --- a/flake.nix +++ b/flake.nix @@ -12,6 +12,7 @@ url = "github:ipetkov/crane"; inputs.nixpkgs.follows = "nixpkgs"; }; + attic.url = "github:zhaofengli/attic?ref=main"; }; outputs = @@ -22,6 +23,7 @@ , fenix , crane + , ... }: flake-utils.lib.eachDefaultSystem (system: let pkgs = nixpkgs.legacyPackages.${system}; From 5cc53c9e14ef5319f2dd8f88aa58d6e966cfdb20 Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Thu, 25 Jan 2024 11:37:35 -0800 Subject: [PATCH 05/18] push oci image and x86_64-*-gnu build to bin cache This will allow most Nix users to use the `default` package and without having to build from source. And also allows any weirdos to get the OCI image from the Nix binary cache if they want. No idea why that would be desireable though lol --- .gitlab-ci.yml | 8 +++++++- bin/nix-build-and-cache | 31 +++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) create mode 100755 bin/nix-build-and-cache diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 746641c8..199429a5 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -46,7 +46,13 @@ oci-image:x86_64-unknown-linux-gnu: stage: artifacts image: nixos/nix:2.19.2 script: - - nix build .#oci-image + # Push artifacts and build requirements to binary cache + # + # Since the OCI image package is based on the binary package, this has the + # fun side effect of uploading the normal binary too. Conduit users who are + # deploying with Nix can leverage this fact by adding our binary cache to + # their systems. + - ./bin/nix-build-and-cache .#oci-image # Make the output less difficult to find - cp result oci-image.tar.gz diff --git a/bin/nix-build-and-cache b/bin/nix-build-and-cache new file mode 100755 index 00000000..b37ebd85 --- /dev/null +++ b/bin/nix-build-and-cache @@ -0,0 +1,31 @@ +#!/usr/bin/env bash + +set -euo pipefail + +# The first argument must be the desired installable +INSTALLABLE="$1" + +# Build the installable and forward any other arguments too +nix build "$@" + +if [ ! -z ${ATTIC_TOKEN+x} ]; then + +nix run --inputs-from . attic -- login \ + conduit \ + https://nix.computer.surgery/conduit \ + "$ATTIC_TOKEN" + + push_args=( + # Attic and its build dependencies + "$(nix path-info --inputs-from . attic)" + "$(nix path-info --inputs-from . attic --derivation)" + + # The target installable and its build dependencies + "$(nix path-info "$INSTALLABLE" --derivation)" + "$(nix path-info "$INSTALLABLE")" + ) + + nix run --inputs-from . attic -- push conduit "${push_args[@]}" +else + echo "\$ATTIC_TOKEN is unset, skipping uploading to the binary cache" +fi From 249fc7769d14e4b4eb9d7f6abc645972c4fc27b8 Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Mon, 22 Jan 2024 22:24:04 -0800 Subject: [PATCH 06/18] don't bother with mold For now, at least. I suspect it will make cross compilation more difficult. --- flake.nix | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/flake.nix b/flake.nix index 51148bad..d4be7d9e 100644 --- a/flake.nix +++ b/flake.nix @@ -28,12 +28,6 @@ let pkgs = nixpkgs.legacyPackages.${system}; - # Use mold on Linux - stdenv = if pkgs.stdenv.isLinux then - pkgs.stdenvAdapters.useMoldLinker pkgs.stdenv - else - pkgs.stdenv; - # Nix-accessible `Cargo.toml` cargoToml = builtins.fromTOML (builtins.readFile ./Cargo.toml); @@ -91,8 +85,7 @@ inherit env - nativeBuildInputs - stdenv; + nativeBuildInputs; meta.mainProgram = cargoToml.package.name; }; @@ -117,7 +110,7 @@ }; }; - devShells.default = (pkgs.mkShell.override { inherit stdenv; }) { + devShells.default = pkgs.mkShell { env = env // { # Rust Analyzer needs to be able to find the path to default crate # sources, and it can read this environment variable to do so. The From 9cef03127bcc0e076286721f6f7d5564e0af36c8 Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Tue, 23 Jan 2024 10:45:02 -0800 Subject: [PATCH 07/18] remove `with` for `nativeBuildInputs` It's going to get more involved and that `with` was too specific. --- flake.nix | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flake.nix b/flake.nix index d4be7d9e..15538efd 100644 --- a/flake.nix +++ b/flake.nix @@ -60,9 +60,9 @@ builder = ((crane.mkLib pkgs).overrideToolchain buildToolchain).buildPackage; - nativeBuildInputs = (with pkgs.rustPlatform; [ - bindgenHook - ]); + nativeBuildInputs = [ + pkgs.rustPlatform.bindgenHook + ]; env = { ROCKSDB_INCLUDE_DIR = "${pkgs.rocksdb}/include"; From cf4015b8307249ccf3f7c036306a1dc69f0af795 Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Mon, 22 Jan 2024 22:25:08 -0800 Subject: [PATCH 08/18] rename pkgs to pkgsHost This will make organizing cross compilation easier. --- flake.nix | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/flake.nix b/flake.nix index 15538efd..039bf0b5 100644 --- a/flake.nix +++ b/flake.nix @@ -26,7 +26,7 @@ , ... }: flake-utils.lib.eachDefaultSystem (system: let - pkgs = nixpkgs.legacyPackages.${system}; + pkgsHost = nixpkgs.legacyPackages.${system}; # Nix-accessible `Cargo.toml` cargoToml = builtins.fromTOML (builtins.readFile ./Cargo.toml); @@ -58,15 +58,15 @@ ]); builder = - ((crane.mkLib pkgs).overrideToolchain buildToolchain).buildPackage; + ((crane.mkLib pkgsHost).overrideToolchain buildToolchain).buildPackage; nativeBuildInputs = [ - pkgs.rustPlatform.bindgenHook + pkgsHost.rustPlatform.bindgenHook ]; env = { - ROCKSDB_INCLUDE_DIR = "${pkgs.rocksdb}/include"; - ROCKSDB_LIB_DIR = "${pkgs.rocksdb}/lib"; + ROCKSDB_INCLUDE_DIR = "${pkgsHost.rocksdb}/include"; + ROCKSDB_LIB_DIR = "${pkgsHost.rocksdb}/lib"; }; in { @@ -94,23 +94,23 @@ let package = self.packages.${system}.default; in - pkgs.dockerTools.buildImage { + pkgsHost.dockerTools.buildImage { name = package.pname; tag = "latest"; config = { # Use the `tini` init system so that signals (e.g. ctrl+c/SIGINT) are # handled as expected Entrypoint = [ - "${pkgs.lib.getExe' pkgs.tini "tini"}" + "${pkgsHost.lib.getExe' pkgsHost.tini "tini"}" "--" ]; Cmd = [ - "${pkgs.lib.getExe package}" + "${pkgsHost.lib.getExe package}" ]; }; }; - devShells.default = pkgs.mkShell { + devShells.default = pkgsHost.mkShell { env = env // { # Rust Analyzer needs to be able to find the path to default crate # sources, and it can read this environment variable to do so. The @@ -121,7 +121,7 @@ # Development tools nativeBuildInputs = nativeBuildInputs ++ [ devToolchain - ] ++ (with pkgs; [ + ] ++ (with pkgsHost; [ engage ]); }; From 692a31620d747a9a640cb3464221c3024c546e09 Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Mon, 22 Jan 2024 22:26:16 -0800 Subject: [PATCH 09/18] make let bindings take pkgs as an argument Again, will make cross compilation easier to set up. --- flake.nix | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/flake.nix b/flake.nix index 039bf0b5..76f8bb25 100644 --- a/flake.nix +++ b/flake.nix @@ -57,20 +57,20 @@ fenix.packages.${system}.latest.rustfmt ]); - builder = - ((crane.mkLib pkgsHost).overrideToolchain buildToolchain).buildPackage; + builder = pkgs: + ((crane.mkLib pkgs).overrideToolchain buildToolchain).buildPackage; - nativeBuildInputs = [ - pkgsHost.rustPlatform.bindgenHook + nativeBuildInputs = pkgs: [ + pkgs.rustPlatform.bindgenHook ]; - env = { - ROCKSDB_INCLUDE_DIR = "${pkgsHost.rocksdb}/include"; - ROCKSDB_LIB_DIR = "${pkgsHost.rocksdb}/lib"; + env = pkgs: { + ROCKSDB_INCLUDE_DIR = "${pkgs.rocksdb}/include"; + ROCKSDB_LIB_DIR = "${pkgs.rocksdb}/lib"; }; in { - packages.default = builder { + packages.default = builder pkgsHost { src = nix-filter { root = ./.; include = [ @@ -83,9 +83,8 @@ # This is redundant with CI doCheck = false; - inherit - env - nativeBuildInputs; + env = env pkgsHost; + nativeBuildInputs = nativeBuildInputs pkgsHost; meta.mainProgram = cargoToml.package.name; }; @@ -111,7 +110,7 @@ }; devShells.default = pkgsHost.mkShell { - env = env // { + env = env pkgsHost // { # Rust Analyzer needs to be able to find the path to default crate # sources, and it can read this environment variable to do so. The # `rust-src` component is required in order for this to work. @@ -119,7 +118,7 @@ }; # Development tools - nativeBuildInputs = nativeBuildInputs ++ [ + nativeBuildInputs = nativeBuildInputs pkgsHost ++ [ devToolchain ] ++ (with pkgsHost; [ engage From 52954f7a11e795211bbecc54df456724773251b6 Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Mon, 22 Jan 2024 22:48:58 -0800 Subject: [PATCH 10/18] use fromToolchainFile I *think* this will make it easier to pull in extra rustc targets. --- .gitlab-ci.yml | 1 + Cargo.toml | 7 +------ flake.nix | 36 ++++++++++++------------------------ rust-toolchain.toml | 17 +++++++++++++++++ 4 files changed, 31 insertions(+), 30 deletions(-) create mode 100644 rust-toolchain.toml diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 199429a5..1f6dab3a 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -62,6 +62,7 @@ oci-image:x86_64-unknown-linux-gnu: debian:x86_64-unknown-linux-gnu: stage: artifacts + # See also `rust-toolchain.toml` image: rust:1.70.0 script: - apt-get update && apt-get install -y --no-install-recommends libclang-dev diff --git a/Cargo.toml b/Cargo.toml index a35cf233..40919599 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,12 +9,7 @@ readme = "README.md" version = "0.7.0-alpha" edition = "2021" -# When changing this, make sure to update the hash near the text "THE -# rust-version HASH" in `flake.nix`. If you don't have Nix installed or -# otherwise don't know how to do this, ping `@charles:computer.surgery` or -# `@dusk:gaze.systems` in the matrix room. -# -# Also make sure to update the docker image tags in `.gitlab-ci.yml`. +# See also `rust-toolchain.toml` rust-version = "1.70.0" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/flake.nix b/flake.nix index 76f8bb25..89a4eb43 100644 --- a/flake.nix +++ b/flake.nix @@ -32,33 +32,15 @@ cargoToml = builtins.fromTOML (builtins.readFile ./Cargo.toml); # The Rust toolchain to use - toolchain = fenix.packages.${system}.toolchainOf { - # Use the Rust version defined in `Cargo.toml` - channel = cargoToml.package.rust-version; + toolchain = fenix.packages.${system}.fromToolchainFile { + file = ./rust-toolchain.toml; - # THE rust-version HASH + # See also `rust-toolchain.toml` sha256 = "sha256-gdYqng0y9iHYzYPAdkC/ka3DRny3La/S5G8ASj0Ayyc="; }; - mkToolchain = fenix.packages.${system}.combine; - - buildToolchain = mkToolchain (with toolchain; [ - cargo - rustc - ]); - - devToolchain = mkToolchain (with toolchain; [ - cargo - clippy - rust-src - rustc - - # Always use nightly rustfmt because most of its options are unstable - fenix.packages.${system}.latest.rustfmt - ]); - builder = pkgs: - ((crane.mkLib pkgs).overrideToolchain buildToolchain).buildPackage; + ((crane.mkLib pkgs).overrideToolchain toolchain).buildPackage; nativeBuildInputs = pkgs: [ pkgs.rustPlatform.bindgenHook @@ -114,12 +96,18 @@ # Rust Analyzer needs to be able to find the path to default crate # sources, and it can read this environment variable to do so. The # `rust-src` component is required in order for this to work. - RUST_SRC_PATH = "${devToolchain}/lib/rustlib/src/rust/library"; + RUST_SRC_PATH = "${toolchain}/lib/rustlib/src/rust/library"; }; # Development tools nativeBuildInputs = nativeBuildInputs pkgsHost ++ [ - devToolchain + # Always use nightly rustfmt because most of its options are unstable + # + # This needs to come before `toolchain` in this list, otherwise + # `$PATH` will have stable rustfmt instead. + fenix.packages.${system}.latest.rustfmt + + toolchain ] ++ (with pkgsHost; [ engage ]); diff --git a/rust-toolchain.toml b/rust-toolchain.toml new file mode 100644 index 00000000..cc3e2545 --- /dev/null +++ b/rust-toolchain.toml @@ -0,0 +1,17 @@ +# This is the authoritiative configuration of this project's Rust toolchain. +# +# Other files that need upkeep when this changes: +# +# * `.gitlab-ci.yml` +# * `Cargo.toml` +# * `flake.nix` +# +# Search in those files for `rust-toolchain.toml` to find the relevant places. +# If you're having trouble making the relevant changes, bug a maintainer. + +[toolchain] +channel = "1.70.0" +components = [ + # For rust-analyzer + "rust-src", +] From 3ac9be5a789f34cd980ad68b6a3824fc3ba3c7a0 Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Tue, 23 Jan 2024 11:10:23 -0800 Subject: [PATCH 11/18] add x86_64-unknown-linux-gnu This is probably the most common target and usually doesn't involve cross compilation. --- rust-toolchain.toml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/rust-toolchain.toml b/rust-toolchain.toml index cc3e2545..8d153e8b 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -15,3 +15,6 @@ components = [ # For rust-analyzer "rust-src", ] +targets = [ + "x86_64-unknown-linux-gnu", +] From 67d280dd2e71dca6e412b94ce63d328f408f3490 Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Mon, 22 Jan 2024 22:56:00 -0800 Subject: [PATCH 12/18] factor package expression into a function We'll need to call it repeatedly to make packages for cross. --- flake.nix | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/flake.nix b/flake.nix index 89a4eb43..a86422c3 100644 --- a/flake.nix +++ b/flake.nix @@ -50,9 +50,8 @@ ROCKSDB_INCLUDE_DIR = "${pkgs.rocksdb}/include"; ROCKSDB_LIB_DIR = "${pkgs.rocksdb}/lib"; }; - in - { - packages.default = builder pkgsHost { + + package = pkgs: builder pkgs { src = nix-filter { root = ./.; include = [ @@ -65,11 +64,14 @@ # This is redundant with CI doCheck = false; - env = env pkgsHost; - nativeBuildInputs = nativeBuildInputs pkgsHost; + env = env pkgs; + nativeBuildInputs = nativeBuildInputs pkgs; meta.mainProgram = cargoToml.package.name; }; + in + { + packages.default = package pkgsHost; packages.oci-image = let From d29591d47d6de9c82539f18994a268f5215a4ee6 Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Mon, 22 Jan 2024 23:07:30 -0800 Subject: [PATCH 13/18] group packages in attrset literal This will make generating packages for cross possible. --- flake.nix | 38 ++++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/flake.nix b/flake.nix index a86422c3..9d73ba9b 100644 --- a/flake.nix +++ b/flake.nix @@ -71,25 +71,27 @@ }; in { - packages.default = package pkgsHost; + packages = { + default = package pkgsHost; - packages.oci-image = - let - package = self.packages.${system}.default; - in - pkgsHost.dockerTools.buildImage { - name = package.pname; - tag = "latest"; - config = { - # Use the `tini` init system so that signals (e.g. ctrl+c/SIGINT) are - # handled as expected - Entrypoint = [ - "${pkgsHost.lib.getExe' pkgsHost.tini "tini"}" - "--" - ]; - Cmd = [ - "${pkgsHost.lib.getExe package}" - ]; + oci-image = + let + package = self.packages.${system}.default; + in + pkgsHost.dockerTools.buildImage { + name = package.pname; + tag = "latest"; + config = { + # Use the `tini` init system so that signals (e.g. ctrl+c/SIGINT) + # are handled as expected + Entrypoint = [ + "${pkgsHost.lib.getExe' pkgsHost.tini "tini"}" + "--" + ]; + Cmd = [ + "${pkgsHost.lib.getExe package}" + ]; + }; }; }; From 3a3cafe912b16d4ce786bedd37247ea200f125b9 Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Tue, 23 Jan 2024 21:29:03 -0800 Subject: [PATCH 14/18] preempt cross problems by using my crane fork I imagine this will get fixed/merged upstream in the near future. --- flake.lock | 11 ++++++----- flake.nix | 5 ++++- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/flake.lock b/flake.lock index acad901c..4508f7ce 100644 --- a/flake.lock +++ b/flake.lock @@ -51,15 +51,16 @@ ] }, "locked": { - "lastModified": 1705597458, - "narHash": "sha256-vJ8Ib9ruxbaBxGEcA0d7dHqxpc6Z+SGR2XIxVeSMuLM=", - "owner": "ipetkov", + "lastModified": 1706070683, + "narHash": "sha256-iQoXIFviH5QbSKDkWyFJKKUtTcSiCvl1tW18ax+pKfI=", + "owner": "CobaltCause", "repo": "crane", - "rev": "742170d82cd65c925dcddc5c3d6185699fbbad08", + "rev": "8060686afabc5b042e8982200cb2cc3fd22cf416", "type": "github" }, "original": { - "owner": "ipetkov", + "owner": "CobaltCause", + "ref": "crimes-for-cross", "repo": "crane", "type": "github" } diff --git a/flake.nix b/flake.nix index 9d73ba9b..ba577123 100644 --- a/flake.nix +++ b/flake.nix @@ -9,7 +9,10 @@ inputs.nixpkgs.follows = "nixpkgs"; }; crane = { - url = "github:ipetkov/crane"; + # TODO: Switch back to upstream after [this issue][0] is fixed + # + # [0]: https://github.com/ipetkov/crane/issues/497 + url = "github:CobaltCause/crane?ref=crimes-for-cross"; inputs.nixpkgs.follows = "nixpkgs"; }; attic.url = "github:zhaofengli/attic?ref=main"; From 81ae579b2546e9fe6d9eda4ed33507f4f159c67c Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Tue, 23 Jan 2024 11:22:18 -0800 Subject: [PATCH 15/18] add static cross to x86_64-unknown-linux-musl --- .gitlab-ci.yml | 13 +++++++ flake.nix | 89 +++++++++++++++++++++++++++++++++++++++++++-- rust-toolchain.toml | 1 + 3 files changed, 100 insertions(+), 3 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 1f6dab3a..95953e20 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -42,6 +42,19 @@ ci: - target - .gitlab-ci.d +static:x86_64-unknown-linux-musl: + stage: artifacts + image: nixos/nix:2.19.2 + script: + # Push artifacts and build requirements to binary cache + - ./bin/nix-build-and-cache .#static-x86_64-unknown-linux-musl + + # Make the output less difficult to find + - cp result/bin/conduit conduit + artifacts: + paths: + - conduit + oci-image:x86_64-unknown-linux-gnu: stage: artifacts image: nixos/nix:2.19.2 diff --git a/flake.nix b/flake.nix index ba577123..c30c9483 100644 --- a/flake.nix +++ b/flake.nix @@ -46,13 +46,82 @@ ((crane.mkLib pkgs).overrideToolchain toolchain).buildPackage; nativeBuildInputs = pkgs: [ - pkgs.rustPlatform.bindgenHook + # bindgen needs the build platform's libclang. Apparently due to + # "splicing weirdness", pkgs.rustPlatform.bindgenHook on its own doesn't + # quite do the right thing here. + pkgs.buildPackages.rustPlatform.bindgenHook ]; env = pkgs: { ROCKSDB_INCLUDE_DIR = "${pkgs.rocksdb}/include"; ROCKSDB_LIB_DIR = "${pkgs.rocksdb}/lib"; - }; + } + // pkgs.lib.optionalAttrs pkgs.stdenv.hostPlatform.isStatic { + ROCKSDB_STATIC = ""; + } + // { + CARGO_BUILD_RUSTFLAGS = let inherit (pkgs) lib stdenv; in + lib.concatStringsSep " " ([] + ++ lib.optionals + # This disables PIE for static builds, which isn't great in terms + # of security. Unfortunately, my hand is forced because nixpkgs' + # `libstdc++.a` is built without `-fPIE`, which precludes us from + # leaving PIE enabled. + stdenv.hostPlatform.isStatic + ["-C" "relocation-model=static"] + ++ lib.optionals + (stdenv.buildPlatform.config != pkgs.stdenv.hostPlatform.config) + ["-l" "c"] + ); + } + + # What follows is stolen from [here][0]. Its purpose is to properly + # configure compilers and linkers for various stages of the build, and + # even covers the case of build scripts that need native code compiled and + # run on the build platform (I think). + # + # [0]: https://github.com/NixOS/nixpkgs/blob/612f97239e2cc474c13c9dafa0df378058c5ad8d/pkgs/build-support/rust/lib/default.nix#L64-L78 + // ( + let + inherit (pkgs.rust.lib) envVars; + in + pkgs.lib.optionalAttrs + (pkgs.stdenv.targetPlatform.rust.rustcTarget + != pkgs.stdenv.hostPlatform.rust.rustcTarget) + ( + let + inherit (pkgs.stdenv.targetPlatform.rust) cargoEnvVarTarget; + in + { + "CC_${cargoEnvVarTarget}" = envVars.ccForTarget; + "CXX_${cargoEnvVarTarget}" = envVars.cxxForTarget; + "CARGO_TARGET_${cargoEnvVarTarget}_LINKER" = + envVars.linkerForTarget; + } + ) + // ( + let + inherit (pkgs.stdenv.hostPlatform.rust) cargoEnvVarTarget rustcTarget; + in + { + "CC_${cargoEnvVarTarget}" = envVars.ccForHost; + "CXX_${cargoEnvVarTarget}" = envVars.cxxForHost; + "CARGO_TARGET_${cargoEnvVarTarget}_LINKER" = envVars.linkerForHost; + CARGO_BUILD_TARGET = rustcTarget; + } + ) + // ( + let + inherit (pkgs.stdenv.buildPlatform.rust) cargoEnvVarTarget; + in + { + "CC_${cargoEnvVarTarget}" = envVars.ccForBuild; + "CXX_${cargoEnvVarTarget}" = envVars.cxxForBuild; + "CARGO_TARGET_${cargoEnvVarTarget}_LINKER" = envVars.linkerForBuild; + HOST_CC = "${pkgs.buildPackages.stdenv.cc}/bin/cc"; + HOST_CXX = "${pkgs.buildPackages.stdenv.cc}/bin/c++"; + } + )); package = pkgs: builder pkgs { src = nix-filter { @@ -96,7 +165,21 @@ ]; }; }; - }; + } // builtins.listToAttrs ( + builtins.map + (crossSystem: { + name = "static-${crossSystem}"; + value = package (import nixpkgs { + inherit system; + crossSystem = { + config = crossSystem; + }; + }).pkgsStatic; + }) + [ + "x86_64-unknown-linux-musl" + ] + ); devShells.default = pkgsHost.mkShell { env = env pkgsHost // { diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 8d153e8b..9a21cdb4 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -17,4 +17,5 @@ components = [ ] targets = [ "x86_64-unknown-linux-gnu", + "x86_64-unknown-linux-musl", ] From 0e8e4f10833aa4ee7104a599e5fe56f2fa027a9b Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Tue, 23 Jan 2024 11:49:52 -0800 Subject: [PATCH 16/18] add static cross to aarch64-unknown-linux-musl --- .gitlab-ci.yml | 13 +++++++++++++ flake.nix | 19 +++++++++++++++++++ rust-toolchain.toml | 1 + 3 files changed, 33 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 95953e20..6695e431 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -55,6 +55,19 @@ static:x86_64-unknown-linux-musl: paths: - conduit +static:aarch64-unknown-linux-musl: + stage: artifacts + image: nixos/nix:2.19.2 + script: + # Push artifacts and build requirements to binary cache + - ./bin/nix-build-and-cache .#static-aarch64-unknown-linux-musl + + # Make the output less difficult to find + - cp result/bin/conduit conduit + artifacts: + paths: + - conduit + oci-image:x86_64-unknown-linux-gnu: stage: artifacts image: nixos/nix:2.19.2 diff --git a/flake.nix b/flake.nix index c30c9483..e7b8cdbf 100644 --- a/flake.nix +++ b/flake.nix @@ -72,6 +72,24 @@ ++ lib.optionals (stdenv.buildPlatform.config != pkgs.stdenv.hostPlatform.config) ["-l" "c"] + ++ lib.optionals + # This check has to match the one [here][0]. We only need to set + # these flags when using a different linker. Don't ask me why, + # though, because I don't know. All I know is it breaks otherwise. + # + # [0]: https://github.com/NixOS/nixpkgs/blob/612f97239e2cc474c13c9dafa0df378058c5ad8d/pkgs/build-support/rust/lib/default.nix#L36-L39 + ( + pkgs.stdenv.hostPlatform.isAarch64 + && pkgs.stdenv.hostPlatform.isStatic + && !pkgs.stdenv.isDarwin + && !pkgs.stdenv.cc.bintools.isLLVM + ) + [ + "-l" + "stdc++" + "-L" + "${stdenv.cc.cc.lib}/${stdenv.hostPlatform.config}/lib" + ] ); } @@ -178,6 +196,7 @@ }) [ "x86_64-unknown-linux-musl" + "aarch64-unknown-linux-musl" ] ); diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 9a21cdb4..8ef64c92 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -18,4 +18,5 @@ components = [ targets = [ "x86_64-unknown-linux-gnu", "x86_64-unknown-linux-musl", + "aarch64-unknown-linux-musl", ] From 2a04a361e090bcd44939b5c7680ee4c445516790 Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Thu, 25 Jan 2024 19:36:17 -0800 Subject: [PATCH 17/18] break oci image builder into a function Now it can be reused for different `pkgs` and `package`s. --- flake.nix | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/flake.nix b/flake.nix index e7b8cdbf..5f4df1e1 100644 --- a/flake.nix +++ b/flake.nix @@ -159,30 +159,29 @@ meta.mainProgram = cargoToml.package.name; }; - in - { - packages = { - default = package pkgsHost; - oci-image = - let - package = self.packages.${system}.default; - in - pkgsHost.dockerTools.buildImage { + mkOciImage = pkgs: package: + pkgs.dockerTools.buildImage { name = package.pname; tag = "latest"; config = { # Use the `tini` init system so that signals (e.g. ctrl+c/SIGINT) # are handled as expected Entrypoint = [ - "${pkgsHost.lib.getExe' pkgsHost.tini "tini"}" + "${pkgs.lib.getExe' pkgs.tini "tini"}" "--" ]; Cmd = [ - "${pkgsHost.lib.getExe package}" + "${pkgs.lib.getExe package}" ]; }; }; + in + { + packages = { + default = package pkgsHost; + + oci-image = mkOciImage pkgsHost self.packages.${system}.default; } // builtins.listToAttrs ( builtins.map (crossSystem: { From 7c1a3e41d94dbc4d5b395dae300bd3d42b937c50 Mon Sep 17 00:00:00 2001 From: Charles Hall Date: Thu, 25 Jan 2024 19:38:25 -0800 Subject: [PATCH 18/18] add package to build an aarch64 oci image And build it as an artifact in CI. --- .gitlab-ci.yml | 17 +++++++++++++++++ flake.nix | 10 ++++++++++ 2 files changed, 27 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 6695e431..a28db4d5 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -86,6 +86,23 @@ oci-image:x86_64-unknown-linux-gnu: paths: - oci-image.tar.gz +oci-image:aarch64-unknown-linux-musl: + stage: artifacts + needs: + # Wait for the static binary job to finish before starting so we don't have + # to build that twice for no reason + - static:aarch64-unknown-linux-musl + image: nixos/nix:2.19.2 + script: + # Push artifacts and build requirements to binary cache + - ./bin/nix-build-and-cache .#oci-image-aarch64-unknown-linux-musl + + # Make the output less difficult to find + - cp result oci-image.tar.gz + artifacts: + paths: + - oci-image.tar.gz + debian:x86_64-unknown-linux-gnu: stage: artifacts # See also `rust-toolchain.toml` diff --git a/flake.nix b/flake.nix index 5f4df1e1..1bc5c148 100644 --- a/flake.nix +++ b/flake.nix @@ -182,6 +182,16 @@ default = package pkgsHost; oci-image = mkOciImage pkgsHost self.packages.${system}.default; + + # Build an OCI image from the musl aarch64 build so we don't have to + # build for aarch64 twice (to make a gnu version specifically for the + # OCI image) + oci-image-aarch64-unknown-linux-musl = mkOciImage + pkgsHost + self.packages.${system}.static-aarch64-unknown-linux-musl; + + # Don't build a musl x86_64 OCI image because that would be pointless. + # Just use the gnu one (i.e. `self.packages."x86_64-linux".oci-image`). } // builtins.listToAttrs ( builtins.map (crossSystem: {