openSUSE:Build Service で複数のディストリビューションのパッケージを扱うための手順

移動先: 案内, 検索

概要

この HOWTO には、 1 つの spec ファイルで複数のディストリビューションに対応させるためのヒントが記されています。なお、これはパッケージ作成に関する初心者向けのガイドではありません。初心者向けの文書をご希望の場合は、 Build Service チュートリアル をお読みください。また、本 HOWTO では Debian 形式のパッケージ に関しては言及していません。

Build Service は openSUSE 向けの信頼に足る RPM パッケージを作成するだけでなく、 SLES, CentOS, Fedora, RedHat Enterprise Linux, Ubuntu, Debian, Mandriva などのディストリビューションに対応するパッケージを作成することができます。

制限事項について SUSE 系のディストリビューションでは、他の Build Service プロジェクトとリンクしたり統合したりすることで、簡単に依存関係を解決できるのに、 Fedora や Mandriva では解決が容易ではない場合があります。たとえば Qt4 や GTK2 の最新バージョンを必要とするパッケージを構築する場合、 SUSE や SLES では古いバージョンに対しても新しい Qt4 がバックポート (旧バージョン対応) されているため、対応する Build Service を利用することで容易に構築することができますが、それ以外のディストリビューションには用意されていないことが多く、それぞれ必要なものを独自に構築しなければならない場合があります。もちろんこれは、できる限り多くのディストリビューションに対応したい場合にのみ、発生する問題です。

複数のディストリビューションに対応するにあたって、注意しておかなければならないポイントは下記のとおりです:

  • デスクトップファイルをインストールする際には、それぞれのディストリビューションで異なるインストール形態やメニュー項目の作成手法などがありますので、それぞれの方式に合わせて設定してください。たとえば Mandriva の場合、特殊な RPM マクロである %update_menus を利用することで、メニューの更新を行なうことができます。これは SUSE や Fedora とは異なる方式です。たとえば下記のようになります:
%post
%update_menus

%postun
%clean_menus
  • 依存関係を指定する際に使用するパッケージ名が、ディストリビューションによって異なる場合があります。下記の章では、 spec ファイル内でこれを解決する際の各種ヒントを示しています。
  • RPM マクロがディストリビューションごとに少しずつ異なる場合があります。こちらも下記をお読みください。

複数プラットフォーム対応のパッケージを作成する際の例

Amilcar 氏の KDevelop パッケージ をご覧になるとよいでしょう。

ディストリビューション固有の構築手順を設定する

たとえば openSUSE/SUSE Linux の場合、下記のコードを追加することで openSUSE/SUSE Linux 固有の構築手順を設定することができます:

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

よりわかりやすくしたい場合は、下記のように記述することもできます:

%if 0%{?suse_version}
  <SUSE 固有の構築手順>
%else
  <その他のディストリビューションでの構築手順>
%endif

上記のようにすると、 SUSE の構築時とそれ以外のディストリビューションの構築時で、手順を分けることができるようになります。また、 SUSE のバージョンごとに手順を分けたい場合は、下記のようにしてください:

%if 0%{?suse_version} > 930

上記のようにすると、 SUSE Linux 9.3 以降のバージョンだけで処理するものを記述することができます。同様のチェックが他のディストリビューションにもあります:

%if %{defined fedora_version}
%if %{defined mandriva_version}
%if 0%{?fedora_version} < 5
%if 0%{?mandriva_version} > 2006

なお、 RPM では

=>

よりも

>= 

のほうが好まれます。

特定のバージョンだけを除外したいような場合は、下記のようにします:

%if 0%{?rhel_version} != 406

複数のディストリビューションを一括して指定したいような場合は、下記のようにします:

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

複数の条件を複数の行に分けて記述することもできます:

# mono は SUSE のバージョン 10 以降にしか用意されていないため
%if 0%{?suse_version}
%if 0%{?suse_version} >= 1010
BuildRequires:  mono-core
%endif
%endif

上記を下記のようにカッコでまとめてしまうと、 Fedora, RHEL, CentOS などでは構築が失敗してしまいます:

# Fedora, RHEL, CentOS では失敗する例:
%if 0%{?suse_version} && ( 0%{?suse_version} == 0 || 0%{?suse_version} >= 1010 )
BuildRequires:  mono-core
%endif

下記のようにしてアーキテクチャを選択することもできます:

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

警告: 下記のバージョン指定は、ディストリビューションの新しいバージョンが公開されるたびに追加されることに注意してください。最新バージョンを確認するには、それぞれのプロジェクトのページに移動して設定ファイルをご確認ください。たとえば RedHat 5 であれば、 https://build.opensuse.org/project/prjconf?project=RedHat%3ARHEL-5 にアクセスして "%rhel_version 505" の行を確認してください。また、新しくバージョンが追加された場合は、この内容も更新しておいてください。

注意: sles_version は SLES 11 では設定されなくなったことにもご注意ください。その代わりに、 %if 0%{?suse_version} == 1110 を指定してください。

下記にバージョンを判別するための記述を示します:

ディストリビューション 記述 コメント
openSUSE Factory  %if 0%{?suse_version} > 1320 将来のリリース向け
openSUSE Leap 42.1  %if 0%{?suse_version} == 1315 SLE12* と同じです
openSUSE 13.2  %if 0%{?suse_version} == 1320
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 SLE 11* と同じです
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 SLE 10* と同じです
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 Leap 42.1* と同じです
CentOS 5  %if 0%{?centos_version} == 505
CentOS 6  %if 0%{?centos_version} == 600
CentOS 7  %if 0%{?centos_version} == 700
RHEL 4  %if 0%{?rhel_version} == 406
RHEL 5  %if 0%{?rhel_version} == 505
RHEL 6  %if 0%{?rhel_version} == 600
RHEL 7  %if 0%{?rhel_version} == 700
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
Fedora 18  %if 0%{?fedora_version} == 18
Fedora 19  %if 0%{?fedora_version} == 19
Fedora 20  %if 0%{?fedora_version} == 20
Fedora 21  %if 0%{?fedora_version} == 21
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

