Application Developer's Guide

Revision History
Revision 0.9.52002-06-19
Add document license

Table of Contents
1. Introduction
1.1. What is the LSB?
1.2. Why develop an LSB-compliant application?
1.3. Overview of the LSB Specification
1.4. Who Defines the LSB?
2. Developers' Checklist
3. Definitions
4. Resources
4.1. Related Standards
4.2. Related Implementations
5. Programming Guidelines
5.1. APIs for LSB-Compliant Applications
5.2. What to Expect from an LSB-Compliant Environment
6. Build Tools
7. Packaging
7.1. Filesystem Hierarchy Standard
7.2. Packaging Tool
7.3. LSB-imposed Restrictions
8. Mechanics
8.1. LSB Environment
8.2. Chroot Build Environment
8.3. gcc Wrapper
8.4. LSB Test Suite
9. Configuring a Debian system for LSB-compliant Application Development
9.1. Setting up the LSB development environment
9.2. Setting up lsbappchk
10. Configuring a RedHat system for LSB-compliant Application Development
10.1. Setting up the LSB development environment
10.2. Setting up lsbappchk
11. Examples
11.1. An LSB-Compliant Application
11.2. A Non-LSB-Compliant Application
11.3. A Complex LSB-Compliant Application
12. Credits

1. Introduction

The Application Developers' Guide covers the highlights and specifics that are important when developing LSB-compliant applications for Linux. This guide is intended to apply generally for the various Linux distributions. Some adjustments may need to be made for each distribution.

This section of the guide explains what the Linux Standard Base is all about, its function, and who defines the specifications.


1.3. Overview of the LSB Specification

At first, the LSB Specification can appear to be an unwieldy mass of information. This section provides a more manageable summary of the type of information covered in the LSB Specification.

The LSB is composed of two basic parts: A common part of the specification, also known as the generic LSB (gLSB), that describes those parts of the interface that remain constant across all hardware implementations of the LSB; and an architecture-specific part of the specification that describes the parts of the specification that are specific to a particular processor architecture. Together, the generic LSB and the architecture-specific supplement for a single hardware architecture provide a complete interface specification for compiled application programs on systems that share a common hardware architecture.

Section I of the gLSB is the Introduction. The purpose of the LSB, related standards and implementations, relevant libraries, instructions on using the LSB, and definitions and terminology are covered in the introduction.

Section II of the gLSB covers object file formats. LSB-complying implementations shall support the object file Executable and Linking Format (ELF). The bulk of this section is devoted to details about ELF such as ELF section types, Linux section types, ELF and Linux special section types, symbol mapping in the C and C++ languages, and symbol versioning.

Section III of the gLSB covers dynamic linking. LSB-complying implementations shall support the object file information and system actions that create running programs as specified in the System V Application Binary Interface, Edition 4.1 and the System V Application Binary Interface - DRAFT - April 29, 1998 and as supplemented by the gLSB and an architecture-specific LSB specification. Any shared object that is loaded must contain sufficient DT_NEEDED records to satisfy the symbols in the shared library. Details about ELF dynamic entries and Linux dynamic entries make up the bulk of this section. Details about the program interpreter are covered in the appropriate architecture-specific LSB specification.

Sections IV, V, and VI of the gLSB cover libraries. The specific APIs provided by these libraries are detailed in the gLSB. Only the general category of the interfaces (for example, string functions) is detailed in this guide.

Section IV of the gLSB covers base libraries. The base libraries include libc, libm, libpthread, libdl, libcrypt, and librt. The interfaces for libc include RPC interfaces, system calls, standard I/O, signal handling, standard libraries, localization, socket interface functions, wide characters, string functions, IPC functions, regular expressions, character type functions, time manipulation, terminal interface functions, system database interface functions, language support, and large file support. The interfaces for libm include math interfaces. The interfaces for libpthread include POSIX thread interfaces. LSB-complying implementations support POSIX threads with the following exceptions. This list is intended to match the behavior of historical Linux implementations. Applications should be written to deal with either POSIX threads or the thread behaviors described here.

  • POSIX specifies a concept of per-process rather than per-thread signals. The LSB does not require this behavior; traditional Linux implementations have had per-thread signals only. A related issue is that applications cannot rely on getpid() returning the same value in different threads.

  • Note: one implication of per-thread signals is that a core dump (for example) may not stop all threads in a given process. This may be an issue when designing ways to stop/start applications.

  • Applications which create child processes (using fork() and the like) must then wait for them (using waitpid() family of functions) in the same thread as they created them. Note that coding applications this way will work both with full POSIX threads and legacy Linux thread implementations.

  • POSIX specifies that changing the user or group id instantly affects the behavior of all threads. This behavior is not specified; applications must use their own lock if they need this behavior. Rationale: it seems unnecessary and it is a performance hit (an SMP kernel must lock the user id).

  • Although the gLSB doesn't specify a way to list processes, it is the intention of the authors of the LSB to not specify whether multiple threads appear as separate processes or as a single process.

  • Applications cannot rely on resource limits (getrusage and setrusage) being maintained per-process rather than per-thread.

  • Applications must disconnect from the controlling tty before calling pthread_create.

  • times() doesn't account for all threads, just the caller

  • Applications must not call pthread_cancel if they call any system libraries (most notably X Window System libraries), as system libraries are not guaranteed to be thread safe. Likewise, for such libraries, only one thread per process may call them.

  • Applications cannot rely on fcntl/lockf locks being visible per-process rather than per-thread. Likewise for mandatory file locks.

  • Threaded applications cannot use SIGUSR1 or SIGUSR2

The interfaces for libdl include dynamic loader function interfaces. The interfaces for libcrypt include encryption function interfaces. The interfaces for librt include asynchronous I/O function interfaces.

Section V of the gLSB covers utility libraries. The utility libraries include libz, libncurses, and libutil. The interfaces for libz include compression library function interfaces. The interfaces for libncurses include Curses function interfaces. The interfaces for libutil include utility function interfaces.

Section VI of the gLSB covers graphics libraries. The graphics libraries include libX11, libXext, libSM, libICE, libXt, and libGL. The interfaces for libX11 include X Windows System Interface function interfaces. The interfaces for libXext include X Shape Extension function interfaces, X Display Power Management Signaling Extension function interfaces, X Shared Memory Extensions function interfaces, X Security Extension function interfaces, and X Double Buffer Extension function interfaces. The interfaces for libSM include Session Management Functions function interfaces. The interfaces for libICE include Inter-Client Exchange (ICE) Protocol Functions function interfaces. The interfaces for libXt include X Toolkit function interfaces. The interfaces for libGL include GL X interface function interfaces and OpenGL® function interfaces.

Section VII of the gLSB covers Package Format and Installation. Applications should be provided in the RPM packaging format as defined in the appendix of Maximum RPM, with some restrictions. See "LSB-imposed Restrictions". Package naming conventions and package dependencies are also detailed in this section.

Section VIII of the gLSB provides an exhaustive list of the commands and utilities specified by the LSB and their various command-line options.

Section IX of the gLSB defines the standard shell that must be available in an LSB-compliant environment. Currently, the LSB defines minor exceptions so that bash meets its requirements.

Section X of the gLSB defines specifics about users and groups in LSB-compliant environments.

Section XI of the gLSB defines the execution environment of LSB-complying systems. The execution environment consists of the File System Hierarchy (the FHS 2.2) plus additional recommendations on directory and file permissions.

Section XII of the gLSB defines the system initialization environment including cron jobs, run levels, init script actions, comment conventions for init scripts, installation and removal of init.d files, facility and script naming conventions, and init script functions.

