本文原链接见 Godot-GDExtension C++ 环境搭建 (Docker+MinGW/跨平台) | Convexwf's Kirakira Blog。

Godot 在4.X 之后推出了 GDExtension,通过第三方绑定扩展功能,目前官方支持的语言只有 C++。通过使用 GDExtension C++ 编写扩展插件,可以作为库文件在 Godot 中交互使用。GDExtension 可以使用 C++ 原生库,提高了性能,还可以自编写游戏逻辑,无需和引擎一同编译。

背景与介绍

笔者刚开始学习 Godot 游戏开发,发现关于 GDExtension 的介绍资料较少,官方文档也很简略,导致我在一开始的环境配置时就踩了不少坑。我主要在 Windows 环境下进行 Godot 开发,Windows 平台下的 C++ 环境可以通过 Microsoft Visual Studio(cl) 或者 MinGW(gcc) 两种方式来进行配置,考虑到 Visual Studio 本身体积庞大,我最后选择了 MinGW-w64 作为 C++ 的编译环境。

一开始我尝试着通过 msysy2 安装 MinGW,但是问题层出不穷,因为平时笔者平时编码都是在 Linux 操作系统,Windows 下的环境配置并不算熟悉,之后还要考虑动态库链接和 Python 环境等问题,于是我在 Github 上找了一圈,看见有人通过 Docker 配置编译环境,只需要本地电脑安装 Git bash 和 Docker 即可,这种方式简单快捷,并且解耦了环境配置与实际开发环境,以后我即使换电脑,甚至换操作系统,也可以很快搭建成功工作流,开箱即用。我在该方案上做了些许调整,接下来介绍一下具体的配置过程。

代码仓库地址:https://github.com/convexwf/godot-gdextension-cpp-examples

打包镜像地址:convexwf/godot-gdextension-cpp-builder

宿主机环境

  • OS: Windows 10
  • Docker Desktop 4.29.0
  • Git version 2.37.3
  • Godot 4.2.2 + godot-cpp 4.2

镜像环境

  • Python 3.11.9
  • scons 4.5.2
  • MinGW-w64 10.2.1(gcc-10)

环境和工具介绍

MinGW 的全称是 Minimalist GNU for Windows,本质是将包括 gcc 在内的 GNU 工具链移植到 Windows 平台,可以将源代码编译成为 Windows 平台下的后缀为 .exe 的可执行文件。MinGW 也可以在 Linux 平台下使用。

MinGW 的编译目标仅兼容 32 位应用程序,于是衍生出了 MinGW-w64,支持 32 位和 64 位的应用程序。MinGW-w64 下载链接见 Downloads - MinGW-w64。

而 Scons 是一个基于 Python 的软件构建工具,类似于 make 和 cmake,由于使用 Python 语法,编写上更加灵活,适用于复杂的项目场景。GDExtension 的 godot-cpp 绑定工具就需要使用 scons 进行编译,所以需要配置 Python 和 scons 环境。

scons 版本依赖于 Python 版本,考虑到之后 scons 的版本更新,不能将基础镜像指定为特定版本的 Python,所以这里选择了 conda 虚拟环境,可以在镜像构建时指定 Python 版本和 scons 版本。conda 虚拟环境可以使用 Anaconda 或者 Miniconda,其中 Anaconda 是一个包含了 conda、Python 和超过 150 个科学包及其依赖项的科学 Python 发行版,体量上非常庞大,而 Miniconda 相对轻量,只包含了 conda 和 Python,需要用户手动安装需要的包。MiniConda 的环境更加简洁,适用于 Docker 镜像构建。

Dockerfile 编写

方案参照的是 mrt-prodz/docker-godot-gdextension-builder: Building Godot 4 GDExtension C++ example with Docker。

这个方案在本地进行测试时,发现镜像构建时会报错,具体原因是找不到特定版本的 g++-mingw-w64-x86-64。于是我调整了一下配置,在一些地方进行了微调。

基础镜像选择的是 continuumio/miniconda3,默认安装了 conda 环境,方便指定 Python 版本和安装 scons 编译工具。

FROM continuumio/miniconda3:latest

这里的 Python 选择的是 3.11.9 版本,一开始我试着配置 Python 3.12.3 + scons 4.7,编译 godot-cpp 时报错找不到 ctypes 模块,努力了下但还是没解决,希望后续哪位同学可以解决这个问题。最新 Python 版本见 Download Python | Python.org。

