首页
/ Ladybird 高级构建指南:Sanitizer、Fuzzer、Clang 插件与 Flatpak 打包的深度构建配置

Ladybird 高级构建指南:Sanitizer、Fuzzer、Clang 插件与 Flatpak 打包的深度构建配置

2026-09-04 09:52:10作者:劳婵绚Shirley

本文聚焦 Ladybird 浏览器仓库中 AdvancedBuildInstructions.md 所覆盖的高级构建场景:脚本之外需要直接用 Ninja 调用的构建目标、全部可选 CMake 构建选项、CMake 缓存的修改方式、Fuzzer 与 Clang 插件的启用、Flatpak 包构建,以及“无优化调试”和 Vulkan 验证层这两个实战技巧。读完本文,你可以在 Ladybird 仓库中按需配置记忆安全检测、编译期静态检查、模糊测试环境,并独立构建 Flatpak 分发包与特定调试构建。

脚本覆盖不到的 Ninja 构建目标

Ladybird 的构建入口 Meta/ladybird.py 对 CMake 暴露的构建目标做了一层抽象,但少数目标没有经过脚本包装,必须手动进入构建目录调用。以默认的 Release 构建为例,先进入 Build/release,再执行 ninja <target>

Ninja 目标 作用
ninja check-style 运行与 CI 相同的 linter,校验被改动文件的代码风格
ninja lint-shell-scripts 用 shellcheck 检查源码树中 shell 脚本的风格
ninja all_generated 只构建全部生成代码,不构建整个系统;适合让分析工具直接使用 compile_commands.json 的场景

从源码结构看,前两个目标正是在根 CMakeLists.txt 中以 add_custom_target 定义的:lint-shell-scripts 调用 Meta/Linters/lint_shell_scripts.shcheck-style 调用 Meta/Linters/check_style.py,且都带 USES_TERMINAL 以便交互式输出。

CMake 可选构建选项全解

CMakeLists.txt 通过 include(cmake_options) 引入 Meta/CMake/cmake_options.cmake 定义全部可配置选项,配合 Meta/CMake/sanitizers.cmake 注入 sanitizer 编译/链接参数。文档列出的选项及其实用含义如下:

Sanitizer 系列(均默认 OFF,定义于 Meta/CMake/cmake_options.cmake):

  • ENABLE_ADDRESS_SANITIZER:为 Lagom 测试用例构建期注入内存破坏检测(缓冲区溢出、内存泄漏等)。对应 Meta/CMake/sanitizers.cmake 中的 -fsanitize=address -fno-omit-frame-pointer 编译与链接参数。
  • ENABLE_MEMORY_SANITIZER:检测未初始化内存访问,对应 -fsanitize=memory -fsanitize-memory-track-origins
  • ENABLE_UNDEFINED_SANITIZER:检测未定义行为(如空指针解引用、有符号整数溢出),同时覆盖 Lagom 与 Ladybird,对应 -fsanitize=undefined
  • UNDEFINED_BEHAVIOR_IS_FATAL:让 UBSan 错误不可恢复(追加 -fno-sanitize-recover=undefined)。开启它会降低 ENABLE_UNDEFINED_SANITIZER 带来的性能开销,适合只关心“是否触发 UB”而非逐条恢复继续执行的场景。

其他选项

  • ENABLE_COMPILER_EXPLORER_BUILD:跳过 Lagom 中非库实体的构建(仅对 Lagom 生效),从 CMakeLists.txt 可见该开关会跳过 UtilitiesTests 目录的加入。
  • ENABLE_FUZZERS / ENABLE_FUZZERS_LIBFUZZER / ENABLE_FUZZERS_OSSFUZZ:分别为系统各部分构建通用 fuzzer、基于 Clang libFuzzer 的 fuzzer、OSS-Fuzz 兼容 fuzzer。后两者一旦开启,CMakeLists.txt 会自动把 ENABLE_FUZZERS 置为 ON,并加入 Meta/Fuzzers 子目录。libFuzzer 路径会额外追加 -fsanitize=fuzzer 编译与链接选项,且要求 Clang 工具链——用 GCC 配置时 CMake 会直接 FATAL_ERROR 报错退出。
  • ENABLE_ALL_THE_DEBUG_MACROS:CI 用它验证所有调试代码能否编译,平时不应开启——它会污染控制台输出并显著拖慢运行速度。需要调试输出时,应只开启下方介绍的单个 <component>_DEBUG 宏。
  • ENABLE_COMPILETIME_FORMAT_CHECK:编译期校验 std::format 风格格式串的有效性,默认开启,开启时向全局追加 ENABLE_COMPILETIME_FORMAT_CHECK 宏定义。
  • INCLUDE_WASM_SPEC_TESTS:下载并纳入 WebAssembly 规范测试套件,使用前需在本机安装 prettierwasm-tools
  • INCLUDE_FLAC_SPEC_TESTS:下载并纳入 xiph.org 的 FLAC 测试套件。
  • LADYBIRD_CACHE_DIR:下载文件的共享缓存位置,默认值为 ${PROJECT_BINARY_DIR}/../caches(即构建目录旁的 caches/)。一般无需手工设置,仅发行版打包等场景需要。
  • ENABLE_NETWORK_DOWNLOADS:默认 ON,允许构建期间联网下载依赖文件;关掉后进入离线构建模式,前提是 LADYBIRD_CACHE_DIR 已按构建预期的目录结构预先填充好。
  • ENABLE_CLANG_PLUGINS:启用编译期代码静态分析插件,详见下文 Clang 插件 一节。

