Fink

Packaging - 3. Packaging Policy

3.1 Package Licenses

The packages included in Fink come with a wide variety of licenses. Most of them place restrictions on redistributing the full source and especially on distributing binaries. Some packages can not be included in the binary distribution of Fink because of these license restrictions. Thus it is very important that package maintainers check the license of their package carefully.

Every package that is to be distributed as a binary package must contain a copy of the license. It must be installed in the doc directory, i.e. in %p/share/doc/%n. (In the InstallScript, %i must be used instead of %p, of course. The DocFiles field takes care of the details automatically.) If there is no explicit license in the original source, include a small text file with a note about the status of the package. Most licenses require that the license accompanies any distribution. Fink's policy is to always do this, even if it is not explicitly required.

To make an automated maintenance of the binary distribution possible, any package that is to be distributed must have a License field. This field denotes the nature of the license and is used to decide which packages make it into the binary distribution and which must be held back. The field may only be present if the actual license terms are included in the binary package, as explained above.

To make the License field useful, only one of the following pre-defined values may be used. If you're packaging something that doesn't fit into these categories, ask for help on the developer mailing list.

3.2 The GPL and OpenSSL

(Policy change effective April, 2005.)

Due to the apparent incompatibility of the OpenSSL license with the GPL and LGPL licenses, fink packages which link to openssl but are licensed under the GPL or LGPL are marked as "Restrictive." As a consequence, the Fink project will not distribute binaries of such packages, although users are free to compile them from source at their discretion.

Package maintainers are encouraged to record the original package license in the DescPackaging field.

3.3 Base System Interference

Fink is an add-on distribution that is installed in a directory separate from the base system. It is crucial that a package does not install files outside of Fink's directory.

Exceptions can be made when there is no other possibility, e.g. with XFree86. In this case the package must check for existing files before installation and refuse to install if it would overwrite existing files. The package must make sure that all files it installed outside of the Fink directory are deleted when the package is removed, or that they cause no harm if they are left there (i.e. they need to check binaries for existence before calling them and the like).

3.4 Shared Libraries

Fink's policy about shared libraries became effective in February 2002. This section of the documentation discusses version 4 of the policy (which coincides with the release of Fink's 0.5.0 distribution), as modified in December, 2006 to handle 64-bit libraries and from January, 2008 to handle private shared libraries. (In addition, the discussion was updated in June, 2008 to eliminate obsolete references to a transitional period for implementing the shared libraries policy.) We begin with a quick summary, and then discuss things in more detail.

Any package which builds shared libraries should treat its shared libraries according to Fink's policy. This means:

Note that a package may also install private shared libraries, which are not intended to be linked from any other package. In this case, the libraries need not go into a separate package, but a Shlibs field must still be part of the package containing shared libraries. Also, maintainers should try to avoid storing a final link from libfoo.dylib in the main library directory %i/lib (or its 64-bit equivalent), to prevent other programs from accidentally linking to this library.

A maintainer who has reasons to deviate from this policy and not split the package should explain the reasons in the DescPackaging field.

For some packages, everything can be accomplished with a main package and a -shlibs package; in other cases you also need a third package. The new SplitOff field actually makes this quite easy.

When three packages are needed, there are two different ways they could be named, depending on whether the libraries (option 1) or the binaries (option 2) are the most important feature of the package. For option 1, use the layout:

PackageContents
foo-shlibs

Shared libraries

foo

Headers

foo-bin

Binaries, etc.

while for option 2, use the layout:

PackageContents
foo-shlibs

Shared libraries

foo-dev

Headers

foo

Binaries, etc.

The policy in detail

We now discuss things in more detail; for examples of the policy in action, see the libpng, libjpeg and libtiff packages.

Software which has been ported to Darwin should build shared libraries whenever possible. (Package maintainers are also free to build static libraries as well, if appropriate for their packages; or they may submit packages containing only static libraries if they wish.) Whenever shared libraries are being built that are expected to be used by other packages, two closely related fink packages should be made, named foo and foo-shlibs. The shared libraries go in foo-shlibs, and the header files go in foo. These two packages can be made with a single .info file, using the SplitOff field, as described below. (In fact, it is often necessary to make more than two packages from the source, and this can be done using SplitOff2, SplitOff3, etc.)

