|
Packit |
1470ea |
|
|
Packit |
1470ea |
<page xmlns="http://projectmallard.org/1.0/" xmlns:its="http://www.w3.org/2005/11/its" type="topic" id="parallel-installability" xml:lang="de">
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<info>
|
|
Packit |
1470ea |
<link type="guide" xref="index#maintainer-guidelines"/>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<credit type="author copyright">
|
|
Packit |
1470ea |
<name>Havoc Pennington</name>
|
|
Packit |
1470ea |
<email its:translate="no">hp@pobox.com</email>
|
|
Packit |
1470ea |
<years>2002</years>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
installability: http://ometer.com/parallel.html.
|
|
Packit |
1470ea |
Licence CC-BY-SA 3.0 confirmed by e-mail with him. -->
|
|
Packit |
1470ea |
</credit>
|
|
Packit |
1470ea |
<credit type="author copyright">
|
|
Packit |
1470ea |
<name>Philip Withnall</name>
|
|
Packit |
1470ea |
<email its:translate="no">philip.withnall@collabora.co.uk</email>
|
|
Packit |
1470ea |
<years>2015</years>
|
|
Packit |
1470ea |
</credit>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<include xmlns="http://www.w3.org/2001/XInclude" href="cc-by-sa-3-0.xml"/>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<desc>
|
|
Packit |
1470ea |
Writing libraries to be future proof through parallel installation
|
|
Packit |
1470ea |
</desc>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<mal:credit xmlns:mal="http://projectmallard.org/1.0/" type="translator copyright">
|
|
Packit |
1470ea |
<mal:name>Mario Blättermann</mal:name>
|
|
Packit |
1470ea |
<mal:email>mario.blaettermann@gmail.com</mal:email>
|
|
Packit |
1470ea |
<mal:years>2016</mal:years>
|
|
Packit |
1470ea |
</mal:credit>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<mal:credit xmlns:mal="http://projectmallard.org/1.0/" type="translator copyright">
|
|
Packit |
1470ea |
<mal:name>Christian Kirbach</mal:name>
|
|
Packit |
1470ea |
<mal:email>christian.kirbach@gmail.com</mal:email>
|
|
Packit |
1470ea |
<mal:years>2016</mal:years>
|
|
Packit |
1470ea |
</mal:credit>
|
|
Packit |
1470ea |
</info>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<title>Parallel Installability</title>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<synopsis>
|
|
Packit |
1470ea |
<title>Zusammenfassung</title>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
If two packages can be parallel installed, then they have no filenames in
|
|
Packit |
1470ea |
common, and people developing against the package always compile against
|
|
Packit |
1470ea |
the version they expected. This applies to daemons, utility programs and
|
|
Packit |
1470ea |
configuration files as it does to header files and library binaries.
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<list>
|
|
Packit |
1470ea |
<item>
|
|
Packit |
1470ea |
Ensure all versions of a library are parallel installable.
|
|
Packit |
1470ea |
(<link xref="#justification"/>)
|
|
Packit |
1470ea |
</item>
|
|
Packit |
1470ea |
<item>
|
|
Packit |
1470ea |
Version all files installed by a library.
|
|
Packit |
1470ea |
(<link xref="#solution"/>)
|
|
Packit |
1470ea |
</item>
|
|
Packit |
1470ea |
<item>
|
|
Packit |
1470ea |
Keep package version numbers separate from soname or libtool version
|
|
Packit |
1470ea |
numbers. Be clear which part of the package version number changes with
|
|
Packit |
1470ea |
the API.
|
|
Packit |
1470ea |
(<link xref="#version-numbers"/>)
|
|
Packit |
1470ea |
</item>
|
|
Packit |
1470ea |
<item>
|
|
Packit |
1470ea |
Install C header files to
|
|
Packit |
1470ea |
<file>$(includedir)/liblibrary-version/library/</file>.
|
|
Packit |
1470ea |
(<link xref="#header-files"/>)
|
|
Packit |
1470ea |
</item>
|
|
Packit |
1470ea |
<item>
|
|
Packit |
1470ea |
Install library binaries to
|
|
Packit |
1470ea |
<file>$(libdir)/liblibrary-version.so.soname</file>.
|
|
Packit |
1470ea |
(<link xref="#libraries"/>)
|
|
Packit |
1470ea |
</item>
|
|
Packit |
1470ea |
<item>
|
|
Packit |
1470ea |
Install pkg-config files to
|
|
Packit |
1470ea |
<file>$(libdir)/pkgconfig/library-version.pc</file>.
|
|
Packit |
1470ea |
(<link xref="#pkg-config"/>)
|
|
Packit |
1470ea |
</item>
|
|
Packit |
1470ea |
<item>
|
|
Packit |
1470ea |
Make configuration files forwards and backwards compatible, or install
|
|
Packit |
1470ea |
them to
|
|
Packit |
1470ea |
<file>$(sysconfdir)/library-version/</file>.
|
|
Packit |
1470ea |
(<link xref="#configuration-files"/>)
|
|
Packit |
1470ea |
</item>
|
|
Packit |
1470ea |
<item>
|
|
Packit |
1470ea |
Set GETTEXT_PACKAGE to
|
|
Packit |
1470ea |
library-version .
|
|
Packit |
1470ea |
(<link xref="#gettext"/>)
|
|
Packit |
1470ea |
</item>
|
|
Packit |
1470ea |
<item>
|
|
Packit |
1470ea |
Include a version number in all D-Bus interface names, service names and
|
|
Packit |
1470ea |
object paths. For example:
|
|
Packit |
1470ea |
org.domain.LibraryVersion.Interface ,
|
|
Packit |
1470ea |
org.domain.LibraryVersion and
|
|
Packit |
1470ea |
/org/domain/LibraryVersion/ .
|
|
Packit |
1470ea |
(<link xref="#dbus"/>)
|
|
Packit |
1470ea |
</item>
|
|
Packit |
1470ea |
<item>
|
|
Packit |
1470ea |
Install daemon binaries to
|
|
Packit |
1470ea |
<file>$(libexecdir)/library-daemon-version</file>.
|
|
Packit |
1470ea |
(<link xref="#programs"/>)
|
|
Packit |
1470ea |
</item>
|
|
Packit |
1470ea |
<item>
|
|
Packit |
1470ea |
Install utility binaries to
|
|
Packit |
1470ea |
<file>$(bindir)/library-utility-version</file>
|
|
Packit |
1470ea |
and install symbolic links to <file>$(bindir)/library-utility</file>.
|
|
Packit |
1470ea |
(<link xref="#programs"/>)
|
|
Packit |
1470ea |
</item>
|
|
Packit |
1470ea |
</list>
|
|
Packit |
1470ea |
</synopsis>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<section id="justification">
|
|
Packit |
1470ea |
<title>Justification</title>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
All public libraries should be designed to be parallel installed to ease
|
|
Packit |
1470ea |
API breaks later in the life of the library. If a library is used by
|
|
Packit |
1470ea |
multiple projects, and wants to break API, either all of the projects must
|
|
Packit |
1470ea |
be ported to the new API in parallel, or some of them will no longer be
|
|
Packit |
1470ea |
installable at the same time as the others, due to depending on
|
|
Packit |
1470ea |
conflicting versions of this library.
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
This is unmaintainable, and asking all the projects to port to a new API
|
|
Packit |
1470ea |
at the same time is hard to organize and demoralizing, as most API breaks
|
|
Packit |
1470ea |
do not bring large new features which would motivate porting.
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
The solution is to ensure that all libraries are parallel installable,
|
|
Packit |
1470ea |
allowing the old and new versions of the API to be installed and compiled
|
|
Packit |
1470ea |
against at the same time, without conflicts. Building in support for this
|
|
Packit |
1470ea |
kind of parallel installation is much easier to do at the start of a
|
|
Packit |
1470ea |
project than it is to do retroactively.
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
This eliminates the ‘chicken and egg’ problem of porting a collection of
|
|
Packit |
1470ea |
applications from one version of a library to the next, and makes breaking
|
|
Packit |
1470ea |
API a lot simpler for library maintainers, which can allow for more rapid
|
|
Packit |
1470ea |
iteration and development of new features if they desire.
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
The alternative, and equally valid, solution is for the library to never
|
|
Packit |
1470ea |
break API — the approach taken by libc .
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
</section>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<section id="solution">
|
|
Packit |
1470ea |
<title>Läsung</title>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
The solution to the problem is essentially to rename the library, and in
|
|
Packit |
1470ea |
most cases the nicest way to do so is to include the version number in the
|
|
Packit |
1470ea |
path of every file it installs. This means multiple versions of the
|
|
Packit |
1470ea |
library can be installed at the same time.
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
For example, say that library Foo traditionally installs
|
|
Packit |
1470ea |
these files:
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<list>
|
|
Packit |
1470ea |
<item><file>/usr/include/foo.h</file> </item>
|
|
Packit |
1470ea |
<item><file>/usr/include/foo-utils.h</file> </item>
|
|
Packit |
1470ea |
<item><file>/usr/lib/libfoo.so</file> </item>
|
|
Packit |
1470ea |
<item><file>/usr/lib/pkgconfig/foo.pc</file> </item>
|
|
Packit |
1470ea |
<item><file>/usr/share/doc/foo/foo-manual.txt</file> </item>
|
|
Packit |
1470ea |
<item><file>/usr/bin/foo-utility</file> </item>
|
|
Packit |
1470ea |
</list>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
You might modify Foo version 4 to install these files
|
|
Packit |
1470ea |
instead:
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<list>
|
|
Packit |
1470ea |
<item><file>/usr/include/foo-4/foo/foo.h</file> </item>
|
|
Packit |
1470ea |
<item><file>/usr/include/foo-4/foo/utils.h</file> </item>
|
|
Packit |
1470ea |
<item><file>/usr/lib/libfoo-4.so</file> </item>
|
|
Packit |
1470ea |
<item><file>/usr/lib/pkgconfig/foo-4.pc</file> </item>
|
|
Packit |
1470ea |
<item><file>/usr/share/doc/foo-4/foo-manual.txt</file> </item>
|
|
Packit |
1470ea |
<item><file>/usr/bin/foo-utility-4</file> </item>
|
|
Packit |
1470ea |
</list>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
It could then be parallel installed with version 5:
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<list>
|
|
Packit |
1470ea |
<item><file>/usr/include/foo-5/foo/foo.h</file> </item>
|
|
Packit |
1470ea |
<item><file>/usr/include/foo-5/foo/utils.h</file> </item>
|
|
Packit |
1470ea |
<item><file>/usr/lib/libfoo-5.so</file> </item>
|
|
Packit |
1470ea |
<item><file>/usr/lib/pkgconfig/foo-5.pc</file> </item>
|
|
Packit |
1470ea |
<item><file>/usr/share/doc/foo-5/foo-manual.txt</file> </item>
|
|
Packit |
1470ea |
<item><file>/usr/bin/foo-utility-5</file> </item>
|
|
Packit |
1470ea |
</list>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
This is easily supported using
|
|
Packit |
1470ea |
<link href="http://www.freedesktop.org/wiki/Software/pkg-config/">
|
|
Packit |
1470ea |
<cmd>pkg-config</cmd></link>: <file>foo-4.pc</file> would add
|
|
Packit |
1470ea |
<file>/usr/include/foo-4</file> to the include path and
|
|
Packit |
1470ea |
<file>libfoo-4.so</file> to the list of libraries to link;
|
|
Packit |
1470ea |
<file>foo-5.pc</file> would add <file>/usr/include/foo-5</file> and
|
|
Packit |
1470ea |
<file>libfoo-5.so</file>.
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
</section>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<section id="version-numbers">
|
|
Packit |
1470ea |
<title>Versionsnummern</title>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
The version number that goes in filenames is an ABI/API version.
|
|
Packit |
1470ea |
It should not be the full version number of your package — just the part
|
|
Packit |
1470ea |
which signifies an API break. If using the standard
|
|
Packit |
1470ea |
major.minor.micro scheme for
|
|
Packit |
1470ea |
project versioning, the API version is typically the major version number.
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
Minor releases (typically where API is added but not changed or
|
|
Packit |
1470ea |
removed) and micro releases (typically bug fixes) do not affect
|
|
Packit |
1470ea |
<link xref="api-stability">API backwards compatibility</link> so do not
|
|
Packit |
1470ea |
require moving all the files.
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
The examples in the following sections assume that the API version and
|
|
Packit |
1470ea |
soname are exported from <file>configure.ac</file> using the following
|
|
Packit |
1470ea |
code:
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<listing>
|
|
Packit |
1470ea |
<title>API-Versionierung in Autoconf</title>
|
|
Packit |
1470ea |
<desc>
|
|
Packit |
1470ea |
Code to export the API version and soname from <file>configure.ac</file>
|
|
Packit |
1470ea |
</desc>
|
|
Packit |
1470ea |
# Before making a release, the LIBRARY_LT_VERSION string should be modified.
|
|
Packit |
1470ea |
# The string is of the form c:r:a. Follow these instructions sequentially:
|
|
Packit |
1470ea |
#
|
|
Packit |
1470ea |
# 1. If the library source code has changed at all since the last update,
|
|
Packit |
1470ea |
# then increment revision (‘c:r:a’ becomes ‘c:r+1:a’).
|
|
Packit |
1470ea |
# 2. If any interfaces have been added, removed, or changed since the last update,
|
|
Packit |
1470ea |
# increment current, and set revision to 0.
|
|
Packit |
1470ea |
# 3. If any interfaces have been added since the last public release,
|
|
Packit |
1470ea |
# then increment age.
|
|
Packit |
1470ea |
# 4. If any interfaces have been removed or changed since the last public release,
|
|
Packit |
1470ea |
# then set age to 0.
|
|
Packit |
1470ea |
AC_SUBST([LIBRARY_LT_VERSION],[1:0:0])
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
AC_SUBST([LIBRARY_API_VERSION],[4])
|
|
Packit |
1470ea |
</listing>
|
|
Packit |
1470ea |
</section>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<section id="header-files">
|
|
Packit |
1470ea |
<title>C-Kopfdateien</title>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
Header files should always be installed in a versioned subdirectory that
|
|
Packit |
1470ea |
requires an <cmd>-I</cmd> flag to the C compiler. For example, if my
|
|
Packit |
1470ea |
header is <file>foo.h</file>, and applications do this:
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
#include <foo/foo.h>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
then I should install these files:
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<list>
|
|
Packit |
1470ea |
<item><file>/usr/include/foo-4/foo/foo.h</file> </item>
|
|
Packit |
1470ea |
<item><file>/usr/include/foo-5/foo/foo.h</file> </item>
|
|
Packit |
1470ea |
</list>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
Applications should pass the flag <cmd>-I/usr/include/foo-4</cmd> or
|
|
Packit |
1470ea |
<cmd>-I/usr/include/foo-5</cmd> to the C compiler. Again, this is
|
|
Packit |
1470ea |
facilitated by using <cmd>pkg-config</cmd>.
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
Note the extra <file>foo/</file> subdirectory. This namespaces the
|
|
Packit |
1470ea |
#include to avoid file naming collisions
|
|
Packit |
1470ea |
with other libraries. For example, if two different libraries install
|
|
Packit |
1470ea |
headers called <file>utils.h</file>, which one gets included when you
|
|
Packit |
1470ea |
use #include <utils.h> ?
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
There’s some temptation to keep one of the header files outside of any
|
|
Packit |
1470ea |
subdirectory:
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<list>
|
|
Packit |
1470ea |
<item><file>/usr/include/foo.h</file> </item>
|
|
Packit |
1470ea |
<item><file>/usr/include/foo-5/foo.h</file> </item>
|
|
Packit |
1470ea |
</list>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
The problem there is that users are always accidentally getting the wrong
|
|
Packit |
1470ea |
header, since <cmd>-I/usr/include</cmd> seems to find its way onto compile
|
|
Packit |
1470ea |
command lines with some regularity. If you must do this, at least add a
|
|
Packit |
1470ea |
check to the library that detects applications using the wrong header file
|
|
Packit |
1470ea |
when the library is initialized.
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
Versioned header files can be installed from automake using the following
|
|
Packit |
1470ea |
code:
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<listing>
|
|
Packit |
1470ea |
<title>Header-Dateien in Automake</title>
|
|
Packit |
1470ea |
<desc>
|
|
Packit |
1470ea |
Code to install versioned header files from <file>Makefile.am</file>
|
|
Packit |
1470ea |
</desc>
|
|
Packit |
1470ea |
libraryincludedir = $(includedir)/liblibrary-@LIBRARY_API_VERSION@/library
|
|
Packit |
1470ea |
library_headers = \
|
|
Packit |
1470ea |
liblibrary/example1.h \
|
|
Packit |
1470ea |
liblibrary/example2.h \
|
|
Packit |
1470ea |
$(NULL)
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
# The following headers are private, and shouldn't be installed:
|
|
Packit |
1470ea |
private_headers = \
|
|
Packit |
1470ea |
liblibrary/example-private.h \
|
|
Packit |
1470ea |
$(NULL)
|
|
Packit |
1470ea |
# The main header simply #includes all other public headers:
|
|
Packit |
1470ea |
main_header = liblibrary/library.h
|
|
Packit |
1470ea |
public_headers = \
|
|
Packit |
1470ea |
$(main_header) \
|
|
Packit |
1470ea |
$(library_headers) \
|
|
Packit |
1470ea |
$(NULL)
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
libraryinclude_HEADERS = $(public_headers)
|
|
Packit |
1470ea |
</listing>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
As well as correct versioning, all APIs in installed headers should be
|
|
Packit |
1470ea |
<link xref="namespacing">namespaced correctly</link>.
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
</section>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<section id="libraries">
|
|
Packit |
1470ea |
<title>Bibliotheken</title>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
Library object files should have a versioned name. For example:
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<list>
|
|
Packit |
1470ea |
<item><file>/usr/lib/libfoo-4.so</file> </item>
|
|
Packit |
1470ea |
<item><file>/usr/lib/libfoo-5.so</file> </item>
|
|
Packit |
1470ea |
</list>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
This allows applications to get exactly the one they want at compile time,
|
|
Packit |
1470ea |
and ensures that versions 4 and 5 have no files in common.
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
Versioned libraries can be built and installed from automake using the
|
|
Packit |
1470ea |
following code:
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<listing>
|
|
Packit |
1470ea |
<title>Bibliotehken in Automake</title>
|
|
Packit |
1470ea |
<desc>
|
|
Packit |
1470ea |
Code to build and install versioned libraries from
|
|
Packit |
1470ea |
<file>Makefile.am</file>
|
|
Packit |
1470ea |
</desc>
|
|
Packit |
1470ea |
lib_LTLIBRARIES = liblibrary/liblibrary-@LIBRARY_API_VERSION@.la
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
liblibrary_liblibrary_@LIBRARY_API_VERSION@_la_SOURCES = \
|
|
Packit |
1470ea |
$(private_headers) \
|
|
Packit |
1470ea |
$(library_sources) \
|
|
Packit |
1470ea |
$(NULL)
|
|
Packit |
1470ea |
liblibrary_liblibrary_@LIBRARY_API_VERSION@_la_CPPFLAGS = …
|
|
Packit |
1470ea |
liblibrary_liblibrary_@LIBRARY_API_VERSION@_la_CFLAGS = …
|
|
Packit |
1470ea |
liblibrary_liblibrary_@LIBRARY_API_VERSION@_la_LIBADD = …
|
|
Packit |
1470ea |
liblibrary_liblibrary_@LIBRARY_API_VERSION@_la_LDFLAGS = \
|
|
Packit |
1470ea |
-version-info $(LIBRARY_LT_VERSION) \
|
|
Packit |
1470ea |
$(AM_LDFLAGS) \
|
|
Packit |
1470ea |
$(NULL)
|
|
Packit |
1470ea |
</listing>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<section id="library-sonames">
|
|
Packit |
1470ea |
<title>Library sonames</title>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
Library sonames (also known as libtool version numbers) only address the
|
|
Packit |
1470ea |
problem of runtime linking previously-compiled applications. They don’t
|
|
Packit |
1470ea |
address the issue of compiling applications that require a previous
|
|
Packit |
1470ea |
version, and they don’t address anything other than libraries.
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
For this reason, sonames should be used, but in addition to
|
|
Packit |
1470ea |
versioned names for libraries. The two solutions address different
|
|
Packit |
1470ea |
problems.
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
</section>
|
|
Packit |
1470ea |
</section>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<section id="pkg-config">
|
|
Packit |
1470ea |
<title>pkg-config-Dateien</title>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
pkg-config files should have a versioned name. For example:
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<list>
|
|
Packit |
1470ea |
<item><file>/usr/lib/pkgconfig/foo-4.pc</file> </item>
|
|
Packit |
1470ea |
<item><file>/usr/lib/pkgconfig/foo-5.pc</file> </item>
|
|
Packit |
1470ea |
</list>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
Since each pkg-config file contains versioned information about the
|
|
Packit |
1470ea |
library name and include paths, any project which depends on the library
|
|
Packit |
1470ea |
should be able to switch from one version to another simply by changing
|
|
Packit |
1470ea |
their pkg-config check from <file>foo-4</file> to <file>foo-5</file> (and
|
|
Packit |
1470ea |
doing any necessary API porting).
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
Versioned pkg-config files can be installed from autoconf and automake
|
|
Packit |
1470ea |
using the following code:
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<listing>
|
|
Packit |
1470ea |
<title>pkg-config-Dateien in Autoconf und Automake</title>
|
|
Packit |
1470ea |
<desc>
|
|
Packit |
1470ea |
Code to install versioned pkg-config files from
|
|
Packit |
1470ea |
<file>configure.ac</file> and <file>Makefile.am</file>
|
|
Packit |
1470ea |
</desc>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
AC_CONFIG_FILES([
|
|
Packit |
1470ea |
liblibrary/library-$LIBRARY_API_VERSION.pc:liblibrary/library.pc.in
|
|
Packit |
1470ea |
],[],
|
|
Packit |
1470ea |
[LIBRARY_API_VERSION='$LIBRARY_API_VERSION'])
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
# Note that the template file is called library.pc.in, but generates a
|
|
Packit |
1470ea |
# versioned .pc file using some magic in AC_CONFIG_FILES.
|
|
Packit |
1470ea |
pkgconfigdir = $(libdir)/pkgconfig
|
|
Packit |
1470ea |
pkgconfig_DATA = liblibrary/library-$(LIBRARY_API_VERSION).pc
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
DISTCLEANFILES += $(pkgconfig_DATA)
|
|
Packit |
1470ea |
EXTRA_DIST += liblibrary/library.pc.in
|
|
Packit |
1470ea |
</listing>
|
|
Packit |
1470ea |
</section>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<section id="configuration-files">
|
|
Packit |
1470ea |
<title>Konfigurationsdateien</title>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
From a user standpoint, the best approach to configuration files is to
|
|
Packit |
1470ea |
keep the format both <link xref="api-stability">forward and backward
|
|
Packit |
1470ea |
compatible</link> (both library
|
|
Packit |
1470ea |
versions understand exactly the same configuration file syntax and
|
|
Packit |
1470ea |
semantics). Then the same configuration file can be used for all versions
|
|
Packit |
1470ea |
of the library, and no versioning is needed on the configuration file
|
|
Packit |
1470ea |
itself.
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
If you can’t do that, the configuration files should simply be renamed,
|
|
Packit |
1470ea |
and users will have to configure each version of the library separately.
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
</section>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<section id="gettext">
|
|
Packit |
1470ea |
<title>Gettext-Übersetzungen</title>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
If you use gettext for translations in combination with autoconf and
|
|
Packit |
1470ea |
automake, normally things are set up to install the translations to
|
|
Packit |
1470ea |
<file>/usr/share/locale/lang/LC_MESSAGES/package</file>.
|
|
Packit |
1470ea |
You’ll need to change package. The convention used in GNOME is
|
|
Packit |
1470ea |
to put this in <file>configure.ac</file>:
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
GETTEXT_PACKAGE=foo-4
|
|
Packit |
1470ea |
AC_SUBST([GETTEXT_PACKAGE])
|
|
Packit |
1470ea |
AC_DEFINE_UNQUOTED([GETTEXT_PACKAGE],["$GETTEXT_PACKAGE"])
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
Then use GETTEXT_PACKAGE as the package name to pass to
|
|
Packit |
1470ea |
bindtextdomain() ,
|
|
Packit |
1470ea |
textdomain() , and
|
|
Packit |
1470ea |
dgettext() .
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
</section>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<section id="dbus">
|
|
Packit |
1470ea |
<title>D-Bus-Schnittstellen</title>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
A D-Bus interface is another form of API, similar to a C API except that
|
|
Packit |
1470ea |
resolution of the version is done at runtime rather than compile time.
|
|
Packit |
1470ea |
Versioning D-Bus interfaces is otherwise no different to C APIs: version
|
|
Packit |
1470ea |
numbers must be included in interface names, service names and object
|
|
Packit |
1470ea |
paths.
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
For example, for a service org.example.Foo exposing
|
|
Packit |
1470ea |
interfaces A and B on objects
|
|
Packit |
1470ea |
Controller and Client , versions 4 and 5 of the
|
|
Packit |
1470ea |
D-Bus API would look like this:
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<list>
|
|
Packit |
1470ea |
<title>Dienstnamen</title>
|
|
Packit |
1470ea |
<item>org.example.Foo4 </item>
|
|
Packit |
1470ea |
<item>org.example.Foo5 </item>
|
|
Packit |
1470ea |
</list>
|
|
Packit |
1470ea |
<list>
|
|
Packit |
1470ea |
<title>Interface Names</title>
|
|
Packit |
1470ea |
<item>org.example.Foo4.InterfaceA </item>
|
|
Packit |
1470ea |
<item>org.example.Foo4.InterfaceB </item>
|
|
Packit |
1470ea |
<item>org.example.Foo5.InterfaceA </item>
|
|
Packit |
1470ea |
<item>org.example.Foo5.InterfaceB </item>
|
|
Packit |
1470ea |
</list>
|
|
Packit |
1470ea |
<list>
|
|
Packit |
1470ea |
<title>Objektpfade</title>
|
|
Packit |
1470ea |
<item>/org/example/Foo4/Controller </item>
|
|
Packit |
1470ea |
<item>/org/example/Foo4/Client </item>
|
|
Packit |
1470ea |
<item>/org/example/Foo5/Controller </item>
|
|
Packit |
1470ea |
<item>/org/example/Foo5/Client </item>
|
|
Packit |
1470ea |
</list>
|
|
Packit |
1470ea |
</section>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<section id="programs">
|
|
Packit |
1470ea |
<title>Programs, Daemons and Utilities</title>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
Desktop applications generally do not need to be versioned, as they are
|
|
Packit |
1470ea |
not depended on by any other modules. Daemons and utility programs,
|
|
Packit |
1470ea |
however, interact with other parts of the system and hence need
|
|
Packit |
1470ea |
versioning.
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
Given a daemon and utility program:
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<list>
|
|
Packit |
1470ea |
<item><file>/usr/libexec/foo-daemon</file> </item>
|
|
Packit |
1470ea |
<item><file>/usr/bin/foo-lookup-utility</file> </item>
|
|
Packit |
1470ea |
</list>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
these should be versioned as:
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
<list>
|
|
Packit |
1470ea |
<item><file>/usr/libexec/foo-daemon-4</file> </item>
|
|
Packit |
1470ea |
<item><file>/usr/bin/foo-lookup-utility-4</file> </item>
|
|
Packit |
1470ea |
</list>
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
You may want to install a symbolic link from
|
|
Packit |
1470ea |
<file>/usr/bin/foo-lookup-utility</file> to the recommended versioned
|
|
Packit |
1470ea |
copy of the utility, to make it more convenient for users to use.
|
|
Packit |
1470ea |
|
|
Packit |
1470ea |
</section>
|
|
Packit |
1470ea |
</page>
|