Appendix A of the gLSB provides and alphabetical listing of the APIs defined in the gLSB.

The LSB IA32 defines low level system information, object file formats, program loading and dynamic linking, and base libraries that are unique to the IA32 platform.

The LSB IA64 defines low level system information, object file formats, program loading and dynamic linking, base libraries, and the execution environment that are unique to the IA64 platform. The LSB IA64 is currently available only as a draft.


2. Developers' Checklist

This section provides a general overview of how to develop LSB-compliant applications.

Developers that want to write LSB-compliant applications should be sure to follow the checklist below. More information about the items in the checklist is available in the remaining sections of this guide.


3. Definitions

This section provides definitions for terms used within the gLSB. Some of these definitions cover the requirements for the term as well.


4. Resources

There are several references available that cover different aspects of the LSB specification. Some of these documents and their locations are listed in this section.


4.1. Related Standards

The specifications listed below are referenced in whole or in part by the LSB specifications. Such references may be normative or non-normative; a reference to a specification shall only be considered normative if it is explicitly cited as such. The LSB specifications may make normative references to a portion of these specifications (that is, to define a specific function or group of functions); in such cases, only the explicitly referenced portion of the specification is to be considered normative.

Table 1. Related Standards

System V Application Binary Interface - DRAFT - 22 June 2000http://www.caldera.com/developers/gabi/2000-07-17/contents.html
Filesystem Hierarchy Standard 2.2http://www.pathname.com/fhs/
IEEE Standard for Binary Floating-Point Arithmetic (ANSI/IEEE Standards 745-1985 and 854-1987)http://www.ieee.org/
System V Application Binary Interface, Edition 4.1http://www.caldera.com/developers/devspecs/gabi41.pdf
IA32 Architecture Software Developer's Manual Volume 1: Basic Architecturehttp://developer.intel.com/design/pentium4/manuals/245470.htm
IA32 Architecture Software Developer's Manual Volume 2: Instruction Set Referencehttp://developer.intel.com/design/pentium4/manuals/245471.htm
IA32 Architecture Software Developer's Manual Volume 3: System Programming Guidehttp://developer.intel.com/design/pentium4/manuals/245472.htm
System V Application Binary Interface - Intel386 Architecture Processor Supplementhttp://www.caldera.com/developers/devspecs/abi386-4.pdf
Itanium™ Architecture Software Developer's Manual Volume 1: Application Architecturehttp://www.intel.com/design/itanium/downloads/24531703s.htm
Itanium™ Architecture Software Developer's Manual Volume 2: System Architecturehttp://www.intel.com/design/itanium/downloads/24531803s.htm
Itanium™ Architecture Software Developer's Manual Volume 3: Instruction Set Referencehttp://developer.intel.com/design/itanium/downloads/24531903s.htm
Intel® Itanium™ Processor Reference Manual for Software Developmenthttp://developer.intel.com/design/itanium/downloads/24532003s.htm
Itanium™ Software Conventions & Runtime Architecture Guidehttp://developer.intel.com/design/itanium/downloads/24535803s.htm
ISO/IEC 9899: 1990, Programming Languages --C
ISO/IEC 9899: 1999, Programming Languages --C
Linux Assigned Names And Numbers Authorityhttp://www.lanana.org/
Large File Supporthttp://www.UNIX-systems.org/version2/whatsnew/lfs20mar.html
Linux Standard Basehttp://www.linuxbase.org/spec/
OpenGL® Application Binary Interface for Linux®http://oss.sgi.com/projects/ogl-sample/ABI/
IEEE Std POSIX 1003.2-1992 (ISO/IEC 9945-2:1993)http://www.ieee.org/
POSIX 1003.1chttp://www.ieee.org/
CAE Specification, May 1996, X/Open Curses, Issue 4, Version 2 (ISBN 1-85912-171-3, C610), plus Corrigendum U018http://www.opengroup.org/
CAE Specification, January 1997, System Interface Definitions (XBD), Issue 5 (ISBN: 1-85912-186-1, C605)http://www.opengroup.org/
CAE Specification, January 1997, Commands and Utilities (XCU), Issue 5 (ISBN 1-85912-191-8, C604)http://www.opengroup.org/
CAE Specification, February 1997, Networking Services (XNS), Issue 5 (ISBN 1-85912-165-9, C523)http://www.opengroup.org/
CAE Specification, January 1997, System Interfaces and Headers (XSH), Issue 5 (ISBN 1-85912-181-0, C606)http://www.opengroup.org/
The Single UNIX® Specification Version 1 (UNIX® 95) System Interfaces & Headershttp://www.opengroup.org/
System V Interface Definition, Issue 3 (ISBN 0201566524)
System V Interface Definition, Fourth Edition
Double Buffer Extension Libraryhttp://www.x.org/
X Display Power Management Signaling (DPMS) Extension, Library Specificationhttp://www.x.org/
X Record Extension Libraryhttp://www.x.org/
Security Extension Specification, Version 7.1http://www.x.org/
X Nonrectangular Window Shape Extension Library Version 1.0http://www.x.org/
MIT-SHM--The MIT Shared Memory Extensionhttp://www.x.org/
X Synchronization Extension Libraryhttp://www.x.org/
XTEST Extension Libraryhttp://www.x.org/
X11R6.4 X Inter-Client Exchange (ICE) Protocolhttp://www.x.org/
X11R6.4 X11 Input Extension Libraryhttp://www.x.org/
X11R6.4 Xlib - C Libraryhttp://www.x.org/
X/Open Portability Guide, Issue 4http://www.opengroup.org/
X11R6.4 X Session Management Libraryhttp://www.x.org/
X11R.4 X Toolkit Intrinsicshttp://www.x.org/
zlib 1.1.3 Manualhttp://www.gzip.org/zlib/

5. Programming Guidelines


6. Build Tools

This section provides a short list of some of the important LSB-related tools, along with references to other parts of this document where they are discussed in greater detail.

lsbcc

Not yet provided by the LSB organization. See "gcc Wrapper"

rpmbuild

Part of the RPM package maintained by the LSB organization. Used to create RPM packages. See "Packaging Tool"

chroot build environment

Provided by the lsbdev package. See "Chroot Build Environment"


7. Packaging

An important part of the LSB specification is the packaging. This section covers the important information concerning packaging of the developed application, such as the filesystem hierarchy and the tool to use for packaging the final application.


7.1. Filesystem Hierarchy Standard

The gLSB relies on the Filesystem Hierarchy Standard (FHS) version 2.2 to define the layout of an LSB-compliant distribution.

Components of the filesystem that are labeled as optional by the FHS must be handled as such by LSB-compliant applications. Applications are required not to assume that those pieces are available.

As an example, the /root directory as the home directory for the root user is optional, albeit recommended. Applications that must access root's home directory might check the invoking user's HOME environment variable[1] and/or use the getpwent function to determine root's home directory if /root does not exist (and perhaps even if it does). Further, as root may be logged onto a system in maintenance mode without all filesystems mounted, if root's home directory isn't mounted, applications should fall back to / for that purpose.


8. Mechanics

The LSB organization specifies the build environment as well as the proper compiler arguments necessary to build an LSB-compliant application. This section covers those details as found in the gLSB.


8.2. Chroot Build Environment

For a high level of confidence that a package uses only LSB-guaranteed commands and interfaces, the lsbdev package provides a chroot environment.

Here are some issues to be aware of when setting up the LSB chroot.

To log into the chroot environment, run the following command (or its equivalent in your environment): ssh -p 5436 localuser@localhost


8.4. LSB Test Suite

The LSB organization provides utilities to test applications, libraries, and operating environments for compliance with its specifications. You can find the main test web page at http://www.linuxbase.org/test/.

Note: http://www.linuxbase.org/test/appcheck.html, linked from that page, refers to lsbcc as if it exists; as of this writing, no such tool seems to be available from the LSB FTP site.

The most important tool for application developers is lsbappchk. Its usage is shown below:

lsbappchk [-L libpath...] {executable}

It neither reports success nor returns a useful exit code. Instead, it always outputs the version of the LSB specification against which it checks the executable's compliance, and then it reports any concerns that it finds.

The -L libpath option allows lsbappchk to trace unidentified library symbols to libraries that will be shipped with the executable; otherwise, lsbappchk would report those symbols as undefined within the LSB specification.

lsblibchk is a similar tool that takes no arguments. It checks runtime libraries in an environment to verify that the right versions of the LSB-specified interfaces are available.

The LSB test suite project also provides more comprehensive tools to test an environment for LSB compliance. These tools use the "Test Environment Toolkit" as a framework.


9. Configuring a Debian system for LSB-compliant Application Development

9.1. Setting up the LSB development environment

  1. Install a Linux 2.4 kernel for your system architecture
    
# apt-get update
    # apt-get install kernel-image-2.4.17-686
                

  2. Install the dependencies for the lsb-rpm package
    
# apt-get update
    # apt-get install libbz2-1.0 libc6 libpopt0 zlib1g
                

  3. Download and install the LSB development applications (lsb-rpm and lsbdev) from ftp://ftp.freestandards.org/pub/lsb/lsbdev/
    
# dpkg -i lsb-rpm_4.0.3-1.03_i386.deb
    # dpkg -i lsbdev_1.1.0-1_i386.deb
                

  4. Edit the lsbdev configuration files (lsbdev.conf, extra_mount_dirs.conf, extra_mount_files.conf) in /etc/lsbdev/ to your liking. The lsbdev.conf file is used to configure the overall LSB build environment chroot. Configuration options include the location of the chroot environment on the local filesystem, the location of the LSB stub libraries, a space separated list of users whose home directories will be automatically bind-mounted into the chroot area, the location of the LSB header files, among others. The extra_mount_dirs.conf file is used to configure additional directories to be bind-mounted into the chroot area. The extra_mount_files.conf file is used to configure additional files to be bind-mounted into the chroot area.

  5. Start the LSB development environment:
    
# /etc/init.d/lsbdev start
    Starting LSB build environment
    Failed to get home directory for cyeoh. Skipping user cyeoh
    Failed to get home directory for vsx0. Skipping user vsx0
    Warning. No LSB header files available. Using system include
    files. The binaries produced may not be LSB compliant.
                

    The LSB header files are included in the lsbdev package, but disabled by default. To enable the inclusion of the LSB header files, edit the /etc/lsbdev/lsbdev.conf file and change the LSB_INCLUDE line to LSB_INCLUDE=$DATA_ROOT/lsb_header or the location of the LSB header files on your system. The LSB header files are located in /var/opt/lsbdev/lsb_header by default.

  6. Connect to the LSB development environment:
    
$ /usr/bin/slogin -p 5436 username@hostname
                

  7. You now have configured a Debian system for LSB-compliant application development. Once you have compiled your application, you should run the lsbappchk program against your executable(s) to verify that they are LSB-compliant.


9.2. Setting up lsbappchk

  1. Download lsbappchk from ftp://ftp.freestandards.org/pub/lsb/test_suites/released-1.1.0/binary/application/. lsbappchk is currently available in RPM format only.

    The proper way to install RPM packages on Debian systems is to first convert them to deb packages using alien and then install the resulting deb package.

  2. Install alien
    
# apt-get update
    # apt-get install alien
                  

  3. Convert the lsbappchk RPM package to a deb package. The resulting deb package will have a minor version increment.
    
$ alien lsbappchk-1.1.1-2.i386.rpm
                  

  4. Install lsbappchk
    
# dpkg -i lsbappchk_1.1.1-3_i386.deb
                  


10. Configuring a RedHat system for LSB-compliant Application Development

10.1. Setting up the LSB development environment

  1. The LSB development environment requires a Linux 2.4 kernel. Redhat 7.1 and 7.2 include Linux 2.4 kernels by default. If you are not running Redhat 7.1 or 7.2, you should install a Linux 2.4 kernel.

  2. The LSB development environment requires an existing ssh server running on the lsbdev machine and files provided by the glibc-devel and binutils packages. If you do not have binutils, glibc-devel, and openssh-server installed, you should install them.

  3. Insure you have the dependencies for the lsb-rpm package installed.
    
# rpm -q gawk fileutils textutils mktemp shadow-utils
                

    If you get any package is not installed errors, you will need to install the missing package(s).

  4. Download and install the LSB development applications (lsb-rpm and lsbdev) from ftp://ftp.freestandards.org/pub/lsb/lsbdev/
    
# rpm -Uvh lsb-rpm-4.0.3-1.03.i386.rpm
    # rpm -Uvh lsbdev-1.1.0-1.i386.rpm
                

  5. Edit the lsbdev configuration files (lsbdev.conf, extra_mount_dirs.conf, extra_mount_files.conf) in /etc/lsbdev/ to your liking. The lsbdev.conf file is used to configure the overall LSB build environment chroot. Configuration options include the location of the chroot environment on the local filesystem, the location of the LSB stub libraries, a space separated list of users whose home directories will be automatically bind-mounted into the chroot area, the location of the LSB header files, among others. The extra_mount_dirs.conf file is used to configure additional directories to be bind-mounted into the chroot area. The extra_mount_files.conf file is used to configure additional files to be bind-mounted into the chroot area.

  6. Start the LSB development environment:
    
# /etc/init.d/lsbdev start
    Starting LSB build environment
    Failed to get home directory for cyeoh. Skipping user cyeoh
    Failed to get home directory for vsx0. Skipping user vsx0
    Warning. No LSB header files available. Using system include
    files. The binaries produced may not be LSB compliant.
                

    The LSB header files are included in the lsbdev package, but disabled by default. To enable the inclusion of the LSB header files, edit the /etc/lsbdev/lsbdev.conf file and change the LSB_INCLUDE line to LSB_INCLUDE=$DATA_ROOT/lsb_header or the location of the LSB header files on your system. The LSB header files are located in /var/opt/lsbdev/lsb_header by default.

  7. Connect to the LSB development environment:
    
$ /usr/bin/slogin -p 5436 username@hostname
                

  8. You now have configured a RedHat system for LSB-compliant application development. Once you have compiled your application, you should run the lsbappchk program against your executable(s) to verify that they are LSB-compliant.


11. Examples

The following examples illustrate an LSB-compliant application and a non-compliant application. Though both examples are simple programs, they provide the program code and the results. Note that these examples should be run in the LSB build environment.


11.1. An LSB-Compliant Application

A simple "hello world" program, hw.c


#include <stdio.h>

int
main(int argc, char *argv[])
{
    printf("Hello World!\n");
    return 0;
}
      

Compile the "hello world" program and link it with the LSB loader and libraries.


$ gcc -o hw -Wall hw.c -L/usr/lib/lsb-stub -Wl,--dynamic-linker=/lib/ld-lsb.so.1
      

Test to see if the "hello world" program works.


$ ./hw
Hello World!
      

