#!/usr/bin/env bun // build.js - Build static binaries for Baba Yaga import { $ } from "bun"; import { existsSync, mkdirSync } from "fs"; // Available targets for cross-compilation const TARGETS = { 'macos-arm64': 'bun-darwin-arm64', 'macos-x64': 'bun-darwin-x64', 'linux-x64': 'bun-linux-x64', 'windows-x64': 'bun-windows-x64' }; // Parse command line arguments const args = process.argv.slice(2); const targetArg = args.find(arg => arg.startsWith('--target=')); const allTargets = args.includes('--all'); const helpFlag = args.includes('--help') || args.includes('-h'); if (helpFlag) { console.log(`๐Ÿ”จ Baba Yaga Binary Builder Usage: bun run build.js [options] Options: --target= Build for specific target --all Build for all supported platforms --help, -h Show this help Available targets: macos-arm64 macOS Apple Silicon (default on Apple Silicon Mac) macos-x64 macOS Intel linux-x64 Linux x86_64 windows-x64 Windows x86_64 Examples: bun run build.js # Build for current platform bun run build.js --target=linux-x64 # Build for Linux bun run build.js --target=windows-x64 # Build for Windows bun run build.js --all # Build for all platforms `); process.exit(0); } let targetsToBuild = []; if (allTargets) { targetsToBuild = Object.keys(TARGETS); } else if (targetArg) { const requestedTarget = targetArg.split('=')[1]; if (!TARGETS[requestedTarget]) { console.error(`โŒ Unknown target: ${requestedTarget}`); console.error(`Available targets: ${Object.keys(TARGETS).join(', ')}`); process.exit(1); } targetsToBuild = [requestedTarget]; } else { // Default to current platform const platform = process.platform; const arch = process.arch; if (platform === 'darwin' && arch === 'arm64') { targetsToBuild = ['macos-arm64']; } else if (platform === 'darwin' && arch === 'x64') { targetsToBuild = ['macos-x64']; } else { console.log("๐Ÿค– Auto-detecting platform..."); targetsToBuild = ['macos-arm64']; // Default fallback } } console.log(`๐Ÿ”จ Building Baba Yaga static binaries for: ${targetsToBuild.join(', ')}\n`); // Create build directory if (!existsSync("./build")) { mkdirSync("./build"); } // Build function for a specific target async function buildTarget(targetName) { const bunTarget = TARGETS[targetName]; const isWindows = targetName.includes('windows'); console.log(`\n๐Ÿ“ฆ Building for ${targetName} (${bunTarget})...`); // Build interpreter binary const interpreterName = isWindows ? `baba-yaga-${targetName}.exe` : `baba-yaga-${targetName}`; const replName = isWindows ? `baba-yaga-repl-${targetName}.exe` : `baba-yaga-repl-${targetName}`; try { console.log(` Building interpreter: ${interpreterName}`); await $`bun build ./index.js --compile --outfile ./build/${interpreterName} --target ${bunTarget}`; console.log(` โœ… Built: ./build/${interpreterName}`); } catch (error) { console.error(` โŒ Failed to build interpreter for ${targetName}:`, error.message); return false; } // Build REPL binary try { console.log(` Building REPL: ${replName}`); await $`bun build ./repl.js --compile --outfile ./build/${replName} --target ${bunTarget}`; console.log(` โœ… Built: ./build/${replName}`); } catch (error) { console.error(` โŒ Failed to build REPL for ${targetName}:`, error.message); return false; } return true; } // Build all requested targets let successCount = 0; for (const target of targetsToBuild) { const success = await buildTarget(target); if (success) successCount++; } console.log(`\n๐ŸŽ‰ Build complete! (${successCount}/${targetsToBuild.length} targets successful)`); // Show what was built console.log("\n๐Ÿ“ฆ Built binaries:"); try { await $`ls -la ./build/`; } catch (error) { console.warn("Could not list build directory"); } // Test the binaries (only test current platform binaries) const currentPlatformBinaries = []; if (existsSync("./build/baba-yaga")) { currentPlatformBinaries.push("./build/baba-yaga"); } if (existsSync("./build/baba-yaga-macos-arm64")) { currentPlatformBinaries.push("./build/baba-yaga-macos-arm64"); } if (existsSync("./build/baba-yaga-macos-x64")) { currentPlatformBinaries.push("./build/baba-yaga-macos-x64"); } if (currentPlatformBinaries.length > 0) { console.log("\n๐Ÿงช Testing binaries..."); for (const binary of currentPlatformBinaries) { try { console.log(`Testing ${binary}...`); await $`${binary} simple.baba`.quiet(); console.log(`โœ… ${binary} test passed`); } catch (error) { console.warn(`โš ๏ธ ${binary} test failed:`, error.message); } } } console.log("\n๐Ÿ“‹ Usage examples:"); if (targetsToBuild.includes('macos-arm64') || targetsToBuild.includes('macos-x64')) { console.log(" # macOS:"); console.log(" ./build/baba-yaga-macos-arm64 program.baba --debug"); console.log(" ./build/baba-yaga-repl-macos-arm64"); } if (targetsToBuild.includes('linux-x64')) { console.log(" # Linux:"); console.log(" ./build/baba-yaga-linux-x64 program.baba --profile"); console.log(" ./build/baba-yaga-repl-linux-x64"); } if (targetsToBuild.includes('windows-x64')) { console.log(" # Windows:"); console.log(" .\\build\\baba-yaga-windows-x64.exe program.baba --debug"); console.log(" .\\build\\baba-yaga-repl-windows-x64.exe"); } console.log("\n๐Ÿš€ All binaries are standalone and require no dependencies!"); if (successCount < targetsToBuild.length) { console.log(`\nโš ๏ธ ${targetsToBuild.length - successCount} target(s) failed to build`); process.exit(1); }