In my example I will build the foo2zjs printer driver to be used together with foomatic to support my Samsung CLP-315 printer. The driver depends only on foomatic which is already supported by IPFire, so I can directly proceed.

Starting

Start by placing a copy of the source code for your addon into the cache folder with the rest of the sources for all of the packages. The file will be compressed e.g. as .xz or .tar.gz. The file name we will use is foo2zjs-source.tar.gz.

The LFS build fragment

The next step is to write a build fragment for LFS. This file requires a well defined structure that we need to customize.

A generic template for this file is available in the lfs-fragment page or you can just copy one of the files from the lfs/. You will need to change a few lines in this template:

  • VERSION The version number of the new package; it will be used in building the archive name.
  • THISAPP The package name
  • DL_FROM The default points to IPFire repository, but this package isn't there, so we need to modify.
  • PROG The name of the main program, usually the same as THISAPP
  • DEPS The dependencies needed by this application.
  • PAK_VER Continuously incrementing package version counter. Set this to a number one higher than previously released version of this package starting at 1 when no earlier release exists.
  • The build recipe: the default is the minimal make, but we may need to expand/modify it.

Save your lfs file as foo2zjs in the lfs/ folder.

See lfs-fragment.

Linking in the build script

To incorporate the new build in IPFire build script you have to add a line in make.sh. This line should be near the end of the buildipfire() function:

...
buildipfire() {
  LOGFILE="$BASEDIR/log/_build.ipfire.log"
...
  lfsmake2 rfkill
  lfsmake2 amazon-ssm-agent
  lfsmake2 foo2zjs # <-- this line was inserted and matches the filename in lfs
}

buildinstaller() {
...
}
...

First compilation

The build environment is now complete and we can try to compile our package. It is enough to issue:

sudo ./make.sh build

It should run very quickly and you should see, at the end of * * * Building IPFire section something like:

