ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

SerenityOS 高级构建指南:磁盘镜像定制、SuperBuild、CMake 选项与 Clang 工具链实战

SerenityOS 高级构建指南:磁盘镜像定制、SuperBuild、CMake 选项与 Clang 工具链实战 SerenityOS 高级构建指南磁盘镜像定制、SuperBuild、CMake 选项与 Clang 工具链实战【免费下载链接】serenityThe Serenity Operating System 项目地址: https://gitcode.com/GitHub_Trending/se/serenity本篇指南以仓库 Documentation/AdvancedBuildInstructions.md 为骨架面向已经完成基础构建见 Documentation/BuildInstructions.md的开发者系统讲解 SerenityOS 构建系统的高级玩法如何通过sync-local.sh定制磁盘镜像、如何用SERENITY_ARCH切换目标架构、如何绕过Meta/serenity.sh直接调用 Ninja 目标、如何精确控制 CMake 构建选项与 CMake 缓存、SuperBuild 的宿主/目标分离机制、组件裁剪以及基于 Clang 的整套工具链构建。读完本文你将能够根据开发场景自由定制、调试与裁剪 SerenityOS 的构建产物。定制磁盘镜像sync-local.sh让改动在重建后持久生效默认情况下基础构建指南生成的磁盘镜像内容是固定的每次重建镜像手动写入根文件系统的改动都会被覆盖。AdvancedBuildInstructions.md给出的方案是在项目根目录创建一个名为sync-local.sh的 shell 脚本构建镜像时构建系统会执行它从而把定制内容烧进镜像文件系统。示例脚本来自原文档路径为项目根目录#!/bin/sh set -e cat EOF mnt/etc/Keyboard.ini [Mapping] Keymapsde EOF # Add a file in anons home dir cp /somewhere/on/your/system/file.txt mnt/home/anon要点说明工作目录脚本执行时当前目录位于被挂载的镜像根文件系统脚本内使用mnt/etc/...、mnt/home/...这样的相对路径因此可以直接写入/etc、/home/anon等系统路径set -e任何一条命令失败即中止脚本避免在镜像处于不一致状态时继续写入默认键盘布局示例把系统默认键盘布局改成德语Keymapsde。SerenityOS 的完整键位映射列表位于仓库 Base/res/keymaps/包含en-us.json、de.json、de-ch.json、fr.json、dvorak.json、colemak.json、jp.json等数十种布局文件与keymap程序的差异运行中的系统里keymap程序同样会修改/etc/Keyboard.ini但那种改动只对当前会话生效、重启后丢失而sync-local.sh中的改动写入了镜像本身会在每次镜像重建时重新应用因此能够跨重建持久化。这一机制的实际挂载流程由Meta/serenity.sh的image子命令触发构建、安装镜像后调用build_image详见 Meta/serenity.sh它是定制开发环境预装文件、调整系统配置、注入测试数据最直接的手段。选择目标架构SERENITY_ARCH构建脚本默认按宿主机的 CPU 架构构建但 SerenityOS 是跨架构操作系统可以显式指定目标架构SERENITY_ARCHaarch64 Meta/serenity.sh runSERENITY_ARCH支持的取值与 Meta/CMake/Superbuild/CMakeLists.txt 中的SERENITY_ARCH缓存变量一致取值说明x86_64默认目标覆盖 QEMU、VirtualBox、VMware 以及绝大多数 PC 硬件aarch64ARM 64 位架构常用于 Raspberry Pi 等 ARM 硬件riscv64RISC-V 64 位架构配合 RISC-V 模拟器或真实硬件使用从 Meta/serenity.sh 的源码看目标解析逻辑is_valid_target会把TARGET参数转换为对应的-DSERENITY_ARCHCMake 参数同时TARGET支持aarch64、x86_64、riscv64、lagom四种取值默认取SERENITY_ARCH环境变量若未设置则取宿主机架构${SERENITY_ARCH:-${HOST_ARCH}}。Ninja 构建目标绕过脚本直接调用底层目标Meta/serenity.sh只是对 CMake/Ninja 构建目标的一层抽象部分目标无法通过脚本直接访问需要先cd Build/architecture再执行ninja target。完整清单如下目标作用ninja limine-image构建带 Limine 引导的 x86-64 磁盘镜像limine_disk_imageninja grub-image构建带 GRUB 的 x86-64 磁盘镜像grub_disk_image面向传统 BIOSninja grub-uefi-image构建带 GRUB 的 x86-64 UEFI 磁盘镜像grub_uefi_disk_imageninja extlinux-image构建带 extlinux 的 x86-64 磁盘镜像extlinux_disk_imageninja raspberry-pi-image构建面向树莓派的 AArch64 磁盘镜像raspberry_pi_disk_imageninja check-style运行与 CI 相同的代码风格检查针对改动文件ninja install-ports把整个 Ports 目录树复制进已安装的 rootfs供在 SerenityOS 内构建 Ports 使用ninja lint-shell-scripts用 shellcheck 检查源码树中的 shell 脚本风格ninja all_generated构建全部生成代码适合在不需要完整系统构建的情况下配合compile_commands.json运行分析工具ninja configure-components启动组件配置工具详见下文组件配置一节另外Meta/serenity.sh的run子命令在默认非 limine路径下实际调用的是qemu-image目标见build_image函数只有显式设置SERENITY_RUNlimine时才改用limine-image。CMake 构建选项为特定开发场景打开开关构建系统把大量可选功能做成 CMake 选项供不同开发场景内存调试、模糊测试、覆盖率、内核调试等按需开启。以下是原文档列出的完整选项及说明ENABLE_ADDRESS_SANITIZER/ENABLE_KERNEL_ADDRESS_SANITIZER分别为 Lagom 测试用例与内核开启内存破坏缓冲区溢出、内存泄漏等的运行时检查ENABLE_KERNEL_UNDEFINED_SANITIZER为内核开启未定义行为运行时检查ENABLE_KERNEL_UNDEFINED_SANITIZER_ALWAYS_DEADLY让上述内核 UBSan 检查在编译器视角下永远致命一旦触发即终止ENABLE_KERNEL_COVERAGE_COLLECTION启用 KCOV API 与内核覆盖率插桩仅用于覆盖率引导的内核模糊测试ENABLE_USERSPACE_COVERAGE_COLLECTION为用户态启用覆盖率插桩当前仅支持 Clang 构建ENABLE_MEMORY_SANITIZER在 Lagom 测试用例中检测未初始化内存访问ENABLE_UNDEFINED_SANITIZER在 Lagom 与 SerenityOS 用户态开启 UBSan如空指针解引用、有符号整数溢出UNDEFINED_BEHAVIOR_IS_FATAL让所有 UBSan 错误不可恢复可降低ENABLE_UNDEFINED_SANITIZER的性能开销ENABLE_COMPILER_EXPLORER_BUILD仅对 Lagom 生效跳过非库实体的构建ENABLE_FUZZERS为系统各组件构建模糊测试器ENABLE_FUZZERS_LIBFUZZER构建基于 Clang libFuzzer 的模糊测试器ENABLE_FUZZERS_OSSFUZZ构建与 OSS-Fuzz 兼容的模糊测试器模糊测试相关背景见 Meta/Lagom/ReadMe.mdENABLE_EXTRA_KERNEL_DEBUG_SYMBOLS以内核-Og -ggdb3编译默认为-O2方便调试内核代码ENABLE_ALL_THE_DEBUG_MACROS用于 CI 检查调试代码能否编译日常不建议开启会刷屏且拖慢系统ENABLE_ALL_DEBUG_FACILITIES同时启用ENABLE_ALL_THE_DEBUG_MACROS与ENABLE_EXTRA_KERNEL_DEBUG_SYMBOLS同样仅供 CIENABLE_COMPILETIME_FORMAT_CHECK编译期校验std::format风格格式化字符串的合法性默认开启ENABLE_PCI_IDS_DOWNLOAD构建时下载 PCI 设备 ID 数据库pci.ids若本地不存在默认开启BUILD_LAGOM构建 Lagom把 SerenityOS 的各类库与程序带到宿主机上运行ENABLE_KERNEL_LTO以内核链接时优化LTO构建ENABLE_MOLD_LINKER用户态使用 mold 链接器可通过Toolchain/BuildMold.sh构建ENABLE_JAKT把 jakt 编译器构建为 Lagom 宿主工具并启用 jakt 语言编写的应用与库JAKT_SOURCE_DIRjakt 开发者本地检出路径用于快速迭代测试例如cmake -S Meta/Lagom -B Build/lagom -DENABLE_JAKTON -DJAKT_SOURCE_DIR/home/me/jaktINCLUDE_WASM_SPEC_TESTS下载并纳入 WebAssembly 规范测试套件需安装prettier与 1.0.35 以上版本的wabtINCLUDE_FLAC_SPEC_TESTS下载并纳入 xiph.org FLAC 测试套件SERENITY_TOOLCHAIN选择 GNU 工具链或实验性 Clang 工具链详见下文Clang 工具链一节SERENITY_ARCH指定目标架构支持x86_64、aarch64、riscv64BUILD_component构建指定组件如BUILD_HEARTS注意必须全大写可用组件清单见构建目录下的components.ini关闭组件后务必执行ninja clean与rm -rf Build/x86_64/Root推荐通过ConfigureComponents工具配置见下文BUILD_EVERYTHING构建全部可选组件开启后覆盖其他BUILD_component标志SERENITY_CACHE_DIR设置下载文件的共享缓存目录一般仅在维护发行包时需要ENABLE_NETWORK_DOWNLOADS允许构建过程中联网下载默认开启关闭后可离线构建但SERENITY_CACHE_DIR的目录结构必须符合构建预期ENABLE_ACCELERATED_GRAPHICS启用基于原生图形库加速绘制的图形特性。这些选项的实际落点在仓库的 Meta/CMake/serenity_options.cmake、Meta/CMake/lagom_options.cmake 与 Meta/CMake/common_options.cmake 中定义SuperBuild 再通过serenity_option宏把同名缓存变量透传给 Lagom 与 Serenity 两个子构建见 Meta/CMake/Superbuild/CMakeLists.txt。按组件开关调试宏SerenityOS 大量模块内置调试功能主要表现为向调试控制台输出额外日志通过组件名_DEBUG宏逐个控制完整清单见 Meta/CMake/all_the_debug_macros.cmake覆盖PROCESS_DEBUG、ACPI_DEBUG、VFS_DEBUG、TCP_DEBUG、KMALLOC_DEBUG、HEARTS_DEBUG等上百个宏。日常开发建议只开启需要的宏而不是用ENABLE_ALL_THE_DEBUG_MACROS一刀切。CMake 缓存操作三种方式修改构建配置CMake 把变量与选项缓存在二进制目录Build/...中开发者可以随时调整set()到持久配置缓存里的变量。有三种主要方式cmake path/to/binary/dir -DVAR_NAMEValueccmake终端 TUI 界面cmake-gui图形界面选项既可以在首次cmake创建二进制目录时作为初始缓存传入也可以在目录创建后通过上述任一方式修改。布尔类选项如ENABLE_setting、组件名_DEBUG用ON/OFF控制# Reconfigure an existing binary directory with process debug enabled $ cmake -B Build/x86_64 -DPROCESS_DEBUGON修改后重新执行ninja或cmake --build即可让改动生效。SuperBuild 配置宿主工具与目标系统的分离构建Serenity 使用地道的 Serenity C 编写宿主工具为目标构建生成代码与数据。SuperBuild 模式把核心 Serenity 库的宿主构建与整个操作系统的目标构建分离一方面让项目的 CMakeLists 明确区分宿主/目标构建另一方面统一了不同编译器工具链与不同架构的处理方式。推荐的运行方式./Meta/serenity.sh run等价于以下 SuperBuild 命令序列$ cmake -GNinja -S Meta/CMake/Superbuild -B Build/superbuild-x86_64 -DSERENITY_ARCHx86_64 -DSERENITY_TOOLCHAINGNU $ cmake --build Build/superbuild-x86_64 $ ninja -C Build/x86_64 setup-and-run从 Meta/CMake/Superbuild/CMakeLists.txt 的源码可以看到superbuild-arch目录的 CMake 配置会创建两个 ExternalProjectlagom项目宿主构建源码目录为Meta/Lagom二进制目录为Build/lagom安装前缀为Build/lagom-install负责构建目标系统编译所需的全部代码生成器与宿主工具背景见 Meta/Lagom/ReadMe.mdserenity主构建使用选定工具链为目标架构编译整个系统且显式依赖lagom-install步骤DEPENDS lagom-install并通过-DCMAKE_PREFIX_PATH指向 Lagom 的安装前缀让find_package(Lagom REQUIRED)找到宿主工具用于代码生成自定义命令。SuperBuild 配置还会根据-DSERENITY_ARCH与-DSERENITY_TOOLCHAIN生成所选工具链/架构的 CMake 交叉编译工具链文件模板分别是 Toolchain/CMake/GNUToolchain.txt.in 与 Toolchain/CMake/ClangToolchain.txt.in同时还会生成对应的meson-cross-file-toolchain.txt。此外SuperBuild 把下游构建目录统一放在Build/archtoolchain后缀非 GNU 工具链会追加小写工具链名作为后缀。手工等价流程原文档给出的展开形式大致是# Generate CMakeToolchain.txt mkdir -p Build/x86_64 cp Toolchain/CMake/GNUToolchain.txt.in Build/x86_64/CMakeToolchain.txt sed -i s/SERENITY_ARCH/x86_64/g Build/x86_64/CMakeToolchain.txt sed -i s/SERENITY_SOURCE_DIR/$PWD/g Build/x86_64/CMakeToolchain.txt sed -i s/SERENITY_BUILD_DIR/$PWD\/Build\/x86_64/g Build/x86_64/CMakeToolchain.txt # Configure and install Lagom cmake -GNinja -S Meta/Lagom -B Build/lagom -DCMAKE_INSTALL_PREFIX${PWD}/Build/lagom-install ninja -C Build/lagom install # Configure and install Serenity, pointing it to Lagoms install prefix cmake -GNinja -B Build/x86_64 -DCMAKE_PREFIX_PATH${PWD}/Build/lagom-install -DSERENITY_ARCHx86_64 -DCMAKE_TOOLCHAIN_FILE${PWD}/Build/x86_64/CMakeToolchain.txt ninja -C Build/x86_64 install两者差异在于SuperBuild 在 Lagom 的 install 阶段与 Serenity 的 configure/build 阶段之间建立了依赖关系因此只要把后续ninja/cmake --build指向superbuild-arch目录宿主机与目标构建共享的头文件或 cpp 文件一旦变更就会自动触发重建并把新生成的宿主工具与库同步到 lagom-install。SuperBuild 的主要限制是非选项类 CMake 缓存变量如组件配置、调试标志必须等构建开始后才能设置——因为 Serenity 与 Lagom 的CMakeCache.txt要等 SuperBuild 构建推进到对应阶段才会生成。构建后的调试标志调整示例# Initial build, generate binary directories for both child builds $ cmake -GNinja -S Meta/CMake/Superbuild -B Build/superbuild-x86_64 -DSERENITY_ARCHx86_64 -DSERENITY_TOOLCHAINGNU $ cmake --build Build/superbuild-x86_64 # Turn on process debug and dont build the browser for the Serenity build $ cmake -B Build/x86_64 -DPROCESS_DEBUGON -DBUILD_BROWSEROFF $ ninja -C Build/x86_64 install # Build host tests in Lagom build $ cmake -S Meta/Lagom -B Build/lagom -DBUILD_LAGOMON $ ninja -C Build/lagom install组件配置ConfigureComponents交互式裁剪系统如果想精细选择构建与安装哪些系统组件可以使用辅助程序ConfigureComponents。它依赖whiptail多数发行版在newt或libnewt软件包中提供。在Build/x86_64目录下执行$ ninja configure-components工具会先询问要使用的构建类型再允许手动增删组件确认后它会基于选择运行相应的 CMake 命令并执行ninja clean与rm -rf Root清理旧构建产物。可用的组件清单在构建目录的components.ini中命令行下也可以通过-DBUILD_组件名ON/OFF全大写直接控制组件选项的定义见 Meta/CMake/serenity_components.cmake。运行测试宿主测试Lagom 在宿主机上运行与目标测试在 SerenityOS 内运行的差异、以及 CI 测试失败的排查方法详见 Documentation/RunningTests.md。补充一点脚本层细节Meta/serenity.sh test lagom [TEST_NAME_PATTERN]会把测试名透传给 ctest 的-R正则过滤器并配合--output-on-failure --test-dir build_dir执行而Meta/serenity.sh test target则以graphics_subsystem_modeoff system_modeself-test内核参数在 QEMU 中跑自测镜像见 Meta/serenity.sh 的run_tests与test分支。在 VirtualBox 与 VMware 中运行除 QEMU 外SerenityOS 也支持在 VirtualBox 与 VMware 中运行。安装步骤分别见 Documentation/VirtualBox.md 与 Documentation/VMware.md。裸机安装更硬核的玩家可以准备合适的硬件把 SerenityOS 安装到物理 PC 上步骤见 Documentation/BareMetalInstallation.md。Windows/WSL2 下的文件系统性能如果你使用 Windows 原生 QEMU 二进制QEMU 无法直接访问 WSL2 安装的 ext4 根分区只能经由 9P 网络文件共享访问WSL2 发行版根目录对应网络路径\\wsl$\{distro-name}。更快的替代方案把Build/_disk_image与Build/Kernel/Kernel复制到 Windows 原生分区如/mnt/c后再执行ninja run此时SERENITY_DISK_IMAGE就是一个普通 Windows 路径如D:\serenity\_disk_image可绕开 9P 带来的性能损耗。Clang 工具链摆脱 GCC 专属行为SerenityOS 也支持用 Clang 替代 GCC 构建目的是避免依赖编译器特有行为并借助内置静态分析器捕获更多缺陷。两种工具链编译出的代码在大多数场景下行为一致限制是Ports 目前还无法用 Clang 构建。构建 Clang 工具链Toolchain/BuildClang.sh脚本会构建一套既能编译宿主机应用、也能编译 SerenityOS 的 Clang 工具链。警告脚本运行期间电脑可能严重变慢甚至短暂卡死通常发生在 CPU 核心数多于可用内存GB时。解决办法是设置MAKEJOBS环境变量为小于 CPU 核心数的值限制并行编译任务数。构建完成后即可用它编译 SerenityOS要么设置SERENITY_TOOLCHAINClang构建选项要么直接给Meta/serenity.sh传 TOOLCHAIN 参数Meta/serenity.sh run x86_64 ClangSerenity-aware clang 工具构建 Clang 工具链的同时也会构建 libTooling 系列工具——clang-format、clang-tidy 以及可选的clangd它们都把 SerenityOS 视为合法目标安装到Toolchain/Local/clang/bin。把编辑器插件指向这套自建工具并配合 Clang 构建生成的compile_commands.json可以获得比宿主发行版自带工具更丰富的报错信息。若要同时构建 clangd先设置环境变量再运行脚本CLANG_ENABLE_CLANGDON Toolchain/BuildClang.sh更新 clang-format部分发行版自带的 clang-format 版本过旧按优先级提供三种获取新版本的方式apt 系发行版使用 LLVM 官方 apt 软件源安装最新版 clang-format编译 SerenityOS 定制的 LLVM按上文用Toolchain/BuildClang.sh从源码编译使用Toolchain/Local/clang/bin/clang-format作为编辑器与终端工具meta-lint-ci 的 pre-commit 钩子会自动选用 Toolchain 里的 clang-format 二进制按 LLVM 官方文档从源码编译 LLVM自行编译整套 LLVM 源码以获得新版本。小结SerenityOS 的构建体系在 CMake 之上做了多层封装Meta/serenity.sh负责日常编排build/install/image/run/gdb/test 等子命令详见脚本顶部的帮助文本 Meta/serenity.shSuperBuild 负责宿主工具与目标系统的联动Ninja 目标与 CMake 缓存则提供细粒度控制。掌握本文介绍的sync-local.sh、SERENITY_ARCH、CMake 选项、ConfigureComponents与 Clang 工具链即可根据自身开发需求定制镜像、裁剪组件、切换架构并搭建更强大的静态分析环境。【免费下载链接】serenityThe Serenity Operating System 项目地址: https://gitcode.com/GitHub_Trending/se/serenity创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表