パッケージ管理ツール porg (3)使い始めた方のための "本当の実践的活用方法"

## 概要
前記事にて porg の実践的な利用方法を示しました：

* [Qiita: パッケージ管理ツール porg (1)実践的インストール](https://qiita.com/matsuand/items/2c1c4e5359e1ff033c92)
* [Qiita: パッケージ管理ツール porg (2)実践的な利用方法](https://qiita.com/matsuand/items/2fbe632282c5612a76ea)

ここでは、実際に porg を使い始めた方に向けての "本当の実践的活用方法" を示します。やり始めてみないと分からない話。テーマはあちこちに飛びます。

## 1. 本当は引用符でくくる ```"make install"```

前記事での操作例は、表記を単純にするために ```porg -lD make install``` としていました。これは ```porg -lD "make install"``` というように、```make install``` を引用符でくくるように覚えておく方がベターです。

例えば以下のような ```install``` ターゲットは、引用符なしではうまく動作しません。

```shell-session:誤った使い方
$ porg -lD make -C doc install     # NG!
porg: invalid option -- 'C'
porg: Try 'porg --help' for more information
```

```make``` コマンドに対する ```-C``` オプションが、porg に対するオプションとして解釈されてしまうためです。```make -C doc install``` 部分は引用符で囲む必要があります。常々引用符をつけるものだ、と覚えておけば間違いはありません。

```shell-session:正しい使い方
$ porg -lD "make -C doc install"   # OK!
```

## 2. ```"make install"``` 以外にもさまざまなコマンド利用
前記事でも述べたことですが、porg を使ってソースパッケージを登録するのは ```make install``` コマンドだけではありません。さまざまなコマンドを用いて porg 登録操作を行っていくことができます。

以下は数々の例を、詳細な説明は抜きにして例示します。コメントを手がかりに読んでください。

```shell-session
# porg -lD "make install"
# vi /etc/myapp.conf
... myapp.conf というファイルを編集 ...
# porg -lD+ "touch /etc/myapp.conf"      # touch コマンドにより porg 登録

# porg -lD+ "cp doc/* /usr/share/doc/hello-2.10"
                                         # cp コマンドを使ってドキュメントコピー
# porg -lD+ "ln -s ../../lib/baz.so /usr/lib/baz.so"
                                         # ln コマンドを使って symlink
# porg -lD+ "rm /usr/lib/libhello.so*"
                                         # rm コマンドを使って so ファイルを削除

# porg -lD+ "mkdir -p /etc/myapp"        # ディレクトリ生成は記録されません
porg: somepackage: No files to log       # 何も記録(log)しなかったという警告エラー

# porg -lD+ "chmod 400 /etc/something"   # chmod も記録されません
porg: somepackage: No files to log

# porg -lD "python setup.py install"     # Autotools 以外のインストールもろもろ
# porg -lD "pip install someapp"
# porg -lD "gem install someapp"
# porg -lD "ninja install"

# porg -lD "make install" | tee mylog.log  # ログ出力
# porg -lD "make install" >mylog.log 2>&1
```

## 3. 余計なものが porg に登録されてしまう

<details><summary>```porg -lD make install``` としたときに余計なファイルが porg に登録されてしまうときがあります。ありがちなのが、ソースディレクトリ内のファイルが porg に登録されてしまうことです。</summary>
ここで注意して頂きたいのは、「余計なファイルがインストールされる」とは言っていません。「余計なファイルが**porg に登録されてしまう**」と言っています。つまりソースパッケージ側の問題ではなく、porg 側の問題なのです。
</details>

<details><summary>具体例を見ます。GNU の [screen-4.6.2](https://ftp.gnu.org/gnu/screen/screen-4.6.2.tar.gz "screen-4.6.2") をインストールした例です。```porg -f screen``` によって screen パッケージとして登録されたファイルを一覧表示してみます。</summary>
```./configure```、```make``` を行い ```porg -lD make install``` によって porg への登録を済ませているとします。
</details>

```shell-session
$ porg -f screen
screen-4.6.2:
/etc/screenrc
/usr/local/src/screen-4.6.2/doc/screen.info    # これは何だ？！
/usr/bin/screen
/usr/bin/screen-4.6.2
/usr/share/info/dir
/usr/share/info/screen.info                    # ここに上と同じファイルあり！
/usr/share/man/man1/screen.1
/usr/share/screen/utf8encodings/01
/usr/share/screen/utf8encodings/02
...以下省略...
```

<details><summary>問題は ```screen-4.6.2:``` に続くファイル一覧の 2 行め、```/usr/local/src/.../screen.info``` というファイルです。これは実はソースディレクトリ内のファイルであって、screen パッケージが「**インストール対象物をここに置きます**」といって置いたものではありません。</summary>
それが証拠に、その数行下に (ディレクトリこそ異なりますが) 同名ファイル ```/usr/share/info/screen.info``` が一覧の中に表示されていて、まさにこれが、正しいディレクトリにインストールされた結果であるわけです。ソースディレクトリ内の ```/usr/local/src/.../screen.info``` というファイルは間違っています。というか、そもそもソースコードからパッケージビルドを行った場合、インストールした後にはソースディレクトリは削除しますから、こんな風に porg に登録されても、ソースディレクトリ内のファイルはすぐ削除されます。porg に登録されることがおかしいのです。
</details>
<details><summary>なぜこんなことになるのか。これは止むを得ません。porg にとっては、```make install``` によって、その裏側で実際にファイルの移動 (```mv```) やコピー (```cp```) などが行われたものすべてを登録することしか、対処のしようがないからです。</summary>
中身を仔細に調べてみると、screen パッケージは ```make install``` の際に、```makeinfo ./screen.texinfo -o screen.info``` というコマンドを実行して ```screen.info``` なるファイルを生成しています。これはソースディレクトリ (厳密にはビルドディレクトリ) 内での話です。これをやられてしまうと porg は、インストール操作中に新たに create されたファイルであることから、インストール対象物として捉えてしまいます。これがインストール処理なのか、そうではないのかは porg には分かりません。だから 2 行めのファイルとして ```-f``` オプションの一覧にあがってしまっているのです。
</details>

<details><summary>これを避ける方法を紹介します。```-E``` オプションを活用します。そして詳細な説明は省略しますが、```-E`pwd` ``` とするのが手っ取り早い解決法です。</summary>
このオプションはディレクトリ名を引数にとるもので、そのディレクトリ配下のファイルは porg に登録しないことを指示します。
```-E`pwd` ``` という入力は、カレントディレクトリ配下のファイルを porg に登録させないことを意味します。ここでいうカレントディレクトリは、ソースディレクトリ (厳密にいうとビルドディレクトリ) を指すことになります。こうすることで、screen パッケージの例でいえば、ソースディレクトリ配下の、例の ```screen.info``` というファイルの登録が阻止できることになります。
</details>

```shell-session
$ porg -lD -E`pwd` "make install"
```

<details><summary>一般的には ```-E`pwd` ``` というオプションだけでは対処できない場合もありますので留意しておいてください。</summary>
そもそもこの ```-E``` オプションのデフォルト値は ```/tmp:/dev:/proc:/selinux:/sys:/run``` というものです。ここに列記されているように、```/``` (ルートディレクトリ) 配下の特別なディレクトリを除外する指定です。
```-E`pwd` ``` という指定の仕方は、このデフォルト値を上書きして ``` `pwd` ``` だけを除外ディレクトリに指定するものとなります。デフォルト値を上書きしたことから、```/tmp:/dev:/proc:/selinux:/sys:/run``` の指定は為されなくなります。したがってもし ```/tmp``` や ```/run``` などにインストールを行う (あるいはインストール処理時に、一時的にせよこれらのディレクトリへの書き込みを行う) パッケージがある場合は、そのディレクトリに対するインストール処理が記録されることになります。少なくとも ```/tmp``` へのインストールなんて普通はありえません。このように ```-E`pwd` ``` という指定は思わぬ副作用を生む可能性がありますから注意してください。一切の不具合をなくすためには ```-E/tmp:/dev:/proc:/selinux:/sys:/run:`pwd` ``` と指定するのが最上の手立てになりますが、そこまでしなくてもせめて ```-E/tmp:`pwd` ``` くらいは必要になるかもしれません。
</details>

## 4. 生成バイナリを tarball にするスクリプト ```porgball```
ソースコードからビルドした各種パッケージを porg に登録した場合に、そのインストールファイル (実行バイナリやドキュメントなど) を tarball に固めるスクリプト ```porgball``` というものが用意されています。せっかくソースコードからビルドしたのですから、バックアップの意味で、あるいは他マシンへのコピーなどに活用できる補助ツールです。

実例を示します。GNU hello パッケージを既に porg により登録しているとします。```porgball``` を使って登録内容 (インストール内容) を tarball にします。

```shell-session
... 操作するディレクトリはどこでもよい...
# porgball hello
tar: メンバ名から先頭の `/' を取り除きます

あるいは
# LANG=C porgball hello
tar: Removing leading `/' from member names
```

警告メッセージ「```メンバ名から先頭の `\' を取り除きます```」は ```tar``` コマンドが出力しているもので、```tar``` の仕様に基づくものです。

上によりカレントディレクトリに tarball が生成されます。以下で確認します。

```shell-session
# ls
hello-2.10.porg.tar.gz

# tar tf hello-2.10.porg.tar.gz | less
usr/bin/hello
usr/share/info/dir
usr/share/info/hello.info
usr/share/locale/bg/LC_MESSAGES/hello.mo
usr/share/locale/ca/LC_MESSAGES/hello.mo
...以下省略...
```

生成される tarball には、サフィックスとして ```.porg``` がつきます。
またデフォルトでは tar.gz が生成されますが、tar.bz2 にするには ```-b``` オプション、tar.xz にするには ```-x``` オプションが用意されています。詳しくは ```porgball --help``` や ```man porgball``` を参照してください。

<!--
5. porg のパッケージ管理は信頼してよいのか

<details><summary>過度の期待は禁物です。ほどほどに用いましょう。</summary>
porg 自体のソースビルドは、大きな依存パッケージもほぼなく、小規模ソフトウェアなので簡単にビルドしインストールすることができます。お手軽に導入できるというのが、porg の良いところです。お手軽である分、パッケージも「お手軽に」(言い換えればそんな煩雑なところまでは手を出さずに) 利用できるというものです。完璧な動作までいかないケースも出てきます。
</details>

-->