macOS编译Chromium 144:环境准备完整指南
2026/9/7 19:05:53 网站建设 项目流程

上周一位读者私信我,说照着网上某篇教程在 macOS 上编译 Chromium,折腾了整整三天,连环境都没搭起来。我远程帮他看了一眼,三个坑全部踩中:装的是 Xcode beta 版、depot_tools 用的是 Homebrew 版本、磁盘分区只剩不到 60GB。这三个问题,官方文档里其实都写清楚了,但分散在不同的页面,第一次接触的人很难把它们串成一条完整链路。这也正是我想写这一系列 macOS 编译指南的原因。

这篇是 Chromium 144 编译指南 macOS 篇的第一篇,只聚焦一件事:把编译环境完整、稳妥地准备好。Chromium 的版本号跟着 Chrome 走,144 这个数字对应的是 Chrome 144 的时间线,代码里src/chrome/VERSION会明确写着MAJOR=144。这个里程碑算是比较新的主线版本,生态和社区资料都比较齐全,拿来当学习目标或开发基线都合适。适合谁看?正在从零开始编译 Chromium 但被环境劝退的开发者,准备把 Chromium 源码作为研究对象但不知道从哪下手的同学,以及想在 M 系列芯片的 Mac 上搭一套可复用开发环境的人。

1. 硬性门槛:编译 Chromium 144 之前,先看看这台 Mac 合不合格

很多人拿到新 Mac 的第一反应是"赶紧装个 Xcode 就开搞",其实编译 Chromium 对硬件和系统版本的要求比想象中高得多。与其到编译中途被各种诡异报错打断,不如在最开始就把这台机器的底细摸清楚。

1.1 内存和 CPU:16GB 是下限,32GB 才谈得上从容

Chromium 是一个体量极其夸张的 C++ 项目,模板实例化的密集程度在业界数一数二。编译过程中 clang 会开多个并行进程同时编译不同目标文件,每个 clang 进程动辄吃掉 1-2GB 内存。到了链接阶段更夸张,ld64 需要把几千个 .o 文件一次性加载进内存做符号解析和重定位,内存占用会瞬间飙到 10GB 以上。

我自己的实测感受是:8GB 内存的机器可以直接放弃,连拉源码都费劲;16GB 能编译,但并发数得手动限制,否则系统会频繁触发内存压缩,整机卡到鼠标都在飘;32GB 以上才是真正舒服的起点,Ninja 默认并发基本不会撞到内存天花板。Apple Silicon 的 Mac 因为采用统一内存架构,内存同时还被 GPU 占用,日常开几个浏览器标签页加 IDE,再跑编译,压力会比同容量 Intel 机型更明显。

先执行下面的命令确认一下当前机器的基本盘:

sysctl -n hw.memsize # 内存大小,单位字节 sysctl -n hw.ncpu # CPU 核心数 uname -m # 输出 arm64 或 x86_64

从实践角度讲,内存和 CPU 核心数决定了后续构建时的并发参数怎么设置。核心数多但内存小的话,autoninja默认的并发数反而可能把机器拖垮,到时候就得手动用-j参数收敛。

1.2 系统版本:macOS 14 Sonoma 是实际起点

Chromium 官方对 macOS 版本的最低要求,其实比很多人印象里要高。原因在于编译工具链的依赖链条非常长:macOS 系统版本决定你能装哪个版本的 Xcode,Xcode 决定 SDK 版本和内置 clang 版本,而 Chromium 的构建脚本会对这些版本做严格校验。

以 144 这个里程碑的经验来看,macOS 13 Ventura 属于"还能跑但开始吃紧"的级别,macOS 14 Sonoma 和 macOS 15 Sequoia 是更稳妥的选择。如果你的机器系统版本低于 macOS 13,我建议先把系统升上来再折腾,否则后续 gn 检查 Xcode 版本时大概率会直接报错。这里的核心逻辑是:Chromium 太新,它对工具链的"底线要求"会随着版本号不断抬升,旧系统的 SDK 无法满足一些新特性和 ABI 要求。

