Building RPM packages for Linux distributions 2/4: Platform-independent package

Building RPM packages for Linux distributions 2/4: Platform-independent package

Packaging already built binaries or platform-independent software
(e.g. Java-based software)

A paradigm issue

RPM build is initially mainly oriented towards C/C++ toolkit. Therefore the structure of a SPEC file is oriented around the following concepts:

  1. %prep macro: prepare the RPM_BUILD_DIR folder by extracting the sources archive(s) and adapting the filesystem layout.
  2. %build usually configuring the build (using configure or automake for example) and making the build (using make with various options) in RPM_BUILD_DIR
  3. %install installing the product (using make install) in the RPM_BUILD_ROOT

SPEC files already provide handy macros in order to make this kind of build very simple.

If you are building a package from something which was already built elsewhere (e.g. a java web application, Tomcat web server), you are therefore going a bit around the usual flow of the tool.

You can already feel that the %build section is not going to be very useful.

Specific configuration gotchas for Java-based software

In recent versions of rpmbuild, 2 steps are automatically added by rpm builds when a package contains Java code or bytecode: jars repack, and automatic creation of Require and Provides attributes for OSGi-based jars.
Jars repack is a very long process for very little gain. It is initially meant to eliminate multilib conflicts, so should be avoided in most cases, and used if your jars provides arch-dependent libs (which could cause conflicts), which is quite rare.
It is avoided by adding the following definition in your spec file:

As for Automatic osgi Requires and Provides, it is altogether tedious, long, and just wrong in 99% of cases.
For example Tomcat ends up “providing” (as an RPM package) log4j in a given version, and requiring some other OSGi bundle libraries (as of some OSGi manifests found in the jars).
This will likely prevent installation or create unforeseen conflicts, in a weird context, because a JVM sets its classpath when it is started, not at installation time…
Moreover OSGi are not static or dynamic bindings such as the ones of C/C++ libraries, and their loading is even more dynamic than the loading of regular java files.
It may make some sense for some GCJ packaging corner-cases, but won’t for most java-based software out there.
In order to deactivate it, one must turn off automatic Require and Provides discovery:

%prep section

In this section, one should just prepare for the %build and %install sections.
This usually is just about creating folder structure in the RPM_BUILD_DIR folder, and extracting the archives and putting files in the right place.

Work in this section must be done in the $RPM_BUILD_DIR folder.

For example:

%build section

In this case, the %build section is not necessary , as usually applications are already built through another platform-independant process.
If required, this section could run any kind of available build tool, but this would have no added value, as we are in a scenario where code is platform-independent.

Work in this section must also be done in the $RPM_BUILD_DIR folder.

For example:

%install section

In this section files from the %prepare and %build sections are going to be copied/moved in the RPM_BUILD_ROOT.
The build root ($RPM_BUILD_ROOT or %{buildroot}) mimics the target file system structure from its root level.
If a file is copied in $RPM_BUILD_ROOT/opt/agilepartner/ it is therefore meant to be installed in /opt/agilepartner/ in the target system.

Work in this section must also be done in the $RPM_BUILD_ROOT folder.

For example:


If your software is both platform and architecture independent, you can also specify the BuildArch tag and set it to noarch (instead of e.g. x86_64 or arm):

Wrapping up:

As you can see, it is quite easy to package Java-based platform-independent software (once you know about the gotchas), even easier because (it’s usually the case) it’s already been built elsewhere.

In the previous blog entry, we saw:

  1. An introduction to RPM packaging.

In the next blog entries, we’ll see:

  1. how to package a platform-dependent software, built from source (if starting from binary, the platform-independent scenario should be relevant)
  2. how to create a SPEC file which produces multiple different packages (and why it is useful)
Pierre-Antoine Grégoire
No Comments

Post a Comment