Go 語言軟體打包準則 - Arch Linux 中文维基

跳至內容

# Go 語言軟體打包準則

出自 Arch Linux 中文维基
Arch 打包準則

32 位 – 安全 – CLR – CMake – DKMS – Eclipse – Electron – Free Pascal – GNOME – Go – Haskell – Java – 交叉編譯工具 – KDE – Lisp – Meson – MinGW – 內核模塊 – Node.js – Nonfree – OCaml – Perl – PHP – Python – R – Ruby – Rust – Shell – VCS – Web – Wine – 字體

翻譯狀態：

- 本文（或部分內容）譯自 Go package guidelines，最近一次同步於 2026-02-16，若英文版本有所更改，則您可以幫助同步與翻譯更改的內容。
- 您可以在 ArchWiki 的對應頁面找到本文翻譯的原始修訂歷史。
- 本文可能與英文原文存在出入。

本文涵蓋了為 Go 軟體包編寫 PKGBUILD 時須遵循的標準和指引。

## 通用準則

### 命名

如果軟體包提供的程序與 Go 生態存在強關聯，請使用 `go-模塊名稱`。對於其它應用，請僅使用程序名。

注意：軟體包名稱只允許使用小寫字符。

## 構建

### 依賴

Go 1.11 為 go 模塊提供了初步支持，使得上游的 Go 代碼可以聲明依賴並將其固定到特定項目版本。Currently our packaging efforts utilize this to vendor dependencies.

#### 上游項目不使用 go 模塊

對於不使用 Go 模塊的上游代碼，可以使用以下變通方法，並請考慮向上游提出 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 模塊

go 默認會使用 `GOPATH` 來下載和存放 go 模塊，並導致用戶的 `~/go` 目錄大小增加。

為將所有 go 模塊保留在構建環境中，可以在準備步驟（prepare）中配置 `GOPATH="${srcdir}"`，然後將 go 模塊下載到軟體包源碼目錄（srcdir）中：

    PKGBUILD

    prepare() {
      cd "${pkgname}-${pkgver}"
      export GOPATH="${srcdir}"
      go mod download -modcacherw
    }

### 構建標誌和選項

Go 不會自動將系統的構建標誌（例如 `CFLAGS` 和 `LDFLAGS`）傳遞給 C 工具鏈。為使用 RELRO 和其它加固標誌構建 Go 二進制文件，需要在構建環境中顯式指定 `CGO_CFLAGS` 和 `CGO_LDFLAGS` 等相關變量：

    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 \
        -trimpath \
        -buildmode=pie \
        -mod=readonly \
        -modcacherw \
        -ldflags "-linkmode external -extldflags \"${LDFLAGS}\"" \
        .

注意：大多數用於 Go 應用的 Makefile 會覆蓋掉 `GOFLAGS`，不會將上述標誌傳遞給編譯器。如果上游項目使用了 Makefile，則需要通過補丁使其遵循傳入的標誌，或是直接調用 `go build` 來繞過該文件。

#### 標誌功能

- `-buildmode=pie` 會啟用 PIE 編譯，用於加固二進制文件。
- `-trimpath` 用於可復現構建，可以防止嵌入完整構建路徑和模塊路徑。
- `-mod=readonly` 可以保證模塊文件不會在 go 的任何操作中被更改。
- `-modcacherw` is not important, but it ensures that go modules creates a write-able path. Default is read-only.

提示：如果軟體的 `modules.txt` 中包含了一個 `vendor` 目錄，那可以將 `-mod` 標誌修改為 `-mod=vendor`。
警告：包維護者需要確保構建標誌被正確傳遞給了編譯器，請務必檢查源碼的 `Makefile`。

#### 支持調試包

Enabling debug packages with source listing and proper symbol look ups require a few modifications to the default buildflags.

- Removal of `-trimpath` to ensure source paths are rewritten in the binary
- Include `-compressdwarf=false` in `-ldflags` to ensure we can parse the DWARF headers as current tooling does not support compressed headers.
- Ensure `-linkmode=external` as the internal linker go uses does not embed a build-id into the binary.
- Include `GOPATH="${srcdir}"` so makepkg can include the source code for all modules.

The above options should produce a debug package with proper detached symbols and source listings which can then be picked up by the debugger.

    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
    }

## 軟體包示例

- podman包
- k9s包
- helm包

分類：​

- Arch 打包準則

Go 語言軟體打包準則
新增話題