build.nix

  1{
  2  lib,
  3  rustPlatform,
  4  fetchpatch,
  5  clang,
  6  cmake,
  7  copyDesktopItems,
  8  curl,
  9  perl,
 10  pkg-config,
 11  protobuf,
 12  fontconfig,
 13  freetype,
 14  libgit2,
 15  openssl,
 16  sqlite,
 17  zlib,
 18  zstd,
 19  alsa-lib,
 20  libxkbcommon,
 21  wayland,
 22  libglvnd,
 23  xorg,
 24  stdenv,
 25  makeFontsConf,
 26  vulkan-loader,
 27  envsubst,
 28  cargo-about,
 29  versionCheckHook,
 30  cargo-bundle,
 31  git,
 32  apple-sdk_15,
 33  darwinMinVersionHook,
 34  makeWrapper,
 35  nodejs_22,
 36  nix-gitignore,
 37
 38  withGLES ? false,
 39}:
 40
 41assert withGLES -> stdenv.hostPlatform.isLinux;
 42
 43let
 44  includeFilter =
 45    path: type:
 46    let
 47      baseName = baseNameOf (toString path);
 48      parentDir = dirOf path;
 49      inRootDir = type == "directory" && parentDir == ../.;
 50    in
 51    !(
 52      inRootDir
 53      && (
 54        baseName == "docs"
 55        || baseName == ".github"
 56        || baseName == "script"
 57        || baseName == ".git"
 58        || baseName == "target"
 59      )
 60    );
 61in
 62rustPlatform.buildRustPackage rec {
 63  pname = "zed-editor";
 64  version = "nightly";
 65
 66  src = lib.cleanSourceWith {
 67    src = nix-gitignore.gitignoreSource [ ] ../.;
 68    filter = includeFilter;
 69    name = "source";
 70  };
 71
 72  patches =
 73    [
 74      # Zed uses cargo-install to install cargo-about during the script execution.
 75      # We provide cargo-about ourselves and can skip this step.
 76      # Until https://github.com/zed-industries/zed/issues/19971 is fixed,
 77      # we also skip any crate for which the license cannot be determined.
 78      (fetchpatch {
 79        url = "https://raw.githubusercontent.com/NixOS/nixpkgs/1fd02d90c6c097f91349df35da62d36c19359ba7/pkgs/by-name/ze/zed-editor/0001-generate-licenses.patch";
 80        hash = "sha256-cLgqLDXW1JtQ2OQFLd5UolAjfy7bMoTw40lEx2jA2pk=";
 81      })
 82    ]
 83    ++ lib.optionals stdenv.hostPlatform.isDarwin [
 84      # Livekit requires Swift 6
 85      # We need this until livekit-rust sdk is used
 86      (fetchpatch {
 87        url = "https://raw.githubusercontent.com/NixOS/nixpkgs/1fd02d90c6c097f91349df35da62d36c19359ba7/pkgs/by-name/ze/zed-editor/0002-disable-livekit-darwin.patch";
 88        hash = "sha256-whZ7RaXv8hrVzWAveU3qiBnZSrvGNEHTuyNhxgMIo5w=";
 89      })
 90    ];
 91
 92  useFetchCargoVendor = true;
 93  cargoHash = "sha256-KURM1W9UP65BU9gbvEBgQj3jwSYfQT7X18gcSmOMguI=";
 94
 95  nativeBuildInputs =
 96    [
 97      clang
 98      cmake
 99      copyDesktopItems
100      curl
101      perl
102      pkg-config
103      protobuf
104      rustPlatform.bindgenHook
105      cargo-about
106    ]
107    ++ lib.optionals stdenv.hostPlatform.isLinux [ makeWrapper ]
108    ++ lib.optionals stdenv.hostPlatform.isDarwin [ cargo-bundle ];
109
110  dontUseCmakeConfigure = true;
111
112  buildInputs =
113    [
114      curl
115      fontconfig
116      freetype
117      libgit2
118      openssl
119      sqlite
120      zlib
121      zstd
122    ]
123    ++ lib.optionals stdenv.hostPlatform.isLinux [
124      alsa-lib
125      libxkbcommon
126      wayland
127      xorg.libxcb
128    ]
129    ++ lib.optionals stdenv.hostPlatform.isDarwin [
130      apple-sdk_15
131      (darwinMinVersionHook "10.15")
132    ];
133
134  cargoBuildFlags = [
135    "--package=zed"
136    "--package=cli"
137  ];
138
139  buildFeatures = lib.optionals stdenv.hostPlatform.isDarwin [ "gpui/runtime_shaders" ];
140
141  env = {
142    ZSTD_SYS_USE_PKG_CONFIG = true;
143    FONTCONFIG_FILE = makeFontsConf {
144      fontDirectories = [
145        "${src}/assets/fonts/plex-mono"
146        "${src}/assets/fonts/plex-sans"
147      ];
148    };
149    ZED_UPDATE_EXPLANATION = "Zed has been installed using Nix. Auto-updates have thus been disabled.";
150    RELEASE_VERSION = version;
151  };
152
153  RUSTFLAGS = if withGLES then "--cfg gles" else "";
154  gpu-lib = if withGLES then libglvnd else vulkan-loader;
155
156  preBuild = ''
157    bash script/generate-licenses
158  '';
159
160  postFixup = lib.optionalString stdenv.hostPlatform.isLinux ''
161    patchelf --add-rpath ${gpu-lib}/lib $out/libexec/*
162    patchelf --add-rpath ${wayland}/lib $out/libexec/*
163    wrapProgram $out/libexec/zed-editor --suffix PATH : ${lib.makeBinPath [ nodejs_22 ]}
164  '';
165
166  preCheck = ''
167    export HOME=$(mktemp -d);
168  '';
169
170  checkFlags =
171    [
172      # Flaky: unreliably fails on certain hosts (including Hydra)
173      "--skip=zed::tests::test_window_edit_state_restoring_enabled"
174    ]
175    ++ lib.optionals stdenv.hostPlatform.isLinux [
176      # Fails on certain hosts (including Hydra) for unclear reason
177      "--skip=test_open_paths_action"
178    ];
179
180  installPhase =
181    if stdenv.hostPlatform.isDarwin then
182      ''
183        runHook preInstall
184
185        # cargo-bundle expects the binary in target/release
186        mv target/${stdenv.hostPlatform.rust.cargoShortTarget}/release/zed target/release/zed
187
188        pushd crates/zed
189
190        # Note that this is GNU sed, while Zed's bundle-mac uses BSD sed
191        sed -i "s/package.metadata.bundle-stable/package.metadata.bundle/" Cargo.toml
192        export CARGO_BUNDLE_SKIP_BUILD=true
193        app_path=$(cargo bundle --release | xargs)
194
195        # We're not using the fork of cargo-bundle, so we must manually append plist extensions
196        # Remove closing tags from Info.plist (last two lines)
197        head -n -2 $app_path/Contents/Info.plist > Info.plist
198        # Append extensions
199        cat resources/info/*.plist >> Info.plist
200        # Add closing tags
201        printf "</dict>\n</plist>\n" >> Info.plist
202        mv Info.plist $app_path/Contents/Info.plist
203
204        popd
205
206        mkdir -p $out/Applications $out/bin
207        # Zed expects git next to its own binary
208        ln -s ${git}/bin/git $app_path/Contents/MacOS/git
209        mv target/${stdenv.hostPlatform.rust.cargoShortTarget}/release/cli $app_path/Contents/MacOS/cli
210        mv $app_path $out/Applications/
211
212        # Physical location of the CLI must be inside the app bundle as this is used
213        # to determine which app to start
214        ln -s $out/Applications/Zed.app/Contents/MacOS/cli $out/bin/zed
215
216        runHook postInstall
217      ''
218    else
219      ''
220        runHook preInstall
221
222        mkdir -p $out/bin $out/libexec
223        cp target/${stdenv.hostPlatform.rust.cargoShortTarget}/release/zed $out/libexec/zed-editor
224        cp target/${stdenv.hostPlatform.rust.cargoShortTarget}/release/cli $out/bin/zed
225
226        install -D ${src}/crates/zed/resources/app-icon@2x.png $out/share/icons/hicolor/1024x1024@2x/apps/zed.png
227        install -D ${src}/crates/zed/resources/app-icon.png $out/share/icons/hicolor/512x512/apps/zed.png
228
229        # extracted from https://github.com/zed-industries/zed/blob/v0.141.2/script/bundle-linux (envsubst)
230        # and https://github.com/zed-industries/zed/blob/v0.141.2/script/install.sh (final desktop file name)
231        (
232          export DO_STARTUP_NOTIFY="true"
233          export APP_CLI="zed"
234          export APP_ICON="zed"
235          export APP_NAME="Zed"
236          export APP_ARGS="%U"
237          mkdir -p "$out/share/applications"
238          ${lib.getExe envsubst} < "crates/zed/resources/zed.desktop.in" > "$out/share/applications/dev.zed.Zed.desktop"
239        )
240
241        runHook postInstall
242      '';
243
244  nativeInstallCheckInputs = [
245    versionCheckHook
246  ];
247
248  meta = {
249    description = "High-performance, multiplayer code editor from the creators of Atom and Tree-sitter";
250    homepage = "https://zed.dev";
251    changelog = "https://zed.dev/releases/preview";
252    license = lib.licenses.gpl3Only;
253    mainProgram = "zed";
254    platforms = lib.platforms.linux ++ lib.platforms.darwin;
255  };
256}