= RPM How-To for packagers = [[PageOutline]] Basic informations for packagers: from writing a spec file, to testing a package, to releasing a package. == Pre Req == yum install rpm-build[[br]] yum install tar[[br]] in the below description the %HOME% is used for the top rpm directory. If you want to have your rpm topdirectory in another location you have to do the following:[[br]] * create a file called .rpmmacros in your %HOME% dir * add the following to the file "%_topdir x:/rpmbuild" (w/o the quotes) == Introduction == RPM uses a special file to compile source code, prepare installation and create .rpm files: it is a .spec file, which is just a bunch of shell commands to prepare, build, install, check and clean the setup. Instead of writing a .spec file from scratch, you can get an existing one: a good source for them is the [http://www.rpmfind.net RPM find service]. Enter the name of your package, and choose a distribution. Usually packages for Fedora or OpenSUSE 11.3 are good. Select your package from the left link, you will get a page with all details; one of them is the .src.rpm package, it contains the spec file, platform specific patches, package sources (in .tar.gz, .tar.bz2, .tar.xz format). Use unrpm.cmd (check bootstrap directory) to extract all files to a temporary location. RPM packages are created from .spec files using the ''rpmbuild'' command. The first time you try to build a package (see '''Building package''' below), rpmbuild will create a set of directories in your %HOME% directory that it uses for the package generation process: * %HOME%\rpmbuild\BUILD (temporary storage for compiled files) * %HOME%\rpmbuild\BUILDROOT (temporary storage for installed files) * %HOME%\rpmbuild\RPMS (destinations of built .rpm files) * %HOME%\rpmbuild\SOURCES (source files and patches) * %HOME%\rpmbuild\SPECS (spec files) * %HOME%\rpmbuild\SRPMS (destination of built .src.rpm files) Basic RPM tags: * ''name:'' * ''version:'' * ''license:'' * ''source:'' * ''source1:'' * ''patch0:'' * ''patch1:'' == Prepare source code == This is done in the ''%prep'' section. Here the ''%setup'' macro will expand your source package (the one in the ''Source:'' line) and write the files by default in the %HOME%\rpmbuild\BUILD\{name}-{version} directory. You can change this with ''-n'' parameter for %setup macro. If you need to extract more source files, use the ''-a'' parameter. To apply first patch add ''patch0 -p1 -b .my_suffix''; the second will use ''patch1...'' and so on. Example: {{{ %prep # -D Do not delete the directory before unpacking. # -T Disable the automatic unpacking of the archives. %setup -q -n %{name}-%{srcver} %{?with_int_bdb:-a 1} -a 2 %patch001 -p1 -b .base }}} Note that rpmbuild defaults expectes to find source tarball and patches in the SOURCES directory. == Build source code == Done in the %build section: common steps are execution of the configure script and use of gnu make to build code (this may be different for other programs). Example: {{{ %build CONFIG_SHELL="/bin/sh" ; export CONFIG_SHELL ; \ LDFLAGS="-Zbin-files -Zhigh-mem -Zomf -Zargs-wild -Zargs-resp" ; export LDFLAGS ; \ LIBS="-lurpo -lmmap -lpthread" ; export LIBS ; \ %configure \ --enable-shared --disable-static --without-lua \ %{!?with_int_bdb: --with-external-db} \ %{?with_sqlite: --enable-sqlite3} \ --enable-python \ "--cache-file=%{_topdir}/cache/%{name}.cache" make %{?_smp_mflags} }}} In this case, ''%configure'' is another macro, and it will be expanded to add proper paths for common variables, like prefix, exec_prefix and others. Keep in mind that rpmbuild will use /@unixroot/usr as prefix, so all built software will go to the same tree layout. Also programs will be able to be executed from other drives. Most of the times, the CONFIG_SHELL variable is required, otherwise bash shell will be selected if available: bash does not work very well, ash is more compatible. CFLAGS will be added by rpm. == Install binaries == Done in the %install section: most of the times, make install is the required step, {{{ %install rm -rf $RPM_BUILD_ROOT make DESTDIR="$RPM_BUILD_ROOT" install }}} DESTDIR is usually a macro supported in most recent build environments. == File packaging == Done in the %files section: here all required package files must be listed. While /* could be fine since it will include all files, it is better to have a detailed list, so it is easier to catch make install errors. {{{ %files %defattr(-,root,root,-) %{_bindir}/rpm.exe %{_mandir}/man8/rpm.8* %{_libdir}/rpm*.dll }}} == Building package == When the .spec file is in place, packaging of binary files and source code can be started with {{{ rpmbuild -ba myfile.spec }}} Special parameters can be used instead of -ba: * -bb build only binaries * -bs build only sources * -bc compile only code and stop. * -bi install only code and stop. * -bl check file list only and stop. Since -bc, -bi, -bl are performing also previous steps, you can add the special option ''--short-circuit'': this will skip all previous steps (rpmbuild will assume they are already ok), and do only the selected task. All output files will be written in the %HOME%\rpmbuild tree, regardless of current directory and drive. == OS/2 specific notes == While the syntax of .spec files is the same used under Unix, not everything is currently working in the OS/2 port. Also many packages are already built and manually installed: this means RPM is not aware of their presence. Many Unix .spec files have a (or multiple) ''BuildRequire:'' rules: if the package is not already built with RPM, the line should be commented until the required package will have a RPM install. The same applies to ''Requires:'' rules. Another missing feature is the automatic detection of required DLLs or packages: Unix rpm does this analyzing the ELF binaries and adding the required DLLs on the fly; the same is done for python or perl scripts, the required abi level is added by parsing scripts and querying python/perl modules.[[BR]] Under OS/2 these requirements must be manually added using a ''BuildRequires'' or ''Requires'' rule. Example: {{{ Requires: python Requires: python(abi) = 2.6 }}}