4 - Advanced Packaging with EPM

This chapter describes the advanced packaging features of EPM.

Including Other List Files

The %include directive includes another list file:

    %include filename

Includes can usually be nested up to 250 levels depending on the host operating system and libraries.

Dependencies

EPM supports four types of dependencies in list files: %incompat, %provides, %replaces, and %requires. Table 4.1 shows the level of support for each package format.

Table 4.1: Dependency Support
Format %incompat %provides %replaces %requires
aix No No Yes Yes
bsd Yes No No Yes
deb Yes Yes1 Yes Yes
inst Yes No Yes Yes
osx No No No No
pkg Yes No No Yes
portable Yes Yes Yes Yes
rpm Yes Yes No Yes
setld No No No No
slackware No No No No
swinstall No No Yes Yes
  1. Debian's package format does not currently support version numbers for %provides dependencies.

 

Software conflicts and requirements are specified using the %incompat and %requires directives.

If your software replaces another package, you can specify that using the %replaces directive. %replaces is silently mapped to %incompat when the package format does not support package replacement.

If your package provides certain functionality associated with a standard name, the %provides directive can be used.

Dependencies are specified using the package name and optionally the lower and upper version numbers:

    %requires foobar
    %requires foobar 1.0
    %incompat foobar 0.9
    %replaces foobar
    %replaces foobar 1.2 3.4
    %provides foobar

or the filename:

    %requires /usr/lib/libfoobar.so
    %incompat /usr/lib/libfoobar.so.1.2

Package dependencies are currently enforced only for the same package format, so a portable distribution that requires package "foobar" will only look for an installed "foobar" package in portable format.

Filename dependencies are only supported by the Debian, portable, and RPM distribution formats.

Scripts

Bourne shell script commands can be executed before or after installation, patching, or removal of the software. Table 4.2 shows the support for scripts in each package format.

The %preinstall and %postinstall directives specify commands to be run before and after installation, respectively:

    %preinstall echo Command before installing
    %postinstall echo Command after installing

Similarly, the %prepatch and %postpatch directives specify commands to be executed before and after patching the software:

    %prepatch echo Command before patching
    %postpatch echo Command after patching

Finally, the %preremove and %postremove directives specify commands that are run before and after removal of the software:

    %preremove echo Command before removing
    %postremove echo Command after removing
Table 4.2: Scripts Support
Format %preinstall %postinstall %prepatch %postpatch %preremove %postremove
aix Yes Yes No No Yes Yes
bsd No Yes No No Yes No
deb Yes Yes No No Yes Yes
inst Yes Yes No No Yes Yes
osx Yes Yes No No No No
pkg Yes Yes No No Yes Yes
portable Yes Yes Yes Yes Yes Yes
rpm Yes Yes No No Yes Yes
setld Yes Yes No No Yes Yes
slackware No Yes No No No No
swinstall Yes Yes No No Yes Yes

 

To include an external script file, use the <filename notation:

    %postinstall <filename

To include multiple lines directly, use the <<string notation (a.k.a. a "here" document):

    %postinstall <<EOF
    echo Command before installing
    /usr/bin/foo
    EOF

Note that all commands specified in the list file will use the variable expansion provided by EPM, so be sure to quote any dollar sign ($) characters in your commands. For example, "$foo" is replaced by the value of "foo", but "$$foo" becomes "$foo".

Conditional Directives

The %system directive can match or not match specific operating system names or versions. The operating system name is the name reported by uname in lowercase, while the operating system version is the major and minor version number reported by uname -r:

%system irix
 
Only include the following files when building a distribution for the IRIX operating system.
 
%system linux-2.0
 
Only include the following files when building a distribution for Linux 2.0.x.
 
%system !irix !linux-2.0
 
Only include the following files when building a distribution for operating systems other than IRIX and Linux 2.0.x.
 

The special name all is used to match all operating systems:

    %system all

For format-specific files, the %format directive can be used:

%format rpm
 
Only include the following files when building an RPM distribution.
 
%format !rpm
 
Only include the following files when not building an RPM distribution.x.
 
%format all
 
Include the following files for all types of distributions.
 

