This little HOWTO is intended to help everyone who wants to write printer drivers for Linux and Unix, as printer manufacturers, ISVs, and also users who simply want to get their printers to work. The goal is to make the drivers available in a form that they "just work" for as many users as possible and that they do not require deep knowledge in system administration and/or software development for installation.
To reach this goal one should already start at the design of the driver. This makes the later steps, as building in the LSB environment and packaging much easier.
The printing process under Linux and Unix is as follows: Applications send the print job as a PostScript (or later PDF]) file to the printing system (usually CUPS) and the printing system converts the job to the printer's language. The resulting data stream it sends through a printer port to the printer.
In the simplest case the printer driver is simply what converts PostScript or PDF into the printer's language, but often there are several other components.
Renderer/filter: This is the core part of the driver. It converts a device-independent page description language (PDL) from standard input into the (model-dependent) PDL of the printer on standard output.
In the beginning Unix was used only in computing centers where one had only PostScript and text-only printers. Data was simply sent without special filtering. Later Ghostscript was introduced as a software PostScript interpreter to support non-PostScript printers by converting PostScript into the appropriate language. The drivers for the printer languages were part of the monolithic Ghostscript executable. To add a driver one had to patch and recompile Ghostscript.
With the time several forms of modularized drivers appeared. This way the renderer (currently only Ghostscript) and the filter got separate and so recompiling Ghostscript was not necessary any more. This simplified adding a printer driver a lot. Currently the recommended (and required by the LSB 3.2) printer driver interfaces in Ghostscript are:
CUPS Raster
CUPS raster drivers are a special form of filter type drivers. The concept is developed as a part of the CUPS printing system to make driver installation easy. CUPS calls Ghostscript to translate the PostScript input into the CUPS raster format and an additional CUPS filter to translate the CUPS raster format into the printer's language. These drivers come always with PPDs which do not only contain options and printer properties but also instruct CUPS to call the correct CUPS filter. Which of these drivers are installed you see by the PPD files in /usr/share/cups/model (and its subdirectories) and by the printer models showing up in the lists when setting up a print queue with the web interface of CUPS (entries usually contain "CUPS").
IJS plug-in
IJS plug-ins are also separate executables and so they also do not require Ghostscript to be patched and recompiled to add support for a new printer. But in contrary to CUPS raster drivers IJS plug-ins communicate bi-directionally with Ghostscript and so Ghostscript can ask them for certain printer properties and adapt its rendering appropriately. The executables have to be in the execution path (or called with an absolute path). They usually contain "ijs" somewhere in their names and some of them can be called with the "-h" command line option to get version information.
OpenPrinting Vector
This interface is developed by the Japanese subgroup of the OpenPrinting working group and it is the only one which allows to plug vector(high-level drawing)-based printer drivers into Ghostscript. The connection between renderer and driver can be done by dynamic library linking or by communicating with a separate driver process via RPC. The latter method helps to avoid license conflicts and also makes it easier to provide distribution-independent driver packages.
With all these interfaces in place there is no necessity any more to write printer drivers which have to be compiled into Ghostscript. This method is deprecated and should not be used any more.
Currently, Ghostscript is the only PostScript/PDF renderer for printing. This may change in the future, especially when the standard format of print jobs will be PDF and not Postscript any more. For example there could be XPDF/Poppler based renderers with the above-mentioned driver interfaces. This is another reason to not write printer drivers to be compiled into Ghostscript any more.
Low-level communication with the printer: Usually nothing special is needed for the low-level communication with the printer. The printers have standard parallel, USB, and or network interfaces and you can simply feed in the data (in a language which the printer understands) and the printer prints.
In some cases special software is needed to communicate with the printer:
This software should not do the conversion of PostScript or PDF into the printer's language. It should simply take the printer-ready data stream and get it into the printer (and provide the extra functions if it is supposed to do so. In some cases this is done by an additional daemon, which listens to requests to access the different features of the printer.
The low-level communication module and the filter should be separate pieces of software, to integrate well with the printing system and also to work if a client sends pre-rendered data (for example a Windows box with the Windows driver).
Printer maintenance and auxiliary tools: Programs to do tasks like observing the ink/toner levels, cleaning and/or aligning print heads, handling incoming and outgoing faxes and fax numbers, ... These tools are called like application programs and can make use of a printer-specific low-level communication module. There should be the possibility to do the tasks with a graphical user interface for best usability on desktop machines but also an option to do things via the command line, so that the printer is also accessible from scripts or by blind people with a Braille text interface.
Scanner drivers: Scanner drivers for multi-function devices should not come in the form of desktop applications, they should come as drivers for SANE, so that every scanning software for Linux can be used with the built-in scanner. This also saves the cost and effort of writing a scanning GUI.
On the current Linux distributions printing is done via the Common Unix Printing System (CUPS). It takes care of making printers available on the local machine and in the network, control printer access, collect and route print jobs, and finally filter and print them.
CUPS: In a CUPS environment the filters and low-level communication modules are all running on the server side (the machine where the printer is connected to). On clients (remote machines to which the printers are shared) one does not even need to set up print queues. as CUPS supports auto-discovery of servers.
CUPS supports several different kinds of auxiliary programs, especially Filters to convert one file format into another and backends for low-level communication with printers. So printer drivers integrate in CUPS as CUPS filters for rendering PostScript to the printer's language and CUPS backends to do the low-level communication. CUPS ships backends for standard interfaces and communication protocols, so a printer driver usually does not need to ship a CUPS backend.
As under Linux and Unix all applications produce PostScript when they send data to the printing system CUPS print queues are emulating PostScript printers (CUPS understands also other input formats, like PDF, images, or plain text, but it usually converts these formats to PostScript). The capabilities of PostScript printers and their user-settable printer-specific options are described in PPD (PostScript Printer Description) files supplied by the printer's manufacturer. For non-PostScript printers CUPS also uses PPD files, but with special CUPS-specific information added, especially which CUPS filter generates the printer's language. PPD files for non-PostScript printers are usually shipped with the driver. The printing options to control the printer and the driver (paper trays, paper size, output quality, color adjustment, ...) users see in printing dialogs of applications or in printer setup tools are the ones described in the PPD file.
Ghostscript: To render PostScript Ghostscript is available on all Linux and Unix operating systems (see above). Ghostscript is called by one of the CUPS filters. In case of CUPS raster drivers this is done by a filter named "pstoraster" which has the CUPS raster format as output and a CUPS filter shipped with the driver package converts this into the printer's language. For the other drivers there is usually one CUPS filter which converts PostScript directly to the printer's language. This filter calls either Ghostscript with one of the built-in drivers or with a plug-in (IJS or OpenPrinting Vector), or it lets Ghostscript produce a standard image format (PNM, PNG, TIFF...) and pipes it through a filter which generates the printer's language.
foomatic-rip: foomatic-rip is a universal print filter. It can be used with all printing systems (including CUPS) auto-detecting the system by analyzing the environment out of which it got called and can call printer drivers (renderer/filter) with arbitrary command lines which have PostScript as standard input and the printer's language as standard output. foomatic-rip uses PPD files (with extra keywords for non-PostScript printers and advanced option types) to know about the driver command line and the user-settable options. This way it also adds PPD file support to non-CUPS printing systems. It has also some extra features like page overrides (different option settings for selected pages), making CUPS raster driver working with non-CUPS printing systems, and converting non-PostScript input data on non-CUPS printing systems.
foomatic-rip is available in all Linux distributions (used as a CUPS filter) and in Sun's Solaris (used with the LP printing system) and is the de-facto standard for using most printer drivers.
CUPS DDK: This does not ship with the Linux distributions, but it is free software which you can download from the CUPS web site and provides interesting tools for building and manipulating PPD files and also two CUPS raster drivers which can be used as a base for your own driver development or as an example for driver programming. As the CUPS DDK ships very convenient tools for generating PPD files it makes part of the LSB DDK. Note that the LSB does not require the presence of the drivers which come with the CUPS DDK. So do not make driver packages based on the drivers coming with the CUPS DDK (or ship these drivers with your package).
SANE: Every Linux distribution ships SANE to access scanners and all free scanning software under Linux uses SANE. So if you want to provide full functionality for a multi-function printer with scanner, base your scanner driver on SANE. This way every user can use the scanning software he is used to, and easily switch between different scanners without needing to learn to use a new interface all the time. SANE is also included in the LSB DDK now, but this part is not yet intensively tested and SANE is also not yet in the LSB. SANE modules compiled in the LSB Build Environment with the LSB DDK should work on all distributions with SANE 1.0.x. It is planned to make SANE a requirement for LSB 4.0.
The Linux Standards Base (LSB): To assure common binary interfaces and directory structures across all major Linux distributions and to make it this way possible to create distribution-independent binary Linux application packages, the LSB was created. The LSB defines standards for common interfaces, system functiuonality, and directory structures which are found in all currecnt major Linux distributions. The current version of the LSB, version 3.2, has requirements for a modern printing infrastructure for the first time. Current [OpenPrinting/Database/DriverPackages distribution-independent driver packages] in the OpenPrinting database are based on LSB 3.2 and so they require nothing else then an LSB-3.2-compliant system, which is the case for most of the current Linux distributions.
There are also older LSB-3.1-based packages, but LSB 3.1 did not yet have any printing-related requirements. So that driver packages require CUPS, Ghostscript (ESP 8.15.3 or later, GPL 8.60 or later), Perl, and foomatic-rip to be installed in addition. It must also be assured that CUPS searches for PPDs in /usr/share/ppd then. See [OpenPrinting/Database/DriverPackages the instructions for the driver packages].
In the LSB 3.2 the following requirements were added:
SANE was not added, it is planned to be added in LSB 4.0. LSB 4.0 will also require the full CUPS API, except interfaces which were dropped after CUPS 1.1.x.
Independent of that Perl and Python are also required by the LSB 3.2.
The OpenPrinting web site: The OpenPrinting database makes it easy for users and also for printer setup tools to find the best driver for a given printer. Now it does not only provide information about printer drivers and PPD files, but it support also providing the drivers themselves. These drivers are made available as distribution-independent printer driver packages and a web API is provided so that printer setup tools can look up printer drivers, present information about the driver to the user and download and install the driver automatically when the user agrees. As this can be done automatically by a printer setup tool, you do not need to get your driver into all the distributions if you provide it in the OpenPrinting database. Once your driver is there, your printer will "just work" for all Linux users with internet connection.
Many printer drivers, especially drivers supplied by printer manufacturers, have problems due to a bad design which makes the drivers difficult or complicated to install or even break things in the user's system including security problems. This often happens when driver developers are used to Microsoft Windows where the architecture of the operating system and the printing infrastructure is well different.
A big difference in the printing infrastructure is that under Windows printer drivers are running on the client machine (the machine which runs the desktop applications). The driver is usually called directly by the application and so it can communicate with the application bi-directionally, can add GUI elements to the application's print dialog and can also pop up its own windows. The application then sends the data in the printer's native language to the spooler. This means also that every client machine which wants to print needs the driver locally installed.
Under Linux the printer drivers are running on the server (the machine to which the printer is connected). Applications send the data in a device-independent page description language (PDL), usually in PostScript or PDF. The driver on the server converts this device-independent PDL into the printer's native PDL. The advantage is that the driver is only installed once on the server and does not need to be downloaded by the clients. Disadvantage is that the driver cannot be interactive and needs to be remote-controlled somehow by the desktop application on the client. This is done via PPD (PostScript printer description) files. The PPDs describe the properties of the printer/driver combo and which parameters can be set by the user. According to this the application adds appropriate GUI elements to its printing dialog. The types of parameters and GUI elements are restricted, as PPDs do not support arbitrary data types for the user-settable parameters.
Also important to say is that Linux is a multi-user operating system where every user has only access to his work data and where there is an administrator ("root") who has access to the whole system. For security reasons also some system processes (like the conversion of print data to the printer's language) are run as non-root users.
There are also some stability and security policies under Linux which do not necessarily exist under Windows, for example that a package cannot overwrite a file from another package, that user-callable desktop applications should run with the rights of the calling user and not as root or as another user, ...
For printer/scanner drivers it is also important that they should be installable in any combination, packages for two different models should not have a file in common, as there can always be users having these two devices connected to one computer. And distributions want to be able to have all printer drivers installed at once, so that a user can connect an arbitrary printer and it just works.
So here are some guidelines of what to do and what not:
The most user-friendly way to supply printer drivers to end-users are binary packages which they can simply install with the tools which come with their distributions. For printer manufacturers sometimes it also the only way to publish drivers, as they contain IP which they cannot publish as open source. Unfortunately, the usual binary packages as shipped with Linux distributions work only with one specific distribution. Also binary packages of drivers shipped by printer manufacturers or posted by free driver projects are usually only for specific distributions. For manufacturers this means duplicate packaging and testing effort to support their printers under Linux, or they restrict their support to only one or two distributions.
To reduce costs and development time the LSB Driver Development Kit (DDK) was developed. The LSB itself was designed to allow the creation of distribution-independent packages of application programs. The LSB DDK expands the LSB development environment to support building and packaging printer and scanner drivers. It consists of the printing environment (LSB 3.2 requires only certain interfaces and therefore the standard development environment does not contain the complete printing environment) and of a macro set for RPM for easy packaging. This way you can create distribution-independent printer driver packages with the not much more effort than distribution-specific ones. So you package and test once for all distributions. Then printers will work with Linux and not with Red Hat, SuSE, Debian, ...
At first you need to install the LSB Build Environment as described in the LSB developer tutorial. If you install RPM packages inside the chroot environment ("lsb-buildenv", not yet available for LSB 3.2) you need to supply always the "--nodeps" option to the "rpm" commands, as the chroot environment is not completely built with RPM like a real Linux distribution, and therefore the RPM database is not complete. Your build environment should contain the packages (click the package names for download locations) "lsb-build-base", "lsb-build-cc", "lsb-build-c++", "lsb-build-libbat", "lsb-appchk", "lsb-pkgchk". lsb-build-libbat is not required, but can make the life eaiser. Check the presence of the packages with "rpm -qa" and install the missing ones with "rpm -Uvh --nodeps <package file name>". On Debian-based distributions use "alien -ick <package file name>" to install the RPMs (this converts the packages to equally-named and -versioned Debian packages before installing). See also the tutorial. Install also your distribution's "lsb" package.
If your driver comes with auxiliary programs with graphical user interface you will also have to install the other "lsb-build-..." packages for X and the GUI.
Every library which is not provided with the LSB Build Environment must be statically linked by the executables in your driver package. The same you have to do with every library from which you are using interfaces which are not covered by the LSB. Alternatively, you can ship the appropriate shared library with your driver but then you have to make sure that only your driver uses your copy of the library and no other program on the system.
Now you need to install the packages of the LSB DDK onto your machine where you have installed the LSB Build environment. Currently, this is the RPM macro set, the CUPS DDK (RPM packages "cupsddk..."), and the sane-backends package (RPM packages "sane-backends..."). The latter is only needed for scanner drivers (also to support the scanning function of multi-function printers). Append the RPM macro set to the file "/etc/rpmrc" or ".rpmmacros" in your home directory. If the file does not exist, create it. Add also the following lines (with the correct data filled in) to ".rpmmacros" in your home directory:
%_topdir /home/YOURLOGIN/rpm %_tmppath /home/YOURLOGIN/tmp %distribution LSB %vendor YOURORGANIZATION %packager YOURNAME <YOURMAILADDRESS>
Now everything is prepared to build printer driver packages.
It is highly recommended to build the driver packages in a chroot LSB Build Environment, it is much more safe to get LSB-compliant executables there. Currently, as there is no LSB Build Environment chroot for LSB 3.2 yet, build on a usual system. Use lsbappchk on all executables and shared libraries of you package, to make sure that you really get LSB binaries.
All distribution-independent LSB packages are provided as RPM packages. For non-RPM distributions (like Debian or Ubuntu) the LSB requires alien to be in the distribution. This program converts RPMs to other package formats. So what you need to know at first is how to make RPM packages. This will not be covered by this document, as there is good documentation elsewhere.
Our RPMs will differ from packages shipped by Linux distributions in the following points:
These things are usually very complicated to do with stock RPM. To make this task as easy as possible there is the RPM macro set which will do most of the stuff by adding only a few simple lines.
Before you start creating your own RPMs you should have a look at the spec files of existing distribution-independent driver packages. If your driver has more complex requirements as needing to install and run a daemon or being split into several binary packages, have a look at the CUPS and Ghostscript packages.
If you have already made usual RPMs of your driver, you can take their spec files and easily convert them to LSB packages by adding the appropriate macros of the macro set. Otherwise create a new spec file and add the macros.
Now we go through the sections of the spec file to show the changes which have to be done to turn the package into a distribution-independent LSB package. The macros are presented in the order how they are usually applied in the spec file.
This is the part before the %prep section begins. Here the following has to be present:
Name: splix Version: 1.0.1 Release: 3lsb3.2
The package name should be the same as commonly used in distributions (and would be great to have it also being the driver name used in the OpenPrinting database). The version number is the version number of your printer driver or if you package someone else's driver the version number of the upstream (source) package. The release number has "lsb" and the version number of the LSB which we are building for as its suffix (our "distribution" is LSB).
License: GPL
This is the license of the driver which you are packaging. For closed-source drivers use "Commercial".
Group: Applications/System
Always use this group for drivers.
URL: http://splix.ap2c.org/
URL where you present the driver on your web site.
%define supplier splix
For free software projects the name of the project, for companies (like printer manufacturers) the company name. This is used as a file name, so use only characters allowed in file names and avoid spaces. This one is used (and required) by the macro set.
%define drivername splix
The name of the driver, in most cases identical to the name of the filter executable or IJS plug-in. Should be the same as the name of the driver database entry in the OpenPrinting database. Also this name is used as a file name. And do not create driver names with spaces for the OpenPrinting database. Also used and required by the macro set.
%define filternames <driver executable name,...>
This lists the names of the driver executables for which the %adjust_ppds macro (%install section) has to add absolute paths. There can be more than one driver executable name be supplied in a comma-separated list. If the driver executable name is given with a full path, this path will be used in the PPD file, otherwise %_bindir. Do not use this macro with CUPS raster drivers. Here %adjust_ppds finds the CUPS filter executables by itself.
%define services <service name,...>
This lists the names of the system services supplied by this package. There can be more than one system service be supplied in a comma-separated list. These services will be set up for being started at boot by the %setup_services macro (in the %post post-install script), restarted by the %restart_services macro (in the %post post-install and the %postun post-uninstall scripts when the package gets updated), and removed by the %remove_services macro (in the %postun post-uninstall script).
BuildRequires: lsb-build-cc, lsb-build-c++, lsb-appchk BuildRequires: perl, gzip
If you use the lsb-build-libbat package, add
BuildRequires: lsb-build-libbat
These are the packages needed to build packages based on the LSB DDK.
Requires: lsb >= 3.2
Do require always the "lsb" package of at least the version for which you build the package. Be careful with other Requires, they need to be available on all LSB-compliant distributions (at least commonly available, not necessarily required by the LSB) and always with the name which you specify. You do not need to require any package which the LSB requires. These packages are already required by the "lsb" package.
BuildRoot: %_tmppath/%name-%version-%release-root
Do not forget to supply a BuildRoot, otherwise the package will mess up with your system (to make this not happen accidentally do not build packages as root).
BuildArch: noarch
If your package does not contain any binary executables, either because it consists of only PPD files or all driver executables and auxiliary programs are scripts, add "BuildArch: noarch" to the RPM header. Otherwise, do not do it.
%install_into_opt
This is the first macro of the macro set which we use. It makes the packaged driver getting installed into /opt/<supplier>/, by redefining all standard directory macros of RPM, like %_prefix, %_bindir, %_datadir, ... It also defines the boolean macro %optinstall, so that you can easily make your package installing in /opt/<supplier>/ or at the usual location, simply by commenting out the %install_into_opt call and using "%if %optinstall" expressions.
This macro also defines the macros %_cupsserverroot, %_cupsserverbin, %_cupsdatadir, and %_cupsppd pointing to locations in /opt/<supplier>/ for CUPS config files and file auto-detection/conversion rules (/opt/<supplier>/cups/etc/), CUPS filters/backends (/opt/<supplier>/cups/lib/), for CUPS-related data files (/opt/<supplier>/cups/data/), and PPD files (/opt/<supplier>/ppds/). These directories (or the files in them) are automatically symlinked to the appropriate locations in the destination system by the maintainer scripts. So CUPS-related files should not be installed to the places which "./configure" detects from the CUPS installed on the build system, but into the locations where these macros point at, for example with appropriate command line options at the "make" command or by executing the macro %adjust_cups_dirs right after running "./configure", which replaces all occurences of the auto-detected CUPS paths anywhere in the source tree by the paths in /opt/<supplier>/.
%has_bin_executables %has_sbin_executables %has_man_pages
This three macros serve for appropriate search paths being set on package installation. Call the first if your driver contains auxiliary programs to be executed by normal users. This adds %_bindir (/opt/<supplier>/bin/) to the $PATH. The second is for drivers with auxiliary programs to be used only by the administrator as it adds %_sbindir (/opt/<supplier>/sbin/) to the $PATH. The third you should use if you ship man pages. It creates a $MANPATH and adds $_mandir (/opt/<supplier>/sbin/) to it. In addition, these macros set %binexec, %sbinexec, and %manpages to 1. These macros are ignored when %optinstall is not set (no call of %install_into_opt), as they do not make sense when the files get installed into the usual directories of the system.
After executing the commands in this section there will be automatically generated a file <source package name>.sh which will be installed into /opt/<supplier>/profile.d/ after the commands in the %install section got executed. This shell script contains all the commands to do the needed extensions on the $PATH and $MANPATH as requested via the %has_bin_executables, %has_sbin_executables, and %has_man_pages macros. The maintainer script put the file into /etc/profile.d/ or append it to the end of the file /etc/profile, so that the changes are applied whenever a login shell is opened. If not %install_into_opt and at least one of %has_bin_executables, %has_sbin_executables, and %has_man_pages were called before, no file is created.
Before executing the commands in the build section, the following environment variables are set:
CC=/opt/lsb/bin/lsbcc
CXX=/opt/lsb/bin/lsbc++
LDFLAGS='-L/opt/lsb/%{_lib}'
This way it is taken care that the LSB compilers and LSB-provided shared libraries are used.
%configure
Using the %configure macro (a macro already available in stock RPM) instead of directly using the "./configure" command sets automatically all installation directories. This is especially important in our packages where everything gets installed into subdirectories of /opt/<supplier>/ (using the %install_into_opt macro in the RPM header). The macros for the CUPS file locations %_cupsserverroot, %_cupsserverbin, %_cupsdatadir, and %_cupsppd do not get applied by this macro, as there are no standardized "configure" command line options for the CUPS directories. Most "configure" scripts do not allow setting these directories at all, they always use the directories auto-detected from the build system's CUPS installation.
%adjust_cups_dirs
As "configure" scripts usually set the directories for the CUPS-related files to the ones auto-detected from the CUPS installation on the build system, the directory settings need to be manually changed to %_cupsserverroot, %_cupsserverbin, %_cupsdatadir, and %_cupsppd after running the "configure" script. In some cases it can be done by supplying command line options to "make" in other cases files need to be patched. The %adjust_cups_dirs does the patching automatically. It searches all files in the source tree for occurrences of the auto-detected CUPS directories and replaces them with the directories defined by the macros %_cupsserverroot, %_cupsserverbin, %_cupsdatadir, and %_cupsppd. The call of this macro is ignored when the %install_into_opt macro was not called.
%make
This macro sets all important installation directories on the command line of "make". This is needed if there is no "configure" script or if "configure" does not set all directories in the Makefiles. Stock RPM does not provide this macro.
%build_foomatic_ppds
Many driver packages ship Foomatic XML data from which the PPDs are generated. To generate the PPDs the Foomatic packages "foomatic-db" (the Foomatic XML database) and "foomatic-db-engine" (the software to access the database and to generate the PPDs) are needed. After unpacking these two packages into the base directory of the source tree and adding the Foomatic XML files of this package to the unpacked "foomatic-db" via the %prep section and setting the %drivername macro correctly, a call of %build_foomatic_ppds generates the PPDs automatically. They will be available in the ppd subdirectory of the source tree. Take care to install them into the %_cupsppd directory in the %install section.
The environment variables CFLAGS, CXXFLAGS, and LDFLAGS are set the same way as in the %build section, before the commands in the %install section get executed. After the execution of the commands in this section the file <source package name>.sh gets installed into /opt/<supplier>/profile.d/.
%makeinstall
This macro has the same motivation as %configure and %make. It sets all important system directories using the RPM macros via the command line. It also preceeds every directory setting on the command line with the %buildroot macro. So the software gets installed into the temporary build directory set by "BuildRoot:" in the RPM header and not into the system. This is very convenient if a Makefile does not provide a DESTDIR option. This is a macro of stock RPM.
%remove_devel_files
The printer driver packages usually provide simply the software to make a certain class of printers and multi-function devices work. They do not supply libraries which can be used by other programs. So they do not need to ship C headers, static libraries, or pkgconfig files. Calling this macro after "make install" removes all these files and the %_includedir.
%adjust_ppds
This macro, called after "make install", rearranges and renames the PPD in %_cupsppd to conform with the agreements for LSB 3.2. All PPDs are put into subdirectories named by the printer manufacturers and renamed to <Manufacturer>-<Model>-<driver>-<language>.ppd. The manufacturer and model names and the language is taken from the PPD file and the drivername from the %drivername macro.
It also adds absolute paths to the filters in the "*cupsFilter" lines (except foomatic-rip, as foomatic-rip is part of the system and should not be shipped with the driver) and in the "*FoomaticRIPCommandLine" lines. For CUPS filters the path %{_cupsserverbin}/filter/ is added. For calls of executables coming with the driver being recognized as such the %filternames macro has to be set before calling %adjust_ppds. It must contain a comma-separated list of all executable names. Then %_bindir is added as absolute path. If a name with absolute path is given in %filternames, this path will be added.
With the macro %set_ppd_links being executed in the post-install script the PPDa get accessible as /usr/share/ppd/<supplier>/<Manufacturer>/<Manufacturer>-<Model>-<driver>-<language>.ppd, as agreed on for the LSB 3.2.
%remove_startup_links
There are special tools to set up and remove the distribution-specific links for the init scripts of services to be started on boot (links in /etc/rcN.d or /etc/init.d/rcN.d). So these links are set by the post-install andremoved by the pre-uninstall scripts using the LSB tools. Calling this macro removes such links created by "make install".
%init_scriptlet
This macro executes /etc/profile and the scripts in /etc/profile.d. It should be called in the beginning of each maintainer script to set the paths so that programs installed into /opt can be accessed by the maintainer scripts.
%update_only ... %end_update_only
Command which should only be executed during an update and not during a removal of the package should be bracketed by these two. This works both directly for the RPM package but also when converting the package to a Debian package with "alien --scripts".
%create_opt_dirs
This macro does nothing more than creating the three directories /opt, /etc/opt, and /var/opt. They usually have to exist on LSB-compliant systems but they do not exist always, for example in the LSB Build Environment chroot or in the LSB sample implementation they are missing.
%set_opt_paths
This macro either symlinks the file /opt/<supplier>/profile.d/<source package name>.sh (if it exists) into /etc/profile.d/ or appends its contents to the end of /etc/profile. This way it is assured that the paths for executables and man pages are set for the programs of this package being used when a login shell is started.
Ignored when package was built without %install_into_opt
%set_cups_links
This links all CUPS-related files into the system's CUPS directories: All files in %_cupsserverbin/filter are linked into the system's CUPS filter directory (usually /usr/lib/cups/filter), all files in %_cupsserverbin/backend into the backend directory (/usr/lib/cups/backend), and all *.types and *.convs files in %_cupsserverroot into the CUPS configuration directory (/etc/cups). This way CUPS finds the filters, backends, and file detection/conversion rules easily. This macro does not symlink the PPD files. Use %set_ppd_links for that.
Ignored when package was built without %install_into_opt
%set_ppd_links
Symlinks the %_cupsppd directory to /usr/share/ppd/<supplier>, so that the PPDs are accessible as /usr/share/ppd/<supplier>/<Manufacturer>/<Manufacturer>-<Model>-<driver>-<language>.ppd to fulfill the agreements for the LSB 3.2.
Ignored when package was built without %install_into_opt
%setup_services
Sets up system services coming with this package to be started at boot. For each service there must be a startup script in %{_rcdir}/init.d/ (/etc/init.d for conventional installation, /etc/opt/<package name>/init.d if package is built with %install_into_opt, then the scripts gets symlinked to /etc/init.d). If possible, the services are set up with the LSB tool /usr/lib/lsb/install_initd, if not common distribution-specific methods are used: "chkconfig<tt>" of Red Hat and derivatives, and "<tt>chkconfig" for Debian and derivatives. The names of the services (the init scripts) have to be supplied in a comma-separated list in the %services macro.
%setup_pam
If this package is installing in /opt and has PAM configuration files in %_pamdir (/etc/opt/<package name>/pam.d), these files get linked into /etc/pam.d to give the system's PAM access to the files.
%restart_cups
This does simply restart the CUPS daemon, so that changes like new *.types and *.convs files or in the case of CUPS 1.1.x being used new backends and PPDs, are taken into account by CUPS. The macro works with both "cups" and "cupsys" as service name for CUPS and uses Debian's "invoke-rc.d" if available.
%restart_services
With this macro all services of this package are restarted. The service names have to be supplied in a comma-separated list in the %services macro. Debian's "invoke-rc.d" is used if available.
%not_on_rpm_update ... %end_not_on_rpm_update
These two macros bracket steps not to be done on an RPM update. This has to be done on things removing infrastructure, as on an update RPM runs the post-install of the new package before the uninstall scripts of the old package, which makes the stuff set up by the post-install removed again. If the package is converted to a Debian package with "alien --scripts", the bracketed commands are executed, as uninstall scripts of the old version are run before the post-install scripts fo the new version.
%remove_opt_paths %remove_services %remove_pam
These macros remove symlinks, files, and configuration settings which the corresponding %set... and %setup... macros have put into the system directories. So a clean removal of the package is assured.
%not_on_rpm_update ... %end_not_on_rpm_update
Same as already shown for the pre-install script. Bracketed commands are not executed on an upgrade of RPM packages.
%remove_cups_links %remove_ppd_links %restart_cups %restart_services
Same as already shown for the post-install script. The first two take down CUPS-related links and the link to the PPD directory. The third restarts CUPS, the forth restarts all services as defined in the %services macro.
Always
CUPS Raster driver
Contains CUPS filters, backends, or *.types or *.convs files
Contains auxiliary programs to be used by ordinary users
Contains auxiliary programs to be used only by the administrator
Contains man pages
Has a "./configure" script
Has a Makefile
Has Foomatic XML data and no ready-made PPDs
Contains a shared library with C headers and pkgconfig files, but simply the driver should be provided, not development sources
Contains a daemon which should start on boot
Contains a daemon which should be restarted on package updates
Contains a daemon and "make install" creates the (distribution-specific) links to the init script so that the daemon gets started on boot
Has PAM support and contains PAM configuration files
Before a package gets released it should naturally be tested. Here are the recommended testing steps:
To assure that the binary executables work on all distributions if only the "lsb" package is installed, the executables need to be tested for LSB compliance. To do so you simply call
lsbappchk <name of the executable with full path>
Do this with all binary executables, which you find either in your ~/rpm/BUILD/<name of source tarball>/ directory and its subdirectories or after installation of your package (see how to install the package in the "Does it really work?" section below) in
/opt/<supplier>/bin /opt/<supplier>/sbin /opt/<supplier>/lib /opt/<supplier>/cups/lib/filter /opt/<supplier>/cups/lib/backend
If there are complaints about interfaces being used which are not provided by the LSB, take care that libraries providing these symbols get either statically linked or shipped with your package.
To assure that the PPD files work well together with the printing system and PPD-aware applications, check whether the PPDs are compliant with the Adobe specifications. To do this, run the command
cupstestppd <name of the PPD file with full path>
on every PPD file which you include in your package. If you get a "PASS" all is OK. In the case of a "FAIL" it is shown which specifications are not fulfilled.
To test whether your driver package really works, install it in the LSB Build Environment chroot and also in real distributions.
Unfortunately, the chroot is not completely set up from RPMs, so most software which exists in the chroot does not exist in the RPM database of the chroot. So a simple RPM installation of your package will fail due to dependencies not being fulfilled. Therefore use always the "--nodeps" option when installing your packages into the chroot:
rpm -Uvh --nodeps <package file name>
To test actual printing out of the chroot, stop your system's CUPS daemon and then start the one inside the chroot. Or configure the CUPS daemon inside the chroot to use another port than 631 ("Port" or "Listen" directive in cupsd.conf, "ServerName localhost:<port>" in client.conf), to keep your system's printing environment working.
If access to the /proc file system is needed from within the chroot, either for observing the printing processes with "ps" or if your driver needs it, simply mount it manually using the command:
mount -t proc none /proc
For testing in a real distribution installation of the package should work as described in the user instructions on the OpenPrinting web site. Especially it should be enough to install the "lsb" package, CUPS, Ghostscript, Perl, and foomatic-filters (packages shipped with the distribution) to be able to install the driver package without the "--nodeps" option (or the "--force-depends" option for Debian).
After having installed your package, try to set up print queues with the printer setup tools which come with the distribution. Your driver should then appear as one of the possible choices, or it will be automatically selected by the tools if it is the only driver for the printer with which you are testing. If your package ships CUPS backends, check whether tey appear under the device connection types in the setup tool and whether they detect your printer correctly.
Try to print from different applications and with different option settings, to see whether everything works as it should work. Try also if your driver's auxiliary programs work correctly.
If you want to have some examples of driver packages, see these RPM spec files and these source RPMs. They were used for generating the appropriate binary packages in the OpenPrinting database.