编译 Chromium 这件事劝退过不少人,我身边就有朋友卡在环境配置这一步直接放弃。前面两篇我们把大方向聊完了:磁盘空间怎么估算、macOS 系统版本怎么选、Xcode 怎么装。今天这篇是整套流程里最要紧、也最容易被忽略的一环——配置 depot_tools。如果你是第一次听说这个名字,我简单解释一下:它是 Chromium 开发者的“瑞士军刀”,包含 gclient、gn、ninja 等一堆工具,后期拉源码、同步依赖、生成编译配置全靠它。机器可以一般,工具链必须顺,不然到最后连fetch chromium都跑不起来。这篇教程面向的是想在 macOS 上从零编译 Chromium 144 的同学,老手也可以跳过前半段直接看第四节的报错清单,保证有能直接用上的东西。
1. 为什么说 depot_tools 是编译 Chromium 的第一道门槛
1.1 depot_tools 到底是干什么的
很多新手最容易犯的错,是把 Chromium 当成一个“大号的 git 仓库”来理解:git clone下来,然后敲make。真实情况完全不是这样。Chromium 源码仓库本身就非常大,而且它还依赖几百个第三方库、工具链组件、测试数据,这些依赖并不是直接塞在 git 仓库里的,而是靠一个叫DEPS的文件描述出来。DEPS 文件里会写明每个依赖从哪个地址下载、对应哪个版本、哪些平台需要哪些钩子脚本。
depot_tools 里的gclient就是专门解析 DEPS 文件的工具。可以把它理解成“终极包管理器”:不仅拉取主仓库,还把整个依赖树一并拉下来;拉完依赖之后,还要执行 DEPS 里定义的 hooks,生成各类辅助文件。这里面的几个核心组件我得提一下:
- gclient:负责
sync(同步源码),是每次更新代码、切换分支时最先启动的工具。 - gn:生成 Ninja 构建文件的工具。Chromium 不再使用传统 configure / make 体系,所有构建配置都由 gn 管理。
- ninja:真正的编译执行器,性能比 make 快得多。
- vpython / cipd:管 Python 环境和工具包下载,Chromium 工具链里很多脚本要用。
换句话说,没有 depot_tools,你连 Chromium 源码的门都进不去。反过来说,只要 depot_tools 配置无误,后面九成的问题都不会落在“工具链缺失”上。
1.2 为什么不用 Homebrew 安装,偏要 git clone
有人会问:depot_tools 这么好用,为什么不用brew install depot_tools?答案很简单:depot_tools 更新太频繁了,而且必须和当前 Chromium 源码的版本严格匹配。Chromium 的构建脚本每天都在变,它的依赖工具也跟着变,Homebrew 里的版本往往是某个时间点的快照,滞后几天甚至几周,就可能出现“gclient 版本太老,解析不了新的 DEPS 格式”这种玄学问题。
官方推荐的拿法永远是:
git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git这样 depot_tools 本身也是一个 git 仓库,想更新时直接git pull就行,完全跟随上游。这个设计思路我觉得挺聪明:既然 Chromium 靠 DEPS 管依赖,那它自己的工具链也用 git 管,省掉中间商。
1.3 配置前的灵魂三问
我先劝你们在动手之前自查三件事,答不上来就先别急着往下走。
- macOS 版本是不是够新?Chromium 144 对系统版本有最低要求,太老的系统可能装不了新版 Xcode,进而缺 SDK。我的建议是至少保证系统能装最新或者次新的 Xcode。
- 磁盘空间留够了吗?depot_tools 本身不大,clone 下来大概几百 MB,但它只是个开始。后续
fetch chromium的源码加上编译产物,轻轻松松突破 100GB。我做过一次统计:源码仓库浅克隆约 20~30GB,编译产物跟配置和架构有关,x64 和 arm64 的中间文件混着放,80GB 只是底线。 - 命令行基础过关了吗?你至少要知道怎么打开终端、编辑
~/.zshrc、看懂 PATH 的概念。如果这些完全没概念,建议先花半小时补一下“环境变量”的知识,不然一个小问题就能卡住一下午。
这三关过了,我们开始正经配置。
2. macOS 上获取 depot_tools 的完整操作
2.1 先确认 Xcode Command Line Tools 装好了
虽然标题是配置 depot_tools,但我还是想从地基说起。macOS 上有非常多编译动作都依赖 Xcode 的命令行工具,包括 git 的某些组件、编译 C/C++ 代码的 clang、系统附带的 make 等。depot_tools 本身有一部分脚本也会调用系统工具链,所以这一步跑不掉。
打开终端,执行:
xcode-select --install如果系统提示“command line tools are already installed”,那就说明已经有了。如果弹窗开始安装,等它跑完就行。装完之后可以顺手验证:
xcode-select -p正常情况下会输出类似/Library/Developer/CommandLineTools的路径。这里有个小细节值得注意:很多人以为必须装完整版 Xcode,其实单看“配置 depot_tools”这一步,Command Line Tools 完全够用。但如果后面你要编译出完整的 macOS 应用包,还是建议从 App Store 装一份完整 Xcode。原因在于 Chromium 的打包脚本会调用一部分 Xcode 自带的工具,只有 CLT 时偶尔会报“missing SDK”一类的错。
2.2 拉取 depot_tools 代码并配置 PATH
现在进入主角环节。打开终端,切到用户主目录,用 git 把 depot_tools 拉下来:
cd ~ git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git我强烈建议把它放~/depot_tools,不要放到带空格或中文的路径下。这一步不是洁癖,而是因为 depot_tools 里很多 Python 脚本在解析路径时会把空格拆开,直接导致各种诡异的“找不到文件”错误。我见过有人把它放在/Users/zhang san/tools/depot_tools,结果 gclient 怎么跑怎么报错,最后挪到根目录下的用户目录就好了。
clone 完成之后,需要把 depot_tools 目录加入 PATH。macOS 现在的默认 shell 是 zsh,所以要操作~/.zshrc。执行:
echo 'export PATH="$HOME/depot_tools:$PATH"' >> ~/.zshrc source ~/.zshrc第一行是把环境变量追加进配置文件,第二行让当前终端立即生效。这里我特别解释一下为什么把$HOME/depot_tools放在最前面,而不是像某些教程那样追加到最后面:depot_tools 内部包含了一些它自己管理的工具包装脚本,比如 ninja、python3、甚至 git 周边脚本,确保它们能最先被找到,可以避免和系统自带或 Homebrew 安装的同名工具抢版本。尤其是 ninja,系统里可能装了一个老版本,如果 PATH 顺序不对,gclient 调用的就不是 depot_tools 里配套的 ninja,行为会很不可控。
新开一个终端窗口之后,可以用下面的命令确认 PATH 是否持久生效:
echo $PATH看到/Users/你的用户名/depot_tools出现在最前面,说明配置成功。
2.3 更新 depot_tools 的正确姿势
depot_tools 拉下来之后其实还不算真正“配好”,因为它内部的工具链会随着 Chromium 版本不断更新。第一次运行 gclient 的时候,它会自动执行一次 self-update,把工具链同步到最新状态:
gclient不要觉得奇怪,真的就是直接输入gclient什么都不带。它会做几件事:先检查自身更新,然后提示你输入更多参数。如果输出中看见了“Usage”或者“updating depot_tools”之类的字样,说明它已经正常运转起来了。
以后想手动更新也没问题,两种方式都可以:
git -C ~/depot_tools pull --rebase或者
gclient这里要提醒一句:不要随便把 depot_tools 切到某个历史版本。Chromium 源码需要的是“当前足够新”的工具集,很多人想“锁版本求稳”,结果反而是给自己挖坑。
2.4 常见初始化报错:git 身份信息没设置
有些人在第一次运行 gclient 时,会遇到 gclient 或者后续 git 命令抱怨没有配置 user.name / user.email。虽然拉单纯拉源码不强制要求,但为了省心,我还是建议提前设置:
git config --global user.name "Your Name" git config --global user.email "you@example.com"这只是写一个身份标识进去,不会影响任何隐私安全,但它能让后面和代码审查、提交相关的脚本不闹脾气。
3. 验证配置与工具链自检
3.1 三个命令判断 depot_tools 是否配好
配置完不急着去拉源码,先做一次快速自检,确保 depot_tools 确实可用。我习惯用下面三个命令:
which gclient ninja --version gclient --helpwhich gclient输出应该指向~/depot_tools/gclient,如果指向了别的地方,说明 PATH 有问题。ninja --version能跑通说明 depot_tools 里的编译工具就位了。gclient --help输出一段长长的可选参数说明,代表脚本可以正常执行。
还有一种情况我想单独拎出来讲:如果你输入gclient后提示 command not found,但which gclient却能找到,自己找一下原因——八成是 shell 的 hash 缓存太旧,直接执行hash -r刷新,或者关掉当前终端重新开一个。
3.2 认识一下 gclient 和 gn 的版本表现
很多教程会让你执行gclient --version,但实际上这个命令在很多版本里并不存在。gclient 的“自我报告”形式比较特殊:裸敲gclient,它会显示 usage 信息,同时如果检测到有新版本更新,它会在输出里提示。不要因此怀疑自己配错了。
至于gn,它的情况比 gclient 复杂一些:gn并不是 depot_tools clone 下来就立刻出现在目录里的关键二进制,真正可用的gn文件通常是在第一次 gclient sync 时通过 cipd 下载到指定目录的。所以现在用which gn找不到不用慌,等源码同步完再验证就可以。ninja 则不同,它在 depot_tools 里已经包含了对应 macOS 的预编译版本,这也是为什么我推荐用 ninja 来快速验证。
3.3 环境变量踩坑实录
配置 PATH 看着简单,实际踩坑的人不少。我总结三个最常见的:
- 写进了
.bash_profile而不是.zshrc:macOS 默认 shell 是 zsh,如果你手动切到了 bash,配置文件自然不一样。可以用echo $SHELL看当前 shell 类型。 - 路径写错了:
export PATH="$HOME/depot_tools:$PATH"这一段,如果你不小心在 depot_tools 后面多打了个斜杠,比如/depot_tools/,部分脚本也会出现差异。 - 覆盖了原有 PATH:有人写
export PATH="$HOME/depot_tools",少了:$PATH那一段。这下等于把系统原来的可执行目录全丢了,连ls都找不到了。遇到这种情况不要慌,在命令窗口里手动用全路径执行编辑器,把写错的配置改回来,或者直接export PATH="/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:$PATH"临时补救。
4. 常见报错与排查清单
这一节我直接给一份速查表,都是我在实际配置过程中见过、或者帮朋友排查过的典型问题。建议先收藏,遇到报错再回来对照。
| 错误现象 | 常见原因 | 处理方法 |
|---|---|---|
-bash: gclient: command not found | PATH 没配置成功,或者当前终端没有 reload | 执行source ~/.zshrc,然后用which gclient确认 |
xcrun: error: invalid active developer path | Command Line Tools 缺失或路径残留 | 执行xcode-select --install,必要时sudo xcode-select --reset |
Agreeing to the Xcode/iOS license requires admin privileges | Xcode 安装后未接受许可证 | 执行sudo xcodebuild -license accept |
python3: No module named ... | 系统 Python 版本被 pyenv 或 Homebrew 替换,和 depot_tools 期望不一致 | 暂时移除 pyenv 的 PATH 注入,或者直接用~/depot_tools/里的 vpython 环境 |
dirmd: command not found | depot_tools 内部文件缺失或版本过老 | 进入~/depot_tools执行git pull --rebase,再跑gclient |
| 打开工具弹出“无法验证开发者” | macOS Gatekeeper 拦截第一次执行 | 在“系统设置-隐私与安全性”里允许,或者右键打开 |
gclient sync长时间没有任何输出 | 网络连接不稳定,或者正在下载大文件 | 不要频繁中断,耐心等;必要时换一个网络平稳的时间段再试 |
源码同步时报错git: invalid active developer path | 只设置了 PATH,没有装 Command Line Tools | 回第二章先执行xcode-select --install |
接下来挑两个我印象最深的问题展开说。
4.1 带空格的路径引发的灵异 Bug
我第一次在一台旧机器配置 depot_tools 时,图省事把目录放到了/Users/me/My Tools/depot_tools。结果第一次运行gclient就开始报错,错误信息还特别抽象,一会儿说找不到某个 Python 脚本,一会儿说目录下没有某文件。我检查了好几遍目录内容,明明文件都在。最后我用python3手动执行那个报错脚本,才看到是路径解析时把带空格的路径拆成了两截。解决办法很简单,重新 clone 到~/depot_tools就一切正常了。从那以后,凡是涉及 Chromium 相关工具链,我全部遵守一个原则:路径必须纯英文、无空格、无特殊字符。
4.2 Python 版本被 pyenv 劫持的惨案
某开发者遇到过一个很有迷惑性的报错:gclient一运行就提示No module named pylint,而且pip install pylint也没用,因为报错来自 depot_tools 内部脚本,它用的不是系统里的 Python 而是 vpython 虚拟环境。后来发现,他的~/.zshrc里有一条pyenv init,导致 python3 指向了 pyenv 管理的版本,depot_tools 检测到 Python 环境“不对劲”,就直接罢工。绕开 pyenv 之后,gclient 立刻恢复。我的建议是:配置 depot_tools 这个阶段,先不要让脚本环境有任何“多余”的干预。如果你确实离不开 pyenv,可以在.zshrc里暂时注释掉相关配置,或者专门把 depot_tools 的 PATH 优先级再提高一点。
4.3 Gatekeeper 拦截未签名二进制
macOS 对从 git clone 下来的二进制文件很敏感,尤其 depot_tools 目录里有一些预编译的小工具,第一次运行时系统会弹出“无法验证开发者”的提示。很多人的第一反应是去网上找强制放行的脚本,但我个人不太推广这种偏暴力的做法。更稳妥的方式是打开“系统设置-隐私与安全性”,在底部找到被拦截的条目,点击“仍要打开”。如果你要非常频繁地使用,也可以考虑在第一次放行后再观察两三次,确认没有异常。
5. depot_tools 配好之后,下一步该做什么
5.1 拉取 Chromium 144 源码的两种方式
工具链配置完,紧接着就是拉源码。这一步会极大考验耐心,但至少工具是齐的。我一般推荐在新目录里操作:
mkdir chromium cd chromium fetch --nohooks chromium熟悉的人可能会好奇,为什么我这里用--nohooks。因为第一次 fetch 时如果同时执行 hooks,下载量会非常可观,一旦中间断了,后续排查起来很头疼。先只拉代码,确认无误后再补跑:
gclient sync需要说明的是,fetch chromium拉下来的默认分支通常是主线代码,版本号会随着 Chromium 迭代自然推进。如果你必须锁定 Chromium 144 的版本号,可以在源码目录里切到对应版本的分支或者 tag 再进行同步。这个操作的时间取决于网络,我见过快的话二十多分钟,慢的话两三个小时都很正常。
5.2 第一次 gclient sync 会等很久
很多人第一次跑gclient sync时看到屏幕上一堆滚动日志,以为卡死了,其实它在并行下载大量依赖。这里我分享一个经验:不要在中途疯狂按 Ctrl+C。Chromium 依赖树里有不少压缩包,断掉以后重新 sync 确实能续传,但部分状态文件可能不一致,反而带来额外的问题。如果实在想中断,宁可等它完成前几个阶段再停,也不要在压缩包解压动作正进行时强停。
5.3 编译参数的前置了解
源码同步完,就该生成构建配置了。记住两个命令:
gn gen out/Default gn args out/Default第一行是生成默认配置,第二行是打开编辑器修改构建参数。常见的一个入门参数是:
is_debug=false is_component_build=false这组参数能编译出一个比较完整、性能也不差的浏览器。之后再执行:
autoninja -C out/Default chromeautoninja 是 depot_tools 里对 ninja 的封装,它会自动根据 CPU 核心数调整并行任务数量,比直接敲ninja -j 16这种手动模式省心得多。第一次编译耗时会比较长,我在这台 Mac 上实测大概两三小时,取决于 CPU 型号和内存大小。
我在整个配置过程中最大的体会是:depot_tools 这个环节,慢就是快。很多人为了省时间跳过某些验证步骤,比如不装齐依赖直接拉源码,结果后面报错了还要回炉,反而更狼狈。把这一步走扎实,后面源码同步和编译都是在给它打配合。如果你现在卡在某个具体报错上,试试上面第四节的排查表;要是还找不到头绪,欢迎把终端里完整的报错原文发到评论区,我尽量帮你看看问题出在哪。