{ description = "Build a cargo project without extra checks"; inputs = { nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; crane.url = "github:ipetkov/crane"; flake-utils.url = "github:numtide/flake-utils"; rust-overlay = { url = "github:oxalica/rust-overlay"; inputs.nixpkgs.follows = "nixpkgs"; }; }; outputs = { self, nixpkgs, crane, flake-utils, ... }@inputs: (flake-utils.lib.eachDefaultSystem ( system: let pkgs = import inputs.nixpkgs { inherit system; overlays = [ (import inputs.rust-overlay) ]; }; craneLib = (inputs.crane.mkLib pkgs).overrideToolchain ( p: p.rust-bin.nightly.latest.default.override { extensions = [ "rustc-codegen-cranelift-preview" "rust-analyzer" "rust-src" ]; } ); # Runtime/shared libraries required by iced/iced_layershell/winit. # winit dlopens libwayland at runtime, so these must be on # LD_LIBRARY_PATH (see https://github.com/iced-rs/iced/issues/2385). guiLibs = [ pkgs.wayland pkgs.wayland-protocols pkgs.libxkbcommon pkgs.vulkan-loader pkgs.libx11 pkgs.libxcursor pkgs.libxrandr pkgs.libxi pkgs.libxcb ]; # Common arguments can be set here to avoid repeating them later # Note: changes here will rebuild all dependency crates commonArgs = { # Exclude build outputs regardless of git state (this repo is not # git-initialized, so cleanCargoSource would otherwise copy target/). src = pkgs.lib.cleanSourceWith { src = ./.; filter = path: type: let base = baseNameOf (toString path); in !(type == "directory" && (base == "target" || base == "result" || base == ".direnv")); }; strictDeps = true; nativeBuildInputs = [ pkgs.pkg-config ] ++ pkgs.lib.optionals pkgs.stdenv.hostPlatform.isLinux [ pkgs.mold ]; # Link with mold (fast linker). Lives in commonArgs so deps and the # final crate share one flag set; note this rebuilds all dependency # crates once when first added. env = pkgs.lib.optionalAttrs pkgs.stdenv.hostPlatform.isLinux { RUSTFLAGS = "-C link-arg=-fuse-ld=mold"; }; buildInputs = guiLibs ++ pkgs.lib.optionals pkgs.stdenv.hostPlatform.isDarwin [ # Additional darwin specific inputs can be set here pkgs.libiconv ]; }; my-crate = craneLib.buildPackage ( commonArgs // { cargoArtifacts = craneLib.buildDepsOnly commonArgs; # Additional environment variables or build phases/hooks can be set # here *without* rebuilding all dependency crates # MY_CUSTOM_VAR = "some value"; } ); # winit dlopens libwayland and wgpu the vulkan loader at runtime, which # rpath alone does not cover; wrap the binary with LD_LIBRARY_PATH so # the package also runs outside the devShell (e.g. from systemd). barbar = pkgs.symlinkJoin { name = "barbar-${my-crate.version}"; paths = [ my-crate ]; nativeBuildInputs = [ pkgs.makeWrapper ]; postBuild = '' wrapProgram $out/bin/core \ --prefix LD_LIBRARY_PATH : ${pkgs.lib.makeLibraryPath guiLibs} ''; meta.mainProgram = "core"; }; in { checks = { inherit my-crate; }; packages.default = barbar; apps.default = flake-utils.lib.mkApp { drv = barbar; exePath = "/bin/core"; }; devShells.default = craneLib.devShell { # Inherit inputs from checks. checks = self.checks.${system}; # Put the GUI shared libraries on the runtime library path so winit # can dlopen libwayland and wgpu can find the vulkan loader. # No RUSTFLAGS here: an env RUSTFLAGS would override (not merge # with) ~/.cargo/config.toml's rustflags, giving devShell and # non-devShell builds different fingerprints and force-rebuilding # every dependency on each switch. shellHook = '' export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${pkgs.lib.makeLibraryPath guiLibs}" ''; # Extra inputs can be added here; cargo and rustc are provided by default. packages = guiLibs ++ pkgs.lib.optionals pkgs.stdenv.hostPlatform.isLinux [ pkgs.mold ]; }; } )) // { # System-independent, so it lives outside eachDefaultSystem. homeManagerModules.default = import ./nix/home-manager.nix self; }; }