From bb35946b286aa4bc8de2112777bde766e859c4b5 Mon Sep 17 00:00:00 2001 From: Shantur Rathore Date: Fri, 24 Oct 2025 16:46:34 +0100 Subject: [PATCH] Add binary build system for cross-platform distribution - Add scripts/build.ts: Bun-based build script for generating binaries - Support macOS (x64, ARM64, Universal), Windows (x64, ARM64), Linux (x64, ARM64) - Add build:* npm scripts for each platform (build:mac, build:win, build:linux, etc) - Configure electron-builder with platform-specific settings: * macOS: DMG + ZIP, Universal binaries, proper icon paths * Windows: NSIS installer + ZIP, configurable install directory * Linux: AppImage + DEB + tar.gz packages - Add BUILD.md: Comprehensive build documentation with examples - Update README.md: Add build instructions and reference BUILD.md - Artifacts named: OpenCode Client-{version}-{os}-{arch}.{ext} - Output directory: release/ Usage: bun run build:mac # macOS Universal (Intel + Apple Silicon) bun run build:win # Windows x64 bun run build:linux # Linux x64 bun run build:all # All platforms --- BUILD.md | 247 +++++++++++++++++++++++++++++++++++++++++++++++ README.md | 11 ++- package.json | 102 ++++++++++++++++++- scripts/build.ts | 84 ++++++++++++++++ 4 files changed, 439 insertions(+), 5 deletions(-) create mode 100644 BUILD.md create mode 100755 scripts/build.ts diff --git a/BUILD.md b/BUILD.md new file mode 100644 index 00000000..771dcf90 --- /dev/null +++ b/BUILD.md @@ -0,0 +1,247 @@ +# Building OpenCode Client Binaries + +This guide explains how to build distributable binaries for OpenCode Client. + +## Prerequisites + +- **Bun** - Package manager and runtime +- **Node.js** - For electron-builder +- **Electron Builder** - Installed via devDependencies + +## Quick Start + +### Build for Current Platform (macOS default) + +```bash +bun run build:binaries +``` + +This builds for macOS (Universal - Intel + Apple Silicon) by default. + +## Platform-Specific Builds + +### macOS + +```bash +# Universal (Intel + Apple Silicon) - Recommended +bun run build:mac + +# Intel only (x64) +bun run build:mac-x64 + +# Apple Silicon only (ARM64) +bun run build:mac-arm64 +``` + +**Output formats:** `.dmg`, `.zip` + +### Windows + +```bash +# x64 (64-bit Intel/AMD) +bun run build:win + +# ARM64 (Windows on ARM) +bun run build:win-arm64 +``` + +**Output formats:** `.exe` (NSIS installer), `.zip` + +### Linux + +```bash +# x64 (64-bit) +bun run build:linux + +# ARM64 +bun run build:linux-arm64 +``` + +**Output formats:** `.AppImage`, `.deb`, `.tar.gz` + +### Build All Platforms + +```bash +bun run build:all +``` + +⚠️ **Note:** Cross-platform builds may have limitations. Build on the target platform for best results. + +## Build Process + +The build script performs these steps: + +1. **Compile TypeScript** → Electron app (main, preload, renderer) +2. **Bundle with Vite** → Optimized production build +3. **Package with electron-builder** → Platform-specific binaries + +## Output + +Binaries are generated in the `release/` directory: + +``` +release/ +├── OpenCode Client-0.1.0-mac-universal.dmg +├── OpenCode Client-0.1.0-mac-universal.zip +├── OpenCode Client-0.1.0-win-x64.exe +├── OpenCode Client-0.1.0-linux-x64.AppImage +└── ... +``` + +## File Naming Convention + +``` +OpenCode Client-{version}-{os}-{arch}.{ext} +``` + +- **version**: From package.json (e.g., `0.1.0`) +- **os**: `mac`, `win`, `linux` +- **arch**: `x64`, `arm64`, `universal` +- **ext**: `dmg`, `zip`, `exe`, `AppImage`, `deb`, `tar.gz` + +## Platform Requirements + +### macOS + +- **Build on:** macOS 10.13+ +- **Run on:** macOS 10.13+ +- **Code signing:** Optional (recommended for distribution) + +### Windows + +- **Build on:** Windows 10+, macOS, or Linux +- **Run on:** Windows 10+ +- **Code signing:** Optional (recommended for distribution) + +### Linux + +- **Build on:** Any platform +- **Run on:** Ubuntu 18.04+, Debian 10+, Fedora 32+, Arch +- **Dependencies:** Varies by distro + +## Troubleshooting + +### Build fails on macOS + +```bash +# Install Xcode Command Line Tools +xcode-select --install +``` + +### Build fails on Linux + +```bash +# Install dependencies (Debian/Ubuntu) +sudo apt-get install -y rpm + +# Install dependencies (Fedora) +sudo dnf install -y rpm-build +``` + +### "electron-builder not found" + +```bash +# Install dependencies +bun install +``` + +### Build is slow + +- Use platform-specific builds instead of `build:all` +- Close other applications to free up resources +- Use SSD for faster I/O + +## Development vs Production + +**Development:** + +```bash +bun run dev # Hot reload, no packaging +``` + +**Production:** + +```bash +bun run build:binaries # Full build + packaging +``` + +## CI/CD Integration + +Example GitHub Actions workflow: + +```yaml +name: Build Binaries + +on: + push: + tags: + - "v*" + +jobs: + build-mac: + runs-on: macos-latest + steps: + - uses: actions/checkout@v3 + - uses: oven-sh/setup-bun@v1 + - run: bun install + - run: bun run build:mac + + build-win: + runs-on: windows-latest + steps: + - uses: actions/checkout@v3 + - uses: oven-sh/setup-bun@v1 + - run: bun install + - run: bun run build:win + + build-linux: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: oven-sh/setup-bun@v1 + - run: bun install + - run: bun run build:linux +``` + +## Advanced Configuration + +Edit `package.json` → `build` section to customize: + +- App icon +- Code signing +- Installer options +- File associations +- Auto-update settings + +See [electron-builder docs](https://www.electron.build/) for details. + +## Clean Build + +Remove previous builds: + +```bash +rm -rf release/ dist/ +bun run build:binaries +``` + +## FAQ + +**Q: Can I build for Windows on macOS?** +A: Yes, but native binaries (e.g., DMG) require the target OS. + +**Q: How large are the binaries?** +A: Approximately 100-150 MB (includes Electron runtime). + +**Q: Do I need code signing?** +A: Not required, but recommended for public distribution to avoid security warnings. + +**Q: How do I update the version?** +A: Update `version` in `package.json`, then rebuild. + +## Support + +For issues or questions: + +- Check [electron-builder documentation](https://www.electron.build/) +- Open an issue in the repository +- Review existing build logs in `release/` diff --git a/README.md b/README.md index 29cfa92a..d575a77b 100644 --- a/README.md +++ b/README.md @@ -65,10 +65,13 @@ bun run dev # Build for production bun run build -# Package for distribution -bun run package:mac # macOS -bun run package:win # Windows -bun run package:linux # Linux +# Build distributable binaries +bun run build:mac # macOS (Universal) +bun run build:win # Windows (x64) +bun run build:linux # Linux (x64) +bun run build:all # All platforms + +# See BUILD.md for more build options ``` ## Development diff --git a/package.json b/package.json index 488e1a39..fa8f7e2b 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,15 @@ "build": "electron-vite build", "typecheck": "tsc --noEmit && tsc --noEmit -p tsconfig.node.json", "preview": "electron-vite preview", + "build:binaries": "bun scripts/build.ts", + "build:mac": "bun scripts/build.ts mac", + "build:mac-x64": "bun scripts/build.ts mac-x64", + "build:mac-arm64": "bun scripts/build.ts mac-arm64", + "build:win": "bun scripts/build.ts win", + "build:win-arm64": "bun scripts/build.ts win-arm64", + "build:linux": "bun scripts/build.ts linux", + "build:linux-arm64": "bun scripts/build.ts linux-arm64", + "build:all": "bun scripts/build.ts all", "package:mac": "electron-builder --mac", "package:win": "electron-builder --win", "package:linux": "electron-builder --linux" @@ -45,6 +54,97 @@ "files": [ "dist/**/*", "package.json" - ] + ], + "mac": { + "category": "public.app-category.developer-tools", + "target": [ + { + "target": "dmg", + "arch": [ + "x64", + "arm64", + "universal" + ] + }, + { + "target": "zip", + "arch": [ + "x64", + "arm64", + "universal" + ] + } + ], + "artifactName": "${productName}-${version}-${os}-${arch}.${ext}", + "icon": "electron/resources/icon.icns" + }, + "dmg": { + "contents": [ + { + "x": 130, + "y": 220 + }, + { + "x": 410, + "y": 220, + "type": "link", + "path": "/Applications" + } + ] + }, + "win": { + "target": [ + { + "target": "nsis", + "arch": [ + "x64", + "arm64" + ] + }, + { + "target": "zip", + "arch": [ + "x64", + "arm64" + ] + } + ], + "artifactName": "${productName}-${version}-${os}-${arch}.${ext}", + "icon": "electron/resources/icon.ico" + }, + "nsis": { + "oneClick": false, + "allowToChangeInstallationDirectory": true, + "createDesktopShortcut": true, + "createStartMenuShortcut": true + }, + "linux": { + "target": [ + { + "target": "AppImage", + "arch": [ + "x64", + "arm64" + ] + }, + { + "target": "deb", + "arch": [ + "x64", + "arm64" + ] + }, + { + "target": "tar.gz", + "arch": [ + "x64", + "arm64" + ] + } + ], + "artifactName": "${productName}-${version}-${os}-${arch}.${ext}", + "category": "Development", + "icon": "electron/resources/icon.png" + } } } diff --git a/scripts/build.ts b/scripts/build.ts new file mode 100755 index 00000000..0744fbc5 --- /dev/null +++ b/scripts/build.ts @@ -0,0 +1,84 @@ +#!/usr/bin/env bun + +import { $ } from "bun" +import { existsSync } from "fs" +import { join } from "path" + +const platforms = { + mac: { + args: ["--mac", "--x64", "--arm64", "--universal"], + description: "macOS (Intel, Apple Silicon, Universal)", + }, + "mac-x64": { + args: ["--mac", "--x64"], + description: "macOS (Intel only)", + }, + "mac-arm64": { + args: ["--mac", "--arm64"], + description: "macOS (Apple Silicon only)", + }, + win: { + args: ["--win", "--x64"], + description: "Windows (x64)", + }, + "win-arm64": { + args: ["--win", "--arm64"], + description: "Windows (ARM64)", + }, + linux: { + args: ["--linux", "--x64"], + description: "Linux (x64)", + }, + "linux-arm64": { + args: ["--linux", "--arm64"], + description: "Linux (ARM64)", + }, + all: { + args: ["--mac", "--win", "--linux", "--x64", "--arm64"], + description: "All platforms (macOS, Windows, Linux)", + }, +} + +async function build(platform: string) { + const config = platforms[platform as keyof typeof platforms] + + if (!config) { + console.error(`❌ Unknown platform: ${platform}`) + console.error(`\nAvailable platforms:`) + for (const [name, cfg] of Object.entries(platforms)) { + console.error(` - ${name.padEnd(12)} : ${cfg.description}`) + } + process.exit(1) + } + + console.log(`\n🔨 Building for: ${config.description}\n`) + + try { + console.log("📦 Step 1/2: Building Electron app...\n") + await $`bun run build` + + console.log("\n📦 Step 2/2: Packaging binaries...\n") + const distExists = existsSync(join(process.cwd(), "dist")) + if (!distExists) { + throw new Error("dist/ directory not found. Build failed.") + } + + await $`bunx electron-builder ${config.args}` + + console.log("\n✅ Build complete!") + console.log(`📁 Binaries available in: release/\n`) + } catch (error) { + console.error("\n❌ Build failed:", error) + process.exit(1) + } +} + +const platform = process.argv[2] || "mac" + +console.log(` +╔════════════════════════════════════════╗ +║ OpenCode Client - Binary Builder ║ +╚════════════════════════════════════════╝ +`) + +await build(platform)