gpt4 book ai didi

c - 编译没有GCO的go库以在 Alpine 上运行,libczmq中出错

转载 作者:行者123 更新时间:2023-12-01 20:21:52 27 4
gpt4 key购买 nike

尝试在alpine上运行二进制文件时,出现错误:

... binary not found

通常在架构出现问题时发生,或者我发现 glibc发生。我搜索发现 alpine改用了 muslc替代的 C库。然后,我找到了这个 Installed Go binary not found in path on Alpine Linux Docker,它教如何不用 CGO 进行编译,这是允许从go加载 C库的东西:
GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -o [name of binary]

运行此命令时,我得到:
go build gopkg.in/zeromq/goczmq.v4: no buildable Go source files in /home/lucas/Go/src/gopkg.in/zeromq/goczmq.v4

我怀疑这是因为 libczmq只是 C编写的 libzmq的包装。在这种情况下,如何使用 libczmq进行编译?为什么在 Alpine 中必须完全禁用 CGO
CGO到底是什么?如果可用,它不应该使用 libc吗?我想了解更多有关背景情况的信息。

注意:我正在ubuntu以外的alpine进行编译,这是一个问题吗?

最佳答案

我知道这个问题现在已经有3年了,但是Internet上对此一无所知,我正面临着同样的问题,大约花了两天时间我才终于找到一个合适的解决方案。

简而言之,我有一个Go项目,它使用goczmq编译为完整的二进制文件以将其放入FROM scratch Docker容器中(尽管在这种情况下, Alpine 容器也可以正常工作)。在Internet上,人们现在倾向于告诉您设置CGO_ENABLED=0,并且一切都会正常进行,这是事实。这告诉Go不要使用CGO,它允许您在Go代码中使用C库,但是在运行代码时需要这些C库在系统上可用。如您所知,alpine没有这些C库(或者,它在muslc而不是glibc中具有不同的C库)。

但是,对于我们而言,这没有帮助。我们希望我们的Go代码能够使用现有的C库,因为我们使用了goczmq,正如您已经确定的那样,它是czmq的Go包装器,而它本身是libzmq的C包装器(用C++编写,这使我们的生活更美好更难)。

我通过使用静态二进制文件解决了这个问题。我没有动态链接到目标系统上可用的任何C库(在本例中为Alpine上的muslc),而是将我的代码和所有库(muslcczmqlibzmq)编译为一个统一的二进制文件。

我在这里使用基于alpine的Docker multi-stage builds,但从理论上讲,您也可以直接在计算机上执行此操作。

# stage 1: build the binary
# we are using alpine Linux with the latest version of golang
FROM golang:1.13-alpine as golang

# first install some dependencies
# (we are using the static versions for each for them as we want these libraries included statically, not dynamically!)
# czmq requires libzmq which in turn requires libsodium
# on alpine Linux we also need to install some specific tools to build C and C++ programs
# libsodium also requires libuuid, which is included in util-linux-dev
RUN apk add --no-cache libzmq-static czmq-dev libsodium-static build-base util-linux-dev

# now we do the magic command mentioned here
# https://stackoverflow.com/questions/34729748/installed-go-binary-not-found-in-path-on-alpine-linux-docker?noredirect=1&lq=1
# this fools the C compiler into thinking we have glibc installed while we are actually using musl
# since we are compiling statically, it makes sense to use musl as it is smaller
# (and it uses the more permissive MIT license if you want to distribute your binary in some form, but check your other libraries before!)
RUN mkdir /lib64 && ln -s /lib/libc.musl-x86_64.so.1 /lib64/ld-linux-x86-64.so.2

# create your project directory for the Go project
WORKDIR /go/src/github.com/<username>/<projectname>/

# copy in all your Go files, assuming these are in the same directory as your Dockerfile
COPY . .

# here is the first hack: we need to tell CGO to use g++ instead of gcc or else it will struggle with libzmq, which is written in C++
# creating and empty C++ file actually works for this
RUN touch ./dummy.cc

# now run go install (go build could also work here but your binary would end up in a different directory)
# the -ldflags will be passed along the CGO toolchain
# -extldflags is especially important here, it has two important flags that we need:
# -static tells the compiler to use static linking, which does the actual magic of putting everything into one binary
# -luuid is needed to correctly find the uuid library that czmq uses
RUN go install -a -ldflags '-linkmode external -w -s -extldflags "-static -luuid" ' .

# stage 2: here is your actual image that will later run on your Docker host
# you can also use alpine here if you so choose
FROM scratch

# now we just copy over the completed binary from the old builder image
COPY --from=golang /go/bin/<projectname> bin

# and we start our program
ENTRYPOINT ["./bin"]


现在,这几乎可行!剩下的唯一事情就是将此语句添加到 main.go文件的开头,否则CGO会对您的操作感到困惑:
import "C"

即使您不直接在程序中使用CGO,这也很重要。

关于c - 编译没有GCO的go库以在 Alpine 上运行,libczmq中出错,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42500973/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com