Homebrew 使用中的一些问题

2023-03-31 • 更新于 2023-11-01

编译 Go 项目超时

众所周知,国内网络环境编译 Go 项目会超时,只要设置国内镜像即可:

export GO111MODULE=on
export GOPROXY=https://goproxy.cn,direct

我想了十天十夜也不明白,源码服务器也要屏蔽?多少有点脑瘫哦。

然而即使设置了镜像,Homebrew 在编译 Go 项目时,不知何故不会读取用户设置,于是也会超时:

==> go build -o=/usr/local/Cellar/v2ray/5.3.0/libexec/v2ray -ldflags=-s -w -buildid= ./main
Last 15 lines from /Users/username/Library/Logs/Homebrew/v2ray/01.go:
proxy/vmess/encoding/auth.go:8:2: golang.org/x/crypto@v0.4.0: Get "https://proxy.golang.org/golang.org/x/crypto/@v/v0.4.0.zip": dial tcp 142.251.42.241:443: i/o timeout
common/protocol/dns/io.go:7:2: golang.org/x/net@v0.4.0: Get "https://proxy.golang.org/golang.org/x/net/@v/v0.4.0.zip": dial tcp 142.251.43.17:443: i/o timeout
app/dns/nameserver_quic.go:14:2: golang.org/x/net@v0.4.0: Get "https://proxy.golang.org/golang.org/x/net/@v/v0.4.0.zip": dial tcp 142.251.43.17:443: i/o timeout
transport/internet/http/hub.go:11:2: golang.org/x/net@v0.4.0: Get "https://proxy.golang.org/golang.org/x/net/@v/v0.4.0.zip": dial tcp 142.251.43.17:443: i/o timeout
common/strmatcher/matchers.go:9:2: golang.org/x/net@v0.4.0: Get "https://proxy.golang.org/golang.org/x/net/@v/v0.4.0.zip": dial tcp 142.251.43.17:443: i/o timeout
common/protocol/headers.go:6:2: golang.org/x/sys@v0.3.0: Get "https://proxy.golang.org/golang.org/x/sys/@v/v0.3.0.zip": dial tcp [2404:6800:4012:2::2011]:443: i/o timeout
transport/internet/filelocker_other.go:9:2: golang.org/x/sys@v0.3.0: Get "https://proxy.golang.org/golang.org/x/sys/@v/v0.3.0.zip": dial tcp [2404:6800:4012:2::2011]:443: i/o timeout
app/commander/commander.go:10:2: google.golang.org/grpc@v1.51.0: Get "https://proxy.golang.org/google.golang.org/grpc/@v/v1.51.0.zip": dial tcp 142.251.43.17:443: i/o timeout
transport/internet/grpc/dial.go:13:2: google.golang.org/grpc@v1.51.0: Get "https://proxy.golang.org/google.golang.org/grpc/@v/v1.51.0.zip": dial tcp 142.251.43.17:443: i/o timeout
app/instman/command/command_grpc.pb.go:6:2: google.golang.org/grpc@v1.51.0: Get "https://proxy.golang.org/google.golang.org/grpc/@v/v1.51.0.zip": dial tcp 142.251.43.17:443: i/o timeout
transport/internet/grpc/dial.go:14:2: google.golang.org/grpc@v1.51.0: Get "https://proxy.golang.org/google.golang.org/grpc/@v/v1.51.0.zip": dial tcp 142.251.43.17:443: i/o timeout
transport/internet/grpc/dial.go:15:2: google.golang.org/grpc@v1.51.0: Get "https://proxy.golang.org/google.golang.org/grpc/@v/v1.51.0.zip": dial tcp 142.251.43.17:443: i/o timeout
transport/internet/grpc/encoding/conn.go:13:2: google.golang.org/grpc@v1.51.0: Get "https://proxy.golang.org/google.golang.org/grpc/@v/v1.51.0.zip": dial tcp 142.251.43.17:443: i/o timeout
app/commander/service.go:7:2: google.golang.org/grpc@v1.51.0: Get "https://proxy.golang.org/google.golang.org/grpc/@v/v1.51.0.zip": dial tcp 142.251.43.17:443: i/o timeout
app/instman/command/command_grpc.pb.go:7:2: google.golang.org/grpc@v1.51.0: Get "https://proxy.golang.org/google.golang.org/grpc/@v/v1.51.0.zip": dial tcp 142.251.43.17:443: i/o timeout

Homebrew 编译时实际上调用的是 Ruby 脚本,那就可以直接修改脚本。以 v2ray 为例:

cd $(brew --repository homebrew/core)
❯ git diff
diff --git a/Formula/v2ray.rb b/Formula/v2ray.rb
index 297d0759440..baef313f96f 100644
--- a/Formula/v2ray.rb
+++ b/Formula/v2ray.rb
@@ -39,6 +39,9 @@ class V2ray < Formula
   end

   def install
+    ENV['GO111MODULE'] = 'on'
+    ENV['GOPROXY'] = 'https://goproxy.cn,direct'
+
     ldflags = "-s -w -buildid="
     system "go", "build", *std_go_args(ldflags: ldflags, output: libexec/"v2ray"), "./main"

install 编译命令前添加 ENV['GO111MODULE'] = 'on'ENV['GOPROXY'] = 'https://goproxy.cn,direct' 就可以了。

sha256 mismatch

这类问题出现频率很高,在官方仓库可以看到大量相关的 issue、commit 和 PR。

除了网络问题外,通常有两种原因。

上游重新发布同一版本

这时依旧修改脚本,例如 launchcontrol

