Bug#509933: versioning SONAMEs of shared libraries is not clearly recommended
Russ Allbery <rra@debian.org> writes:
> I read through the shared library sections of Policy a few times last
> night and can't find anywhere where Policy unambiguously recommends
> always including a version in SONAME for public libraries. If you don't
> have a version, you can't represent the library in the shlibs format, so
> there's an implicit recommendation, but I think it would be better to
> make it explicit.
There was a lot of background information missing from Policy, which in my
opinion made it unnecessarily difficult to understand the motivation and
implications of the various Policy requirements. Here's a first draft of
a patch to add much more information about how shared libraries work,
better motivate the requirements already present (and tighten some of the
language), and add a should-level requirement to change the SONAME if the
library ABI changes.
Objections, sections, or other review?
diff --git a/policy.sgml b/policy.sgml
index 7736ddb..2d535d3 100644
--- a/policy.sgml
+++ b/policy.sgml
@@ -5106,55 +5106,138 @@ Replaces: mail-transport-agent
</p>
<p>
- Packages involving shared libraries should be split up into
- several binary packages. This section mostly deals with how
- this separation is to be accomplished; rules for files within
- the shared library packages are in <ref id="libraries"> instead.
+ This section deals only with public shared libraries: shared
+ libraries that are placed in directories searched by the dynamic
+ linker by default or which are intended to be linked against
+ normally and possibly used by other, independent packages. Shared
+ libraries that are internal to a particular package or that are
+ only loaded as dynamic modules are not covered by this section and
+ are not subject to its requirements.
</p>
- <sect id="sharedlibs-runtime">
- <heading>Run-time shared libraries</heading>
+ <p>
+ A shared library must be uniquely identified by an <tt>SONAME</tt>
+ attribute stored in its dynamic section. When a binary is linked
+ against a shared library, the <tt>SONAME</tt> of the shared
+ library is recorded in the binary's <tt>NEEDED</tt> section so
+ that the dynamic linker knows that library must be loaded at
+ runtime. The full name of the shared library (which usually
+ contains additional version information not needed in
+ the <tt>SONAME</tt> is therefore not referenced directly.
+ Instead, the shared library is loaded by its <tt>SONAME</tt>,
+ which exists on the file system as a symlink pointing to the full
+ name of the shared library.<footnote>
+ Some unusual libraries have an <tt>SONAME</tt> which matches the
+ full library name, but normally there is a minor revision that
+ changes even though the ABI has not changed in a
+ backward-incompatible way. The <tt>SONAME</tt> only changes
+ when binaries linked with the earlier version of the shared
+ library may no longer work. See <ref id="sharedlibs-runtime">
+ for more information.
+ </footnote>
+ This symlink is updated and its location cached
+ by <prgn>ldconfig</prgn>, but must also be created by the
+ package. <ref id="sharedlibs-runtime"> describes how to do this.
+ </p>
<p>
- The run-time shared library needs to be placed in a package
- whose name changes whenever the shared object version
- changes.<footnote>
- <p>
- Since it is common place to install several versions of a
- package that just provides shared libraries, it is a
- good idea that the library package should not
- contain any extraneous non-versioned files, unless they
- happen to be in versioned directories.</p>
- </footnote>
- The most common mechanism is to place it in a package
- called
- <package><var>libraryname</var><var>soversion</var></package>,
- where <file><var>soversion</var></file> is the version number
- in the soname of the shared library<footnote>
- The soname is the shared object name: it's the thing
- that has to match exactly between building an executable
- and running it for the dynamic linker to be able run the
- program. For example, if the soname of the library is
- <file>libfoo.so.6</file>, the library package would be
- called <file>libfoo6</file>.
- </footnote>.
- Alternatively, if it would be confusing to directly append
- <var>soversion</var> to <var>libraryname</var> (e.g. because
- <var>libraryname</var> itself ends in a number), you may use
- <package><var>libraryname</var>-<var>soversion</var></package> and
- <package><var>libraryname</var>-<var>soversion</var>-dev</package>
- instead.
+ When linking a binary or another shared library against a shared
+ library, the <tt>SONAME</tt> for that shared library is not yet
+ known. Instead, the shared library is found by library name
+ with <tt>.so</tt> appended. This file exists on the file system
+ as a symlink pointing to the shared library.<footnote>
+ Some shared libraries have no version information in
+ their <tt>SONAME</tt> and therefore need no symlink since the
+ file found when linking is the same as the library name. This
+ is highly unusual, however, and means the shared library cannot
+ be versioned. It is used only for very special situations where
+ the shared library provides a tiny set of symbols and must not
+ be versioned for some reason.
+ </footnote>
+ </p>
+
+ <p>
+ Shared libraries are normally split into several binary packages.
+ The <tt>SONAME</tt> symlink is installed by the runtime shared
+ library package, and the bare <tt>.so</tt> symlink is installed in
+ the development package since it's only used when linking binaries
+ or shared libraries. However, there are some exceptions for
+ unusual shared libraries or for shared libraries that are also
+ loaded as dynamic modules by other programs.
</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 you change all of
- their sonames at once (so that you don't get filename
- clashes if you try to install different versions of the
- combined shared libraries package).
+ This section is primarily concerned with how the separation of
+ shared libraries into multiple packages should be done and how
+ dependencies on and between shared library binary packages are
+ managed in Debian. <ref id="libraries"> should be read in
+ conjunction with this section and contains additional rules for
+ the files contained in the shared library packages.
</p>
+ <sect id="sharedlibs-runtime">
+ <heading>Run-time shared libraries</heading>
+
+ <p>
+ The run-time shared library must be placed in a package
+ whose name changes whenever the <tt>SONAME</tt> of the shared
+ library changes. This allows several versions of the shared
+ library to be installed at the same time, allowing installation
+ of the new version of the shared library without immediately
+ breaking binaries that depend on the old version. Normally, the
+ run-time shared library and its <tt>SONAME</tt> symlink should
+ 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
+ <package><var>libraryname</var>-<var>soversion</var></package>
+ instead.
+ </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
+ always change together. Be aware that this is not normally the
+ case, and if the <tt>SONAME</tt>s do not change together,
+ upgrading such a merged shared library package will be
+ unnecessarily difficult because of file conflicts with the old
+ version of the package. When in doubt, always split shared
+ library packages so that each binary package installs a single
+ shared library.
+ </p>
+
+ <p>
+ Every time the shared library ABI changes in a way that may
+ break binaries linked against older versions of the shared
+ library, the <tt>SONAME</tt> of the library and the
+ corresponding name for the binary package containing the runtime
+ shared library should change. Normally, this means
+ the <tt>SONAME</tt> must change any time an interface is removed
+ from the shared library or the signature of an interface (the
+ number of parameters or the types of parameters that it takes,
+ for example) is changed. This practice is vital to allowing
+ clean upgrades from older versions of the package and clean
+ transitions between the old ABI and new ABI without having to
+ upgrade every affected package simultaneously.
+ </p>
+
+ <p>
+ The <tt>SONAME</tt> and binary package name need not, and indeed
+ normally should not, change if new interfaces are added but none
+ are removed or changed, since this will not break binaries
+ 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>shilbs</tt>
+ system</qref>.
+ </p>
+
<p>
The package should install the shared libraries under
their normal names. For example, the <package>libgdbm3</package>
@@ -5174,10 +5257,11 @@ Replaces: mail-transport-agent
</p>
<p>
- The run-time library package should include the symbolic link that
- <prgn>ldconfig</prgn> would create for the shared libraries.
- For example, the <package>libgdbm3</package> package should include
- a symbolic link from <file>/usr/lib/libgdbm.so.3</file> to
+ The run-time library package should include the symbolic link for
+ the <tt>SONAME</tt> that <prgn>ldconfig</prgn> would create for
+ the shared libraries. For example,
+ the <package>libgdbm3</package> package should include a symbolic
+ link from <file>/usr/lib/libgdbm.so.3</file> to
<file>libgdbm.so.3.0.0</file>. This is needed so that the dynamic
linker (for example <prgn>ld.so</prgn> or
<prgn>ld-linux.so.*</prgn>) can find the library between the
--
Russ Allbery (rra@debian.org) <http://www.eyrie.org/~eagle/>
Reply to: