build.ts 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. #!/usr/bin/env bun
  2. import { $ } from "bun"
  3. import fs from "fs"
  4. import { rm } from "fs/promises"
  5. import path from "path"
  6. import { Script } from "@opencode-ai/script"
  7. import { createSolidTransformPlugin } from "@opentui/solid/bun-plugin"
  8. import pkg from "../package.json"
  9. import { modelsData } from "./generate"
  10. const dir = path.resolve(import.meta.dirname, "..")
  11. const binary = "opencode2"
  12. process.chdir(dir)
  13. await rm("dist", { recursive: true, force: true })
  14. const singleFlag = process.argv.includes("--single")
  15. const baselineFlag = process.argv.includes("--baseline")
  16. const skipInstall = process.argv.includes("--skip-install")
  17. const plugin = createSolidTransformPlugin()
  18. const allTargets: {
  19. os: string
  20. arch: "arm64" | "x64"
  21. abi?: "musl"
  22. avx2?: false
  23. }[] = [
  24. { os: "linux", arch: "arm64" },
  25. { os: "linux", arch: "x64" },
  26. { os: "linux", arch: "x64", avx2: false },
  27. { os: "linux", arch: "arm64", abi: "musl" },
  28. { os: "linux", arch: "x64", abi: "musl" },
  29. { os: "linux", arch: "x64", abi: "musl", avx2: false },
  30. { os: "darwin", arch: "arm64" },
  31. { os: "darwin", arch: "x64" },
  32. { os: "darwin", arch: "x64", avx2: false },
  33. { os: "win32", arch: "arm64" },
  34. { os: "win32", arch: "x64" },
  35. { os: "win32", arch: "x64", avx2: false },
  36. ]
  37. const targets = singleFlag
  38. ? allTargets.filter((item) => {
  39. if (item.os !== process.platform || item.arch !== process.arch) return false
  40. if (item.avx2 === false) return baselineFlag
  41. return item.abi === undefined
  42. })
  43. : allTargets
  44. if (!skipInstall) await $`bun install --os="*" --cpu="*" @opentui/core@${pkg.dependencies["@opentui/core"]}`
  45. const localParserWorker = path.resolve(dir, "node_modules/@opentui/core/parser.worker.js")
  46. const rootParserWorker = path.resolve(dir, "../../node_modules/@opentui/core/parser.worker.js")
  47. const parserWorker = fs.realpathSync(fs.existsSync(localParserWorker) ? localParserWorker : rootParserWorker)
  48. for (const item of targets) {
  49. const target = [
  50. binary,
  51. item.os === "win32" ? "windows" : item.os,
  52. item.arch,
  53. item.avx2 === false ? "baseline" : undefined,
  54. item.abi,
  55. ]
  56. .filter(Boolean)
  57. .join("-")
  58. const name = target.replace(binary, "cli")
  59. console.log(`building ${name}`)
  60. const result = await Bun.build({
  61. entrypoints: ["./src/index.ts", parserWorker],
  62. tsconfig: "./tsconfig.json",
  63. plugins: [plugin],
  64. external: ["node-gyp"],
  65. format: "esm",
  66. minify: true,
  67. sourcemap: "inline",
  68. splitting: true,
  69. compile: {
  70. autoloadBunfig: false,
  71. autoloadDotenv: false,
  72. autoloadTsconfig: true,
  73. autoloadPackageJson: true,
  74. target: target.replace(binary, "bun") as Bun.Build.CompileTarget,
  75. outfile: `./dist/${name}/bin/${binary}`,
  76. execArgv: [`--user-agent=${binary}/${Script.version}`, "--use-system-ca", "--"],
  77. windows: {},
  78. },
  79. define: {
  80. OPENCODE_VERSION: `'${Script.version}'`,
  81. OPENCODE_CLI_NAME: `'${binary}'`,
  82. OPENCODE_MODELS_DEV: modelsData,
  83. OPENCODE_CHANNEL: `'${Script.channel}'`,
  84. OPENCODE_LIBC: item.os === "linux" ? `'${item.abi ?? "glibc"}'` : "undefined",
  85. // FFF_LIBC selects the fff native lib variant: "musl" or "gnu".
  86. FFF_LIBC: item.os === "linux" ? `'${item.abi ?? "gnu"}'` : "undefined",
  87. OTUI_TREE_SITTER_WORKER_PATH:
  88. (item.os === "win32" ? '"B:/~BUN/root/' : '"/$bunfs/root/') +
  89. path.relative(dir, parserWorker).replaceAll("\\", "/") +
  90. '"',
  91. ...(item.os === "linux" ? { "process.env.OPENTUI_LIBC": JSON.stringify(item.abi ?? "glibc") } : {}),
  92. },
  93. })
  94. if (!result.success) {
  95. for (const log of result.logs) console.error(log)
  96. process.exit(1)
  97. }
  98. await Bun.write(
  99. `./dist/${name}/package.json`,
  100. JSON.stringify(
  101. {
  102. name: `@opencode-ai/${name}`,
  103. version: Script.version,
  104. license: "MIT",
  105. repository: { type: "git", url: "git+https://github.com/anomalyco/opencode.git" },
  106. os: [item.os],
  107. cpu: [item.arch],
  108. },
  109. null,
  110. 2,
  111. ),
  112. )
  113. }