细粒度 <component>_DEBUG

代码库中大量模块提供调试输出能力,形式是向调试控制台打印额外信息,由构建期的 <component_name>_DEBUG 宏按组件单独启用。全部宏清单维护在 Meta/CMake/all_the_debug_macros.cmake,涵盖 AK、CSS、HTML 解析、HTTP 缓存、TLS、WebGL、WASM 验证器、WebDriver、Vulkan 验证层等 80 余个组件,例如:

  • CSS_PARSER_DEBUGHTML_PARSER_DEBUG:样式与 HTML 解析链路;
  • HTTP_DISK_CACHE_DEBUGHTTP_MEMORY_CACHE_DEBUG:HTTP 缓存;
  • WEBGL_CONTEXT_DEBUGCOMPOSITOR_DEBUG:图形与合成;
  • VULKAN_VALIDATION_LAYERS_DEBUG:Vulkan 验证层(用法见文末一节)。

该文件同时以注释标出了被排除的误报项,如 ANDROID_LOG_DEBUG 是日志级别而非调试开关,以及 skia vcpkg 端口覆盖层的 gn_*_DEBUG 等,可见这份清单是经过人工核对的。

CMake 缓存操作

CMake 把变量和选项缓存在二进制目录中,开发者可以在持久化配置缓存中改写 set() 过的变量。有三种主要方式:

cmake path/to/binary/dir -DVAR_NAME=Value
ccmake   # TUI 界面
cmake-gui

选项既可以在首次创建二进制目录的 cmake 调用中作为初始缓存写入,也可以在目录创建后用上述任一方式修改。布尔类选项(如 ENABLE_<setting><component_name>_DEBUG)取 ON 表示启用、OFF 表示禁用:

# 对已存在的构建目录重新配置,启用进程调试
$ cmake -B Build/ladybird -DPROCESS_DEBUG=ON

Clangd 配置

仓库根目录有一个 .clangd 配置文件。其中一条配置指明了编译数据库(compilation database)的位置,当前内容是:

CompileFlags:
  CompilationDatabase: Build/release

由于不同的构建配置(Release、Debug、Sanitizer)对应不同的构建目录,文件里写死的路径可能与你实际的构建目录不一致。此时可以编辑 .clangd 文件,把 CompilationDatabase 指向你自己的构建目录(如 Build/ladybird 或自定义目录)。另外注意根 CMakeLists.txt 已设置 CMAKE_EXPORT_COMPILE_COMMANDS ON,任何构建目录都会生成 compile_commands.json,这也是前文 ninja all_generated 能单独服务于语言服务器和分析工具的原因。

Clang 插件

Clang 插件用于在编译期校验代码正确性。当前它们主要检测 JavaScript 相关的垃圾回收误用,例如漏访(neglecting to visit)某个 GC 托管类型。插件源码位于 Meta/ClangPluginsLibJSGCPluginAction.cpp 实现 LibJS 的 GC 检查,LambdaCapturePluginAction.cpp 检查 lambda 捕获;根 CMakeLists.txt 中把它们包装为 JSClangPluginGenericClangPlugin 两个 INTERFACE 库,并仅在 Clang 主机(非交叉、非 fuzzer、非 Compiler Explorer)构建时编译启用。

启用条件:

  1. 需要安装 Clang 开发头文件,例如 Ubuntu 上的 libclang-dev 包;
  2. 通过前文“CMake 缓存操作”的方式设置 -DENABLE_CLANG_PLUGINS=ON

启用后,建议为 ccache 设置如下环境变量:

export CCACHE_COMPILERCHECK="%compiler% -v"

原因:ccache 默认会把链接进编译器调用的插件本身计入文件哈希,一旦插件更新,所有文件的哈希都会变化,缓存全部失效。设置该变量后,ccache 不再把插件纳入哈希计算,插件更新也不会强制全量重编译。

