Files
Genarrative/apps/ai-game-creator-shell/scripts/cargo-features.mjs
T
suzmii 0bfc5768cc 修复AGC跨平台资源构建目标
让Linux no-bundle smoke不再误用Windows随包资源目标。

统一dev与release的Cargo目标和feature解析,补充跨平台回归测试。

同步随包资源staging技术方案中的实际构建目标约定。
2026-09-30 20:24:23 +08:00

135 lines
5.3 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/** 默认桌面能力;显式 feature 参数优先,不把应用参数当 Cargo 参数。 */
export function withDefaultCargoFeatures(argv, features) {
// 只看第一个 `--` 之前的 Tauri 选项:runner 参数区里的 `--features` 会与这里注入的
// 默认值在 Cargo 侧合并,不能当作「用户已经指定过了」而跳过注入。
if (!features.length || tauriOptions(argv).some(hasExplicitFeatures)) {
return argv;
}
return [`--features=${features.join(',')}`, ...argv];
}
/// 第一个 `--` 之前是 Tauri 自己的选项,之后是 runner(Cargo)参数。
function tauriOptions(argv) {
const separator = argv.indexOf('--');
return separator < 0 ? argv : argv.slice(0, separator);
}
/**
* 交给 Tauri 与 Cargo 的参数区间:第一个 `--` 之前是 Tauri 选项,之后到第二个 `--` 是
* runner(Cargo)参数;第二个 `--` 之后由 Tauri 转交应用,不属于构建参数。
* dev 入口(`buildTauriArguments` 会把启动器的单个 `--` 补成 runner + 应用两段)与发布
* 入口都用这一份区间解析,两边的目标与 feature 必须来自同一个口径。
*/
function cargoArguments(argv) {
const separator = argv.indexOf('--');
if (separator < 0) return argv;
const applicationStart = argv.indexOf('--', separator + 1);
return applicationStart < 0 ? argv : argv.slice(0, applicationStart);
}
/// 四种拼写(`--features x` / `--features=x` / `-f x` / `-fx`)都算显式指定。
function hasExplicitFeatures(value) {
return (
value === '--features' ||
value === '-f' ||
value.startsWith('--features=') ||
/^-f.+/u.test(value)
);
}
function parseFeatureNames(raw) {
return String(raw)
.split(',')
.map((name) => name.trim())
.filter(Boolean);
}
export function defaultEditorFeatures(target) {
return target === 'win32' || target.includes('windows')
? ['cocos-editor-execute', 'unity-editor-execute', 'godot-editor-execute']
: [];
}
/**
* 显式 Cargo 目标解析:`--target <triple>` / `--target=<triple>` / `-t <triple>`。
* 应用参数区(第二个 `--` 之后)不参与解析。未显式指定返回 undefined;取值缺失、
* 取到另一个选项或重复指定都失败关闭。
* dev 入口与发布入口共用这一份解析:cargo 的构建目标与随包资源 staging 目标
* 必须来自同一个显式来源,不能一方读参数、另一方回退宿主默认值。
*/
export function readCargoTarget(argv = []) {
const options = cargoArguments(argv);
let target;
for (let index = 0; index < options.length; index += 1) {
const argument = String(options[index]);
let value;
if (argument === '--target' || argument === '-t') {
value = options[index + 1];
index += 1;
} else if (argument.startsWith('--target=')) {
value = argument.slice('--target='.length);
} else if (argument.startsWith('-t') && argument.length > 2) {
value = argument.slice(2).replace(/^=/u, '');
} else {
continue;
}
if (!value?.trim() || String(value).startsWith('-')) {
throw new Error('--target 缺少有效目标');
}
if (target !== undefined) throw new Error('不能重复指定 --target');
target = String(value).trim();
}
return target;
}
/**
* 单一声明式解析:本次构建实际生效的编辑器 feature 集。
* 解析顺序:命令行 `--features`(Cargo 真正收到的参数,不能被环境覆盖)
* > 环境变量 `AGC_DEV_CARGO_FEATURES`(存在即以它为准,空串即关闭默认 feature)
* > 目标平台默认值。
* 传入的必须是「最终交给 Tauri 的参数」:dev 入口与发布入口的 cargo 参数与随包资源
* 准备步骤都消费这里的返回值,否则会出现「cargo 开了 feature、staging 没开(或反之)」。
*/
export function resolveEditorFeatures({
argv = [],
target,
env = process.env,
} = {}) {
const fromArgv = featuresFromArgv(argv);
if (fromArgv) {
return fromArgv;
}
// 变量存在本身即声明「本次 feature 集由环境决定」:空串是有意的关闭,不是未设置。
if (env.AGC_DEV_CARGO_FEATURES !== undefined) {
return parseFeatureNames(env.AGC_DEV_CARGO_FEATURES);
}
return defaultEditorFeatures(target);
}
/// 汇总 cargo 参数区里出现在任何位置的 `--features` / `-f`(Cargo 会把多个 flag 合并);
/// 没有任何 feature flag 时返回 null。显式但为空(如 `--features=`)返回空数组。
export function featuresFromArgv(argv = []) {
const options = cargoArguments(argv);
const features = [];
let found = false;
for (let index = 0; index < options.length; index += 1) {
const value = String(options[index]);
if (value.startsWith('--features=')) {
found = true;
features.push(...parseFeatureNames(value.slice('--features='.length)));
} else if (value === '--features' || value === '-f') {
found = true;
index += 1;
const next = options[index];
// 变参 flag:后面不是选项时才是它的取值。
if (next !== undefined && !String(next).startsWith('-')) {
features.push(...parseFeatureNames(next));
}
} else if (value.startsWith('-f') && value.length > 2) {
found = true;
features.push(...parseFeatureNames(value.slice(2).replace(/^=/u, '')));
}
}
return found ? features : null;
}