Home Wiki > openSUSE:Build Service cross distribution howto
Sign up | Login

openSUSE:Build Service cross distribution howto

tagline: From openSUSE

Overview

This howto lists special hints to work with one spec file for different distributions. It is not a beginners guide for packagers, please visit the Build Service Tutorial for this instead. Also, this document does not cover distributions that use Debian packages.

The Build Service can reliably package rpms for not only openSUSE, but also recent SLES, CentOS, Fedora, Red Hat Enterprise Linux, Ubuntu, Debian and Mandriva distributions.

What are the limitations ? The only practical limit is not having certain dependencies satisfied for Fedora or Mandriva, where they can be easily satisfied for SUSE distributions by linking or aggregating to another Build Service project. An example: It is easy to build packages for SUSE which require the latest versions of Qt4 or GTK2, as these dependencies can be satisfied by other repos on the Build Service which provide backports of newer Qt4 packages for older SUSE versions, as well as SLES. This can only be overcome by also packaging the needed dependencies within your own project. Even then, this is only an issue if you wish to support as many distributions as possible.

Some 'gotcha' differences between distributions which you need to pay attention to:

  • Installing desktop files. Each of the five distros use somewhat different mechanisms for installing desktop files and then creating the menu entries. Mandriva even has a special rpm macro  %update_menus to accomplish this, which uses a Debian-like setup, different from SUSE or Fedora. Example:
%post
%update_menus

%postun
%clean_menus
  • Package naming for dependencies. See below for more specific hints and tricks to make this work in your spec file.
  • Subtle differences in rpm macros. Link with a table showing the variations below.

Can you point me to good example of a cross-platform package ?

Amilcar's KDevelop Package

Detect a distribution flavor for special code

You can add

%if %{defined suse_version}
%if %{undefined suse_version}

or more portable:

%if 0%{?suse_version}
  <suse stuff here>
%else
  <other distros>
%endif

to check if the current build is for a SUSE distribution or not. Note that there is no '%elseif' to chain multiple tests at the same level. Note that Fedora uses "%{fedora}" without "_version". You can also check for which SUSE distribution by using

%if 0%{?suse_version} > 1130

for instance to execute something for everything after SUSE Linux 11.3. Similar checks for other distributions exist as well.

%if %{defined fedora}
%if %{defined mdkversion}
%if 0%{?fedora} < 5
%if 0%{?mdkversion} > 2006

Note that rpm prefers:

>= 

vs.

=>

You can also exclude one particular version:

%if 0%{?rhel_version} != 406

You can combine multiple distributions in a single if block like this:

%if 0%{?fedora} || 0%{?rhel_version} || 0%{?centos_version}
 <yourstuff>
%endif

To group conditionals, split the conditional to several lines, like this:

# mono:  only on suse, sle only from sle10
%if 0%{?suse_version}
%if 0%{?suse_version} >= 1010
BuildRequires:  mono-core
%endif
%endif

Grouping with parentheses will fail on fedora/rhel/centos:

# mono:  only on suse, sle only from sle10
# FAIL on fedora RHEL centos:
%if 0%{?suse_version} && ( 0%{?suse_version} == 0 || 0%{?suse_version} >= 1010 )
BuildRequires:  mono-core
%endif

You can also select a special architecture using e.g.:

%if 0%{?suse_version} == 1310
%ifarch x86_64
 <yourstuff>
%endif
%endif

Warning: The following version can change ! to check for the latest version go to the project page, and check the configuration file. For example with RedHat 5 go to: https://build.opensuse.org/project/prjconf?project=RedHat%3ARHEL-5 and look for the content "%rhel_version 505" to get the latest version. Please update this page if versions doesn't match.

Note: sles_version is no longer set in SLES 11. Use %if 0%{?suse_version} == 1110 instead. It's OK to use since openSUSE 11.1 is long EOL.

The following overview helps to choose correct settings:

Distribution Variable Comment
openSUSE Factory  %if 0%{?suse_version} > 1310 current upcoming release (changing)
openSUSE 13.1  %if 0%{?suse_version} == 1310
openSUSE 12.3  %if 0%{?suse_version} == 1230
openSUSE 12.2  %if 0%{?suse_version} == 1220
openSUSE 12.1  %if 0%{?suse_version} == 1210
openSUSE 11.4  %if 0%{?suse_version} == 1140
openSUSE 11.3  %if 0%{?suse_version} == 1130
openSUSE 11.2  %if 0%{?suse_version} == 1120
openSUSE 11.1  %if 0%{?suse_version} == 1110 could also be SLE11
openSUSE 11.0  %if 0%{?suse_version} == 1100
openSUSE 10.3  %if 0%{?suse_version} == 1030
openSUSE 10.2  %if 0%{?suse_version} == 1020
SUSE Linux 10.1  %if 0%{?suse_version} == 1010 could also be SLE10
SUSE Linux 10.0  %if 0%{?suse_version} == 1000
SUSE Linux 9.3  %if 0%{?suse_version} == 930
SLES 9  %if 0%{?suse_version} == 910
SLE 10  %if 0%{?suse_version} == 1010
SLE 11  %if 0%{?suse_version} == 1110
SLE 12  %if 0%{?suse_version} == 1315
CentOS 5  %if 0%{?centos_version} == 505
CentOS 6  %if 0%{?centos_version} == 600
RHEL 4  %if 0%{?rhel_version} == 406
RHEL 5  %if 0%{?rhel_version} == 505
RHEL 6  %if 0%{?rhel_version} == 600
Fedora 6 with Extras  %if 0%{?fedora_version} == 6
Fedora 7 with Extras  %if 0%{?fedora_version} == 7
Fedora 8 with Extras  %if 0%{?fedora_version} == 8
Fedora 9 with Extras  %if 0%{?fedora_version} == 9
Fedora 10 with Extras  %if 0%{?fedora_version} == 10
Fedora 11 with Extras  %if 0%{?fedora_version} == 11
Fedora 15  %if 0%{?fedora_version} == 15
Fedora 16  %if 0%{?fedora_version} == 16
Fedora 17  %if 0%{?fedora_version} == 17
Mandriva 2006  %if 0%{?mdkversion} == 2006
Mandriva 2007  %if 0%{?mdkversion} == 2007
Mandriva 2008  %if 0%{?mdkversion} == 2008
Mandriva 2009.0  %if 0%{?mdkversion} == 2009
Mandriva 2009.1  %if 0%{?mdkversion} == 200910
Mandriva 2010.0  %if 0%{?mdkversion} == 201000


