Fink:Shlibs tutorial

From the Fink Wiki
Revision as of 12:12, 1 June 2012 by Nieder (talk | contribs) (fix </code> closing)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search


Work in progress: All 'information' contained herein is probably wrong.

Chapter 3.4 of the packaging manual sets out Fink policy for packages containing shared libraries, and is essential reading if you want to make such a package. This document is an attempt to provide extra help for new shared-library packagers.

SplitOffs

Any package containing shared libraries will contain SplitOffs -- multiple separate, non-overlapping packages compiled from the same source code. The points of SplitOffs are:

  • To allow solve concurrency/overlap issues: Assume Package A conflicts with Package B...perhaps both contain identically-named files. But there are subsets of A and B that don't conflict. By putting these non-conflicting files in splitoffs of A and B, a user can have both of these splitoffs installed concurrently, along with either A's or B's subset that overlaps the other's.
  • Users may want to install only part of a package. There may be some files that are widely used while others are only rarely needed and have extensive dependencies.

The first of these situations is particularly relevant for packages containing shared libraries. The actual shared libraries and other support and data files are put in one SplitOff, which is used at runtime by other fink packages. All filenames (or directories) in this "-shlibs" package contain a "library version" number, which is assigned by the library author and may or may not have any relationship to the package's version number. This convention allows multiple versions of the same library to be installed concurrently without conflict. For a given compiled package, -shlibs packages for different library versions to which it links are not interchangeable. Compiled programs contain the complete filenames of files to which they link, which are therefore specific to a given library-version's -shlibs package.

The compile-time development files -- headers, generic library symlinks, etc -- often do conflict among major versions of a given library, however. so they are put in separate SplitOff packages that can be swapped in or out as necessary for whichever version is desired when compiling something. This division is mandated by Fink's shared library policy.

How they work

Once the parent package has been built and installed into the temporary build-root directory (%d):

  • a new build-root directory is made for each SplitOff.
  • specified files are copied fromt the original build-root and/or compile directory to each new build-root
  • a separate .deb file is made from each build-root (as well as the build-root for the main/parent package)

Thus, you perform a single compile and install process. But, then splitting-off occurs, and you end up with several .debs -- one for the parent package and one for each SplitOff.

Separation of build parameters from .deb-related parameters

The structure of a SplitOff-containing .info file reflects the fact that there is one build process and several package-creation processes.

Build parameters

These parameters affect how the source is built, i.e. everything up to the end of the InstallScript. There should be only one instance of each of them, preferably at the start of the .info file. Since there is ony one build step, these parameters affect the contents of every .deb made by the .info file.

e.g. BuildDepends, Maintainer?, Source, HomePage, License, Source-MD5, SetCPPFLAGS, SetLDFLAGS, ConfigureScript, InstallScripts... (finish list)

Deb parameters

These parameters affect how the built software is put into .deb packages, after the InstallScript has finished. Each may occur multiple times in the .info file -- a maximum of once per SplitOff, plus once for the parent package. For the parent package, these parameters go at the top of the .info file. For SplitOffs, they go inside the SplitOffN: field.

e.g. Package, Depends, Files, Shlibs, ConfigFiles, DocFiles...

NB. Some .deb parameters are automatically inherited from the parent. This can be confusing, because it means they only appear once per .info file, making them falsely look like build parameters. You can treat them like build parameters, and specify them only once at the top of the .info file. Or you can override them

e.g. Version?, Revision?, Description, DescDetail...

Parent package deb parameters

A source of major confusion is that the parent package doesn't have it's own SplitOff section, but nevertheless has a package created. Thus, its deb-related parameters appear at the top of the .info file, near the build parameters. But don't be fooled! These are still deb-related parameters -- and so they apply only to the parent package, and are not inherited by SplitOffs. A good strategy is to keep these in a separate section of the .info file, after the build parameters.

Name your package

Many packages contain both shared libraries and binaries. The 'main' package (i.e. the one called %N) should contain whichever of these is more important -- i.e. whichever one the user is most likely to expect. It can't contain both. The Packaging Manual [1] gives clear guidance on whether to call your package libfoo (with splitoffs foo-shlibs, foo-bin) or bar-dev (with splitoffs bar-dev, bar-shlibs).

