Scroll to navigation

dpkg-gensymbols(1) dpkg ユーティリティ dpkg-gensymbols(1)

名前

dpkg-gensymbols - シンボルファイル (共有ライブラリの依存情報) の生成

書式

dpkg-gensymbols [option...]

説明

dpkg-gensymbols は一時的なビルドツリー (デフォルトでは debian/tmp) 以下にあるライブラリを探しだし、それらの情報を記載した symbols ファイルを生成する。このファイルが空でない場合、ファイルはビルドツリーの DEBIAN サブディレクトリにインストールされ、最終的にパッケージの制御情報ファイルに含まれる。
これらのファイルの生成の際には、入力情報として、メンテナによって提供されるシンボルファイルが用いられる。シンボルファイルとして、以下のファイルが確認される (最初に見つかったファイルが用いられる):
debian/package.symbols.arch
debian/symbols.arch
debian/package.symbols
debian/symbols
これらのファイルの主要な目的は、ライブラリが提供する各シンボルに対応づけられた最小バージョンの情報を提供することである。通常、これはシンボルを提供するパッケージの最初のバージョンに一致するが、シンボルの ABI が後方互換性を損なわずに拡張可能であれば、メンテナによって手動で増加させることも可能である。これらのファイルを更新して維持するのはメンテナの責任であるが、 dpkg-gensymbols も役に立つ。
生成されたシンボルファイルがメンテナが提供するものと異なっていた場合、 dpkg-gensymbols は双方の差分を表示する。相違点が大量の場合は、処理を失敗させる (どの程度の量を大量と見なすかについては調整可能である。 -c オプションを参照のこと)。

シンボルファイルのメンテナンス

シンボルファイルは、リリースを重ねることによるパッケージの進化に追従してこそ、はじめて有益なものとなる。つまり、メンテナは新しいシンボルが追加される度にファイルを更新し、これにより関連付けられた最小のバージョンを実態に即したものとする必要がある。この作業を適切に行うために、ビルドのログに含まれる差分情報を使用することができる。大半の場合、差分情報は直接 debian/ package.symbols ファイルに適用することができる。しかしながら、通常は更に細かい調整が必要となる。例えば最小バージョンから Debian リビジョンを削除することにより、アップストリームのバージョンが同一だが、バックポートにはより小さいバージョン番号が付与されているケースでも、生成された依存関係を満たすことができる。シンボルが Debian 固有の変更により追加されたものであり、Debian リビジョンを削除することができない場合は、バージョンに続く "~" の後に記載する。
シンボルファイルに何らかのパッチを適用する前に、メンテナは本当にそれが必要かどうかを再度確認すること。公開シンボルが削除されることは想定されていないため、パッチは新しい行を追加するだけに留めるのが理想である。
シンボルファイルにコメントを記載することもできる。'#' から始まる行は'#include' ( Using includes セクションを参照) から始まる場合をのぞき、コメントと見なされる。'#MISSING:' から始まる行は、なくなったシンボルについて記載された特別なコメントを意味する。

#PACKAGE# 置換の使用

稀ではあるが、アーキテクチャによってライブラリ名が異なる場合がある。シンボルファイルにパッケージ名をハードコードすることを避けるため、 #PACKAGE# マークを使用することができる。これはシンボルファイルのインストール時に実際のパッケージ名に置換される。 #MINVER# マークと異なり、 #PACKAGE# がバイナリパッケージ内のシンボルファイルに現れることは決してない。

シンボルタグの使用

シンボルタグは何らかの意味で特別なシンボルを識別する際に有用である。シンボルには任意の数のタグを関連付けることができる。すべてのタグが解析されて保存されるが、 dpkg-gensymbols が認識し、シンボルに対して特殊な扱いを行うものは、その一部のみである。これらのタグについての詳細は、 標準シンボルタグ サブセクションを参照のこと。
タグはシンボル名の前に設置され (空白文字を間にいれることはできない)、 ( から始まり) で終わり、間に最低 1 つのタグを記載する必要がある。複数のタグは | 文字で区切る。各タグには、タグ名との間を = 文字で区切った形式で値を設定することもできる。タグ名と値には、特別な文字 ) | = を除き、任意の文字を含めることができる。タグに続くシンボル名には、 ' もしくは " 文字でクオートすることで、空白文字を含めることができる。ただし、シンボルにタグが設定されていなかった場合、クオートはシンボル名の一部と見なされ、最初のスペースまでがシンボル名と認識される。

