this repo has no description
1{
2 description = "A compression multi-tool for the command line.";
3
4 inputs = {
5 nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
6
7 crane = {
8 url = "github:ipetkov/crane";
9 };
10
11 fenix = {
12 # Needed because rust-overlay, normally used by crane, doesn't have llvm-tools for coverage
13 url = "github:nix-community/fenix";
14 inputs.nixpkgs.follows = "nixpkgs";
15 inputs.rust-analyzer-src.follows = "";
16 };
17
18 # Flake helper for better organization with modules.
19 flake-parts = {
20 url = "github:hercules-ci/flake-parts";
21 inputs.nixpkgs-lib.follows = "nixpkgs";
22 };
23
24 # For creating a universal `nix fmt`
25 treefmt-nix = {
26 url = "github:numtide/treefmt-nix";
27 inputs.nixpkgs.follows = "nixpkgs";
28 };
29 };
30
31 outputs = inputs @ {
32 self,
33 flake-parts,
34 ...
35 }:
36 flake-parts.lib.mkFlake {inherit inputs;} {
37 systems = [
38 "aarch64-darwin"
39 "aarch64-linux"
40 "x86_64-darwin"
41 "x86_64-linux"
42 ];
43
44 imports = [
45 flake-parts.flakeModules.easyOverlay
46 inputs.treefmt-nix.flakeModule
47 ];
48
49 perSystem = {
50 config,
51 system,
52 pkgs,
53 ...
54 }: let
55 # Use the stable rust tools from fenix
56 fenixStable = inputs.fenix.packages.${system}.stable;
57 rustSrc = fenixStable.rust-src;
58 toolChain = fenixStable.completeToolchain;
59
60 # Use the toolchain with the crane helper functions
61 craneLib = (inputs.crane.mkLib pkgs).overrideToolchain toolChain;
62
63 # Common arguments for mkCargoDerivation, a helper for the crane functions
64 # Arguments can be included here even if they aren't used, but we only
65 # place them here if they would otherwise show up in multiple places
66 commonArgs = {
67 inherit cargoArtifacts;
68 # Clean the src to only have the Rust-relevant files
69 src = craneLib.cleanCargoSource ./.;
70 strictDeps = true;
71 nativeBuildInputs = [
72 pkgs.pkg-config
73 pkgs.gcc
74 ];
75 };
76
77 # Build only the cargo dependencies so we can cache them all when running in CI
78 cargoArtifacts = craneLib.buildDepsOnly commonArgs;
79
80 # Build the actual crate itself, reusing the cargoArtifacts
81 cmprss = craneLib.buildPackage (commonArgs
82 // {
83 doCheck = false; # Tests are run as a separate build with nextest
84 meta.mainProgram = "cmprss";
85 nativeBuildInputs = commonArgs.nativeBuildInputs ++ [pkgs.installShellFiles];
86 postInstall = pkgs.lib.optionalString (pkgs.stdenv.buildPlatform.canExecute pkgs.stdenv.hostPlatform) ''
87 installShellCompletion --cmd cmprss \
88 --bash <($out/bin/cmprss completions bash) \
89 --fish <($out/bin/cmprss completions fish) \
90 --zsh <($out/bin/cmprss completions zsh)
91 '';
92 });
93
94 # Fully static musl build (Linux only)
95 staticMusl = pkgs.lib.optionalAttrs pkgs.stdenv.isLinux (
96 let
97 muslTarget =
98 if system == "x86_64-linux"
99 then "x86_64-unknown-linux-musl"
100 else "aarch64-unknown-linux-musl";
101
102 muslToolchain = inputs.fenix.packages.${system}.combine [
103 fenixStable.cargo
104 fenixStable.rustc
105 inputs.fenix.packages.${system}.targets.${muslTarget}.stable.rust-std
106 ];
107
108 craneLibMusl = (inputs.crane.mkLib pkgs).overrideToolchain muslToolchain;
109
110 musl-cc = pkgs.pkgsStatic.stdenv.cc;
111
112 staticArgs = {
113 src = craneLibMusl.cleanCargoSource ./.;
114 strictDeps = true;
115 CARGO_BUILD_TARGET = muslTarget;
116 CARGO_BUILD_RUSTFLAGS = "-C target-feature=+crt-static";
117 TARGET_CC = "${musl-cc}/bin/${musl-cc.targetPrefix}cc";
118 HOST_CC = "${pkgs.stdenv.cc}/bin/cc";
119 nativeBuildInputs = [
120 musl-cc
121 pkgs.pkg-config
122 ];
123 };
124
125 cargoArtifactsStatic = craneLibMusl.buildDepsOnly staticArgs;
126 in {
127 cmprss-static = craneLibMusl.buildPackage (staticArgs
128 // {
129 cargoArtifacts = cargoArtifactsStatic;
130 doCheck = false;
131 meta.mainProgram = "cmprss";
132 nativeBuildInputs = staticArgs.nativeBuildInputs ++ [pkgs.installShellFiles];
133 postInstall = pkgs.lib.optionalString (pkgs.stdenv.buildPlatform.canExecute pkgs.stdenv.hostPlatform) ''
134 installShellCompletion --cmd cmprss \
135 --bash <($out/bin/cmprss completions bash) \
136 --fish <($out/bin/cmprss completions fish) \
137 --zsh <($out/bin/cmprss completions zsh)
138 '';
139 });
140 }
141 );
142 # Source filtered to specific file extensions for lightweight linter checks
143 cleanSrc = pkgs.lib.cleanSource ./.;
144 sourceWithExts = exts:
145 pkgs.lib.cleanSourceWith {
146 src = cleanSrc;
147 filter = path: type:
148 (type == "directory")
149 || (pkgs.lib.any (ext: pkgs.lib.hasSuffix ".${ext}" path) exts);
150 };
151
152 mkSimpleLinter = {
153 name,
154 packages ? [],
155 src ? cleanSrc,
156 command,
157 }:
158 pkgs.runCommand "lint-${name}" {
159 nativeBuildInputs = packages;
160 inherit src;
161 } ''
162 cd $src
163 ${command}
164 mkdir -p $out
165 '';
166
167 linters = {
168 statix = mkSimpleLinter {
169 name = "statix";
170 packages = [pkgs.statix];
171 src = sourceWithExts ["nix"];
172 command = "statix check .";
173 };
174 deadnix = mkSimpleLinter {
175 name = "deadnix";
176 packages = [pkgs.deadnix];
177 src = sourceWithExts ["nix"];
178 command = "deadnix --fail .";
179 };
180 shellcheck = mkSimpleLinter {
181 name = "shellcheck";
182 packages = [pkgs.shellcheck pkgs.findutils];
183 src = sourceWithExts ["sh"];
184 command = ''find . -name "*.sh" -type f -exec shellcheck {} +'';
185 };
186 actionlint = mkSimpleLinter {
187 name = "actionlint";
188 packages = [pkgs.actionlint pkgs.shellcheck pkgs.findutils];
189 src = pkgs.lib.cleanSourceWith {
190 src = cleanSrc;
191 filter = path: type:
192 (type == "directory")
193 || (pkgs.lib.hasSuffix ".yml" path && pkgs.lib.hasInfix ".github" path);
194 };
195 command = ''find .github/workflows -name "*.yml" -exec actionlint {} +'';
196 };
197 };
198 in {
199 packages =
200 {
201 default = cmprss;
202 inherit cmprss;
203
204 # Check code coverage with tarpaulin
205 coverage = craneLib.cargoTarpaulin (commonArgs
206 // {
207 # Use lcov output as thats far more widely supported
208 cargoTarpaulinExtraArgs = "--skip-clean --include-tests --output-dir $out --out lcov";
209 });
210
211 # Run clippy (and deny all warnings) on the crate source
212 clippy = craneLib.cargoClippy (commonArgs
213 // {
214 cargoClippyExtraArgs = "--all-targets -- --deny warnings";
215 });
216
217 # Check docs build successfully
218 doc = craneLib.cargoDoc commonArgs;
219
220 # Check formatting
221 fmt = craneLib.cargoFmt commonArgs;
222
223 # Run tests with cargo-nextest
224 test = craneLib.cargoNextest commonArgs;
225
226 # Audit dependencies, check licenses, and detect duplicate crates
227 deny = craneLib.cargoDeny (commonArgs
228 // {
229 # advisories excluded: needs network access (blocked by nix sandbox)
230 cargoDenyChecks = "bans licenses sources";
231 });
232 }
233 // staticMusl;
234
235 checks =
236 {
237 inherit cmprss;
238 # Build almost every package in checks, with exceptions:
239 # - coverage: It requires a full rebuild, and only needs to be run occasionally
240 inherit (self.packages.${system}) clippy doc fmt test deny;
241 }
242 // linters;
243
244 # This also sets up `nix fmt` to run all formatters
245 treefmt = {
246 projectRootFile = "./flake.nix";
247 programs = {
248 alejandra.enable = true;
249 prettier.enable = true;
250 rustfmt.enable = true;
251 shfmt.enable = true;
252 typos = {
253 enable = true;
254 configFile = "./.config/typos.toml";
255 };
256 };
257 };
258
259 apps = rec {
260 default = cmprss;
261 cmprss.program = self.packages.${system}.cmprss;
262 };
263
264 overlayAttrs = {
265 inherit (config.packages) cmprss;
266 };
267
268 devShells.default = pkgs.mkShell {
269 name = "cmprss";
270 shellHook = ''
271 echo ---------------------
272 just --list
273 echo ---------------------
274 '';
275
276 # Include the packages from the defined checks and packages
277 # Installs the full cargo toolchain and the extra tools, e.g. cargo-tarpaulin.
278 inputsFrom =
279 (builtins.attrValues self.checks.${system})
280 ++ (builtins.attrValues self.packages.${system});
281
282 # Extra inputs can be added here
283 packages = with pkgs; [
284 act # For running Github Actions locally
285 alejandra
286 actionlint
287 deadnix
288 git-cliff
289 gum # Pretty printing in scripts
290 just
291 nodePackages.prettier
292 shellcheck
293 statix
294 typos
295
296 # For running tests
297 diffutils
298
299 # Official tools
300 brotli
301 bzip2
302 gnutar
303 gzip
304 lz4
305 p7zip
306 snzip
307 unzip
308 xz
309 zip
310 zstd
311 ];
312
313 # Many tools read this to find the sources for rust stdlib
314 RUST_SRC_PATH = "${rustSrc}/lib/rustlib/src/rust/library";
315 };
316 };
317 };
318}