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 [
88 cmake
89 copyDesktopItems
90 curl
91 perl
92 pkg-config
93 protobuf
94 cargo-about
95 rustPlatform.bindgenHook
96 ]
97 ++ lib.optionals stdenv'.hostPlatform.isLinux [ makeWrapper ]
98 ++ lib.optionals stdenv'.hostPlatform.isDarwin [
99 # TODO: move to overlay so it's usable in the shell
100 (cargo-bundle.overrideAttrs (
101 new: old: {
102 version = "0.6.1-zed";
103 src = fetchFromGitHub {
104 owner = "zed-industries";
105 repo = "cargo-bundle";
106 rev = "2be2669972dff3ddd4daf89a2cb29d2d06cad7c7";
107 hash = "sha256-cSvW0ND148AGdIGWg/ku0yIacVgW+9f1Nsi+kAQxVrI=";
108 };
109 # https://nixos.asia/en/buildRustPackage
110 cargoDeps = old.cargoDeps.overrideAttrs ({
111 inherit src;
112 name = "${new.pname}-${new.version}-vendor.tar.gz";
113 outputHash = "sha256-Q49FnXNHWhvbH1LtMUpXFcvGKu9VHwqOXXd+MjswO64=";
114 });
115 }
116 ))
117 ];
118
119 buildInputs =
120 [
121 curl
122 fontconfig
123 freetype
124 # TODO: need staticlib of this for linking the musl remote server.
125 # should make it a separate derivation/flake output
126 # see https://crane.dev/examples/cross-musl.html
127 libgit2
128 openssl
129 sqlite
130 zlib
131 zstd
132 ]
133 ++ lib.optionals stdenv'.hostPlatform.isLinux [
134 alsa-lib
135 libxkbcommon
136 wayland
137 gpu-lib
138 xorg.libxcb
139 ]
140 ++ lib.optionals stdenv'.hostPlatform.isDarwin [
141 apple-sdk_15
142 darwin.apple_sdk.frameworks.System
143 (darwinMinVersionHook "10.15")
144 ];
145
146 cargoExtraArgs = "-p zed -p cli --locked --features=gpui/runtime_shaders";
147
148 stdenv =
149 pkgs:
150 let
151 base = pkgs.llvmPackages.stdenv;
152 addBinTools = old: {
153 cc = old.cc.override {
154 inherit (pkgs.llvmPackages) bintools;
155 };
156 };
157 custom = lib.pipe base [
158 (stdenv: stdenv.override addBinTools)
159 pkgs.stdenvAdapters.useMoldLinker
160 ];
161 in
162 if stdenv'.hostPlatform.isLinux then custom else base;
163
164 env = {
165 ZSTD_SYS_USE_PKG_CONFIG = true;
166 FONTCONFIG_FILE = makeFontsConf {
167 fontDirectories = [
168 ../assets/fonts/plex-mono
169 ../assets/fonts/plex-sans
170 ];
171 };
172 ZED_UPDATE_EXPLANATION = "Zed has been installed using Nix. Auto-updates have thus been disabled.";
173 RELEASE_VERSION = version;
174 LK_CUSTOM_WEBRTC = livekit-libwebrtc;
175
176 CARGO_PROFILE = profile;
177 # need to handle some profiles specially https://github.com/rust-lang/cargo/issues/11053
178 TARGET_DIR = "target/" + (if profile == "dev" then "debug" else profile);
179
180 # for some reason these deps being in buildInputs isn't enough, the only thing
181 # about them that's special is that they're manually dlopened at runtime
182 NIX_LDFLAGS = lib.optionalString stdenv'.hostPlatform.isLinux "-rpath ${
183 lib.makeLibraryPath [
184 gpu-lib
185 wayland
186 ]
187 }";
188 };
189
190 # prevent nix from removing the "unused" wayland/gpu-lib rpaths
191 dontPatchELF = stdenv'.hostPlatform.isLinux;
192
193 # TODO: try craneLib.cargoNextest separate output
194 # for now we're not worried about running our test suite (or tests for deps) in the nix sandbox
195 doCheck = false;
196
197 cargoVendorDir = craneLib.vendorCargoDeps {
198 inherit src cargoLock;
199 overrideVendorGitCheckout =
200 let
201 hasWebRtcSys = builtins.any (crate: crate.name == "webrtc-sys");
202 # we can't set $RUSTFLAGS because that clobbers the cargo config
203 # see https://github.com/rust-lang/cargo/issues/5376#issuecomment-2163350032
204 glesConfig = builtins.toFile "config.toml" ''
205 [target.'cfg(all())']
206 rustflags = ["--cfg", "gles"]
207 '';
208
209 # `webrtc-sys` expects a staticlib; nixpkgs' `livekit-webrtc` has been patched to
210 # produce a `dylib`... patching `webrtc-sys`'s build script is the easier option
211 # TODO: send livekit sdk a PR to make this configurable
212 postPatch =
213 ''
214 substituteInPlace webrtc-sys/build.rs --replace-fail \
215 "cargo:rustc-link-lib=static=webrtc" "cargo:rustc-link-lib=dylib=webrtc"
216 ''
217 + lib.optionalString withGLES ''
218 cat ${glesConfig} >> .cargo/config/config.toml
219 '';
220 in
221 crates: drv:
222 if hasWebRtcSys crates then
223 drv.overrideAttrs (o: {
224 postPatch = (o.postPatch or "") + postPatch;
225 })
226 else
227 drv;
228 };
229 };
230 cargoArtifacts = craneLib.buildDepsOnly commonArgs;
231in
232craneLib.buildPackage (
233 lib.recursiveUpdate commonArgs {
234 inherit cargoArtifacts;
235
236 dontUseCmakeConfigure = true;
237
238 # without the env var generate-licenses fails due to crane's fetchCargoVendor, see:
239 # https://github.com/zed-industries/zed/issues/19971#issuecomment-2688455390
240 # TODO: put this in a separate derivation that depends on src to avoid running it on every build
241 preBuild = ''
242 ALLOW_MISSING_LICENSES=yes bash script/generate-licenses
243 echo nightly > crates/zed/RELEASE_CHANNEL
244 '';
245
246 installPhase =
247 if stdenv.hostPlatform.isDarwin then
248 ''
249 runHook preInstall
250
251 pushd crates/zed
252 sed -i "s/package.metadata.bundle-nightly/package.metadata.bundle/" Cargo.toml
253 export CARGO_BUNDLE_SKIP_BUILD=true
254 app_path="$(cargo bundle --profile $CARGO_PROFILE | xargs)"
255 popd
256
257 mkdir -p $out/Applications $out/bin
258 # Zed expects git next to its own binary
259 ln -s ${git}/bin/git "$app_path/Contents/MacOS/git"
260 mv $TARGET_DIR/cli "$app_path/Contents/MacOS/cli"
261 mv "$app_path" $out/Applications/
262
263 # Physical location of the CLI must be inside the app bundle as this is used
264 # to determine which app to start
265 ln -s "$out/Applications/Zed Nightly.app/Contents/MacOS/cli" $out/bin/zed
266
267 runHook postInstall
268 ''
269 else
270 ''
271 runHook preInstall
272
273 mkdir -p $out/bin $out/libexec
274 cp $TARGET_DIR/zed $out/libexec/zed-editor
275 cp $TARGET_DIR/cli $out/bin/zed
276
277 install -D "crates/zed/resources/app-icon-nightly@2x.png" \
278 "$out/share/icons/hicolor/1024x1024@2x/apps/zed.png"
279 install -D crates/zed/resources/app-icon-nightly.png \
280 $out/share/icons/hicolor/512x512/apps/zed.png
281
282 # TODO: icons should probably be named "zed-nightly"
283 (
284 export DO_STARTUP_NOTIFY="true"
285 export APP_CLI="zed"
286 export APP_ICON="zed"
287 export APP_NAME="Zed Nightly"
288 export APP_ARGS="%U"
289 mkdir -p "$out/share/applications"
290 ${lib.getExe envsubst} < "crates/zed/resources/zed.desktop.in" > "$out/share/applications/dev.zed.Zed-Nightly.desktop"
291 )
292
293 runHook postInstall
294 '';
295
296 # TODO: why isn't this also done on macOS?
297 postFixup = lib.optionalString stdenv.hostPlatform.isLinux ''
298 wrapProgram $out/libexec/zed-editor --suffix PATH : ${lib.makeBinPath [ nodejs_22 ]}
299 '';
300
301 meta = {
302 description = "High-performance, multiplayer code editor from the creators of Atom and Tree-sitter";
303 homepage = "https://zed.dev";
304 changelog = "https://zed.dev/releases/preview";
305 license = lib.licenses.gpl3Only;
306 mainProgram = "zed";
307 platforms = lib.platforms.linux ++ lib.platforms.darwin;
308 };
309 }
310)