首页
/ Godot Engine macOS 平台移植剖析:platform/macos 目录组织、SCons 构建配置与 .app 打包

Godot Engine macOS 平台移植剖析:platform/macos 目录组织、SCons 构建配置与 .app 打包

2026-09-05 14:34:36作者:沈韬淼Beryl

本文以 platform/macos/README.md 为骨架,系统讲解 Godot Engine 的 macOS 平台移植:该目录由哪些 C++/Objective-C/ObjC++ 源文件构成、如何复用 drivers/apple 中的共享 Apple 代码、SCons 构建系统如何针对 macOS 选择工具链与渲染驱动,以及 misc/dist 下的 .app 模板与签名资源如何支撑编辑器与导出模板的打包。读完后,你将能够读懂整个 macOS 移植层的文件职责,并在 scons platform=macos 构建时正确理解每一个平台级选项的生效条件与底层影响。

目录定位:macOS 平台移植的主体

platform/macos 目录包含 macOS 平台移植的全部 C++、Objective-C 与 Objective-C++ 代码,这是 platform/macos/README.md 给出的核心定位。围绕这一定位,目录内的文件可以从源码结构中划分为五个功能组:

功能组 代表文件 职责
OS 层 os_macos.hos_macos.mmgodot_application.mmgodot_application_delegate.mm OS::MACOS 实现与 NSApplication 生命周期管理
显示与窗口 display_server_macos.mmdisplay_server_macos_base.mmgodot_window.mmgodot_content_view.mmkey_mapping_macos.mm DisplayServer 实现、NSWindow 封装、按键映射
图形驱动 gl_manager_macos_angle.mmgl_manager_macos_legacy.mmrendering_context_driver_vulkan_macos.mmplatform_egl.hplatform_gl.hplatform_egl.hmacos_quartz_core_spi.h OpenGL ES 3(原生/ANGLE)与 Vulkan(MoltenVK)上下文管理
系统交互 dir_access_macos.mmtts_macos.mmnative_menu_macos.mmcrash_handler_macos.mmstack_trace_macos.h 文件访问、语音播报、原生菜单栏、崩溃处理与堆栈回溯
构建脚本 SCsubdetect.pyplatform_macos_builders.pymsvs.py SCons 源文件清单、平台探测与构建选项、Bundle 生成动作

此外还有大量 AppKit 辅助视图类,如 godot_button_view.mmgodot_progress_view.mmgodot_status_item.mmgodot_core_cursor.mmgodot_menu_item.mmgodot_open_save_delegate.mm,它们实现 Godot 在 macOS 上的窗口按钮、进度提示、光标与菜单委托等原生 UI 行为。

入口文件按产物类型二选一,这一选择在 platform/macos/SCsub 中完成:

if env["library_type"] == "executable":
    files += ["godot_main_macos.mm"]   # 可执行文件入口
else:
    files += ["libgodot_macos.mm"]    # 作为 libgodot 库时的入口

这与 platform/macos/detect.pyget_flags() 声明的 "supported": ["library", "metal", "mono"] 一致:macOS 移植支持构建为库(libgodot,供 GDExtension 等场景使用)、默认启用 Metal 渲染,并支持 .NET(Mono)构建。

共享 Apple 代码:drivers/apple

README 指出该移植复用了共享的 Apple 代码 drivers/apple。该目录包含三个与 iOS/macOS 共用的组件:

将这部分代码从 platform/macos 抽离,使得 macOS 与 iOS(platform/ios)可以共享同一套 Foundation、日志与线程实现,避免两份重复代码。

SCons 构建:平台探测与选项

在哪些环境下可以构建 macOS

platform/macos/detect.pycan_build() 决定了 scons platform=macos 是否可用:

def can_build():
    if sys.platform == "darwin" or "OSXCROSS_ROOT" in os.environ or "APPLE_LLVM_CROSS" in os.environ:
        return True
    return False

即三种情形之一即可:在 macOS(darwin)上原生构建;通过 OSXCross 交叉工具链交叉构建;或通过 APPLE_LLVM_CROSS 路径从 Linux 用 clang 交叉编译(源码注释说明这是 godot-apple 构建容器采用的免 OSXCross 路径)。

平台级构建选项

get_opts()platform/macos/detect.py)注册的构建选项及默认值如下:

选项 类型 默认值 作用
osxcross_sdk 字符串 darwin16 OSXCross SDK 版本
SWIFT_COMPILER / SWIFT_FRONTEND 字符串 swiftc 二进制路径(Mono 构建用)
MACOS_SDK_PATH 字符串 自动探测 macOS SDK 路径
vulkan_sdk_path 字符串 MoltenVK / Vulkan SDK 路径
macports_clang 枚举 no 改用 MacPorts 提供的 Clang(5.0devel
use_ubsan / use_asan / use_tsan 布尔 未定义行为 / 地址 / 线程 Sanitizer
use_coverage 布尔 生成覆盖率插桩代码
accesskit_sdk_path 字符串 自动推导 AccessKit C SDK 路径(屏幕阅读器支持)
angle_libs 字符串 自动推导 ANGLE 静态库路径(OpenGL over Metal 回退)
bundle_sign_identity 字符串 - 签名编辑器 .app 所用的签名身份
generate_bundle 布尔 构建后自动生成 .app Bundle

其中 accesskit_sdk_pathangle_libs 的默认值推导逻辑在 platform/macos/detect.py:若设置了 LOCALAPPDATA 环境变量则取 %LOCALAPPDATA%/Godot/build_deps(该变量在 Windows 上才有),否则回退到构建脚本所在目录下的 bin/build_deps——源码注释自述这是交叉编译场景下依赖安装脚本的输出位置。

架构与最低系统版本

configure() 首先校验架构,仅接受 x86_64arm64,随后按架构设定部署目标(platform/macos/detect.py):

supported_arches = ["x86_64", "arm64"]
validate_arch(env["arch"], get_name(), supported_arches)

if env["arch"] == "arm64":
    print("Building for macOS 13.0+.")
    env.Append(CCFLAGS=["-arch", "arm64", "-mmacosx-version-min=13.0"])
elif env["arch"] == "x86_64":
    print("Building for macOS 11.0+.")
    env.Append(CCFLAGS=["-arch", "x86_64", "-mmacosx-version-min=11.0"])

也就是说 arm64 构建产物面向 macOS 13.0+,x86_64 构建产物面向 macOS 11.0+。所有 ASFLAGS/CCFLAGS/LINKFLAGS 都会带上对应 -arch-mmacosx-version-min。随后还统一追加 -ffp-contract=off(禁用 FP 收缩以保证数值一致性)以及 -fobjc-arc -fvisibility=hidden(启用 Objective-C ARC、隐藏符号可见性)。

工具链选择

编译器选择按优先级分为四路(platform/macos/detect.py):

  1. OSXCross 交叉工具链:当环境变量 OSXCROSS_ROOT 存在时,将 CC/CXX/AR/RANLIB/AS 指向 $OSXCROSS_ROOT/target/bin/{arch}-apple-{osxcross_sdk}- 前缀的 cctools-port 包装器;
  2. APPLE_LLVM_CROSS 交叉编译:从 Linux 侧直接用 PATH 上的 clang/clang++,显式追加 -target {arch}-apple-darwin-isysroot $MACOS_SDK_PATH,部署目标仍由前述 -mmacosx-version-min 决定;
  3. MacPorts Clangmacports_clangno 时,使用 $MACPORTS_PREFIX/libexec/llvm-{版本}/bin/ 下的 clang 与 llvm-ar 等工具;
  4. 原生构建:直接使用 clang/clang++(支持 CCACHE 前缀加速),并调用 detect_darwin_sdk_path 探测 SDK 后追加 -isysroot

一个值得注意的细节是对 Xcode 15 链接器缺陷的临时规避(platform/macos/detect.py):

# Workaround for Xcode 15 linker bug.
if is_apple_clang(env) and cc_version_major == 1500 and cc_version_minor == 0:
    env.Prepend(LINKFLAGS=["-ld_classic"])

仅在 Apple Clang 版本为 15.0 时切回旧版链接器。

渲染驱动的配置逻辑

渲染相关的配置最能体现 macOS 移植的平台约束:

  • Metal(默认开启)get_flags()"metal": Trueconfigure()platform/macos/detect.py 检查架构,非 arm64 时打印警告并关闭 Metal——即当前仓库中 Metal 驱动实质上是 arm64 专属路径;开启后定义 METAL_ENABLEDRD_ENABLED 并链接 Metal、MetalKit、MetalFX 框架;
  • OpenGL ES 3opengl3 开启时定义 GLES3_ENABLED;若同时启用 angle,则链接预编译的 ANGLE 静态库(-lANGLE.macos.{arch}-lEGL.macos.{arch}-lGLES.macos.{arch})并额外链接 Metal 框架;找不到 ANGLE 库时会给出警告,提示运行 misc/scripts/install_angle.py 安装依赖或用 angle=no 显式关闭(见 platform/macos/detect.py);
  • Vulkan:macOS 上的 Vulkan 由 MoltenVK 提供。由于 get_flags()"use_volk": False,构建时直接链接系统安装的 MoltenVK(platform/macos/detect.py):定义 VULKAN_ENABLEDRD_ENABLED,追加 -framework Metal-lMoltenVK,并通过 detect_mvk()macos-arm64_x86_64macos-{arch} 两类目录中查找 SDK;找不到则报错退出,提示用 vulkan_sdk_path 指定路径。对应的运行时上下文驱动实现位于 rendering_context_driver_vulkan_macos.mm

Sanitizer、LTO 与栈大小

Sanitizer 相关配置在 platform/macos/detect.py:任一 Sanitizer 启用时产物名追加 .san 后缀;UBSan 同时启用了 undefined 的一组细粒度检查与 nullability 检查,ASan 追加 pointer-subtract,pointer-compare,TSan 使用 -fsanitize=thread。栈大小上,普通可执行文件链接参数为 -Wl,-stack_size,0x800000(8 MiB,与 detect.pySTACK_SIZE = 8388608 一致),启用 Sanitizer 时提升到 30 MiB(STACK_SIZE_SANITIZERS = 30 * 1024 * 1024),以容纳 Sanitizer 的额外栈开销。

LTO 方面(platform/macos/detect.py),lto=auto 会被降为 none,源码注释说明“macOS 上 LTO 的收益(体积、性能)尚未被明确证实”;显式指定时支持 thin-flto=thin)与普通 -flto

