From 4564da28757d744364ff12dd3c7b43155d75f84a Mon Sep 17 00:00:00 2001 From: Stanislav Alekseev <43210583+WeetHet@users.noreply.github.com> Date: Wed, 27 Nov 2024 20:22:17 +0200 Subject: [PATCH] Improve Nix package and shell (#21075) With an addition of useFetchCargoVendor, crane becomes less necessary for our use. This reuses the package from nixpkgs as well as creating a better devshell that both work on macOS. I use Xcode's SDKROOT and DEVELOPER_DIR to point the swift in the livekit client crate to a correct sdk when using a devshell. Devshell should work without that once apple releases sources for the 15.1 SDK but for now this is an easy fix This also replaces fenix with rust-overlay because of issues with the out-of-sandbox access I've noticed fenix installed toolchains have Release Notes: - N/A --- .envrc | 2 + flake.lock | 70 +++--------- flake.nix | 81 ++++++------- nix/build.nix | 307 ++++++++++++++++++++++++++++++++++---------------- nix/shell.nix | 104 +++++++++-------- 5 files changed, 326 insertions(+), 238 deletions(-) create mode 100644 .envrc diff --git a/.envrc b/.envrc new file mode 100644 index 0000000000..082c01feeb --- /dev/null +++ b/.envrc @@ -0,0 +1,2 @@ +watch_file nix/shell.nix +use flake diff --git a/flake.lock b/flake.lock index 5666e73569..4011b38c4b 100644 --- a/flake.lock +++ b/flake.lock @@ -1,41 +1,5 @@ { "nodes": { - "crane": { - "locked": { - "lastModified": 1727060013, - "narHash": "sha256-/fC5YlJy4IoAW9GhkJiwyzk0K/gQd9Qi4rRcoweyG9E=", - "owner": "ipetkov", - "repo": "crane", - "rev": "6b40cc876c929bfe1e3a24bf538ce3b5622646ba", - "type": "github" - }, - "original": { - "owner": "ipetkov", - "repo": "crane", - "type": "github" - } - }, - "fenix": { - "inputs": { - "nixpkgs": [ - "nixpkgs" - ], - "rust-analyzer-src": "rust-analyzer-src" - }, - "locked": { - "lastModified": 1727073227, - "narHash": "sha256-1kmkEQmFfGVuPBasqSZrNThqyMDV1SzTalQdRZxtDRs=", - "owner": "nix-community", - "repo": "fenix", - "rev": "88cc292eb3c689073c784d6aecc0edbd47e12881", - "type": "github" - }, - "original": { - "owner": "nix-community", - "repo": "fenix", - "type": "github" - } - }, "flake-compat": { "locked": { "lastModified": 1696426674, @@ -53,11 +17,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1726937504, - "narHash": "sha256-bvGoiQBvponpZh8ClUcmJ6QnsNKw0EMrCQJARK3bI1c=", + "lastModified": 1732014248, + "narHash": "sha256-y/MEyuJ5oBWrWAic/14LaIr/u5E0wRVzyYsouYY3W6w=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "9357f4f23713673f310988025d9dc261c20e70c6", + "rev": "23e89b7da85c3640bbc2173fe04f4bd114342367", "type": "github" }, "original": { @@ -69,26 +33,28 @@ }, "root": { "inputs": { - "crane": "crane", - "fenix": "fenix", "flake-compat": "flake-compat", - "nixpkgs": "nixpkgs" + "nixpkgs": "nixpkgs", + "rust-overlay": "rust-overlay" } }, - "rust-analyzer-src": { - "flake": false, + "rust-overlay": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, "locked": { - "lastModified": 1726443025, - "narHash": "sha256-nCmG4NJpwI0IoIlYlwtDwVA49yuspA2E6OhfCOmiArQ=", - "owner": "rust-lang", - "repo": "rust-analyzer", - "rev": "94b526fc86eaa0e90fb4d54a5ba6313aa1e9b269", + "lastModified": 1732242723, + "narHash": "sha256-NWI8csIK0ujFlFuEXKnoc+7hWoCiEtINK9r48LUUMeU=", + "owner": "oxalica", + "repo": "rust-overlay", + "rev": "a229311fcb45b88a95fdfa5cecd8349c809a272a", "type": "github" }, "original": { - "owner": "rust-lang", - "ref": "nightly", - "repo": "rust-analyzer", + "owner": "oxalica", + "repo": "rust-overlay", "type": "github" } } diff --git a/flake.nix b/flake.nix index 2ee86c4466..3258522eb4 100644 --- a/flake.nix +++ b/flake.nix @@ -3,60 +3,61 @@ inputs = { nixpkgs.url = "github:NixOS/nixpkgs?ref=nixos-unstable"; - fenix = { - url = "github:nix-community/fenix"; + rust-overlay = { + url = "github:oxalica/rust-overlay"; inputs.nixpkgs.follows = "nixpkgs"; }; - crane.url = "github:ipetkov/crane"; flake-compat.url = "github:edolstra/flake-compat"; }; - outputs = { - nixpkgs, - crane, - fenix, - ... - }: let - systems = ["x86_64-linux" "aarch64-linux"]; + outputs = + { nixpkgs, rust-overlay, ... }: + let + systems = [ + "x86_64-linux" + "x86_64-darwin" + "aarch64-linux" + "aarch64-darwin" + ]; - overlays = { - fenix = fenix.overlays.default; - rust-toolchain = final: prev: { - rustToolchain = final.fenix.stable.toolchain; - }; - zed-editor = final: prev: { - zed-editor = final.callPackage ./nix/build.nix { - craneLib = (crane.mkLib final).overrideToolchain final.rustToolchain; - rustPlatform = final.makeRustPlatform { - inherit (final.rustToolchain) cargo rustc; + overlays = { + rust-overlay = rust-overlay.overlays.default; + rust-toolchain = final: prev: { + rustToolchain = final.rust-bin.fromRustupToolchainFile ./rust-toolchain.toml; + }; + zed-editor = final: prev: { + zed-editor = final.callPackage ./nix/build.nix { + rustPlatform = final.makeRustPlatform { + cargo = final.rustToolchain; + rustc = final.rustToolchain; + }; }; }; }; - }; - mkPkgs = system: - import nixpkgs { - inherit system; - overlays = builtins.attrValues overlays; - }; + mkPkgs = + system: + import nixpkgs { + inherit system; + overlays = builtins.attrValues overlays; + }; - forAllSystems = f: nixpkgs.lib.genAttrs systems (system: f (mkPkgs system)); - in { - packages = forAllSystems (pkgs: { - zed-editor = pkgs.zed-editor; - default = pkgs.zed-editor; - }); + forAllSystems = f: nixpkgs.lib.genAttrs systems (system: f (mkPkgs system)); + in + { + packages = forAllSystems (pkgs: { + zed-editor = pkgs.zed-editor; + default = pkgs.zed-editor; + }); - devShells = forAllSystems (pkgs: { - default = import ./nix/shell.nix {inherit pkgs;}; - }); + devShells = forAllSystems (pkgs: { + default = import ./nix/shell.nix { inherit pkgs; }; + }); - formatter = forAllSystems (pkgs: pkgs.alejandra); + formatter = forAllSystems (pkgs: pkgs.nixfmt-rfc-style); - overlays = - overlays - // { + overlays = overlays // { default = nixpkgs.lib.composeManyExtensions (builtins.attrValues overlays); }; - }; + }; } diff --git a/nix/build.nix b/nix/build.nix index 4782c9a56f..903f9790c7 100644 --- a/nix/build.nix +++ b/nix/build.nix @@ -1,10 +1,9 @@ { lib, - craneLib, rustPlatform, + fetchpatch, clang, - llvmPackages_18, - mold-wrapped, + cmake, copyDesktopItems, curl, perl, @@ -22,122 +21,236 @@ wayland, libglvnd, xorg, + stdenv, makeFontsConf, vulkan-loader, envsubst, - stdenvAdapters, + cargo-about, + versionCheckHook, + cargo-bundle, + git, + apple-sdk_15, + darwinMinVersionHook, + makeWrapper, + nodejs_22, nix-gitignore, + withGLES ? false, - cmake, -}: let - includeFilter = path: type: let - baseName = baseNameOf (toString path); - parentDir = dirOf path; - inRootDir = type == "directory" && parentDir == ../.; - in - !(inRootDir && (baseName == "docs" || baseName == ".github" || baseName == "script" || baseName == ".git" || baseName == "target")); +}: + +assert withGLES -> stdenv.hostPlatform.isLinux; + +let + includeFilter = + path: type: + let + baseName = baseNameOf (toString path); + parentDir = dirOf path; + inRootDir = type == "directory" && parentDir == ../.; + in + !( + inRootDir + && ( + baseName == "docs" + || baseName == ".github" + || baseName == "script" + || baseName == ".git" + || baseName == "target" + ) + ); +in +rustPlatform.buildRustPackage rec { + pname = "zed-editor"; + version = "nightly"; src = lib.cleanSourceWith { - src = nix-gitignore.gitignoreSource [] ../.; + src = nix-gitignore.gitignoreSource [ ] ../.; filter = includeFilter; name = "source"; }; - stdenv = stdenvAdapters.useMoldLinker llvmPackages_18.stdenv; + patches = + [ + # Zed uses cargo-install to install cargo-about during the script execution. + # We provide cargo-about ourselves and can skip this step. + # Until https://github.com/zed-industries/zed/issues/19971 is fixed, + # we also skip any crate for which the license cannot be determined. + (fetchpatch { + url = "https://raw.githubusercontent.com/NixOS/nixpkgs/1fd02d90c6c097f91349df35da62d36c19359ba7/pkgs/by-name/ze/zed-editor/0001-generate-licenses.patch"; + hash = "sha256-cLgqLDXW1JtQ2OQFLd5UolAjfy7bMoTw40lEx2jA2pk="; + }) + ] + ++ lib.optionals stdenv.hostPlatform.isDarwin [ + # Livekit requires Swift 6 + # We need this until livekit-rust sdk is used + (fetchpatch { + url = "https://raw.githubusercontent.com/NixOS/nixpkgs/1fd02d90c6c097f91349df35da62d36c19359ba7/pkgs/by-name/ze/zed-editor/0002-disable-livekit-darwin.patch"; + hash = "sha256-whZ7RaXv8hrVzWAveU3qiBnZSrvGNEHTuyNhxgMIo5w="; + }) + ]; - commonArgs = - craneLib.crateNameFromCargoToml {cargoToml = ../crates/zed/Cargo.toml;} - // { - inherit src stdenv; + useFetchCargoVendor = true; + cargoHash = "sha256-xL/EBe3+rlaPwU2zZyQtsZNHGBjzAD8ZCWrQXCQVxm8="; - nativeBuildInputs = [ - clang - copyDesktopItems - curl - mold-wrapped - perl - pkg-config - protobuf - rustPlatform.bindgenHook - cmake + nativeBuildInputs = + [ + clang + cmake + copyDesktopItems + curl + perl + pkg-config + protobuf + rustPlatform.bindgenHook + cargo-about + ] + ++ lib.optionals stdenv.hostPlatform.isLinux [ makeWrapper ] + ++ lib.optionals stdenv.hostPlatform.isDarwin [ cargo-bundle ]; + + dontUseCmakeConfigure = true; + + buildInputs = + [ + curl + fontconfig + freetype + libgit2 + openssl + sqlite + zlib + zstd + ] + ++ lib.optionals stdenv.hostPlatform.isLinux [ + alsa-lib + libxkbcommon + wayland + xorg.libxcb + ] + ++ lib.optionals stdenv.hostPlatform.isDarwin [ + apple-sdk_15 + (darwinMinVersionHook "10.15") + ]; + + cargoBuildFlags = [ + "--package=zed" + "--package=cli" + ]; + + buildFeatures = lib.optionals stdenv.hostPlatform.isDarwin [ "gpui/runtime_shaders" ]; + + env = { + ZSTD_SYS_USE_PKG_CONFIG = true; + FONTCONFIG_FILE = makeFontsConf { + fontDirectories = [ + "${src}/assets/fonts/plex-mono" + "${src}/assets/fonts/plex-sans" ]; - - buildInputs = [ - curl - fontconfig - freetype - libgit2 - openssl - sqlite - zlib - zstd - - alsa-lib - libxkbcommon - wayland - xorg.libxcb - ]; - - ZSTD_SYS_USE_PKG_CONFIG = true; - FONTCONFIG_FILE = makeFontsConf { - fontDirectories = [ - "../assets/fonts/zed-mono" - "../assets/fonts/zed-sans" - ]; - }; - ZED_UPDATE_EXPLANATION = "zed has been installed using nix. Auto-updates have thus been disabled."; }; + ZED_UPDATE_EXPLANATION = "Zed has been installed using Nix. Auto-updates have thus been disabled."; + RELEASE_VERSION = version; + }; - cargoArtifacts = craneLib.buildDepsOnly commonArgs; + RUSTFLAGS = if withGLES then "--cfg gles" else ""; + gpu-lib = if withGLES then libglvnd else vulkan-loader; - gpu-lib = - if withGLES - then libglvnd - else vulkan-loader; + preBuild = '' + bash script/generate-licenses + ''; - zed = craneLib.buildPackage (commonArgs - // { - inherit cargoArtifacts; - cargoExtraArgs = "--package=zed --package=cli"; - buildFeatures = ["gpui/runtime_shaders"]; - doCheck = false; + postFixup = lib.optionalString stdenv.hostPlatform.isLinux '' + patchelf --add-rpath ${gpu-lib}/lib $out/libexec/* + patchelf --add-rpath ${wayland}/lib $out/libexec/* + wrapProgram $out/libexec/zed-editor --suffix PATH : ${lib.makeBinPath [ nodejs_22 ]} + ''; - RUSTFLAGS = - if withGLES - then "--cfg gles" - else ""; + preCheck = '' + export HOME=$(mktemp -d); + ''; - postFixup = '' - patchelf --add-rpath ${gpu-lib}/lib $out/libexec/* - patchelf --add-rpath ${wayland}/lib $out/libexec/* - ''; + checkFlags = + [ + # Flaky: unreliably fails on certain hosts (including Hydra) + "--skip=zed::tests::test_window_edit_state_restoring_enabled" + ] + ++ lib.optionals stdenv.hostPlatform.isLinux [ + # Fails on certain hosts (including Hydra) for unclear reason + "--skip=test_open_paths_action" + ]; + + installPhase = + if stdenv.hostPlatform.isDarwin then + '' + runHook preInstall + + # cargo-bundle expects the binary in target/release + mv target/${stdenv.hostPlatform.rust.cargoShortTarget}/release/zed target/release/zed + + pushd crates/zed + + # Note that this is GNU sed, while Zed's bundle-mac uses BSD sed + sed -i "s/package.metadata.bundle-stable/package.metadata.bundle/" Cargo.toml + export CARGO_BUNDLE_SKIP_BUILD=true + app_path=$(cargo bundle --release | xargs) + + # We're not using the fork of cargo-bundle, so we must manually append plist extensions + # Remove closing tags from Info.plist (last two lines) + head -n -2 $app_path/Contents/Info.plist > Info.plist + # Append extensions + cat resources/info/*.plist >> Info.plist + # Add closing tags + printf "\n\n" >> Info.plist + mv Info.plist $app_path/Contents/Info.plist + + popd + + mkdir -p $out/Applications $out/bin + # Zed expects git next to its own binary + ln -s ${git}/bin/git $app_path/Contents/MacOS/git + mv target/${stdenv.hostPlatform.rust.cargoShortTarget}/release/cli $app_path/Contents/MacOS/cli + mv $app_path $out/Applications/ + + # Physical location of the CLI must be inside the app bundle as this is used + # to determine which app to start + ln -s $out/Applications/Zed.app/Contents/MacOS/cli $out/bin/zed + + runHook postInstall + '' + else + '' + runHook preInstall - postInstall = '' mkdir -p $out/bin $out/libexec - mv $out/bin/zed $out/libexec/zed-editor - mv $out/bin/cli $out/bin/zed + cp target/${stdenv.hostPlatform.rust.cargoShortTarget}/release/zed $out/libexec/zed-editor + cp target/${stdenv.hostPlatform.rust.cargoShortTarget}/release/cli $out/bin/zed - install -D crates/zed/resources/app-icon@2x.png $out/share/icons/hicolor/1024x1024@2x/apps/zed.png - install -D crates/zed/resources/app-icon.png $out/share/icons/hicolor/512x512/apps/zed.png + install -D ${src}/crates/zed/resources/app-icon@2x.png $out/share/icons/hicolor/1024x1024@2x/apps/zed.png + install -D ${src}/crates/zed/resources/app-icon.png $out/share/icons/hicolor/512x512/apps/zed.png - export DO_STARTUP_NOTIFY="true" - export APP_CLI="zed" - export APP_ICON="zed" - export APP_NAME="Zed" - export APP_ARGS="%U" - mkdir -p "$out/share/applications" - ${lib.getExe envsubst} < "crates/zed/resources/zed.desktop.in" > "$out/share/applications/dev.zed.Zed.desktop" + # extracted from https://github.com/zed-industries/zed/blob/v0.141.2/script/bundle-linux (envsubst) + # and https://github.com/zed-industries/zed/blob/v0.141.2/script/install.sh (final desktop file name) + ( + export DO_STARTUP_NOTIFY="true" + export APP_CLI="zed" + export APP_ICON="zed" + export APP_NAME="Zed" + export APP_ARGS="%U" + mkdir -p "$out/share/applications" + ${lib.getExe envsubst} < "crates/zed/resources/zed.desktop.in" > "$out/share/applications/dev.zed.Zed.desktop" + ) + + runHook postInstall ''; - }); -in - zed - // { - meta = with lib; { - description = "High-performance, multiplayer code editor from the creators of Atom and Tree-sitter"; - homepage = "https://zed.dev"; - changelog = "https://zed.dev/releases/preview"; - license = licenses.gpl3Only; - mainProgram = "zed"; - platforms = platforms.linux; - }; - } + + nativeInstallCheckInputs = [ + versionCheckHook + ]; + + meta = { + description = "High-performance, multiplayer code editor from the creators of Atom and Tree-sitter"; + homepage = "https://zed.dev"; + changelog = "https://zed.dev/releases/preview"; + license = lib.licenses.gpl3Only; + mainProgram = "zed"; + platforms = lib.platforms.linux ++ lib.platforms.darwin; + }; +} diff --git a/nix/shell.nix b/nix/shell.nix index e0b4018778..75ceb0d8e3 100644 --- a/nix/shell.nix +++ b/nix/shell.nix @@ -1,51 +1,57 @@ -{pkgs ? import {}}: let - stdenv = pkgs.stdenvAdapters.useMoldLinker pkgs.llvmPackages_18.stdenv; +{ + pkgs ? import { }, +}: +let + inherit (pkgs) lib; in - if pkgs.stdenv.isDarwin - then - # See https://github.com/NixOS/nixpkgs/issues/320084 - throw "zed: nix dev-shell isn't supported on darwin yet." - else let - buildInputs = with pkgs; [ - curl - fontconfig - freetype - libgit2 - openssl - sqlite - zlib - zstd - alsa-lib - libxkbcommon - wayland - xorg.libxcb - vulkan-loader - rustToolchain +pkgs.mkShell rec { + packages = [ + pkgs.clang + pkgs.curl + pkgs.cmake + pkgs.perl + pkgs.pkg-config + pkgs.protobuf + pkgs.rustPlatform.bindgenHook + pkgs.rust-analyzer + ]; + + buildInputs = + [ + pkgs.curl + pkgs.fontconfig + pkgs.freetype + pkgs.libgit2 + pkgs.openssl + pkgs.sqlite + pkgs.zlib + pkgs.zstd + pkgs.rustToolchain + ] + ++ lib.optionals pkgs.stdenv.hostPlatform.isLinux [ + pkgs.alsa-lib + pkgs.libxkbcommon + ] + ++ lib.optional pkgs.stdenv.hostPlatform.isDarwin pkgs.apple-sdk_15; + + # We set SDKROOT and DEVELOPER_DIR to the Xcode ones instead of the nixpkgs ones, + # because we need Swift 6.0 and nixpkgs doesn't have it. + # Xcode is required for development anyways + shellHook = + '' + export LD_LIBRARY_PATH="${lib.makeLibraryPath buildInputs}:$LD_LIBRARY_PATH" + export PROTOC="${pkgs.protobuf}/bin/protoc" + '' + + lib.optionalString pkgs.stdenv.hostPlatform.isDarwin '' + export SDKROOT="/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk"; + export DEVELOPER_DIR="/Applications/Xcode.app/Contents/Developer"; + ''; + + FONTCONFIG_FILE = pkgs.makeFontsConf { + fontDirectories = [ + "./assets/fonts/zed-mono" + "./assets/fonts/zed-sans" ]; - in - pkgs.mkShell.override {inherit stdenv;} { - nativeBuildInputs = with pkgs; [ - clang - curl - cmake - perl - pkg-config - protobuf - rustPlatform.bindgenHook - ]; - - inherit buildInputs; - - shellHook = '' - export LD_LIBRARY_PATH="${pkgs.lib.makeLibraryPath buildInputs}:$LD_LIBRARY_PATH" - export PROTOC="${pkgs.protobuf}/bin/protoc" - ''; - - FONTCONFIG_FILE = pkgs.makeFontsConf { - fontDirectories = [ - "./assets/fonts/zed-mono" - "./assets/fonts/zed-sans" - ]; - }; - ZSTD_SYS_USE_PKG_CONFIG = true; - } + }; + ZSTD_SYS_USE_PKG_CONFIG = true; +}