Go 软件包指南
32 位 – CLR – CMake – Cross – DKMS – Eclipse – Electron – Font – Free Pascal – GNOME – Go – Haskell – Java – KDE – 内核模块 – Lisp – Meson – MinGW – Node.js – Nonfree – OCaml – Perl – PHP – Python – R – Ruby – Rust - Security – Shell – VCS – Web – Wine
本文档涵盖了关于为 Go 编写 PKGBUILD 的标准和指南。
通用指南
软件包命名
如果软件包提供的程序与 Go 生态系统紧密耦合,请使用 go-模块名
。对于其他应用程序,仅使用程序名称。
构建
依赖
Go 1.11 引入了对 go modules 的初始支持。这允许 Go 上游代码声明依赖项并将其固定到给定的项目版本。目前,我们的打包工作利用此功能来 vendor 依赖项。
不使用 go modules 的上游项目
对于不使用 Go modules 的上游代码,存在以下解决方法。考虑向上游提交 issue。
PKGBUILD
url=https://github.com/upstream_user/upstream_project prepare() { cd "$pkgname-$pkgver" go mod init "${url#https://}" # strip https:// from canonical URL go mod tidy }
标志和构建选项
大多数为 go 应用程序编写的 Makefile 不遵守构建系统提供的构建标志,并且会覆盖 GOFLAGS
,这导致 Go 二进制文件在编译时没有启用 RELRO,因为我们需要为编译器设置 CGO_CFLAGS
和 CGO_LDFLAGS
。这需要修补到 Makefile 中,或者应该省略 Makefile。
export CGO_CPPFLAGS="${CPPFLAGS}" export CGO_CFLAGS="${CFLAGS}" export CGO_CXXFLAGS="${CXXFLAGS}" export CGO_LDFLAGS="${LDFLAGS}" export GOFLAGS="-buildmode=pie -trimpath -ldflags=-linkmode=external -mod=readonly -modcacherw" # or alternatively you can define some of these flags from the CLI options go build \ -trimpath \ -buildmode=pie \ -mod=readonly \ -modcacherw \ -ldflags "-linkmode external -extldflags \"${LDFLAGS}\"" \ .
标志含义
-buildmode=pie
启用 PIE 编译 以增强二进制文件的安全性。-trimpath
对于 可重现构建 非常重要,这样就不会嵌入完整的构建路径和模块路径。-mod=readonly
确保模块文件在任何 go 操作中都不会被更新。-modcacherw
不是必需的,但它可以确保 go modules 创建一个可写的路径。默认是只读的。
modules.txt
的 vendor
目录时,-mod
标志可以安全地更改为 -mod=vendor
。Makefile
,请阅读它。支持调试包
启用带有源代码列表和正确符号查找的调试包需要对默认构建标志进行一些修改。
- 移除
-trimpath
以确保源代码路径在二进制文件中被重写 - 在
-ldflags
中包含-compressdwarf=false
以确保我们可以解析 DWARF 标头,因为当前的工具不支持压缩标头。 - 确保
-linkmode=external
,因为 go 使用的内部链接器不会将 build-id 嵌入到二进制文件中。 - 包含
GOPATH="${srcdir}"
,以便 makepkg 可以包含所有模块的源代码。
以上选项应生成一个带有正确分离符号和源代码列表的调试包,然后可以被调试器拾取。
export CGO_CPPFLAGS="${CPPFLAGS}" export CGO_CFLAGS="${CFLAGS}" export CGO_CXXFLAGS="${CXXFLAGS}" export CGO_LDFLAGS="${LDFLAGS}" export GOPATH="${srcdir}" export GOFLAGS="-buildmode=pie -mod=readonly -modcacherw" go build -ldflags "-compressdwarf=false -linkmode external" .
输出目录
目前有几种方法可以在项目中构建所有 go 二进制文件。
build(){ cd "$pkgname-$pkgver" go build -o output-binary . }
...
是编译器递归地进入目录并查找所有二进制文件的简写。它可以与输出目录结合使用来构建所有内容。
prepare(){ cd "$pkgname-$pkgver" mkdir -p build } build(){ cd "$pkgname-$pkgver" go build -o build ./cmd/... }
PKGBUILD 示例
pkgname=foo pkgver=0.0.1 pkgrel=1 pkgdesc='Go PKGBUILD Example' arch=('x86_64') url="https://example.org/$pkgname" license=('GPL') makedepends=('go') source=("$url/$pkgname-$pkgver.tar.gz") sha256sums=('1337deadbeef') prepare(){ cd "$pkgname-$pkgver" mkdir -p build/ } build() { cd "$pkgname-$pkgver" export CGO_CPPFLAGS="${CPPFLAGS}" export CGO_CFLAGS="${CFLAGS}" export CGO_CXXFLAGS="${CXXFLAGS}" export CGO_LDFLAGS="${LDFLAGS}" export GOFLAGS="-buildmode=pie -trimpath -ldflags=-linkmode=external -mod=readonly -modcacherw" go build -o build ./cmd/... } check() { cd "$pkgname-$pkgver" go test ./... } package() { cd "$pkgname-$pkgver" install -Dm755 build/$pkgname "$pkgdir"/usr/bin/$pkgname }