为macOS的Homebrew配置大陆镜像源

立泉

Homebrew之于macOS正如apt之于Ubuntu,且正如apt在大陆面临的网络问题一样,Homebrew也面临着相近甚至更糟的网络问题,因为它默认的居然就是“剪不断、理还乱”的GitHubGitHub Packages…后面会提到。

HomebrewmacOS的包管理器,但并没有被其内置,需要手动安装:

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

从官方脚本来看其实就是把HomebrewGitHub仓库clone下来,再把brew可执行文件映射到环境变量目录里。clone后所在的目录被称为prefix目录,在x86芯片的Mac上是/usr/local/,而在使用Apple SiliconMac上为了和Rosetta转译的包共存被改为/opt/homebrew/。其源码和可执行文件就位于[prefix]/Homebrew/之中,通过它安装的包都被保存在[prefix]/Cellar/目录里。

术语

Homebrew直译为“家酿啤酒🍺”,之所以取这么泛化的名字据说是因为当初作者根本没想到它之后会变得如此受欢迎,想要更改的时候已经来不及了。其实不仅仅这个名字,它所使用的术语也不是通用的package之类,而真的是一堆很形象的“酿酒”词。

prefix

前面提过是Homebrew的安装目录,通过brew安装的包都不会超出这个目录。

包会被安装到[prefix]/Cellar/中然后通过symlink软链接将其可执行文件和其它必要文件映射到[prefix]/里,因为可执行文件所在的[prefix]/bin/本身是环境变量$PATH的一部分,所以这个包也就能被外部使用。

formulae

直译“酿酒配方”,是安装时要从上游源码编译的包定义,现场酿酒。

这些包定义是通过一个GitHub仓库来管理的:

https://github.com/homebrew/homebrew-core

每个包都对应其中一个记录其属性的Ruby文件,通过brew安装要先从此仓库pull下来整个包列表所以会特别慢…

即然包列表就是一个git仓库,那么如果要上传自己的包到Homebrew就只需把自定义包文件push到这个仓库里即可,这也是Homebrew和其它包管理器很不一样的地方。

cask

直译“酒桶”,是macOS使用的原生包定义,和formulae一样也是通过GitHub仓库管理:

https://github.com/homebrew/homebrew-cask.git

bottle

直译“酒瓶”,是预编译好的二进制包,酿好的酒。

这些包都被托管在GitHub Packages上:

https://github.com/Homebrew/homebrew-core/packages

cellar

直译“酒窖”,是包的安装目录,也就是藏酒的地方:

[prefix]/Cellar/

keg

直译“装酒的小桶”,无论是现酿的酒formulae还是酿好的酒bottle,都要被pour倾倒到小酒桶keg放入地窖cellar储存,其实是指定包的指定版本的目录。

# 指定包的指定版本的目录
[prefix]/Cellar/kotlin/1.9.20/

使用Homebrew可能会经常看到keg-only这个词,意思是酒仅仅是被储存在酒窖里了,但并不能被外界使用,也就是说brew安装第二步将该包的可执行文件symlink软链接到[prefix]/bin/中并没有进行。原因可能是里面已经有同名文件,比如macOS自带的git也会软链接到这里,如果想使用brew安装的新版本git,需要按照提示执行brew link,但是建议在执行覆盖前先--dry-run检查一下可能会被影响的文件。

# 将git链接到[prefix]的对应目录,覆盖已有文件
brew link --overwrite git
# 检查并输出会被影响的文件
brew link --overwrite --dry-run git

对于一些不能使用软链接覆盖的包比如openjdk,可以通过手动将其路径添加进环境变量的方式解决。

brew info openjdk

==> openjdk: stable 21.0.1 (bottled) [keg-only]
Development kit for the Java programming language
https://openjdk.java.net/
/usr/local/Cellar/openjdk/21.0.1 (600 files, 331.4MB)
  Poured from bottle using the formulae.brew.sh API on 2023-11-13 at 01:24:39
From: https://mirrors.tuna.tsinghua.edu.cn/git/homebrew/homebrew-core.git/Formula/o/openjdk.rb
License: GPL-2.0-only with Classpath-exception-2.0
==> Dependencies
Build: autoconf ✔, pkg-config ✔
Required: giflib ✔, harfbuzz ✔, jpeg-turbo ✔, libpng ✔, little-cms2 ✔
==> Requirements
Build: Xcode (on macOS) ✔
Required: macOS >= 10.15 (or Linux) ✔
==> Caveats
For the system Java wrappers to find this JDK, symlink it with
  sudo ln -sfn /usr/local/opt/openjdk/libexec/openjdk.jdk /Library/Java/JavaVirtualMachines/openjdk.jdk

openjdk is keg-only, which means it was not symlinked into /usr/local,
because macOS provides similar software and installing this software in
parallel can cause all kinds of trouble.

If you need to have openjdk first in your PATH, run:
  echo 'export PATH="/usr/local/opt/openjdk/bin:$PATH"' >> ~/.zshrc

For compilers to find openjdk you may need to set:
  export CPPFLAGS="-I/usr/local/opt/openjdk/include"

rack

直译“装着很多小酒桶的支架”,其实是指定包的目录,它会包含很多版本keg

# rack
[prefix]/Cellar/kotlin/
# kegs
[prefix]/Cellar/kotlin/1.9.20/
[prefix]/Cellar/kotlin/1.9.21/

tap

直译“阀门”,比如formulaebottle的来源:

https://github.com/homebrew/homebrew-core
https://github.com/Homebrew/homebrew-core/packages

修改镜像源正是通过brew tap来实现的。

大陆镜像

现在我们知道为什么brew install这么慢了,不仅仅是从GitHub拉取代码和下载package,在4.0版本之后每次执行操作都会去https://formulae.brew.sh/api/获取完整的包信息,使用镜像源就是要将这些地址全都改为大陆链接。推荐我自用十分稳定的清华大学镜像站,它的文档比阿里云更完整,而且很奇怪我之前尝试阿里云Homebrew源均是404…不知道现在是什么状态。

首先编辑~/.zshrc添加这些brew使用的环境变量:

export HOMEBREW_API_DOMAIN="https://mirrors.tuna.tsinghua.edu.cn/homebrew-bottles/api"
export HOMEBREW_BREW_GIT_REMOTE="https://mirrors.tuna.tsinghua.edu.cn/git/homebrew/brew.git"
export HOMEBREW_CORE_GIT_REMOTE="https://mirrors.tuna.tsinghua.edu.cn/git/homebrew/homebrew-core.git"
export HOMEBREW_BOTTLE_DOMAIN="https://mirrors.tuna.tsinghua.edu.cn/homebrew-bottles"
export HOMEBREW_PIP_INDEX_URL="https://pypi.tuna.tsinghua.edu.cn/simple"

应用配置:

. ~/.zshrc

使用brew tap进一步修改源地址:

# 注:自 brew 4.0 起,大部分 Homebrew 用户无需设置 homebrew/core 和 homebrew/cask 镜像,只需设置 HOMEBREW_API_DOMAIN 即可。
# 如果需要使用 Homebrew 的开发命令 (如 `brew cat <formula>`),则仍然需要设置 homebrew/core 和 homebrew/cask 镜像。
# 请按需执行如下两行命令:
brew tap --custom-remote --force-auto-update homebrew/core https://mirrors.tuna.tsinghua.edu.cn/git/homebrew/homebrew-core.git
brew tap --custom-remote --force-auto-update homebrew/cask https://mirrors.tuna.tsinghua.edu.cn/git/homebrew/homebrew-cask.git
# 除 homebrew/core 和 homebrew/cask 仓库外的 tap 仓库仍然需要设置镜像
brew tap --custom-remote --force-auto-update homebrew/cask-fonts https://mirrors.tuna.tsinghua.edu.cn/git/homebrew/homebrew-cask-fonts.git
brew tap --custom-remote --force-auto-update homebrew/cask-versions https://mirrors.tuna.tsinghua.edu.cn/git/homebrew/homebrew-cask-versions.git
brew tap --custom-remote --force-auto-update homebrew/command-not-found https://mirrors.tuna.tsinghua.edu.cn/git/homebrew/homebrew-command-not-found.git
brew tap --custom-remote --force-auto-update homebrew/services https://mirrors.tuna.tsinghua.edu.cn/git/homebrew/homebrew-services.git

试试更新,芜湖起飞🚀。

brew update
arrow_upward