feat(tree): close rust family shell cutover
This commit is contained in:
@@ -0,0 +1,122 @@
|
||||
#!/usr/bin/env node
|
||||
"use strict";
|
||||
|
||||
const fs = require("fs/promises");
|
||||
const path = require("path");
|
||||
const { spawnSync } = require("child_process");
|
||||
|
||||
const REPO_ROOT = path.resolve(__dirname, "..", "..");
|
||||
const RUST_ROOT = path.join(REPO_ROOT, "rust");
|
||||
const CRATE_ROOT = path.join(RUST_ROOT, "crates", "tree-shell-runtime-wasm");
|
||||
const GENERATED_ROOT = path.join(CRATE_ROOT, "generated");
|
||||
const TOOLCHAIN = "1.89.0-x86_64-unknown-linux-gnu";
|
||||
const TARGET = "wasm32-unknown-unknown";
|
||||
const OUT_NAME = "mnote-tree-shell-runtime";
|
||||
const MANIFEST_PATH = path.join(CRATE_ROOT, "Cargo.toml");
|
||||
const WASM_PATH = path.join(
|
||||
RUST_ROOT,
|
||||
"target",
|
||||
TARGET,
|
||||
"debug",
|
||||
"tree_shell_runtime_wasm.wasm",
|
||||
);
|
||||
const ENTRY_PATH = path.join(GENERATED_ROOT, `${OUT_NAME}.js`);
|
||||
const OUTPUT_WASM_PATH = path.join(GENERATED_ROOT, `${OUT_NAME}_bg.wasm`);
|
||||
const GITIGNORE_PATH = path.join(GENERATED_ROOT, ".gitignore");
|
||||
|
||||
function run(command, args, options = {}) {
|
||||
const result = spawnSync(command, args, {
|
||||
cwd: options.cwd ?? REPO_ROOT,
|
||||
env: process.env,
|
||||
encoding: "utf8",
|
||||
stdio: "pipe",
|
||||
});
|
||||
|
||||
if (result.status === 0) {
|
||||
return result;
|
||||
}
|
||||
|
||||
const stdout = (result.stdout || "").trim();
|
||||
const stderr = (result.stderr || "").trim();
|
||||
const details = [stdout, stderr].filter(Boolean).join("\n");
|
||||
throw new Error(
|
||||
[`命令失败:${command} ${args.join(" ")}`, details].filter(Boolean).join("\n"),
|
||||
);
|
||||
}
|
||||
|
||||
async function ensureGeneratedDir() {
|
||||
await fs.rm(GENERATED_ROOT, { recursive: true, force: true });
|
||||
await fs.mkdir(GENERATED_ROOT, { recursive: true });
|
||||
await fs.writeFile(GITIGNORE_PATH, "*\n!.gitignore\n", "utf8");
|
||||
}
|
||||
|
||||
async function verifyOutput() {
|
||||
const entrySource = await fs.readFile(ENTRY_PATH, "utf8");
|
||||
await fs.access(OUTPUT_WASM_PATH);
|
||||
|
||||
if (!entrySource.includes("export function reduceTreeShellRuntime")) {
|
||||
throw new Error("tree shell runtime js glue 缺少 reduceTreeShellRuntime 导出");
|
||||
}
|
||||
}
|
||||
|
||||
async function buildTreeShellRuntime() {
|
||||
// 说明:tree shell iframe 主链直接加载固定 wasm/js 产物,因此在 Next 启动前先生成正式 artifact。
|
||||
run("rustup", ["target", "add", TARGET, "--toolchain", TOOLCHAIN], { cwd: RUST_ROOT });
|
||||
run(
|
||||
"cargo",
|
||||
[
|
||||
`+${TOOLCHAIN}`,
|
||||
"build",
|
||||
"--manifest-path",
|
||||
MANIFEST_PATH,
|
||||
"--package",
|
||||
"tree-shell-runtime-wasm",
|
||||
"--lib",
|
||||
"--target",
|
||||
TARGET,
|
||||
"--locked",
|
||||
],
|
||||
{ cwd: RUST_ROOT },
|
||||
);
|
||||
|
||||
await ensureGeneratedDir();
|
||||
|
||||
run(
|
||||
"wasm-bindgen",
|
||||
[
|
||||
WASM_PATH,
|
||||
"--target",
|
||||
"web",
|
||||
"--out-dir",
|
||||
GENERATED_ROOT,
|
||||
"--out-name",
|
||||
OUT_NAME,
|
||||
],
|
||||
{ cwd: RUST_ROOT },
|
||||
);
|
||||
|
||||
await verifyOutput();
|
||||
|
||||
return {
|
||||
generatedRoot: GENERATED_ROOT,
|
||||
entryPath: ENTRY_PATH,
|
||||
wasmPath: OUTPUT_WASM_PATH,
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
buildTreeShellRuntime,
|
||||
GENERATED_ROOT,
|
||||
OUT_NAME,
|
||||
};
|
||||
|
||||
if (require.main === module) {
|
||||
buildTreeShellRuntime()
|
||||
.then(({ generatedRoot }) => {
|
||||
process.stdout.write(`tree shell runtime 已生成:${generatedRoot}\n`);
|
||||
})
|
||||
.catch((error) => {
|
||||
process.stderr.write(`${error instanceof Error ? error.stack ?? error.message : String(error)}\n`);
|
||||
process.exit(1);
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user