From f55a79151b3def701f38b2c512a3c12d83c42df7 Mon Sep 17 00:00:00 2001 From: Leah Amelia Chen Date: Sat, 14 Dec 2024 17:28:58 +0100 Subject: [PATCH] itch: build from source electron-packager was a *pain* to figure out. Please don't subject me to this ever again. --- pkgs/by-name/it/itch/package.nix | 174 +++++++++++------- .../by-name/it/itch/patch-build-scripts.patch | 69 +++++++ 2 files changed, 180 insertions(+), 63 deletions(-) create mode 100644 pkgs/by-name/it/itch/patch-build-scripts.patch diff --git a/pkgs/by-name/it/itch/package.nix b/pkgs/by-name/it/itch/package.nix index c4ecd6f509502..2cf5fda258e58 100644 --- a/pkgs/by-name/it/itch/package.nix +++ b/pkgs/by-name/it/itch/package.nix @@ -1,55 +1,123 @@ { lib, stdenvNoCC, - fetchzip, fetchFromGitHub, + fetchNpmDeps, + fetchzip, + replaceVars, + runCommand, + makeDesktopItem, + + nodejs, + npmHooks, electron, - steam-run, - makeWrapper, + makeBinaryWrapper, copyDesktopItems, - makeDesktopItem, -}: + zip, + nix-update-script, +}: let - version = "26.1.9"; - butler = fetchzip { - url = "https://broth.itch.zone/butler/linux-amd64/15.21.0/butler.zip"; - stripRoot = false; - hash = "sha256-jHni/5qf7xST6RRonP2EW8fJ6647jobzrnHe8VMx4IA="; + # See release/common.js + arches = { + "x86_64" = { + electron = "x64"; + itch = "amd64"; + }; + "i686" = { + electron = "ia32"; + itch = "386"; + }; }; - itch-setup = fetchzip { - url = "https://broth.itch.ovh/itch-setup/linux-amd64/1.26.0/itch-setup.zip"; + os = stdenvNoCC.hostPlatform.parsed.kernel.name; + arch = arches.${stdenvNoCC.hostPlatform.parsed.cpu.name}; + + # FIXME: build from source once possible + butler = fetchzip { + url = "https://broth.itch.zone/butler/${os}-${arch.itch}/15.24.0/butler.zip"; stripRoot = false; - hash = "sha256-5MP6X33Jfu97o5R1n6Og64Bv4ZMxVM0A8lXeQug+bNA="; + hash = "sha256-/0rwqkWfvQd1p8NbjQLARILBfpwmwC6dsR2ZYje4fXs="; }; - - sparseCheckout = "/release/images/itch-icons"; - icons = - fetchFromGitHub { - owner = "itchio"; - repo = "itch"; - rev = "v${version}"; - hash = "sha256-jugg+hdP0y0OkFhdQuEI9neWDuNf2p3+DQuwxe09Zck="; - sparseCheckout = [ sparseCheckout ]; - } - + sparseCheckout; in stdenvNoCC.mkDerivation (finalAttrs: { pname = "itch"; - inherit version; + version = "26.1.9"; - src = fetchzip { - url = "https://broth.itch.ovh/itch/linux-amd64/${finalAttrs.version}/archive/default#.zip"; - stripRoot = false; - hash = "sha256-4k6afBgOKGs7rzXAtIBpmuQeeT/Va8/0bZgNYjuJhgI="; + src = fetchFromGitHub { + owner = "itchio"; + repo = "itch"; + tag = "v${finalAttrs.version}"; + hash = "sha256-+fjgQDQKeHLGqVKSAgort8fJ2laAKfHkpKAKeQcte4Y="; + }; + + patches = [ + (replaceVars ./patch-build-scripts.patch { + electronVersion = electron.version; + + # For some reason, electron-packager only allows one to skip downloading Electron + # if and only if `electronZipDir` is set to a directory containing a zip file + # named `electron-v${electron.version}-${os}-${arch}.zip`. I don't know why, + # though it seems unavoidable. + electronZipDir = runCommand "electron-zip-dir" { nativeBuildInputs = [ zip ]; } '' + cp -r ${electron.dist} electron-dist + (cd electron-dist; zip -0Xqr ../electron-v${electron.version}-${os}-${arch.electron}.zip *) + install -D *.zip -t $out + ''; + }) + ]; + + npmDeps = fetchNpmDeps { + pname = "itch-npm-deps"; + inherit (finalAttrs) version src; + hash = "sha256-mSPoXdKogE+mX6efjW8VcKYwtiXEkKJ00YznsR9jtfs="; }; nativeBuildInputs = [ + nodejs + npmHooks.npmConfigHook copyDesktopItems - makeWrapper + makeBinaryWrapper ]; + env = { + ELECTRON_SKIP_BINARY_DOWNLOAD = true; + # For proper version identification + CI_COMMIT_TAG = finalAttrs.src.tag; + }; + + buildPhase = '' + runHook preBuild + + # TODO: figure out why electron-packager fails to create this itself + mkdir -p build/${finalAttrs.src.tag}/${os}-${arch.electron}-template/{locales,resources}/ + + node release/build.js --os ${os} --arch ${arch.itch} + node release/package.js --os ${os} --arch ${arch.itch} + + runHook postBuild + ''; + + installPhase = '' + runHook preInstall + + mkdir -p $out/share/itch + cp -r artifacts/${os}-${arch.itch}/{locales,resources{,.pak}} -t $out/share/itch + + makeWrapper ${lib.getExe electron} $out/bin/itch \ + --add-flags "$out/share/itch/resources/app.asar" \ + --add-flags "\''${NIXOS_OZONE_WL:+\''${WAYLAND_DISPLAY:+--ozone-platform-hint=auto --enable-features=WaylandWindowDecorations --enable-wayland-ime=true}}" \ + --set BROTH_USE_LOCAL butler \ + --prefix PATH : ${butler} + + for size in 16 32 36 48 64 72 114 128 144 150 256 512 1024; do + install -D release/images/itch-icons/icon''${size}.png \ + $out/share/icons/hicolor/''${size}x''${size}/apps/itch.png + done + + runHook postInstall + ''; + desktopItems = [ (makeDesktopItem { name = "itch"; @@ -66,44 +134,24 @@ stdenvNoCC.mkDerivation (finalAttrs: { }) ]; - # As taken from https://aur.archlinux.org/cgit/aur.git/tree/PKGBUILD?h=itch-bin - installPhase = '' - runHook preInstall - - mkdir -p $out/bin $out/share/itch/resources/app - cp -r resources/app "$out/share/itch/resources/" - - install -Dm644 LICENSE -t "$out/share/licenses/$pkgname/" - install -Dm644 LICENSES.chromium.html -t "$out/share/licenses/$pkgname/" - - for icon in ${icons}/icon*.png - do - iconsize="''${icon#${icons}/icon}" - iconsize="''${iconsize%.png}" - icondir="$out/share/icons/hicolor/''${iconsize}x''${iconsize}/apps/" - install -Dm644 "$icon" "$icondir/itch.png" - done - - runHook postInstall - ''; - - postFixup = '' - makeWrapper ${steam-run}/bin/steam-run $out/bin/itch \ - --add-flags ${electron}/bin/electron \ - --add-flags $out/share/itch/resources/app \ - --add-flags "\''${NIXOS_OZONE_WL:+\''${WAYLAND_DISPLAY:+--ozone-platform-hint=auto --enable-features=WaylandWindowDecorations --enable-wayland-ime=true}}" \ - --set BROTH_USE_LOCAL butler,itch-setup \ - --prefix PATH : ${butler}:${itch-setup} - ''; + passthru.updateScript = nix-update-script { }; meta = { description = "Best way to play itch.io games"; homepage = "https://github.com/itchio/itch"; - changelog = "https://github.com/itchio/itch/releases/tag/v${version}-canary"; + changelog = "https://github.com/itchio/itch/releases/tag/${finalAttrs.src.tag}"; license = lib.licenses.mit; - platforms = lib.platforms.linux; - sourceProvenance = [ lib.sourceTypes.binaryBytecode ]; - maintainers = with lib.maintainers; [ pasqui23 ]; + # https://itchio.itch.io/itch only provides up-to-date binaries for these platforms + platforms = [ + "x86_64-linux" + "x86_64-darwin" + "x86_64-windows" + "i686-windows" + ]; + maintainers = with lib.maintainers; [ + pasqui23 + pluiedev + ]; mainProgram = "itch"; }; }) diff --git a/pkgs/by-name/it/itch/patch-build-scripts.patch b/pkgs/by-name/it/itch/patch-build-scripts.patch new file mode 100644 index 0000000000000..06a1185d7d6b8 --- /dev/null +++ b/pkgs/by-name/it/itch/patch-build-scripts.patch @@ -0,0 +1,69 @@ +diff --git a/release/packaging/build.js b/release/packaging/build.js +index 2315cfa..3c43f4b 100644 +--- a/release/packaging/build.js ++++ b/release/packaging/build.js +@@ -44,7 +44,6 @@ async function build(cx) { + // TODO: legacy-peer-deps is used here due to react-json-inspector having + // dependencies set incorrectly locked to old version of react. In the future we should remove it + // this flag was added for npm 7 support +- $(`npm install --no-save --legacy-peer-deps ${externals.join(" ")}`); + }); + } + +diff --git a/release/packaging/context.js b/release/packaging/context.js +index 965b9ca..0a3aa99 100644 +--- a/release/packaging/context.js ++++ b/release/packaging/context.js +@@ -105,9 +105,7 @@ async function parseContext() { + os === "darwin" ? `./${appName}.app/Contents/MacOS` : "."; + + const iconsPath = ospath.join("release", "images", `${appName}-icons`); +- const electronVersion = JSON.parse( +- readFileSync("package.json", { encoding: "utf-8" }) +- ).devDependencies.electron.replace(/^\^/, ""); ++ const electronVersion = "@electronVersion@"; + + console.log(`| ${chalk.green(appName)} for ${chalk.green(os)}-${chalk.green(arch)}, Electron ${chalk.blue(electronVersion)}, code signing (${shouldSign ? chalk.green("enabled") : chalk.magenta("disabled")})`); + +diff --git a/release/packaging/do-package.js b/release/packaging/do-package.js +index e345be6..53389ef 100644 +--- a/release/packaging/do-package.js ++++ b/release/packaging/do-package.js +@@ -35,9 +35,11 @@ async function doPackage(cx) { + appVersion, + buildVersion: appVersion, + appCopyright: "MIT license, (c) itch corp.", +- asar: false, ++ asar: true, + overwrite: true, + out: outDir, ++ electronZipDir: '@electronZipDir@', ++ tmpdir: false, + ...getElectronOptions(cx), + }; + +diff --git a/release/packaging/test.js b/release/packaging/test.js +index d467dd8..451c553 100644 +--- a/release/packaging/test.js ++++ b/release/packaging/test.js +@@ -9,7 +9,6 @@ const ospath = require("path"); + */ + async function test(cx) { + await cd("integration-tests", async () => { +- $(`go build -o runner -v`); + }); + process.env.ELECTRON_DISABLE_SANDBOX = "1"; + +diff --git a/src/main/broth/formulas.ts b/src/main/broth/formulas.ts +index f43f174..59adde1 100644 +--- a/src/main/broth/formulas.ts ++++ b/src/main/broth/formulas.ts +@@ -63,6 +63,7 @@ describeFormula("butler", { + * https://github.com/itchio/itch-setup + */ + describeFormula("itch-setup", { ++ requiredAtStartup: false, + sanityCheck: async (ctx, logger, versionPrefix) => { + await spawn({ + ctx, +