Go 語言軟件打包準則

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

32 位CLRCMakeCrossDKMSEclipseElectronFontFree PascalGNOMEGoHaskellJavaKDEKernelLispMesonMinGWNode.jsNonfreeOCamlPerlPHPPythonRRubyRustVCSWebWine

Arch Linux 對 Go 的支持非常完善。

軟件包 go 中包含了 go 工具 (用於運行 go fix, go build 等)。 另外還有個提供 gccgogcc-go 軟件包。

通用準則[編輯 | 編輯原始碼]

命名[編輯 | 編輯原始碼]

  • 對於使用 Go 語言編寫的軟件庫,請使用小寫字母的 go-庫名 作為軟件包名。
    • 如果軟件庫名本身就是以 go- 開頭的,請不要使用 go-go-模塊名 這樣的名字,而改用 go-模塊名
  • 對於使用"go"工具下載的軟件包,只有當它不是從tar包或者tagged提交(而是從trunk/HEAD)下載源碼時,軟件包名才添加"-git"後綴。
    • 類似的,對於mercurial 版本控制系統,只有當軟件包未從release-revision下載源碼時,才添加"-hg"後綴。
    • 其他版本控制系統,請一併參考該準則。
    • "go"工具下載那個分支或者Tag通常有他自己的一套邏輯。請參考 go get --help.
  • 如果有多個同名的軟件包,可考慮將作者的名字添加到軟件包名之中,例如:dcpu16-kballardAUR[損壞的連結:package not found]
    • 當然,通常情況下,最流行的軟件包會使用最短或者"最佳"的軟件包名。
  • 如果軟件開發者本身並沒有正式的官方發佈,那麼這種後綴名 (例如 -hg, -git-svn) 只是可選的。 一方面,這種軟件包通常都是直接通過源碼版本庫下載使用的。另一方面, 大多數 Go 語言項目從不發佈任何tarball,而只發佈源碼版本庫。並將版本庫的master分支、HEAD提交以外的分支、Tag作為官方發佈的方式。另一方面,Go語言官方的模塊安裝方式 go get 也往往直接使用源碼版本庫。所以請根據情況作出最佳選擇。

打包[編輯 | 編輯原始碼]

  • Go 語言項目通常只包含軟件庫、可執行文件或者兩者俱有。請以合適的方式打包他們。後續有幾個例子以供參考。
  • 有些 Go 語言項目並不支持最新版本的Go編譯。這種情況下
    • 直接執行 go build -fix 一般就可以搞定了。如果仍有問題,請上報給上游開發者,並且他們修復。
  • 有些Go語言項目並沒有版本號或者授權協議文件。這種情況下:
    • 使用 license=('unknown') 並向上游開發者提交授權協議缺失的報告。
    • 如果沒有版本號,請使用 "0.1", "1" 或者Git庫的revision ( 其他版本控制系統類似)。
    • 作為備選,可以用當前日期作為版本號,格式形如 YYYYMMDD

PKGBUILD 範例[編輯 | 編輯原始碼]

Go 語言開發的獨立程序 PKGBUILD[編輯 | 編輯原始碼]

# Maintainer: NAME <EMAIL>

pkgname=PACKAGE NAME
pkgver=1.2.3
pkgrel=1
pkgdesc="PACKAGE DESCRIPTION"
arch=('x86_64' 'i686')
url="http://SERVER/$pkgname/"
license=('MIT')
makedepends=('go')
options=('!strip' '!emptydirs')
source=("http://SERVER/$pkgname/$pkgname-$pkgver.tar.gz")
sha256sums=('00112233445566778899aabbccddeeff')

build() {
  cd "$pkgname-$pkgver"

  go build
}

package() {
  cd "$pkgname-$pkgver"

  install -Dm755 "$pkgname-$pkgver" "$pkgdir/usr/bin/$pkgname"
  install -Dm644 LICENSE "$pkgdir/usr/share/licenses/$pkgname/LICENSE"
}

# vim:set ts=2 sw=2 et:

參考示例包[編輯 | 編輯原始碼]

僅包含單個Go文件的程序 PKGBUILD[編輯 | 編輯原始碼]

# Maintainer: NAME <EMAIL>

pkgname=PACKAGE NAME
pkgver=1.2.3
pkgrel=1
pkgdesc="PACKAGE DESCRIPTION"
arch=('x86_64' 'i686')
url="http://SERVER/$pkgname/"
license=('GPL3')
makedepends=('go')
options=('!strip' '!emptydirs')
source=("http://SERVER/$pkgname/$pkgname.go")
sha256sums=('00112233445566778899aabbccddeeff')

build() {
  go build -o "$pkgname"
}

package() {
  install -Dm755 "$pkgname" "$pkgdir/usr/bin/$pkgname"
}

# vim:set ts=2 sw=2 et:

參考示例包[編輯 | 編輯原始碼]

包含可執行文件的Go語言庫 PKGBUILD[編輯 | 編輯原始碼]

使用 go get[編輯 | 編輯原始碼]

