build steps

This commit is contained in:
2026-06-07 22:55:56 +08:00
parent dff504ef67
commit 7b42a6be63
14 changed files with 467 additions and 18 deletions
+95 -7
View File
@@ -12,12 +12,23 @@
- 运行时热重载保留字段状态,接近 Python/Lua 那种 reload 手感
- demo 是一个简单 Flappy Bird,用来测输入、Process、状态迁移和重载
先拉子模块:
## 编译
拉子模块:
```bash
git submodule update --init --recursive
```
LeanCLR 默认会把所有未实现的 icall 视为致命错误并 abort。本项目对接的 Godot API 只是一小部分,所以必须先把这个开关关掉,否则跑 demo 时第一碰到未实现接口就崩。修改 `thirdparty/leanclr/src/runtime/build_config.h`
```c
-#define LEANCLR_FATAL_ON_RAISE_NOT_IMPLEMENTED_ERROR 1
+#define LEANCLR_FATAL_ON_RAISE_NOT_IMPLEMENTED_ERROR 0
```
> 这个 patch 在子模块里,`git submodule update` 之后需要重新打。
编 native 扩展:
```bash
@@ -25,23 +36,101 @@ cmake -S . -B build-master
cmake --build build-master --config Debug --target leanclr_godot
```
> 第一次 `cmake -S . -B build-master` 会通过 FetchContent 拉 godot-cpp 4.5,但此时 `src/generated/godot_api.generated.cpp` 还不存在,配置会失败。所以顺序是:
>
> ```bash
> cmake -S . -B build-master
> python3 tools/binding_generator/generate_bindings.py --api build-master/_deps/godot-cpp-src/gdextension/extension_api.json
> cmake -S . -B build-master # 再配一次,让 add_library 看到生成的 cpp
> cmake --build build-master --config Debug --target leanclr_godot
> ```
> `GODOT_CPP_BRANCH` 默认是 `4.5`,仓库里已经为 4.5 打过两个补丁(见下方「已知补丁」)。
编 demo 的 C#
```bash
dotnet msbuild project/Game.csproj /p:Configuration=Debug
dotnet msbuild managed/GodotSharpCompat/GodotSharpCompat.csproj -p:Configuration=Debug
dotnet msbuild project/Game.csproj -p:Configuration=Debug
```
运行项目:
> `dotnet msbuild` 只能用单横线参数(`-p:...`),双横线(`/p:...`)会报 `MSB1008: 只能指定一个项目`。
> Windows 上要用 `python3`,别用 `python`(会被 Microsoft Store 别名劫持弹出安装器)。
## 运行
```bash
/Applications/Godot.app/Contents/MacOS/Godot --path project
"/path/to/Godot" --path project
```
几个常看的文件:
> 把 `/path/to/Godot` 换成你机器上实际的 Godot 可执行文件路径。这台机器是 `D:/Projects/godot-build/build/godot.exe`Godot 4.6.3。
## 已知补丁
### `thirdparty/leanclr` 子模块
- `src/runtime/build_config.h``LEANCLR_FATAL_ON_RAISE_NOT_IMPLEMENTED_ERROR` 设为 `0`(见上文)。
### `src/leanclr_script.cpp`
godot-cpp 4.5 把 `gdextension_interface_script_instance_create3``gdextension_interface::` 命名空间搬到了 `godot::internal::` 里,且原来的 `<godot_cpp/core/gdextension_interface_loader.hpp>` 头文件已经不存在。要把:
```cpp
#include <godot_cpp/core/gdextension_interface_loader.hpp>
// ...
void* script_instance = gdextension_interface::script_instance_create3(&script_instance_info(), instance);
```
改成:
```cpp
#include <godot_cpp/godot.hpp>
// ...
void* script_instance = ::godot::internal::gdextension_interface_script_instance_create3(&script_instance_info(), instance);
```
### `tools/binding_generator/generate_bindings.py`
godot-cpp 4.5 把 `ClassDB` 整体重命名成了 `ClassDBSingleton` 单例包装。生成器原本的 `CPP_HEADER_NAME_OVERRIDES["ClassDB"] = "class_db_singleton"` 只重命名了头文件路径,C++ 类名仍是 `ClassDB`,编译会爆 `get_class_static` 不存在。补丁:新增 `SINGLETON_CLASS_CPP_NAMES = {"ClassDB": "ClassDBSingleton"}`,让生成出的 C++ 走 `ClassDBSingleton::get_singleton()->method(...)`C# 侧 `ClassDB` 的方法全部变成 `static`
### `CMakeLists.txt`Web 构建)
仓库里已经为 Web 构建持久化地打了两个补丁,都在 `if(EMSCRIPTEN)` 块(或紧邻它的 `option` 块)里:
1. **强制单线程**Web 当前不支持多线程,且 `-sSIDE_MODULE + pthreads` 在 emcc 里是实验性的):
```cmake
if(EMSCRIPTEN)
set(GODOTCPP_THREADS OFF CACHE BOOL "godot-cpp threading support" FORCE)
endif()
```
2. **降到 `-O1`**:自动生成的 `godot_api.generated.cpp` 里有几千个 invoker 函数,`-O3` 下编译器会把参数拆包全部内联,单个函数会塞进 11 万+ 局部变量,浏览器加载时会报 `Uncaught (in promise) CompileError: WebAssembly.instantiate(): Compiling function #N failed: local count too large`(V8 单函数局部变量上限 50,000)。`leanclr_godot` target 在 `if(EMSCRIPTEN)` 块里被显式加了 `target_compile_options(leanclr_godot PRIVATE -O1)`。
Web 构建方法:
```bash
# 需要 Emscripten 3.1+、Ninja 都在 PATH 上
rm -rf build-web
cmake -S . -B build-web -G Ninja \
-DCMAKE_TOOLCHAIN_FILE="<emsdk>/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake" \
-DCMAKE_BUILD_TYPE=Release
cmake --build build-web --target leanclr_godot
```
> 这台机器 Emscripten 在 `D:/Projects/emsdk/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake`。
> `leanclr.gdextension` 已经配了 `web.release.wasm32 = "res://bin/Release/leanclr_godot.wasm"`,构建产物会自动落到 `project/bin/Release/libleanclr_godot.wasm`。要跑起来用编辑器导出一份 Web 即可(或 `godot --headless --export-release "Web" output.html` 配 `project/export_presets.cfg`)。
>
> 注意事项:
> - `-O1` 让 wasm 从 `-O3` 时的 26 MB 涨到 10 MB 左右(Release 去掉符号),是必要的代价。
> - `leanclr_wasm_libcxx_shim.cpp` 提供 Emscripten libc++ 缺的 `std::__1::__hash_memory` 符号,Web 链接时会自动包含。
> - `em++: warning: ignoring unsupported linker flag: -soname` 是无害的,`-soname` 是 ELF 链接器标志,emcc 不识别但 wasm 产物仍然正确。
## 几个常看的文件
`src/` : GDExtension 和 bridge。
`managed/GodotSharpCompat/` : 给 C# 用的 Godot API 外观。
`managed/GodotSharpCompat/` : 给 C# 用的 Godot API 外观。`Generated/` 子目录是绑定生成器的产物,`.gitignore` 已忽略。
`project/runtime_hot_reload_demo.tscn` : 现在的主 demo。
@@ -50,4 +139,3 @@ dotnet msbuild project/Game.csproj /p:Configuration=Debug
`project/scripts/RuntimeCSharpEditor.gd` : 游戏里的 C# 编辑器窗口。
`project/leanclr/live_reload.txt` : 热重载 marker。写 `Game` 就回到默认 `Game.dll`,写别的 assembly 名就切到那个 dll。