{ inputs = { nix-haskell.url = "github:reflex-frp/nix-haskell"; nixpkgs.follows = "nix-haskell/nixpkgs"; hls-src = { url = "github:haskell/haskell-language-server/2.13.0.0"; flake = false; }; hs-bindgen-src = { url = "github:well-typed/hs-bindgen/release-0.1-alpha2"; flake = false; }; libclang-src = { url = "github:well-typed/libclang"; flake = false; }; flake-utils.url = "github:numtide/flake-utils"; crane.url = "github:ipetkov/crane"; rust-overlay = { url = "github:oxalica/rust-overlay"; inputs.nixpkgs.follows = "nixpkgs"; }; }; outputs = inputs: inputs.flake-utils.lib.eachSystem [ "x86_64-linux" ] (system: let pkgs = (import inputs.nixpkgs { inherit system; }).extend (import inputs.rust-overlay); crane = (inputs.crane.mkLib pkgs).overrideToolchain (p: p.rust-bin.selectLatestNightlyWith ( toolchain: toolchain.default.override { extensions = [ "rust-src" ]; targets = [ "x86_64-unknown-linux-gnu" ]; } )); addLibcIncludeDir = '' export C_INCLUDE_PATH="${pkgs.stdenv.cc.libc.dev}/include''${C_INCLUDE_PATH:+:$C_INCLUDE_PATH}" ''; project = (import inputs.nix-haskell { inherit system inputs; } { name = "garnet"; src = ./.; compiler-nix-name = "ghc914"; source-repository-packages = { # not on Hackage yet: https://well-typed.com/blog/2026/02/hs-bindgen-alpha # we're using more recent versions than in that post, because we want record-dot support: # https://github.com/well-typed/hs-bindgen/issues/1829#issuecomment-4081875451 c-expr-dsl = inputs.hs-bindgen-src + "/c-expr-dsl"; c-expr-runtime = inputs.hs-bindgen-src + "/c-expr-runtime"; hs-bindgen = inputs.hs-bindgen-src + "/hs-bindgen"; hs-bindgen-runtime = inputs.hs-bindgen-src + "/hs-bindgen-runtime"; libclang-bindings = inputs.libclang-src; }; overrides = [ ({ pkgs, ... }: { packages.libclang-bindings.components.library = { build-tools = [ pkgs.llvmPackages.llvm ]; libs = [ pkgs.llvmPackages.libclang ]; }; packages.garnet.components.library = { preBuild = addLibcIncludeDir; preConfigure = '' mkdir -p rust/target/debug ln -s ${garnet-rs}/include/garnet_rs.h rust/target/debug/garnet_rs.h ln -s ${garnet-rs}/lib/libCgarnet_rs.a rust/target/debug/libCgarnet_rs.a ''; preInstall = '' cp ${garnet-rs}/lib/libCgarnet_rs.a dist/build/libCgarnet_rs.a ''; configureFlags = [ "--extra-lib-dirs=${garnet-rs}/lib" ]; }; }) ]; shell = { tools = { cabal = "latest"; haskell-language-server = { src = inputs.hls-src; sha256map = { "https://github.com/snowleopard/alga" = { "d4e43fb42db05413459fb2df493361d5a666588a" = "0s1mlnl64wj7pkg3iipv5bb4syy3bhxwqzqv93zqlvkyfn64015i"; }; }; }; }; withHoogle = false; withHaddock = true; shellHook = addLibcIncludeDir; }; }).project.haskell-nix; garnet-rs = crane.buildPackage { src = crane.cleanCargoSource ./rust; doCheck = false; installPhaseCommand = '' mkdir -p $out/lib $out/include cp target/release/libgarnet_rs.a $out/lib/libCgarnet_rs.a cp target/release/garnet_rs.h $out/include/ ''; }; in rec { defaultPackage = packages.garnet-exe; packages = let garnet = project.hsPkgs.garnet; in { inherit garnet-rs; garnet-exe = garnet.components.exes.garnet; garnet-lib = garnet.components.library; }; devShells.default = pkgs.mkShell { inputsFrom = [ project.shell (crane.devShell { }) ]; packages = with pkgs; [ bacon ghcid rust-analyzer ]; }; }); }