簡単! パッケージを作成してAURへ登録しよう

これは [ArchLinux Advent Calendar 2015](https://qiita.com/advent-calendar/2015/archlinux)の25日目の記事です。

ArchLinuxを使い始めて3年程になりますが、とても気に入っていますし、もちろんまだまだ使い続けるつもりです。
個人的な用途は開発機としてですが、ArchLinuxのポリシーである「ローリング・リリース」との相性が抜群です。
コマンド一発で環境を最新に維持できます。

```shell-session
sudo pacman -Syu
```

私の場合、仕事で扱うサーバはまだRedHat 5.9が主なのですが、最近のライブラリはそのままではビルド出来ない事もあります。
必要なライブラリをビルドするために、gccを新しくしたり、autoconf/automakeを新しくしたり、依存パッケージを更新したり、時にはRubyやPython等を新しくしたり、更にパッチを当てたり、同じツールの複数バージョンを上手く切り替えるための設定をしたり、と何とかしのいでいますが、いわれのない辛さがあります。
また、Ubuntu 14.xもクラウド環境で良く使いますが、それでもライブラリやツール類が若干古いというのは案外あります。
ArchLinuxの場合、環境をアグレッシブに最新化するのがディストリビューションのポリシーのため、そういった環境の陳腐化に伴う苦労がほとんどないのは気分的に爽快です。

# ArchLinuxはパッケージの作成が楽
他に私がArchLinuxで好きな点を挙げるとしたら、真っ先に思いつくのがパッケージの作成が簡単なところです。

これを書いている2015年12月現在、[AUR](https://aur.archlinux.org/)(Arch User Repositoryの略)には3万を超えるパッケージが存在していますし、新規パッケージが登録されるのは、ArchLinuxはさまざまなディストリビューションの中でも一番速い部類でしょう。

とはいえ、新しく開発・公開されたライブラリやツールは、パッケージ化されていないことも多々あるかと。
…そういう時こそ自分で作ってみましょう!
結構簡単です。

私の場合、AURに存在しない開発用のライブラリ等をその都度パッケージ化していたら、いつのまにか[作成したパッケージ](https://aur.archlinux.org/packages/?O=0&SeB=m&K=dseg&SB=p&PP=50&SO=d)が100を超えていました。

# AUR
[AUR](https://wiki.archlinuxjp.org/index.php/Arch_User_Repository)には、ユーザがメンテナンスしている非公式パッケージが日々登録されています。

公式パッケージの場合、ビルド用の一式は[ABS](https://wiki.archlinuxjp.org/index.php/Arch_Build_System)(Arch Build Systemの略)で管理されていて、pacmanでユーザがパッケージをインストールする場合、ビルド済みのバイナリが使われます。
AURは、ABSで行われていることを自分達でやるための場所、という感じです。

パッケージ作成者はビルドのための一式をAURに登録し、パッケージ利用者はそれを取得して自分のマシンでビルド、インストールします。
従ってAURのパッケージはほとんどソースからビルドする形になります。

## AURの管理ツール
pacmanでは、AURからパッケージをダウンロード出来ないので、専用のツールが必要です。
人気があるのは、

 - [yaourt](https://aur.archlinux.org/packages/yaourt/)
 - [packer](https://aur.archlinux.org/packages/packer/)
 - [cower](https://aur.archlinux.org/packages/cower/)

等。インストールしたAURのパッケージは、コマンド一発で更新可能です。

```shell-session
# AURのパッケージを含め、システム一括更新
$ yaourt -Syu --aur --noconfirm 
# or
$ yaourt -Syua --noconfirm
```

## 既存パッケージの更新
一番ありがちなパターンなのでこちらをまず紹介します。
AURにはバージョンが古いままのパッケージが結構あります。
そういう場合は、パッケージをダウンロードし、PKGBUILDを編集してバージョンだけ少しだけ書き換え、リビルドすれば大体最新版になります。

```shell-session
$ yaourt -G パッケージ名

# 例
$ yaourt -G rebol
==> Download rebol sources
x .AURINFO
x .SRCINFO
x PKGBUILD
```

```shell-session
$ cd rebol
$ vi PKGBUILD
# pkgver を書き換えて保存

$ updpkgsums
==> Retrieving sources...
==> Generating checksums for source files...

# ビルド
$ makepkg -s

# インストール
$ sudo pacman -U パッケージ名*.xz
```
# パッケージの作り方

## 概要
1. 公式ドキュメントを読む
2. AURにユーザ登録
3. 必須ツールのインストール
4. PKGBUILD記述
  - ひな型から作成
  - 既存パッケージから変換
5. ビルド
6. 確認
7. AURに登録

## 1. 公式ドキュメントを読む
何はなくてもArchWiki、という訳で、手順は例のごとくArchWikiに詳しく記載されています。

- <https://wiki.archlinux.org/index.php/Creating_packages>
- <https://wiki.archlinuxjp.org/index.php/Arch_User_Repository#Creating_a_new_package>
今は日本語訳あるんですね。翻訳してくれた方に感謝。
- <https://wiki.archlinux.org/index.php/Arch_packaging_standards> パッケージ先のディレクトリ等

## 2. AURのWebサイトでユーザー登録
<https://aur.archlinux.org/register/>
まずは必須項目だけ入力すればOKです。
SSHの鍵は、実際にパッケージをAURに登録するときに必要になります。

## 3. 必須ツールのインストール
パッケージ作成に必要なツールをインストールします。

```shell-session
$ sudo pacman -S base-devel openssh git 
$ sudo pacman -S pkgbuild-introspection
```

オプションですが、作成したパッケージの確認をしてくれる「[namcap](https://wiki.archlinux.org/index.php/Namcap)」というユーティリティがありますのでお勧めです。
lintのようなツールです。

```shell-session
sudo pacman -S namcap
```
## 4. PKGBUILD記述
既存のパッケージが存在しないか確認しておきます。

```shell-session
$ yaourt -Ss パッケージ名
```

### ひな型から作成
/usr/share/pacman/ に幾つかひな型がありますので、適切なものを選んでコピーします。

```shell-session
[dseg@vultrserver01]$ ls /usr/share/pacman/
keyrings        PKGBUILD-split.proto  proto.install
PKGBUILD.proto  PKGBUILD-vcs.proto
```

```shell-session
# パッケージを格納するディレクトリ作成
mkdir ~/mypkg

# PKGBUILDのひな型をコピー
cd ~/mypkg
cp /usr/share/pacman.d/PKGBUILD.proto PKGBUILD
```
### 既存パッケージから変換
- [gem2arch](https://aur.archlinux.org/packages/gem2arch/) Rubyのgemを変換
- [Pip2Arch](https://github.com/bluepeppers/pip2arch) Pythonのpypiを変換
- [npm2arch](https://github.com/Filirom1/npm2arch) nodejsのnpmを変換

### PKGBUILDを記述する
パッケージを作るには、PKGBUILDというシェル風のテキストファイルに記述しますが、書式がシンプルでノイズが少ないと思います。

以前は、RedHat環境で自前のRPMを作るため時々SPECファイルを記述していました。
SPECもそう複雑ではないですが、ArchLinuxのPKGBUILDを始めて作った時には比較して「すごくシンプル」と感動したのを覚えています。

そもそも、パッケージングというのはそう手間がかかる作業であってはいけないと思います。
サクッと始められて記述も簡単、新バージョンが出た時の更新もすぐ可能、位でないと疲れてしまいますからね。

#### PKGBUILDの構造

- 先頭部分
  変数定義です。パッケージ名や依存関係、バージョンの定義をします。
- prepare()
準備です。ここではパッチを当てたり、automakeをしたりします。
- build()
ビルドです。configure, make をするのが多いです。
- check()
make check 等を記述しますが、省略される場合が多いです。
- package()
ディレクトリを作ったり、ビルドしたもののインストールを行います。

#### PKGBUILDの内容
大体見たら分かると思います。

```bash:PKGBUILD
# Maintainer: Somebody <somebody[at]foo[dot]tld>
pkgname=foo
pkgver=10.0.2
pkgrel=2
pkgdesc="Foo is an example package for this PKGBUILD file."
url="http://www.foo.tld"
arch=('x86_64' 'i686')
license=('GPLv3')
depends=('php' 'mysql')
optdepends=('java-runtime')
makedepends=()
conflicts=()
replaces=()
backup=()
install='foo.install'
source=("http://www.server.tld/${pkgname}-${pkgver}.tar.gz"
        "foo.desktop")
md5sums=('a0afa52d60cea6c0363a2a8cb39a4095'
         'a0afa52d60cea6c0363a2a8cb39a4095')

build() {
  cd "${srcdir}/${pkgname}-${pkgver}"
  cmake ./ -DCMAKE_INSTALL_PREFIX=/usr
  make
}

package() {
  cd "${srcdir}/${pkgname}-${pkgver}"
  make DESTDIR="${pkgdir}" install
  install -Dm644 COPYING "$pkgdir/usr/share/licenses/$pkgname/COPYING"
}

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

##### install=
インストールが実施されたあとに実行されるシェルスクリプトを指定できます。
例えば、システムユーザの追加・削除をしたり、Emacsのマクロをコンパイルするのに使えます。
(この仕組みを使えば、ディレクトリ構成の違うパッケージング時には実施できない処理をインストール時に行うことが出来る)

##### package()について
$pkgdir にインストールするように記述していきます。

#### PKGBUILD-git,svn,hg について
ArchLinuxでは VCSパッケージというものがあり、この種のパッケージをビルドすると、gitなどソース管理システムから最新版が取得されるようにできます。
また、ビルドを実施すると、pkgver()関数で定義した内容でパッケージ名を付けてくれます。
例えば、
```
grpc-git-0.9.0.r84.g12bde00-1.tar.xz
```
などとなります。
この例だと、パッケージを管理者がビルドした時、git上でのバージョンが0.9.0.r84だったことを表していますが、
ローカルでこれをビルドすると、再度gitから取得するので、もっと新しいバージョンがビルドされることがほとんどです。
yaourtと組み合わせて、gitから取得するパッケージの最進化も自動で実施できるところが便利です。

VCS用のPKGBUILDのひな型も用意されていますが、基本そんなに内容は変わりません。
source行をgitにするのと、pkgver()関数を定義すること位です。

https://aur.archlinux.org/cgit/aur.git/tree/PKGBUILD?h=grpc-git

```bash:PKGBUILD
source=('git+https://github.com/grpc/grpc.git')
md5sums=('SKIP')

pkgver() {
  cd $_pkgname
  git describe --long --tags|sed 's/\([^-]*-g\)/r\1/;s/[-_]/./g;s/^release.//'
}
```

#### マルチパッケージ機能を使う
一つのPKGBUILDから、複数のパッケージを作成することが出来ます。
昔は不可能でしたが、最近のアップデートで機能追加され、出来るようになりました。

良くあるのは、python2/python3用の2つのパッケージを、1つのPKGBUILDから作る例です。

 - [python-paho-mqtt](https://aur.archlinux.org/cgit/aur.git/tree/PKGBUILD?h=paho-mqtt)

pkgbase、pkgname変数を定義。package関数を複数用意します。

```bash:PKGBUILD
pkgbase=paho-mqtt
pkgname=(python-$pkgbase python2-$pkgbase)

package_python-paho-mqtt() {
    pkgdesc="Python client library for MQTT v3.1 and v3.1.1"
    depends=('python')

    cd $srcdir/$pkgbase-$pkgver
    python setup.py install --root="$pkgdir" --optimize=1
}

package_python2-paho-mqtt() {
    pkgdesc="Python 2 client library for MQTT v3.1 and v3.1.1"
    depends=('python2')

    cd $srcdir/python2-$pkgbase-$pkgver
    python2 setup.py install --root="$pkgdir" --optimize=1
}
```

### 5. ビルド

#### ビルド
```shell-session
$ makepkg -s
```
#### メタデータ生成
AURへのパッケージ登録には、.SRCINFOというメタデータが*必須*です。
mksrcinfo コマンドで生成します。

```shell-session
$ mksrcinfo
```

### 6. チェック

```shell-session
$ namcap ビルド済みパッケージ.tar.xz
```

### 7. AURへ登録

登録はシンプルで、gitでクローン・コミット・プッシュするだけです。

ただし、事前にSSHの鍵を登録しないといけません。
このあたりはGitHub等と同じような仕組みです。

#### 鍵の作成と設定

##### 鍵の生成
```shell-session
$ ssh-keygen -t rsa -b 4096 -f ~/.ssh/id_aur
$ chmod 400 ~/.ssh/id_aur
```
##### AURのgitサーバで鍵を使う設定
```shell-session
$ cat <<EOL >>~/.ssh/config

Host aur.archlinux.org
  User aur
  IdentitiesOnly yes
  IdentityFile ~/.ssh/id_aur
EOL
```

##### AURのユーザーページに公開鍵を登録
生成したid_aurをWindowsにコピーしてputtygenで開きます。
ssh-rsa .... の部分をAURの鍵の部分にコピペします。

![](hhttps://raw.githubusercontent.com/dseg/dseg.github.io/master/img/qiita/08-arch-aur/puttygen-ssh-pubkey.png)
  ↓
![](hhttps://raw.githubusercontent.com/dseg/dseg.github.io/master/img/qiita/08-arch-aur/profile-ssh-key.png)
#### パッケージの初期化
存在しないパッケージをgit cloneすることで、パッケージが初期化されます。

```shell-session
$ git clone ssh://aur.archlinux.org/<<パッケージ名>>
# 例
$ git clone ssh://aur.archlinux.org/haxe
```

#### パッケージの更新
編集作業が完了したら、ローカルでの変更をコミットし、AURにpushします。

```shell-session
$ git commit -m "(例) Bump version to 0.26.0" .SRCINFO PKGBUILD
[master 45f3c31] Bump version to 0.26.0
 2 files changed, 8 insertions(+), 5 deletions(-)

$ git push origin master
```
以上で完了です。
後は、AURのパッケージのWebページで、アップデートしたことをコメントすると親切です。
(通知設定をしているユーザに更新が通知される)

# AURからCommunityへのパッケージ移動
先日、AURで公開しているパッケージの件で突然E-メールが届き、「Communityレポジトリにそのパッケージを移したいんだけど良いかな?」
とのことでした。もちろんOK! と返事すると、その日のうちにパッケージがCommunityに移動され、AURのパッケージは削除されました。
今までyaourtでインストールしていたパッケージがpacmanでインストールできるようになり、少なからず驚きました。

どんな時にAURからCommunityレポジトリに移動されるのかについて調べたところ、
ArchWikiには以下のように記述がありました。

 - [How to get a PKGBUILD into the community repository?](https://wiki.archlinux.org/index.php/Arch_User_Repository#How_to_get_a_PKGBUILD_into_the_community_repository.3F)
  - パッケージに10件以上のユーザの投票がある
  - もしくは、[Trusted User](https://wiki.archlinuxjp.org/index.php/Trusted_Users) (TU)がCommunityへの移動を支持している

## Trusted Userの役目
これはTUの方から聞いたので間違いないですが、[Trusted User](https://wiki.archlinuxjp.org/index.php/Trusted_Users)は、AURからCommunityレポジトリへとパッケージを移動する権限を持っているそうです。

…でもTrusted Userになるにはどうすれば良いのか?
ArchWikiには以下のように記載されていました。

- [AUR Trusted User ガイドライン](https://wiki.archlinuxjp.org/index.php/AUR_Trusted_User_%E3%82%AC%E3%82%A4%E3%83%89%E3%83%A9%E3%82%A4%E3%83%B3)

これを読むと大変そうですが、実際には、質の高い(規約を守っている)パッケージを10数個作成していればOKのようです。
[aur-general mlでの議論](https://www.mail-archive.com/search?a=1&l=aur-general%40archlinux.org&haswords=trusted+user&x=20&y=12&from=&subject=&datewithin=6m&date=&notwords=&o=newest)が参考になります。
立候補制で、かつ投票制なので、なかなか面倒だとは思いますが。

# Tips
## 更新できなくなったパッケージはすぐにDisownしよう
忙しくて更新できない、興味がなくなった、ビルド機が壊れた・買い換えたからメンテ不能…、そういう時はパッケージをDisownしましょう。
誰かがメンテナンスしてくれるはず。
長年見てますが、パッケージのDisownはごく普通のことなので、むしろ積極的にやった方が良いです。
今まで、AURでは、ある人がメインテナンスしているパッケージは占有状態になり他の人がメンテできませんでした。
最近の更新で、共同メンテナ(Co-maintainer)を任命できるようになったり、パッケージの所有権の移転を申し込みが出来るようになりました。

## ライセンスを確認しよう
ついパッケージの本体の内容に気が向きがちですが、ライセンスの選択も重要です。
README等をよく読み、正しいライセンスを選択し、コピーライト関連のファイルをパッケージに含める必要があります。
よくユーザからコメントなどで指摘を受ける箇所でもあります。

## makepkgのオプションを使いこなそう
- ビルド時に依存パッケージをインストールする

```shell-session
makepkg -s
```
- ビルドしないでパッケージだけ実施

```shell-session
makepkg -R
```
- ビルドが成功したらクリーンする

```shell-session
makepkg -Cc
```
- checkをスキップ

```shell-session
makepkg --nocheck
```

## 放置パッケージのメンテナンスをしたい
放置されているパッケージは引き取る事ができます。
パッケージのページの右側、Package Actionsの囲みからFile Requestを選択し、Request typeをOrphanにし、File Requestボタンを押して下さい。
![](https://raw.githubusercontent.com/dseg/dseg.github.io/master/img/qiita/08-arch-aur/orphan-request.png)

# 参考
 - [Arch Linuxとパッケージシステム](http://qiita.com/boronology/items/6ea8a4dd540c5980627b)

# おわりに
誰でも一度は、ビルド用の簡単なシェルスクリプトなどを作った事があると思うのですが、ArchLinuxのPKGBUILDはその延長の感じで手軽に作れます。
また、インストールしたパッケージはpacmanで管理できますので便利です。

それではみなさん、 Happy ARCHing!