升级系统这件事本身也有讲究。不要用 OTA 覆盖式升级后直接开干,有条件的话建议备份后做一次相对干净的升级,因为 Chromium 工具链对系统的"整洁度"异常敏感,系统里残留的旧开发工具、多个 Xcode 并存、手动改过系统目录权限,都可能在编译阶段以难以理解的方式爆出来。

1.3 Intel Mac 和 Apple Silicon:架构不同,准备策略也不同

uname -m命令的输出决定了很多东西。Apple Silicon 上输出arm64,Intel 上输出x86_64。Chromium 的构建系统会读取宿主机架构来设定默认的target_cpu,也就是说 Apple Silicon 默认编 arm64 版本,Intel 默认编 x64 版本。

如果你在 Apple Silicon 上想交叉编译 x64 版本,可以在 gn 参数里显式设置target_cpu="x64",但这会失去原生架构的性能优势,链接和运行都会通过 Rosetta 兜底,慢不少。反过来,Intel 机器上编 arm64 基本不现实,构建速度和交叉编译的复杂度都划不来。所以我建议:什么芯片就编什么架构,不要一上来就折腾交叉编译。

还有一个容易被忽略的点:M 系列 Mac 上如果把 macOS 升级到 Sonoma 之后,系统会默认把部分卷标为只读,如果以前安装过乱七八糟的开发工具,可能会在编译时触发代码签名或文件权限的问题。环境准备阶段不需要立刻处理这类问题,但心里要有这根弦。

2. 磁盘规划:150GB 可用空间是保守值,大小写敏感卷是隐藏要求

磁盘规划是环境准备里最不性感、但翻车率最高的一环。Chromium 源码本身、构建缓存和中间产物三者的体量叠加起来,对磁盘容量的消耗远超普通项目。我见过太多人在编译进行到一半时被 "No space left on device" 直接终结,那种挫败感足以劝退大多数人。

2.1 源码加构建产物到底吃掉多少空间

先说源码侧。Chromium 采用单仓(monorepo)模式,src目录下几乎包含了所有第三方依赖,从 WebKit、V8 到各种音频视频编解码库全部在内。执行fetch chromium --no-history拉取当前快照后,src目录体积大约在 20-30GB 之间。如果不用--no-history参数而把完整 git 历史也拉下来,.git目录里的大历史对象会让整体体积翻几倍,这也是我在后面章节强烈建议加--no-history的原因。

构建产物的体量则取决于构建模式。下面是我在 macOS 上实测过的参考范围:

构建模式典型占用说明
Debug + symbol_level=2100GB 以上调试符号极其占空间,适合需要断点调试的场景
Debug 组件构建 + symbol_level=040-60GB日常开发调试常用,不开符号加快速度和省空间
Release 组件构建 + symbol_level=025-40GB性能验证相关,链接体积相对可控

另外,如果你打算启用 ccache 来加速二次编译,缓存目录还得额外留出至少 30-50GB。官方文档确实写着 100GB 起步,但那是最保守的数字,我的建议是直接留出 150GB,如果想开缓存或者做跨版本源码切换,200GB 会更从容。

2.2 创建大小写敏感的 APFS 卷

这绝对是 macOS 编译 Chromium 环境准备里最容易被忽略、却最容易埋雷的一个点。macOS 默认的 APFS 文件系统是大小写不敏感(case-insensitive)的,而 Chromium 官方明确要求源码必须放在大小写敏感(case-sensitive)的文件系统上。

为什么会有这个要求?因为 Chromium 和它依赖的大量第三方库在代码里存在仅靠大小写区分的文件或目录名,比如Foo.hfoo.h同时存在于不同目录。在大小写不敏感的文件系统上,这类文件在 checkout 或构建时可能出现文件互相覆盖、脚本找不到目标文件等灵异问题。这类报错通常不直观,排查起来非常痛苦。

解决办法是在现有 APFS 卷上新建一个大小写敏感的卷,不需要重装系统,也不需要重新分区。先查看当前磁盘信息:

diskutil list

找到系统所在物理磁盘的标识符,比如disk3,然后执行:

sudo diskutil apfs addVolume disk3 APFSX "ChromiumDev" -mountpoint /Volumes/ChromiumDev

这条命令会在disk3上创建一个名为ChromiumDev的新卷,挂载到/Volumes/ChromiumDev。注意 APFSX 这个文件系统格式标记,X 后缀就代表大小写敏感。创建完成后,用df -h /Volumes/ChromiumDev确认卷已经挂载并且容量符合预期,然后把所有 Chromium 相关源码都放到这个卷下面。

提示:不要把新卷的名字取得太复杂,后面所有命令都要用到这个挂载路径,越简单越不容易出错。

有人可能想问:我硬要在默认卷上编译行不行?多数情况下确实能编出来,但这是官方不支持的部署方式,而且只要第三方依赖更新时出现一个大小写冲突的文件,构建就会以一种极其反直觉的方式挂掉。既然要折腾 Chromium,就别在文件系统这个地基上省事。

2.3 固态硬盘和剩余空间的缓冲逻辑

Chromium 源码里有几十万个文件,checkout 和构建过程中会有海量的小文件读写操作。机械硬盘在这个场景下完全没有一战之力,固态硬盘是硬性要求。Apple Silicon 机型全部标配 SSD,这块问题不大,但老款 Intel Mac 如果有外置机械硬盘作为源码盘,建议趁早放弃。

除了总容量,剩余空间的缓冲也很关键。构建过程中会生成大量临时文件,链接阶段的产物也会短时间内快速膨胀。如果磁盘剩余空间长期低于 20-30GB,SSD 的垃圾回收和写入放大效应会拖慢编译速度,极端情况下还会导致 clang 进程崩溃或链接器无法创建输出文件。我的经验是,源码卷的可用空间从 150GB 开始,每次构建结束后注意观察剩余容量变化,如果发现空间一直往红线走,就需要清理旧构建产物了。

src下最占空间的通常是out目录,删除不必要的构建输出可以直接释放大量空间:

rm -rf out/旧的构建目录名

3. Xcode 与 Command Line Tools:环境准备里最容易被低估的环节

很多第一次接触 Chromium 编译的人对 Xcode 的理解是"装个 IDE 而已",但在这个项目里,Xcode 的核心作用是提供编译 macOS 原生代码所需的 SDK、工具链以及系统库头文件。Chromium 编译对 Xcode 版本的敏感程度,可以说远超一般项目。

3.1 Xcode 正式版优先,别用 beta 当主力

Chromium 官方 CI 对工具链的跟进速度很快,但默认情况下都是基于最新的稳定版 Xcode 做验证。beta 版 Xcode 不是不能用,而是经常出现 chromium 构建脚本还没来得及适配的情况,表现就是 gn 阶段直接报 SDK 版本不满足要求,或者构建到一半链接器炸掉。我见过有人在 macOS 上装了 Xcode 26 beta,折腾一整天才发现是版本适配问题。

所以环境准备的原则就一条:去 App Store 安装当前最新的正式版 Xcode。以 macOS 14/15 搭配 Chromium 144 的经验看,Xcode 16.x 系列是合理的选择。安装过程需要下载好几个 GB 的安装包,时间会比较长,建议预留出充足时间,不要边下载边编译。

3.2 首次启动的许可协议与 xcode-select -p

Xcode 安装完成后,很多人直接跑编译,结果 gn 报错说找不到 Xcode 或者许可协议未接受。这是因为 Xcode 的许可证需要显式同意,命令行工具才能正常工作。首次打开 Xcode 应用后它会弹窗要求同意协议,如果没有图形界面操作条件,也可以直接执行:

sudo xcodebuild -license accept

接下来是比较关键的一步:安装 Command Line Tools。这个组件经常被忽略,因为 Xcode 本身带了一部分命令行工具,但 Chromium 构建需要独立的 Command Line Tools 来配合工作:

xcode-select --install

安装完成后,务必验证当前激活的开发目录路径:

xcode-select -p

正常情况下输出应该指向:

/Applications/Xcode.app/Contents/Developer

如果输出的是/Library/Developer/CommandLineTools,说明当前激活的是精简版命令行工具而不是完整 Xcode,gn 会因为找不到完整 SDK 而报错。解决办法是用sudo xcode-select -s手动切换:

sudo xcode-select -s /Applications/Xcode.app/Contents/Developer

这一步是环境准备中最容易翻车的细节,很多人明明装了 Xcode,gn 却报一堆 SDK 路径相关的错误,根因就是xcode-select指向错了地方。