系统框架链接清单

platform/macos/detect.py 为 macOS 移植统一追加宏定义与框架链接:

env.Append(CPPDEFINES=["MACOS_ENABLED", "UNIX_ENABLED", "COREAUDIO_ENABLED", "COREMIDI_ENABLED"])
env.Append(LINKFLAGS=[
    "-framework", "Cocoa", "-framework", "Carbon", "-framework", "AudioUnit",
    "-framework", "CoreAudio", "-framework", "CoreMIDI", "-framework", "IOKit",
    "-framework", "GameController", "-framework", "CoreHaptics", "-framework", "CoreVideo",
    "-framework", "AVFoundation", "-framework", "CoreMedia", "-framework", "QuartzCore",
    "-framework", "Security", "-framework", "UniformTypeIdentifiers", "-framework", "IOSurface",
])
env.Append(LIBS=["pthread", "z"])

这些框架分别对应 UI(Cocoa/Carbon/QuartzCore)、音频(AudioUnit/CoreAudio)、MIDI、手柄(GameController/CoreHaptics)、视频采集(AVFoundation/CoreMedia/IOSurface)与压缩(z)能力。此外还统一设置了动态库搜索路径:

env.Append(LINKFLAGS=["-rpath", "@executable_path/../Frameworks", "-rpath", "@executable_path"])

这使得 .app Bundle 内 Contents/Frameworks 下的依赖库能被按相对路径解析。

SCsub:源文件清单与产物形态

platform/macos/SCsub 定义了参与编译的文件清单与产物形态:

.app 打包资源与签名配置

README 提到的 misc/dist/macos 及两个 .app 模板,构成了 macOS 打包的静态资源层:

编辑器 Bundle 模板:misc/dist/macos_tools.app

misc/dist/macos_tools.app 是用于打包 macOS 编辑器的 .app 模板,其 Contents/ 下包含 Info.plistPkgInfoResources/:资源中包含 GDScript、GodotLG(Godot 主图标)、Project、Resource、Scene、Shader 等 .icns 文件,以及约 60 个语言目录(en.lprojzh_CN.lprojja.lproj 等)的 InfoPlist.strings,用于本地化 Bundle 显示名称。构建时 generate_bundle 动作会把编译出的可执行文件复制进该模板,形成完整的编辑器 Bundle;bundle_sign_identity 选项则指定对编辑器 Bundle 使用的签名身份。

