書式
dpkg-gensymbols [option...]説明
dpkg-gensymbols は一時的なビルドツリー (デフォルトでは debian/tmp) 以下にあるライブラリを探しだし、それらの情報を記載した symbols ファイルを生成する。このファイルが空でない場合、ファイルはビルドツリーの DEBIAN サブディレクトリにインストールされ、最終的にパッケージの制御情報ファイルに含まれる。これらのファイルの生成の際には、入力情報として、メンテナによって提供されるシンボルファイルが用いられる。シンボルファイルとして、以下のファイルが確認される (最初に見つかったファイルが用いられる):
- debian/package.symbols.arch
- debian/symbols.arch
- debian/package.symbols
- debian/symbols
The main interest of those files is to provide the minimal version associated to each symbol provided by the libraries. Usually it corresponds to the first version of that package that provided the symbol, but it can be manually incremented by the maintainer if the ABI of the symbol is extended without breaking backwards compatibility. It's the responsibility of the maintainer to keep those files up-to-date and accurate, but dpkg-gensymbols helps with that.
生成されたシンボルファイルがメンテナが提供するものと異なっていた場合、dpkg-gensymbols は双方の差分を表示する。相違点が大量の場合は、処理を失敗させる (どの程度の量を大量と見なすかについては調整可能である。-c オプションを参照のこと)。
シンボルファイルのメンテナンス
The symbols files are really useful only if they reflect the evolution of the package through several releases. Thus the maintainer has to update them every time that a new symbol is added so that its associated minimal version matches reality. The diffs contained in the build logs can be used as a starting point, but the maintainer, additionally, has to make sure that the behaviour of those symbols has not changed in a way that would make anything using those symbols and linking against the new version, stop working with the old version. In most cases, the diff applies directly to the debian/package.symbols file. That said, further tweaks are usually needed: it's recommended for example to drop the Debian revision from the minimal version so that backports with a lower version number but the same upstream version still satisfy the generated dependencies. If the Debian revision can't be dropped because the symbol really got added by the Debian specific change, then one should suffix the version with '~'.シンボルファイルに何らかのパッチを適用する前に、メンテナは本当にそれが必要かどうかを再度確認すること。公開シンボルが削除されることは想定されていないため、パッチは新しい行を追加するだけに留めるのが理想である。
Note that you can put comments in symbols files: any line with '#' as the first character is a comment except if it starts with '#include' (see section Using includes). Lines starting with '#MISSING:' are special comments documenting symbols that have disappeared.
Do not forget to check if old symbol versions need to be increased. There is no way dpkg-gensymbols can warn about this. Blindly applying the diff or assuming there is nothing to change if there is no diff, without checking for such changes, can lead to packages with loose dependencies that claim they can work with older packages they cannot work with. This will introduce hard to find bugs with (partial) upgrades.
#PACKAGE# 置換の使用
稀ではあるが、アーキテクチャによってライブラリ名が異なる場合がある。シンボルファイルにパッケージ名をハードコードすることを避けるため、#PACKAGE# マークを使用することができる。これはシンボルファイルのインストール時に実際のパッケージ名に置換される。#MINVER# マークと異なり、#PACKAGE# がバイナリパッケージ内のシンボルファイルに現れることは決してない。
シンボルタグの使用
Symbol tagging is useful for marking symbols that are special in some way. Any symbol can have an arbitrary number of tags associated with it. While all tags are parsed and stored, only some of them are understood by dpkg-gensymbols and trigger special handling of the symbols. See subsection Standard symbol tags for reference of these tags.
タグはシンボル名の前に設置され (空白文字を間にいれることはできない)、( から始まり) で終わり、間に最低 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 という名前のタグが設定されている。最後のシンボルは一般的なタグのないシンボルの例である。
Since symbol tags are an extension of the deb-symbols(5) format, they can only be part of the symbols files used in source packages (those files should then be seen as templates used to build the symbols files that are embedded in binary packages). When dpkg-gensymbols is called without the -t option, it will output symbols files compatible to the deb-symbols(5) format: it fully processes symbols according to the requirements of their standard tags and strips all tags from the output. On the contrary, in template mode (-t) all symbols and their tags (both standard and unknown ones) are kept in the output and are written in their original form as they were loaded.
標準シンボルタグ
- optional
-
A symbol marked as optional can disappear from the library at any time and
that will never cause dpkg-gensymbols to fail. However, disappeared
optional symbols will continuously appear as MISSING in the diff in each new
package revision. This behaviour serves as a reminder for the maintainer
that such a symbol needs to be removed from the symbol file or readded to
the library. When the optional symbol, which was previously declared as
MISSING, suddenly reappears in the next revision, it will be upgraded back
to the "existing" status with its minimum version unchanged.
このタグはシンボルの削除が ABI の互換性を損なわないようなプライベートなシンボルに有用である。例えば、C++ テンプレートのインスタンス化の多くがこれに分類される。その他のタグと同様、このタグには任意の値を設定することができる。これはシンボルが optional と見なされる理由を示すために使用することができる。
- arch=architecture-list
-
arch-bits=architecture-bits
arch-endian=architecture-endianness
These tags allow one to restrict the set of architectures where the symbol
is supposed to exist. The arch-bits and arch-endian tags are supported
since dpkg 1.18.0. When the symbols list is updated with the symbols
discovered in the library, all arch-specific symbols which do not concern
the current host architecture are treated as if they did not exist. If an
arch-specific symbol matching the current host architecture does not exist
in the library, normal procedures for missing symbols apply and it may cause
dpkg-gensymbols to fail. On the other hand, if the arch-specific symbol
is found when it was not supposed to exist (because the current host
architecture is not listed in the tag or does not match the endianness and
bits), it is made arch neutral (i.e. the arch, arch-bits and arch-endian
tags are dropped and the symbol will appear in the diff due to this change),
but it is not considered as new.
デフォルトの非テンプレートモードで動作する際には、アーキテクチャ固有のシンボルの中で、現在のホストのアーキテクチャに合致するもののみがシンボルファイルに書き込まれる。一方、テンプレートモードで動作している場合は、アーキテクチャ固有のシンボルのすべて (異なるアーキテクチャのものも含む) がシンボルファイルに書き込まれる。
The format of architecture-list is the same as the one used in the Build-Depends field of debian/control (except the enclosing square brackets []). For example, the first symbol from the list below will be considered only on alpha, any-amd64 and ia64 architectures, the second only on linux architectures, while the third one anywhere except on armel.
(arch=alpha any-amd64 ia64)64bit_specific_symbol@Base 1.0
(arch=linux-any)linux_specific_symbol@Base 1.0
(arch=!armel)symbol_armel_does_not_have@Base 1.0The architecture-bits is either 32 or 64.
(arch-bits=32)32bit_specific_symbol@Base 1.0
(arch-bits=64)64bit_specific_symbol@Base 1.0The architecture-endianness is either little or big.
(arch-endian=little)little_endian_specific_symbol@Base 1.0
(arch-endian=big)big_endian_specific_symbol@Base 1.0Multiple restrictions can be chained.
(arch-bits=32|arch-endian=little)32bit_le_symbol@Base 1.0 - ignore-blacklist
- dpkg-gensymbols は、ツールチェインの詳細な実装の副作用以外では通常存在しないため、シンボルファイル中に存在すべきではないシンボルからなる内部的なブラックリストを持っている。なんらかの理由により、シンボルファイルにこうしたシンボルの一つを本気で加えたい場合は、ignore-blacklist タグをシンボルに付ける必要がある。これは、 libgcc のような低レベルなツールチェインのライブラリの一部で必要な場合がある。
- c++
- c++ シンボルパターンを示す。以下の シンボルパターンの使用 サブセクションも参照のこと。
- symver
- symver (シンボルバージョン) シンボルパターンを示す。以下の シンボルパターンの使用 サブセクションも参照のこと。
- regex
- regex シンボルパターンを示す。以下の シンボルパターンの使用 サブセクションも参照のこと。
シンボルパターンの使用
標準シンボルと異なり、パターンにはライブラリがエクスポートする複数の実シンボルが含まれうる。dpkg-gensymbols は、シンボルファイルによって特定のシンボルと関連付けられていない各実シンボルについて、パターンとのマッチングを行う。最初にパターンにマッチした時点で、シンボルの基本的な機能として、パターンのタグおよび属性が用いられる。パターンにマッチしなかった場合、そのシンボルは新しいシンボルと見なされる。
A pattern is considered lost if it does not match any symbol in the library. By default this will trigger a dpkg-gensymbols failure under -c1 or higher level. However, if the failure is undesired, the pattern may be marked with the optional tag. Then if the pattern does not match anything, it will only appear in the diff as MISSING. Moreover, like any symbol, the pattern may be limited to the specific architectures with the arch tag. Please refer to Standard symbol tags subsection above for more information.
Patterns are an extension of the deb-symbols(5) format hence they are only valid in symbol file templates. Pattern specification syntax is not any different from the one of a specific symbol. However, symbol name part of the specification serves as an expression to be matched against name@version of the real symbol. In order to distinguish among different pattern types, a pattern will typically be tagged with a special tag.
現在のところ、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.2GLIBC_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.01 番目のパターンには、"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
- Only analyze libraries explicitly listed instead of finding all public libraries. You can use shell patterns used for pathname expansions (see the File::Glob(3perl) manual page for details) in library-file to match multiple libraries with a single argument (otherwise you need multiple -e).
- -Ifilename
- filename を、パッケージに同梱するシンボルファイルを生成する際のリファレンスファイルとして使用する。
- -O[filename]
- Print the generated symbols file to standard output or to filename if specified, rather than to debian/tmp/DEBIAN/symbols (or package-build-dir/DEBIAN/symbols if -P was used). If filename is pre-existing, its contents are used as basis for the generated symbols file. You can use this feature to update a symbols file so that it matches a newer upstream version of your library.
- -t
- Write the symbol file in template mode rather than the format compatible with deb-symbols(5). The main difference is that in the template mode symbol names and tags are written in their original form contrary to the post-processed symbol names with tags stripped in the compatibility mode. Moreover, some symbols might be omitted when writing a standard deb-symbols(5) file (according to the tag processing rules) while all symbols are always written to the symbol file template.
- -c[0-4]
-
生成されたシンボルファイルをベースとして用いたテンプレートファイルと比較する際のチェック項目を定義する。デフォルトのレベルは 1
である。レベルを上げるとより低いレベルのチェック項目すべてに加えて、より多くのチェックが行われる。レベル 0 を指定した場合、常に失敗しない。レベル 1
は、幾つかのシンボルが消失した場合に失敗となる。レベル 2 は新しいシンボルが出現しても失敗となる。レベル 3
はライブラリが消失すると失敗となる。レベル 4 はライブラリが出現した場合にも失敗となる。
This value can be overridden by the environment variable DPKG_GENSYMBOLS_CHECK_LEVEL.
- -q
- Keep quiet and never generate a diff between generated symbols file and the template file used as starting point or show any warnings about new/lost libraries or new/lost symbols. This option only disables informational output but not the checks themselves (see -c option).
- -aarch
- シンボルファイルの処理の際に、arch をホストのアーキテクチャと見なす。このオプションは、バイナリファイルが既に利用可能な場合に、シンボルファイルや差分情報を生成する際に使用する。
- -d
- デバッグモードを有効化する。dpkg-gensymbols の動作を示す大量のメッセージが表示される。
- -V
- 冗長モードを有効化する。生成されたシンボルファイルには、廃止されたシンボルがコメントとして残される。さらにテンプレートモードの場合、パターンシンボルについて、パターンとマッチした実シンボルの一覧もコメントとして残される。
- -?, --help
- 利用方法を表示して終了する。
- --version
- バージョン情報を表示して終了する。