3.3 验证编译器与 SDK 版本的匹配关系

Xcode 安装并激活完成后,还需要验证编译器工具链的状态。执行以下三组命令:

xcrun --show-sdk-path xcrun --show-sdk-version clang --version

第一组命令输出 SDK 的完整路径,第二组输出 SDK 版本号,第三组输出编译器信息。正常状态下,xcrun --show-sdk-path应该指向 Xcode 内部的MacOSX.sdk目录,而不是 Command Line Tools 的 SDK 目录。如果这三项任意一项为空或报错,说明 Xcode 安装不完整或路径有残留问题。

关于版本匹配关系,可以做一个粗略的参考:

操作系统版本建议 Xcode 版本说明
macOS 15 SequoiaXcode 16.x搭配 Chromium 144 比较顺
macOS 14 SonomaXcode 15.x 或 16.x需要确保 SDK 版本不被 Chromium 判定过旧
macOS 13 VenturaXcode 15.x能用,但可能出现版本告警

Chromium 构建脚本对 Xcode 版本的容忍窗口比较窄,版本太高或太低都可能被判定不可用。所以在正式动手之前,先确认自己的 Xcode 版本在当前系统上能正常工作,并且介于 Chromium 144 可接受的范围内。如果后续 gn 报出Xcode version does not meet minimum requirements这样的错误,优先考虑升级 Xcode 而不是绕过检查。

4. depot_tools:Chromium 所有命令行工具的真正来源

如果你之前编译过一些开源项目,大概率习惯用 Homebrew 安装各种依赖工具。但在 Chromium 的世界里,这个习惯要改一改。Chromium 官方维护了一套独立的命令行工具集,叫 depot_tools,fetch、gclient、gn、ninja、autoninja 这些命令全部来自这里。

4.1 克隆 depot_tools 的正确方式和目录位置

不要用 Homebrew 安装 depot_tools。Homebrew 里的版本更新可能滞后于 Chromium 主线,并且安装路径和官方预期不一致,容易引发后续各种奇怪问题。官方推荐的方式是直接从 googlesource 克隆源码:

git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git ~/depot_tools

建议把 depot_tools 克隆到用户目录下的~/depot_tools,这个路径在后续配置 PATH 时最自然。克隆完成后,目录里已经有了一系列可执行脚本,但还需要把目录加入 PATH 才能让系统找到这些命令。

4.2 PATH 配置与自动更新机制

打开~/.zshrc(如果用的是 zsh)或~/.bashrc(如果用的是 bash),在文件头部加入:

export PATH="$HOME/depot_tools:$PATH"

然后重新加载配置:

source ~/.zshrc

或者直接新开一个终端窗口。这里有一个细节值得注意:$HOME/depot_tools一定要放在 PATH 的最前面,不要追加在末尾。原因是某些 macOS 系统自带或 Homebrew 安装的工具可能与 depot_tools 中的同名命令冲突,把 depot_tools 放在前面可以确保系统优先执行 Chromium 官方版本。

depot_tools 还有一套自动更新机制。每次执行gclientfetch等命令时,它会先检查自身是否有更新,有就自动拉取。这套机制在个人开发环境里建议保留,它保证了工具链和 Chromium 主线的同步。如果在 CI 环境里,可以用环境变量DEPOT_TOOLS_UPDATE=0禁掉自动更新,避免每次构建都被拉取动作拖慢。

4.3 为什么 fetch、gn、ninja、gclient 都从这里来

很多人第一次接触 Chromium 构建时,会被这一堆工具搞糊涂。简单梳理一下各自的职责:

  • fetch:负责初始化项目、拉取主源码和第三方依赖。
  • gclient:Chromium 的依赖管理工具,相当于其他项目里的git submodule和包管理器的结合体。
  • gn:元构建系统,负责根据构建参数生成 Ninja 构建文件。它不直接编译代码,而是产生"如何编译"的蓝图。
  • ninja:真正的构建执行器,负责调度编译和链接任务。它的核心优势是增量构建和并行调度能力。
  • autoninja:对 ninja 的封装,会自动根据机器核心数和内存情况设置合理的并发参数。

