Packaging Tutorial - 2. Example - the Maxwell Package
2.1 Basics
First Maxwell. Lets open our editor and get started. We know the package name, its version and where to grab the source tar ball from. So we'll type this into our editor window:
Package: maxwell Version: 0.5.1 Revision: 1 Source: mirror:sourceforge:%n/%n-%v.tar.gz
So we have the name and version which are easy to understand, but what of these other two fields? Revision is the "version" of the Fink package, Version, on the other hand is the upstream source version. Since this is the first time we have attempted to make a maxwell-0.5.1 package, it is revision 1.
The Source field is where fink
will grab the source tarball from. Because
Sourceforge has a system where
packages are mirrored around the world, and since fink
knows about it,
we use mirror:sourceforge:
. %n
expands to the package name,
maxwell, and %v
expands to the package version, 0.5.1.
Now we can save this as maxwell.info
in
/opt/sw/fink/dists/local/main/finkinfo/
. That done, we can see how we
are doing by using fink validate
.
finkdev% fink validate maxwell.info Validating package file maxwell.info... Error: Required field "Maintainer" missing. (maxwell.info)
Oops, looks like we missed a couple of fields. Lets add some more:
Maintainer: John Doe <jdoe@example.com> HomePage: http://maxwell.sourceforge.net License: MIT
We add ourselves as the maintainer of the Fink maxwell package and add it's homepage, looking at the sourceforge project page, we see that it is MIT Licensed, so we add that too. Now lets try again:
finkdev% fink validate maxwell.info Validating package file maxwell.info... Warning: Unknown license "MIT". (maxwell.info) Error: No MD5 checksum specified for "source". (maxwell.info) Error: No package description supplied. (maxwell.info)
Aaargh! We seem to be getting worse, not better, never mind, head off over to the Packaging Manual to see what is allowed for License, and we see that we can just change MIT to OSI-Approved, as the MIT license is, indeed, approved by the OSI. We can also grab a one line description of the package from the homepage. So we change those:
License: OSI-Approved Description: Mac OS X S.M.A.R.T. Tool
But what to do about that warning about MD5 checksums? Well, why don't we just
ask fink
to fetch the source?
finkdev% fink fetch maxwell /usr/bin/sudo /opt/sw/bin/fink fetch maxwell Reading package info... Updating package index... done. Information about 3377 packages read in 30 seconds. WARNING: No MD5 specified for Source of package maxwell-0.5.1-1 \ Maintainer: John Doe <jdoe@example.com> curl -f -L -O http://distfiles.opendarwin.org/maxwell-0.5.1.tar.gz % Total % Received % Xferd Average Speed Time Curr. Dload Upload Total Current Left Speed 0 0 0 0 0 0 0 0 --:--:-- 0:00:00 --:--:-- 0 curl: (22) The requested URL returned error: 404 ### execution of curl failed, exit code 22 Downloading the file "maxwell-0.5.1.tar.gz" failed. (1) Give up (2) Retry the same mirror (3) Retry another mirror from your continent (4) Retry another mirror (5) Retry using next mirror set "sourceforge" How do you want to proceed? [3] 5 curl -f -L -O http://west.dl.sourceforge.net/sourceforge/maxwell/maxwell-0.5.1.tar.gz % Total % Received % Xferd Average Speed Time Curr. Dload Upload Total Current Left Speed 100 7856 100 7856 0 0 19838 0 0:00:00 0:00:00 0:00:00 6511k
The tarball couldn't be downloaded from the Fink mirrors (distfiles) since your package is not added to the distribution yet. That's why you need to change to the next mirror set. More information about this problem is in the FAQ.
So we can now get the md5 by running md5sum /opt/sw/src/maxwell-0.5.1.tar.gz
,
and add it to the .info file:
Source-MD5: ce5c354b2fed4e237524ad0bc59997a3
And now we find that fink validate
passes, yippee!
2.2 Build
Now we can build the package, let's just try it:
finkdev% fink -m --build-as-nobody rebuild maxwell /usr/bin/sudo /opt/sw/bin/fink build maxwell Reading package info... Updating package index... done. Information about 3498 packages read in 32 seconds. The following package will be built: maxwell gzip -dc /opt/sw/src/maxwell-0.5.1.tar.gz | /opt/sw/bin/tar -xvf - \ --no-same-owner --no-same-permissions maxwell-0.5.1/ maxwell-0.5.1/LICENSE maxwell-0.5.1/Makefile maxwell-0.5.1/maxwell.8 maxwell-0.5.1/maxwell.c maxwell-0.5.1/README ./configure --prefix=/opt/sw Can't exec "./configure": No such file or directory at \ /opt/sw/lib/perl5/Fink/Services.pm line 403.
Hmm, well that did not go all that well. Let's read the README
(which you can find at /opt/sw/src/maxwell-0.5.1-1/maxwell-0.5.1/README
)
and see what it says...
To build type 'make'. To install in /usr/local type 'sudo make install', to install elsewhere, type 'sudo make install prefix=/elsewhere'
Ah hah, so we can't use the default CompileScript and InstallScript here, we need our own, that's easily resolved:
CompileScript: make InstallScript: << #! /bin/sh -ev make install prefix=%i <<
We need to use prefix=%i
since fink
builds the binary deb file
from the files in %i
. These files are later installed into
%p
(which is /opt/sw
by default) when you use
fink install maxwell
. For more details about %p
and
%i
please consult the
Packaging Manual.
Normally the lines in the Script fields are passed line by line to the shell.
But the #! /bin/sh -ev
line makes fink
run it as a separate script.
The parameter -e
means "die on error" and -v
means
"verbose".
So, let's validate the package again and try to rebuild it:
finkdev% fink validate maxwell.info Validating package file maxwell.info... Package looks good! finkdev% fink -m --build-as-nobody rebuild maxwell /usr/bin/sudo /opt/sw/bin/fink build maxwell Reading package info... Updating package index... done. Information about 3498 packages read in 32 seconds. The following package will be built: maxwell gzip -dc /opt/sw/src/maxwell-0.5.1.tar.gz | /opt/sw/bin/tar -xvf - \ --no-same-owner --no-same-permissions maxwell-0.5.1/ maxwell-0.5.1/LICENSE maxwell-0.5.1/Makefile maxwell-0.5.1/maxwell.8 maxwell-0.5.1/maxwell.c maxwell-0.5.1/README make cc -L/opt/sw/lib -c -o maxwell.o maxwell.c cc -I/opt/sw/include -o maxwell -framework IOKit -framework CoreFoundation maxwell.o /bin/rm -rf /opt/sw/src/root-maxwell-0.5.1-1 /bin/mkdir -p /opt/sw/src/root-maxwell-0.5.1-1/opt/sw /bin/mkdir -p /opt/sw/src/root-maxwell-0.5.1-1/DEBIAN /var/tmp/tmp.1.A3sRc2 #! /bin/sh -ev make install prefix=/opt/sw/src/root-maxwell-0.5.1-1/opt/sw /usr/bin/install -d -m 755 /opt/sw/src/root-maxwell-0.5.1-1/opt/sw/doc/maxwell /usr/bin/install -m 644 LICENSE /opt/sw/src/root-maxwell-0.5.1-1/opt/sw/doc/maxwell/LICENSE /usr/bin/install -m 644 README /opt/sw/src/root-maxwell-0.5.1-1/opt/sw/doc/maxwell/README /usr/bin/install -d -m 755 /opt/sw/src/root-maxwell-0.5.1-1/opt/sw/bin /usr/bin/install -m 755 maxwell /opt/sw/src/root-maxwell-0.5.1-1/opt/sw/bin/maxwell /usr/bin/install -d -m 755 /opt/sw/src/root-maxwell-0.5.1-1/opt/sw/man/man8 /usr/bin/install -m 644 maxwell.8 /opt/sw/src/root-maxwell-0.5.1-1/opt/sw/man/man8/maxwell.8 /bin/rm -f /opt/sw/src/root-maxwell-0.5.1-1/opt/sw/info/dir \ /opt/sw/src/root-maxwell-0.5.1-1/opt/sw/info/dir.old \ /opt/sw/src/root-maxwell-0.5.1-1/opt/sw/share/info/dir \ /opt/sw/src/root-maxwell-0.5.1-1/opt/sw/share/info/dir.old Writing control file... Finding prebound objects... Writing dependencies... Writing package script postinst... dpkg-deb -b root-maxwell-0.5.1-1 /opt/sw/fink/dists/local/main/binary-darwin-powerpc dpkg-deb: building package `maxwell' in \ `/opt/sw/fink/dists/local/main/binary-darwin-powerpc/maxwell_0.5.1-1_darwin-powerpc.deb'.
Fink seems to have installed everything into the correct place:
/opt/sw/src/root-maxwell-0.5.1-1
from where the binary package
maxwell_0.5.1-1_darwin-powerpc.deb
was built.
Also note how fink
automatically included some compiler flags to enable it to
access other Fink packages (e.g. -I/opt/sw/include
).
Let's have a look at what is in the binary package:
finkdev% dpkg -c \ /opt/sw/fink/dists/local/main/binary-darwin-powerpc/maxwell_0.5.1-1_darwin-powerpc.deb drwxr-xr-x root/admin 0 2004-07-15 09:40:38 ./ drwxr-xr-x root/admin 0 2004-07-15 09:40:39 ./opt/sw/ drwxr-xr-x root/admin 0 2004-07-15 09:40:39 ./opt/sw/bin/ -rwxr-xr-x root/admin 29508 2004-07-15 09:40:39 ./opt/sw/bin/maxwell drwxr-xr-x root/admin 0 2004-07-15 09:40:39 ./opt/sw/doc/ drwxr-xr-x root/admin 0 2004-07-15 09:40:39 ./opt/sw/doc/maxwell/ -rw-r--r-- root/admin 1076 2004-07-15 09:40:39 ./opt/sw/doc/maxwell/LICENSE -rw-r--r-- root/admin 1236 2004-07-15 09:40:39 ./opt/sw/doc/maxwell/README drwxr-xr-x root/admin 0 2004-07-15 09:40:39 ./opt/sw/man/ drwxr-xr-x root/admin 0 2004-07-15 09:40:39 ./opt/sw/man/man8/ -rw-r--r-- root/admin 1759 2004-07-15 09:40:39 ./opt/sw/man/man8/maxwell.8 drwxr-xr-x root/admin 0 2004-07-15 09:40:39 ./opt/sw/var/ drwxr-xr-x root/admin 0 2004-07-15 09:40:39 ./opt/sw/var/lib/ drwxr-xr-x root/admin 0 2004-07-15 09:40:39 ./opt/sw/var/lib/fink/ drwxr-xr-x root/admin 0 2004-07-15 09:40:39 ./opt/sw/var/lib/fink/prebound/ drwxr-xr-x root/admin 0 2004-07-15 09:40:39 ./opt/sw/var/lib/fink/prebound/files/ -rw-r--r-- root/admin 16 2004-07-15 09:40:39 ./opt/sw/var/lib/fink/prebound/files/maxwell.pblist
Seems ok, right? But we have to verify that it complies with the Fink packaging policy. So let's validate it with:
finkdev% fink validate \ /opt/sw/fink/dists/local/main/binary-darwin-powerpc/maxwell_0.5.1-1_darwin-powerpc.deb Validating .deb file \ /opt/sw/fink/dists/local/main/binary-darwin-powerpc/maxwell_0.5.1-1_darwin-powerpc.deb... Warning: File installed into deprecated directory /opt/sw/doc/ Offender is /opt/sw/doc/ Warning: File installed into deprecated directory /opt/sw/doc/ Offender is /opt/sw/doc/maxwell/ Warning: File installed into deprecated directory /opt/sw/doc/ Offender is /opt/sw/doc/maxwell/LICENSE Warning: File installed into deprecated directory /opt/sw/doc/ Offender is /opt/sw/doc/maxwell/README Warning: File installed into deprecated directory /opt/sw/man/ Offender is /opt/sw/man/ Warning: File installed into deprecated directory /opt/sw/man/ Offender is /opt/sw/man/man8/ Warning: File installed into deprecated directory /opt/sw/man/ Offender is /opt/sw/man/man8/maxwell.8
Oops... something is wrong. Let's consult the
Packaging Manual
again. It tells us to install man pages into /opt/sw/share/man
and files such
as README
into /opt/sw/share/doc/%n
. If we look into the
Makefile
of maxwell we see that the mandir and datadir can be set:
prefix = /usr/local mandir = ${prefix}/man man8dir = ${mandir}/man8 bindir = ${prefix}/bin datadir = ${prefix}/doc/maxwell
One easy way to fix that is to change the InstallScript to
make install prefix=%i mandir=%i/share/man datadir=%i/share/doc/%n
and rebuild the package with
finkdev% fink -m --build-as-nobody rebuild maxwell
(We used fink rebuild
because fink build
would not do
anything since the package was already built successfully.)
Review the contents of your deb file (with dpkg -c
) to see where
the files got installed now. Then validate the deb file again with
fink validate
. If all is well you can install the new package with:
finkdev% fink install maxwell /usr/bin/sudo /opt/sw/bin/fink install maxwell Information about 3377 packages read in 30 seconds. The following package will be installed or updated: maxwell dpkg -i /opt/sw/fink/dists/local/main/binary-darwin-powerpc/maxwell_0.5.1-1_darwin-powerpc.deb Selecting previously deselected package maxwell. (Reading database ... 56046 files and directories currently installed.) Unpacking maxwell (from .../maxwell_0.5.1-1_darwin-powerpc.deb) ... Setting up maxwell (0.5.1-1) ...
You can now run the software by typing
finkdev% maxwell
Congratulations, you just finished your first Fink package! Now try to package something yourself by following the Packaging tutorial from the beginning.
We are looking forward to your contributions to Fink!