提交 5ed7b96b 编写于 作者: S skyler

update wasm split: add incremental build

上级 ce514810
......@@ -85,3 +85,30 @@ unity导出小游戏项目后,代码是在一个wasm文件里,经过brotli
### 关闭分包
如果想回退到未分包的版本,点击插件页的关闭代码分包按钮即可
### 增量分包
从unity每一次导出后的小游戏,都需要重新分包,对于小版本改动会产生比较烦人的工作量
因此我们支持了增量分包,可以在二次导出时,通过选择之前已经进行过分包的版本,在之前分包的基础上进行增量分包
<image src="../image/wasmsplit/incremental-split.png">
这里主要是通过symbol文件,按函数签名识别相同函数来实现的,因此需要导出时有symbol文件
**注意**
由于unity 2021目前导出symbol的流程有问题,在unity修复之前,需要先手动执行下工具来导出symbol,具体见导出后的unity console信息。
### FAQ
* iOS上进不去游戏
iOS由于加载子包的实现不同,所以最开始的收集会比较卡,这个时候可以观察分包插件面板,如果能看到有新增函数个数的变化,一般就是没问题的。如果新增函数较多(超过1000),可以先继续往下生成分包,再进行收集,这样可以加速已收集部分的运行。
* 没有看到增量分包的界面
由于增量分包是新增的功能,因此之前的项目不能被用来增量更新。更新分包插件后,第二次导出的版本开始才可以使用
另外对于unity 2021的版本,注意检查下minigame目录下有没有webgl.wasm.symbols.unityweb这个文件,没有的话注意按照导出时unity console的指引执行工具生成这个文件。
\ No newline at end of file
var fs = require("fs");
var process = require("process");
function demangle(func) {
// var hasLibcxxabi = !!Module["___cxa_demangle"];
var hasLibcxxabi = false;
// if (hasLibcxxabi) {
// try {
// var buf = _malloc(func.length);
// writeStringToMemory(func.substr(1), buf);
// var status = _malloc(4);
// var ret = Module["___cxa_demangle"](buf, 0, 0, status);
// if (getValue(status, "i32") === 0 && ret) {
// return Pointer_stringify(ret);
// }
// } catch (e) {
// } finally {
// if (buf) _free(buf);
// if (status) _free(status);
// if (ret) _free(ret);
// }
// }
var i = 3;
var basicTypes = {
v: "void",
b: "bool",
c: "char",
s: "short",
i: "int",
l: "long",
f: "float",
d: "double",
w: "wchar_t",
a: "signed char",
h: "unsigned char",
t: "unsigned short",
j: "unsigned int",
m: "unsigned long",
x: "long long",
y: "unsigned long long",
z: "...",
};
var subs = [];
var first = true;
function dump(x) {
if (x) Module.print(x);
Module.print(func);
var pre = "";
for (var a = 0; a < i; a++) pre += " ";
Module.print(pre + "^");
}
function parseNested() {
i++;
if (func[i] === "K") i++;
var parts = [];
while (func[i] !== "E") {
if (func[i] === "S") {
i++;
var next = func.indexOf("_", i);
var num = func.substring(i, next) || 0;
parts.push(subs[num] || "?");
i = next + 1;
continue;
}
if (func[i] === "C") {
parts.push(parts[parts.length - 1]);
i += 2;
continue;
}
var size = parseInt(func.substr(i));
var pre = size.toString().length;
if (!size || !pre) {
i--;
break;
}
var curr = func.substr(i + pre, size);
parts.push(curr);
subs.push(curr);
i += pre + size;
}
i++;
return parts;
}
function parse(rawList, limit, allowVoid) {
limit = limit || Infinity;
var ret = "",
list = [];
function flushList() {
return "(" + list.join(", ") + ")";
}
var name;
if (func[i] === "N") {
name = parseNested().join("::");
limit--;
if (limit === 0) return rawList ? [name] : name;
} else {
if (func[i] === "K" || (first && func[i] === "L")) i++;
var size = parseInt(func.substr(i));
if (size) {
var pre = size.toString().length;
name = func.substr(i + pre, size);
i += pre + size;
}
}
first = false;
if (func[i] === "I") {
i++;
var iList = parse(true);
var iRet = parse(true, 1, true);
ret += iRet[0] + " " + name + "<" + iList.join(", ") + ">";
} else {
ret = name;
}
paramLoop: while (i < func.length && limit-- > 0) {
var c = func[i++];
if (c in basicTypes) {
list.push(basicTypes[c]);
} else {
switch (c) {
case "P":
list.push(parse(true, 1, true)[0] + "*");
break;
case "R":
list.push(parse(true, 1, true)[0] + "&");
break;
case "L": {
i++;
var end = func.indexOf("E", i);
var size = end - i;
list.push(func.substr(i, size));
i += size + 2;
break;
}
case "A": {
var size = parseInt(func.substr(i));
i += size.toString().length;
if (func[i] !== "_") throw "?";
i++;
list.push(parse(true, 1, true)[0] + " [" + size + "]");
break;
}
case "E":
break paramLoop;
default:
ret += "?" + c;
break paramLoop;
}
}
}
if (!allowVoid && list.length === 1 && list[0] === "void") list = [];
if (rawList) {
if (ret) {
list.push(ret + "?");
}
return list;
} else {
return ret + flushList();
}
}
var parsed = func;
try {
if (func == "Object._main" || func == "_main") {
return "main()";
}
// if (typeof func === "number") func = Pointer_stringify(func);
if (func[0] !== "_") return func;
if (func[1] !== "_") return func;
if (func[2] !== "Z") return func;
switch (func[3]) {
case "n":
return "operator new()";
case "d":
return "operator delete()";
}
parsed = parse();
} catch (e) {
parsed += "?";
}
if (parsed.indexOf("?") >= 0 && !hasLibcxxabi) {
// Runtime.warnOnce(
// "warning: a problem occurred in builtin C++ name demangling; build with -s DEMANGLE_SUPPORT=1 to link in libcxxabi demangling"
// );
return func;
}
return parsed;
}
function printHelp() {
console.log(
"Usage: node rewrite_exception_symbol.js <exception_file> <symbol_file>\n"
);
}
if (process.argv.length < 4) {
printHelp();
process.exit(0);
}
var exceptionText = fs.readFileSync(process.argv[2], { encoding: "utf8" });
var symbolText = fs.readFileSync(process.argv[3], { encoding: "utf8" });
function parseSymbol(symbolText) {
var symbolMap = new Map();
var startLine = "var debugSymbols = {";
var start = symbolText.indexOf(startLine);
start += startLine.length;
for (;;) {
var next = symbolText.indexOf(",", start);
var s = symbolText.substr(start, next - start).trim();
// console.log("symbol line:", s);
var b = s.length > 0 ? s.charCodeAt(0) : 0;
if (b < 48 || b > 57) {
// not in [0-9]
break;
}
var mid = s.indexOf(":");
if (mid < 0) {
break;
}
var left = s.substr(0, mid);
var right = s.substr(mid + 1, s.length - mid - 1);
if (right[0] === "'" && right[right.length - 1] === "'") {
right = right.substr(1, right.length - 2);
}
// console.log("symbol:", left, right);
right = demangle(right);
// console.log("after demangle:", right);
// console.log("symbol:", start, mid, left, right);
symbolMap.set(left, right);
start = next + 1;
}
return symbolMap;
}
var symbolMap = parseSymbol(symbolText);
function replaceWithSymbol(src, symbolMap, regex) {
var res = src.matchAll(regex);
// console.log("to replace symbol:", src, regex);
var output = "";
var start = 0;
for (;;) {
var d = res.next();
if (d.value) {
var s = symbolMap.get(d.value[1]);
// console.log("to replace:", d.value, s, start);
if (s) {
output += src.substr(start, d.value.index - start);
output += s + ":wasm-function[" + d.value[1] + "]";
} else {
output += src.substr(start, d.value.index - start);
output += d.value[0];
}
start = d.value.index + d.value[0].length;
}
if (d.done) {
output += src.substr(start);
break;
}
}
return output;
}
var output = replaceWithSymbol(
exceptionText,
symbolMap,
/j(\d+):wasm-function\[\d+]/g
);
output = replaceWithSymbol(
output,
symbolMap,
/<anonymous>:wasm-function\[(\d+)\]/g
);
console.log(output);
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册