Build

Make a splitoff-less .info file for your package, without worrying about what will go in each SplitOff. Make sure it compiles, installs and validates correctly. Build with -kK so you have access to the source and build directories afterwards.

Split up the SplitOffs

Once you have a single built package, installed into a single build-root, you can sift through the files and work out which belong in which SplitOff. The idea here is to separate stuff into splitoffs by "use case". If a bunch of files satisfy one use case (running linked things, building linked things, running an included executable) they go together.

Here are the debs you should end up with for a shared libraries package:

Shared libraries

  • How many debs: One per 'set of related libraries'. Usually this means one :-)
  • Naming convention: libfoo1-shlibs. The number is that of the library version, not (necessarily) the package version.
  • What files go in it: Everything required for an executable that links to this one to run.
    • The file containing the actual shared library and all links to it, named at least as specifically as the install_name for it.
      • The file containing the actual code, for example, libfoo.1.1.0.dylib
      • Less-versioned symlinks, for example, libfoo.1.1.dylib and libfoo.1.dylib
    • Any runtime resources needed by the library. For example config files, default images, or gettext .mo files.
  • Required fields:
    • Package
    • Shlibs (see below)

Development stuff

  • How many debs: One per shlibs package.
  • Naming convention: libfoo1 (the parent) or bar2-dev
  • What files go in it: Everything needed to link something to the library
  • Contents:
    • The symlink that '-lfoo' finds: libfoo.dylib
    • The static libraries
    • All headers
    • If there are pkgconfig files, include them
    • If there's a 'foo-config' executable to find compile parameters, include it
    • If there's developer documentation or examples put them here.
  • Required fields:
    • BuildDependsOnly: true
    • Depends: libfoo1-shlibs (= %v-%r). There should be NO other depends.
    • If there's a libfoo1-dev and a libfoo2-dev, they should Conflict/Replace each other

Other stuff

  • How many debs: As many as necessary, maybe none. At least one for type 'bar'.
  • Naming convention: bar (the parent), bar-plugins, libfoo1-bin, etc
  • What goes in it: Any logical 'group of things the user might want together'.
  • Contents:
    • One or more executables, OR
    • One or more plugins, OR
    • One or more loadable themes, ...
    • PLUS anything needed to use the required contents, such as config files, default images or .mo files
    • user documentation, or useful examples
  • Required fields:
    • Depends: libfoo1-shlibs (= %v-%r). May be other depends.

Dependencies

Once you've decided which files belong in which SplitOff, you can work out the dependencies for each splitoff:

  • Run 'otool -L' on every binary and library in your package. Every listed library in /sw or /usr/X11R6 is a dependency that should be declared in the appropriate splitoff.
  • There may also be non-link dependencies -- e.g. an image-editor may want to use the command-line tool 'imagemagick' to convert things at runtime. One way to find these is to look at the output of ./configure. Any other methods?

Dependency rules:

  • Dependencies within the same .info file should ALWAYS have (= %v-%r), because things that are built together generally have high interdependence.
  • Within a library package, the developement deb should always depend on the associated shlibs deb. Usually it should have no other depends.
  • 'indirect dependencies'. Basically, this is when foo depends on bar, and bar depends on iggy. Does foo need to depend on iggy? Well, it kinda depends. What if bar stops depending on iggy? Then things break...so you have to make sure that won't happen without appropriate adjustments to foo. A good rule is to always include indirect deps, *unless* you control all the intermediate packages, in which case you'll probably notice if something changes!
  • What about the shlibs deb, and other debs within a library package? Treat them just as if they were all totally separate, *except* for the %v-%r issue. You should still use otool to find the link deps for each of them, which may include other splitoffs, or may include totally different things, or both.

The Shlibs field

Your %N-shlibs SplitOff needs to contain a field 'Shlibs'. The contents of this field are clearly described in the Packaging Manual. Note that the third field (the name of the package that provides the library) should be %N-shlibs not %N. Usually %n will be appropriate.

Packaging Manual

Now go back and read the Packaging Manual to make sure your package follows the policy described there.