Each software package for which public shared libraries are built must have a major version number N, which is included in the shared library's filename (for example, libbar.N.dylib). The major version number is only supposed to change when a backwards-incompatible change in the library's API has been made. Fink uses the following naming convention: if the upstream name of the package is bar, then the fink packages are called barN and barN-shlibs. (This is only strictly applied to new packages, or when the major version number changes.) For example, the major version number for the pre-existing libpng package was 2, but recent versions of the library have major version number 3. So there are now four fink packages to handle this: libpng, libpng-shlibs, libpng3, libpng3-shlibs. Only one of libpng and libpng3 can be installed at any given time, but libpng-shlibs and libpng3-shlibs can be installed at the same time. (Note that only two .info files are required to build these four packages.)

The shared library itself and certain related files will be put into the package barN-shlibs; the "include" files and certain other files will be put into the package barN. There can be no overlapping files between these two packages, and everything stored in barN-shlibs must have a pathname which somehow includes the major version number N. In many instances, your package will need some files at runtime which are typically installed into %i/lib/bar/ or %i/share/bar/ ; you should adjust the installation paths to %i/lib/bar/N/ or %i/share/bar/N/.

All other packages which depend on bar, major version N, will be asked to use the dependencies

  Depends: barN-shlibs
  BuildDepends: barN

It is not be permitted for another package to depend on barN itself. (Although there may still be a few such dependencies involving packages which were in place prior to February, 2002.) This is signaled to other developers by a boolean field

  BuildDependsOnly: True

within the package description for barN.

If your package includes both shared libraries and binary files, and if the binary files need to be present at runtime (not just at build time), then the binaries must be split off into a third package, which could be called barN-bin. Other packages are allowed to depend on barN-bin as well as barN-shlibs.

When building shared libraries under major version N, it is important that the "install_name" of the library be %p/lib/libbar.N.dylib. (You can find the install_name by running otool -L on your library, or otool64 -L for 64-bit libraries on 10.4.) The actual library file may be installed at another location, such as

  %i/lib/libbar.N.x.y.dylib

and your packages should create symbolic links

  %i/lib/libbar.N.dylib -> %p/lib/libbar.N.x.y.dylib
  %i/lib/libbar.dylib -> %p/lib/libbar.N.x.y.dylib

from the install_name path and from the linking path to the actual library. (The first will not be needed if the library is in fact installed at the install_name path, which is becoming more common.)

If the static library is also built, then it will be installed at

  %i/lib/libbar.a

If the package uses libtool, these things are usually handled automatically, but in any event you should check that they have been done correctly in your case. You should also check that current_version and compatibility_version were defined appropriately for your shared libraries. (These are also shown with the otool -L query, or otool64 -L for 64-bit libraries.)

Files are then divided between the two packages as follows

Notice that both packages are required to have some documentation about the license, but that the directories containing the DocFiles will be different.

Doing this is quite easy in practice, using the SplitOff field. Here is how the example above would be implemented (in part):

Package: barN
Version: N.x.y
Revision: 1
License: GPL
Depends: barN-shlibs (= %v-%r)
BuildDependsOnly: True
DocFiles: COPYING
SplitOff: <<
  Package: barN-shlibs
  Files: lib/libbar.N.x.y.dylib lib/libbar.N.dylib lib/bar/N
  DocFiles: COPYING
<<

During the execution of the SplitOff field, the specified files and directories are moved from the install directory %I of the main package to the install directory %i of the splitoff package. (There is a similar convention for names: %N is the name of the main package, and %n is the name of the current package.) The DocFiles command then puts a copy of the documentation into %i/share/doc/barN-shlibs.

Notice that we have included the exact current version of barN-shlibs as a dependency of the main package barN (which can be abbreviated %N-shlibs (= %v-%r) ). This ensures that the versions match, and also guarantees that barN automatically "inherits" all the dependencies of barN-shlibs.

The BuildDependsOnly field

When libraries are being upgraded over time, it is often necessary to have two versions of the header files available during a transition period, with one version used for compiling some things and the other version used for compiling others. For this reason, the packages containing header files must be constructed with some care. If both foo-dev and bar-dev contain overlapping headers, then foo-dev should declare

  Conflicts: bar-dev
  Replaces: bar-dev

and similarly bar-dev declares Conflicts/Replaces on foo-dev.

In addition, both packages should declare

  BuildDependsOnly: True

This inhibits others from writing packages which depend on foo-dev or bar-dev, since any such dependency will prevent the smooth operation of the Conflicts/Replaces method.

