MacOS上进行Go应用编译至Linux
引言
在 macOS 上开发 Go 应用,但需要部署到 Linux 上时,跨平台编译可能会遇到一些坑。特别是当你的应用依赖需要 CGO 的库(比如 `libpq`)时,问题会更加复杂。
首次尝试
最初,我以为将 Go 应用编译为 Linux 很容易,只需要将 GOOS 环境变量设置为 linux 即可:
GOOS=linux go build -o my-app但是在 Linux 服务器上执行文件时,报了以下错误
failed to initialize database, got error Binary was compiled with 'CGO_ENABLED=0', libpq requires cgo to work. This is a stub提示 libpq 需要 CGO 才能正常工作。
再次尝试
为了解决这个问题,我启用了 CGO 再次尝试编译
CGO_ENABLED=1 GOOS=linux go build -o my-app但是又出现了如下编译错误
# runtime/cgo
linux_syscall.c:67:13: error: implicit declaration of function 'setresgid' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
...经过一番AI询问+搜索,发现在 macOS 上使用 CGO 进行跨平台编译需要 musl-cross 的支持,最终有了如下解决方案:
解决方案
在 macOS 上安装 musl-cross 可以通过以下命令完成(会有点慢,耐心等待即可):
brew install FiloSottile/musl-cross/musl-cross安装完成后,修改编译命令
CGO_ENABLED=1 GOOS=linux GOARCH=amd64 CC=x86_64-linux-musl-gcc CXX=x86_64-linux-musl-g++ go build -o my-app成功了!编译过程没有问题。
部署方案
当试在 Linux 服务器上运行生成的二进制文件时,又遇到了另一个错误:
: No such file or directory回过头来再看,发现 Linux 服务器也需要 musl 的支持。对于基于 Debian 的系统,这可以通过以下方式实现:
apt-get install -y musl对于基于 Red Hat 的系统:
wget https://copr.fedorainfracloud.org/coprs/ngompa/musl-libc/repo/epel-7/ngompa-musl-libc-epel-7.repo -O /etc/yum.repos.d/ngompa-musl-libc-epel-7.repo
yum install -y musl-libc-static最终,程序终于可以正常跑起来了。
结论
带有依赖 CGO 的库(如 libpq)的 Go 应用的跨平台编译可能会出现一些问题,特别是在 macOS 和 Linux 之间切换时。然而通过使用 musl-cross 并在目标 Linux 服务器上安装好必要的库,就可以成功地构建并运行应用了。