Test to see if the "hello world" program is using the LSB loader and libraries


$ ldd hw
libc.so.6 => /lib/libc.so.6
/lib/ld-lsb.so.1 => /lib/ld-lsb.so.1
      

Test whether the "hello world" program is LSB-compliant.


$ lsbappchk hw
      

If there is any output from lsbappchk, then it detected API calls that are not specified by the gLSB.

To correct this situation, the programmer has the following options:


11.2. A Non-LSB-Compliant Application

A simple "domain name" program, dn.c


#include <stdio.h>
#include <unistd.h>

int
main(int argc, char *argv[])
{
    char domain[BUFSIZ];
    int rc;

    rc = call_my_non_lsb_getdomainname((char *)&domain, BUFSIZ);

    if (0 == rc) {
        printf("domainname is: %s\n", domain);
    }
}
        

Compile the "domain name" program and link it with the LSB loader and libraries.


$ gcc -o dn -Wall dn.c -L/usr/lib/lsb-stub -Wl,--dynamic-linker=/lib/ld-lsb.so.1
dn.c: In function `main':
dn.c:14: warning: control reaches end of non-void function
/tmp/ccHpOeFD.o: In function `main':
/tmp/ccHpOeFD.o(.text+0x16): undefined reference to
`call_my_non_lsb_getdomainname'
collect2: ld returned 1 exit status
        

The dn.c failed to link with the LSB filter libraries because the API call_my_non_lsb_getdomainname is not defined.

Let's assume that we were able to compile and link some libraries and are using the correct LSB loader. Test to verify with lsbappchk that the domain name application is using only LSB-specified APIs.


$ lsbappchk dn
call_my_non_lsb_getdomainname
        

The LSB's lsbappchk output call_my_non_lsb_getdomainname, so it detected an API call that is not specified by the gLSB. To correct this problem, the application should discontinue the use of those APIs, or a trouble report should be sent to the LSB organization.


11.3. A Complex LSB-Compliant Application

The previous two examples were very simple in nature. In this section we will examine a much more complex situation. The goal will be take take an existing piece of software and bring it into compliance with the LSB specifications and then build an LSB-compliant RPM package.

For this example we will be using an existing application named Mutt. Mutt is a very powerful text-based mail user agent which runs on a variety of operating systems. In this example with Mutt we will come across a variety of issues and see how to resolve them as you might with your own application.

To work through this example it will be helpful to have a LSB chroot build environment at your disposal. You should configure the LSB chroot to utilize the system header files by setting LSB_INCLUDE in the lsbdev.conf file to null (that is, "LSB_INCLUDE=", without the quotes, should appear in your lsbdev.conf file without anything after the equal sign. Assuming you have started the LSB chroot build environment as described previously in this document you can login by running the following.


% ssh -p 5436 username@hostname
    

Now logged into our LSB environment, we are ready to begin. The first step will be to retrieve and extract the source to Mutt. Chapter 14 of the LSB specification requires the presence of various commands and utilities. Among those mandated are rsync and GNU tar.


% cd /var/tmp
% rsync -v ftp.mutt.org::mutt/mutt-1.3.27i.tar.gz .
mutt-1.3.27i.tar.gz
wrote 21832 bytes  read 14602 bytes  10409.71 bytes/sec
total size is 2536093  speedup is 69.61
% tar xzf mutt-1.3.27i.tar.gz
% cd mutt-1.3.27
    

Equipped with the source, we can start figuring out what kinds of changes, if any, we will need to make to bring Mutt into compliance with the LSB specification. If we read the INSTALL file distributed with Mutt we will discover that Mutt uses the commonplace ./configure && make && make install process for building and installing. Let's begin by trying to configure Mutt.


% CC=lsbcc ./configure
creating cache ./config.cache
checking for a BSD compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking whether make sets ${MAKE}... yes
checking for working aclocal... found
[ irrelevant text trimmed ]
checking for fchdir... yes
checking for regcomp... yes
checking whether your system's regexp library is completely broken... no
checking where new mail is stored... no
configure: error: Could not determine where new mail is stored.
    

The configure step failed because it could not determine where mail is to be stored. Running ./configure --help will show us that there is a --with-mailpath option that lets us specify the path to where mail is stored. The question remains though, where should that be? Chapter 17 of the LSB specification declares that the file system should be laid out as specified in FHS 2.2. The FHS website has the 2.2 version of the standard, and reading it will reveal that mail should be stored in /var/mail.


% CC=lsbcc ./configure --with-mailpath=/var/mail
creating cache ./config.cache
checking for a BSD compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking whether make sets ${MAKE}... yes
checking for working aclocal... found
[ irrelevant text trimmed ]
creating Muttrc.head
creating doc/instdoc.sh
creating config.h
creating po/POTFILES
creating po/Makefile
    

This time ./configure completed successfully, and we can proceed to building Mutt.


% make
./gen_defs ./OPS ./OPS.PGP > keymap_defs.h
./patchlist.sh < ./PATCHES > patchlist.c
cd . \
  && CONFIG_FILES=Makefile CONFIG_HEADERS= /bin/sh ./config.status
creating Makefile
[ irrelevant text trimmed ]
lsbcc -Wall -pedantic -g -O2  -o mutt  patchlist.o addrbook.o
alias.o attach.o \
base64.o browser.o buffy.o color.o commands.o complete.o compose.o copy.o \
curs_lib.o curs_main.o date.o edit.o enter.o flags.o init.o filter.o from.o \
getdomain.o handler.o hash.o hdrline.o headers.o help.o hook.o keymap.o main.o \
mbox.o menu.o mh.o mx.o pager.o parse.o pattern.o postpone.o query.o \
recvattach.o recvcmd.o rfc822.o rfc1524.o rfc2047.o rfc2231.o score.o send.o \
sendlib.o signal.o sort.o status.o system.o thread.o charset.o history.o lib.o \
muttlib.o editmsg.o utf8.o mbyte.o wcwidth.o url.o ascii.o pgp.o pgpinvoke.o \
pgpkey.o pgplib.o gnupgparse.o pgpmicalg.o pgppacket.o resize.o dotlock.o \ 
-lncurses     
color.o: In function `mutt_alloc_color':
/var/tmp/mutt-1.3.27/color.c:215: undefined reference to `COLOR_PAIRS'
color.o: In function `parse_color_name':
/var/tmp/mutt-1.3.27/color.c:319: undefined reference to `COLORS'
color.o: In function `_mutt_parse_color':
/var/tmp/mutt-1.3.27/color.c:710: undefined reference to `use_default_colors'
menu.o: In function `print_enriched_string':
/var/tmp/mutt-1.3.27/menu.c:57: undefined reference to `acs_map'
/var/tmp/mutt-1.3.27/menu.c:65: undefined reference to `acs_map'
/var/tmp/mutt-1.3.27/menu.c:73: undefined reference to `acs_map'
/var/tmp/mutt-1.3.27/menu.c:81: undefined reference to `acs_map'
/var/tmp/mutt-1.3.27/menu.c:89: undefined reference to `acs_map'
menu.o:/var/tmp/mutt-1.3.27/menu.c:97: more undefined references to `acs_map' follow
signal.o: In function `exit_handler':
/var/tmp/mutt-1.3.27/signal.c:39: undefined reference to `sys_siglist'
resize.o: In function `mutt_resize_screen':
/var/tmp/mutt-1.3.27/resize.c:79: undefined reference to `resizeterm'
collect2: ld returned 1 exit status
make[2]: *** [mutt] Error 1
make[2]: Leaving directory `/var/tmp/mutt-1.3.27'
make[1]: *** [all-recursive] Error 1
make[1]: Leaving directory `/var/tmp/mutt-1.3.27'
make: *** [all-recursive-am] Error 2
    

The build has failed trying to to link to a library containing various functions. A little knowledge or a quick search on the Internet helps us to figure out these functions are part of ncurses. The ncurses library for terminal handling is defined as part of the LSB specification, but for some unknown reason they have only specified a portion of the interface and thus a number of symbols are missing from the stub libraries provided in the LSB development environment.

Until the situation with with the LSB's ncurses implementation is resolved we will have to work around it. There are two options available to us: build our own copy of ncurses or use another terminal handling library Mutt supports, named S-Lang. For this example we'll use S-Lang since it is a library outside of the LSB, and it is reportedly better at handling some bad termcap entries.

To use S-Lang we need to download the source and extract it just like we did with Mutt.


% cd /var/tmp
% ftp ftp://space.mit.edu/pub/davis/slang/v1.4/slang-1.4.5.tar.gz
Connected to SPACE.MIT.EDU.
220 space FTP server (SunOS 4.1) ready.
331 Guest login ok, send ident as password.
230 Guest login ok, access restrictions apply.
200 Type set to I.
250 CWD command successful.
250 CWD command successful.
250 CWD command successful.
250 CWD command successful.
local: slang-1.4.5.tar.gz remote: slang-1.4.5.tar.gz
500 'EPSV': command not understood.
227 Entering Passive Mode (18,75,0,10,7,253)
150 Binary data connection for slang-1.4.5.tar.gz (216.37.46.170,52199) (757822 bytes).
226 Binary Transfer complete.
757822 bytes received in 00:08 (88.28 KB/s)
221 Goodbye.
% tar xzf slang-1.4.5.tar.gz
% cd slang-1.4.5
    

To figure out how to build S-Lang we will look around in the source, and will quickly find INSTALL.unx. Reading that file will reveal that S-Lang builds in a manner very similar to the way Mutt does, except for the addition of an optional make runtests step.


% CC=lsbcc ./configure --prefix=`pwd`/install
creating cache ./config.cache
checking host system type... i686-pc-linux-gnu
checking for gcc... lsbcc
checking whether the C compiler (lsbcc  ) works... yes
checking whether the C compiler (lsbcc  ) is a cross-compiler... no
[ irrelevant text trimmed ]
checking for Terminfo... no
creating ./config.status
creating Makefile

Configuration complete.  You may need to edit src/Makefile.
You are compiling SLANG with the following compiler configuration:
       CC = lsbcc
   CFLAGS = -g -O2  -fno-strength-reduce
  LDFLAGS =  -Wl,-export-dynamic

   ELF_CC = gcc
 ELF_LINK = gcc -shared -Wl,-soname#
ELF_CFLAGS= -O2 -fno-strength-reduce -fPIC 

                  prefix: /var/tmp/slang-1.4.5/install
             exec_prefix: ${prefix}
    Installation Lib Dir: ${exec_prefix}/lib
Installation Include Dir: ${prefix}/include

See also src/sl-feat.h for various features.
Type 'make' to build normal library.
On ELF systems, type 'make elf' to create ELF shared library.
    

It seems to have configured fine, and so we are ready to build it. We will just run make without any arguments, because we want the static library, not the shared one produced by the elf target. If we were to link Mutt to a shared version of S-Lang we would need to include the shared library as part of the Mutt package or in a separate package that Mutt would depend on.


% make
cd src; make all
make[1]: Entering directory `/var/tmp/slang-1.4.5/src'
cd /var/tmp/slang-1.4.5/src/objs; lsbcc -c -g -O2  -fno-strength-reduce -Dunix \
-DSLANG -DMISC_TERMINFO_DIRS='""' /var/tmp/slang-1.4.5/src/sltermin.c
cd /var/tmp/slang-1.4.5/src/objs; lsbcc -c -g -O2  -fno-strength-reduce -Dunix \
-DSLANG  /var/tmp/slang-1.4.5/src/sldisply.c
cd /var/tmp/slang-1.4.5/src/objs; lsbcc -c -g -O2  -fno-strength-reduce -Dunix \
-DSLANG  /var/tmp/slang-1.4.5/src/slutty.c
[ irrelevant text trimmed ]
cd /var/tmp/slang-1.4.5/src/objs; ar cr libslang.a sltermin.o sldisply.o \
slutty.o slang.o slarray.o slclass.o slcmd.o slerr.o slgetkey.o slkeymap.o
\
slmalloc.o slmath.o slmemchr.o slmemcmp.o slmemcpy.o slmemset.o slmisc.o \
slparse.o slprepr.o slregexp.o slrline.o slsearch.o slsmg.o slstd.o sltoken.o \
sltypes.o slxstrng.o slcurses.o slscroll.o slsignal.o slkeypad.o slerrno.o \
slstring.o slstruct.o slcmplex.o slarrfun.o slimport.o slpath.o slarith.o \
slassoc.o slcompat.o slposdir.o slstdio.o slproc.o sltime.o slstrops.o \
slbstr.o slpack.o slintall.o slistruc.o slposio.o slnspace.o slarrmis.o \
slospath.o slscanf.o
ranlib /var/tmp/slang-1.4.5/src/objs/libslang.a

libslang.a created in /var/tmp/slang-1.4.5/src/objs
make[1]: Leaving directory `/var/tmp/slang-1.4.5/src'
    

Next we want to run make runtests to check to see if S-Lang built properly.


% make runtests
cd src; make runtests
make[1]: Entering directory `/var/tmp/slang-1.4.5/src'
cd test; make CC="lsbcc" CFLAGS="-g -O2  -fno-strength-reduce" \
TCAPLIB="-ltermcap"
make[2]: Entering directory `/var/tmp/slang-1.4.5/src/test'
lsbcc -g -O2  -fno-strength-reduce  sltest.c -o sltest -I.. -L../objs -lslang \
-ltermcap -lm
/usr/bin/ld: cannot find -ltermcap
collect2: ld returned 1 exit status
make[2]: *** [sltest] Error 1
make[2]: Leaving directory `/var/tmp/slang-1.4.5/src/test'
make[1]: *** [runtests] Error 2
make[1]: Leaving directory `/var/tmp/slang-1.4.5/src'
make: *** [runtests] Error 2
    

The test has failed miserably. When trying to compile the S-Lang test program it tried to link to the termcap library. The termcap library is not a part of LSB specifications and is not available in the LSB build environment. The newer alternative to termcap is terminfo, and this is what most vendors prefer. If you look back at the output from S-Lang's ./configure you will see that it tested for terminfo and could not find support.

Investigation will reveal that the test for using termcap versus terminfo is inadequate. To resolve this we will edit the autoconf/aclocal.m4 file. Good documentation on how to use and work with Autoconf can be found in the GNU Autoconf, Automake, and Libtool book. The changes illustrated below make sure termcap is actually usable, before falling back to it. This way S-Lang will not try to link to it when it doesn't exist.


diff -Naur slang-1.4.5.orig/autoconf/aclocal.m4 slang-1.4.5/autoconf/aclocal.m4
--- slang-1.4.5.orig/autoconf/aclocal.m4        Sun Feb 10 07:39:19 2002
+++ slang-1.4.5/autoconf/aclocal.m4     Fri Feb 15 17:46:27 2002
@@ -415,7 +415,13 @@
 done
 if test "$TERMCAP"; then
   AC_MSG_RESULT(no)
-  AC_DEFINE(USE_TERMCAP)
+
+  AC_CHECK_LIB(termcap, tgetent)
+  if test "$ac_cv_lib_termcap_tgetent" = yes; then
+    AC_DEFINE(USE_TERMCAP)
+  else
+    TERMCAP=""
+  fi
 fi
 AC_SUBST(TERMCAP)dnl
 AC_SUBST(MISC_TERMINFO_DIRS)dnl
    

After making these changes the configure scripts need to be regenerated. This is accomplished by running autoconf.


% cd autoconf && autoconf -o ../configure
% cd ../demo && autoconf -l ../autoconf
% cd ..
    

Now with newly generated configure scripts we should create a diff from the original source for our later use when building the RPM package.


% make distclean
/bin/rm -f *~ Makefile config.status config.log config.cache files.pck
cd src; make distclean
make[1]: Entering directory `/var/tmp/slang-1.4.5/src'
rm -f *~ "#"*
rm -f /var/tmp/slang-1.4.5/src/objs/*
rm -f /var/tmp/slang-1.4.5/src/elfobjs/*
rm -rf /var/tmp/slang-1.4.5/src/objs /var/tmp/slang-1.4.5/src/elfobjs Makefile \
sysconf.h config.h
make[1]: Leaving directory `/var/tmp/slang-1.4.5/src'
cd demo; make distclean
make[1]: Entering directory `/var/tmp/slang-1.4.5/demo'
/bin/rm -f /var/tmp/slang-1.4.5/demo/objs/* *~
/bin/rm -rf /var/tmp/slang-1.4.5/demo/objs Makefile
make[1]: Leaving directory `/var/tmp/slang-1.4.5/demo'
% cd .. && mkdir $$ && tar xzf \
slang-1.4.5.tar.gz -C $$ && mv $$/slang-1.4.5 slang-1.4.5.orig \
&& rm -r $$
% LC_ALL=C TZ=UTC0 diff -Naur slang-1.4.5.orig slang-1.4.5 > /var/tmp/slang-ac_terminfo.patch
    

With the patch saved, we can go back to the beginning and give it another shot.


% cd slang-1.4.5
% CC=lsbcc ./configure --prefix=`pwd`/install
[ irrelevant text trimmed ]
% make
[ irrelevant text trimmed ]
% make runtests
cd src; make runtests
make[1]: Entering directory `/var/tmp/slang-1.4.5/src'
cd test; make CC="lsbcc" CFLAGS="-g -O2  -fno-strength-reduce" TCAPLIB=""
make[2]: Entering directory `/var/tmp/slang-1.4.5/src/test'
lsbcc -g -O2  -fno-strength-reduce  sltest.c -o sltest -I.. -L../objs-lslang  \
-lm

Running tests:

Testing syntax ...Ok
Testing sscanf ...Ok
Testing looping constructs ...Ok
Testing Arithmetic ...Ok
Testing array functions ...Ok
Testing string functions...Ok
Testing Binary Strings...Ok
Testing pack and unpack functions...Ok
Testing stdio routines...Ok
Testing Associative Arrays ...Ok
Testing recursive function modifications ...Ok
Testing structures ...Ok
Testing NameSpace routines ...Ok
Testing ospath ...Ok
Testing #ifeval ...Ok
Testing Any_Type ...Ok
Testing Matrix Multiplications ...Ok
touch sltest.c
make[2]: Leaving directory `/var/tmp/slang-1.4.5/src/test'
make[1]: Leaving directory `/var/tmp/slang-1.4.5/src'
    

S-Lang has built properly, and we are now ready to install it. You may remember the --prefix=`pwd`/install we gave to ./configure earlier. This was done so that S-Lang would be installed in a temporary directory, specifically /var/tmp/slang-1.4.5/install, and not on the system its self.


% make install
[ irrelevant text trimmed ]
    

With S-Lang built and working we can go back to compiling Mutt. The steps will be very similar to the last time we tried.


% cd /var/tmp/mutt-1.3.27
% CC=lsbcc ./configure --with-mailpath=/var/mail --with-slang=/var/tmp/slang-1.4.5/install
[ irrelevant text trimmed ]
% make
./gen_defs ./OPS ./OPS.PGP > keymap_defs.h
./patchlist.sh < ./PATCHES > patchlist.c
cd . \
  && CONFIG_FILES=Makefile CONFIG_HEADERS= /bin/sh ./config.status
creating Makefile
[ irrelevant text trimmed ]
lsbcc  -Wall -pedantic -g -O2 -L/var/tmp/slang-1.4.5/install/lib -o mutt \
patchlist.o addrbook.o alias.o attach.o base64.o browser.o buffy.o color.o \
commands.o complete.o compose.o copy.o curs_lib.o curs_main.o date.o edit.o \
enter.o flags.o init.o filter.o from.o getdomain.o handler.o hash.o hdrline.o \
headers.o help.o hook.o keymap.o main.o mbox.o menu.o mh.o mx.o pager.o \
parse.o pattern.o postpone.o query.o recvattach.o recvcmd.o rfc822.o rfc1524.o \
rfc2047.o rfc2231.o score.o send.o sendlib.o signal.o sort.o status.o system.o \
thread.o charset.o history.o lib.o muttlib.o editmsg.o utf8.o mbyte.o \
wcwidth.o url.o ascii.o pgp.o pgpinvoke.o pgpkey.o pgplib.o gnupgparse.o \
pgpmicalg.o pgppacket.o resize.o dotlock.o   -lslang -lm      
signal.o: In function `exit_handler':
/var/tmp/mutt-1.3.27/signal.c:39: undefined reference to `sys_siglist'
collect2: ld returned 1 exit status
make[2]: *** [mutt] Error 1
make[2]: Leaving directory `/var/tmp/mutt-1.3.27'
make[1]: *** [all-recursive] Error 1
make[1]: Leaving directory `/var/tmp/mutt-1.3.27'
make: *** [all-recursive-am] Error 2
    

The build has failed trying to use the sys_siglist function which is not part of the LSB specification. The problem occurs due to the fact we are using our regular system headers in which sys_siglist is defined. If the LSB stub headers were functional they would solve the problem for us. To hack around this we can simply tell the build system to not to use sys_siglist and try building again.


% echo '#undef SYS_SIGLIST_DECLARED' >> config.h
% make clean
[ irrelevant text trimmed ]
% make
./gen_defs ./OPS ./OPS.PGP > keymap_defs.h
./patchlist.sh < ./PATCHES > patchlist.c
cd . \
  && CONFIG_FILES=Makefile CONFIG_HEADERS= /bin/sh ./config.status
creating Makefile
<lineannotation>[ irrelevant text trimmed ]</lineannotation>
lsbcc -DPKGDATADIR=\"/usr/local/share/mutt\" -DSYSCONFDIR=\"/usr/local/etc\" \
-DBINDIR=\"/usr/local/bin\" -DMUTTLOCALEDIR=\"/usr/local/share/locale\" \
-DHAVE_CONFIG_H=1 -I. -I.  -Iintl  -I/var/tmp/slang-1.4.5/install/include \
-I./intl -I/usr/local/include  -Wall -pedantic -g -O2 -c sha1.c
lsbcc  -Wall -pedantic -g -O2 -L/var/tmp/slang-1.4.5/install/lib -o pgpring \
pgppubring.o pgplib.o lib.o extlib.o sha1.o pgppacket.o ascii.o   
lsbcc -Wall -pedantic -g -O2 -I/var/tmp/slang-1.4.5/install/include -I./intl \
-I/usr/local/include -L/var/tmp/slang-1.4.5/install/lib  pgpewrap.c -o pgpewrap
make[2]: Leaving directory `/var/tmp/mutt-1.3.27'
make[1]: Leaving directory `/var/tmp/mutt-1.3.27'
    