The %arch directive can match or not match specific architectures. The architecture name is the name reported by uname -m; "arm" is a synonym for "armv6", "armv7", and "armv8", "intel" is a synonym for "i386", "i486", "i586", and "i686", and "powerpc" is a synonym for "ppc":

%arch intel
 
Only include the following files when building a package for 32-bit Intel processors.
 
%arch armv6
 
Only include the following files when building a package for ARMv6 processors.
 
%system !powerpc
 
Only include the following files when building a package for processors other than PowerPC.
 

The special name all is used to match all architectures:

    %arch all

Finally, EPM can conditionally include lines using the %if, %elseif, %ifdef, %elseifdef, %else, and %endif directives.

%if directives include the text that follows if the named variable(s) are defined to a non-empty string:

    %if FOO
    f 755 root sys /usr/bin/foo foo
    %elseif BAR
    f 755 root sys /usr/bin/bar bar
    %endif

%ifdef directives only include the text if the named variable(s) are defined to any value:

    %ifdef OSTYPE
    f 755 root sys /usr/bin/program program-$OSTYPE
    %else
    f 755 root sys /usr/bin/program program.sh
    %endif

Protecting Object Files from Stripping

The nostrip() option can be included at the end of a file line to prevent EPM from stripping the symbols and debugging information from a file:

    f 755 root sys /usr/lib/libfoo.so libfoo.so nostrip()

Software Patches

EPM supports portable software patch distributions which contain only the differences between the original and patch release. Patch files are specified using uppercase letters for the affected files. In the following example, the files /usr/bin/bar and /etc/foo.conf are marked

as changed since the original release:

    f 755 root sys /usr/bin/foo foo
    F 755 root sys /usr/bin/bar bar
    f 755 root sys /usr/share/man/man1/foo.1 foo.man
    f 755 root sys /usr/share/man/man1/bar.1 bar.man
    C 644 root sys /etc/foo.conf foo.conf

Variables

EPM imports the current environment variables for use in your list file. You can also define new variable in the list file or on the command-line when running EPM.

Variables are defined by starting the line with the dollar sign ($) followed by the name and value:

    $name=value
    $prefix=/usr
    $exec_prefix=${prefix}
    $bindir=$exec_prefix/bin

Variable substitution is performed when the variable is defined, so be careful with the ordering of your variable definitions.

Also, any variables you specify in your list file will be overridden by variables defined on the command-line or in your environment, just like with make. This can be a useful feature or a curse, depending on your choice of variable names.

As you can see, variables are referenced using the dollar sign ($). As with most shells, variable names can be surrounded by curly braces (${variable}) to explicitly delimit the name.

If you need to insert a $ in a filename or a script, use $$:

    %install echo Enter your name:
    %install read $$name
    %install echo Your name is $$name.

Init Scripts

Initialization scripts are generally portable between platforms, however the location of initialization scripts varies greatly.

The i file type can be used to specify and init script that is to be installed on the system. EPM will then determine the appropriate init file directories to use and create any required symbolic links to support the init script:

    i 755 root sys foo foo.sh

The previous example creates an init script named foo on the end-user system and will create symbolic links to run levels 0, 2, 3, and 5 as needed, using a sequence number of 00 (or 000) for the shutdown script and 99 (or 999) for the startup script.

To specify run levels and sequence numbers, use the runlevel(), start(), and stop() options:

    i 755 root sys foo foo.sh "runlevel(02) start(50) stop(30)"

Literal Package Data

Sometimes you need to include format-specific package data such as keywords, signing keys, and response data. The %literal(section) directive adds format-specific data to the packages you create. Literal data is currently only supported for RPM and PKG packages.

PKG Literal Data

PKG packages support request files that are used to do batch installations when installation commands require user input. The %literal(request) directive can be used to provide this user input:

    %literal(request) <<EOF
    John Doe
    1 Any Lane
    Forest Lawn, OH 12345
    EOF

RPM Literal Data

RPM packages support numerous attributes in the "spec" file that control how the package is created and what metadata is included with the package. The %literal(spec) directive can be used to provide attributes for the spec file:

    %literal(spec) <<EOF
    %changelog
    * Tue Aug 26 2008 John Doe <johndoe@domain.com>

    - Added new feature "bar"

    * Fri Aug 1 2008 John Doe <johndoe@domain.com>

    - Added new feature "foo"
    EOF