When generating those files, it uses as input some symbols files provided by the maintainer. It looks for the following files (and use the first that is found):
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 him.
When the generated symbols files differ from the maintainer supplied one, dpkg-gensymbols will print a diff between the two versions. Furthermore if the difference are too significant, it will even fail (you can customize how much difference you can tolerate, see the -c option).
Before applying any patch to the symbols file, the maintainer should double-check that it's sane. Public symbols are not supposed to disappear, so the patch should ideally only add new lines.
In some rare cases, the name of the library varies between architectures. To avoid hardcoding the name of the package in the symbols file, you can use the marker #PACKAGE#. It will be replaced by the real package name during installation of the symbols files. Contrary to the #MINVER# marker, #PACKAGE# will never appear in a symbols file inside a binary 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 a 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.
Tag specification comes right before the symbol name (no whitespace is allowed in between). It always starts with an opening bracket (, ends with a closing bracket ) and must contain at least one tag. Multiple tags are separated by the | character. Each tag can optionally have a value which is separated form the tag name by the = character. Tag names and values can be arbitrary strings except they cannot contain any of the special ) | = characters. Symbol names following a tag specification can optionally be quoted with either ' or " characters to allow whitespaces in them. However, if there are no tags specified for the symbol, quotes are treated as part of the symbol name which continues up until the first space.
(tag1=i am marked|tag name with space)"tagged quoted symbol"@Base 1.0
(optional)[email protected] 1.0 1
[email protected] 1.0
The first symbol in the example is named tagged quoted symbol and has two tags: tag1 with value i am marked and tag name with space that has no value. The second symbol named tagged_unquoted_symbol is only tagged with the tag named optional. The last symbol is an example of the normal untagged symbol.
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 orignal form as they were loaded.
This tag is useful for symbols which are private where their disappearance do not cause ABI breakage. For example, most of C++ template instantiations fall into this category. Like any other tag, this one may also have an arbitrary value: it could be used to indicate why the symbol is considered optional.
When operating in the default non-template mode, among arch-specific symbols only those that match the current host architecture are written to the symbols file. On the contrary, all arch-specific symbols (including those from foreign arches) are always written to the symbol file when operating in template mode.
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, amd64 and ia64 architectures while the second one anywhere except on armel.
(arch=alpha amd64 ia64)[email protected] 1.0
(arch=!armel)[email protected] 1.0
When the set of exported symbols differ between architectures, it may become inefficient to use a single symbol file. In those cases, an include directive may prove to be useful in a couple of ways:
As a result, all symbols included from file_to_include will be considered to be tagged with tag .. tagN by default. You can use this feature to create a common package.symbols file which includes architecture specific symbol files:
[email protected] 1.0
(arch=amd64 ia64 alpha)#include "package.symbols.64bit"
(arch=!amd64 !ia64 !alpha)#include "package.symbols.32bit"
[email protected] 1.0
The symbols files are read line by line, and include directives are processed as soon as they are encountered. This means that the content of the included file can override any content that appeared before the include directive and that any content after the directive can override anything contained in the included file. Any symbol (or even another #include directive) in the included file can specify additional tags or override values of the inherited tags in its tag specification. However, there is no way for the symbol to remove any of the inherited tags.
An included file can repeat the header line containing the SONAME of the library. In that case, it overrides any header line previously read. However, in general it's best to avoid duplicating header lines. One way to do it is the following:
[email protected] 1.0
Well maintained libraries have versioned symbols where each version corresponds to the upstream version where the symbol got added. If that's the case, it's possible to write a symbols file with wildcard entries like "[email protected]_2.0" that would match any symbol associated to the version GLIBC_2.0. It's still possible to include specific symbols in the file, they'll take precedence over any matching wildcard entry. An example:
libc.so.6 libc6 #MINVER#
[email protected]_2.0 2.0
[email protected]_2.7 2.7
[email protected]_2.0 2.2
The symbol [email protected]_2.0 will lead to a minimal dependency on libc6 version 2.2 despite the wildcard entry [email protected]_2.0 which associates symbols versioned as GLIBC_2.0 with the minimal version 2.0.
Note that using wildcards means that dpkg-gensymbols can't check for symbols that might have disappeared and can't generate a diff between the maintainer-supplied symbols file and the generated one in the binary package.
A well-maintained library has the following features:
While maintaining the symbols file, it's easy to notice appearance and disappearance of symbols. But it's more difficult to catch incompatible API and ABI change. Thus the maintainer should read thoroughly the upstream changelog looking for cases where the rules of good library management have been broken. If potential problems are discovered, the upstream author should be notified as an upstream fix is always better than a Debian specific work-around.
This value can be overridden by the environment variable DPKG_GENSYMBOLS_CHECK_LEVEL.
This is free software; see the GNU General Public Licence version 2 or later for copying conditions. There is NO WARRANTY.