(tag1=i am marked|tag name with space)"tagged quoted symbol"@Base 1.0
(optional)tagged_unquoted_symbol@Base 1.0 1
untagged_symbol@Base 1.0
設定例の 1 番目のシンボルは tagged quoted symbol という名前であり、 i am marked という値を持つ tag1 というタグと tag name with space という値を持たないタグの 2 つが設定されている。2 番目のシンボルは tagged_unquoted_symbol という名前で optional という名前のタグが設定されている。最後のシンボルは一般的なタグのないシンボルの例である。
シンボルタグは deb-symbols(5) 形式の拡張であるため、これらは、ソースパッケージで用いられるシンボルファイルの一部分として扱う必要がある (これらのファイルはバイナリパッケージに埋め込まれるシンボルファイルをビルドするために使われるテンプレートとして扱われる)。 dpkg-gensymbols-t オプションなしで呼び出された場合は、 deb-symbols(5) 形式と互換性のあるシンボルファイルを出力する。標準タグの制約に則ってシンボルの処理を完全に行い、出力からすべてのタグを削除する。一方、テンプレートモード ( -t) の場合、シンボルのすべてとタグ (標準のものもそれ以外のものも) が出力でも保持され、読み取られた時の元々の形式で書き込まれる。

標準シンボルタグ

optional
optional とマークされたシンボルはいつでもライブラリから削除することができる。削除によって dpkg-gensymbols に失敗することは決してない。ただし、削除された optional のシンボルは、新しいパッケージのリビジョン各々において、差分情報内に MISSING として残り続ける。この挙動は、メンテナに対して、このシンボルをシンボルファイルから削除するか、再度ライブラリに追加する必要があることを通知するために行われる。以前に MISSING として宣言していた optional シンボルが突然次のリビジョンで復活した場合は、最小バージョンを変更せずに "existing" ステータスに戻される。
 
このタグはシンボルの削除が ABI の互換性を損なわないようなプライベートなシンボルに有用である。例えば、C++ テンプレートのインスタンス化の多くがこれに分類される。その他のタグと同様、このタグには任意の値を設定することができる。これはシンボルが optional と見なされる理由を示すために使用することができる。
arch=architecture list
このタグにより、シンボルが存在しているはずのアーキテクチャを限定することが可能になる。ライブラリで発見されたシンボルにより、シンボルのリストが更新された際にも、現在のホストのアーキテクチャに関連しないアーキテクチャに固有のシンボルは、存在していないものとして扱われる。現在のホストのアーキテクチャに関連するアーキテクチャに固有のシンボルがライブラリに存在していない場合は、シンボルが存在しない場合の通常の処理が行われ、おそらくは、dpkg-gensymbols の停止を引き起こすことになるだろう。一方、アーキテクチャ依存のシンボルが存在している場合に、存在しているはずだとされていない場合 (現在のホストのアーキテクチャがタグに記載されていない場合) は、アーキテクチャ非依存として扱われる (アーキテクチャのタグの削除という変更が行われるため、シンボルは差分情報として現れる) が、新しいシンボルとしては扱われない。
 
デフォルトの非テンプレートモードで動作する際には、アーキテクチャ固有のシンボルの中で、現在のホストのアーキテクチャに合致するもののみがシンボルファイルに書き込まれる。一方、テンプレートモードで動作している場合は、アーキテクチャ固有のシンボルのすべて (異なるアーキテクチャのものも含む) がシンボルファイルに書き込まれる。
 
architecture list の形式は、(ブラケット [] を除き) debian/control における Build-Depends フィールドと同じ書式である。下の例における、最初のシンボルは、alpha, any-amd64, ia64 アーキテクチャのいずれかであることを示し、2 番目は Linux アーキテクチャを、3 番目は armel 以外のすべてを示す。
 