There are some packages containing header files for which it's not appropriate to declare BuildDependsOnly to be true. In that case, the package should declare

  BuildDependsOnly: False

and the reason must be given in the DescPackaging field.

The BuildDependsOnly field should only be mentioned in the package's .info file if the package contains header files, installed into %i/include (or subdirectories thereof).

As of fink 0.20.5, "fink validate" will issue a warning for any .deb which contains header files and at least one dylib, and does not declare BuildDependsOnly to be either true or false. (It is possible that in future versions of fink, this warning will be expanded to cover the case of a .deb with header files and a static library as well.)

The goal of the Shared Library Policy is to allow assure compatibility between libraries supplied by one package and libraries or programs that use them in a different package. Some packages may have shared libraries that are not designed to be used by other packages. Common situations include a suite of programs that come with a back-end library of utility functions or a program that comes with plugins to handle various features. Because these libraries are "private" to the package that has them, they do not require being packaged with separate -shlibs or BuildDependsOnly SplitOffs.

The Shlibs field

In addition to putting the shared libraries in the correct package, as of version 4 of this policy, you must also declare all of the shared libraries using the Shlibs field. This field has one line for each shared library, which contains the -install_name of the library. If the library is public, its Shlibs entry also lists the -compatibility_version, versioned dependency information specifying the Fink package which provides this library at this compatibility version, and the library architecture. (The library architecture may either be "32", "64", or "32-64", and may be absent. If the library architecture is not explicitly listed, it defaults to the standard value for the current architecture of Fink; these standard values are "32" for the powerpc and i386 architectures, and "64" for the x86_64 architecture.) The dependency should be stated in the form foo (>= version-revision) where version-revision refers to the first version of a Fink package which made this library (with this compatibility version) available. For example, a declaration

  Shlibs: <<
    %p/lib/libbar.1.dylib 2.1.0 bar1 (>= 1.1-2) 32
  <<

indicates that a (32-bit) library with -install_name %p/lib/libbar.1.dylib and -compatibility_version 2.1.0 has been installed since version 1.1-2 of the bar1 package. In addition, this declaration amounts to a promise from the maintainer that a 32-bit library with this name and a compatibility-version of at least 2.1.0 will always be found in later versions of the bar1 package.

Note the use of %p in the name of the library, which allows the correct -install_name to be found by all users of Fink, no matter what prefix they have chosen.

When a package is updated, usually the Shlibs field can simply be copied to the next version/revision of the package. The exception to this is if the -compatibility_version increases: in that case, the version number in the dependency information should be changed to the current version/revision (which is the first version/revision to provide the library with the new compatibility version number).

The Shlibs entry for a private library uses a different syntax:

  Shlibs: <<
    !%p/lib/%N/libbar.1.dylib
  <<

The leading exclamation point indicates that this is a private library, and since the other information is not relevant in this case, it is not included.

Note that in this example, the private shared library has been placed in its own subdirectory %N of the %i/lib directory (which was named after the package). This is a recommended procedure for private libraries, as an additional safety measure, to prevent other packages from accidentally linking to this library.

What to do when the major version number changes:

If the major version number changes from N to M, you will create two new packages barM and barM-shlibs. The package barM-shlibs can have no overlap with the package barN-shlibs, since many users will have both of these installed simultaneously. In package barM, you should use dependencies

  Conflicts: barN
  Replaces: barN

and similarly, you should revise barN to include dependencies

  Conflicts: barM
  Replaces: barM

Users will then see barN and barM shuffling in and out as various other packages are built which depend on one version or another of the shared library, while barN-shlibs and barM-shlibs remain permanently installed.

Packages containing both binary files and libraries:

When an upstream package contains both binary files and public libraries, some care must be exercised in constructing fink packages. In some cases, the only binary files will be things like foo-config which are presumably only used at build time and never at run time. In these cases, the binaries can go with the header files in the foo package.

In other cases, the binary files will be needed by other packages at runtime, and they must be split off into a separate fink package with a name something like foo-bin. The foo-bin package should depend on the foo-shlibs package, and maintainers of other packages should be encouraged to use

  Depends: foo-bin
  BuildDepends: foo

which will take care of foo-shlibs implicitly.

Upgrading presents a problem in this situation, however, since users won't be prompted to install foo-bin. To work around this, until all other package maintainers have revised their packages as above, your foo package can say

  Depends: foo-shlibs (= exact.version), foo-bin

