diff --git a/pkgs/default.nix b/pkgs/default.nix index 71c248ca..5ff78e39 100644 --- a/pkgs/default.nix +++ b/pkgs/default.nix @@ -1,6 +1,7 @@ { pkgs, ... }: { screen-cap = pkgs.callPackage ./screen-cap/default.nix { }; + neovide = pkgs.callPackage ./neovide/package.nix { }; Fmt = pkgs.writeShellApplication { name = "Fmt"; runtimeInputs = with pkgs; [ diff --git a/pkgs/neovide/fetch-skia-externals.py b/pkgs/neovide/fetch-skia-externals.py new file mode 100644 index 00000000..83ef89cb --- /dev/null +++ b/pkgs/neovide/fetch-skia-externals.py @@ -0,0 +1,79 @@ +#!/usr/bin/env -S nix shell nixpkgs#python3 nixpkgs#nix-prefetch-git --command python3 + +import subprocess +import sys +import json +from typing import TypedDict + + +class FetchedJson(TypedDict): + url: str + rev: str + date: str + path: str + sha256: str + hash: str + fetchLFS: bool + fetchSubmodules: bool + deepClone: bool + leaveDotGit: bool + + +class ExternalDepVals(TypedDict): + url: str + rev: str + hash: str + + +ExternalDep = dict[str, ExternalDepVals] +Deps = dict[str, str] + + +def fetch_dep(url: str, rev: str) -> ExternalDepVals: + out = subprocess.run(["nix-prefetch-git", url, "--rev", rev], capture_output=True) + + if out.returncode != 0: + print( + f"Failed to fetch: '{url}@{rev}'!", + "======== Error ========", + out.stderr.decode(), + "=======================", + sep="\n", + file=sys.stderr, + ) + out.check_returncode() + + fetched_json: FetchedJson = json.loads(out.stdout) + return { + "url": fetched_json["url"], + "rev": fetched_json["rev"], + "hash": fetched_json["hash"], + } + + +# NOTE: copied from https://github.com/rust-skia/skia/blob/adf3a68b5e8424137861d61eae0b97bc2e528bbb/DEPS#L33-L46 +# These dependencies should be updated on every Neovide update +deps: Deps = { + "third_party/externals/expat": "https://chromium.googlesource.com/external/github.com/libexpat/libexpat.git@624da0f593bb8d7e146b9f42b06d8e6c80d032a3", + "third_party/externals/harfbuzz": "https://chromium.googlesource.com/external/github.com/harfbuzz/harfbuzz.git@a070f9ebbe88dc71b248af9731dd49ec93f4e6e6", + "third_party/externals/icu": "https://chromium.googlesource.com/chromium/deps/icu.git@364118a1d9da24bb5b770ac3d762ac144d6da5a4", + "third_party/externals/libjpeg-turbo": "https://chromium.googlesource.com/chromium/deps/libjpeg_turbo.git@ccfbe1c82a3b6dbe8647ceb36a3f9ee711fba3cf", + "third_party/externals/libpng": "https://skia.googlesource.com/third_party/libpng.git@ed217e3e601d8e462f7fd1e04bed43ac42212429", + "third_party/externals/wuffs": "https://skia.googlesource.com/external/github.com/google/wuffs-mirror-release-c.git@e3f919ccfe3ef542cfc983a82146070258fb57f8", + "third_party/externals/zlib": "https://chromium.googlesource.com/chromium/src/third_party/zlib@646b7f569718921d7d4b5b8e22572ff6c76f2596", +} + +output: ExternalDep = {} + +for dep_path, dep_url in deps.items(): + dep_name = dep_path.split("/")[-1] + url, rev = dep_url.split("@") + print( + f"Fetching Skia External '{dep_name}':\n URL: '{url}'\n REV: '{rev}'", + file=sys.stderr, + ) + fetched_json = fetch_dep(url, rev) + external_dep: ExternalDep = {dep_name: fetched_json} + output |= external_dep + +print(json.dumps(output, indent=2)) diff --git a/pkgs/neovide/package.nix b/pkgs/neovide/package.nix new file mode 100644 index 00000000..6100ad96 --- /dev/null +++ b/pkgs/neovide/package.nix @@ -0,0 +1,135 @@ +{ + lib, + rustPlatform, + clangStdenv, + fetchFromGitHub, + linkFarm, + fetchgit, + runCommand, + gn, + neovim, + ninja, + makeWrapper, + pkg-config, + python3, + removeReferencesTo, + apple-sdk_11, + cctools, + SDL2, + fontconfig, + xorg, + stdenv, + libglvnd, + libxkbcommon, + enableWayland ? stdenv.hostPlatform.isLinux, + wayland, +}: + +rustPlatform.buildRustPackage.override { stdenv = clangStdenv; } rec { + pname = "neovide"; + version = "0.14.0"; + + src = fetchFromGitHub { + owner = "neovide"; + repo = "neovide"; + rev = version; + hash = "sha256-4fdC/wChsCICLd69ZjK7IaCH7gDmXvfKllCnRNsdqYI="; + }; + + cargoHash = "sha256-CqnT9FEDzEMSais4dJg7zYVoSPNvIA09hmI0JE2YZIg="; + + SKIA_SOURCE_DIR = + let + repo = fetchFromGitHub { + owner = "rust-skia"; + repo = "skia"; + # see rust-skia:skia-bindings/Cargo.toml#package.metadata skia + rev = "m131-0.79.1"; + hash = "sha256-XqXfKNYSiECbN96WVWA67Vy4sPuVvg6KqHESjA8gFJM="; + }; + # The externals for skia are taken from skia/DEPS + externals = linkFarm "skia-externals" ( + lib.mapAttrsToList (name: value: { + inherit name; + path = fetchgit value; + }) (lib.importJSON ./skia-externals.json) + ); + in + runCommand "source" { } '' + cp -R ${repo} $out + chmod -R +w $out + ln -s ${externals} $out/third_party/externals + ''; + + SKIA_GN_COMMAND = "${gn}/bin/gn"; + SKIA_NINJA_COMMAND = "${ninja}/bin/ninja"; + + nativeBuildInputs = + [ + makeWrapper + pkg-config + python3 # skia + removeReferencesTo + ] + ++ lib.optionals stdenv.hostPlatform.isDarwin [ + cctools.libtool + ]; + + nativeCheckInputs = [ neovim ]; + + buildInputs = [ + SDL2 + fontconfig + rustPlatform.bindgenHook + ] ++ lib.optionals stdenv.hostPlatform.isDarwin [ apple-sdk_11 ]; + + postFixup = + let + libPath = lib.makeLibraryPath ( + [ + libglvnd + libxkbcommon + xorg.libXcursor + xorg.libXext + xorg.libXrandr + xorg.libXi + ] + ++ lib.optionals enableWayland [ wayland ] + ); + in + '' + # library skia embeds the path to its sources + remove-references-to -t "$SKIA_SOURCE_DIR" \ + $out/bin/neovide + + wrapProgram $out/bin/neovide \ + --prefix LD_LIBRARY_PATH : ${libPath} + ''; + + postInstall = + lib.optionalString stdenv.hostPlatform.isDarwin '' + mkdir -p $out/Applications + cp -r extra/osx/Neovide.app $out/Applications + ln -s $out/bin $out/Applications/Neovide.app/Contents/MacOS + '' + + lib.optionalString stdenv.hostPlatform.isLinux '' + for n in 16x16 32x32 48x48 256x256; do + install -m444 -D "assets/neovide-$n.png" \ + "$out/share/icons/hicolor/$n/apps/neovide.png" + done + install -m444 -Dt $out/share/icons/hicolor/scalable/apps assets/neovide.svg + install -m444 -Dt $out/share/applications assets/neovide.desktop + ''; + + disallowedReferences = [ SKIA_SOURCE_DIR ]; + + meta = with lib; { + description = "This is a simple graphical user interface for Neovim"; + mainProgram = "neovide"; + homepage = "https://github.com/neovide/neovide"; + changelog = "https://github.com/neovide/neovide/releases/tag/${version}"; + license = with licenses; [ mit ]; + maintainers = with maintainers; [ ck3d ]; + platforms = platforms.unix; + }; +} diff --git a/pkgs/neovide/skia-externals.json b/pkgs/neovide/skia-externals.json new file mode 100644 index 00000000..de3aa622 --- /dev/null +++ b/pkgs/neovide/skia-externals.json @@ -0,0 +1,37 @@ +{ + "expat": { + "url": "https://chromium.googlesource.com/external/github.com/libexpat/libexpat.git", + "rev": "624da0f593bb8d7e146b9f42b06d8e6c80d032a3", + "hash": "sha256-Iwu9+i/0vsPyu6pOWFxjNNblVxMl6bTPW5eWyaju4Mg=" + }, + "harfbuzz": { + "url": "https://chromium.googlesource.com/external/github.com/harfbuzz/harfbuzz.git", + "rev": "a070f9ebbe88dc71b248af9731dd49ec93f4e6e6", + "hash": "sha256-DSjzCLqMmlYCz2agrrY2iwr+VdpxukE/QbhzXmVOVpw=" + }, + "icu": { + "url": "https://chromium.googlesource.com/chromium/deps/icu.git", + "rev": "364118a1d9da24bb5b770ac3d762ac144d6da5a4", + "hash": "sha256-frsmwYMiFixEULsE91x5+p98DvkyC0s0fNupqjoRnvg=" + }, + "libjpeg-turbo": { + "url": "https://chromium.googlesource.com/chromium/deps/libjpeg_turbo.git", + "rev": "ccfbe1c82a3b6dbe8647ceb36a3f9ee711fba3cf", + "hash": "sha256-UhDKDfAgcCS92R2EvxKpoiJMvakUDQgyHu2k/xeE7do=" + }, + "libpng": { + "url": "https://skia.googlesource.com/third_party/libpng.git", + "rev": "ed217e3e601d8e462f7fd1e04bed43ac42212429", + "hash": "sha256-Mo1M8TuVaoSIb7Hy2u6zgjZ1DKgpmgNmGRP6dGg/aTs=" + }, + "wuffs": { + "url": "https://skia.googlesource.com/external/github.com/google/wuffs-mirror-release-c.git", + "rev": "e3f919ccfe3ef542cfc983a82146070258fb57f8", + "hash": "sha256-373d2F/STcgCHEq+PO+SCHrKVOo6uO1rqqwRN5eeBCw=" + }, + "zlib": { + "url": "https://chromium.googlesource.com/chromium/src/third_party/zlib", + "rev": "646b7f569718921d7d4b5b8e22572ff6c76f2596", + "hash": "sha256-jNj6SuTZ5/a7crtYhxW3Q/TlfRMNMfYIVxDlr7bYdzQ=" + } +}