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

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: