编译 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'
就可以了。
./t-git-credential-netrc.sh: No such file or directory
编译安装 git 时出现错误:
# ~/Library/Logs/Homebrew/git/05.make
make
test
/Applications/Xcode.app/Contents/Developer/usr/bin/make -C ../../.. SCRIPT_PERL="contrib/credential/netrc/git-credential-netrc.perl" \
build-perl-script
* new perl-specific parameters
\
INSTLIBDIR='/private/tmp/git-20250521-61559-k2ku4o/git-2.49.0/.brew_home/share/perl5' && \
INSTLIBDIR_EXTRA='/Applications/Xcode.app/Contents/Developer/Library/Perl/5.18/darwin-thread-multi-2level:/Library/Developer/CommandLineTools/Library/Perl/5.18/darwin-thread-multi-2level' && \
INSTLIBDIR="$INSTLIBDIR${INSTLIBDIR_EXTRA:+:$INSTLIBDIR_EXTRA}" && \
sed -e 's=@PATHSEP@=:=g' \
-e "s=@INSTLIBDIR@=$INSTLIBDIR=g" \
-e 's=@PERLLIBDIR_REL@=share/perl5=g' \
-e 's=@GITEXECDIR_REL@=libexec/git-core=g' \
-e 's=@LOCALEDIR_REL@=share/locale=g' \
perl/header_templates/fixed_prefix.template.pl >GIT-PERL-HEADER+ && \
mv GIT-PERL-HEADER+ GIT-PERL-HEADER
/bin/sh generate-perl.sh ./GIT-BUILD-OPTIONS ./GIT-VERSION-FILE GIT-PERL-HEADER "contrib/credential/netrc/git-credential-netrc.perl" "contrib/credential/netrc/git-credential-netrc+" && \
mv contrib/credential/netrc/git-credential-netrc+ contrib/credential/netrc/git-credential-netrc
./t-git-credential-netrc.sh
?!ERR?! ./t-git-credential-netrc.sh: No such file or directory
ok 1 - set up test repository
not ok 2 - git-credential-netrc
#
# perl "$GIT_SOURCE_DIR"/contrib/credential/netrc/test.pl
#
# failed 1 among 2 test(s)
1..2
make: *** [test] Error 1
提示找不到 ./t-git-credential-netrc.sh
这个文件,这个错误让人很容易以为是路径问题。
从 2.47.1 版本以后就这样,就先 pin 了,以为过一段时间会有 brew 或 git 维护人员发现并修复,然而都 2.49.0 了还是不行。
如果在 git 源码 contrib/credential/netrc
目录下运行 make testverbose
,会出现以下错误:
Perl v5.26.0 required--this is only v5.18.4
继续查阅源码可知 git 从 2.48 就开始要求 perl 5.26 了。
Catalina 自带的 /usr/bin/perl 只有 5.18,brew 编译 git 时并不使用 brew 版 perl,而是系统自带,于是我这个 Catalina 老同志就被偷袭了。
如果指定较新的 perl export PERL_PATH=/usr/local/bin/perl
,就可以正常编译。
对此,考虑以下几种解决方法:
如果不追求新版,可以 pin 在 2.47.1。
如果还没有用 brew 安装 git,本地有 homebrew-core 源码的话,可以提取历史版本并编译:
git show aecf26f53d0:Formula/g/git.rb >git.rb brew install ./git.rb --formula rm ./git.rb
或者去官方仓库下载历史版本。
brew 脚本我认为是有 bug 的,它编译出的 git-credential-netrc 中模块路径错误,用的是编译时的临时目录,例如
/private/tmp/git-20250527-25582-blyz61/git-2.49.0/.brew_home/share/perl5
。如果不需要 git-credential-netrc,可以将相关脚本注释掉。或者参考方法 3 修改路径。
如果想升级 git,可以将脚本中与 perl 相关部分注释掉,包括 git-credential-netrc、diff-highlight、git-send-email 相关代码,以及 Net::SMTP::SSL 模块(git-send-email 依赖它)。这也意味着这些工具将无法使用。
git 源码中还有一个
NO_PERL
环境变量,但我没试过。git-credential-netrc 可能用的人不多,毕竟 macOS 上一般用 SSH、git-credential-osxkeychain。但 diff-highlight 还是很有用的,可以在 diff 高亮显示不同的部分。git-send-email 用于发送邮件。
如果想升级 git 且需要 perl 相关工具,可以使用 brew 版 perl。
在 brew 脚本中做如下修改:
git diff Formula/g/git.rb diff --git a/Formula/g/git.rb b/Formula/g/git.rb index a58a53ea0d6..82200f7576f 100644 --- a/Formula/g/git.rb +++ b/Formula/g/git.rb @@ -23,6 +23,7 @@ class Git < Formula depends_on "gettext" depends_on "pcre2" + depends_on "perl" => :build uses_from_macos "curl", since: :catalina # macOS < 10.15.6 has broken cert path logic uses_from_macos "expat" @@ -125,12 +126,13 @@ class Git < Formula # Generate diff-highlight perl script executable cd "contrib/diff-highlight" do - system "make" + system "make", "PERL_PATH=#{ENV["PERL_PATH"]}" end # Install the netrc credential helper cd "contrib/credential/netrc" do - system "make", "test" + system "make", "PERL_PATH=#{ENV["PERL_PATH"]}", "test" + inreplace "git-credential-netrc", %r{(?<=\$ENV\{GITPERLLIB\} \|\| ')[^:']+}, share/"perl5" git_core.install "git-credential-netrc" end
depends_on "perl" => :build
指定 brew 版 perl,脚本会将路径保存在PERL_PATH
环境变量。子模块编译时此环境变量无效,因此 make 命令还是需要
PERL_PATH=
。inreplace
一行会将 git-credential-netrc 脚本中的临时路径use lib (split(/:/, $ENV{GITPERLLIB} || '/private/tmp/git-20250527-25582-blyz61/git-2.49.0/.brew_home/share/perl5:/Applications/Xcode.app/Contents/Developer/Library/Perl/5.40/darwin-thread-multi-2level:/Library/Developer/CommandLineTools/Library/Perl/5.40/darwin-thread-multi-2level'));
修改为形如
/usr/local/Cellar/git/2.49.0/share/perl5
,这也是编译脚本中模块安装位置。另外,临时路径之后的几个路径也是错误的。它在 brew 脚本里通过
PERLLIB_EXTRA
设置,这可能是新版 macOS 的路径。但不影响使用。最后可将
/usr/local/opt/git/share/git-core/contrib/diff-highlight
加入PATH
环境变量,并添加到 git 配置:git config --global pager.diff 'diff-highlight | less' git config --global pager.log 'diff-highlight | less' git config --global pager.show 'diff-highlight | less'
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"]
整个世界都清净了!
当然,后果自负。