(arch=alpha any-amd64 ia64)a_64bit_specific_symbol@Base 1.0
(arch=linux-any)linux_specific_symbol@Base 1.0
(arch=!armel)symbol_armel_does_not_have@Base 1.0
ignore-blacklist
dpkg-gensymbols は、ツールチェインの詳細な実装の副作用以外では通常存在しないため、シンボルファイル中に存在すべきではないシンボルからなる内部的なブラックリストを持っている。なんらかの理由により、シンボルファイルにこうしたシンボルの一つを本気で加えたい場合は、 ignore-blacklist タグをシンボルに付ける必要がある。これは、 libgcc のような低レベルなツールチェインのライブラリの一部で必要な場合がある。
c++
c++ シンボルパターンを示す。以下の シンボルパターンの使用 サブセクションも参照のこと。
symver
symver (シンボルバージョン) シンボルパターンを示す。以下の シンボルパターンの使用 サブセクションも参照のこと。
regex
regex シンボルパターンを示す。以下の シンボルパターンの使用 サブセクションも参照のこと。

シンボルパターンの使用

標準シンボルと異なり、パターンにはライブラリがエクスポートする複数の実シンボルが含まれうる。 dpkg-gensymbols は、シンボルファイルによって特定のシンボルと関連付けられて いない各実シンボルについて、パターンとのマッチングを行う。最初にパターンにマッチした時点で、シンボルの基本的な機能として、パターンのタグおよび属性が用いられる。パターンにマッチしなかった場合、そのシンボルは新しいシンボルと見なされる。
 
ライブラリ内のシンボルと一切マッチしなかったパターンは、消失したと見なされる。これは、 -c1 以上のレベルを指定していた場合、デフォルトで dpkg-gensymbols の停止を引き起こす。停止させたくない場合は、パターンに optional タグを付加することもできる。その場合、パターンが一切マッチしなかった場合でも、差分情報で MISSING 扱いとなるだけになる。また、他のシンボルと同様、パターンに対しても arch タグにより対象のアーキテクチャを限定することが可能である。これに関する詳細な情報は、前述の 標準シンボルタグ サブセクションを参照のこと。
 
パターンは deb-symbols(5) を拡張した形式であるため、シンボルファイルのテンプレートでのみ有効である。パターン定義の文法はシンボル定義のものとまったく変わらない。ただし、シンボル名の部分は、実シンボルの name@version 部分にマッチするような表現になっている。パターンのタイプを判別するために、通常パターンには特別なタグが付けられている。
 
現在のところ、 dpkg-gensymbols は 3 つの基本的なパターンタイプをサポートしている:
c++
このパターンは c++ タグを示す。これは ( c++filt(1) ユーティリティによって出力された) デコードされた (demangled) シンボル名による C++ シンボルにのみマッチする。このパターンは、デコードされた名前は同一であるが、エンコードされたシンボル名がアーキテクチャによってばらばらであるようなシンボルにマッチさせたい場合に非常に有用である。こうしたシンボルの一つのグループが、 non-virtual thunks と呼ばれるもので、エンコードされた名前にアーキテクチャ依存のオフセットが埋め込まれるシンボルである。このパターンの実例として、ダイアモンド継承において、仮想継承でないサンクシンボルを必要とする仮想デストラクタが挙げられる。32 ビットアーキテクチャ上で _ZThn8_N3NSB6ClassDD1Ev@Base となるシンボルが 64 ビットでは _ZThn16_N3NSB6ClassDD1Ev@Base となってしまう場合であっても、これらを単一の c++ パターンでマッチさせることができる。
libdummy.so.1 libdummy1 #MINVER#
[...]
(c++)"non-virtual thunk to NSB::ClassD::~ClassD()@Base" 1.0
[...]
上記のデコードされた名前は、以下のコマンドを実行することで取得できる:

$ echo '_ZThn8_N3NSB6ClassDD1Ev@Base' | c++filt
エンコードされた名前がライブラリ内で一意に定義されていた場合であっても、デコードされた名前が一位である必要はない。幾つかの実シンボルのデコードされた名前が同じである場合もある。これは、例えば仮想継承でないサンクシンボルに複雑な継承の設定が行われている場合や、大半のコンストラクタとデストラクタについて言える (ただし、g++ は、これらに対して通常 2 つの実シンボルを生成する)。ただし、こうした衝突は ABI レベルで発生しているものであり、シンボルファイルの品質を低下させるものではない。
symver
このパターンは、symver タグを示す。きちんとメンテナンスされているライブラリでは、シンボルがバージョン管理されており、各バージョンがシンボルの追加されたアップストリームのバージョンに対応付けられている。この場合、 symver パターンを使用することで、特定のバージョンに対応付けられた任意のシンボルにマッチさせることが可能である。以下に例を示す:
libc.so.6 libc6 #MINVER#
(symver)GLIBC_2.0 2.0
[...]
(symver)GLIBC_2.7 2.7
access@GLIBC_2.0 2.2
GLIBC_2.0 および GLIBC_2.7 のバージョンに対応付けられたすべてのシンボルは、access@GLIBC_2.0 シンボルを除き、最低バージョンが各々 2.0 および 2.7 となる。後者は、"(symver)GLIBC_2.0" パターンにマッチするが、libc6 バージョン 2.2 が最低限の依存関係となる。これは、シンボルの指定がパターンによるマッチより優先されるためである。
古い形式のワイルドカードのパターン (シンボル名フィールドで "*@version" を指定) は、"(symver|optional)version" は、まだサポートされているが、廃止予定となっている点に留意すること。例えば、"*@GLIBC_2.0 2.0" という表記は、同じ動作をさせたいのであれば、"(symver|optional)GLIBC_2.0 2.0" に修正すべきである。
regex
正規表現パターンは regex タグで指定される。これは、シンボル名フィールドで指定された perl 形式の正規表現にマッチする。正規表現であるため、 ^ 文字から始めることを忘れないこと、さもなくば、実シンボル name@version の任意の部分にマッチする可能性がある。以下に例を示す:
libdummy.so.1 libdummy1 #MINVER#
(regex)"^mystack_.*@Base$" 1.0
(regex|optional)"private" 1.0
1 番目のパターンには、"mystack_new@Base", "mystack_push@Base", "mystack_pop@Base" のようなシンボルがマッチするが、"ng_mystack_new@Base" はマッチしない。2 番目のパターンには、"private" という文字列を含む名前のすべてのシンボルにマッチし、マッチしたシンボル名が optional タグに引き継がれる。
前述した基本的なパターンは、整合性がとれる限り複合して用いてもよい。その場合、パターンはタグで指定された順に処理される。以下の例において、

(c++|regex)"^NSA::ClassA::Private::privmethod\d\(int\)@Base" 1.0
(regex|c++)N3NSA6ClassA7Private11privmethod\dEi@Base 1.0
両方のパターンとも、"_ZN3NSA6ClassA7Private11privmethod1Ei@Base" シンボルと "_ZN3NSA6ClassA7Private11privmethod2Ei@Base" シンボルにマッチする。1 番目のパターンでは、本来のシンボル名が 1 番目に C++ シンボルにデコードされ、デコードされたシンボル名を用いて正規表現によりマッチが行われる。一方、2 番目のパターンにマッチした場合、正規表現が本来のシンボル名にマッチし、その後そのシンボル名がデコードされた上で、C++ シンボル名として評価される。いずれかの基本パターンのマッチングに失敗すると、全体が失敗と見なされる。そのため、例えば "__N3NSA6ClassA7Private11privmethod\dEi@Base" は、正しい C++ シンボルでないため、どちらのパターンにもマッチしないと見なされる。
一般的に、すべてのパターンはエイリアス (基本的な c++symver) と汎用パターン ( regex および任意の基本パターンの組み合わせ) という 2 つのグループに大別される。基本的なエイリアスベースのパターンに対するマッチングは (O(1)) であるため高速であるが、汎用パターンは各シンボルに対して O(N) (N - 汎用的なパターンの数) となる。そのため、汎用パターンを多用しすぎないことを推奨する。
組み合わせのパターンが同じ実シンボルにマッチした場合、エイリアス ( c++symver の順) が汎用パターンよりも優先される。汎用パターンは、マッチングに成功するまで、シンボルファイルのテンプレートに記載された順にマッチングを試みる。ただし、テンプレートファイルのエントリに記載された順序を手作業で修正することは推奨されない。これは、 dpkg-gensymbols が差分を生成する際に、名前が英数字順になっていることを前提としているためである。