cd $(brew --repository homebrew/cask)
❯ git diff
diff --git a/Casks/launchcontrol.rb b/Casks/launchcontrol.rb
index 5c2db44947..db25b721a8 100644
--- a/Casks/launchcontrol.rb
+++ b/Casks/launchcontrol.rb
@@ -1,7 +1,7 @@
 cask "launchcontrol" do
   on_catalina :or_older do
     version "1.52.7"
-    sha256 "16c3d89e41a99cbf43e6996681358e8e7a4bc63fa770b9f8c0bc72c5356a0b8a"
+    sha256 "760edc3f3238ecbbc9f0c14b17ced9ac2a46c46a4ed8feec6bfb532fced37b7e"

     livecheck do
       skip "Legacy version"

确认没问题的话可以去提 PR。

源码归档在服务端重新生成

GitHub 和 Gitlab 都使用 git archive 将源码归档为 tar 包,但不管是 GitHub1 还是 Gitlab2,都不保证源码归档的稳定性。

例如我发现的 Gitlab 校验变化问题:

❯ curl -fsSL https://gitlab.com/AOMediaCodec/SVT-AV1/-/archive/v1.4.1/SVT-AV1-v1.4.1.tar.bz2 | sha256sum
2ddef549e1eaeecc1fc48f0d8332ea3545809e46509db69beb3a0a4bf19ef906  -
# 过一段时间
❯ curl -fsSL https://gitlab.com/AOMediaCodec/SVT-AV1/-/archive/v1.4.1/SVT-AV1-v1.4.1.tar.bz2 | sha256sum
0e988582f315fe76c909accf5e7f81b975c5bd2b850ee760d8e9fac297f70b5d  -

两个 tar 包内容完全一样,只有文件夹名不同:

❯ curl -fsSL https://gitlab.com/AOMediaCodec/SVT-AV1/-/archive/v1.4.1/SVT-AV1-v1.4.1.tar.bz2 >old
# 过一段时间
❯ curl -fsSL https://gitlab.com/AOMediaCodec/SVT-AV1/-/archive/v1.4.1/SVT-AV1-v1.4.1.tar.bz2 >new
❯ tar xf old
❯ ls
SVT-AV1-v1.4.1
❯ tar xf new
❯ ls
SVT-AV1-018276d714ce65d9b586f6205ee016cbd8d5425d
SVT-AV1-v1.4.1
❯ diff SVT-AV1-v1.4.1 SVT-AV1-018276d714ce65d9b586f6205ee016cbd8d5425d -r
echo $?
0

我也是服了某些 Homebrew 的维护者,复现不了我的问题就说是我配置问题,神他妈配置问题😅

Gitlab 官方人员解释如下:

The root cause was discussed in a confidential issue, but I can share a general idea what went wrong.

One of deployed fixes had a side-effect of changing the hash sum of the archived files.
When it was discovered, we reverted the code.
However, Cloudflare still responded with old archive files for some regions.
We updated the cache and that resolved the problem.

好了,破案了。Gitlab 也是个鬼才,归档生成机制变了也就算了,同一个老 URL,还能返回不同的文件。

要是不幸遇到这种问题,自认倒霉吧,依旧直接改脚本。鬼知道什么时候抽风。

其结果就是,明明服务商不保证自动归档的稳定性,而 Homebrew 却依赖这一点。

要保证源码包的稳定性,应该由作者官方以 release 形式发布,就像各种开源软件官网那样,然后由官方提供校验方法。

那么从全局看,怎么避免这种错误?我觉得 Homebrew 完全可以定期检查哈希值,如果变更则自动提 PR,这一点可以通过 CI/CD 自动化完成。

Warning: You are using macOS 10.15.

We (and Apple) do not provide support for this old version.
It is expected behaviour that some formulae will fail to build in this old version.
It is expected behaviour that Homebrew will be buggy and slow.
Do not create any issues about this on Homebrew's GitHub repositories.
Do not create any issues even if you think this message is unrelated.
Any opened issues will be immediately closed without response.
Do not ask for help from Homebrew or its maintainers on social media.
You may ask for help in Homebrew's discussions but are unlikely to receive a response.
Try to figure out the problem yourself and submit a fix as a pull request.
We will review it but may or may not accept it.

啊对对对,我知道我们老古董不配用高贵的 Homebrew,出了问题后果自负我理解。

但是你每次一大堆烦人的警告跳脸连个他妈的开关都没有?哪怕减到一行呢?

何况苹果只是对系统停止了支持,你一个包管理器,不想支持老系统直接大方说不就行了,和苹果对系统的支持有个毛线关系?难道苹果不让 Catalina 用户用 App Store 了?Ubuntu 就连 12.04 甚至更老的版本,改一下源就能继续用官方的老仓库。

对于一个非盈利的开源软件,我表示支持,但你别又当又立😅

发现我脾气逐渐暴躁,管他的,反正鬼佬看不懂中文。

编辑 $(brew --repository)/Library/Homebrew/extend/os/mac/diagnostic.rb 这个脚本,在 check_for_unsupported_macos 方法第一行直接返回:

cd $(brew --repository)
❯ git diff
diff --git a/Library/Homebrew/extend/os/mac/diagnostic.rb b/Library/Homebrew/extend/os/mac/diagnostic.rb
index 1cbc907f3..37b5b91ba 100644
--- a/Library/Homebrew/extend/os/mac/diagnostic.rb
+++ b/Library/Homebrew/extend/os/mac/diagnostic.rb
@@ -106,6 +106,7 @@ module Homebrew
       end

       def check_for_unsupported_macos
+        return
         return if Homebrew::EnvConfig.developer?
         return if ENV["HOMEBREW_INTEGRATION_TEST"]

整个世界都清净了!

当然,后果自负。

macOSGoHomebrew
知识共享许可协议
本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。

在 Linux 上使用 Exim4 发送邮件

在 Android 上部署 Linux