From dc008b70ca4b12e761f00df331ea7b1ce77d26b9 Mon Sep 17 00:00:00 2001 From: Solomon Date: Mon, 7 Jul 2025 15:27:00 +0100 Subject: [PATCH] perf: Share Cargo build cache across git worktrees (#60) Use a common target directory for all worktrees to avoid recompiling the backend in every worktree directory. --- .cargo/config.toml | 2 -- package.json | 17 ++++++++++------- scripts/cargo.js | 31 +++++++++++++++++++++++++++++++ 3 files changed, 41 insertions(+), 9 deletions(-) create mode 100644 scripts/cargo.js diff --git a/.cargo/config.toml b/.cargo/config.toml index 34084869..67dbd242 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -1,7 +1,5 @@ -[env] # Set macOS deployment target to avoid linker warnings # Use Rust project defaults: 10.12 for x86_64, 11.0 for aarch64 - [target.x86_64-apple-darwin.env] MACOSX_DEPLOYMENT_TARGET = "10.12" diff --git a/package.json b/package.json index 28806879..1adae44b 100644 --- a/package.json +++ b/package.json @@ -3,17 +3,20 @@ "version": "0.0.37", "private": true, "scripts": { - "dev": "export FRONTEND_PORT=$(node scripts/setup-dev-environment.js frontend) && export BACKEND_PORT=$(node scripts/setup-dev-environment.js backend) && concurrently \"cargo watch -w backend -x 'run --manifest-path backend/Cargo.toml'\" \"npm run frontend:dev\"", - "build": "npm run frontend:build && cargo build --release --manifest-path backend/Cargo.toml && cargo build --release --bin mcp_task_server --manifest-path backend/Cargo.toml", - "build:single": "npm run frontend:build && cargo build --release --manifest-path backend/Cargo.toml", + "dev": "export FRONTEND_PORT=$(node scripts/setup-dev-environment.js frontend) && export BACKEND_PORT=$(node scripts/setup-dev-environment.js backend) && concurrently \"npm run backend:dev:watch\" \"npm run frontend:dev\"", + "build": "npm run frontend:build && npm run backend:build", + "build:single": "npm run frontend:build && npm run backend:build:single", "build:npm": "./build-npm-package.sh", "test:npm": "./test-npm-package.sh", "frontend:dev": "cd frontend && npm run dev -- --port ${FRONTEND_PORT:-3000} --open", "frontend:build": "cd frontend && npm run build", - "backend:dev": "BACKEND_PORT=$(node scripts/setup-dev-environment.js backend) cargo watch -w backend -x 'run --manifest-path backend/Cargo.toml'", - "backend:build": "cargo build --release --manifest-path backend/Cargo.toml", - "backend:run": "cargo run --manifest-path backend/Cargo.toml", - "backend:test": "cargo test --lib", + "cargo": "node scripts/cargo.js", + "backend:dev": "BACKEND_PORT=$(node scripts/setup-dev-environment.js backend) npm run backend:dev:watch", + "backend:dev:watch": "npm run cargo -- watch -w backend -x 'run --manifest-path backend/Cargo.toml'", + "backend:build": "npm run cargo -- build --release --manifest-path backend/Cargo.toml && npm run cargo -- build --release --bin mcp_task_server --manifest-path backend/Cargo.toml", + "backend:build:single": "npm run cargo -- build --release --manifest-path backend/Cargo.toml", + "backend:run" : "npm run cargo -- run --manifest-path backend/Cargo.toml", + "backend:test" : "npm run cargo -- test --lib", "generate-types": "cd backend && cargo run --bin generate_types", "prepare-db": "node scripts/prepare-db.js", "dev:clear-ports": "node scripts/setup-dev-environment.js clear" diff --git a/scripts/cargo.js b/scripts/cargo.js new file mode 100644 index 00000000..1d32f433 --- /dev/null +++ b/scripts/cargo.js @@ -0,0 +1,31 @@ +#!/usr/bin/env node +/** + * Drop-in replacement for the `cargo` binary. + * If CARGO_TARGET_DIR is already set we leave it alone. + * Otherwise we compute a path that is the same for every git-worktree: + * /target + * + * Usage : node scripts/cargo.js […] + * NPM : "backend:build": "node scripts/cargo.js build --release …" + */ +const { spawnSync, execSync } = require('node:child_process'); +const path = require('node:path'); + +function sharedTarget() { + try { + // Works in any work-tree folder + const common = execSync('git rev-parse --git-common-dir', { encoding: 'utf8' }).trim(); + return path.resolve(common, '..', 'target'); + } catch { + return undefined; // not a git repo? -> let Cargo use ./target + } +} + +const env = { ...process.env }; +if (!env.CARGO_TARGET_DIR) { + const dir = sharedTarget(); + if (dir) env.CARGO_TARGET_DIR = dir; +} + +const result = spawnSync('cargo', process.argv.slice(2), { stdio: 'inherit', env }); +process.exitCode = result.status;