just playing with tangled
1{
2 description = "Jujutsu VCS, a Git-compatible DVCS that is both simple and powerful";
3
4 inputs = {
5 # For listing and iterating nix systems
6 flake-utils.url = "github:numtide/flake-utils";
7
8 nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
9
10 # For installing non-standard rustc versions
11 rust-overlay.url = "github:oxalica/rust-overlay";
12 rust-overlay.inputs.nixpkgs.follows = "nixpkgs";
13 };
14
15 outputs = {
16 self,
17 nixpkgs,
18 flake-utils,
19 rust-overlay,
20 }:
21 {
22 overlays.default = final: prev: {
23 jujutsu = self.packages.${final.system}.jujutsu;
24 };
25 }
26 // (flake-utils.lib.eachDefaultSystem (system: let
27 pkgs = import nixpkgs {
28 inherit system;
29 overlays = [
30 rust-overlay.overlays.default
31 ];
32 };
33
34 filterSrc = src: regexes:
35 pkgs.lib.cleanSourceWith {
36 inherit src;
37 filter = path: type: let
38 relPath = pkgs.lib.removePrefix (toString src + "/") (toString path);
39 in
40 pkgs.lib.all (re: builtins.match re relPath == null) regexes;
41 };
42
43 # When we're running in the shell, we want to use rustc with a bunch
44 # of extra junk to ensure that rust-analyzer works, clippy etc are all
45 # installed.
46 rustShellToolchain = (pkgs.rust-bin.selectLatestNightlyWith (t: t.default)).override {
47 # NOTE (aseipp): explicitly add rust-src to the rustc compiler only in
48 # devShell. this in turn causes a dependency on the rust compiler src,
49 # which bloats the closure size by several GiB. but doing this here and
50 # not by default avoids the default flake install from including that
51 # dependency, so it's worth it
52 #
53 # relevant PR: https://github.com/rust-lang/rust/pull/129687
54 extensions = ["rust-src" "rust-analyzer"];
55 };
56
57 # But, whenever we are running CI builds or checks, we want to use a
58 # smaller closure. This reduces the CI impact on fresh clones/VMs, etc.
59 rustMinimalPlatform =
60 let platform = pkgs.rust-bin.selectLatestNightlyWith (t: t.minimal);
61 in pkgs.makeRustPlatform { rustc = platform; cargo = platform; };
62
63 nativeBuildInputs = with pkgs;
64 [
65 gzip
66 pkg-config
67
68 # for libz-ng-sys (zlib-ng)
69 # TODO: switch to the packaged zlib-ng and drop this dependency
70 cmake
71 ]
72 ++ lib.optionals stdenv.isLinux [
73 mold-wrapped
74 ];
75
76 buildInputs = with pkgs;
77 [
78 openssl
79 libgit2
80 libssh2
81 ]
82 ++ lib.optionals stdenv.isDarwin [
83 darwin.apple_sdk.frameworks.Security
84 darwin.apple_sdk.frameworks.SystemConfiguration
85 libiconv
86 ];
87
88 nativeCheckInputs = with pkgs; [
89 # for signing tests
90 gnupg
91 openssh
92
93 # for git subprocess test
94 git
95
96 # for schema tests
97 taplo
98 ];
99
100 env = {
101 LIBSSH2_SYS_USE_PKG_CONFIG = "1";
102 RUST_BACKTRACE = 1;
103 };
104 in {
105 formatter = pkgs.alejandra;
106
107 packages = {
108 jujutsu = rustMinimalPlatform.buildRustPackage {
109 pname = "jujutsu";
110 version = "unstable-${self.shortRev or "dirty"}";
111
112 buildFeatures = ["packaging"];
113 cargoBuildFlags = ["--bin" "jj"]; # don't build and install the fake editors
114 useNextest = true;
115 cargoTestFlags = ["--profile" "ci"];
116 src = filterSrc ./. [
117 ".*\\.nix$"
118 "^.jj/"
119 "^flake\\.lock$"
120 "^target/"
121 ];
122
123 cargoLock.lockFile = ./Cargo.lock;
124 nativeBuildInputs = nativeBuildInputs ++ [pkgs.installShellFiles];
125 inherit buildInputs nativeCheckInputs;
126
127 env =
128 env
129 // {
130 RUSTFLAGS = pkgs.lib.optionalString pkgs.stdenv.isLinux "-C link-arg=-fuse-ld=mold";
131 NIX_JJ_GIT_HASH = self.rev or "";
132 CARGO_INCREMENTAL = "0";
133 };
134
135 postInstall = ''
136 $out/bin/jj util install-man-pages man
137 installManPage ./man/man1/*
138
139 installShellCompletion --cmd jj \
140 --bash <(COMPLETE=bash $out/bin/jj) \
141 --fish <(COMPLETE=fish $out/bin/jj) \
142 --zsh <(COMPLETE=zsh $out/bin/jj)
143 '';
144
145 meta = {
146 description = "Git-compatible DVCS that is both simple and powerful";
147 homepage = "https://github.com/jj-vcs/jj";
148 license = pkgs.lib.licenses.asl20;
149 mainProgram = "jj";
150 };
151 };
152 default = self.packages.${system}.jujutsu;
153 };
154
155 checks.jujutsu = self.packages.${system}.jujutsu.overrideAttrs ({...}: {
156 # The default Rust infrastructure runs all builds in the release
157 # profile, which is significantly slower. Run this under the `test`
158 # profile instead, which matches all our other CI systems, Cargo, etc.
159 cargoBuildType = "test";
160 cargoCheckType = "test";
161
162 # By default, `flake check` will want to run the install phase, but
163 # because we override the cargoBuildType, it fails to find the proper
164 # binary. But we don't even care about the binary or even the buildPhase
165 # in this case; just remove them both.
166 buildPhase = "true";
167 installPhase = "touch $out";
168 });
169
170 devShells.default = let
171 packages = with pkgs; [
172 rustShellToolchain
173
174 # Additional tools recommended by contributing.md
175 bacon
176 cargo-deny
177 cargo-insta
178 cargo-nextest
179
180 # Miscellaneous tools
181 watchman
182
183 # In case you need to run `cargo run --bin gen-protos`
184 protobuf
185
186 # For building the documentation website
187 uv
188 # nixos does not work with uv-installed python
189 python3
190 ];
191
192 # on macOS and Linux, use faster parallel linkers that are much more
193 # efficient than the defaults. these noticeably improve link time even for
194 # medium sized rust projects like jj
195 rustLinkerFlags =
196 if pkgs.stdenv.isLinux
197 then ["-fuse-ld=mold" "-Wl,--compress-debug-sections=zstd"]
198 else if pkgs.stdenv.isDarwin
199 then
200 # on darwin, /usr/bin/ld actually looks at the environment variable
201 # $DEVELOPER_DIR, which is set by the nix stdenv, and if set,
202 # automatically uses it to route the `ld` invocation to the binary
203 # within. in the devShell though, that isn't what we want; it's
204 # functional, but Xcode's linker as of ~v15 (not yet open source)
205 # is ultra-fast and very shiny; it is enabled via -ld_new, and on by
206 # default as of v16+
207 ["--ld-path=$(unset DEVELOPER_DIR; /usr/bin/xcrun --find ld)" "-ld_new"]
208 else [];
209
210 rustLinkFlagsString =
211 pkgs.lib.concatStringsSep " "
212 (pkgs.lib.concatMap (x: ["-C" "link-arg=${x}"]) rustLinkerFlags);
213
214 # The `RUSTFLAGS` environment variable is set in `shellHook` instead of `env`
215 # to allow the `xcrun` command above to be interpreted by the shell.
216 shellHook = ''
217 export RUSTFLAGS="-Zthreads=0 ${rustLinkFlagsString}"
218 '';
219 in
220 pkgs.mkShell {
221 name = "jujutsu";
222 packages = packages ++ nativeBuildInputs ++ buildInputs ++ nativeCheckInputs;
223 inherit env shellHook;
224 };
225 }));
226}