SHELL ["/bin/bash", "--login", "-c"]

RUN conda init bash

RUN set -ex \
    \
    && conda create -y -n py311 python=3.11.9 \
    && conda activate py311 \
    && conda install -c conda-forge -y scons=${SCONS_VERSION} \
    && ln -s /opt/conda/envs/py311/bin/python /usr/bin/python311

Dockerfile 中使用 conda 命令时,需要注意这是一个交互式命令,首先需要切换终端为 bash,然后使用 conda init bash 初始化 conda 环境,如果不初始化,后续使用 conda 命令会报错 Run 'conda init' before 'conda activate'。之后指定 Python 版本建立激活虚拟环境并安装 scons 编译工具,最后创建一个软链接,方便后续使用。

接下来需要配置 C++ 的编译环境,镜像基于 Debian,使用 apt 包管理器,使用官方源可能会出现部分包下载失败的情况,具体错误为 503 Service Unavailable,这种情况下需要更换为国内源。

# replace the default sources.list with aliyun mirrors
RUN sed -i 's#http://deb.debian.org/#http://mirrors.aliyun.com/#' /etc/apt/sources.list

然后是安装 MingW-w64 的相关库依赖,可以指定相关版本号。

RUN set -ex \
    && DEBIAN_FRONTEND=noninteractive apt-get update \
    && DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends -y \
    build-essential \
    g++-mingw-w64-x86-64=${MINGW_VERSION} \
    binutils-mingw-w64=${MINGW_BINUTIL_VERSION}

其中 set -ex 是用来设置 shell 的行为,-e 选项表示当前命令执行失败时,停止执行后续命令,-x 选项表示输出具体的执行命令和过程。

这样 Dockfile 的编写就完成了,可以通过 docker build 命令构建镜像。

docker build -t convexwf/godot-gdextension-cpp-builder .

构建 C++ 绑定库

构建的目录结构如下(部分省略):