* SLE と openSUSE を区別したい場合は、 0%{?is_opensuse} をお使いください。


サービスパックについては判別することができません。 SLES 11 SP1 は SLES 11 と同じ変数が設定されます。

info ファイルのインストール

info ファイルは %info_add および %info_del の各マクロを利用してインストールする必要があります。たとえば下記のようになります:

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

なお、ディストリビューションによっては info ファイルを .gz や .bz2, .lzma (Mandriva など) の形式に圧縮する場合があります。ファイルリストでは、 %ext_info マクロを利用することで、ファイルの拡張子を取得することができます。

依存関係の処理

ディストリビューションが異なるとパッケージの名前付けルールも異なることから、 Requires: や BuildRequires: のタグに指定するパッケージの名前も違ってきます。そのような問題に直面した場合は、下記のような置き換え (Substitute) ルールを作成してください:

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

プロジェクトの設定を変更するには、 osc meta prjconf <プロジェクト名> -e のように実行してください。これにより $EDITOR 環境変数で指定したエディタが起動します。 Web クライアントの場合は、プロジェクトの Advanced セクション内に隠されています。

このような置き換えを build.opensuse.org で使用していて、置き換えルールを他のユーザにも公開したいと考えていらっしゃる (つまり、中央の設定ファイル内に統合してもらいたい) 場合は、 opensuse-buildservice@opensuse.org 宛に英語でご連絡ください。

ディストリビューションに対してすでに設定されている Substitutes: ルールを確認したい場合は、それぞれのディストリビューションに対応したプロジェクトの設定ファイルをお読みください。たとえば CentOS 6 であれば https://build.opensuse.org/project/prjconf?project=CentOS%3ACentOS-6 になります。

SUSE 固有で、かつ 10.0 以上でしか利用できない Suggests:

# 'Suggests:' は SUSE 固有の機能です。 "Requires:" よりは弱い関係を示す
# もので、必ずしも vi や graphwiz が必要となるプログラムではないが、
# あったほうがより適切であることを示します。
%if 0%{?suse_version} > 1000
# 920 や 930 でも利用できますが、 sle9 や 910 では利用できません
Suggests:       vim graphviz
%endif

Fedora/RHEL での Qt 3.x の検出

RedHat や Fedora では、 Qt を利用してアプリケーションを構築する際、パッケージの命名ルールや構築設定が他のものとは異なっています。下記は、 Qt ベースのアプリケーションを SUSE と Fedora の両方で、かつ 1 つの spec ファイルで構築する場合の例です:

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

BuildRequires 以下には下記のように指定します:

%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>

Mandriva での Qt4 の検出

既定では Qt4 よりも前に Qt3 が見つかってしまうため、 spec ファイル内の %build セクションに下記のように指定します:

%build  
 
%if 0%{?mandriva_version} > 2006  
export PATH=/usr/lib/qt4/bin:$PATH  
export QTDIR=%{_prefix}/lib/qt4/  
%endif  
  • Mandriva 2008 以降で変更されているかもしれません

Mandriva での Provides/Obsoletes の取り扱い

CentOS や RHEL, Fedora, SUSE などとは異なり、 Mandriva を取り扱う際は特別に注意する必要があります。これらは対象のライブラリがアプリケーション内でしか使用されないものであっても、アプリケーションとは別にライブラリ用の RPM を作成することが多いためです。一般的なライブラリの取り扱いと同じく、アプリケーション側ではライブラリへの依存関係を設定する (foo -> libfoo) だけですが、他のディストリビューションとは依存関係が異なるため、 Provides や Obsoletes を明示的に指定して、矛盾が起こらないようにする必要があります。 RPM では依存関係を自動的に処理しますが、場合によっては下記のように明示的な指定をしたほうがより便利な場合もあります:

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

古いディストリビューションの取り扱い

パッケージ内のソースコードは古いディストリビューションにも対応している場合がありますが、パッケージを構築するにあたっては、古いディストリビューションとの互換性確保が面倒になる場合があります。

たとえば autoreconf -fi を呼び出す際 (一般的な spec ファイルではよく用いられます) 、インストールを意味する -i を指定していることから、 tar ボール内に同梱されている config.sub, config.guess, ltmain.sh は、ターゲットとなるディストリビューションの autoconf パッケージが提供するものに置き換えられます。これはつまり、ソースコードが 2007 年に作成されたものであっても、 SLE 10 用に構築する場合は 2005 年のものに置き換えられることになり、うまく動作しなくなってしまう場合がありうることを示しています。これはたとえば、 SLE10 で libapr1 をコンパイルしたいような場合に当てはまります。

このような場合は、 autoheader, autoconf を呼び出すように設定するのが適切 (場合によっては必須となるかもしれません) であるほか、 autoreconf の代わりに必要な処理を記述するように指定するのがよいでしょう。たとえば下記のようになります:

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

Debian および xUbuntu のパッケージ

これらのパッケージを作成する際は、 Debian ビルド をお読みください。

ディストリビューションごとの RPM マクロとドキュメンテーション

パッケージングガイドライン

Fedora Packager's Guide (英語)

Mandriva Packaging (英語)

RHEL, Mandriva, SUSE の RPM マクロの比較 (英語)