MacOS上进行Go应用编译至Linux

MacOS上进行Go应用编译至Linux

彼方 12 2024-10-10

引言

如果您在 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 服务器上安装了必要的库,可以成功地构建并运行您的应用。