From e802614b38faa19004f3e5e8e9fe73ef44ad03e9 Mon Sep 17 00:00:00 2001 From: Dillen Meijboom Date: Mon, 17 Aug 2026 15:19:55 +0200 Subject: [PATCH 1/2] feat: link statically --- flake.nix | 196 +++++++++++++++++++++++++++++++++++------------------- 1 file changed, 128 insertions(+), 68 deletions(-) diff --git a/flake.nix b/flake.nix index cf49244..5fdffd6 100644 --- a/flake.nix +++ b/flake.nix @@ -8,75 +8,135 @@ inputs.nixpkgs.follows = "nixpkgs"; }; }; - outputs = { - nixpkgs, - crane, - rust-overlay, - nix-filter, - ... - }: let - supportedSystems = [ - "x86_64-linux" - "x86_64-darwin" - "aarch64-linux" - "aarch64-darwin" - ]; - overlays = [(import rust-overlay)]; - filter = import nix-filter; - eachSystem = nixpkgs.lib.genAttrs supportedSystems; + outputs = + { + nixpkgs, + crane, + rust-overlay, + nix-filter, + ... + }: + let + supportedSystems = [ + "x86_64-linux" + "x86_64-darwin" + "aarch64-linux" + "aarch64-darwin" + ]; + overlays = [ (import rust-overlay) ]; + filter = import nix-filter; + eachSystem = nixpkgs.lib.genAttrs supportedSystems; - toolchainFor = pkgs: - pkgs.rust-bin.nightly.latest.minimal.override { - extensions = ["clippy" "rust-src"]; - }; - in { - packages = eachSystem (system: let - pkgs = import nixpkgs {inherit system overlays;}; - craneLib = (crane.mkLib pkgs).overrideToolchain (toolchainFor pkgs); - src = filter { - root = ./.; - include = [ - "src" - "Cargo.toml" - "Cargo.lock" - ]; - }; - craneArgs = { - inherit src; - strictDeps = true; - SSL_CERT_FILE = "${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt"; - } // pkgs.lib.optionalAttrs pkgs.stdenv.hostPlatform.isDarwin { - RUSTFLAGS = "-C link-arg=-Wl,-dead_strip_dylibs"; - }; - cargoArtifacts = craneLib.buildDepsOnly craneArgs; - in { - default = craneLib.buildPackage (craneArgs - // { - inherit cargoArtifacts; - pname = "brainpod-cli"; - version = "0.1.0"; - meta.mainProgram = "brainpod"; + rustTargetFor = + system: + { + x86_64-linux = "x86_64-unknown-linux-musl"; + aarch64-linux = "aarch64-unknown-linux-musl"; } - // pkgs.lib.optionalAttrs pkgs.stdenv.hostPlatform.isDarwin { - postFixup = '' - if otool -L "$out/bin/brainpod" | tail -n +2 | grep -F /nix/store/; then - echo "brainpod contains a dynamic Nix store dependency" >&2 - exit 1 - fi - ''; - }); - }); + .${system} or null; - devShells = eachSystem (system: let - pkgs = import nixpkgs {inherit system overlays;}; - craneLib = (crane.mkLib pkgs).overrideToolchain (toolchainFor pkgs); - in { - default = craneLib.devShell { - packages = with pkgs; [ - rustfmt - rust-analyzer - ]; - }; - }); - }; + toolchainFor = + pkgs: + let + rustTarget = rustTargetFor pkgs.stdenv.hostPlatform.system; + in + pkgs.rust-bin.nightly.latest.minimal.override ( + { + extensions = [ + "clippy" + "rust-src" + ]; + } + // pkgs.lib.optionalAttrs (rustTarget != null) { + targets = [ rustTarget ]; + } + ); + in + { + packages = eachSystem ( + system: + let + rustTarget = rustTargetFor system; + pkgs = import nixpkgs ( + { + localSystem = system; + inherit overlays; + } + // nixpkgs.lib.optionalAttrs (rustTarget != null) { + crossSystem.config = rustTarget; + } + ); + craneLib = (crane.mkLib pkgs).overrideToolchain toolchainFor; + src = filter { + root = ./.; + include = [ + "src" + "Cargo.toml" + "Cargo.lock" + ]; + }; + craneArgs = { + inherit src; + strictDeps = true; + SSL_CERT_FILE = "${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt"; + } + // pkgs.lib.optionalAttrs pkgs.stdenv.hostPlatform.isLinux { + CARGO_BUILD_TARGET = rustTarget; + CARGO_BUILD_RUSTFLAGS = "-C target-feature=+crt-static"; + } + // pkgs.lib.optionalAttrs pkgs.stdenv.hostPlatform.isDarwin { + RUSTFLAGS = "-C link-arg=-Wl,-dead_strip_dylibs"; + }; + cargoArtifacts = craneLib.buildDepsOnly craneArgs; + in + { + default = craneLib.buildPackage ( + craneArgs + // { + inherit cargoArtifacts; + pname = "brainpod-cli"; + version = "0.1.0"; + meta.mainProgram = "brainpod"; + } + // pkgs.lib.optionalAttrs pkgs.stdenv.hostPlatform.isLinux { + nativeBuildInputs = [ pkgs.buildPackages.binutils ]; + postFixup = '' + if readelf -l "$out/bin/brainpod" | grep -F INTERP; then + echo "brainpod contains a dynamic ELF interpreter" >&2 + exit 1 + fi + if readelf -d "$out/bin/brainpod" | grep -F '(NEEDED)'; then + echo "brainpod contains a dynamic library dependency" >&2 + exit 1 + fi + ''; + } + // pkgs.lib.optionalAttrs pkgs.stdenv.hostPlatform.isDarwin { + postFixup = '' + if otool -L "$out/bin/brainpod" | tail -n +2 | grep -F /nix/store/; then + echo "brainpod contains a dynamic Nix store dependency" >&2 + exit 1 + fi + ''; + } + ); + } + ); + + devShells = eachSystem ( + system: + let + pkgs = import nixpkgs { inherit system overlays; }; + craneLib = (crane.mkLib pkgs).overrideToolchain toolchainFor; + in + { + default = craneLib.devShell { + packages = with pkgs; [ + rustfmt + rust-analyzer + ]; + }; + } + ); + }; } From 5627fe0554351ad2f7516792b7ec252f2ecdf885 Mon Sep 17 00:00:00 2001 From: Dillen Meijboom Date: Mon, 17 Aug 2026 15:24:22 +0200 Subject: [PATCH 2/2] feat: add flake check workflow --- .github/workflows/flake.yml | 22 ++++++++++++++++++++++ flake.lock | 16 ---------------- flake.nix | 25 +++++++++++++------------ 3 files changed, 35 insertions(+), 28 deletions(-) create mode 100644 .github/workflows/flake.yml diff --git a/.github/workflows/flake.yml b/.github/workflows/flake.yml new file mode 100644 index 0000000..977bbe2 --- /dev/null +++ b/.github/workflows/flake.yml @@ -0,0 +1,22 @@ +name: Flake + +on: + pull_request: + +permissions: + contents: read + +jobs: + check: + name: Check + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - uses: cachix/install-nix-action@v31 + with: + github_access_token: ${{ secrets.GITHUB_TOKEN }} + + - name: Check flake + run: nix flake check --all-systems --no-build diff --git a/flake.lock b/flake.lock index 14f5617..d7c48f8 100644 --- a/flake.lock +++ b/flake.lock @@ -15,21 +15,6 @@ "type": "github" } }, - "nix-filter": { - "locked": { - "lastModified": 1757882181, - "narHash": "sha256-+cCxYIh2UNalTz364p+QYmWHs0P+6wDhiWR4jDIKQIU=", - "owner": "numtide", - "repo": "nix-filter", - "rev": "59c44d1909c72441144b93cf0f054be7fe764de5", - "type": "github" - }, - "original": { - "owner": "numtide", - "repo": "nix-filter", - "type": "github" - } - }, "nixpkgs": { "locked": { "lastModified": 1780930886, @@ -49,7 +34,6 @@ "root": { "inputs": { "crane": "crane", - "nix-filter": "nix-filter", "nixpkgs": "nixpkgs", "rust-overlay": "rust-overlay" } diff --git a/flake.nix b/flake.nix index 5fdffd6..0f03006 100644 --- a/flake.nix +++ b/flake.nix @@ -1,7 +1,6 @@ { inputs = { nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; - nix-filter.url = "github:numtide/nix-filter"; crane.url = "github:ipetkov/crane"; rust-overlay = { url = "github:oxalica/rust-overlay"; @@ -13,7 +12,6 @@ nixpkgs, crane, rust-overlay, - nix-filter, ... }: let @@ -24,7 +22,6 @@ "aarch64-darwin" ]; overlays = [ (import rust-overlay) ]; - filter = import nix-filter; eachSystem = nixpkgs.lib.genAttrs supportedSystems; rustTargetFor = @@ -67,16 +64,22 @@ } ); craneLib = (crane.mkLib pkgs).overrideToolchain toolchainFor; - src = filter { - root = ./.; - include = [ - "src" - "Cargo.toml" - "Cargo.lock" - ]; + src = pkgs.lib.cleanSourceWith { + src = ./.; + filter = + path: _: + let + relative = pkgs.lib.removePrefix "${toString ./.}/" (toString path); + in + relative == "Cargo.toml" + || relative == "Cargo.lock" + || relative == "src" + || pkgs.lib.hasPrefix "src/" relative; }; craneArgs = { inherit src; + cargoTomlContents = builtins.readFile ./Cargo.toml; + cargoLockContents = builtins.readFile ./Cargo.lock; strictDeps = true; SSL_CERT_FILE = "${pkgs.cacert}/etc/ssl/certs/ca-bundle.crt"; } @@ -94,8 +97,6 @@ craneArgs // { inherit cargoArtifacts; - pname = "brainpod-cli"; - version = "0.1.0"; meta.mainProgram = "brainpod"; } // pkgs.lib.optionalAttrs pkgs.stdenv.hostPlatform.isLinux {