読者です 読者をやめる 読者になる 読者になる

いけむランド

はてダからやってきました

cygport 再入門

かなり昔に cygport 入門 - BOOLEANLABEL という記事を書いたが、あれから 5 年以上経ち cygport 自体がかなり機能拡張されたということもあり、そろそろ Modern Cygport みたいなチュートリアルを書いておくべきかなと思ったため、加筆 & 修正版を書くことにした。

cygport とは

cygport は cygwin のパッケージを作成するツールで Linux ディストリでいうところの rpm の spec みたいなものである。(作者曰く GentooPortage に inspire されたらしい。)

(Yes, the syntax is *inspired* by Gentoo Portage, but not identical, and the code behind it is mostly my own.)

大昔はとても読む気にならない generic-build-script を使用していたが、今はすべて cygport へ移行しているようである。

チュートリアル

まずはパッケージのレシピとなる .cygport ファイルを用意する必要がある。

というわけで適当に作業するディレクトリに移動する。/usr/src が推奨されているが、別に ${HOME}/src などでも問題ない。

cygport ファイルの作成

とりあえず .cygport ファイルを作成してみる。今回は libpinyin-1.0.0-1bl2 のパッケージを作成してみる。*1

HOMEPAGE="https://github.com/${PN}/${PN}"
SRC_URI="mirror://sourceforge/${PN}/${P}.tar.gz"

CATEGORY="Libs"
SUMMARY="Library to deal with pinyin"
DESCRIPTION="The libpinyin project aims to provide the algorithms core for intelligent
sentence-based Chinese pinyin input methods."

CYGCONF_ARGS="
        --program-prefix=pinyin-
"

PKG_NAMES="
        ${PN}
        ${PN}4
        ${PN}-devel
