fix(nix): natively compile and correctly stage node-pty for desktop app
- Add ELECTRON_SKIP_BINARY_DOWNLOAD=1 to nix/lib.nix to prevent offline download failures. - Manually trigger native compilation of node-pty via npm rebuild --build-from-source in buildPhase. - Run stage-native-deps.cjs to copy the natively compiled binary into build/native-deps. - Flatten native-deps and install-stamp.json to the root of the output derivation in installPhase, matching electron-builder's extraResources behavior so main.cjs can find it at process.resourcesPath + '/native-deps/node-pty'. - Add doCheck=true and a strict checkPhase to fail fast if the staged native binary is missing.
This commit is contained in:
parent
046f444ddc
commit
906bee9cf7
@ -95,6 +95,7 @@ try {
|
|||||||
nodePty = require(nodePtyDir)
|
nodePty = require(nodePtyDir)
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
|
console.log(`[terminal] failed to load node-pty from path ${nodePtyDir}`)
|
||||||
nodePty = null
|
nodePty = null
|
||||||
nodePtyDir = null
|
nodePtyDir = null
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,7 +18,8 @@
|
|||||||
"profile:main": "wait-on http://127.0.0.1:5174 && cross-env XCURSOR_SIZE=24 HERMES_DESKTOP_DEV_SERVER=http://127.0.0.1:5174 electron --inspect=9229 .",
|
"profile:main": "wait-on http://127.0.0.1:5174 && cross-env XCURSOR_SIZE=24 HERMES_DESKTOP_DEV_SERVER=http://127.0.0.1:5174 electron --inspect=9229 .",
|
||||||
"profile:main:cpu": "wait-on http://127.0.0.1:5174 && cross-env XCURSOR_SIZE=24 NODE_OPTIONS=--cpu-prof HERMES_DESKTOP_DEV_SERVER=http://127.0.0.1:5174 electron .",
|
"profile:main:cpu": "wait-on http://127.0.0.1:5174 && cross-env XCURSOR_SIZE=24 NODE_OPTIONS=--cpu-prof HERMES_DESKTOP_DEV_SERVER=http://127.0.0.1:5174 electron .",
|
||||||
"start": "npm run build && electron .",
|
"start": "npm run build && electron .",
|
||||||
"build": "node scripts/assert-root-install.cjs && node scripts/write-build-stamp.cjs && node scripts/stage-native-deps.cjs && tsc -b && vite build && node scripts/assert-dist-built.cjs",
|
"build": "node scripts/assert-root-install.cjs && node scripts/write-build-stamp.cjs && node scripts/stage-native-deps.cjs && tsc -b && vite build && npm run postbuild",
|
||||||
|
"postbuild": "node scripts/assert-dist-built.cjs",
|
||||||
"builder": "cross-env NODE_OPTIONS=--max-old-space-size=16384 electron-builder",
|
"builder": "cross-env NODE_OPTIONS=--max-old-space-size=16384 electron-builder",
|
||||||
"pack": "npm run build && npm run builder -- --dir",
|
"pack": "npm run build && npm run builder -- --dir",
|
||||||
"dist": "npm run build && npm run builder",
|
"dist": "npm run build && npm run builder",
|
||||||
|
|||||||
128
nix/desktop.nix
128
nix/desktop.nix
@ -6,63 +6,99 @@
|
|||||||
# `HERMES_DESKTOP_HERMES` override env var, so the desktop's resolver
|
# `HERMES_DESKTOP_HERMES` override env var, so the desktop's resolver
|
||||||
# uses our fully wrapped binary at step 4 ("existing Hermes CLI").
|
# uses our fully wrapped binary at step 4 ("existing Hermes CLI").
|
||||||
# No reimplementation of the agent resolution in this wrapper.
|
# No reimplementation of the agent resolution in this wrapper.
|
||||||
{ pkgs, lib, stdenv, makeWrapper, hermesNpmLib, electron, hermesAgent, ... }:
|
{
|
||||||
|
pkgs,
|
||||||
|
lib,
|
||||||
|
stdenv,
|
||||||
|
makeWrapper,
|
||||||
|
hermesNpmLib,
|
||||||
|
electron,
|
||||||
|
hermesAgent,
|
||||||
|
...
|
||||||
|
}:
|
||||||
let
|
let
|
||||||
npm = hermesNpmLib.mkNpmPassthru { folder = "apps/desktop"; attr = "desktop"; pname = "hermes-desktop"; };
|
npm = hermesNpmLib.mkNpmPassthru {
|
||||||
|
folder = "apps/desktop";
|
||||||
|
attr = "desktop";
|
||||||
|
pname = "hermes-desktop";
|
||||||
|
};
|
||||||
|
|
||||||
packageJson = builtins.fromJSON (builtins.readFile (npm.src + "/apps/desktop/package.json"));
|
packageJson = builtins.fromJSON (builtins.readFile (npm.src + "/apps/desktop/package.json"));
|
||||||
version = packageJson.version;
|
version = packageJson.version;
|
||||||
|
|
||||||
# Build the renderer (dist/ + electron/ + package.json).
|
# Build the renderer (dist/ + electron/ + package.json).
|
||||||
renderer = pkgs.buildNpmPackage (npm // {
|
renderer = pkgs.buildNpmPackage (
|
||||||
pname = "hermes-desktop-renderer";
|
npm
|
||||||
inherit version;
|
// {
|
||||||
|
pname = "hermes-desktop-renderer";
|
||||||
|
inherit version;
|
||||||
|
doCheck = true;
|
||||||
|
|
||||||
doCheck = false;
|
buildPhase = ''
|
||||||
# The workspace lockfile resolves all peer deps
|
runHook preBuild
|
||||||
# correctly so --legacy-peer-deps is not needed.
|
|
||||||
# --ignore-scripts comes from mkNpmPassthru (shared).
|
|
||||||
makeCacheWritable = true;
|
|
||||||
|
|
||||||
buildPhase = ''
|
# write-build-stamp.cjs replacement. Packaged Electron reads this
|
||||||
runHook preBuild
|
# at first-launch to pin the install.ps1 git ref; informational in
|
||||||
|
# nix builds (the backend comes from the derivation directly).
|
||||||
|
mkdir -p apps/desktop/build
|
||||||
|
echo '{"schemaVersion":1,"commit":"nix","branch":"nix","dirty":false,"source":"nix"}' > apps/desktop/build/install-stamp.json
|
||||||
|
|
||||||
# write-build-stamp.cjs replacement. Packaged Electron reads this
|
# patch shebangs in node_modules/.bin so npm exec can find the
|
||||||
# at first-launch to pin the install.ps1 git ref; informational in
|
# nix-store equivalents of /usr/bin/env (which doesn't exist in the sandbox)
|
||||||
# nix builds (the backend comes from the derivation directly).
|
patchShebangs .
|
||||||
mkdir -p apps/desktop/build
|
|
||||||
echo '{"schemaVersion":1,"commit":"nix","branch":"nix","dirty":false,"source":"nix"}' > apps/desktop/build/install-stamp.json
|
|
||||||
|
|
||||||
# Build from apps/desktop/ so vite.config.ts resolves correctly.
|
pushd apps/desktop
|
||||||
# The workspace root's node_modules/ is accessible as ../../node_modules/.
|
# stage node-pty native binaries into build/native-deps for the final nix output
|
||||||
cd apps/desktop
|
npm rebuild node-pty --build-from-source
|
||||||
|
node scripts/stage-native-deps.cjs
|
||||||
|
|
||||||
|
npm exec tsc -b
|
||||||
|
npm exec vite build
|
||||||
|
popd
|
||||||
|
|
||||||
# vite handles TS transpilation via esbuild — no type-checking.
|
runHook postBuild
|
||||||
# We skip `tsc -b` to avoid type errors in test files that don't
|
'';
|
||||||
# ship in the bundle (real upstream peer-dep version mismatches
|
|
||||||
# in @testing-library/react v16 — not blocking the build).
|
|
||||||
# Call vite directly from root node_modules to avoid npx resolving
|
|
||||||
# through unpatched workspace symlinks.
|
|
||||||
node ../../node_modules/vite/bin/vite.js build --outDir dist
|
|
||||||
|
|
||||||
# Return to source root so installPhase paths are correct.
|
checkPhase = ''
|
||||||
cd ../..
|
runHook preCheck
|
||||||
|
|
||||||
runHook postBuild
|
pushd apps/desktop
|
||||||
'';
|
|
||||||
|
|
||||||
installPhase = ''
|
npm run postbuild
|
||||||
runHook preInstall
|
|
||||||
mkdir -p $out
|
# validate staged node-pty native binary is present
|
||||||
# vite writes to apps/desktop/dist/ (we cd'd there in buildPhase).
|
STAGED_PTY_NODE="./build/native-deps/node-pty/build/Release/pty.node"
|
||||||
# apps/desktop/build was created before the cd. electron/ is source.
|
|
||||||
cp -r apps/desktop/dist $out/
|
if [ ! -f "$STAGED_PTY_NODE" ]; then
|
||||||
cp -r apps/desktop/electron $out/
|
echo "FATAL: Missing staged node-pty native binary at $STAGED_PTY_NODE"
|
||||||
cp -r apps/desktop/build $out/
|
echo "node-pty must be compiled natively"
|
||||||
cp apps/desktop/package.json $out/
|
exit 1
|
||||||
runHook postInstall
|
fi
|
||||||
'';
|
|
||||||
});
|
popd
|
||||||
|
|
||||||
|
runHook postCheck
|
||||||
|
'';
|
||||||
|
|
||||||
|
installPhase = ''
|
||||||
|
runHook preInstall
|
||||||
|
mkdir -p $out
|
||||||
|
# vite writes to apps/desktop/dist/ (we cd'd there in buildPhase).
|
||||||
|
# apps/desktop/build was created before the cd. electron/ is source.
|
||||||
|
cp -rn apps/desktop/dist $out/
|
||||||
|
cp -rn apps/desktop/electron $out/
|
||||||
|
|
||||||
|
# flatten native-deps and install-stamp.json to the root level, exactly like
|
||||||
|
# electron-builder's extraResources does ("from": "build/native-deps", "to": "native-deps")
|
||||||
|
# so main.cjs can find it at process.resourcesPath + '/native-deps/node-pty'
|
||||||
|
cp -rn apps/desktop/build/native-deps $out/
|
||||||
|
cp -n apps/desktop/build/install-stamp.json $out/
|
||||||
|
|
||||||
|
cp -n apps/desktop/package.json $out/
|
||||||
|
runHook postInstall
|
||||||
|
'';
|
||||||
|
}
|
||||||
|
);
|
||||||
in
|
in
|
||||||
|
|
||||||
# Electron wrapper: nixpkgs' electron binary pointed at the renderer dir.
|
# Electron wrapper: nixpkgs' electron binary pointed at the renderer dir.
|
||||||
@ -81,6 +117,12 @@ stdenv.mkDerivation {
|
|||||||
mkdir -p $out/share/hermes-desktop $out/bin
|
mkdir -p $out/share/hermes-desktop $out/bin
|
||||||
cp -r ${renderer}/* $out/share/hermes-desktop/
|
cp -r ${renderer}/* $out/share/hermes-desktop/
|
||||||
|
|
||||||
|
# Standard nixpkgs pattern for electron-builder apps: patch process.resourcesPath
|
||||||
|
# to point to the app's directory. In Nix, unpackaged electron defaults this
|
||||||
|
# to the electron distribution's resources path, breaking extraResources lookups.
|
||||||
|
substituteInPlace $out/share/hermes-desktop/electron/main.cjs \
|
||||||
|
--replace-fail "process.resourcesPath" "'$out/share/hermes-desktop'"
|
||||||
|
|
||||||
# Wrap the nixpkgs electron binary to launch our app. Set
|
# Wrap the nixpkgs electron binary to launch our app. Set
|
||||||
# HERMES_DESKTOP_HERMES to the absolute path of the nix-built `hermes`
|
# HERMES_DESKTOP_HERMES to the absolute path of the nix-built `hermes`
|
||||||
# binary so the desktop's resolver step 4 ("existing Hermes CLI on
|
# binary so the desktop's resolver step 4 ("existing Hermes CLI on
|
||||||
|
|||||||
@ -65,11 +65,7 @@ in
|
|||||||
npmRoot = ".";
|
npmRoot = ".";
|
||||||
npmDepsFetcherVersion = 2;
|
npmDepsFetcherVersion = 2;
|
||||||
|
|
||||||
# --ignore-scripts: the workspace includes electron (apps/desktop)
|
ELECTRON_SKIP_BINARY_DOWNLOAD = 1;
|
||||||
# which has a postinstall that tries to download from github.com.
|
|
||||||
# nix builds are offline, so all scripts must be skipped. Each
|
|
||||||
# package sets up its own build commands in buildPhase instead.
|
|
||||||
npmFlags = [ "--ignore-scripts" ];
|
|
||||||
|
|
||||||
patchPhase = ''
|
patchPhase = ''
|
||||||
runHook prePatch
|
runHook prePatch
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user