付録A 上級パッケージング

# 付録A 上級パッケージング

最新の内容とより実用的な例でこの入門書を書き換えたものが Guide for Debian Maintainers として入手できます。この新しい入門書を第一次的な入門書として使ってください。

あなたが出会いそうな上級パッケージング課題に関するヒントや外部参照をいくつか記します。ここに提案されたレファレンス全てに目を通すことを切にお薦めします。

本章で取り上げたトピックをカバーするには dh_make コマンドで生成されたパッケージ用テンプレートファイルではマニュアル編集する必要があるかもしれません。より新しい debmake コマンドはこのようなトピックへの対応が優れています。

## A.1. 共有ライブラリー

共有 ライブラリー をパッケージングする前に、以下の 一次レファレンスを詳細に読むべきです:

- Debian Policy Manual, 8 "Shared libraries"

- Debian Policy Manual, 9.1.1 "File System Structure"

- Debian Policy Manual, 10.2 "Libraries"

以下はあなたが手を付け始めるための少々簡略化しすぎたヒントです:

- 共有ライブラリーとはコンパイルされたコードを含む ELF オブジェクトファイルです。

- 共有ライブラリーは `*.so` ファイルとして頒布されます。(`*.a` ファイルでも `*.la` ファイルでもありません)

- 主に、共有ライブラリーは ld メカニズムを用い複数の実行プログラム間でコードを共有するのに使用されます。

- 時々、共有ライブラリーは dlopen メカニズムを用いある実行プログラムに複数のプラグインを提供するのに使用されます。

- 共有ライブラリーは変数や関数やクラスのようなコンパイルされたオブジェクトを表す シンボル をエキスポートし、リンクされた実行プログラムからそれらへのアクセスを可能とします。

- 共有ライブラリー `lib`foo`.so`.`1` の SONAME: `objdump -p lib`foo`.so.`1` | grep SONAME` [87]

- 共有ライブラリーの SONAME は通常ライブラリーのファイル名と一致します(例外もあります)。

- ``/usr/bin/foo`` にリンクされた共有ライブラリーの SONAME: `objdump -p `/usr/bin/foo` | grep NEEDED` [88]

- `lib`foo``1``: 共有ライブラリー `lib`foo`.so.`1`` で SONAME ABI バージョンが `1` のライブラリーパッケージ。[89]

- ライブラリーパッケージのパッケージメンテナースクリプトは SONAME に必要なシンボリックリンクを作成するために特定の環境下で ldconfig を呼ばなければいけません。[90]

- `lib`foo``1`-dbg`: 共有ライブラリー `lib`foo``1`` のデバッグシンボルを含むデバッグシンボルパッケージ。

- `lib`foo`-dev`: 共有ライブラリー `lib`foo`.so.`1`` 用のヘッダーファイル他を含む開発用パッケージ 。[91]

- Debian パッケージは一般的に `*.la` Libtool アーカイブファイルを含んではいけません。[92]

- Debian パッケージは一般的に RPATH を使うべきではありません。[93]

- 少々内容が古くなった二次的なレファレンスですが、Debian Library Packaging Guide はまだ有用かもしれません。

## A.2. `debian/`package`.symbols` の管理

共有ライブラリーをパッケージする際には、同一共有ライブラリーパッケージ名のライブラリーの同一 SONAME の下での後方互換性のある変更に関して、各シンボルと関連付けられる最小のバージョンが記された `debian/`package`.symbols` ファイルを作成すべきです。[94] 以下の一次的レファレンスを詳細に読むべきです:

- Debian Policy Manual, 8.6.3 "The symbols system"[95]

- dh_makeshlibs(1)

- dpkg-gensymbols(1)

- dpkg-shlibdeps(1)

- deb-symbols(5)

過去バージョン `1.3` のアップストリームバージョンから適切な `debian/libfoo1.symbols` ファイルを用いて `libfoo1` パッケージを作成する概略例は以下です:

