From 5a0cf3f6ea2bbed982f05c3a4a0f434134374944 Mon Sep 17 00:00:00 2001 From: yhh <359807859@qq.com> Date: Thu, 5 Nov 2026 18:14:07 -0800 Subject: [PATCH] build(studio): make studio skips the frontend and kernel steps when nothing they read is newer than what they made STUDIO_REBUILD=1 forces both. The comparison is a small Node script because the launcher runs under a Git Bash that may have no GNU find. --- desktop/electron/packaging/stale.js | 35 +++++++++++++++++++++++++++++ desktop/electron/run-studio.sh | 26 +++++++++++++++++---- 2 files changed, 57 insertions(+), 4 deletions(-) create mode 100644 desktop/electron/packaging/stale.js diff --git a/desktop/electron/packaging/stale.js b/desktop/electron/packaging/stale.js new file mode 100644 index 0000000000..cdbb54600e --- /dev/null +++ b/desktop/electron/packaging/stale.js @@ -0,0 +1,35 @@ +"use strict"; +const fs = require("node:fs"); +const path = require("node:path"); + +// Exit 0 when the artifact is missing or any file under the given paths is +// newer than it, 1 when it is up to date. run-studio.sh asks this before +// rebuilding; the shell has no portable `find` on every platform it runs on. +const [artifact, ...inputs] = process.argv.slice(2); +if (!artifact) process.exit(2); + +let built; +try { + built = fs.statSync(artifact).mtimeMs; +} catch { + process.exit(0); +} + +const SKIP = new Set(["node_modules", ".git", "dist"]); + +function newer(entry) { + let info; + try { + info = fs.statSync(entry); + } catch { + return false; + } + if (!info.isDirectory()) return info.mtimeMs > built; + for (const name of fs.readdirSync(entry)) { + if (SKIP.has(name)) continue; + if (newer(path.join(entry, name))) return true; + } + return false; +} + +process.exit(inputs.some(newer) ? 0 : 1); diff --git a/desktop/electron/run-studio.sh b/desktop/electron/run-studio.sh index ed0a30ca4f..879dfcf442 100755 --- a/desktop/electron/run-studio.sh +++ b/desktop/electron/run-studio.sh @@ -12,11 +12,29 @@ if [ ! -d "$here/node_modules" ]; then (cd "$here" && pnpm install --frozen-lockfile) fi -echo "==> frontend" -(cd "$here/../frontend-next" && pnpm install --frozen-lockfile >/dev/null && pnpm build >/dev/null) +# A step is skipped when nothing it reads is newer than what it produced; +# STUDIO_REBUILD=1 forces every step. +stale() { + [ -n "${STUDIO_REBUILD:-}" ] || node "$here/packaging/stale.js" "$@" +} -echo "==> kernel" -(cd "$here" && pnpm build:host) +root="$here/../.." +web="$here/../frontend-next" +host=$(ls "$here"/bin/reasonix-studio-host* 2>/dev/null | head -n 1 || true) + +if stale "$web/dist/index.html" "$web/src" "$web/public" "$web/index.html" "$web/package.json" "$web/pnpm-lock.yaml" "$web/vite.config.ts" "$web/tsconfig.json"; then + echo "==> frontend" + (cd "$web" && pnpm install --frozen-lockfile >/dev/null && pnpm build >/dev/null) +else + echo "==> frontend (up to date)" +fi + +if [ -z "$host" ] || stale "$host" "$root/internal" "$root/cmd" "$root/go.mod" "$root/go.sum" "$here/packaging"; then + echo "==> kernel" + (cd "$here" && pnpm build:host) +else + echo "==> kernel (up to date)" +fi echo "==> studio" cd "$here" && exec pnpm start