ServicePacks cannot be distinguished. SLES11 SP1 sets exactly the same variables as SLES11.

Install info files

Info files should get installed by using the %info_add and %info_del macros. For example

%post
%info_add %{name}.info
%preun
%info_del %{name}.info

Please note that the info files get compressed on some distros as .gz and as .bz2 or even .lzma (recent Mandriva) on some others. You can use %ext_info for the file suffix in the file list.

Handling dependencies

Different distributions often use different names for packages, so the Requires: and BuildRequires: tags may need to vary from repository to repository. It is possible to specify package name substitutions in the configuration of a project e.g.

%if 0%{?fedora_version}
  Substitute: libnetcdf-devel netcdf
%endif

In order to change your project configuration, use osc meta prjconf <project-name> -e, which starts $EDITOR. In the web client this is hidden in the Advanced section of the central project menu.

In case you are doing this on build.opensuse.org and you think your substitution is of interest to others as well (and might be added to the central configuration) drop a message on opensuse-buildservice@opensuse.org.

If you want to have a look which Substitutes for a special distro already exist, have a look at the project configuration of that distro, e.g. https://build.opensuse.org/project/prjconf?project=CentOS%3ACentOS-6

Suggests: is only on SUSE and only from 10.0

# 'Suggests:' is a SUSE feature.  Don't make it "Requires:", though,
# the package does not need vi or graphviz to run.
%if 0%{?suse_version} > 1000
# possibly 920 or 930 is ok to.  sle9 910 sure is not.
Suggests:       vim graphviz
%endif

Finding Qt 3.x on Fedora/RHEL

Redhat/Fedora uses a different naming scheme and build setup to use Qt to build other apps. Here is an example from a spec file to build Qt based apps on both SUSE and Fedora in one spec file:

BuildRequires:  cups cups-devel python-devel shared-mime-info libart_lgpl-devel libtiff-devel libxml2-devel
BuildRequires:  fontconfig-devel openssl-devel pkgconfig desktop-file-utils qt-devel

%if 0%{?fedora} >= 5
BuildRequires:  libstdc++-devel gcc-c++ lcms-devel >= 1.12 qt
%endif

%if 0%{?suse_version} > 910
BuildRequires:  update-desktop-files 
%endif

Then:

%if 0%{?fedora} >= 5
source "%{_sysconfdir}/profile.d/qt.sh"
%endif
%configure \
%if 0%{?fedora} >= 5
--with-xinerama \
--with-extra-libs=%{_libdir} \
%endif
%if 0%{?suse_version} > 910
--with-qt-libraries=/usr/%_lib/qt3/%_lib \
--with-docdir=%{prefix}/share/doc/packages/scribus \
%ifarch x86_64 ppc64 s390x
 --enable-libsuffix=64 \ 
%endif
%endif
<programoptions>

Finding Qt4 on Mandriva

By default, Qt3 will be found before Qt4, so simply add this to the %build section of your spec file:

%build  
 
%if 0%{?mandriva_version} > 2006  
export PATH=/usr/lib/qt4/bin:$PATH  
export QTDIR=%{_prefix}/lib/qt4/  
%endif  
  • This may have changed on Mdv 2008

Handling Mandriva Provides/Obsoletes

Special care is needed when handling Mandriva, as unlike CentOS, RHEL, Fedora or SUSE, they often create separate library rpms for many apps which use these libraries privately. Application foo may also have a dependency on libfoo or libfoo-0. Thus, you need to check Mandriva original spec files if they have explicit Provides and Obsoletes to prevent conflicts on install. Even though RPM handles dependencies automatically, you may still need to explicitly added these like below:

%if 0%{?mandriva_version}
Provides: foo libfoo-0
Obsoletes: foo libfoo-0
%endif

Building on Older Distros

While sources in a package can build on older distros, the way packages are built sometimes evolve in an incompatible way.

For example, when calling autoreconf -fi (as is commonly done in spec files), it happens (due to the -i for install) that the tarball's versions of config.sub, config.guess and ltmain.sh are replaced with the versions from the autoconf package of the target build platform. This can mean that files from the year 2007 are replaced with the 2005 versions when building for SLE10, for instance, which may not work properly. This can have negative effects, and even lead to a miscompile, for example when building libapr1 on SLE10.

Thus, it might be better, or even required, that you call autoheader, autoconf or whatever is needed by hand instead of autoreconf on targets older than Factory. An example would be:

%if 0%{?suse_version} > 1010
  autoreconf -fi
%else
  autoheader
  autoconf
%endif

Debian and xUbuntu packages

For these kind of packages, please read the debian builds page.

Distro RPM Macros and Documentation

openSUSE Packaging Conventions

Fedora Packager's Guide

Mandriva Packaging

Comparison of RHEL,Mandriva,SUSE RPM Macros