pkgsrcでGo言語で書かれたソフトウェアをパッケージにする方法

この記事は、NetBSD Advent Calendar 2018の7日目の記事です。

はじめに

pkgsrcのパッケージは、オフラインでビルドできることが求められています。 ですので、ビルドの準備段階や最中に依存するソースコードをダウンロードするのは 避けなくてはいけません。

今日はGo言語で書かれたソフトウエアであるHugo と言うスタティックサイトジェネレーターを例にして、Go言語で書かれたソフトウエアの場合の buildlinkの仕組みを体験してみたいと思います。

依存するソフトウエアの準備方法

pkgsrcでは、configureステージ(典型的には GNU autoconfのconfigureスクリプトを実行する段階で、ビルドの1つ前の段階)の前に WRKSRC(デフォルトではそのパッケージのディレクトリー内にwork ディレクトリー)以下に、依存するパッケージのヘッダーファイルやライブラリファイルを用意して おきます。 このような処理をする場合には、例えば以下のように パッケージのMakefileから buildlink3.mkファイルをインクルードしておきます。

(snip)
.include "../../devel/go-locker/buildlink3.mk"
.include "../../www/go-toml-burntsushi/buildlink3.mk"
.include "../../www/go-urlesc/buildlink3.mk"
.include "../../devel/go-purell/buildlink3.mk"
.include "../../textproc/go-chroma/buildlink3.mk"
(snip)

ヘッダーファイルやライブラリーファイルをWRKSRC以下に配置すると 書きましたが、Go言語の場合には、ちょっと事情が異なり、ソースコードとスタティックライブラリーが 配置されます)。 実際に依存先のソースコードとスタティックライブラリーが格納されるのは、 work/.buildlink/gopkgディレクトリー以下です。 pkgsrc/www/hugoの場合の中身を少し確認してみます。
$ find work/.buildlink/gopkg
(snip)
work/.buildlink/gopkg/src/github.com/disintegration/imaging/utils.go
work/.buildlink/gopkg/src/github.com/disintegration/imaging/utils_test.go
work/.buildlink/gopkg/src/github.com/dlclark
work/.buildlink/gopkg/src/github.com/dlclark/regexp2
work/.buildlink/gopkg/src/github.com/dlclark/regexp2/ATTRIB
work/.buildlink/gopkg/src/github.com/dlclark/regexp2/LICENSE
work/.buildlink/gopkg/src/github.com/dlclark/regexp2/README.md
work/.buildlink/gopkg/src/github.com/dlclark/regexp2/match.go
work/.buildlink/gopkg/src/github.com/dlclark/regexp2/regexp.go
(snip)
以上のように/usr/pkg/gopkgの以下の必要なパッケージの分だけが配置 されています。

パッケージング手順

Hugoの場合には、依存するソフトウエアの情報がREADME.mdに記載されています。 最初のステップは、そこに記載されているソフトウエアがpkgsrcに 収録されているかどうかを確認することから始めます。 Go言語で書かれたソフトウエアは、GitHubやgolang.org、gopkg.inといった ウェブサイトでホスティングされている例が多く、URIがソフトウエアを識別する 名前空間になっているようです。それは、MakefileGO_SRCPATHに指定されていますので、pkgsrcの ツリー内を検索すれば、目的のソフトウエアが既にpkgsrcに 収録されているか分かると思います。

通常、pkgsrcのパッケージを作る際には、 pkgsrc/pkgtools/url2pkgパッケージで提供される url2pkgコマンドを使うの便利ですが、Go言語で書かれたソフトウエアの 場合には、利用してもあまり利点はありません。 既存のGo言語で書かれたソフトウエアのパッケージのディレクトリーをコピーして それを元に作成するのが良いと思います。

ここでは、pkgsrc/www/go-aceパッケージのMakefilelbuildlink3.mkを例に注意点を説明してみます。

# $NetBSD: Makefile,v 1.6 2018/11/04 18:38:08 bsiegert Exp $ # CVSタグは変更は不要です。適切に書き変わります、

DISTNAME= ace-0.0.4b # ウェブブラウザーでダウンロードしてみてファイル名を確認して、それを使用します。
PKGNAME= go-${DISTNAME} # パッケージの名前です。通常はこのままで良いです。
PKGREVISION= 4 # 初回作成時には、PKGREVISIONは含めません。
MASTER_SITES= ${MASTER_SITE_GITHUB:=yosssi/} # GitHubでホスティングされている場合には、MASTER_SITE_GITHUBを使います。ここでは、https://github.com/yosssi/ と展開されます。
CATEGORIES= www # カテゴリーを選択して設定します。
GITHUB_TAG= 71afeb714739f9d5f7e1849bcd4a0a5938e1a70d # リリースもされておらず、タグも打たれていない場合にはハッシュ値を設定します。
GITHUB_PROJECT= ${PKGBASE:S/^go-//} # GitHubのプロジェクト名です。通常はこのままで良いです。

MAINTAINER= pkgsrc-users@NetBSD.org # 自分の電子メールアドレスを設定します。
HOMEPAGE= https://github.com/yosssi/ace # プロジェクトのウェブサイトを設定します。
COMMENT= HTML template engine for Go # パッケージの説明を1行で書きます。
LICENSE= mit # pkgsrc/licenses以下のファイル名でライセンスを指定します。

GO_DIST_BASE= ${GITHUB_PROJECT}-${GITHUB_TAG} # 通常はこのまま良いです。
GO_SRCPATH= github.com/yosssi/ace # GitHubのURIから作成します。

# Avoid a circular dependency on ace-proxy
# 以下の部分は、www/go-ace特有の処理なので、通常は必要ありません。
post-patch:
 ${RUN} ${RM} -rf ${WRKSRC}/examples/cache_options

.include "../../www/go-gohtml/buildlink3.mk" # go-aceの依存するパッケージを指定します。
.include "../../lang/go/go-package.mk" # GO言語で書かれたパッケージ用の定型句です。
.include "../../mk/bsd.pkg.mk" # pkgsrcのパッケージ用の定型句です。
実際には、pkgsrc/pkgtools/pkglintを使って、以下のようにチェックし、 「Looks fine.」となるようにします。
$ cd /usr/pkgsrc/www/go-ace
$ pkglint -Wall -Call

ビルドしてみる

Hugoの場合には、README.mdに依存するパッケージが書かれていましたが、 書かれているパッケージが依存するパッケージまでは書かれていません。 また、こんなに丁寧なではないこともあります。 Go言語のパッケージの場合には、実際にビルドしてみれば簡単に不足するパッケージが 分かります。

ここでは、pkgsrc/www/hugoから

.include "../../devel/go-locker/buildlink3.mk"
の行を削除して、ビルドしてみます。 以下のようにビルドに失敗しました。
===> Building for go-hugo-0.52
/usr/tmp/pkgsrc/www/hugo/work/src/github.com/gohugoio/hugo/cache/filecache/filecache.go:30:2: cannot find package "github.com/BurntSushi/locker" in any of:
        /usr/pkg/go111/src/github.com/BurntSushi/locker (from $GOROOT)
        /usr/tmp/pkgsrc/www/hugo/work/src/github.com/BurntSushi/locker (from $GOPATH)
        /usr/tmp/pkgsrc/www/hugo/work/.buildlink/gopkg/src/github.com/BurntSushi/locker
*** Error code 1

Stop.
make[1]: stopped in /usr/pkgsrc/www/hugo
*** Error code 1

Stop.
make: stopped in /usr/pkgsrc/www/hugo
https://github.com/BurntSushi/lockerがないことが分かりました。 これが既にpkgsrc内にあればbuildlinkすれば良いですし、 なければpkgsrc/www/go-aceの例のようにパッケージを 作成した上でbuildlinkします。 パッケージの依存関係は数珠つなぎになっていますから、 パッケージを作る作業は再帰的に続いてなかなか終わらない場合もあります。 ですが、依存しなくなったパッケージを依存関係から削除するのよりはずっと簡単です。

Go言語のパッケージは、まだまだ充実しているとは言えないと思いますので、 面白いソフトウエアがあれば教えてもらえればと思います。

明日は、pkgsrcでのクロスコンパイルの方法について書こうと思います。

Comments

Popular posts from this blog

#5000へCメールを送れないau端末でezweb.ne.jpの電子メールアドレスをIMAP4/SMTPで扱う方法

PostgreSQLのOracle Foreign Data WrapperをWindowsで使う

Vaio Pro 11/13用のサードパーティーのACアダプター