We have finally successfully built Mutt. The last step before proceeding to package building will be to make sure we have indeed built an LSB compliant binary. We will do this using the lsbappchk utility that was previously described in this document.


% lsbappchk mutt
lsbappchk 1.1
    

The simple output means that we are compliant with version 1.1 of the LSB specification. If the binary had not been LSB-compliant lsbappchk would have listed all the violations. With the knowledge of how to build an LSB-compliant Mutt we are ready to begin the processes of packaging Mutt.

The rest of this example will document the process of creating an LSB RPM package for Mutt. A number of the details of creating and building RPM packages will be absent, and thus for further documentation the best resource is Maximum RPM.

At the core of RPM packages is the RPM spec file. The spec file contains information about the package and how to build it. An RPM spec file contains several different key sections:

  • The preamble contains various bits of information about the package. Each different piece of data is stored on each line, in the form `keyword: value'. Some examples of data that can be found in the preamble is a summary of what the package does, the name of the package, its copyright, who created the package, and so on. A special section of the preamble spans multiple lines and is indicated by the `%description' marker. As it suggests, that is where you can put an extended description of the software.

  • The %prep section of the spec file tells the computer how to prepare for building the package. Commands in the %prep section are run in a shell, so you can use all the standard shell syntax and commands.

  • The %build section is what actually compiles the software. This is where one runs ./configure, make, and friends.

  • The %install section of the RPM spec file installs the files built in the section section onto your system. Typically you will want to install into a DESTDIR so that you don't clutter your actual filesystem.

  • The %clean section is pretty self explanatory. It is where all files built during the run of the spec file should be cleaned up using shell syntax and commands.

  • The last key section of the spec file is the %files section. This is where all the files that will be installed by the package should be listed. Unfortunately, there are no standard methods to generate this automatically so it takes a little thought and grudge-work to get this list compiled.

An example spec file written for our purposes follows. Examine it closely to get a solid understanding of how it works. Any parts which you do not understand are probably explained in the Maximum RPM.


# RPM spec file for Mutt

Summary: A powerful text-based mail user agent
Name: mutt
Version: 1.3.27i
Release: 1
Copyright: GPL
Group: Application/Internet
Source: ftp://ftp.mutt.org/pub/mutt/mutt-1.3.27i.tar.gz
Source1: ftp://space.mit.edu/pub/davis/slang/v1.4/slang-1.4.5.tar.gz
Patch10: slang-ac_terminfo.patch
URL: http://www.mutt.org/
Vendor: Progeny Linux Systems, Inc.
Packager: Percival P. Progeny <percival@progeny.com>
BuildRoot: /var/tmp/mutt-root

%description
Mutt is a powerful text-based mail user agent supporting many features,
some of which are:
  - color support
  - message threading
  - MIME support (including RFC2047 support for encoded headers)
  - PGP/MIME (RFC2015)
  - various features to support mailing lists, including list-reply
  - active development community
  - POP3 support
  - IMAP support
  - full control of message headers when composing
  - support for multiple mailbox formats (mbox, MMDF, MH, Maildir)
  - highly customizable, including keybindings and macros
  - change configuration automatically based on recipients, current folder,
    etc.
  - searches using regular expressions, including an internal pattern
    matching language
  - Delivery Status Notification (DSN) support
  - postpone message composition indefinitely for later recall
  - easily include attachments when composing, even from the command line
  - ability to specify alternate addresses for recognition of mail forwarded
    from other accounts, with ability to set the From: headers on
    replies/etc. accordingly
  - multiple message tagging
  - reply to or forward multiple messages at once
  - .mailrc style configuration files
  - easy to install (uses GNU autoconf)
  - translation into at least 20 languages
  - small and efficient
  - It's free!  (no cost and GPL'ed)

%prep
rm -rf $RPM_BUILD_DIR/slang-1.4.5
rm -rf $RPM_BUILD_DIR/mutt-1.3.27
tar xzvf $RPM_SOURCE_DIR/slang-1.4.5.tar.gz
cd $RPM_BUILD_DIR/slang-1.4.5 && patch -p1 < \
$RPM_SOURCE_DIR/slang-ac_terminfo.patch && cd -
tar xzvf $RPM_SOURCE_DIR/mutt-1.3.27i.tar.gz

%build
cd $RPM_BUILD_DIR/slang-1.4.5
CC=lsbcc ./configure --prefix=`pwd`/install
make
make install

cd $RPM_BUILD_DIR/mutt-1.3.27
CC=lsbcc ./configure --with-mailpath=/var/mail \
--with-slang=$RPM_BUILD_DIR/slang-1.4.5/install --prefix=/opt/mutt-1.3.27 \
--with-docdir=/opt/mutt-1.3.27/doc
echo '#undef SYS_SIGLIST_DECLARED' >> config.h
make

%install
rm -rf $RPM_BUILD_ROOT
cd $RPM_BUILD_DIR/mutt-1.3.27
make install DESTDIR=$RPM_BUILD_ROOT

%clean
rm -rf $RPM_BUILD_ROOT