构建 Flatpak 包

Ladybird 在仓库内维护了一份 Flatpak manifest,位于 Meta/CMake/flatpak/org.ladybird.Ladybird.json(同目录还有 cargo-sources.jsonskiaangle 子目录的构建辅助文件)。推荐用大多数发行版都提供的 flatpak-builder 工具构建,先按 Flatpak 官方 setup 文档配置好用户级 Flatpak 构建环境和 Flathub 仓库,然后在仓库根目录执行:

flatpak-builder --user --force-clean --install-deps-from=flathub \
  --ccache --repo=Build/repo --install Build/flatpak \
  Meta/CMake/flatpak/org.ladybird.Ladybird.json

该命令会构建 Flatpak 包并安装到本地 Flatpak 仓库 Build/repo。由于它要下载并构建 Ladybird 的全部依赖,耗时较长;flatpak-builder 会把缓存与构建产物放到 .flatpak-builderBuild/repoBuild/flatpak 三处。

构建完成后运行:

flatpak run --user org.ladybird.Ladybird

需要调试时,给 flatpak run--devel--command=sh,即可进入 Flatpak 沙箱内的 shell:

flatpak run --user --command=sh --devel org.ladybird.Ladybird

无优化调试:临时把 Debug 构建降到 -O0

在调试器中检查某些栈帧变量时,可能遇到类似这样的错误:

error: Couldn't look up symbols: __ZN2AK6Detail10StringBaseD2Ev Hint: The expression tried to call a function that is not present in the target, perhaps it was optimized out by the compiler.

出现这种情况时,可以临时把 Debug 构建的优化级别从 -Og 降到 -O0,使所有调试符号始终可用。默认配置位于 Meta/CMake/compile_options.cmake

if (CMAKE_BUILD_TYPE STREQUAL "Debug")
    if (NOT MSVC)
        add_cxx_compile_options(-ggdb3)
        add_cxx_compile_options(-Og)
    endif()

操作步骤(注意:官方建议只在“正在用调试器检查某个特定构建的状态”时临时应用此改动,跑 WPT 或树内测试时不要保留):

  1. 在 shell 中粘贴并执行以下补丁,把 -Og 改为 -O0(也可以用你平常的方式应用该 diff):

    $ patch -p1 <<EOF
    diff --git a/Meta/CMake/compile_options.cmake b/Meta/CMake/compile_options.cmake
    --- a/Meta/CMake/compile_options.cmake
    +++ b/Meta/CMake/compile_options.cmake
    @@
         if (NOT MSVC)
             add_cxx_compile_options(-ggdb3)
    -        add_cxx_compile_options(-Og)
    +        add_cxx_compile_options(-O0)
         endif()
    EOF
    
  2. 让 git 忽略这次本地改动,避免误提交:

    git update-index --skip-worktree Meta/CMake/compile_options.cmake
    
  3. Debug preset 重新构建,回到调试器,之前无法检查的栈帧变量现在都可以查看了。

调试完成后恢复原状:

git update-index --no-skip-worktree Meta/CMake/compile_options.cmake \
    && git checkout Meta/CMake/compile_options.cmake

启用 Vulkan 验证层调试

以 Release 构建为例,用 CMake 缓存选项打开 Vulkan 验证层:

cmake -B Build/release -DVULKAN_VALIDATION_LAYERS_DEBUG=ON

然后照常构建即可(该宏正是 all_the_debug_macros.cmake 清单中的 VULKAN_VALIDATION_LAYERS_DEBUG)。运行时如果验证层配置正确,创建 VulkanContext 时会看到 Vulkan validation layers: active 的输出;如果看到 Vulkan validation layers: not available,说明系统缺少验证层——Ubuntu 上可安装 vulkan-validationlayers 包,Arch、Fedora、NixOS 等发行版包名通常为 vulkan-validation-layers;也可以改用 Vulkan SDK 获取。如果完全没有相关输出,则说明上述 cmake 配置步骤未执行,或 VulkanContext 未被成功创建。

更新 clang-format 的两条路径

部分发行版不随系统提供足够新的 clang-format。文档给出两条按优先级排列的获取方式:

  1. Debian 系(apt)发行版:使用 LLVM 官方的 apt 仓库安装最新稳定版 clang-format;
  2. 从 LLVM 官方文档描述的源码流程自行编译 LLVM 工具链。

相关文档索引

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

项目优选

收起
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
590
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
904
1.82 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
854
1.34 K
docsdocs
暂无描述
Markdown
889
5.78 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.52 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.33 K
1.45 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
983
503
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
540
384