把这套工具想成一条流水线:fetch把原料拉回来,gclient整理依赖关系,gn画好施工图,ninja负责按图施工。后续所有操作都离不开这条流水线,而它们全都位于~/depot_tools目录下。

配置完成后,可以做一次快速验证:

gclient --version fetch --help gn --version

fetch --help能正常输出说明命令已经生效。gn --version首次运行时会尝试下载预编译的 gn 二进制,需要网络畅通,看到版本号输出就说明 depot_tools 这一环已经通了。

5. fetch chromium --no-history:第一次拉取源码的完整动作

环境准备到这里,距离真正动手只剩一步:把源码拉下来。这一步的动作很简单,但有非常多的细节值得讲究。

5.1 源码根目录的组织方式和 .gclient 配置

在大小写敏感的磁盘卷下新建一个目录,比如前面创建的/Volumes/ChromiumDev/chromium

mkdir -p /Volumes/ChromiumDev/chromium cd /Volumes/ChromiumDev/chromium

然后在当前目录下执行 fetch:

fetch chromium --no-history

这里的--no-history参数非常关键。Chromium 的 git 历史非常庞大,完整拉取的话光历史记录就能占用几十上百 GB,下载时间和磁盘消耗都会成倍增加。对于大多数只想编译和开发的人来说,历史记录没有太大价值,--no-history只拉取当前代码快照,干净利落。

fetch 过程会自动创建.gclient文件。这个文件记录了项目的依赖配置,初始内容大致长这样:

solutions = [ { "name": "src", "url": "https://chromium.googlesource.com/chromium/src.git", "managed": False, "custom_deps": {}, "custom_vars": {}, }, ]

.gclient文件告诉 gclient 工具主源码的位置以及需要同步哪些依赖。如果后续想配置 iOS 交叉编译或其他目标平台,就在这个文件里加target_os字段,但 macOS 原生构建一般不需要改动。

5.2 拉取耗时、过程观察与断点续传

fetch 的耗时取决于网络状况和磁盘速度,常见的区间在半小时到两小时。期间终端会滚动大量输出,主要分两个阶段:第一阶段是 git 拉取主仓库,第二阶段是 gclient 同步第三方依赖。后者会列出一个个子项目名和进度,比如third_party/llvmv8webrtc这些重头戏,每一个都可能单独下载几百 MB 到几个 GB。

整个过程比较枯燥,但不建议全程盯着终端。有一个经验可以分享:fetch 过程中如果因为网络波动或休眠导致中断,不要慌,直接重新执行一遍fetch chromium --no-history,git 和 gclient 都支持断点续传,已经下载完的部分不会重新来一遍。千万不要因为中断就删掉目录重下,那样反而浪费更多时间。

判断 fetch 是否完成的标志是:gclient 的同步阶段结束,进入Running hooks阶段,并且最终没有 fatal error 输出。Hooks 是 Chromium 构建系统在源码同步完成后自动执行的一些脚本任务,比如下载构建工具链、生成必要的补丁文件等。看到 hooks 跑完,说明这次拉取基本成功了。

5.3 拉完后先别急着编译,检查这几个关键文件

fetch 完成后不要急着立刻跳到 gn 阶段,先花两分钟做几个确认:

cd src cat chrome/VERSION ls -d buildtools/ third_party/llvm/

cat chrome/VERSION会输出类似这样的内容:

MAJOR=144 MINOR=0 BUILD=XXXX PATCH=XXXX

确认MAJOR=144就说明当前代码确实就是目标里程碑。检查buildtoolsthird_party/llvm是否存在,这两个目录是构建的关键依赖,如果缺失,后续 gn 和 ninja 都会报错。

如果 fetch 过程中终端输出显示一切正常,但目录结构感觉不对,可以再补跑一次同步:

gclient sync

gclient sync会重新检查所有依赖是否完整,并自动补下载缺失部分。如果需要重新执行源码生成阶段的脚本,也可以跑:

gclient runhooks

这一步会重新执行依赖中的 hook 脚本,通常在升级 Xcode 或切换系统 SDK 版本后特别有用。

6. 最小验证:gn gen 跑通,环境准备才算真正结束