- アップストリームの `libfoo-1.3.tar.gz` ファイルを用いてDebian 化したソースツリーの骨子を準備します。

  - もし `libfoo1` パッケージの最初のパッケージングの場合は、内容が空の `debian/libfoo1.symbols` ファイルを作成します。

  - もし以前のアップストリームバージョン `1.2` が `libfoo1` パッケージとして適切な `debian/libfoo1.symbols` を用いてパッケージされていた場合には、それを再び使いましょう。

  - もし過去のアップストリームバージョン `1.2` が `debian/libfoo1.symbols` を用いてパッケージされていない場合には、そのライブラリーの同一 SONAME を含む同一共有ライブラリーパッケージ名 の全ての手に入るバイナリーパッケージ、例えば `1.1-1` と `1.2-1` バージョンから、それを `symbols` として生成できます。[96]

        $ dpkg-deb -x libfoo1_1.1-1.deb libfoo1_1.1-1
        $ dpkg-deb -x libfoo1_1.2-1.deb libfoo1_1.2-1
        $ : > symbols
        $ dpkg-gensymbols -v1.1 -plibfoo1 -Plibfoo1_1.1-1 -Osymbols
        $ dpkg-gensymbols -v1.2 -plibfoo1 -Plibfoo1_1.2-1 -Osymbols

- debuild や pdebuild 等のツールを使ってソースツリーのテストビルドをします。 (もしシンボルの欠如等でビルドがうまく行かない場合には、共有ライブラリーパッケージ名を `libfoo1a` 等と繰り上げる必要のある何らかの後方非互換な ABI 変更があったので、最初からやり直す必要があります。)

      $ cd libfoo-1.3
      $ debuild
      ...
      dpkg-gensymbols: warning: some new symbols appeared in the symbols file: ...
       see diff output below
      --- debian/libfoo1.symbols (libfoo1_1.3-1_amd64)
      +++ dpkg-gensymbolsFE5gzx        2012-11-11 02:24:53.609667389 +0900
      @@ -127,6 +127,7 @@
        foo_get_name@Base 1.1
        foo_get_longname@Base 1.2
        foo_get_type@Base 1.1
      + foo_get_longtype@Base 1.3-1
        foo_get_symbol@Base 1.1
        foo_get_rank@Base 1.1
        foo_new@Base 1.1
      ...

- もし上記のように dpkg-gensymbols によって diff がプリントされるのを発見した場合には、生成された共有ライブラリーのバイナリーパッケージから適切な `symbols` ファイルを抽出しましょう。[97]

      $ cd ..
      $ dpkg-deb -R  libfoo1_1.3_amd64.deb libfoo1-tmp
      $ sed -e 's/1\.3-1/1\.3/' libfoo1-tmp/DEBIAN/symbols \
              >libfoo-1.3/debian/libfoo1.symbols

- debuild や pdebuild のようなツールでリリースパッケージをビルドします。

      $ cd libfoo-1.3
      $ debuild -- clean
      $ debuild
      ...

上記の例に加えて、更に ABI 互換性を確認し、必要に応じていくつかのシンボルのバージョンを手作業で繰り上げる必要があります。[98]

二次的なレファレンスではありますが、Debian wiki UsingSymbolsFiles とそこからリンクされているウェブページは有用かもしれません。

## A.3. マルチアーチ

Debian wheezy で導入されたマルチアーチ機能は `dpkg` と `apt` の中でのバイナリーパッケージのアーキテクチャー間サポート (他の組み合わせもありますが、特に`i386`<->`amd64`) を統合します。 以下のレファレンスを詳細に読んで下さい:

- Ubuntu wiki MultiarchSpec (アップストリーム)

- Debian wiki Multiarch/Implementation (Debian の状況)

マルチアーチは共有ライブラリーのインストールパスに `i386-linux-gnu` や `x86_64-linux-gnu` 等のトリプレットを使います。実際のトリプレットパスは、ビルドごとに dpkg-architecture(1) によって動的に `$(DEB_HOST_MULTIARCH)` 値として設定されます。例えば、マルチアーチライブラリーをインストールするパスは以下のように変更されます: [99]

旧パス | i386 マルチアーチパス | amd64 マルチアーチパス
--- | --- | ---
`/lib/` | `/lib/i386-linux-gnu/` | `/lib/x86_64-linux-gnu/`
`/usr/lib/` | `/usr/lib/i386-linux-gnu/` | `/usr/lib/x86_64-linux-gnu/`

