使用Golang创建共享同一库的Debian软件包

使用Golang创建共享同一库的Debian软件包 我正在尝试创建一个包含3个共享相同Go库的可执行文件的Debian包。我的目录包含以下文件:

  • rtd_dsp.go 一个在命令行显示流式测量的可执行文件
  • rtd_web.go 一个通过Web服务器显示最近一次测量的可执行文件
  • rtd_influxdb.go 一个将流式测量存储到数据库的可执行文件
  • dmn.go 包含用于多个测量流的监听器的库代码

可以按如下方式轻松创建可执行文件:

  • go build rtd_dsp.go dmn.go
  • go build rtd_web.go dmn.go
  • go build rtd_influxdb.go dmn.go

我找到了用于创建Debian包的debian包 dh-golang,并尝试使其正常工作。然而,这似乎不像宣传的那么简单。在创建了包含所需changelog、control、copyright和rules、source/target文件的debian文件夹,并在Ubuntu 20.04.2(使用golang-1.16)上使用dh-golang 1.48运行 dpkg-buildpackage -us -uc -d 之后,它抱怨了几件事:

  • 它找不到外部包,而这些包在 $(GOMODCACHE)=$(HOME)/go/pkg/mod 中是可用的。在我看来,它要么可以自己获取它们,要么重用现有的包。作为实验,我修改了golang.pm,将GOPATH设置为$(GOMODCACHE)。
  • 它找不到任何Go文件,而这些文件就在创建的 _build/src/sst-goflow 目录中。
  • 我预计会出现一个错误,指出每个可执行的go文件都实现了相同的handleMessage调用(正如简单的 go install 所指示的那样),而我却希望它能创建单独的可执行文件。

是否有更简单的方法来创建包含Go可执行文件的Debian包?并且/或者上述问题是否容易解决?

此致, Dennis


更多关于使用Golang创建共享同一库的Debian软件包的实战教程也可以访问 https://www.itying.com/category-94-b0.html

6 回复

你好Christoph,

感谢你的回复,我会看看goreleaser / NFPM,希望它不会比我目前的解决方案过于复杂;-)

我在嵌入式目标上使用debian/install时遇到了一些问题,但目前可以通过不从二进制文件中剥离调试符号来缓解。我提交了一个debian dpkg-dev的工单,希望能彻底解决这个问题。

此致, Dennis

更多关于使用Golang创建共享同一库的Debian软件包的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


我成功找到了一个更简单的解决方案,使用 debian/install 文件和一个带有构建目标的常规 GNU Makefile 来创建可执行文件。install 文件用于将可执行文件复制到 debian 包中的 usr/bin。所以,除非有人能说服我改变主意,否则我不再使用 dh-golang 了;-)

祝好, Dennis

呵呵,是的,使用 goreleaser 可能有点杀鸡用牛刀。基础部分很简单(我在这里写过相关内容),但要让后端(NFPM、Fury.io 等)启动并运行起来,看起来就有点复杂了。我认为 goreleaser 真正大放异彩的地方是在 CI/CD 流水线中。

可能是因为 Go 源码文件名中的下划线具有特殊含义:下划线后的单词必须是构建标签名称。例如,名为 myfile_windows.go 的文件仅在 GOOS=windows 时才会被构建。myfile_linux_386.go 仅在 GOOS=linux 且 GOARCH=386 时才会被构建,依此类推。或许可以尝试从 Go 源码文件名中移除下划线,看看行为是否发生变化。

我完全不了解 gh-golang,因此无法对其发表任何评论,但如果常规的 Debian 构建安装包的方式可行,那么我就不会再寻找其他方法了。

Go 二进制文件的静态特性(即没有共享库依赖)使得打包和部署 Go 二进制文件变得特别容易,无需专门的工具。

话虽如此,总有一些便利的选项可用,例如 goreleaser。(特别是配合 NFPM 选项。)

针对你使用dh-golang创建包含多个共享库的可执行文件的Debian包时遇到的问题,以下是具体的解决方案和示例代码:

首先,确保你的项目结构符合Go模块规范。在项目根目录初始化模块:

go mod init github.com/yourname/rtd

创建标准的Debian包结构,debian/control文件示例:

Source: rtd
Section: utils
Priority: optional
Maintainer: Dennis <dennis@example.com>
Build-Depends: debhelper-compat (= 13), dh-golang, golang-1.16
Standards-Version: 4.5.1
Homepage: https://github.com/yourname/rtd

Package: rtd-dsp
Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends}
Description: Display streaming measurements
 Command-line tool for displaying streaming measurements.

Package: rtd-web
Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends}
Description: Web interface for measurements
 Web server displaying recent measurements.

Package: rtd-influxdb
Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends}
Description: Store measurements to InfluxDB
 Stores streaming measurements to InfluxDB database.

debian/rules文件配置:

#!/usr/bin/make -f

%:
	dh $@ --with=golang

override_dh_auto_build:
	# 构建所有可执行文件
	GOBIN=$(CURDIR)/debian/rtd-dsp/usr/bin go install ./cmd/rtd_dsp
	GOBIN=$(CURDIR)/debian/rtd-web/usr/bin go install ./cmd/rtd_web
	GOBIN=$(CURDIR)/debian/rtd-influxdb/usr/bin go install ./cmd/rtd_influxdb

override_dh_auto_install:
	# 安装可执行文件到对应包目录
	install -d debian/rtd-dsp/usr/bin
	install -d debian/rtd-web/usr/bin
	install -d debian/rtd-influxdb/usr/bin
	install -m 0755 $(CURDIR)/debian/rtd-dsp/usr/bin/rtd_dsp debian/rtd-dsp/usr/bin/
	install -m 0755 $(CURDIR)/debian/rtd-web/usr/bin/rtd_web debian/rtd-web/usr/bin/
	install -m 0755 $(CURDIR)/debian/rtd-influxdb/usr/bin/rtd_influxdb debian/rtd-influxdb/usr/bin/

调整项目目录结构,将可执行文件移到cmd目录:

project/
├── cmd/
│   ├── rtd_dsp/
│   │   └── main.go
│   ├── rtd_web/
│   │   └── main.go
│   └── rtd_influxdb/
│       └── main.go
├── internal/
│   └── dmn/
│       └── dmn.go
├── go.mod
└── go.sum

每个main.go文件导入共享库:

package main

import (
    "github.com/yourname/rtd/internal/dmn"
)

func main() {
    dmn.HandleMessage()
}

共享库dmn.go示例:

package dmn

import "fmt"

func HandleMessage() {
    fmt.Println("Handling measurement")
}

构建命令:

# 设置Go模块代理
export GOPROXY=https://proxy.golang.org,direct

# 清理并构建
dpkg-buildpackage -us -uc -d -i -I

对于外部依赖问题,在debian/rules中添加:

override_dh_auto_configure:
	# 确保使用系统Go模块缓存
	export GOMODCACHE=/usr/share/gocode/pkg/mod; \
	export GOPROXY=https://proxy.golang.org,direct; \
	dh_auto_configure

如果遇到符号冲突,在debian/rules中添加:

override_dh_strip:
	# 为每个包单独构建以避免符号冲突
	dh_strip --dbg-package=rtd-dsp-dbg
	dh_strip --dbg-package=rtd-web-dbg
	dh_strip --dbg-package=rtd-influxdb-dbg

使用gbp buildpackage替代dpkg-buildpackage

gbp buildpackage --git-ignore-new --git-ignore-branch -us -uc

创建debian/source/format文件:

3.0 (quilt)

运行完整构建流程:

# 更新依赖
go mod tidy
go mod vendor

# 构建包
dpkg-buildpackage -rfakeroot -us -uc -d -i -I

这样配置后,dh-golang会正确识别Go模块结构,分别构建三个可执行文件,并打包到对应的Debian包中。共享的dmn库会被自动编译并链接到每个可执行文件中。

回到顶部