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]
...
经过一番搜索,发现在 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 服务器上安装好必要的库,就可以成功地构建并运行应用了。