资讯动态

从环境准备到产物验证:macOS编译Chromium 144全流程解析

发布时间:2026/10/19 16:33:44 来源:尧图企业网站定制
1. 编译启动前的最后检查工具链与环境变量到了这一步你的 depot_tools 应该已经就位源码目录也已经同步完成。很多第一次动手编译 Chromium 的朋友容易在这里犯一个错误——以为代码拉下来就可以直接敲autoninja结果编译到一半才发现 Xcode 版本不对、SDK 路径没配好或者 Python 环境被 Homebrew 的版本污染了。这一篇我们就从编译前的环境检查开始把最容易翻车的几个点一次性揪出来。1.1 macOS 工具链版本硬性要求Chromium 144 这个版本的构建对 macOS 工具链要求非常明确Xcode 15 或更高版本对应的 macOS SDK 至少是 14.4。如果你还在用 Xcode 14那么请先去 App Store 升级否则在生成构建文件阶段就会直接报错根本走不到编译那一步。我建议在开始之前先执行一条命令把当前工具链信息打出来确认自己的环境到底处于什么状态xcode-select -p xcodebuild -showsdks clang --version python3 --version正常情况下xcode-select -p应该输出类似/Applications/Xcode.app/Contents/Developer的路径。如果你发现指向的是 Command Line Tools或者干脆是别的地方先执行sudo xcode-select -r重置一下。还有一个小细节容易被忽略Xcode 首次启动时的许可协议。如果你刚装完 Xcode 还没打开过命令行工具会有可能报 license not accepted 的错误。这时候运行sudo xcodebuild -license accept就好。1.2 环境变量配置与 depot_tools 的 PATH 优先级env 里最关键的是DEPOT_TOOLS_UPDATE这个变量。很多老手在编译 144 这个版本时建议设置export DEPOT_TOOLS_UPDATE0为什么因为 depot_tools 会在每次执行gclient或gn时自动尝试更新自身而 Chromium 144 这个版本的源码树对 depot_tools 的版本有隐性依赖一旦 depot_tools 更新到过新的版本反而可能出现兼容性异常。我踩过一次坑某次编译到一半gclient sync自动拉取了最新的 depot_tools结果导致gn的生成结果和源码树里的构建假设不匹配浪费了整整一个下午排查。从那时起我固定在编译某个版本时先写好环境变量的 export再进编译流程。建议把以下内容加到你的~/.zshrc里export DEPOT_TOOLS_UPDATE0 export PATH$HOME/chromium/depot_tools:$PATH注意 PATH 的顺序务必让 depot_tools 在最前面。macOS 自带的clang、python3路径如果排在 depot_tools 前面gn在解析工具链时可能找到错误的工具版本。depot_tools 里面自带了一套与 Chromium 构建系统匹配的 Python 环境必须保证解释器和脚本优先从 depot_tools 目录加载。2. 生成构建文件gn 参数的核心逻辑环境没问题之后下一步就是使用gn gen生成构建文件。这是整个编译流程中最需要动脑的一步因为这里的参数直接决定了编译产物是什么样的、编译时长是多少、以及跑起来时候的内存占用。2.1 out 目录与构建目录命名规范Chromium 的构建产物放在 source 目录下的out/文件夹同一个源码树可以同时维护多个构建目录。常见的命名是out/Default、out/Release、out/Components但你想叫什么都行gn不区分名字的魔法值。通常我会建议把构建类型和用途直接写进目录名里比如out/arm64_Release、out/x64_Debug避免隔了几个月回来忘记这个目录是什么配置。构建目录在第一次执行gn gen时自动创建。比如创建一个 Release 版本的构建目录gn gen out/Release --argsis_debugfalse is_official_buildtrue target_cpu\arm64\这里我提前说清楚Chromium 144 在 Apple Silicon 机器上默认生成的是 arm64 架构的产物如果你的 Mac 是 Intel 的target_cpu 应设为x64。如果你在 Apple Silicon 的机器上强行指定x64也不是不行但需要 Rosetta 环境配合而且 arm64 的原生编译效率会高很多没必要主动降级。2.2 关键 build args 详解Debug 与 Release 的取舍关于is_debug和is_official_build这两个参数对编译行为和产物体积的影响巨大值得花一分钟搞明白背后的逻辑。先看is_debugtrue的情况。这是 Chromium 源码默认的状态所有符号不裁剪、优化级别低方便用 LLDB 打断点调试。但代价是编译出来的二进制体积巨大——以我实测的数据Debug 版 Chromium 的 dSYM 符号文件和主程序加起来经常超过 8GB。运行速度和系统浏览器比也有肉眼可见的差距毕竟所有断言、调试检查都是开启状态。再看 Release 模式即is_debugfalse。Release 模式下编译器启用 O2/O3 级别的优化调试符号默认裁剪产物体积小得多运行效率接近线上版本。对于大部分只是想研究 Chromium 性能、跑自动化测试或者做二次开发的朋友来说Release 是更合理的日常选择。如果你做的是正式分发用的构建还需要加is_official_buildtrue。这个参数会进一步收紧编译参数比如启用-ffunction-sections、-fdata-sections和链接阶段的--gc-sections把没用的代码段和函数直接剔除出最终二进文件。2.3 component build在编译速度与产物完整性之间做选择这里我特别想谈谈is_component_build这个参数。如果是首次编译 Chromium对编译时长有敏感要求可以把is_component_buildtrue放到构建参数里。Component Build 的核心思想是把 Chromium 拆成一组动态库.dylib而不是打成一个巨大的可执行文件。它的优势在于增量编译——改一个模块的代码只需要重新链接对应的 dylib而不需要像非组件构建那样把几百个静态库重新塞到主二进制里。话虽如此component build 也有自己的问题。动态库拆分带来的性能开销是真实存在的尤其是对浏览器内核这种处处讲究性能的软件组件模式下的 Javascript 引擎和渲染管线会有约 10%~20% 的性能退化。如果你需要做性能测试或者想拿编译出的 Chromium 当一个主力研究浏览器我更推荐关闭组件构建老老实实让链接器合并产出单一的执行文件。就我个人的实践而言我把 144 的第一次完整编译用了非组件模式全量耗时约 3 小时 50 分钟。如果使用 component build初次全量编译大约可以缩短到 2 个半小时左右但后续调整代码的重编译速度差异才是关键——组件模式通常能把这部分耗时减少 80%。2.4 针对 mac 的常用参数配置参考直接给你一份经过验证的构建参数适合在 macOS 上、Apple Silicon 芯片的机器编译 Chromium 144 Release 版gn gen out/Release --args is_debugfalse is_official_buildtrue target_cpu\arm64\ symbol_level0 enable_strippingtrue symbol_level0是很多人容易遗漏的参数。Chromium 的默认符号等级在不同配置下表现不一样Release 模式下有时默认会带上部分 DWARF 符号直接把符号完全关掉能明显减少链接负担和占用磁盘空间。而enable_strippingtrue会让构建系统在链接完成后主动删除可执行文件中的符号表这对于只是日常运行、不打算断点调试的场景非常合适。如果你是 x64 的 Intel Mac那么把target_cpux64换上去就行其余参数不用动。3. 启动 Ninja 构建第一次编译的全流程实战gn gen成功之后out 目录里会生成build.ninja文件接下来就是整个流程里机器负载最高、耗时最长的一个环节——执行autoninja。3.1 autoninja 与 ninja 的选择Chromium 老指南里常见的命令是ninja -C out/Release chrome但如果你用的是 depot_tools 里自带的autoninja它会自动根据机器 CPU 核数和内存大小调整并发任务数。苹果 M 系列芯片的 CPU 核心分性能核和能效核autoninja对这类异构核心架构做了适配比直接用ninja盲目指定-j参数要稳妥得多。建议完整命令如下autoninja -C out/Release chromechrome是目标名表示构建完整的浏览器可执行文件。如果只想快速验证某个模块可以考虑只构建对应的单元测试目标。但既然走到了编译全流程这一步直接上主目标就好——只有完整构建过一遍之后做增量编译才有参照基准。3.2 初次编译的耗时评估与硬件影响初次编译的综合耗时取决于机器配置。我手上的 M 系列芯片的机器32GB 内存起步编译 144 的 Release 非组件版全量时长大约在 3 到 4 小时之间。如果你的机器内存只有 16GB那么 ninja 为了控制内存占用会自动降低并行度实际耗时可能拉到 6 小时以上——这不是配置有问题而是构建系统做的自我保护。内存不足时最典型的症状是链接阶段突然报出 clang: error: unable to execute command: Killed 之类的信息。这个Killed是系统层面的 OOM 杀进程导致的不是 clang 本身的编译错误。遇到这种情况别急着翻代码先用memory_pressure命令看看系统内存水位同时检查是不是同时开了太多 IDE 和浏览器窗口。如果你预算许可我想给一个具体建议把内存升到 32GB 以上会是最值得的一笔投资。编译 Chromium 的时候32GB 内存的机型可以跑满并行度16GB 只能在 60% 左右的速度徘徊这种差距不是靠软件调优能抹平的。3.3 构建过程的实时状态解读执行autoninja后终端会开启类似仪表盘的实时界面。刚开始会有几秒钟的静止然后出现大量[0/XXXX]进度的闪烁和不断变化的编译命令。这里的XXXX是当前构建系统根据源文件数量计算出的总任务数对 Chromium 144 来说全量任务数通常在 40000 这个数量级。第一次看到 40000 多个任务时不要慌这数字看着吓人但每个任务对应的是单个源码文件的编译或链接操作。构建过程中有一批文件会先完成进度跳跃的幅度会逐渐变大因为后面的阶段并行度会稳定下来。需要特别提醒如果在终端里看到某个文件反复编译失败又自动重试不要一直挂着等。Ninja 在编译失败后默认会停止整个构建链。长时间卡住通常意味着某个前置任务在等待资源或者某个编译参数产生了冲突。果断中断构建CtrlC根据报错信息排查后再重来。4. 链接阶段与产物验证从构建成功到可运行跳过那些进展顺利的部分如果你最终看到了像这样的输出那就说明编译真正完成了[42000/42000] LINK ./Chromium是否真的万事大吉还不是。链接成功只代表这一步技术上通过了还需要做几个产物验证步骤。4.1 可执行文件的位置与结构编译成功后产物路径是out/Release/Chromium.app。注意文件名的大小写macOS 上构建出来的应用包名是Chromium.app而不是大多数人直觉中的chrome.app。如果你的is_official_buildtrue整个Chromium.app内部结构是相当紧凑的。主可执行文件在Chromium.app/Contents/MacOS/Chromium绝大多数内嵌资源如默认扩展组、组件清单、ICU 数据也会被一并打包进Contents/Frameworks或Contents/Resources目录。相比之下非 official 版本会有更多框架零散放置在同一个 bundle 中行为上类似但不完全一致。4.2 首次运行的常见失败与原因定位拿到Chromium.app之后直接双击或者在终端里执行./out/Release/Chromium.app/Contents/MacOS/Chromium如果秒退最常见的原因是macOS 的 Gatekeeper 拦截。本地构建的应用没有签名首次运行可能被拒绝。用sudo xattr -dr com.apple.quarantine ./out/Release/Chromium.app移除隔离属性一般就能解决。如果你在命令行运行发现输出了一堆类似FATAL:root:...的日志那大概率是运行时需要的某些资源文件没有在预期路径下找到。请检查你是否用--user-data-dir指定了一个独立的用户数据目录./out/Release/Chromium.app/Contents/MacOS/Chromium --user-data-dir/tmp/chromium_tmp_profile这个参数强烈建议首次运行时都带上。默认用户目录里可能残留旧版本 Chromium 的配置格式和 144 的偏好系统不兼容轻则页面排版异常重则直接闪退。5. 增量编译与日常迭代真正的效率提升手段全量编译完成后我们遇到的大部分场景其实是改一段代码然后看效果。这意味着了解增量编译的机制能极大改善体验。5.1 ninja 增量编译的基本逻辑Ninja 的增量构建核心依赖文件时间戳和内容哈希。每次执行autoninja -C out/Release chrome时ninja 会根据build.ninja里定义的依赖关系比对当前磁盘上源文件的修改时间和上次构建时的记录。只有发生变化的源文件才会被重新编译再重新链接。不过有个连锁反应要注意如果改的是一个头文件而头文件被几百个 cc 文件引用那么这些 cc 文件会一起重编——这就是#include依赖树带来的头文件地震。5.2 减少无用重编译的两个关键技巧第一个技巧是不要把构建目录和源码目录混放。Chromium 的构建脚本会把编译产物输出到 out 目录运行时动态下载的资源在源码树之外的 cache 目录。如果你做了任何改源码的操作不要顺手修改 out 目录下的文件那样会污染构建系统对文件状态的判断。第二个技巧是善用 gn 的依赖分析。在改代码之前先跑一下gn check out/Release这个命令会扫描 include 依赖关系提前把缺失头文件、循环依赖等结构性问题暴露出来避免编译跑到一半才被报错中断。5.3 实测一次小改动引起的重编译规模拿我最近一次实践举例。我在 Chromium 144 源码里改动了content/browser下某个 worker 生命周期管理相关的源文件顺手改了一个被十余个文件共用的头文件。触发增量编译后ninja 显示需要重新编译的文件数是 314 个链接阶段重新执行一次。整个流程耗时约 4 分 20 秒——和全量编译相比已经非常轻量了。如果你的增量编译耗时超过 15 分钟大概率是改动触碰到了 core 级别的公共头文件比如base或third_party/blink/public下面的头文件这类文件一旦变化波及范围能到几千个源文件。6. 编译期内存管理与拖慢构建的隐形杀手除开硬件水平和编译参数的差异有几个隐形因素会明显拖慢编译速度。6.1 后台驻留程序对 ninja 并行度的负面影响编译 Chromium 时ninja 会按照 CPU 调度器看到的可用核心数来决定并行编译任务数。如果此时你同时开着 Docker、多个 JetBrains IDE、浏览器几十个标签页、甚至剪辑软件在后台跑渲染这些程序会抢占 CPU 时间片并导致 macOS 的内存压力升高。我在一次实测中发现后台开着常规开发环境时ninja 实际编译时间比干净的终端环境多了约 27%。编译期间强烈建议把无关 App 退干净至少是暂时退出。6.2 使用 iconv/spotlight 导致的异常 CPU 占用的排查有另一个隐蔽的问题macOS 的 Spotlight 索引在首次生成大量新文件时比如首次全量编译创建了几十万个 .o 文件会触发mds_store进程疯狂占用 CPU。这时候你以为在编译实际系统一半算力都被搜索服务抢走了。可以在系统设置里暂时把 Chromium 源码目录加入 Spotlight 的排除列表。如果在编译期间明显感受到系统卡顿打开活动监视器确认mdworker、mds的 CPU 占用率是不是飙升如果是那就手动踢一脚索引sudo mdutil -i off /path/to/chromium/src编译完成、不再频繁生成新文件后再sudo mdutil -i on恢复索引。6.3 温度墙与降频长时间高负载下的硬件特性还有一个必须直面的事实——长时间编译会让 Mac 的温度持续飙升。Apple Silicon 芯片的散热设计偏向轻薄本高负载下温度墙触发后CPU 频率会明显下降导致编译速度不升反降。这属于硬件特性不是配置失误。解决方法是给笔记本垫高、加强通风或者使用散热底座。台式机的 Mac 相对好一些但也别把机器放在密闭柜子里编译。如果你用的是带风扇的 Mac编译时能听到风扇呼啸属于正常现象如果听不到声音但不卡顿说明系统在通过降频方式控制温度表面上安静了编译时长却可能拉长。7. 针对常见报错场景的排查手册这个章节把我在编译 Chromium 144 过程中亲身踩过的报错和解决方案整理出来按症状分类。7.1 常见错误速查表报错关键字出现阶段可能原因处理方式depot_tools update failedgclient / fetch网络无法访问 depot_tools 更新源设置DEPOT_TOOLS_UPDATE0Xcode version too oldgn gen系统 Xcode 低于构建要求升级 Xcode 到 15SDK not foundgn gen命令行工具未选到完整 Xcodesudo xcode-select -r重置路径unable to execute command: Killed编译阶段内存不足OOM减少并行度或升级内存ld: library not found for -lcabi链接阶段SDK 路径异常或 SDK 版本过新检查xcrun --show-sdk-pathninja: error: unknown target chromeautoninjaout 目录的 gn 配置未完成先执行 gn genFailed to locate installed Mac OS X SDKsgn genXcode 未完全安装完成打开一次 Xcode 完成初始化7.2 链接阶段的 lld 崩溃问题如果你在链接阶段碰到clang-17: error: linker command failed with exit code 1先不要怀疑代码写错了。Chromium 144 的链接过程对内存和临时目录空间同时有要求。链接器在合并大量静态库时需要在/tmp或构建目录生成中间文件如果磁盘剩余空间小于 20GB就会在这里失败。先执行df -h检查可用空间清理掉 Xcode DerivedData 的缓存和各类旧的编译产物后重试。7.3 Xcode 路径错乱导致的诡异问题还有一类偶发问题是Xcode 路径错乱。你也许之前装过 Command Line Tools后面又装了完整版 Xcode但系统里仍残留了旧工具的符号链接。这时xcrun --show-sdk-path看到的路径可能指向/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk。Chromium 的构建认为这个 SDK 版本与工具链不匹配就会出现各种莫名其妙的编译失败。解决办法是一套三连sudo xcode-select -r xcode-select --install sudo xcodebuild -license accept然后再检查xcrun --show-sdk-path确认它输出的是 Xcode.app 内部的 SDK 路径。这个细节虽然简单但经常能解决那些日志看起来完全无解的问题。8. 编译结束之后的进阶自定义 GN 参数与性能调试如果全流程你已经能流畅跑通了那就可以考虑通过这些进阶参数把编译出的 Chromium 真正变成你专属的版本。8.1 针对性能调试开启符号与优化共存日常开发如果想调试性能问题通常希望保留部分符号但开启高优化这种需求可以用symbol_level1实现。这个等级只保留函数名等基础符号不带源码行号信息体积比symbol_level2小得多又能让sample工具分析调用栈时看到函数名不至于全是十六进制地址。8.2 自定义编译参数带来的功能差异你可以按需加入若干开关。比如gn gen out/Profile --args is_debugfalse is_component_buildtrue symbol_level1 enable_naclfalse enable_naclfalse会跳过 NaCl 相关模块的构建能省几分钟编译时间。如果你明知用不到这个功能在源码头文件里也会减少很多没必要的依赖文件重编。另一个实用的开关是enable_remotingfalse它会裁掉 Chromium 内置的远程桌面客户端相关代码后续增量编译时涉及这个模块的文件都不会被纳入任务队列。说老实话这些小开关积累下来对后续每次增量编译的提速效果相当可观。8.3 基于编译产物的二次开发环境准备如果你的目标不只是获得一个浏览器而是基于 Chromium 做二次开发那么最值得花时间的事情是配置 IDE 的代码跳转环境。Chromium 144 的源码树接近 2GB各种符号几千万个没有合适的索引系统浏览代码就是一场灾难。建议生成一个compile_commands.json编译数据库供 IDE 使用gn gen out/Release --args... --export-compile-commands这个命令会在 out 目录下生成compile_commands.json里面记录了你全部源文件的精确编译命令、include 路径和宏定义。无论你是用 Visual Studio Code 的 clangd 插件还是用 CLion都能直接读这个文件实现精准的跳转和补全。实际使用中我最明显的感受是没有这个文件的代码浏览基本靠猜有了之后从一个render_frame_host跳到它的实现整个过程一秒内完成极大提升日常改代码的效率。9. 一次编译过程的复盘与经验沉淀前前后后把 144 的编译流程走完了我想把这次实践中积累的一些体会尽量坦诚地分享出来。9.1 时间规划上的建议全量编译期间最好不要盯着终端一直看。每 5 分钟瞄一眼确认没有卡死就行人可以对编译流程完全放手。把编译安排在工作日晚间挂机运行第二天早上直接获得产物是最高效的方式。如果你需要连续做多次实验性修改可以考虑给测试机上配好组件构建模式节省每次改动后的等待时间。9.2 内存资源的硬性预算说句实在话不切换构建参数的前提下编译 Chromium 144 的过程中内存占用峰值通常在 20GB 到 28GB 之间。如果机器只有 16GB 内存即便设置了低并行度也会在链接阶段频繁触碰内存上限导致系统响应变缓甚至编译被中止。预算充足的话不要犹豫升级到 32GB 是性价比最高的选择。9.3 保持源码文件夹的干净还有一个看似微小但实际影响很大的习惯不要把 Chromium 的源码目录放到 iCloud Drive、OneDrive 这类自动同步的网盘目录下也不要用 Time Machine 对源码目录做频繁的完整备份。这类连续大量文件变化的操作会让文件系统陷入频繁快照状态macOS 的 APFS 虽然对小文件快照有优化但几十万个目标文件的增量快照还是会造成显著的磁盘 I/O 开销直接拉低编译时文件读取的速度。根据个人经验用一块本地 SSD 存放源码和构建产物构建速度通常比存储在同步盘上要快 30% 左右。很值得专门准备一块外置 SSD接口余量充足的前提下专门放编译工程。9.4 把这套知识沉淀成脚本每次都手动 export 环境变量、写 gn 参数、启动 autoninja很容易犯错。建议在src目录之外放一个build_env.sh脚本把环境变量和编译参数写死然后一键执行#!/bin/bash export DEPOT_TOOLS_UPDATE0 export PATH$HOME/chromium/depot_tools:$PATH cd ~/chromium/src gn gen out/Release --argsis_debugfalse is_official_buildtrue target_cpu\arm64\ symbol_level0 autoninja -C out/Release chrome这样即使隔了两三个月再回来看到脚本也能立刻回忆起完整的构建流程。这也让我在想复现 Chromium 144 的特定行为时可以快速进入状态不用重新翻阅文档。最后再说一个小技巧如果你打算长期从事 Chromium 相关的研究建议在第一次编译成功之后立刻对 out 目录做一个文件列表快照记录下所有产物的尺寸和哈希。以后遇到构建产物异常、二进制文件被改动等问题时这个基线快照能帮助你快速定位问题范围。编译流程是重复性劳动不假但很多玄学问题其实都出在基础环境不干净、参数理解不到位这些可控因素上。把这些可控因素逐一排除Chromium 144 的编译之路就顺了。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