This will force the installation of foo-bin on most users' systems, until such time as the other package maintainers have upgraded their packages which depend on foo.

As of fink-0.28.0 (released in January 2008), the format of the Shlibs entry for a "private" shared library has changed (see earlier discussion of the difference between a public and a private shared library). Note that the Shared Library Policy has always required all shared libraries to be listed; the change here is only in the syntax of the Shlibs field. Because this type of shared library is not designed to be used by external packages, there is no need to document its compatilibity or other versioning. Instead, an exclamation-mark is used. For example, if libquux.3.dylib is the install_name of a private shared library, it would be listed as follows:

  Shlibs: <<
    !%p/lib/libquux.3.dylib
  <<

3.5 Perl Modules

Fink's policy about perl modules, originally implemented in May 2003, has been revised as of April 2004.

Traditionally, the Fink packages for perl modules had the suffix -pm, and were built using the Type: perl directive, which stores the perl module's files in /opt/sw/lib/perl5 and/or /opt/sw/lib/perl5/darwin. Under the policy now in place, this storage location is only permitted for perl modules which are independent of the version of perl being used to compile them (and which do not depend on other perl modules that lack this independence-of-version).

The perl modules which are version-dependent are the so-called XS modules, which frequently contain compiled C code as well as pure perl routines. There are a number of ways of recognizing these, including the presence of a file with a suffix .bundle.

A version-dependent perl module must be built using a versioned binary of perl, such as perl5.12.3, and must store its files in versioned subdirectories of the standard perl directories, such as /opt/sw/lib/perl5/5.12.3 and /opt/sw/lib/perl5/5.12.3/darwin. By convention, package names use the suffix -pm5123 for a perl module of version 5.12.3. Similar storage and naming conventions are in force for other versions of perl, which include perl 5.10.0 (in the 10.6 tree only), perl 5.12.4 (in the 10.7 tree only), and perl 5.16.2 (in the 10.7 tree only).

The directive Type: perl 5.12.3 automatically uses the versioned perl binary and stores the files in the correct subdirectories. (This directive is available starting with version 0.13.0 of fink.)

Under the May 2003 policy, it was permitted to create a -pm package which is essentially a "bundle" package that loads the -pm560 variant or any others which may be exist. Under the April 2004 policy this is discouraged, and after a transitional period was outlawed entirely.

As of fink 0.20.2, the system-perl virtual package automatically "Provides" certain perl modules depending on the system-perl version. The code generating the list of provided perl modules is found in the VirtPackage.pm file that is part of the fink package.

As different system perls provide different modules, package maintainers are encouraged to check to be sure that they are assuming the correct list when using provided perl modules.

Effective with version 0.13.0 of fink, the fink validate command when applied to a .deb file will check to see if the fink package is an XS module which has been installed in a non-versioned directory, and will issue a warning if so.

Users may have more than one version of perl installed at a time, so any perl-versioned module packages must be written to allow more than one version of themselves to be installed concurrently. One must use care when installing manpages and binary or other script executables in these packages in order to prevent installation conflicts due to filename collisions. You are not allowed to have any files in a package whose name ends with -pmXYZ that would have an identical pathname across different XYZ. Using Replaces to allow the same-named files to overwrite each other in different perl-versions of these perl-module packages is no longer acceptable. As a simple solution for manpages, starting in March 2005, Fink has defined alternate locations in MANPATH: %p/lib/perl5/X.Y.Z/man for each perl-X.Y.Z. You no longer need to create mutually-exclusive -man or -doc SplitOff packages. For example, to avoid conflicts between uri-pm5124 and uri-pm5162, the same-named URI.3pm manpage is installed as %p/lib/perl5/5.12.4/man/man3/URI.3pm and %p/lib/perl5/5.16.2/man/man3/URI.3pm, respectively. Note that the default scripts provided by Type: perl X.Y.Z have not changed, so you will have to locate the manpages here manually in your InstallScript. If you don't have a highly customized script, you can still use the default one, and then simply move the files manually:

%{default_script}
mv %i/share/man %i/lib/perl5/5.12.4

That will move all manpages. If you wish to move only one section of manpages (for example, only section 3, the module manpages, not script manpages in section 1), a similar approach works:

%{default_script}
mkdir -p %i/lib/perl5/5.12.4/man
mv %i/share/man/man3 %i/lib/perl5/5.12.4/man

