's'
This commit is contained in:
88
electron/scripts/verify-runtime.mjs
Normal file
88
electron/scripts/verify-runtime.mjs
Normal file
@@ -0,0 +1,88 @@
|
||||
import fs from 'fs'
|
||||
import path from 'path'
|
||||
import { spawnSync } from 'child_process'
|
||||
import { fileURLToPath } from 'url'
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url)
|
||||
const __dirname = path.dirname(__filename)
|
||||
|
||||
const electronRoot = path.resolve(__dirname, '..')
|
||||
const backendRoot = path.resolve(electronRoot, '..')
|
||||
|
||||
const pythonCandidates = [
|
||||
path.join(backendRoot, 'python', 'python.exe'),
|
||||
path.join(backendRoot, 'python', 'Scripts', 'python.exe'),
|
||||
]
|
||||
const web2Py = path.join(backendRoot, 'web2.py')
|
||||
const ffmpegCandidates = [
|
||||
path.join(backendRoot, 'ffmpeg', 'ffmpeg.exe'),
|
||||
path.join(backendRoot, 'ffmpeg', 'bin', 'ffmpeg.exe'),
|
||||
path.join(backendRoot, 'tools', 'ffmpeg', 'ffmpeg.exe'),
|
||||
path.join(backendRoot, 'tools', 'ffmpeg', 'bin', 'ffmpeg.exe'),
|
||||
]
|
||||
|
||||
const errors = []
|
||||
|
||||
if (!fs.existsSync(web2Py)) {
|
||||
errors.push(`缺少后端入口文件: ${web2Py}`)
|
||||
}
|
||||
const pythonExe = pythonCandidates.find((p) => fs.existsSync(p)) ?? null
|
||||
if (!pythonExe) {
|
||||
errors.push(`缺少内置 Python(任一路径即可):\n- ${pythonCandidates[0]}\n- ${pythonCandidates[1]}`)
|
||||
}
|
||||
// venv 结构在跨机器分发时可能依赖构建机本地 Python,不可作为懒人包运行时。
|
||||
if (fs.existsSync(path.join(backendRoot, 'python', 'pyvenv.cfg'))) {
|
||||
errors.push(
|
||||
`检测到 venv 运行时(${path.join(
|
||||
backendRoot,
|
||||
'python',
|
||||
'pyvenv.cfg',
|
||||
)})。该结构不保证跨机器可用,请改为可分发的独立 Python Runtime(嵌入式/便携式)。`,
|
||||
)
|
||||
}
|
||||
|
||||
const ffmpegExe = ffmpegCandidates.find((p) => fs.existsSync(p)) ?? null
|
||||
if (!ffmpegExe) {
|
||||
errors.push(
|
||||
`缺少 ffmpeg.exe(以下任一路径都可):\n${ffmpegCandidates.map((p) => `- ${p}`).join('\n')}`,
|
||||
)
|
||||
}
|
||||
|
||||
if (pythonExe) {
|
||||
const check = spawnSync(
|
||||
pythonExe,
|
||||
['-c', 'import fastapi,uvicorn,requests,psutil;print("runtime_ok")'],
|
||||
{
|
||||
cwd: backendRoot,
|
||||
encoding: 'utf8',
|
||||
windowsHide: true,
|
||||
timeout: 30000,
|
||||
},
|
||||
)
|
||||
if (check.status !== 0) {
|
||||
errors.push(
|
||||
`内置 Python 缺少运行依赖(fastapi/uvicorn/requests/psutil)。\n请先在 ${path.join(
|
||||
backendRoot,
|
||||
'python',
|
||||
)} 环境安装 requirements.txt。\n\nstdout:\n${check.stdout || '(empty)'}\n\nstderr:\n${check.stderr || '(empty)'}`,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if (errors.length) {
|
||||
console.error('[verify:runtime] 运行时检查失败:\n')
|
||||
for (const e of errors) console.error(`- ${e}\n`)
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
const st = spawnSync('node', [path.join(__dirname, 'stage-offline-runtime.mjs')], {
|
||||
cwd: electronRoot,
|
||||
stdio: 'inherit',
|
||||
})
|
||||
if (st.status !== 0) {
|
||||
console.error('[verify:runtime] 生成 offline-runtime 镜像失败')
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
console.log('[verify:runtime] OK: 内置 Python/依赖/ffmpeg 已就绪,offline-runtime 已同步。')
|
||||
|
||||
Reference in New Issue
Block a user