以下の場合に関する典型的なパッケージ分割シナリオの例を示します。

- ライブラリーソース `lib`foo`-1.tar.gz`

- コンパイラー用の言語で書かれたツールのソース ``bar`-1.tar.gz`

- インタープリター用言語で書かれたツールのソース ``baz`-1.tar.gz`

パッケージ | Architecture: | Multi-Arch: | パッケージ内容
--- | --- | --- | ---
`lib`foo``1`` | any | same | 共有ライブラリー、同時インストール可能
`lib`foo``1`-dbg` | any | same | 共有ライブラリーデバッグシンボル、同時インストール可能
`lib`foo`-dev` | any | same | 共有ライブラリーヘッダーファイル他、同時インストール可能
`lib`foo`-tools` | any | foreign | 実行時サポートプログラム、同時インストール不可
`lib`foo`-doc` | all | foreign | 共有ライブラリーのドキュメンテーションファイル
``bar`` | any | foreign | コンパイルされ実行されるプログラムファイル、同時インストール不可
``bar`-doc` | all | foreign | プログラムのドキュメンテーションファイル
``baz`` | all | foreign | インタープリターで実行されるプログラムファイル

開発パッケージは関連した共有ライブラリーへのバージョン番号無しのシンボリックリンクを含んでいるべきです。例えば: `/usr/lib/x86_64-linux-gnu/libfoo.so` -> `libfoo.so.1`

## A.4. 共有ライブラリーパッケージのビルド

dh(1) を以下のように使えばマルチアーチをサポートするようにして Debian のライブラリーパッケージをビルドできます:

- `debian/control` を更新します。

  - ソースパッケージセクションに `Build-Depends: debhelper (>=10)` を追加します。

  - 共有ライブラリーのバイナリーパッケージごとに `Pre-Depends: ${misc:Pre-Depends}` を追加します。

  - `Multi-Arch:` スタンザを各バイナリーパッケージセクション毎に追加します。

- `debian/compat` を "10" と設定します。

- すべてのパッケージングスクリプトに関して、通常の `/usr/lib/` から、マルチアーチの `/usr/lib/$(DEB_HOST_MULTIARCH)/` へとパスを調整します。

  - 最初に `debian/rules` 中で `DEB_HOST_MULTIARCH ?= $(shell dpkg-architecture -qDEB_HOST_MULTIARCH)` を呼び `DEB_HOST_MULTIARCH` 変数を設定します。

  - `debian/rules` 中の `/usr/lib/` を `/usr/lib/$(DEB_HOST_MULTIARCH)/` で置き換えます。

  - もし `debian/rules` 中の `override_dh_auto_configure` ターゲットの一部分として `./configure` が用いられている場合には、それを `dh_auto_configure --` と置き換えるようにしましょう。[100]

  - `debian/`foo`.install` ファイル中にある全ての `/usr/lib/` を `/usr/lib/*/` で置き換えます。

  - `debian/rules` 中の `override_dh_auto_configure` ターゲットにスクリプトを追加し `debian/`foo`.links.in` から `debian/`foo`.links` を動的に生成します。

        override_dh_auto_configure:
                dh_auto_configure
                sed 's/@DEB_HOST_MULTIARCH@/$(DEB_HOST_MULTIARCH)/g' \
                        debian/foo.links.in > debian/foo.links

共有ライブラリーパッケージが期待されるファイルのみを含み、-dev パッケージも依然として動作することを確認しましょう。

マルチアーチパッケージとして同時に同一パスにインストールされる全てのファイルはファイルの内容が完全に同じあるべきです。データのバイトオーダーや圧縮アルゴリズムにより生成される相違に注意すべきです。

## A.5. ネイティブ Debian パッケージ

もしパッケージが Debian のためだけとか、またローカル使用のために保守されている場合、そのソースファイルは `debian/*` ファイルすべてをその中に含まれます。それをパッケージするのには2つの方法があります。

`debian/*` ファイルを除外したアップストリームターボールを作成し、「Debian パッケージビルドのワークフロー」 にあるようにしてノンネイティブ Debian パッケージできます。これが一部の人に推奨される通常の方法です。