include の使用

エクスポートされた一連のシンボルがアーキテクチャにより異なっている場合、単一のシンボルファイルでは不便な場合がある。その場合、include ディレクティブにより、以下のような方法で、利便性を向上させることができる場合もある:
外出ししたファイルの共通部分を取り出した上で、include ディレクティブを次にように用いて、該当ファイルを package.symbols.arch ファイルに挿入する:
 
#include " packages.symbols.common"
include ディレクティブには、他のシンボル同様タグを付加してもよい:
 
(tag|..|tagN)#include "file-to-include"
 
結果として、 file-to-include から挿入されるすべてのシンボルが tag ... tagN にデフォルトでタグづけされたと見なされる。この機能を用いて、以下のように共通の package.symbols ファイルを作成した上で、それをアーキテクチャ固有のシンボルファイルに挿入することもできる:
 

common_symbol1@Base 1.0
(arch=amd64 ia64 alpha)#include "package.symbols.64bit"
(arch=!amd64 !ia64 !alpha)#include "package.symbols.32bit"
common_symbol2@Base 1.0
シンボルファイルは 1 行ずつ読み取られ、include ディレクティブがあれば、都度処理される。つまり、挿入されるファイルの設定で include ディレクティブの前に存在していた設定が上書きされる可能性もあり、include ディレクティブの後に存在している設定により、挿入されたファイルの設定が上書きされることもある。挿入されるファイルに存在する任意のシンボル (別の #include ディレクティブを含む) では、新しいタグを追加することも、継承されたタグの値を上書きすることもできるが、シンボルから継承されたタグを削除することはできない。
挿入されたファイルで、ライブラリの SONAME を含むヘッダ行を繰り返すことも可能である。その場合、そこまで読み込んだヘッダ行はすべて上書きされる。ただし、一般的に、ヘッダ行の重複は避けるべきである。これを避ける方法の一つを以下に示す:
#include "libsomething1.symbols.common"
arch_specific_symbol@Base 1.0

推奨されるライブラリ管理

適切に維持されているライブラリの特徴を以下に示す:
API の変更がなく (公開シンボルの消失は一切なく、新しい公開シンボルが追加されるのみである)、SONAME の変更以外に互換性を損なう API の変更が行われない。
理想的には、ABI の安定性を維持するため、内部的な変更と API の拡張を除いてシンボルのバージョン管理が行われている。
非公開シンボルをエクスポートしない (そうしたシンボルは暫定で optional のタグづけをしておくこともできる)。
シンボルファイルをメンテナンスする上で、追加されたり削除されたりしたシンボルを把握することは難しくないが、互換性のない API や ABI の変更を把握するのは難しい。メンテナにはアップストリームの changelog を読み込んで、推奨されるライブラリ管理のルールが守られていない点を探しだすことが求められる。潜在的な問題が発見されたら、アップストリームの開発者に通知すること。Debian 独自の暫定対処よりも、アップストリーム側での修正が常に望ましい。

オプション

-Ppackage-build-dir
debian/tmp の代わりに package-build-dir 内を確認する。
-ppackage
パッケージ名を定義する。debian/control ファイルに複数のバイナリパッケージが記載されている (もしくは debian/control ファイルが存在しない) 場合は必須である。
-vversion
パッケージのバージョンを定義する。デフォルトは debian/changelog から取得されたバージョンが用いられる。ソースパッケージツリー以外で呼び出された際は必須である。
-elibrary-file
すべての公開されているライブラリを探索する代わりに、明示的に指定されたライブラリのみを探索する。library-file に、パス名の展開に使用されるシェルのパターンマッチングを指定することで (詳細は File::Glob マニュアルページを参照のこと) 、単一の設定で複数のライブラリをマッチさせることもできる (さもなくば -e を複数回指定する必要がある)。
-Ifilename
filename を、パッケージに同梱するシンボルファイルを生成する際のリファレンスファイルとして使用する。
-O
生成されたシンボルファイルをパッケージビルドツリーに保存する代わりに標準出力に出力する。
-Ofilename
生成されたシンボルファイルを filename として保存する。 filename があらかじめ存在している場合、その内容は生成されるシンボルファイルの元として使われる。この機能を用いてシンボルファイルを更新することで、ライブラリを新しいアップストリームのバージョンに対応させることができる。
-t
シンボルファイルを deb-symbols(5) と互換性のある形式ではなく、テンプレートモードで保存する。両者の主な違いは、テンプレートモードではシンボル名とタグの両方がオリジナルの形式のまま書き出されるのに対し、互換モードでは、処理済みのシンボル名のみが書き出され、タグは削除される点である。さらに、テンプレートモードでは、すべてのシンボルが常にシンボルファイルのテンプレートに書き込まれるのに対し、互換モードでは、シンボルの一部が標準の deb-symbols(5) ファイルに書き出される際に削除される場合がある (タグの処理ルールによる)。
-c[0-4]
生成されたシンボルファイルをベースとして用いたテンプレートファイルと比較する際のチェック項目を定義する。デフォルトのレベルは 1 である。レベルを上げるとより低いレベルのチェック項目すべてに加えて、より多くのチェックが行われる。レベル 0 を指定した場合、常に失敗しない。レベル 1 は、幾つかのシンボルが消失した場合に失敗となる。レベル 2 は新しいシンボルが出現しても失敗となる。レベル 3 はライブラリが消失すると失敗となる。レベル 4 はライブラリが出現した場合にも失敗となる。
 
この値は、環境変数 DPKG_GENSYMBOLS_CHECK_LEVEL により上書きすることができる。
-q
出力を抑止し、生成されたシンボルファイルとベースとなったテンプレートファイルとの差分を生成せず、新規の、もしくは消失したライブラリや、新規の、もしくは消失したシンボルに関する警告も表示しない。このオプションは情報の出力を抑止するのみであり、チェック自体は行われる ( -c オプションも参照のこと)。
-aarch
シンボルファイルの処理の際に、arch をホストのアーキテクチャと見なす。このオプションは、バイナリファイルが既に利用可能な場合に、シンボルファイルや差分情報を生成する際に使用する。
-d
デバッグモードを有効化する。dpkg-gensymbols の動作を示す大量のメッセージが表示される。
-V
冗長モードを有効化する。生成されたシンボルファイルには、廃止されたシンボルがコメントとして残される。さらにテンプレートモードの場合、パターンシンボルについて、パターンとマッチした実シンボルの一覧もコメントとして残される。
-?, --help
利用方法を表示して終了する。
--version
バージョン情報を表示して終了する。

関連項目

http://people.redhat.com/drepper/symbol-versioning
 
http://people.redhat.com/drepper/goodpractice.pdf
 
http://people.redhat.com/drepper/dsohowto.pdf
 
deb-symbols(5), dpkg-shlibdeps(1).

翻訳者

高橋 基信 <monyo@monyo.com>. 喜瀬 浩 <kise@fuyuneko.jp>. 関戸 幸一 <sekido@mbox.kyoto-inet.or.jp>. 鍋谷 栄展 <nabe@debian.or.jp>. 倉澤 望 <nabetaro@debian.or.jp>. 石川 睦 <ishikawa@linux.or.jp>. 鵜飼 文敏 <ukai@debian.or.jp>. 中野 武雄 <nakano@apm.seikei.ac.jp>.

翻訳校正

Debian JP Documentation ML <debian-doc@debian.or.jp>.
2012-04-22 Debian Project