76 lines
3.7 KiB
JavaScript
76 lines
3.7 KiB
JavaScript
import { spawn } from 'node:child_process'
|
|
import { access, mkdir } from 'node:fs/promises'
|
|
import path from 'node:path'
|
|
import { fileURLToPath } from 'node:url'
|
|
|
|
export const root = fileURLToPath(new URL('../', import.meta.url))
|
|
export const plugins = [
|
|
{ id: 'spam_block', executable: 'spam_block', directory: 'backend', source: './hooks/spam_block' },
|
|
{ id: 'telegram_push', executable: 'pmail_telegram_push', directory: 'plugins/pmail_telegram_push', source: '.' },
|
|
{ id: 'wechat_push', executable: 'wechat_push', directory: 'backend', source: './hooks/wechat_push' }
|
|
]
|
|
export const targets = ['linux_amd64', 'linux_arm64', 'windows_amd64', 'windows_arm64', 'darwin_amd64', 'darwin_arm64']
|
|
|
|
export function hostTarget() {
|
|
const goos = { win32: 'windows', linux: 'linux', darwin: 'darwin' }[process.platform]
|
|
const goarch = { x64: 'amd64', arm64: 'arm64' }[process.arch]
|
|
return `${goos}_${goarch}`
|
|
}
|
|
|
|
export function buildPlan({ target = hostTarget(), plugin, development = false } = {}) {
|
|
if (!targets.includes(target)) throw new Error(`不支持的编译平台:${target}`)
|
|
if (plugin && !plugins.some(item => item.id === plugin)) throw new Error(`未知插件:${plugin}`)
|
|
if (development && target !== hostTarget()) throw new Error('开发运行目录只能使用本机平台插件')
|
|
const [goos, goarch] = target.split('_')
|
|
return plugins.filter(item => !plugin || item.id === plugin).map(item => ({
|
|
...item,
|
|
goos,
|
|
goarch,
|
|
output: path.join(root, 'out', 'plugins', ...(development ? [] : [target]), `${item.executable}${goos === 'windows' ? '.exe' : ''}`)
|
|
}))
|
|
}
|
|
|
|
function run(command, args, cwd, env = process.env) {
|
|
return new Promise((resolve, reject) => {
|
|
const child = spawn(command, args, { cwd, env, stdio: 'inherit', windowsHide: true })
|
|
child.once('error', reject)
|
|
child.once('exit', code => code === 0 ? resolve() : reject(new Error(`构建失败:${command},退出码 ${code}`)))
|
|
})
|
|
}
|
|
|
|
export async function buildPlugins(args) {
|
|
const options = {}
|
|
let all = false
|
|
for (const arg of args) {
|
|
if (arg === '--all') all = true
|
|
else if (arg === '--dev') options.development = true
|
|
else if (arg.startsWith('--target=')) options.target = arg.slice(9)
|
|
else if (arg.startsWith('--plugin=')) options.plugin = arg.slice(9)
|
|
else throw new Error(`未知构建参数:${arg}`)
|
|
}
|
|
if (all && (options.target || options.development)) throw new Error('全平台编译不能同时指定单个平台或开发目录')
|
|
const plan = (all ? targets : [options.target || hostTarget()]).flatMap(target => buildPlan({ ...options, target }))
|
|
if (plan.some(item => item.id === 'telegram_push')) {
|
|
const directory = path.join(root, 'plugins', 'pmail_telegram_push')
|
|
const vite = path.join(directory, 'node_modules', 'vite', 'bin', 'vite.js')
|
|
try { await access(vite) } catch { throw new Error('请先在 plugins/pmail_telegram_push 执行 npm ci 安装依赖') }
|
|
// 构建并同步 Telegram 单文件界面,保证 Go 嵌入的是本次资源。
|
|
await run(process.execPath, [vite, 'build'], directory)
|
|
await run(process.execPath, [path.join(root, 'deploy', 'prepare-frontend.mjs'), 'telegram'], root)
|
|
}
|
|
for (const item of plan) {
|
|
await mkdir(path.dirname(item.output), { recursive: true })
|
|
await run('go', ['build', '-ldflags', '-s -w', '-o', item.output, item.source], path.join(root, item.directory), {
|
|
...process.env, CGO_ENABLED: '0', GOOS: item.goos, GOARCH: item.goarch
|
|
})
|
|
console.log(`插件已编译:${path.relative(root, item.output)}`)
|
|
}
|
|
}
|
|
|
|
if (process.argv[1] && path.resolve(process.argv[1]) === fileURLToPath(import.meta.url)) {
|
|
buildPlugins(process.argv.slice(2)).catch(error => {
|
|
console.error(error.message)
|
|
process.exitCode = 1
|
|
})
|
|
}
|