這是推薦的使用"go get"的方式,請優先選用這種方式,後文介紹的那種僅供參考。

這種方式將依賴於"go get"。

通常情況下你無需修改 build() 或 package() 函數,只需要修改前面定義的變量 (pkgname 等)即可。

如果打包失敗,請先確保手動執行"go get"能成功。

提示: 如果打包失敗,嘗試去掉 /...再試試!
# Maintainer: NAME <EMAIL>

pkgname=codesearch
pkgver=20120515
pkgrel=1
pkgdesc="Code indexing and search written in Go"
arch=('x86_64' 'i686')
url="https://github.com/google/codesearch"
license=('BSD')
depends=('go')
makedepends=('mercurial')
options=('!strip' '!emptydirs')
_gourl=github.com/google/codesearch

build() {
  GOPATH="$srcdir" go get -fix -v -x ${_gourl}/...
}

check() {
  GOPATH="$GOPATH:$srcdir" go test -v -x ${_gourl}/...
}

package() {
  mkdir -p "$pkgdir/usr/bin"
  install -p -m755 "$srcdir/bin/"* "$pkgdir/usr/bin"

  mkdir -p "$pkgdir/$GOPATH"
  cp -Rv --preserve=timestamps "$srcdir/"{src,pkg} "$pkgdir/$GOPATH"

  # Package license (if available)
  for f in LICENSE COPYING LICENSE.* COPYING.*; do
    if [ -e "$srcdir/src/$_gourl/$f" ]; then
      install -Dm644 "$srcdir/src/$_gourl/$f" \
        "$pkgdir/usr/share/licenses/$pkgname/$f"
    fi
  done
}

# vim:set ts=2 sw=2 et:

感謝 Rémy Oudompheng‎ 提供該範例。

使用 go get[編輯 | 編輯原始碼]

另外一種依靠 go get的方式如下。

一般不需要修改 build() 或 package() 函數,只需要修改前面的變量 (pkgname 等)即可。

如果打包有問題,請先確保手動執行 go get 沒問題。

# Maintainer: NAME <EMAIL>

pkgname=PACKAGE NAME
pkgver=1.2.3
pkgrel=1
pkgdesc="PACKAGE DESCRIPTION"
arch=('x86_64' 'i686')
url="http://SERVER/$pkgname/"
license=('MIT')
makedepends=('go' 'git')
options=('!strip' '!emptydirs')
_gourl=SERVER.NET/PATH/MODULENAME

build() {
  export GOROOT=/usr/lib/go

  rm -rf build
  mkdir -p build/go
  cd build/go

  for f in "$GOROOT/"*; do
    ln -s "$f"
  done

  rm pkg
  mkdir pkg
  cd pkg

  for f in "$GOROOT/pkg/"*; do
    ln -s "$f"
  done

  platform=`for f in "$GOROOT/pkg/"*; do echo \`basename $f\`; done|grep linux`

  rm -f "$platform"
  mkdir "$platform"
  cd "$platform"

  for f in "$GOROOT/pkg/$platform/"*.h; do
    ln -s "$f"
  done

  export GOROOT="$srcdir/build/go"
  export GOPATH="$srcdir/build"

  go get -fix "$_gourl"

  # Prepare executable
  if [ -d "$srcdir/build/src" ]; then
    cd "$srcdir/build/src/$_gourl"
    go build -o "$srcdir/build/$pkgname"
  else
    echo 'Old sources for a previous version of this package are already present!'
    echo 'Build in a chroot or uninstall the previous version.'
    return 1
  fi
}

package() {
  export GOROOT="$GOPATH"

  # Package go package files
  for f in "$srcdir/build/go/pkg/"* "$srcdir/build/pkg/"*; do
    # If it's a directory
    if [ -d "$f" ]; then
      cd "$f"
      mkdir -p "$pkgdir/$GOROOT/pkg/`basename $f`"
      for z in *; do
        # Check if the directory name matches
        if [ "$z" == `echo $_gourl | cut -d/ -f1` ]; then
          cp -r $z "$pkgdir/$GOROOT/pkg/`basename $f`"
        fi
      done
      cd ..
    fi
  done

  # Package source files
  if [ -d "$srcdir/build/src" ]; then
    mkdir -p "$pkgdir/$GOROOT/src/pkg"
    cp -r "$srcdir/build/src/"* "$pkgdir/$GOROOT/src/pkg/"
    find "$pkgdir" -depth -type d -name .git -exec rm -r {} \;
  fi

  # Package license (if available)
  for f in LICENSE COPYING; do
    if [ -e "$srcdir/build/src/$_gourl/$f" ]; then
      install -Dm644 "$srcdir/build/src/$_gourl/$f" \
        "$pkgdir/usr/share/licenses/$pkgname/$f"
    fi
  done

  # Package executables
  if [ -e "$srcdir/build/$pkgname" ]; then
    install -Dm755 "$srcdir/build/$pkgname" \
      "$pkgdir/usr/bin/$pkgname"
  fi
}

# vim:set ts=2 sw=2 et: