1{
2 pkgs,
3 system,
4 lib,
5 stdenv,
6
7 apple-sdk_15,
8 darwin,
9 darwinMinVersionHook,
10
11 cargo-about,
12 cargo-bundle,
13 crane,
14 rustPlatform,
15 rustToolchain,
16
17 copyDesktopItems,
18 envsubst,
19 fetchFromGitHub,
20 makeFontsConf,
21 makeWrapper,
22
23 alsa-lib,
24 cmake,
25 curl,
26 fontconfig,
27 freetype,
28 git,
29 glib,
30 libdrm,
31 libgbm,
32 libgit2,
33 libglvnd,
34 libva,
35 libxcomposite,
36 libxdamage,
37 libxext,
38 libxfixes,
39 libxkbcommon,
40 libxrandr,
41 nodejs_22,
42 openssl,
43 perl,
44 pkg-config,
45 protobuf,
46 sqlite,
47 vulkan-loader,
48 wayland,
49 xorg,
50 zlib,
51 zstd,
52
53 withGLES ? false,
54 profile ? "release",
55}:
56assert withGLES -> stdenv.hostPlatform.isLinux;
57let
58 mkIncludeFilter =
59 root': path: type:
60 let
61 # note: under lazy-trees this introduces an extra copy
62 root = toString root' + "/";
63 relPath = lib.removePrefix root path;
64 topLevelIncludes = [
65 "crates"
66 "assets"
67 "extensions"
68 "script"
69 "tooling"
70 "Cargo.toml"
71 ".config" # nextest?
72 ".cargo"
73 ];
74 firstComp = builtins.head (lib.path.subpath.components relPath);
75 in
76 builtins.elem firstComp topLevelIncludes;
77
78 craneLib = crane.overrideToolchain rustToolchain;
79 gpu-lib = if withGLES then libglvnd else vulkan-loader;
80 commonArgs =
81 let
82 zedCargoLock = builtins.fromTOML (builtins.readFile ../crates/zed/Cargo.toml);
83 stdenv' = stdenv;
84 in
85 rec {
86 pname = "zed-editor";
87 version = zedCargoLock.package.version + "-nightly";
88 src = builtins.path {
89 path = ../.;
90 filter = mkIncludeFilter ../.;
91 name = "source";
92 };
93
94 cargoLock = ../Cargo.lock;
95
96 nativeBuildInputs = [
97 cmake
98 copyDesktopItems
99 curl
100 perl
101 pkg-config
102 protobuf
103 # Pin cargo-about to 0.8.2. Newer versions don't work with the current license identifiers
104 # See https://github.com/zed-industries/zed/pull/44012
105 (cargo-about.overrideAttrs (
106 new: old: rec {
107 version = "0.8.2";
108
109 src = fetchFromGitHub {
110 owner = "EmbarkStudios";
111 repo = "cargo-about";
112 tag = version;
113 sha256 = "sha256-cNKZpDlfqEXeOE5lmu79AcKOawkPpk4PQCsBzNtIEbs=";
114 };
115
116 cargoHash = "sha256-NnocSs6UkuF/mCM3lIdFk+r51Iz2bHuYzMT/gEbT/nk=";
117
118 # NOTE: can drop once upstream uses `finalAttrs` here:
119 # https://github.com/NixOS/nixpkgs/blob/10214747f5e6e7cb5b9bdf9e018a3c7b3032f5af/pkgs/build-support/rust/build-rust-package/default.nix#L104
120 #
121 # See (for context): https://github.com/NixOS/nixpkgs/pull/382550
122 cargoDeps = rustPlatform.fetchCargoVendor {
123 inherit (new) src;
124 hash = new.cargoHash;
125 patches = new.cargoPatches or [ ];
126 name = new.cargoDepsName or new.finalPackage.name;
127 };
128 }
129 ))
130 rustPlatform.bindgenHook
131 ]
132 ++ lib.optionals stdenv'.hostPlatform.isLinux [ makeWrapper ]
133 ++ lib.optionals stdenv'.hostPlatform.isDarwin [
134 (cargo-bundle.overrideAttrs (
135 new: old: {
136 version = "0.6.1-zed";
137 src = fetchFromGitHub {
138 owner = "zed-industries";
139 repo = "cargo-bundle";
140 rev = "2be2669972dff3ddd4daf89a2cb29d2d06cad7c7";
141 hash = "sha256-cSvW0ND148AGdIGWg/ku0yIacVgW+9f1Nsi+kAQxVrI=";
142 };
143 cargoHash = "sha256-urn+A3yuw2uAO4HGmvQnKvWtHqvG9KHxNCCWTiytE4k=";
144
145 # NOTE: can drop once upstream uses `finalAttrs` here:
146 # https://github.com/NixOS/nixpkgs/blob/10214747f5e6e7cb5b9bdf9e018a3c7b3032f5af/pkgs/build-support/rust/build-rust-package/default.nix#L104
147 #
148 # See (for context): https://github.com/NixOS/nixpkgs/pull/382550
149 cargoDeps = rustPlatform.fetchCargoVendor {
150 inherit (new) src;
151 hash = new.cargoHash;
152 patches = new.cargoPatches or [ ];
153 name = new.cargoDepsName or new.finalPackage.name;
154 };
155 }
156 ))
157 ];
158
159 buildInputs = [
160 curl
161 fontconfig
162 freetype
163 # TODO: need staticlib of this for linking the musl remote server.
164 # should make it a separate derivation/flake output
165 # see https://crane.dev/examples/cross-musl.html
166 libgit2
167 openssl
168 sqlite
169 zlib
170 zstd
171 ]
172 ++ lib.optionals stdenv'.hostPlatform.isLinux [
173 alsa-lib
174 glib
175 libva
176 libxkbcommon
177 wayland
178 gpu-lib
179 xorg.libX11
180 xorg.libxcb
181 libdrm
182 libgbm
183 libva
184 libxcomposite
185 libxdamage
186 libxext
187 libxfixes
188 libxrandr
189 ]
190 ++ lib.optionals stdenv'.hostPlatform.isDarwin [
191 apple-sdk_15
192 (darwinMinVersionHook "10.15")
193 ];
194
195 cargoExtraArgs = "-p zed -p cli --locked --features=gpui_platform/runtime_shaders";
196
197 stdenv =
198 pkgs:
199 let
200 base = pkgs.llvmPackages.stdenv;
201 addBinTools = old: {
202 cc = old.cc.override {
203 inherit (pkgs.llvmPackages) bintools;
204 };
205 };
206 custom = lib.pipe base [
207 (stdenv: stdenv.override addBinTools)
208 pkgs.stdenvAdapters.useMoldLinker
209 ];
210 in
211 if stdenv'.hostPlatform.isLinux then custom else base;
212
213 env = {
214 ZSTD_SYS_USE_PKG_CONFIG = true;
215 FONTCONFIG_FILE = makeFontsConf {
216 fontDirectories = [
217 ../assets/fonts/lilex
218 ../assets/fonts/ibm-plex-sans
219 ];
220 };
221 ZED_UPDATE_EXPLANATION = "Zed has been installed using Nix. Auto-updates have thus been disabled.";
222 RELEASE_VERSION = version;
223 LK_CUSTOM_WEBRTC = pkgs.callPackage ./livekit-libwebrtc/package.nix { };
224 PROTOC = "${protobuf}/bin/protoc";
225
226 CARGO_PROFILE = profile;
227 # need to handle some profiles specially https://github.com/rust-lang/cargo/issues/11053
228 TARGET_DIR = "target/" + (if profile == "dev" then "debug" else profile);
229
230 # for some reason these deps being in buildInputs isn't enough, the only thing
231 # about them that's special is that they're manually dlopened at runtime
232 NIX_LDFLAGS = lib.optionalString stdenv'.hostPlatform.isLinux "-rpath ${
233 lib.makeLibraryPath [
234 gpu-lib
235 wayland
236 libva
237 ]
238 }";
239
240 NIX_OUTPATH_USED_AS_RANDOM_SEED = "norebuilds";
241 };
242
243 # prevent nix from removing the "unused" wayland/gpu-lib rpaths
244 dontPatchELF = stdenv'.hostPlatform.isLinux;
245
246 # TODO: try craneLib.cargoNextest separate output
247 # for now we're not worried about running our test suite (or tests for deps) in the nix sandbox
248 doCheck = false;
249
250 cargoVendorDir = craneLib.vendorCargoDeps {
251 inherit src cargoLock;
252 overrideVendorGitCheckout =
253 let
254 hasWebRtcSys = builtins.any (crate: crate.name == "webrtc-sys");
255 # we can't set $RUSTFLAGS because that clobbers the cargo config
256 # see https://github.com/rust-lang/cargo/issues/5376#issuecomment-2163350032
257 glesConfig = builtins.toFile "config.toml" ''
258 [target.'cfg(all())']
259 rustflags = ["--cfg", "gles"]
260 '';
261
262 # `webrtc-sys` expects a staticlib; nixpkgs' `livekit-webrtc` has been patched to
263 # produce a `dylib`... patching `webrtc-sys`'s build script is the easier option
264 # TODO: send livekit sdk a PR to make this configurable
265 postPatch = ''
266 substituteInPlace webrtc-sys/build.rs --replace-fail \
267 "cargo:rustc-link-lib=static=webrtc" "cargo:rustc-link-lib=dylib=webrtc"
268
269 substituteInPlace webrtc-sys/build.rs --replace-fail \
270 'add_gio_headers(&mut builder);' \
271 'for lib_name in ["glib-2.0", "gio-2.0"] {
272 if let Ok(lib) = pkg_config::Config::new().cargo_metadata(false).probe(lib_name) {
273 for path in lib.include_paths {
274 builder.include(&path);
275 }
276 }
277 }'
278 ''
279 + lib.optionalString withGLES ''
280 cat ${glesConfig} >> .cargo/config/config.toml
281 '';
282 in
283 crates: drv:
284 if hasWebRtcSys crates then
285 drv.overrideAttrs (o: {
286 postPatch = (o.postPatch or "") + postPatch;
287 })
288 else
289 drv;
290 };
291 };
292 cargoArtifacts = craneLib.buildDepsOnly commonArgs;
293in
294craneLib.buildPackage (
295 lib.recursiveUpdate commonArgs {
296 inherit cargoArtifacts;
297
298 dontUseCmakeConfigure = true;
299
300 # without the env var generate-licenses fails due to crane's fetchCargoVendor, see:
301 # https://github.com/zed-industries/zed/issues/19971#issuecomment-2688455390
302 # TODO: put this in a separate derivation that depends on src to avoid running it on every build
303 preBuild = ''
304 ALLOW_MISSING_LICENSES=yes bash script/generate-licenses
305 echo nightly > crates/zed/RELEASE_CHANNEL
306 '';
307
308 installPhase =
309 if stdenv.hostPlatform.isDarwin then
310 ''
311 runHook preInstall
312
313 pushd crates/zed
314 sed -i "s/package.metadata.bundle-nightly/package.metadata.bundle/" Cargo.toml
315 export CARGO_BUNDLE_SKIP_BUILD=true
316 app_path="$(cargo bundle --profile $CARGO_PROFILE | xargs)"
317 popd
318
319 mkdir -p $out/Applications $out/bin
320 # Zed expects git next to its own binary
321 ln -s ${git}/bin/git "$app_path/Contents/MacOS/git"
322 mv $TARGET_DIR/cli "$app_path/Contents/MacOS/cli"
323 mv "$app_path" $out/Applications/
324
325 # Physical location of the CLI must be inside the app bundle as this is used
326 # to determine which app to start
327 ln -s "$out/Applications/Zed Nightly.app/Contents/MacOS/cli" $out/bin/zed
328
329 runHook postInstall
330 ''
331 else
332 ''
333 runHook preInstall
334
335 mkdir -p $out/bin $out/libexec
336 cp $TARGET_DIR/zed $out/libexec/zed-editor
337 cp $TARGET_DIR/cli $out/bin/zed
338 ln -s $out/bin/zed $out/bin/zeditor # home-manager expects the CLI binary to be here
339
340
341 install -D "crates/zed/resources/app-icon-nightly@2x.png" \
342 "$out/share/icons/hicolor/1024x1024@2x/apps/zed.png"
343 install -D crates/zed/resources/app-icon-nightly.png \
344 $out/share/icons/hicolor/512x512/apps/zed.png
345
346 # TODO: icons should probably be named "zed-nightly"
347 (
348 export DO_STARTUP_NOTIFY="true"
349 export APP_CLI="zed"
350 export APP_ICON="zed"
351 export APP_NAME="Zed Nightly"
352 export APP_ARGS="%U"
353 mkdir -p "$out/share/applications"
354 ${lib.getExe envsubst} < "crates/zed/resources/zed.desktop.in" > "$out/share/applications/dev.zed.Zed-Nightly.desktop"
355 chmod +x "$out/share/applications/dev.zed.Zed-Nightly.desktop"
356 )
357
358 runHook postInstall
359 '';
360
361 # TODO: why isn't this also done on macOS?
362 postFixup = lib.optionalString stdenv.hostPlatform.isLinux ''
363 wrapProgram $out/libexec/zed-editor --suffix PATH : ${lib.makeBinPath [ nodejs_22 ]}
364 '';
365
366 meta = {
367 description = "High-performance, multiplayer code editor from the creators of Atom and Tree-sitter";
368 homepage = "https://zed.dev";
369 changelog = "https://zed.dev/releases/preview";
370 license = lib.licenses.gpl3Only;
371 mainProgram = "zed";
372 platforms = lib.platforms.linux ++ lib.platforms.darwin;
373 };
374 }
375)