...
rfkill                [       0.5 ]             [        0 ] [ DONE ]
amazon-ssm-agent      [   2.3.930.0 ]           [        0 ] [ DONE ]
foo2zjs               [  noversion ]            [      141 ] [ DONE ]
*** Building installer (Last sta      versionec options    time (sec)   status
...

If something went wrong You can try to manually install in the IPFire build environment this is done using make.sh shell. This command will set-up the same chroot environment used for building and start a shell in it. When you are done with your tests you can just close the shell with <Ctrl>D.

$ sudo ./make.sh shell
Resetting our nice level to 10                                         [ DONE ]
Checking if we're running as root user                                 [ DONE ]
Checking for necessary space on disk                                   [ DONE ]
Entering to a shell inside LFS chroot, go out with exit

$ cd /tmp

$ tar xaf /usr/src/cache/foo2zjs-source.tar.gz

$ cd foo2zjs/

$ ls
COPYING         foo2qpdl.1in         icc2ps
...
foo2qpdl-wrapper.in hplj10xx_gui.tcl     zjsdecode.c

$ exit

I used this environment to understand why downloading from the Internet failed consistently in the build environment while it worked perfectly well at the shell prompt.

Please Note:

  • I am always working as "normal" unprivileged user, so I need to prepend sudo to build commands
  • Changing anything in the compilation script will not cause module recompilation. You need to remove the file that equals to your package name from the log directory to trigger recompilation on next sudo ./make.sh build.

Package definition

At this point we are almost there.

You still need to define which files need to be in the packages.

The IPFire build system is very kind and will prepare for you a file containing all files added or removed by the installation. At the very end of the compilation you will see something like:

xvid                            [      1.2.1 ]            [        0 ] [ DONE ]
xen-image                       [     ipfire ] [ ED=full ][      200 ] [ DONE ]
Generating files list from logs                                        [ DONE ]
*** Checking Logfiles for new Fi      versionge options8 s time (sec)   status
Changes in cdrtools-2.01.01 check rootfile!
Changes in foo2zjs-source check rootfile!
***Build is finished now and took 0 hour(s) 29 minute(s) 57 second(s)!

This file have the same name as your filename (foo2zjs-source) and is located in the log directory. Copy it into config/rootfiles/packages but also rename it to the lfs filename you used before:

cp log/foo2zjs-source config/rootfiles/packages/foo2zjs

Now open the file in a text editor. It contains a list of all files added, removed or changed by your make install (a changed file will appear as added and deleted).

You will need to remove the prepended plus (+) or minus (-) sign and, possibly, to comment out some files.

Rule-of-thumb is as follows:

  • remove all lines with a minus (-) sign.
  • remove all plus (+) signs.
  • comment out (prepending a hash (#) sign) all lines pointing to directories.
  • comment out (prepending a hash (#) sign) all lines pointing to "useless" files.

Useless files are:

  • manpages (are usually located in /usr/share/man)
  • pkg-config files ( are usually located in /usr/lib/pkgconfig)
  • *.so files (are usually located in /usr/lib)
  • *.a files (are usually located in /usr/lib)
  • *.la files (are usually located in /usr/lib)
  • *.h files or header files (are usually located in /usr/include)
  • *.m4 files (are usually located in /usr/share/aclocal)
Note!
If your new rootfile contains files which are located in /usr/local this is really bad. Nothing should go there. If files are located there for example library files this cause a lot of trouble because in the most cases they are not found by the program. To avoid this you should always use --prefix=/usr.

Original and edited files for foo2zjs can be found in the package page.

Pakfire Routines

Last bit of customization is about the installation/removal routines.

Pakfire provides a set of standard scripts for install, uninstall and upgrade; they can be found in src/paks/default.

If these are not enough, for any reason, you can customize them.

Required steps are:

  • copy src/paks/default to src/paks/<yourPackage>
  • edit src/paks/<yourPackage>/install.sh, src/paks/<yourPackage>/uninstall.sh or src/paks/<yourPackage>/update.sh

Final build

Finally you have to restart the build to produce the final product using the following commands:

sudo ./make.sh clean
sudo ./make.sh build

Testing

You should now have a brand new packages/<youraddon>-<version>-#.ipfire, so in this example we would have packages/foo2zjs-noversion-2.ipfire

To test it you have to send it to your installed IPFire. Currently there is no easy way to install the pak using pakfire itself, though this is easily done manually via scp/ssh by extracting the package, copying the ROOTFILE to the pakfire db/rootfiles dir as your addon-name (required for uninstall) and executing the install.sh/upgrade.sh and uninstall.sh manually.

Make sure to thoroughly test the install/upgrade and uninstall scripts as well as the actual addon.

$ scp -P 222 foo2zjs-noversion-2.ipfire root@ipfire:/tmp
foo2zjs-noversion-2.ipfire                          100%   19MB   9.6MB/s   00:02

$ ssh -p 222 root@ipfire
Last login: Thu Nov 18 08:51:10 2010 from vmrunner.condarelli.it



$# cd /opt/pakfire/tmp/

$# tar xvf /tmp/foo2zjs-noversion-2.ipfire
files
install.sh
uninstall.sh
update.sh
ROOTFILES

$# ls -l
total 39426
-rw-r--r-- 1 root root 20080640 2010-11-17 18:33 files
-rw-r--r-- 1 root root 20111360 2010-11-18 08:50 foo2zjs-noversion-2.ipfire
-rwxr-xr-x 1 root root     1735 2010-11-17 18:33 install.sh
-rw-r--r-- 1 root root    13306 2010-11-17 18:33 ROOTFILES
-rwxr-xr-x 1 root root     1717 2010-11-17 18:33 uninstall.sh
-rwxr-xr-x 1 root root     1691 2010-11-17 18:33 update.sh

$# cp ROOTFILES `/opt/pakfire/db/rootfiles/foo2zjs`

$# NAME=foo2zjs ./install.sh
Extracting files...
bin/
bin/usb_printerid
...
usr/lib/cups/
usr/lib/cups/filter/
usr/lib/cups/filter/command2foo2lava-pjl
...Finished.
Stopping CUPS Printserver...                                                               [  OK  ]
Starting CUPS Printserver...                                                               [  OK  ]

$# NAME=foo2zjs ./update.sh
Stopping CUPS Printserver...                                                               [  OK  ]
Removing files...
removed '/usr/lib/cups/filter/command2foo2lava-pjl'
removed directory '/usr/lib/cups/filter'
removed directory '/usr/lib/cups'
...
removed '/bin/usb_printerid'
...Finished.
Extracting files...
bin/
bin/usb_printerid
...
usr/lib/cups/
usr/lib/cups/filter/
usr/lib/cups/filter/command2foo2lava-pjl
...Finished.
Stopping CUPS Printserver...                                                               [  OK  ]
Starting CUPS Printserver...                                                               [  OK  ]

$# NAME=foo2zjs ./uninstall.sh
Stopping CUPS Printserver...                                                               [  OK  ]
Removing files...
removed '/usr/lib/cups/filter/command2foo2lava-pjl'
removed directory '/usr/lib/cups/filter'
removed directory '/usr/lib/cups'
...
removed '/bin/usb_printerid'
...Finished.

$# rm *
rm: remove regular file 'files.tar.xz'? y
rm: remove regular file 'install.sh'? y
rm: remove regular file 'ROOTFILES'? y
rm: remove regular file 'uninstall.sh'? y
rm: remove regular file 'update.sh'? y

$# rm /opt/pakfire/db/rootfiles/foo2zjs
rm: remove regular file '/opt/pakfire/db/rootfiles/foo2zjs'? y

$# logout
Bye bye.
Connection to ipfire closed.

After an invocation of NAME=foo2zjs ./install.sh or NAME=foo2zjs ./update.sh, the Package is installed and ready to run.

Note!
If there's something wrong and you need to modify some of the files in the upstream archive (i.e.: the archive downloaded from ${DL_FROM}/${DL_FILE}), you will need to prepare a patch and to add the information in the recipe. I plan to write a page on that; it will be linked here.

Next Step: Sharing with others

FIXME:
How can your package be added to the pakfire list in ipfire?
Pakfire build services??
How to change Branches (stable, testing, unstable) Process to submit??
How can someone install an unofficial pakfire? Only using the testing steps?

The End

That's all, Folks!