[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#571776: document symbols



Here is a new proposed patch that incorporates the feedback to date with
some other, substantial changes.

It's apparent to me from hands-on experimentation with C++ libraries that,
at least at the moment, shlibs is likely to have an ongoing existence in
the archive.  Accordingly, some of the layout decisions I made to keep the
shlibs section separate in a way that would let it potentially be dropped
later weren't a good idea.  This version therefore substantially
reorganizes and somewhat expands the documentation to:

* Describe the difference between symbols and shlibs in more detail and
  provide advice on how to choose between them.

* Document calling dpkg-shlibdeps in a separate section independent of
  either symbols or shlibs, since the details of how to use it doesn't
  vary based on the dependency system in play.

* Provide separate documentation for how to handle ABI changes and
  determine dependency versions independent of either system, since the
  same process should be used either way.  The only difference between the
  systems is whether the version information is per-symbol or per-library.

* Move the symbols and shlibs documentation to subsections of the general
  section on shared library dependency management.

* Move the information on how to determine the soversion out of the shlibs
  section and to the runtime shared library section so that it is next to
  the discussion of shared library package names.  The shlibs
  documentation now just references it.

Due to the reformatting, the diff is even longer and is now really just
the complete removal of the current shlibs section followed by the
addition of the new section.  I'm therefore including here the complete
SGML source of that section not in diff format, followed by the diff of
everything *outside* of that section.  I think this will be easier to
review.

      <sect id="sharedlibs-depends">
	<heading>Dependencies between the library and other
	  packages</heading>

	<p>
	  If a package contains a binary or library which links to a
	  shared library, we must ensure that, when the package is
	  installed on the system, all of the libraries needed are also
	  installed.  These dependencies must be added to the binary
	  package when it is built, since they may change based on which
	  version of a shared library the binary or library was linked
	  with even if there are no changes to the source of the binary
	  (for example, symbol versions change, macros become functions or
	  vice versa, or the binary package may determine at compile-time
	  whether new library interfaces are available and can be called).
	  To allow these dependencies to be constructed, shared libraries
	  must provide either a <file>symbols</file> file or
	  a <file>shlibs</file> file, which provide information on the
	  package dependencies required to ensure the presence of this
	  library.  Any package which uses a shared library must use these
	  files to determine the required dependencies when it is built.
	</p>

	<p>
	  These two mechanisms differ in the degree of detail that they
	  provide.  A <file>symbols</file> file documents every symbol
	  that is part of the library ABI and, for each, the version of
	  the package in which it was introduced.  This permits detailed
	  analysis of the symbols used by a particular package and
	  construction of an accurate dependency, but it requires the
	  package maintainer to track more information about the shared
	  library.  A <file>shlibs</file> file, in contrast, only
	  documents the last time the library ABI changed in any way.  It
	  only provides information about the library as a whole, not
	  individual symbols.  When a package is built using a shared
	  library with only a <file>shlibs</file> file, the generated
	  dependency will require a version of the shared library equal to
	  or newer than the version of the last ABI change.  This
	  generates unnecessarily restrictive dependencies compared
	  to <file>symbols</file> files if none of the symbols used by the
	  package have changed.  This, in turn, may make upgrades
	  needlessly complex and unnecessarily restrict use of the package
	  on systems with older versions of the shared libraries.
	</p>

	<p>
	  <file>shlibs<file> files also have a flawed representation of
	  library SONAMEs, making it difficult to use <file>shlibs</file>
	  files in some unusual corner cases.
	</p>

	<p>
	  <file>symbols</file> files are therefore recommended for most
	  shared library packages since they provide more accurate
	  dependencies.  For most C libraries, the additional detail
	  required by <file>symbols</file> files is not too difficult to
	  maintain.  However, maintaining exhaustive symbols information
	  for a C++ library can be quite onerous, so <file>shlibs</file>
	  files may be more appropriate for most C++ libraries.  udebs
	  must also use <file>shlibs</file>, since the udeb infrastructure
	  does not use <file>symbols</file>.
	</p>

	<sect1 id="dpkg-shlibdeps">
	  <heading>Generating dependencies on shared libraries</heading>

	  <p>
	    When a package that contains any shared libraries or compiled
	    binaries is built, it must run <prgn>dpkg-shlibdeps</prgn> on
	    each shared library and compiled binary to determine the
	    libraries used and hence the dependencies needed by the
	    package.<footnote>
	      <prgn>dpkg-shlibdeps</prgn> will use a program
	      like <prgn>objdump</prgn> or <prgn>readelf</prgn> to find
	      the libraries and the symbols in those libraries directly
	      needed by the binaries or shared libraries in the package.
	    </footnote>
	    To do this, put a call to <prgn>dpkg-shlibdeps</prgn> into
	    your <file>debian/rules</file> file in the source package.
	    List all of the compiled binaries, libraries, or loadable
	    modules in your package.<footnote>
	      The easiest way to call <prgn>dpkg-shlibdeps</prgn>
	      correctly is to use a package helper framework such
	      as <package>debhelper</package>.  If you are
	      using <package>debhelper</package>,
	      the <prgn>dh_shlibdeps</prgn> program will do this work for
	      you.  It will also correctly handle multi-binary packages.
	    </footnote>
	    <prgn>dpkg-shlibdeps</prgn> will use the <file>symbols</file>
	    or <file>shlibs</file> files installed by the shared libraries
	    to generate dependency information.  The package must then
	    provide a substitution variable into which the discovered
	    dependency information can be placed.
	  </p>

	  <p>
	    If you are creating a udeb for use in the Debian Installer,
	    you will need to specify that <prgn>dpkg-shlibdeps</prgn>
	    should use the dependency line of type <tt>udeb</tt> by adding
	    the <tt>-tudeb</tt> option<footnote>
	      <prgn>dh_shlibdeps</prgn> from the <tt>debhelper</tt> suite
	      will automatically add this option if it knows it is
	      processing a udeb.
	    </footnote>. If there is no dependency line of
	    type <tt>udeb</tt> in the <file>shlibs</file>
	    file, <prgn>dpkg-shlibdeps</prgn> will fall back to the
	    regular dependency line.
	  </p>

	  <p>
	    <prgn>dpkg-shlibdeps</prgn> puts the dependency information
	    into the <file>debian/substvars</file> file by default, which
	    is then used by <prgn>dpkg-gencontrol</prgn>.  You will need
	    to place a <tt>${shlibs:Depends}</tt> variable in
	    the <tt>Depends</tt> field in the control file of every binary
	    package built by this source package that contains compiled
	    binaries, libraries, or loadable modules.  If you have
	    multiple binary packages, you will need to
	    call <prgn>dpkg-shlibdeps</prgn> on each one which contains
	    compiled libraries or binaries, using the <tt>-T</tt> option
	    to the <tt>dpkg</tt> utilities to specify a
	    different <file>substvars</file> file for each binary
	    package.<footnote>
	      Again, <prgn>dh_shlibdeps</prgn>
	      and <prgn>dh_gencontrol</prgn> will handle everything except
	      the addition of the variable to the control file for you if
	      you're using <package>debhelper</package>, including
	      generating separate <file>substvars</file> files for each
	      binary package and calling <prgn>dpkg-gencontrol</prgn> with
	      the appropriate flags.
	    </footnote>
	  </p>

	  <p>
	    For more details on <prgn>dpkg-shlibdeps</prgn>,
	    see <manref name="dpkg-shlibdeps" section="1">.
	  </p>

	  <p>
	    We say that a binary <tt>foo</tt> <em>directly</em> uses a
	    library <tt>libbar</tt> if it is explicitly linked with that
	    library (that is, the library is listed in the
	    ELF <tt>NEEDED</tt> attribute, caused by adding <tt>-lbar</tt>
	    to the link line when the binary is created).  Other libraries
	    that are needed by <tt>libbar</tt> are
	    linked <em>indirectly</em> to <tt>foo</tt>, and the dynamic
	    linker will load them automatically when it
	    loads <tt>libbar</tt>.  A package should depend on the
	    libraries it directly uses, but not the libraries it
	    indirectly uses.  The dependencies for the libraries used
	    directly will automatically pull in the indirectly-used
	    libraries.  <prgn>dpkg-shlibdeps</prgn> will handle this logic
	    automatically, but package maintainers need to be aware of
	    this distinction between directly and indirectly using a
	    library if they have to override its results for some reason.
	    <footnote>
	      A good example of where this helps is the following.  We
	      could update <tt>libimlib</tt> with a new version that
	      supports a new revision of a graphics format called dgf (but
	      retaining the same major version number) and depends on a
	      new library package <package>libdgf4</package> instead of
	      the older <package>libdgf3</package>.  If we
	      used <prgn>ldd</prgn> to add dependencies for every library
	      directly or indirectly linked with a binary, every package
	      that uses <tt>libimlib</tt> would need to be recompiled so
	      it would also depend on <package>libdgf4</package> in order
	      to retire the older <package>libdgf3</package> package.
	      Since dependencies are only added based on
	      ELF <tt>NEEDED</tt> attribute, packages
	      using <tt>libimlib</tt> can rely on <tt>libimlib</tt> itself
	      having the dependency on an appropriate version
	      of <tt>libdgf</tt> and do not need rebuilding.
	    </footnote>
	  </p>
	</sect1>

	<sect1 id="sharedlibs-updates">
	  <heading>Shared library ABI changes</heading>

	  <p>
	    Maintaining a shared library package using
	    either <file>symbols</file> or <file>shlibs</file> files
	    requires being aware of the exposed ABI of the shared library
	    and any changes to it.  Both <file>symbols</file>
	    and <file>shlibs</file> files record every change to the ABI
	    of the shared library; <file>symbols</file> files do so per
	    public symbol, whereas <file>shlibs</file> files record only
	    the last change for the entire library.
	  </p>

	  <p>
	    There are two types of ABI changes: ones that are
	    backward-compatible and ones that are not.  An ABI change is
	    backward-compatible if any binary was linked with the previous
	    version of the shared library will still work correctly with
	    the new version of the shared library.  Adding new symbols to
	    the shared library is a backward-compatible change.  Removing
	    symbols from the shared library is not.  Changing the behavior
	    of a symbol may or may not be backward-compatible depending on
	    the change; for example, changing a function to accept a new
	    enum constant not previously used by the library is generally
	    backward-compatible, but changing the members of a struct that
	    is passed into library functions is generally not unless the
	    library takes special precautions to accept old versions of
	    the data structure.
	  </p>

	  <p>
	    ABI changes that are not backward-compatible normally require
	    changing the <tt>SONAME</tt> of the library and therefore the
	    shared library package name, which forces rebuilding all
	    packages using that shared library to update their
	    dependencies and allow them to use the new version of the
	    shared library.  For more information,
	    see <ref id="sharedlibs-runtime">.  The remainder of this
	    section will deal with backward-compatible changes.
	  </p>

	  <p>
	    Backward-compatible changes require either updating or
	    recording the <var>minimal-version</var> for that symbol
	    in <file>symbols</file> files or updating the version in
	    the <var>dependencies</var> in <file>shlibs</file> files.  For
	    more information on how to do this in the two formats, see
	    <ref id="symbols"> and <ref id="shlibs">.  Below are general
	    rules that apply to both files.
	  </p>

	  <p>
	    The easy case is when a public symbol is added.  Simply add
	    the version at which the symbol was introduced
	    (for <file>symbols</file> files) or update the dependency
	    version (for <file>shlibs</file>) files.  But special care
	    should be taken to update dependency versions when the
	    behavior of a public symbol changes.  This is easy to neglect,
	    since there is no automated method of determining such
	    changes, but failing to update versions in this case may
	    result in binary packages with too-weak dependencies that will
	    fail at runtime, possibly in ways that can cause security
	    vulnerabilities.  If the package maintainer believes that a
	    symbol behavior change may have occurred but isn't sure, it's
	    safer to update the version rather than leave it unmodified.
	    This may result in unnecessarily strict dependencies, but it
	    ensures that packages whose dependencies are satisfied will
	    work properly.
	  </p>

	  <p>
	    A common example of when a change to the is required is a
	    function that takes an enum or struct argument that controls
	    what the function does.  For example:
	    <example>
	      enum library_op { OP_FOO, OP_BAR };
	      int library_do_operation(enum library_op);
	    </example>
	    If a new operation, <tt>OP_BAZ</tt>, is added,
	    the <var>minimal-version</var>
	    of <tt>library_do_operation</tt> (for <file>symbols</file>
	    files) or the version in the dependency for the shared library
	    (for <file>shlibs</file> files) must be increased to the
	    version at which <tt>OP_BAZ</tt> was introduced.  Otherwise, a
	    binary built against the new version of the library (having
	    detected at compile-time that the library
	    supports <tt>OP_BAZ</tt>) may be installed with a shared
	    library that doesn't support <tt>OP_BAZ</tt> and will fail at
	    runtime when it tries to pass <tt>OP_BAZ</tt> into this
	    function.
	  </p>

	  <p>
	    Dependency versions in either <file>symbols</file>
	    or <file>shlibs</file> files normally should not contain the
	    Debian revision of the package, since the library behavior is
	    normally fixed for a particular upstream version and any
	    Debian packaging of that upstream version will have the same
	    behavior.  In the rare case that the library behavior was
	    changed in a particular Debian revision, appending <tt>~</tt>
	    to the end of the version that includes the Debian revision is
	    recommended, since this allows backports of the shared library
	    package using the normal backport versioning convention to
	    satisfy the dependency.
	  </p>
	</sect1>

	<sect1 id="sharedlibs-symbols">
	  <heading>The <tt>symbols</tt> system</heading>

	  <p>
	    In the following sections, we will first describe where the
	    various <file>symbols</file> files are to be found, then
	    the <file>symbols</file> file format, and finally how to
	    create <file>symbols</file> files if your package contains a
	    shared library.
	  </p>

	  <sect2 id="symbols-paths">
	    <heading>The <file>symbols</file> files present on the
	      system</heading>

	    <p>
	      <file>symbols</file> files for a shared library are normally
	      provided by the shared library package, but there are
	      several override paths that are checked first in case that
	      information is wrong or missing.  The following list gives
	      them in the order in which they are read
	      by <prgn>dpkg-shlibdeps</prgn> The first one that contains
	      the required information is used.
	      <list>
		<item>
		  <p><file>debian/*/DEBIAN/symbols</file></p>

		  <p>
		    During the package build, if the package itself
		    contains shared libraries with <file>symbols</file>
		    files, they will be generated in these staging
		    directories by <prgn>dpkg-gensymbols</prgn>
		    (see <ref id="providing-symbols">).  <file>symbols</file>
		    files found in the build tree take precedence
		    over <file>symbols</file> files from other binary
		    packages.
		  </p>

		  <p>
		    These files must exist
		    before <prgn>dpkg-shlibdeps</prgn> is run or the
		    dependencies of binaries and libraries from a source
		    package on other libraries from that same source
		    package will not be correct.  In practice, this means
		    that <prgn>dpkg-gensymbols</prgn> must be run
		    before <prgn>dpkg-shlibdeps</prgn> during the package
		    build.<footnote>
		      An example may clarify.  Suppose the source
		      package <tt>foo</tt> generates two binary
		      packages, <tt>libfoo2</tt> and <tt>foo-runtime</tt>.
		      When building the binary packages, the contents of
		      the packages are staged in the
		      directories <file>debian/libfoo2</file>
		      and <file>debian/foo-runtime</file> respectively.
		      (<file>debian/tmp</file> could be used instead of
		      one of these.)  Since <tt>libfoo2</tt> provides
		      the <tt>libfoo</tt> shared library, it will contain
		      a <tt>symbols</tt> file, which will be installed
		      in <file>debian/libfoo2/DEBIAN/symbols</file>,
		      eventually to be included as a control file in that
		      package.  When <prgn>dpkg-shlibdeps</prgn> is run on
		      the
		      executable <file>debian/foo-runtime/usr/bin/foo-prog</file>,
		      it will examine
		      the <file>debian/libfoo2/DEBIAN/symbols</file> file
		      to determine whether <tt>foo-prog</tt>'s library
		      dependencies are satisfied by any of the libraries
		      provided by <tt>libfoo2</tt>.  Since those binaries
		      were linked against the just-built shared library as
		      part of the build process, the <file>symbols</file>
		      file for the newly-built <tt>libfoo2</tt> must take
		      precedence over a <file>symbols</file> file for any
		      other <tt>libfoo2</tt> package already installed on
		      the system.
		    </footnote>
		  </p>
		</item>

		<item>
		  <p>
		    <file>/etc/dpkg/symbols/<var>package</var>.symbols.<var>arch</var></file>
		    and <file>/etc/dpkg/symbols/<var>package</var>.symbols</file>
		  </p>

		  <p>
		    Per-system overrides of shared library dependencies.
		    These files normally do not exist.  They are
		    maintained by the local system administrator and must
		    not be created by any Debian package.
		  </p>
		</item>

		<item>
		  <p><file>symbols</file> control files for packages
		    installed on the system</p>

		  <p>
		    The <file>symbols</file> control files for all the
		    packages currently installed on the system are
		    searched last.  This will be the most common source of
		    shared library dependency information.  These are
		    normally found
		    in <file>/var/lib/dpkg/info/*.symbols</file>, but
		    packages should not rely on this and instead should
		    use <tt>dpkg-query --control-path <var>package</var>
		    symbols</tt> if for some reason these files need to be
		    examined.
		  </p>
		</item>
	      </list>
	    </p>

	    <p>
	      Be aware that if a <file>debian/shlibs.local</file> exists
	      in the source package, it will override
	      any <file>symbols</file> files.  This is the only case where
	      a <file>shlibs</file> is used despite <file>symbols</file>
	      files being present.  See <ref id="shlibs-paths">
	      and <ref id="sharedlibs-shlibdeps"> for more information.
	    </p>
	  </sect2>

	  <sect2 id="symbols">
	    <heading>The <file>symbols</file> File Format</heading>

	    <p>
	      The following documents the format of
	      the <file>symbols</file> control file as included in binary
	      packages.  These files are built from
	      template <file>symbols</file> files in the source package
	      by <prgn>dpkg-gensymbols</prgn>.  The template files support
	      a richer syntax that allows <prgn>dpkg-gensymbols</prgn> to
	      do some of the tedious work involved in
	      maintaining <file>symbols</file> files, such as handling C++
	      symbols or optional symbols that may not exist on particular
	      architectures.  When writing <file>symbols</file> files for
	      a shared library package, refer
	      to <manref name="dpkg-gensymbols" section="1"> for the
	      richer syntax.
	    </p>

	    <p>
	      A <file>symbols</file> may contain one or more entries, one
	      for each shared library contained in the package
	      corresponding to that <file>symbols</file>.  Each entry has
	      the following format:
	    </p>

	    <p>
	      <example>
		<var>library-soname</var> <var>main-dependency-template</var>
		[| <var>alternative-dependency-template</var>]
		[...]
		[* <var>field-name</var>: <var>field-value</var>]
		[...]
		<var>symbol</var> <var>minimal-version</var>[ <var>id-of-dependency-template</var> ]
	      </example>
	    </p>

	    <p>
	      To explain this format, we'll use the the <tt>zlib1g</tt>
	      package as an example, which (at the time of writing)
	      installs the shared
	      library <file>/usr/lib/libz.so.1.2.3.4</file>.  Mandatory
	      lines will be described first, followed by optional lines.
	    </p>

	    <p>
	      <var>library-soname</var> must contain exactly the value of
	      the ELF <tt>SONAME</tt> attribute of the shared library.  In
	      our example, this is <tt>libz.so.1</tt>.<footnote>
		This can be determined by using the command
		<example compact="compact">
		  readelf -d /usr/lib/libz.so.1.2.3.4 | grep SONAME
		</example>
	      </footnote>
	    </p>

	    <p>
	      <var>main-dependency-template</var> has the same syntax as a
	      dependency field in a binary package control file, except
	      that the string <tt>#MINVER#</tt> is replaced by a version
	      restriction like <tt>(>= <var>version</var>)</tt> or by
	      nothing if an unversioned dependency is deemed sufficient.
	      The version restriction will be based on which symbols from
	      the shared library are referenced and the version at which
	      they were introduced (see below).  In nearly all
	      cases, <var>main-dependency-template</var> will
	      be <tt><var>package</var> #MINVER#</tt>,
	      where <var>package</var> is the name of the binary package
	      containing the shared library.  This adds a simple,
	      possibly-versioned dependency on the shared library package.
	      In some rare cases, such as when multiple packages provide
	      the same shared library ABI, the dependency template may
	      need to be more complex.
	    </p>

	    <p>
	      In our example, the first line of
	      the <tt>zlib1g</tt> <file>symbols</file> file would be:
	      <example compact="compact">
		libz.so.1 zlib1g #MINVER#
	      </example>
	    </p>

	    <p>
	      Each public symbol exported by the shared library must have
	      a corresponding symbol line, indented by one
	      space.  <var>symbol</var> is the exported symbol (which, for
	      C++, means the mangled symbol) followed by <tt>@</tt> and
	      the symbol version, or the string <tt>Base</tt> if there is
	      no symbol version.  <var>minimal-version</var> is the most
	      recent version of the shared library that changed the
	      behavior of that symbol, whether by adding it, changing its
	      function signature (the parameters, their types, or the
	      return type), or its behavior in a way that is visible to a
	      caller.  <var>id-of-dependency-template</var> is an optional
	      field that references
	      an <var>alternative-dependency-template</var>; see below for
	      a full description.
	    </p>

	    <p>
	      For example, <tt>libz.so.1</tt> contains the
	      symbols <tt>compress</tt>
	      and <tt>compressBound</tt>.  <tt>compress</tt> has no symbol
	      version and last changed its behavior in upstream
	      version <tt>1:1.1.4</tt>.  <tt>compressBound</tt> has the
	      symbol version <tt>ZLIB_1.2.0</tt>, was introduced in
	      upstream version <tt>1:1.2.0</tt>, and has not changed its
	      behavior.  Its <file>symbols</file> file therefore contains
	      the lines:
	      <example compact="compact">
		compress@Base 1:1.1.4
		compressBound@ZLIB_1.2.0 1:1.2.0
	      </example>
	      Packages using only <tt>compress</tt> would then get a
	      dependency of <tt>zlib1g (>= 1:1.1.4)</tt>, but packages
	      using <tt>compressBound</tt> would get a dependency
	      of <tt>zlib1g (>= 1:1.2.0)</tt>.
	    </p>

	    <p>
	      One or more <var>alternative-dependency-template</var> lines
	      may be provided.  These are used in cases where some symbols
	      in the shared library should use one dependency template
	      while others should use a different template.  The
	      alternative dependency templates are used only if a symbol
	      line contains the <var>id-of-dependency-template</var>
	      field.  The first alternative dependency template is
	      numbered 1, the second 2, and so forth.<footnote>
		An example of where this may be needed is with a library
		that implements the libGL interface.  All GL
		implementations provide the same set of base interfaces,
		and then may provide some additional interfaces only used
		by programs that require that specific GL implementation.
		So, for example, libgl1-mesa-glx may use the
		following <file>symbols</file> file:
		<example>
		  libGL.so.1 libgl1
		  | libgl1-mesa-glx #MINVER#
		  publicGlSymbol@Base 6.3-1
		  [...]
		  implementationSpecificSymbol@Base 6.5.2-7 1
		  [...]
		</example>
		Binaries or shared libraries using
		only <tt>publicGlSymbol</tt> would depend only
		on <tt>libgl1</tt> (which may be provided by multiple
		packages), but ones
		using <tt>implementationSpecificSymbol</tt> would get a
		dependency on <tt>libgl1-mesa-glx (>= 6.5.2-7)</tt>
	      </footnote>
	    </p>

	    <p>
	      Finally, the entry for the library may contain one or more
	      metadata fields.  Currently, the only
	      supported <var>field-name</var>
	      is <tt>Build-Depends-Package</tt>, whose value lists
	      the <qref id="sharedlibs-dev">library development
	      package</qref> on which packages using this shared library
	      declare a build dependency.  If this field is
	      present, <prgn>dpkg-shlibdeps</prgn> uses it to ensure that
	      the resulting binary package dependency on the shared
	      library is at least as strict as the source package
	      dependency on the shared library development
	      package.<footnote>
		This field should normally not be necessary, since if the
		behavior of any symbol has changed, the corresponding
		symbol <var>minimal-version</var> should have been
		increased.  But including it makes the <tt>symbols</tt>
		system more robust by tightening the dependency in cases
		where the package using the shared library specifically
		requires at least a particular version of the shared
		library development package for some reason.
	      </footnote>
	      For our example, the <tt>zlib1g</tt> <file>symbols</file>
	      file would contain:
	      <example compact="compact">
		* Build-Depends-Package: zlib1g-dev
	      </example>
	    </p>

	    <p>
	      Also see <manref name="deb-symbols" section="5">.
	    </p>
	  </sect2>

	  <sect2 id="providing-symbols">
	    <heading>Providing a <file>symbols</file> file</heading>

	    <p>
	      If your package provides a shared library, you should
	      arrange to include a <file>symbols</file> control file
	      following the format described above in that package.  You
	      must include either a <file>symbols</file> control file or
	      a <file>shlibs</file> control file.
	    </p>

	    <p>
	      Normally, this is done by creating a <file>symbols</file> in
	      the source package
	      named <file>debian/<var>package</var>.symbols</file>
	      or <file>debian/symbols</file>, possibly
	      with <file>.<var>arch</var></file> appended if the symbols
	      information varies by architecture.  This file may use the
	      extended syntax documented in <manref name="dpkg-gensymbols"
	      section="1">.  Then, call <prgn>dpkg-gensymbols</prgn> as
	      part of the package build process.  It will
	      create <file>symbols</file> files in the package staging
	      area based on the binaries and libraries in the package
	      staging area and the <file>symbols</file> files in the
	      source package.<footnote>
		If you are
		using <tt>debhelper</tt>, <prgn>dh_makeshlibs</prgn> will
		take care of calling either <prgn>dpkg-gensymbols</prgn>
		or generating a <file>shlibs</file> file as appropriate.
	      </footnote>
	    </p>

	    <p>
	      Packages that provide <file>symbols</file> files must keep
	      them up-to-date to ensure correct dependencies in packages
	      that use the shared libraries.  This means updating
	      the <file>symbols</file> file whenever a new public symbol
	      is added, changing the <var>minimal-version</var> field
	      whenever a symbol changes behavior or signature in a
	      backward-compatible way (see <ref id="sharedlibs-updates">),
	      and changing the <var>library-soname</var>
	      and <var>main-dependency-template</var>, and probably all of
	      the <var>minimal-version</var> fields, when the library
	      changes <tt>SONAME</tt>.  Removing a public symbol from
	      the <file>symbols</file> file because it's no longer
	      provided by the library normally requires changing
	      the <tt>SONAME</tt> of the library.
	      See <ref id="sharedlibs-runtime"> for more information
	      on <tt>SONAME</tt>s.
	    </p>
	  </sect2>
	</sect1>

	<sect1 id="sharedlibs-shlibdeps">
	  <heading>The <tt>shlibs</tt> system</heading>

	  <p>
	    The <tt>shlibs</tt> system is an simpler alternative to
	    the <tt>symbols</tt> system for declaring dependencies for
	    shared libraries.  It may be more appropriate for C++
	    libraries and other cases where tracking individual symbols is
	    too difficult.  It predated the <tt>symbols</tt> system and is
	    therefore frequently seen in older packages.  It is also
	    required for udebs, which do not support <tt>symbols</tt>.
	  </p>

	  <p>
	    In the following sections, we will first describe where the
	    various <file>shlibs</file> files are to be found, then how to
	    use <prgn>dpkg-shlibdeps</prgn>, and finally
	    the <file>shlibs</file> file format and how to create them.
	  </p>

	  <sect2 id="shlibs-paths">
	    <heading>The <file>shlibs</file> files present on the
	      system</heading>

	    <p>
	      There are several places where <tt>shlibs</tt> files are
	      found.  The following list gives them in the order in which
	      they are read by <prgn>dpkg-shlibdeps</prgn>.  (The first
	      one which gives the required information is used.)
	      <list>
		<item>
		  <p><file>debian/shlibs.local</file></p>

		  <p>
		    This lists overrides for this package.  This file
		    should normally not be used, but may be needed
		    temporarily in unusual situations to work around bugs
		    in other packages, or in unusual cases where the
		    normally declared dependency information in the
		    installed <file>shlibs</file> file for a library
		    cannot be used.  This file overrides information
		    obtained from any other source.
		  </p>
		</item>

		<item>
		  <p><file>/etc/dpkg/shlibs.override</file></p>

		  <p>
		    This lists global overrides.  This list is normally
		    empty.  It is maintained by the local system
		    administrator.
		  </p>
		</item>

		<item>
		  <p><file>DEBIAN/shlibs</file> files in the "build
		    directory"</p>

		  <p>
		    These files are generated as part of the package build
		    process and staged for inclusion as control files in
		    the binary packages being built.  They provide details
		    of any shared libraries included in the same package.
		  </p>
		</item>

		<item>
		  <p><file>shlibs</file> control files for packages
		    installed on the system</p>

		  <p>
		    The <file>shlibs</file> control files for all the
		    packages currently installed on the system.  These are
		    normally found
		    in <file>/var/lib/dpkg/info/*.symbols</file>, but
		    packages should not rely on this and instead should
		    use <tt>dpkg-query --control-path <var>package</var>
		    shlibs</tt> if for some reason these files need to be
		    examined.
		  </p>
		</item>

		<item>
		  <p><file>/etc/dpkg/shlibs.default</file></p>

		  <p>
		    This file lists any shared libraries whose packages
		    have failed to provide correct <file>shlibs</file>
		    files.  It was used when the <file>shlibs</file> setup
		    was first introduced, but it is now normally empty.
		    It is maintained by the <tt>dpkg</tt> maintainer.
		  </p>
		</item>
	      </list>
	    </p>

	    <p>
	      If a <file>symbols</file> file for a shared library package
	      is available, <prgn>dpkg-shlibdeps</prgn> will always use it
	      in preference to a <file>shlibs</file>, with the exception
	      of <file>debian/shlibs.local</file>.  The latter overrides
	      any other <file>shlibs</file> or <file>symbols</file> files.
	    </p>
	  </sect2>

	  <sect2 id="shlibs">
	    <heading>The <file>shlibs</file> File Format</heading>

	    <p>
	      Each <file>shlibs</file> file has the same format.  Lines
	      beginning with <tt>#</tt> are considered to be comments and
	      are ignored.  Each line is of the form:
	      <example compact="compact">
		[<var>type</var>: ]<var>library-name</var> <var>soname-version</var> <var>dependencies ...</var>
	      </example>
	    </p>

	    <p>
	      We will explain this by reference to the example of the
	      <tt>zlib1g</tt> package, which (at the time of writing)
	      installs the shared
	      library <file>/usr/lib/libz.so.1.2.3.4</file>.
	    </p>

	    <p>
	      <var>type</var> is an optional element that indicates the
	      type of package for which the line is valid. The only type
	      currently in use is <tt>udeb</tt>.  The colon and space
	      after the type are required.
	    </p>

	    <p>
	      <var>library-name</var> is the name of the shared library,
	      in this case <tt>libz</tt>.  (This must match the name part
	      of the soname, see below.)
	    </p>

	    <p>
	      <var>soname-version</var> is the version part of the
	      ELF <tt>SONAME</tt> attribute of the library, determined the
	      same way that the <var>soversion</var> component of the
	      recommended shared library package name is determined.
	      See <ref id="sharedlibs-runtime"> for the details.
	    </p>

	    <p>
	      <var>dependencies</var> has the same syntax as a dependency
	      field in a binary package control file.  It should give
	      details of which packages are required to satisfy a binary
	      built against the version of the library contained in the
	      package.  See <ref id="depsyntax"> for details on the
	      syntax, and <ref id="sharedlibs-updates"> for details on how
	      to maintain the dependency version constraint.
	    </p>

	    <p>
	      In our example, if the last change to the <tt>zlib1g</tt>
	      package that could change behavior for a client of that
	      library was in version <tt>1:1.2.3.3.dfsg-1</tt>, then
	      the <tt>shlibs</tt> entry for this library could say:
	      <example compact="compact">
		libz 1 zlib1g (>= 1:1.2.3.3.dfsg-1)
	      </example>
	      This version restriction must be new enough that any binary
	      built against the current version of the library will work
	      with any version of the shared library that satisfies that
	      dependency.
	    </p>

	    <p>
	      As zlib1g also provides a udeb containing the shared
	      library, there would also be a second line:
	      <example compact="compact">
		udeb: libz 1 zlib1g-udeb (>= 1:1.2.3.3.dfsg-1)
	      </example>
	    </p>
	  </sect2>

	  <sect2>
	    <heading>Providing a <file>shlibs</file> file</heading>

	    <p>
	      To provide a <file>shlibs</file> file for a shared library
	      binary package, create a <file>shlibs</file> file following
	      the format described above and place it in
	      the <file>DEBIAN</file> directory for that package during
	      the build.  It will then be included as a control file for
	      that package<footnote>
		This is what <prgn>dh_makeshlibs</prgn> in
		the <package>debhelper</package> suite does. If your
		package also has a udeb that provides a shared
		library, <prgn>dh_makeshlibs</prgn> can automatically
		generate the <tt>udeb:</tt> lines if you specify the name
		of the udeb with the <tt>--add-udeb</tt> option.
	      </footnote>.
	    </p>

	    <p>
	      Since <prgn>dpkg-shlibdeps</prgn> reads
	      the <file>DEBIAN/shlibs</file> files in all of the binary
	      packages being built from this source package, all of
	      the <file>DEBIAN/shlibs</file> files should be installed
	      before <prgn>dpkg-shlibdeps</prgn> is called on any of the
	      binary packages.
	    </p>
	  </sect2>
	</sect1>
      </sect>

diff --git a/policy.sgml b/policy.sgml
index 1a61d4f..57caf5d 100644
--- a/policy.sgml
+++ b/policy.sgml
@@ -848,10 +848,11 @@
 	Among those files are the package maintainer scripts
 	and <file>control</file>, the <qref id="binarycontrolfiles">binary
 	package control file</qref> that contains the control fields for
-	the package.  Other control information files
-	include <qref id="sharedlibs-shlibdeps">the <file>shlibs</file>
-	file</qref> used to store shared library dependency information
-	and the <file>conffiles</file> file that lists the package's
+	the package.  Other control information files include
+	the <qref id="sharedlibs-symbols"><file>symbols</file> file</qref>
+	or <qref id="sharedlibs-shlibdeps"><file>shlibs</file> file</qref>
+	used to store shared library dependency information and
+	the <file>conffiles</file> file that lists the package's
 	configuration files (described in <ref id="config-files">).
       </p>
 
@@ -5493,17 +5494,29 @@ Replaces: mail-transport-agent
 	  be placed in a package named
 	  <package><var>libraryname</var><var>soversion</var></package>,
 	  where <var>soversion</var> is the version number in
-	  the <tt>SONAME</tt> of the shared library.
-	  See <ref id="shlibs"> for detailed information on how to
-	  determine this version.  Alternatively, if it would be confusing
-	  to directly append <var>soversion</var>
-	  to <var>libraryname</var> (if, for example, <var>libraryname</var>
-	  itself ends in a number), you should use
+	  the <tt>SONAME</tt> of the shared library.  Alternatively, if it
+	  would be confusing to directly append <var>soversion</var>
+	  to <var>libraryname</var> (if, for
+	  example, <var>libraryname</var> itself ends in a number), you
+	  should use
 	  <package><var>libraryname</var>-<var>soversion</var></package>
 	  instead.
 	</p>
 
 	<p>
+	  To determine the <var>soversion</var>, look at
+	  the <tt>SONAME</tt> of the library, stored in the
+	  ELF <tt>SONAME</tt> attribute.  it is usually of the
+	  form <tt><var>name</var>.so.<var>major-version</var></tt> (for
+	  example, <tt>libz.so.1</tt>).  The version part is the part
+	  which comes after <tt>.so.</tt>, so in that example it
+	  is <tt>1</tt>.  The soname may instead be of the
+	  form <tt><var>name</var>-<var>major-version</var>.so</tt>, such
+	  as <tt>libdb-5.1.so</tt>, in which case the name would
+	  be <tt>libdb</tt> and the version would be <tt>5.1</tt>.
+	</p>
+
+	<p>
 	  If you have several shared libraries built from the same source
 	  tree, you may lump them all together into a single shared
 	  library package provided that all of their <tt>SONAME</tt>s will
@@ -5538,9 +5551,8 @@ Replaces: mail-transport-agent
 	  linked against the old shared library.  Correct versioning of
 	  dependencies on the newer shared library by binaries that use
 	  the new interfaces is handled via
-	  the <qref id="sharedlibs-shlibdeps"><tt>shlibs</tt>
-	  system</qref> or via symbols files (see
-	  <manref name="deb-symbols" section="5">).
+	  the <qref id="sharedlibs-depends"><tt>symbols</tt>
+	  or <tt>shlibs</tt> system</qref>.
 	</p>
 
       <p>
@@ -7760,8 +8271,9 @@ INSTALL = install -s # (or use strip on the files in debian/tmp)
           Although not enforced by the build tools, shared libraries
           must be linked against all libraries that they use symbols from
           in the same way that binaries are.  This ensures the correct
-          functioning of the <qref id="sharedlibs-shlibdeps">shlibs</qref>
-          system and guarantees that all libraries can be safely opened
+          functioning of the <qref id="sharedlibs-symbols">symbols</qref>
+          and <qref id="sharedlibs-shlibdeps">shlibs</qref>
+          systems and guarantees that all libraries can be safely opened
           with <tt>dlopen()</tt>.  Packagers may wish to use the gcc
           option <tt>-Wl,-z,defs</tt> when building a shared library.
           Since this option enforces symbol resolution at build time,
@@ -10569,82 +11081,10 @@ END-INFO-DIR-ENTRY
 	  </heading>
 
 	  <p>
-	    This program is usually called from <file>debian/rules</file>
-	    just before <prgn>dpkg-gencontrol</prgn> (see <ref
-	    id="pkg-sourcetree">), in the top level of the source tree.
-	  </p>
-
-	  <p>
-	    Its arguments are executables and shared libraries
-	    <footnote>
-	      <p>
-		They may be specified either in the locations in the
-		source tree where they are created or in the locations
-		in the temporary build tree where they are installed
-		prior to binary package creation.
-	      </p>
-	    </footnote> for which shared library dependencies should
-	    be included in the binary package's control file.
-	  </p>
-
-	  <p>
-	    If some of the found shared libraries should only
-	    warrant a <tt>Recommends</tt> or <tt>Suggests</tt>, or if
-	    some warrant a <tt>Pre-Depends</tt>, this can be achieved
-	    by using the <tt>-d<var>dependency-field</var></tt> option
-	    before those executable(s).  (Each <tt>-d</tt> option
-	    takes effect until the next <tt>-d</tt>.)
-	  </p>
-
-	  <p>
-	    <prgn>dpkg-shlibdeps</prgn> does not directly cause the
-	    output control file to be modified.  Instead by default it
-	    adds to the <file>debian/substvars</file> file variable
-	    settings like <tt>shlibs:Depends</tt>.  These variable
-	    settings must be referenced in dependency fields in the
-	    appropriate per-binary-package sections of the source
-	    control file.
-	  </p>
-
-	  <p>
-	    For example, a package that generates an essential part
-	    which requires dependencies, and optional parts that 
-	    which only require a recommendation, would separate those
-	    two sets of dependencies into two different fields.<footnote>
-		At the time of writing, an example for this was the
-		<package/xmms/ package, with Depends used for the xmms
-		executable, Recommends for the plug-ins and Suggests for
-		even more optional features provided by unzip.
-	    </footnote>
-            It can say in its <file>debian/rules</file>:
-	    <example>
-  dpkg-shlibdeps -dDepends <var>program anotherprogram ...</var> \
-                 -dRecommends <var>optionalpart anotheroptionalpart</var>
-	    </example>
-	    and then in its main control file <file>debian/control</file>:
-	    <example>
-  <var>...</var>
-  Depends: ${shlibs:Depends}
-  Recommends: ${shlibs:Recommends}
-  <var>...</var>
-	    </example>
-	  </p>
-
-	  <p>
-	    Sources which produce several binary packages with
-	    different shared library dependency requirements can use
-	    the <tt>-p<var>varnameprefix</var></tt> option to override
-	    the default <tt>shlibs:</tt> prefix (one invocation of
-	    <prgn>dpkg-shlibdeps</prgn> per setting of this option).
-	    They can thus produce several sets of dependency
-	    variables, each of the form
-	    <tt><var>varnameprefix</var>:<var>dependencyfield</var></tt>,
-	    which can be referred to in the appropriate parts of the
-	    binary package control files.
+	    See <manref name="dpkg-shlibdeps" section="1">.
 	  </p>
 	</sect1>
 
-
 	<sect1 id="pkg-dpkg-distaddfile">
 	  <heading>
 	    <prgn>dpkg-distaddfile</prgn> - adds a file to

-- 
Russ Allbery (rra@debian.org)               <http://www.eyrie.org/~eagle/>



Reply to: