如何分发具有 C 依赖项的 Go 模块

Tgs*_*591 7 go cgo go-modules

我有一个 Go 包(称之为它)foo,我围绕一些现有的 C 代码构建了它,并且我正在尝试确定如何最好地分发它。

一些背景知识...这是我的目录结构的简化版本:

foo/
  |_ include/
      |_ <several other header files>
  |_ libs/
      |_ <several .so files>
  |_ foo.c
  |_ foo.h
  |_ foo.go
Run Code Online (Sandbox Code Playgroud)

一个被剥光的头foo.go

foo/
  |_ include/
      |_ <several other header files>
  |_ libs/
      |_ <several .so files>
  |_ foo.c
  |_ foo.h
  |_ foo.go
Run Code Online (Sandbox Code Playgroud)

_foo.so作为构建过程的一部分生成的动态库在哪里。我能够很好地运行和测试我的代码,但我希望能够分发它并在一个单独的项目(使用go mod. 这就是事情变得有点棘手的地方,而且我对 Go 的理解也变得脆弱。从概念上讲,我只是希望能够将foo/目录(.so文件和所有内容)分发到另一个应用程序可以找到并导入它的位置,但是我遇到了一些障碍:

  • 我无法将其作为二进制包,因为我们使用的是 Go 1.13,并且据我所知,该功能在 1.12 后已被删除。
  • 该文件的构建过程.so非常重要,我不希望其他开发人员花费 30 分钟以上的时间来构建该对象。

我找到了很多 CGO 演示和博客,但没有很多关于如何分发 CGO 包的解释。有任何想法吗?

值得注意的是,这是针对我的公司的,环境是标准的,所以我不必控制不同的操作系统等。

编辑

我忘记提及我尝试过的一件事是将库烘焙到GOPATHDocker 映像中,然后从该基础构建依赖于它的微服务。但是,当使用 构建服务时-mod=vendor,无法在 中找到该库GOPATH

RUN GOOS=linux \
    GOARCH=amd64 \
    CGO_ENABLED=1 \
    GOFLAGS=-mod=vendor \
    GO111MODULE=on \
    go build \
    -o service ./cmd/serve/main.go
Run Code Online (Sandbox Code Playgroud)
./service
# build foo: cannot load foo: open /.../svc/vendor/foo: no such file or directory
Run Code Online (Sandbox Code Playgroud)

Tgs*_*591 4

对于将来可能遇到类似问题的任何人,以下是我为完成这项工作而采取的步骤。

  1. 我将生成的工件烘焙到基础 docker 镜像中,如下所示:
FROM golang:1.13.4

COPY ./foo /go/src/foo/foo
COPY ./foo.mod /go/src/foo
Run Code Online (Sandbox Code Playgroud)

这避免了必须将.so文件提交到源代码管理的问题,而只需将 Docker 映像推送到注册表即可。

  1. 任何需要此库的服务都是从该基础映像构建的:
FROM my-foo-base:latest

COPY ./vendor ./vendor
COPY ./go.mod ./
COPY ./go.sum ./

# Put foo in /vendor so it's discoverable, and put its libs where they
# can be discovered
RUN mv /go/src/foo ./vendor && \
    mv ./vendor/foo/foo/libs/*.so /usr/lib/ && \
    mv ./vendor/foo/foo/include/* /usr/include/

# Copy in app code
COPY ./my-app ./my-app

# Required so the app can find the _foo.so shared object
ENV LD_LIBRARY_PATH="/vendor/foo/foo:/usr/lib:${LD_LIBRARY_PATH}"

# Build into a single binary
RUN GOOS=linux \
    GOARCH=amd64 \
    CGO_ENABLED=1 \
    GOFLAGS=-mod=vendor \
    GO111MODULE=on \
    go build \
    -o service ./cmd/serve/main.go
Run Code Online (Sandbox Code Playgroud)

这有效,并且该服务能够发现 CGO 包。