この代わりの方法は、ネイティブ Debian パッケージのワークフローです。

- 全てのファイルが含まれる単一の圧縮された tar ファイルを用いる `3.0 (native)` フォーマットでネイティブの Debian ソースパッケージを作成します。

  - ``package`_`version`.tar.gz`
  - ``package`_`version`.dsc`

- ネイティブ Debian ソースパッケージから、Debian バイナリーパッケージをビルドします。

  - ``package`_`version`_`arch`.deb`

例えば `debian/*` ファイルを含まない `~/mypackage-1.0` ソースファイルがあれば、以下のように dh_make コマンドを用いてネイティブ Debian パッケージが作れます:

    $ cd ~/mypackage-1.0
    $ dh_make --native

すると、`debian` ディレクトリーとその内容は 「最初のノンネイティブ Debian パッケージ」 とちょうど同じように作成されます。これはネイティブ Debian パッケージなので tar アーカイブを作りません。しかし相違点はこれだけです。他のパッケージング操作は実質的にまったく同じです。

dpkg-buildpackage コマンドを実行した後、親ディレクトリーに以下のファイルが生成します:

- `mypackage_1.0.tar.gz`

  これは、dpkg-source コマンドにより `mypackage-1.0` ディレクトリーから作られたソースコードのターボールです。(そのサフィックスは `orig.tar.gz` ではありません。)

- `mypackage_1.0.dsc`

  これは、ノンネイティブ Debian パッケージと同様でソースコード内容の要約です。(Debian リビジョンはありません。)

- `mypackage_1.0_i386.deb`

  これは、ノンネイティブ Debian パッケージと同様で完成したバイナリーパッケージです。(Debian リビジョンはありません。)

- `mypackage_1.0_i386.changes`

  これは、ノンネイティブ Debian パッケージと同様で現パッケージバージョンでの全変更を記述します。(Debian リビジョンはありません。)

[87] もしくは: `readelf -d lib`foo`.so.`1` | grep SONAME`

[88] もしくは: `readelf -d lib`foo`.so.`1` | grep NEEDED`

[89] Debian Policy Manual, 8.1 "Run-time shared libraries" を参照下さい。

[90] Debian Policy Manual, 8.1.1 "ldconfig" を参照下さい。

[91] See Debian Policy Manual, 8.3 "Static libraries" and Debian Policy Manual, 8.4 "Development files" を参照下さい。

[92] Debian wiki ReleaseGoals/LAFileRemoval を参照下さい。

[93] Debian wiki RpathIssue を参照下さい。

[94] 後方非互換な ABI 変更をした場合、通常、ライブラリーの SONAME と共有ライブラリーパッケージ名を新規なものにそれぞれアップデートしないといけません。

[95] C++ ライブラリーや個別シンボルを追跡するのが非常に困難な他の場合には、これに代えて Debian Policy Manual, 8.6.4 "The shlibs system" に従いましょう。

[96] Debian パッケージの過去全てのバージョンは http://snapshot.debian.org/ から得られます。 パッケージのバックポートが楽にできるように Debian リビジョンはバージョンから取り除きます。: `1.1` << `1.1-1~bpo70+1` << `1.1-1` と `1.2` << `1.2-1~bpo70+1` << `1.2-1`

[97] Debian リビジョンはパッケージのバックポートを容易にすべく外します: `1.3` << `1.3-1~bpo70+1` << `1.3-1`

[98] Debian Policy Manual, 8.6.2 "Shared library ABI changes" を参照下さい。

[99] 旧来の `/lib32/` や `/lib64/` 等の特定目的のライブラリーパスは使われなくなっています。

[100] これに代えて、`./configure` に `--libdir=\$${prefix}/lib/$(DEB_HOST_MULTIARCH)` と `--libexecdir=\$${prefix}/lib/$(DEB_HOST_MULTIARCH)` 引数を追加することもできます。注意いただきたいのは、ユーザーではなく他のプログラムによりのみ実行される実行プログラムをインストールするデフォルトパスを `--libexecdir` は設定します。その Autotools のデフォルトは `/usr/libexec/` ですが、Debian デフォルトは `/usr/lib/` です。

第9章 パッケージをアップロードする |  |