%files
/opt/mutt-1.3.27/bin/flea
/opt/mutt-1.3.27/bin/mutt
/opt/mutt-1.3.27/bin/muttbug
/opt/mutt-1.3.27/bin/pgpewrap
/opt/mutt-1.3.27/bin/pgpring
/opt/mutt-1.3.27/doc/COPYRIGHT
/opt/mutt-1.3.27/doc/ChangeLog
/opt/mutt-1.3.27/doc/GPL
/opt/mutt-1.3.27/doc/INSTALL
/opt/mutt-1.3.27/doc/NEWS
/opt/mutt-1.3.27/doc/PGP-Notes.txt
/opt/mutt-1.3.27/doc/README
/opt/mutt-1.3.27/doc/README.SECURITY
/opt/mutt-1.3.27/doc/README.SSL
/opt/mutt-1.3.27/doc/TODO
/opt/mutt-1.3.27/doc/applying-patches.txt
/opt/mutt-1.3.27/doc/devel-notes.txt
/opt/mutt-1.3.27/doc/html/manual-1.html
/opt/mutt-1.3.27/doc/html/manual-2.html
/opt/mutt-1.3.27/doc/html/manual-3.html
/opt/mutt-1.3.27/doc/html/manual-4.html
/opt/mutt-1.3.27/doc/html/manual-5.html
/opt/mutt-1.3.27/doc/html/manual-6.html
/opt/mutt-1.3.27/doc/html/manual-7.html
/opt/mutt-1.3.27/doc/html/manual.html
/opt/mutt-1.3.27/doc/manual.txt
/opt/mutt-1.3.27/doc/patch-notes.txt
/opt/mutt-1.3.27/doc/samples/Mush.rc
/opt/mutt-1.3.27/doc/samples/Pine.rc
/opt/mutt-1.3.27/doc/samples/Tin.rc
/opt/mutt-1.3.27/doc/samples/gpg.rc
/opt/mutt-1.3.27/doc/samples/iconv/iconv.aix-3.2.5.rc
/opt/mutt-1.3.27/doc/samples/iconv/iconv.aix-4.1.5.rc
/opt/mutt-1.3.27/doc/samples/iconv/iconv.aix-4.2.0.rc
/opt/mutt-1.3.27/doc/samples/iconv/iconv.aix-4.3.2.rc
/opt/mutt-1.3.27/doc/samples/iconv/iconv.freebsd-3.3.rc
/opt/mutt-1.3.27/doc/samples/iconv/iconv.glibc-2.1.3.rc
/opt/mutt-1.3.27/doc/samples/iconv/iconv.glibc-2.1.90.rc
/opt/mutt-1.3.27/doc/samples/iconv/iconv.hpux-10.01.rc
/opt/mutt-1.3.27/doc/samples/iconv/iconv.hpux-10.20.rc
/opt/mutt-1.3.27/doc/samples/iconv/iconv.hpux-11.00.rc
/opt/mutt-1.3.27/doc/samples/iconv/iconv.irix-6.5.rc
/opt/mutt-1.3.27/doc/samples/iconv/iconv.osf1-4.0a.rc
/opt/mutt-1.3.27/doc/samples/iconv/iconv.osf1-4.0d.rc
/opt/mutt-1.3.27/doc/samples/iconv/iconv.solaris-2.4.rc
/opt/mutt-1.3.27/doc/samples/iconv/iconv.solaris-2.5.1.rc
/opt/mutt-1.3.27/doc/samples/iconv/iconv.solaris-2.6-cjk.rc
/opt/mutt-1.3.27/doc/samples/iconv/iconv.solaris-2.6.rc
/opt/mutt-1.3.27/doc/samples/iconv/iconv.solaris-2.7.rc
/opt/mutt-1.3.27/doc/samples/pgp2.rc
/opt/mutt-1.3.27/doc/samples/pgp5.rc
/opt/mutt-1.3.27/doc/samples/pgp6.rc
/opt/mutt-1.3.27/doc/samples/sample.mailcap
/opt/mutt-1.3.27/doc/samples/sample.muttrc
/opt/mutt-1.3.27/doc/samples/sample.muttrc-tlr
/opt/mutt-1.3.27/etc/Muttrc
/opt/mutt-1.3.27/etc/mime.types
/opt/mutt-1.3.27/man/man1/flea.1
/opt/mutt-1.3.27/man/man1/mutt.1
/opt/mutt-1.3.27/man/man1/mutt_dotlock.1
/opt/mutt-1.3.27/man/man1/muttbug.1
/opt/mutt-1.3.27/man/man5/mbox.5
/opt/mutt-1.3.27/man/man5/muttrc.5
/opt/mutt-1.3.27/share/locale/ca/LC_MESSAGES/mutt.mo
/opt/mutt-1.3.27/share/locale/cs/LC_MESSAGES/mutt.mo
/opt/mutt-1.3.27/share/locale/da/LC_MESSAGES/mutt.mo
/opt/mutt-1.3.27/share/locale/de/LC_MESSAGES/mutt.mo
/opt/mutt-1.3.27/share/locale/el/LC_MESSAGES/mutt.mo
/opt/mutt-1.3.27/share/locale/eo/LC_MESSAGES/mutt.mo
/opt/mutt-1.3.27/share/locale/es/LC_MESSAGES/mutt.mo
/opt/mutt-1.3.27/share/locale/et/LC_MESSAGES/mutt.mo
/opt/mutt-1.3.27/share/locale/fr/LC_MESSAGES/mutt.mo
/opt/mutt-1.3.27/share/locale/gl/LC_MESSAGES/mutt.mo
/opt/mutt-1.3.27/share/locale/hu/LC_MESSAGES/mutt.mo
/opt/mutt-1.3.27/share/locale/id/LC_MESSAGES/mutt.mo
/opt/mutt-1.3.27/share/locale/it/LC_MESSAGES/mutt.mo
/opt/mutt-1.3.27/share/locale/ja/LC_MESSAGES/mutt.mo
/opt/mutt-1.3.27/share/locale/ko/LC_MESSAGES/mutt.mo
/opt/mutt-1.3.27/share/locale/lt/LC_MESSAGES/mutt.mo
/opt/mutt-1.3.27/share/locale/nl/LC_MESSAGES/mutt.mo
/opt/mutt-1.3.27/share/locale/pl/LC_MESSAGES/mutt.mo
/opt/mutt-1.3.27/share/locale/pt_BR/LC_MESSAGES/mutt.mo
/opt/mutt-1.3.27/share/locale/ru/LC_MESSAGES/mutt.mo
/opt/mutt-1.3.27/share/locale/sk/LC_MESSAGES/mutt.mo
/opt/mutt-1.3.27/share/locale/sv/LC_MESSAGES/mutt.mo
/opt/mutt-1.3.27/share/locale/tr/LC_MESSAGES/mutt.mo
/opt/mutt-1.3.27/share/locale/uk/LC_MESSAGES/mutt.mo
/opt/mutt-1.3.27/share/locale/zh_CN/LC_MESSAGES/mutt.mo
/opt/mutt-1.3.27/share/locale/zh_TW/LC_MESSAGES/mutt.mo
    

Building RPM packages requires root privileges, and thus it will be easiest if you su to root for the rest of the example.

Save the spec file as mutt.spec in /opt/lsb-rpm-4.0.3/src/lsb/SPECS. After that, copy your other source files to /opt/lsb-rpm-4.0.3/src/lsb/SOURCES.


# cd /opt/lsb-rpm-4.0.3/src/lsb/SOURCES
# cp /var/tmp/mutt-1.3.27i.tar.gz /var/tmp/slang-1.4.5.tar.gz \
/var/tmp/slang-ac_terminfo.patch .
    

With all the files in the appropriate places now we are ready to build the RPM.


# cd ../SPECS
# rpm -ba mutt.spec
Executing(%prep): /bin/sh -e
/opt/lsb-rpm-4.0.3/var/tmp/rpm-tmp.11297
+ umask 022
+ cd /opt/lsb-rpm-4.0.3/src/lsb/BUILD
+ rm -rf /opt/lsb-rpm-4.0.3/src/lsb/BUILD/slang-1.4.5
+ rm -rf /opt/lsb-rpm-4.0.3/src/lsb/BUILD/mutt-1.3.27
[ irrelevant text trimmed ]
Wrote: /opt/lsb-rpm-4.0.3/src/lsb/SRPMS/mutt-1.3.27i-1.src.rpm
Wrote:
/opt/lsb-rpm-4.0.3/src/lsb/RPMS/i386/mutt-1.3.27i-1.i386.rpm
Executing(%clean): /bin/sh -e
/opt/lsb-rpm-4.0.3/var/tmp/rpm-tmp.39642
+ umask 022
+ cd /opt/lsb-rpm-4.0.3/src/lsb/BUILD
+ rm -rf /var/tmp/mutt-root
+ exit 0
    

Congratulations! You have built binary and source RPM packages. Hopefully this example has been helpful in showing some of the various steps you might have to take as your prepare your own application for LSB-compliance. Good luck.


12. Credits

Portions of this document (Introduction, Definitions, Resources, and Examples) are condensed from versions 1.0.0 and 1.1.0 of the gLSB. Versions 1.0.0 and 1.1.0 of the gLSB are available at http://www.linuxbase.org/spec/refspecs/LSB_1.0.0/gLSB.html and http://www.linuxbase.org/spec/, respectively.

Notes

[1]

Note that a user who is running sudo or su to run an application or install a package may have his or her personal HOME instead of root's.

[2]

/etc/passwd and /etc/shadow are pulled into the chroot, so any users already defined there can log in with their existing passwords. The home directories to be imported are defined in lsbdev.conf.