Development/Howto/LSB Package
From Mandriva Community Wiki
This document will attempt to walk through building a package as an LSB package, which should be able to be installed and run on any LSB compliant distribution. It is not the intent of this guide to replace the LSB specification, nor the book Writing LSB Applications, published by IBM press, but simply to pull together a bit of the available information in a short guide. Much more detail on the specification requirements as well as portability issues are covered by these documents.
LSB compliant applications may be packaged as rpm v3 packages or another package format. Since Mandriva Linux is an RPM based distribution, we'll focus on rpm packaging.
[edit] File Locations
LSB applications should, for the most part, place files under the /opt directory. Configuration files should go under /etc/opt. Namespace should follow LANANA namings for package and provider. Init scripts can be placed in /etc/init.d and can be initialized for the desired bootlevels using the LSB defined install_initd and remove_initd which should be located in /usr/lib/lsb in an LSB compliant distribution.
Examples:
Company Foobar with application wizbang (both names registered with LANANA):
- Binarys, libs, shared files: /opt/foobar/wizbang/{bin,lib,var,share} or /opt/wizbang/{bin,lib,var,share}
- Configuration files: /etc/opt/foobar/wizbang or /etc/opt/wizbang
Symbolic links can be used to simplify paths, but must not be created outside the assigned namespace. The system administrator is responsible for creating any PATH modifications to make the application readily available for users. This should not be done in any %post scripts in the packaging.
ISVs as well as open source projects should register their desired namespace with LANANA, to avoid conflicts.
[edit] Restrictions to LSB compliance
The application must only use those libraries defined by LSB. Any additional requirements must be provided by the package as private shared libraries or statically compiled.
The application should not make any assumptions about the system init style of the system, beyond what is defined by the specification.
[edit] Tools
Mandriva Linux provides a toolchain for building LSB compliant applications, with the lsb-build packages. The packages include:
- lsb-build-base-devel
- lsb-build-cc
- lsb-build-c++-devel
These packages provide a wrapper environment around the system gcc to insure LSB compliance in the compilation and linking of an application.
[edit] Testing for compliance
The LSB group provides several test packages to test your application for compliance:
- lsb-appchk - check a binary application for compliance
- lsb-archk - check a static archive for compliance
- lsb-dynchk - check application interfaces to LSB ABI while the application is running
- lsb-pkgchk - check a packaged LSB application
[edit] Very simple compilation example using hello.c
#include <stdio.h> int main() { printf("Hello, World.\n"); }
GCC compilation: gcc -o hello hello.c
[stew@presario30 c-code]$ ldd hello linux-gate.so.1 => (0xffffe000) libc.so.6 => /lib/tls/libc.so.6 (0xb7eb1000) /lib/ld-linux.so.2 (0xb7fec000) [stew@presario30 c-code]$ /opt/lsb/bin/lsbappchk hello /opt/lsb/bin/lsbappchk for LSB Specification 3.0.0 Checking binary hello Incorrect program interpreter: /lib/ld-linux.so.2 Header[ 1] PT_INTERP Failed Found wrong intepreter in .interp section: /lib/ld-linux.so.2 instead of: /lib/l d-lsb.so.3 Section .got.plt: Not recognized by name. Checking as type SHT_PROGBITS
Lsbcc compilation: lsbcc -o hello hello.c
[stew@presario30 c-code]$ ldd hello linux-gate.so.1 => (0xffffe000) libm.so.6 => /lib/tls/libm.so.6 (0xb7fb8000) libc.so.6 => /lib/tls/libc.so.6 (0xb7e8d000) /lib/ld-lsb.so.3 (0xb7fec000) [stew@presario30 c-code]$ /opt/lsb/bin/lsbappchk hello /opt/lsb/bin/lsbappchk for LSB Specification 3.0.0 Checking binary hello Section .got.plt: Not recognized by name. Checking as type SHT_PROGBITS
This is built with LSB3.0 versions of the toolset, on a system preparing for LSB 3.0. An LSB2.0 system would show ld-lsb.so.2 in the ldd output.
[edit] Choosing an LSB version
LSB is a maturing spec. It attempts to document existing practice and as such will change as Linux changes. It is possible to be compliant with multiple versions of LSB, provided the distribution or runtime environment provides compliance for the target versions. At the of this writing LSB2.0 is the released specification, with LSB3.0 scheduled to be released very soon.
[edit] Packaging the gnu xpaint application in an LSB compliant manner
We're going to repackage xpaint as an LSB applicaton, calling it xpaint-lsb. The complete source rpm is available on my web space.
As we discuss the various changes we'll need to make to the spec file, we show snippets of the diff between the orginal spec file and the new one. The first change will be the name, as well as defining %{tdir} as a macro to aid in setting up/installing the application. We also need to override the automatic requires, as an LSB package should only require lsb-core and possibly lsb-graphics.
--- xpaint.spec.org 2005-06-13 19:27:49.000000000 -0400 +++ xpaint-lsb.spec 2005-06-13 19:20:32.000000000 -0400 @@ -1,16 +1,23 @@ +%define rname xpaint +%define tdir /opt/%{rname} +%define <i>requires</i>exceptions \\(lib\\(ICE\\|SM\\|X11\\|Xext\\|Xt\\|c\\|dl\\|m\\|z\\)\\)\\.so* + Summary: An X Window System image editing or paint program -Name: xpaint +Name: %{rname}-lsb
If we look the the xpaint package included with Mandriva Linux, we'll find the binary is linked with several libraries not defined in the LSB.
linux-gate.so.1 => (0xffffe000) libXpm.so.4 => /usr/X11R6/lib/libXpm.so.4 (0x55581000) libtiff.so.3 => /usr/lib/libtiff.so.3 (0x55591000) libjpeg.so.62 => /usr/lib/libjpeg.so.62 (0x555df000) libpng.so.3 => /usr/lib/libpng.so.3 (0x555fd000) libz.so.1 => /lib/libz.so.1 (0x55624000) libdl.so.2 => /lib/libdl.so.2 (0x55635000) libXaw.so.8 => /usr/X11R6/lib/libXaw.so.8 (0x55639000) libXmu.so.6 => /usr/X11R6/lib/libXmu.so.6 (0x55695000) libXt.so.6 => /usr/X11R6/lib/libXt.so.6 (0x556aa000) libSM.so.6 => /usr/X11R6/lib/libSM.so.6 (0x556fc000) libICE.so.6 => /usr/X11R6/lib/libICE.so.6 (0x55706000) libXp.so.6 => /usr/X11R6/lib/libXp.so.6 (0x5571e000) libXext.so.6 => /usr/X11R6/lib/libXext.so.6 (0x55726000) libX11.so.6 => /usr/X11R6/lib/libX11.so.6 (0x55734000) libm.so.6 => /lib/libm.so.6 (0x55801000) libc.so.6 => /lib/libc.so.6 (0x55825000) /lib/ld-linux.so.2 (0x55555000)
Specifically, libtiff, libjpeg, libpng, libXaw, libXmu and libXp are not part of LSB at this time.
This means we'll need to either provide these libs in our package or compile them in statically. For the example, we'll choose static compilation, which means the BuildRequirements of the package will change:
Version: 2.7.7 Release: 1mdk License: MIT Group: Graphics -BuildRequires: XFree86-devel xpm-devel jpeg-devel png-devel -BuildRequires: tiff-devel zlib-devel bison flex +BuildRequires: XFree86-static-devel xpm-devel jpeg-static-devel png-sta tic-devel +BuildRequires: tiff-static-devel zlib-devel bison flex lsbcc
Also, since LSB does not yet define how menus are setup for a GUI, we'll drop the icons and menu setupparts of the spec:
Source0: http://prdownloads.sourceforge.net/sf-xpaint/xpaint-%{version}.tar.bz2 -Source1: icons-%{name}.tar.bz2 URL: https://sourceforge.net/projects/sf-xpaint BuildRoot: %{_tmppath}/xpaint-root -mkdir -p $RPM_BUILD_ROOT%{_menudir} -#mdk menu entry -cat << EOF > $RPM_BUILD_ROOT%{_menudir}/%{name} -?package(xpaint):needs="X11" \ -section="Multimedia/Graphics" \ -title="Xpaint" \ -longtitle="Paint program" \ -command="/usr/X11R6/bin/xpaint" \ -icon="xpaint.png" -EOF - -#mdk icon -install -d $RPM_BUILD_ROOT%{_iconsdir} -tar jxf %{SOURCE1} -C $RPM_BUILD_ROOT%{_iconsdir} -%{_menudir}/%{name} -%{_iconsdir}/*.png -%{_iconsdir}/'''/'''.png -%post -%update_menus -%postun -%clean_menus
Rpm normally finds application requirements and includes them in the packaged application. For LSB, we need to specify these manually as rpm does not do it for us. We'll specifically require LSB3.0, although it's possible to allow lesser or multiple versions.
+# (sb) automatic requires doesn't pick the ld-lsb dynamic loader requirement +%ifarch %ix86 +Requires: lsb-core-ia32 = 3.0 lsb-graphics-ia32 = 3.0 +%endif +
This change in the %setup section is just because we've renamed the package to xpaint-lsb:
-%setup -q +%setup -q -n %rname-%version
To build the application, we need to make a change in Local.config so the /opt/xpaint directory is used asthe target directory. We also want to use lsbcc instead of gcc.
%build +sed -i "s|SHAREDIR = /usr/share/xpaint|SHAREDIR = %{tdir}/share|" Local.config -make CDEBUGFLAGS="$RPM_OPT_FLAGS" xaw +make CC=lsbcc CDEBUGFLAGS="$RPM_OPT_FLAGS" xaw
For the %install stanza we again use lsbcc and modify the destination paths to /opt/xpaint.
%install -make \ +make CC=lsbcc \ DESTDIR=$RPM_BUILD_ROOT \ - BINDIR=%{_prefix}/X11R6/bin \ - MANDIR=%{_prefix}/X11R6/man/man1 install install.man + BINDIR=%{tdir}/bin \ + LIBDIR=%{tdir}/lib \ + SHAREDIR=%{tdir}/share \ + MANDIR=%{tdir}/man/man1 \ + CONFDIR=%{_sysconfdir}%{tdir}/X11 \ + install install.man
Normally we use the %doc macro to install documents, this doesn't seem to work for an LSB application, so we manually install the docs in %install:
+# (sb) can't use %doc macro in an LSB package +install -d $RPM_BUILD_ROOT%{tdir}%{_datadir}/doc/%{rname}-%{version} +install [[ChangeLog]] README README.PNG TODO Doc/* $RPM_BUILD_ROOT%{tdir}%{_datadir }/doc/%{rname}-%{version}
Finally the %files section reflects the changes in locations we've made, basically moving everything from /usr to /opt/xpaint:
%files %defattr(-,root,root) -%doc [[ChangeLog]] README README.PNG TODO Doc -%{_prefix}/X11R6/bin/xpaint -%{_prefix}/X11R6/man/man1/xpaint.1x* -%dir %{_datadir}/xpaint -%{_datadir}/xpaint/*.xpm -%dir %{<i>datadir}/xpaint/c</i>scripts -%dir %{<i>datadir}/xpaint/c</i>scripts/3d_curves -%dir %{<i>datadir}/xpaint/c</i>scripts/3d_surfaces -%dir %{<i>datadir}/xpaint/c</i>scripts/filters -%dir %{<i>datadir}/xpaint/c</i>scripts/images -%dir %{<i>datadir}/xpaint/c</i>scripts/layers -%dir %{<i>datadir}/xpaint/c</i>scripts/procedures -%{<i>datadir}/xpaint/c</i>scripts/3d_curves/* -%{<i>datadir}/xpaint/c</i>scripts/3d_surfaces/* -%{<i>datadir}/xpaint/c</i>scripts/filters/* -%{<i>datadir}/xpaint/c</i>scripts/images/* -%{<i>datadir}/xpaint/c</i>scripts/layers/* -%{<i>datadir}/xpaint/c</i>scripts/procedures/* -%dir %{_datadir}/xpaint/help -%{_datadir}/xpaint/help/* -%dir %{_datadir}/xpaint/messages -%{_datadir}/xpaint/messages/* -%dir %{_datadir}/xpaint/include -%{_datadir}/xpaint/include/* -%config(noreplace) %{_sysconfdir}/X11/app-defaults/XPaint* -%{_prefix}/X11R6/lib/X11/doc/html/* +%{tdir}/bin/xpaint +%{tdir}/man/man1/xpaint.1x* +%dir %{tdir}/share +%{tdir}/share/*.xpm +%dir %{tdir}/share/c_scripts +%dir %{tdir}/share/c_scripts/3d_curves +%dir %{tdir}/share/c_scripts/3d_surfaces +%dir %{tdir}/share/c_scripts/filters +%dir %{tdir}/share/c_scripts/images +%dir %{tdir}/share/c_scripts/layers +%dir %{tdir}/share/c_scripts/procedures +%{tdir}/share/c_scripts/3d_curves/* +%{tdir}/share/c_scripts/3d_surfaces/* +%{tdir}/share/c_scripts/filters/* +%{tdir}/share/c_scripts/images/* +%{tdir}/share/c_scripts/layers/* +%{tdir}/share/c_scripts/procedures/* +%dir %{tdir}/share/help +%{tdir}/share/help/* +%dir %{tdir}/share/messages +%{tdir}/share/messages/* +%dir %{tdir}/share/include +%{tdir}/share/include/* +%dir %{_sysconfdir}%{tdir} +%config(noreplace) %{_sysconfdir}%{tdir}/X11/app-defaults/XPaint* +%{tdir}/lib/doc/html/* +%{tdir}%{_docdir}/%{rname}-%{version}/*
[edit] Building our application
The specification for ia32 requires that the package must specify an architecture of i486. Normally on Mandriva Linux our packages are .i586.rpm. We can specify the architecture when we build:
[stew@presario30 SPECS]$ rpm -bb --target i486-linux xpaint-lsb.spec
[edit] Checking our application
We can check our xpaint binary using the lsbappchk program. Since xpaint is a graphical based application, we'll need to tell lsbappchk to consider the LSB_Graphics module or it will complain about requirements outside of LSB_Core.
[root@presaro30 /]# /opt/lsb/bin/lsbappchk -M LSB_Graphics /opt/xpaint/bin/xpaint also checking symbols in module LSB_Graphics /opt/lsb/bin/lsbappchk for LSB Specification 3.0.0 Checking binary /opt/xpaint/bin/xpaint Section .data.rel.ro: Not recognized by name. Checking as type SHT_PROGBITS Section .got.plt: Not recognized by name. Checking as type SHT_PROGBITS
Tjreport is used to summarize the output from the LSB testing tools. A copy is provided in the "lsb" package:
[root@presario30 ~]# tjreport journal.appchk.xpaint Test was run: 20050622 10:01:24 Total Tests Passed: 2068 Total Tests Failed (including waived): 0 Total Tests Failed (excluding waived): 0
[edit] Checking our package
We can test our package with lsbpkgchk. We use the "-L xpaint" to simulate that we're using a registered LANANA name. Otherwise pkgchk will complain about usage of /opt/xpaint and /etc/opt/expaint as not conforming to FHS.
[stew@presario30 i486]$ /opt/lsb/bin/lsbpkgchk -L xpaint xpaint-lsb-2.7.7-1mdk.i486.rpm
At the time of this writing, lsbpkgchk sends a lot of error output to stdout. For now we'll ignore this and just look at the journal:
[stew@presario30 i486]$ tjreport journal.pkgchk.xpaint-lsb-2.7.7-1mdk.i486.rpm Test was run: 20050622 18:09:15 Total Tests Passed: 88 Total Tests Failed (including waived): 0 Total Tests Failed (excluding waived): 0
[edit] Summary
That's about it. We could have chosen to bundle the libraries that LSB doesn't define in our application and place them under /opt/xpaint/lib. A larger application might be a bit more complicated getting it configured to compile and run correctly out of /opt. As LSB grows, more interfaces will be defined and included.