导出模板 Bundle:misc/dist/macos_template.app

misc/dist/macos_template.app 用于打包 macOS 导出模板(export template),结构更精简:Contents/Info.plistPkgInfo,以及 Resources/ 下的 icon.icnsPrivacyInfo.xcprivacy。可以推断该 .xcprivacy 隐私清单是为满足 Apple 平台对应用隐私披露的要求而随模板分发的。导出模板最终会供编辑器在“导出项目”时打入用户游戏。

图标与 entitlements

misc/dist/macos 还包含:

其中正式版 editor.entitlements 声明了以下权限:

entitlement 含义
com.apple.security.cs.allow-dyld-environment-variables 允许 dyld 环境变量
com.apple.security.cs.allow-jit 允许 JIT
com.apple.security.cs.allow-unsigned-executable-memory 允许未签名可执行内存
com.apple.security.cs.disable-executable-page-protection 关闭可执行页保护
com.apple.security.cs.disable-library-validation 关闭库验证
com.apple.security.device.audio-input 允许访问麦克风
com.apple.security.device.camera 允许访问摄像头

这些项对应 Godot 编辑器的典型运行时需求:GDScript/Jolt 等组件可能写入或加载内存页、需要 dlopen 外部库,而音频输入与摄像头权限服务于编辑器内对麦克风和摄像头设备的测试(对应 detect.py 中链接的 AudioUnit/CoreAudio/AVFoundation 框架)。

编辑器导出功能

macOS 移植的另一半职责是在编辑器内提供“导出到 macOS”的能力,实现位于 platform/macos/export 目录:export.cpp / export.hexport_plugin.cpp / export_plugin.h,以及 logo.svgrun_icon.svg 等图标资源。其暴露给脚本与文档的编辑器类由 platform/macos/detect.pyget_doc_classes() 声明,文档类定义见 platform/macos/doc_classes/EditorExportPlatformMacOS.xml(对应 EditorExportPlatformMacOS 类,get_doc_path() 指向 doc_classes)。这一层负责在用户点击“导出项目”时调用 misc/dist/macos_template.app 模板完成 macOS 目标的打包。

相关文档章节

platform/macos/README.md 末尾的 Documentation 小节指向官方文档站点的三篇配套文章,本篇不复制外部链接,仅列出其覆盖的操作范围,供查阅:

  • Compiling for macOS:从源码构建 macOS 平台移植的步骤,对应本文“SCons 构建”一节的各项选项;
  • Exporting for macOS:使用已编译的导出模板导出项目的步骤,对应 platform/macos/export 的导出逻辑;
  • Running Godot apps on macOS:在 macOS 上运行 Godot 项目的说明。

小结

macOS 移植在仓库中的形态可以概括为三层:

  1. 代码层platform/macos):以 os_macos.mm 为核心的 OS 实现、AppKit 窗口与视图封装、OpenGL/Metal/Vulkan 三种图形路径的上下文管理,以及编辑器的内嵌运行/调试支持;共享的 Apple 基础代码上提至 drivers/apple 与 iOS 复用;
  2. 构建层detect.py + SCsub):按架构锁定部署目标(arm64 面向 macOS 13+、x86_64 面向 macOS 11+),在原生 clang、OSXCross、APPLE_LLVM_CROSS、MacPorts Clang 四条工具链路径间切换,并按 opengl3/angle/metal/vulkan 组合链接 Metal、MoltenVK、ANGLE 与全套系统框架;
  3. 打包层misc/dist/macos + 两个 .app 模板):编辑器 Bundle 模板、导出模板 Bundle、本地化资源、图标源文件与两版 entitlements 共同保证签名与沙箱行为。

三层层层对应,读懂这一目录即掌握了 Godot 在 macOS 上“从源码到签名 .app”的完整链路。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.12 K
2.72 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
528
588
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
906
1.82 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
854
1.34 K
docsdocs
暂无描述
Markdown
891
5.78 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.53 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.34 K
1.45 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
987
504
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
540
384