If you have executables, for example, demo or utility scripts in %p/bin, you have several options. One example is to put these files (and their associated manpages and/or other related files) in a %N-bin splitoff package. Use of Conflicts and Replaces fields ensures that installation of different perl-version forms of these packages, which contain files of the same name, is mutually exclusive. The user can install many different perl-versions of the runtime modules, and then choose whichever one perl-version of the scripts he wants at a given time. For example, Tk.pm comes with an executable ptksh, so the set of tk-pm* packages could be constructed as follows:

Info2: <<
Package: tk-pm%type_pkg[perl]
Type: perl (5.12.3 5.12.4 5.16.2)
InstallScript: <<
  %{default_script}
  mkdir -p %i/lib/perl5/%type_raw[perl]/man
  mv %i/share/man/man3 %i/lib/perl5/%type_raw[perl]/man
<<
SplitOff: <<
  Package: %N-bin
  Depends: %N
  Conflicts: %{Ni}5.12.3, %{Ni}5.12.4, %{Ni}5.16.2
  Replaces: %{Ni}5.12.3, %{Ni}5.12.4, %{Ni}5.16.2
  Files: bin share/man/man1
<<
<<

An alternative arrangement is to rename the scripts and their manpages to include perl-version information. This method means there is no naming conflict at all, so one does not need the mutually-exclusive %N-bin splitoffs:

Info2: <<
Package: tk-pm%type_pkg[perl]
Type: perl (5.12.3 5.12.4 5.16.2)
InstallScript: <<
  %{default_script}
  mkdir -p %i/lib/perl5/%type_raw[perl]/man
  mv %i/share/man/man3 %i/lib/perl5/%type_raw[perl]/man
  mv %i/bin/ptksh %i/bin/ptksh%type_raw[perl]
  mv %i/share/man/man1/ptksh.1 %i/share/man/man1/ptksh%type_raw[perl].1
<<
<<

The user accesses ptksh for whichever perl she wants. For convenience, one could use update-alternatives to allow users to be able to access these by their generic (no perl-version) names as well.

Also as of March 2005, the location of manpages and modules installed by fink packages for perl itself (packages perlXYZ and perlXYZ-core other than the perl-version provided by Apple) has changed. As a result of this relocation, other fink packages that supply updated versions of core perl modules should not list any perlXYZ or perlXYZ-core packages in the Replaces field.

3.6 Emacs Policy

The Fink project has chosen to follow the Debian project's policy regarding emacs, with a few small differences. (The Debian policy document can be found at http://www.debian.org/doc/packaging-manuals/debian-emacs-policy.) There are two differences in the Fink policy. First, this policy only applies to the emacs21, emacs22, and emacs23 packages in fink at the moment, not to the xemacs package. (This may change some day in the future.) And second, unlike the Debian policy, Fink packages are allowed to install things directly into /opt/sw/share/emacs/site-lisp.

3.7 Source Policy

Sources should normally be downloaded from the location(s) that the upstream developer(s) use, and any modifications for Fink should be done through the use of a PatchFile and/or a PatchScript. Do not make changes manually and use a changed source archive as a Source in your Fink packaging.

If a VCS checkout (e.g. from git or svn) is to be used, e.g. because a project doesn't do formal releases, or a fix for a particular issue has been added between releases of a package, an acceptable source can be generated via the following method:

  1. Check out the package, preferably at a definite revision of the VCS.
  2. Make an archive from the VCS checkout (e.g. zip, tar, tar.gz, or tar.bz2).

    Give the tarball a unique version. For example, you can include the VCS revision in the archive name, e.g. foo-0svn1234.tar.gz for a package that doesn't make releases, or bar-1.2.3+svn4567.tar.bz2 for a Fink package which is between upstream releases.

  3. Use the same Version in your .info file.
  4. It is also useful to put the commands that you ran to generate the source tarball in the DescPackaging field.
  5. Upload the tarball to a public download site where users can use fink to download it. If you don't have ready access to one, ask on the Fink developers mailing list or the #fink IRC channel, and someone should be able to help.

3.8 File Download Policy

Packages are not to download any files during the unpack, patch, compile, install, or build phases of the build process. Any large patches (i.e. larger than can be accommodated conveniently in a PatchFile) that need to be applied should set up as additional Sources in accordance with the Source Policy.

Packages may download data in a PostInstScript after they have been installed on the system, under some limited circumstances:

If you are unsure, contact the Fink Core Team.

Next: 4. Filesystem Layout