源码拉完,环境准备看起来"完成"了,但我个人衡量环境是否就绪的标准,从来不是"装了 Xcode"或者"拉完了代码",而是gn gen能顺利跑出一个构建目录。这个验证过不了,后面全是空中楼阁。

6.1 首次 gn gen 的参数怎么给

进入src目录,第一次生成构建文件的时候,参数建议简洁克制。我的建议是先做一次 Release 风格的组件构建验证,参数如下:

cd /Volumes/ChromiumDev/chromium/src gn gen out/Default --args="is_debug=false is_component_build=true symbol_level=0"

逐个解释这几个参数:

  • is_debug=false:生成 Release 配置,不额外注入调试符号信息,编译速度更快,产出体积更小。
  • is_component_build=true:组件构建模式,把整个 Chromium 拆分成一系列动态库,而不是链接成一个巨型可执行文件。这个模式能大幅降低链接阶段的内存压力和时长,是日常开发验证的首选。
  • symbol_level=0:不生成调试符号。环境验证阶段不需要符号,等后面真正需要断点调试再单独开。

如果你后面打算完整调试 Chromium 源码,可以换成is_debug=true加默认的symbol_level=2,但磁盘和内存压力会成倍上升,不建议在环境准备阶段就开满。

gn gen成功时,输出会显示生成的 build.ninja 文件路径,以及类似 "Done. Made xxx targets" 的信息。同时out/Default目录下会生成args.gnbuild.ninja两个关键文件。看到这个输出,说明环境配置已经通了。

6.2 三个高频首跑报错与根因分析

环境准备阶段最容易撞上的报错其实非常固定,我整理成了一张对照表,遇到问题可以直接对着排查:

报错现象根本原因解决方案
gn: command not founddepot_tools 没有加入 PATH,或 PATH 顺序不对检查source ~/.zshrc是否执行,确认which gn指向~/depot_tools
Xcode version does not meet minimum requirementsXcode 版本过旧或者路径指向了 Command Line Tools升级到正式版 Xcode,sudo xcode-select -s切换到完整 Xcode
No space left on device磁盘容量或卷容量不足清理旧构建产物,给源码卷留出至少 50GB 以上空间

第一个报错最常见的原因是配置完 PATH 后没有重新加载配置,或者新开的终端没有读取到~/.zshrc。第二个报错很多时候不是 Xcode 版本真的老,而是xcode-select -p输出了错误路径。第三个报错则要从两方面看:总磁盘空间不足是表层,深层原因可能是大小写敏感卷创建时分配的容量不够,需要先用diskutil apfs resize调整卷容量。

还有一个不那么高频但同样容易误判的报错是FATAL: xcode-select: error: tool 'xcodebuild' requires Xcode, but system active developer directory is '/Library/Developer/CommandLineTools'。这个英文报错已经把答案说得很直白了,就是系统激活的开发目录不对,同样的解法,切回完整 Xcode 路径即可。

6.3 验证完成后的个人建议

gn gen通过之后,环境准备这个阶段才算真正收口。但如果你想让这次准备更扎实,我建议再做一步轻量级验证:编译一个体积较小的基础库,确认编译器工具链和 Ninja 调度真正能跑通。

进入src目录,执行:

autoninja -C out/Default base

base是 Chromium 的基础库,依赖相对少,编译时间通常控制在几分钟到十几分钟,却能完整覆盖 clang 编译、链接、产物生成这一整条链路。看到base库的链接产物生成,就说明从 Xcode 到 depot_tools 再到源码目录的每一环都已经打通了。

这时候你可能会想干脆直接编全量chrome目标,我的建议是不要急。全量chrome链接在普通配置的机器上可能要跑几十分钟到几个小时,而且内存不足时很容易在链接阶段直接爆掉。先把base这样的小目标跑通,确认环境稳定,后续再逐步加大目标,排查问题时会轻松很多。

环境准备的验证到这里就完成了。对我个人来说,判断 macOS 环境是否真的准备好,从来不是"装完了 Xcode"或者"拉完了代码",而是gn gen之后能稳定跑完base这样一个基础目标的编译。这一步跑通,后面的构建才有意义,排查问题也才有参照系。下一篇我会展开讲gn args的完整参数选择和 Ninja 构建的实战调优。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询