.
|-- .gitignore
|-- Dockerfile
|-- SConstruct
|-- demo
|   |-- .godot
|   |-- gdextension
|   |   |-- gdexample.gdextension
|   |   `-- libgdexample.windows.template_debug.x86_64.dll
|   |-- icon.svg
|   |-- icon.svg.import
|   `-- project.godot
|-- godot-cpp
|   |-- bin
|   |-- cmake
|   |-- gdextension
|   |-- gen
|   |-- include
|   |-- misc
|   |-- src
|   |-- test
|   `-- tools
`-- src
    |-- gdexample.cpp
    |-- gdexample.h
    |-- register_types.cpp
    `-- register_types.h

其中 godot-cpp 是 Godot 官方提供的 C++ 绑定库,通过 git clone 下载到本地。

git clone -b 4.2 git@github.com:godotengine/godot-cpp.git godot-cpp

src 目录用于存放 GDExtension C++ 的源码,构建产物在 godot-cpp/bin 目录下生成,也可以通过 SConstruct 指定构建目标和生成位置。本文使用的 src 目录下的文件是 Godot 4.2 官方文档中的示例代码,具体见 GDExtension C++ example — Godot Engine (stable) documentation in English。

demo 目录用于存放 Godot 项目,一般需要通过 Godot 的编辑器打开。

SConstruct 文件是 scons 编译时的配置文件,可以指定编译目标、编译器、编译选项等,需要用户根据实际需求编写。官方提供了一个 SConstruct 文件 作为参考。

本文涉及的 SConstruct 文件如下:

#!/usr/bin/env python
import os
import sys

GODOT_PROJECT_NAME = "demo"
env = SConscript("godot-cpp/SConstruct")

env.Append(CPPPATH=["src/"])
sources = Glob("src/*.cpp")

# env['platform'] = windows
# env['target'] = template_debug
# env['suffix'] = .windows.template_debug.x86_64
# env['SHLIBSUFFIX'] = .dll

if env["platform"] == "macos":
    library = env.SharedLibrary(
        "{}/gdextension/libgdexample.{}.{}.framework/libgdexample.{}.{}".format(
            GODOT_PROJECT_NAME, env["platform"], env["target"], env["platform"], env["target"]
        ),
        source=sources,
    )
else:
    library = env.SharedLibrary(
        "demo/gdextension/libgdexample{}{}".format(env["suffix"], env["SHLIBSUFFIX"]),
        source=sources,
    )

Default(library)

文件中指定 Windows 平台下的最终编译产物为 demo/gdextension/libgdexample.windows.template_debug.x86_64.dll。

剩下的文件中,.gitignore 文件来自 godot/.gitignore at master · godotengine/godot。

demo/gdexetension 目录下的 gdexample.gdextension 文件是为了能让 Godot 识别载入动态链接库,具体内容会在下一节说明。

因为我们之前已经写好了 Dockerfile,搭配 SConstruct 就可以执行正式构建,执行 shell/build.sh 脚本,或者手动执行下面的命令。

docker run --rm \
    -v ${WorkingDir}:/app \
    convexwf/godot-gdextension-cpp-builder \
    bash -c "cd /app/godot-cpp && source activate gde && scons platform=windows custom_api_file=../extension_api.json"

其中 ${WorkingDir} 是当前工作目录,需要替换为实际的绝对路径。注意 Windows 平台下的 git bash 挂载路径需要使用 // 开头,比如 //d/project。

第一次构建时需要等待较长时间,笔者的八核笔记本构建时间大约在 10 分钟左右,后续构建时间会缩短。构建产物在 godot-cpp/bin 和 demo/gdextension 目录下。

构建 Godot 项目

新建godot项目

首先通过 Godot 新建项目,也可以从已有项目导入,如上图所示。

demo 目录下的 gdextension 目录是用于存放 GDExtension 的相关文件,libgdexample.windows.template_debug.x86_64.dll 是编译产物,gdexample.gdextension 是 GDExtension 的配置文件,文件命名是任意的,只要保持后缀为 .gdextension 即可被 Godot 识别。其内容如下。

[configuration]

entry_symbol = "example_library_init"
compatibility_minimum = "4.2"

[libraries]

macos.debug = "res://gdextension/libgdexample.macos.template_debug.framework"
macos.release = "res://gdextension/libgdexample.macos.template_release.framework"
windows.debug.x86_32 = "res://gdextension/libgdexample.windows.template_debug.x86_32.dll"
windows.release.x86_32 = "res://gdextension/libgdexample.windows.template_release.x86_32.dll"
windows.debug.x86_64 = "res://gdextension/libgdexample.windows.template_debug.x86_64.dll"
windows.release.x86_64 = "res://gdextension/libgdexample.windows.template_release.x86_64.dll"
linux.debug.x86_64 = "res://gdextension/libgdexample.linux.template_debug.x86_64.so"
linux.release.x86_64 = "res://gdextension/libgdexample.linux.template_release.x86_64.so"
linux.debug.arm64 = "res://gdextension/libgdexample.linux.template_debug.arm64.so"
linux.release.arm64 = "res://gdextension/libgdexample.linux.template_release.arm64.so"
linux.debug.rv64 = "res://gdextension/libgdexample.linux.template_debug.rv64.so"
linux.release.rv64 = "res://gdextension/libgdexample.linux.template_release.rv64.so"
android.debug.x86_64 = "res://gdextension/libgdexample.android.template_debug.x86_64.so"
android.release.x86_64 = "res://gdextension/libgdexample.android.template_release.x86_64.so"
android.debug.arm64 = "res://gdextension/libgdexample.android.template_debug.arm64.so"
android.release.arm64 = "res://gdextension/libgdexample.android.template_release.arm64.so"

字段说明:

  • entry_symbol:声明模块的入口函数,和 C++ 源码 register_types.cpp 中的函数名保持一致。
  • compatibility_minimum:最低兼容版本,必填。
  • libraries:声明不同平台下需要识别的动态链接库路径。

保存后查看 Godot 编辑器的输出日志,如果出现 GDExtension configuration file must contain a "configuration/entry_symbol" key: res://gdextension/gdexample.gdextension 等类似错误,可以把 *.gdextension 中的注释和多余空行都删去再看看。

如果一切正常,可以在节点中找到插件 GDExample,之后将其添加到场景中即可。之后的步骤不再赘述,可以参考官方文档进行操作。

总结和后续

至此,我们已经完成了 GDExtension C++ 的环境搭建和构建,通过 Docker 镜像的方式,可以在不同的操作系统下快速搭建开发工作流,提高开发效率。后续开发过程中笔者还会持续调整和优化这个方案,欢迎大家多提 issue 和 PR,友好交流,共同进步!

Reference

posted on 2024-05-04 21:45  孤舟掠影  阅读(1350)  评论(0)    收藏  举报