"
libpinyin_CONTENTS="
        usr/bin/*.exe
        usr/share
"
libpinyin4_CONTENTS="
        usr/bin/*.dll
        usr/lib/${PN}/data
"
libpinyin_devel_CONTENTS="
        usr/include
        usr/lib/${PN}.*
        usr/lib/pkgconfig
"

libpinyin_SUMMARY="${SUMMARY} (utilities)"
libpinyin4_SUMMARY="${SUMMARY} (runtime)"
libpinyin_devel_SUMMARY="${SUMMARY} (development)"
HOMEPAGE

HOMEPAGE にはそのソフトウェアの詳細が書いてあるサイトの URI をセットする。ここで使用している ${PN} にはパッケージの名前 (今回は libpinyin) があらかじめセットされている。

SRC_URI

SRC_URI には (wget で取得できる) ソースアーカイブのある URI をセットする。ここで使用している ${P} にはパッケージのバージョン番号込の名前 (今回は libpinyin-1.0.0) があらかじめセットされている。

よくあるプロジェクトホスティングサービス (例 : sourceforge, gnome, ...) はミラーサイトから取得するための mirror://... 記法がサポートされている。普通のサイトからダウンロードする場合は http://... をセットすれば良い。

また、配布形式が VCS の場合は cygclass による拡張をする必要がある。例えば、git で取得する場合は以下のように書き換える必要がある。

GIT_URI="https://github.com/libpinyin/libpinyin.git"
inherit git

他にも svn や hg など主要な VCS にも対応している。

PATCH_URI

パッチがある場合は PATCH_URIURI をセットすれば良い。(以下はその例。)

PATCH_URI="
    http://example.com/1.patch
    http://example.com/2.patch.gz
"
CATEGORY / SUMMARY / DESCRIPTION

cygwin のパッケージは単なる tarball であるため、パッケージの情報を内部に保持しておらず、それらはダウンロードサイトのトップに置かれた setup.ini に書かれている。cygwin の installer はこれを読んで、インストール時にパッケージの情報を表示している。

setup.ini はパッケージ毎の .hint ファイルから生成されるが、必要とされるパッケージの情報を保持しておく変数が CATEGORY / SUMMARY / DESCRIPTION である。

PKG_NAMES

生成物を複数のパッケージをわけて作成する場合には PKG_NAMES にパッケージ名を列挙する。今回の場合は以下のパッケージが作成されることになる。

  • libpinyin-1.0.0-1bl2-src.tar.xz
  • libpinyin-debug-1.0.0-1bl2.tar.xz
  • libpinyin-1.0.0-1bl2.tar.xz
  • libpinyin4-1.0.0-1bl2.tar.xz
  • libpinyin-devel-1.0.0-1bl2.tar.xz

一番上の *-src という名前になっているパッケージはソースパッケージと呼ばれるもので cygport を使用してバイナリパッケージを再生成できるようにすべてのファイルがアーカイブされている。次の *-debug というパッケージはデバッグ用にソースアーカイブ内の *.c や *.h を集めたものである。それ以外は PKG_NAMES にセットしたパッケージである。

*_CONTENTS

パッケージ毎に梱包するファイルは ${パッケージ名}_CONTENTS に列挙する。これは tar に引数として渡されるため、--exclude=PATTERN で除外指定することもできる。

*_SUMMARY

パッケージ毎にサマリを指定したい場合は ${パッケージ名}_SUMMARY にセットする。${パッケージ名}_CATEGORY および ${パッケージ名}_DESCRIPTION もセットすることができる。(ここでは例示しない。)

パッケージの作成

fetch

.cygport の準備ができたため、パッケージの作成に入る。まずは fetch コマンドでソースアーカイブを取得する。

% cygport libpinyin-1.0.0-1bl2 fetch
--2014-01-11 00:21:37--  http://downloads.sourceforge.net/libpinyin/libpinyin-1.0.0.tar.gz
Resolving downloads.sourceforge.net... 216.34.181.59
Connecting to downloads.sourceforge.net|216.34.181.59|:80... connected.
HTTP request sent, awaiting response... 301 Moved Permanently
Location: http://downloads.sourceforge.net/project/libpinyin/libpinyin/libpinyin-1.0.0.tar.gz [following]
--2014-01-11 00:21:37--  http://downloads.sourceforge.net/project/libpinyin/libpinyin/libpinyin-1.0.0.tar.gz
Reusing existing connection to downloads.sourceforge.net:80.
HTTP request sent, awaiting response... 302 Found
Location: http://jaist.dl.sourceforge.net/project/libpinyin/libpinyin/libpinyin-1.0.0.tar.gz [following]
--2014-01-11 00:21:38--  http://jaist.dl.sourceforge.net/project/libpinyin/libpinyin/libpinyin-1.0.0.tar.gz
Resolving jaist.dl.sourceforge.net... 150.65.7.130
Connecting to jaist.dl.sourceforge.net|150.65.7.130|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 19726060 (19M) [application/x-gzip]
Saving to: `libpinyin-1.0.0.tar.gz.tmp'

100%[======================================>] 19,726,060   429K/s   in 48s

2014-01-11 00:22:26 (402 KB/s) - `libpinyin-1.0.0.tar.gz.tmp' saved [19726060/19726060]

% ls
libpinyin-1.0.0-1bl2.cygport  libpinyin-1.0.0.tar.gz

ちなみに VCS からソースを取得する場合は一時ディレクトリにチェックアウトしたものを再度固めることでソースアーカイブをダウンロードしてきたように振る舞う。

prep

次に prep コマンドで作業ディレクトリの準備をする。

% cygport libpinyin-1.0.0-1bl2 prep
>>> Preparing libpinyin-1.0.0-1bl2
>>> Unpacking source libpinyin-1.0.0.tar.gz
>>> Preparing working source directory
% ls 
libpinyin-1.0.0-1bl2  libpinyin-1.0.0-1bl2.cygport  libpinyin-1.0.0.tar.gz

作業ディレクトリは以下のような構成になっている。

ディレクトリ名 用途
build ビルド用ディレクトリ
config cygport 設定ファイル置場
dist パッケージツリー置場
inst インストール先となるダミーディレクトリ
log ログ置場
origsrc オリジナルソースディレクトリ
patch パッチファイル置場
spkg パッケージ置場
src 作業用ソースディレクトリ
temp 一時ディレクトリ (前述の VCS チェックアウトで使用する)

ちなみに prep は以下の作業をする。

  • 作業ディレクトリを作成する。
  • origsrc 配下にソースを展開する。
  • origsrc に必要な patch をあてる。
  • src に origsrc をコピーする。
  • src/${SRC_DIR}/CYGWIN-PATCHES を作成する。
compile

いよいよビルドする。

% cygport libpinyin-1.0.0-1bl2 compile
>>> Compiling libpinyin-1.0.0-1bl2
autoreconf-2.69: Entering directory `.'
autoreconf-2.69: configure.ac: not using Gettext
autoreconf-2.69: running: aclocal --force
autoreconf-2.69: configure.ac: tracing
autoreconf-2.69: running: libtoolize --copy --force
    :
    :

実際にはビルドに使用するツールによって挙動は違う。cmake や waf などビルドツール系の cygclass を inherit しない場合は autotools によるものと解釈される。*2

単純な Makefile のように cygclass を使用しない場合は src_compile() を再定義すれば良い。

src_compile()
{
    cd ${B} # ビルド用ディレクトリ (上述の build) に移動
    lndirs  # 作業用ソースディレクトリから再帰的にシンボリックリンクを作成
    cygmake # cygport 用のオプションつきで make を起動
}

また、コンソールに流れる compile のログは log/${P}-compile.log にも書き出されているため、検索する場合はそちらを使用することができる。

check

ビルドが終わったらテストをする。ただし、ソースアーカイブに含まれているテストを実行するため、テストが含まれていない場合は何もしない。デフォルト (autotools) では make check を実行する。

必要な場合は自分で src_test() を実装することでテストをさせることができる。

% cygport libpinyin-1.0.0-1bl2 check
>>> Testing libpinyin-1.0.0-1bl2
Making check in src
make[1]: Entering directory '/cygdrive/c/Users/fd0/src/libpinyin/libpinyin-1.0.0-1bl2/build/src'
    :
    :

compile 同様にログは log/${P}-check.log に書きだされる。

install

ビルド結果をダミーのルート (上述の inst) にインストールする。デフォルト (autotools) では make install DESTDIR=${top}/${PF}/inst を実行する。

% cygport libpinyin-1.0.0-1bl2 install
>>> Installing libpinyin-1.0.0-1bl2
Making install in src
make[1]: Entering directory '/cygdrive/c/Users/fd0/src/libpinyin/libpinyin-1.0.0-1bl2/build/src'
    :
    :

ログは log/${P}-install.log にある。

install の内部では postinst という別のコマンドも実行される。postinst では以下のような処理がされる。

  • /etc/{postinst,preremove} の生成
  • man や info の gzip
  • PE バイナリの strip
  • 空ディレクトリや .la の削除
package

インストールファイル群からパッケージを作成する。

% cygport libpinyin-1.0.0-1bl2 package
>>> Packaging libpinyin-1.0.0-1bl2
>>> Creating binary package(s)
>>> libpinyin-1.0.0-1bl2.tar.xz
    :
    :

ログは log/${P}-pkg.log にある。

package では以下の処理がされる。

  • inst 配下のファイルのうち *_CONTENTS で指定したものを tar + xz
  • パッケージに含まれないファイルやパッケージ間で重複しているファイルがないか確認
  • cygwin でビルドするための patch の生成
  • *.hint の生成

また cygwin のバイナリパッケージには CYGWIN 用の README が必要となる。これは package 前に CYGWIN-PATCHES/README に置いておく必要がある。

% ls libpinyin-1.0.0-1bl2/src/libpinyin-1.0.0/CYGWIN-PATCHES
README

配布

package 実行後には dist 配下に配布用の構成でパッケージが生成されている。

% tree dist/libpinyin
dist/libpinyin
├── libpinyin-1.0.0-1bl2-src.tar.xz
├── libpinyin-1.0.0-1bl2.tar.xz
├── libpinyin-debuginfo
│   ├── libpinyin-debuginfo-1.0.0-1bl2.tar.xz
│   └── setup.hint
├── libpinyin-devel
│   ├── libpinyin-devel-1.0.0-1bl2.tar.xz
│   └── setup.hint
├── libpinyin4
│   ├── libpinyin4-1.0.0-1bl2.tar.xz
│   └── setup.hint
└── setup.hint

3 directories, 9 files

これをインストールできるようにするために http でアクセスできる場所へ持っていき、genini で setup.exe が読むための setup.ini を生成する。*3

# 使用する httpd の設定によって DocumentRoot は変更する
% cp -R libpinyin /var/www/dist/x86_64/release/
% cd /var/www/dist
% genini --recursive x86_64 | bzip2 -c > x86_64/setup.bz2

インストール

いよいよ setup.exe で自作のパッケージをインストールするが、setup.exe はセキュリティの面からデフォルトで signature を必要とする。しかし、-X オプションでオフでできるため、起動時に -X を渡すようにしておく。


f:id:fd0:20140121084854p:plain


起動後にダウンロードサイトの選択画面に遷移したら、パッケージを置いている URL を指定する。(具体的にはフォームに URL を入力して Add する。)


f:id:fd0:20140121085150p:plain


先ほど作成したパッケージを選択する。(SKIP になっているあたりをクリックするとインストールするバージョン番号に変わる。)


f:id:fd0:20140121085739p:plain


あとは Next を押して進んでいけばインストール完了となる。

インストールができているかは cygcheck で確認することができる。

%  cygcheck -cd | grep libpinyin
libpinyin                           1.0.0-1bl2
libpinyin-devel                     1.0.0-1bl2
libpinyin4                          1.0.0-1bl2

まとめ

cygport を使った自作パッケージの作成からインストールまでの手順をまとめた。

他にも cygclass やそれらで使用するオプションについても今後、紹介する予定としている。

*1:パッケージ名は pkg-ver-rel で構成される。pkg はパッケージ名、ver はバージョン番号、rel はリリース番号をそれぞれ表現する。一般的に元のソースのバージョンが変わらないまま、リビルドなどでパッケージをアップデートする場合はリリース番号を上げるポリシーとなっている。

*2:各 cygclass については /usr/share/cygport/cygclass 配下を参照されたい。

*3:httpd として cygwinapachelighttpd を使用することはできるが、その場合は windows は起動中の executable の書き換えができないため、それら自身の update ができなくなることに注意する。