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