openSUSE:构建服务跨分发行方法
概述
本指南列出了使用单个 spec 文件处理不同发行版的特殊提示。这不是打包人员的入门指南,请访问 构建服务教程 以获取更多信息。此外,本文档不涵盖使用 Debian 包 的发行版。
构建服务不仅可以为 openSUSE,还可以为最新的 SLES、CentOS、Fedora、Red Hat Enterprise Linux、Ubuntu、Debian 和 Mandriva/Mageia 发行版可靠地打包 rpm。
有哪些限制? 实际的唯一限制是 Fedora 或 Mandriva 缺少某些依赖项,而这些依赖项可以很容易地通过链接或聚合到另一个构建服务项目来满足 SUSE 发行版。例如:构建需要最新版本 Qt4 或 GTK2 的 SUSE 包很容易,因为这些依赖项可以通过构建服务上提供较新 Qt4 包回溯版本的其他仓库来满足旧版本的 SUSE 以及 SLES。只有通过在您自己的项目中打包所需的依赖项才能克服这一点。即使这样,只有当您希望支持尽可能多的发行版时,才会出现此问题。
您需要注意的发行版之间的“陷阱”差异
- 安装桌面文件。这五个发行版中的每一个都使用略有不同的机制来安装桌面文件,然后创建菜单项。Mandriva 甚至有一个特殊的 rpm 宏 %update_menus 来完成此操作,它使用类似 Debian 的设置,与 SUSE 或 Fedora 不同。例如
%post %update_menus %postun %clean_menus
- 有关依赖项的包命名。请参阅下面的更多特定提示和技巧,以使您的 spec 文件中的工作正常。
- 微妙的 rpm 宏差异。使用下表显示以下变体。
您能告诉我一个跨平台包的良好示例吗?
检测用于特殊代码的发行版风味
您可以添加
%if %{defined suse_version}
%if %{undefined suse_version}
或者更可移植的
%if 0%{?suse_version}
<suse stuff here>
%else
<other distros>
%endif
来检查当前构建是否针对 SUSE 发行版。请注意,[在同一级别上没有 '%elseif' 来链接多个测试]。请注意,Fedora 使用%{fedora}没有_version。您还可以使用
%if 0%{?suse_version} > 1130
例如,在 SUSE Linux 11.3 之后执行某些操作。其他发行版也存在类似的检查。
%if %{defined fedora}
%if %{defined mdkversion}
%if 0%{?fedora} < 5
%if 0%{?mdkversion} > 2006
请注意,rpm 优先使用
>=
而不是
=>
您还可以排除一个特定的版本
%if 0%{?rhel_version} != 406
您可以将多个发行版组合到一个 if 块中,如下所示
%if 0%{?fedora} || 0%{?rhel_version} || 0%{?centos_version}
<yourstuff>
%endif
要对条件进行分组,请将条件拆分为多行,如下所示
# mono: only on suse, sle only from sle10
%if 0%{?suse_version}
%if 0%{?suse_version} >= 1010
BuildRequires: mono-core
%endif
%endif
另一种方法是使用括号,例如
# mono: only on suse, sle only from sle10
%if 0%{?suse_version} && ( 0%{?suse_version} == 0 || 0%{?suse_version} >= 1010 )
BuildRequires: mono-core
%endif
在较旧的基于 RHEL 的发行版(如 Fedora、RHEL 和 CentOS)上,括号分组可能会失败。任何基于 RHEL-5 及更高版本的发行版都应支持分组。对于较旧的版本,请将条件拆分并正确嵌套它们。
您还可以使用例如
%if 0%{?suse_version} == 1310
%ifarch x86_64
<yourstuff>
%endif
%endif
警告:以下列出的版本可能会更改!要检查最新版本,请转到项目页面并检查配置文件(例如,对于 RHEL 5,请查看内容 "%rhel_version": https://build.opensuse.org/project/prjconf?project=RedHat%3ARHEL-5)。如果版本不匹配,请更新此页面。
注意: "sles_version" 宏已 不再设置 在 SLE 12 中。
openSUSE:Packaging_for_Leap#RPM_Distro_Version_Macros 有助于为 openSUSE/SUSE 选择正确的设置。您还可以使用 osc buildconfig 来检查特定构建配置的宏定义。
在本地,您还可以运行以下命令来获取您的值
grep suse_version /usr/lib/rpm/suse/macros
否则,下表可能有助于选择正确的设置,包括非 (open)SUSE 发行版
| 发行版 | 变量 | 评论 |
|---|---|---|
| openSUSE Tumbleweed | %if 0%{?suse_version} > 1600 | 当前即将发布的版本(正在更改) |
| openSUSE Leap 16.0 | %if 0%{?suse_version} == 1600 && 0%{?is_opensuse} | SLES 16 目前不使用 sle_version 宏。 |
| openSUSE Leap 15.6 | %if 0%{?sle_version} == 150600 && 0%{?is_opensuse} | |
| openSUSE Leap 15.5 | %if 0%{?sle_version} == 150500 && 0%{?is_opensuse} | |
| openSUSE Leap 15.4 | %if 0%{?sle_version} == 150400 && 0%{?is_opensuse} | |
| openSUSE Leap 15.3 | %if 0%{?sle_version} == 150300 && 0%{?is_opensuse} | |
| openSUSE Leap 15.2 | %if 0%{?sle_version} == 150200 && 0%{?is_opensuse} | |
| openSUSE Leap 15.1 | %if 0%{?sle_version} == 150100 && 0%{?is_opensuse} | |
| openSUSE Leap 15.0 | %if 0%{?sle_version} == 150000 && 0%{?is_opensuse} | 也可以是 Backports:SLE-15¹ |
| openSUSE Leap 42.3 | %if 0%{?sle_version} == 120300 && 0%{?is_opensuse} | "leap_version" 已弃用,请参阅下文 |
| openSUSE Leap 42.2 | %if 0%{?sle_version} == 120200 && 0%{?is_opensuse} | "leap_version" 已弃用,请参阅下文 |
| openSUSE Leap 42.1 | %if 0%{?sle_version} == 120100 && 0%{?is_opensuse} | |
| openSUSE Leap 42.x | %if 0%{?suse_version} == 1315 && 0%{?is_opensuse} | 使用上面的比较来区分特定版本 |
| 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 | 也可以是 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 | 也可以是 SLE10* |
| SUSE Linux 10.0 | %if 0%{?suse_version} == 1000 | |
| SUSE Linux 9.3 | %if 0%{?suse_version} == 930 | |
| Backports:SLE-15 | %if 0%{?sle_version} == 150000 && 0%{?is_backports} | |
| Backports:SLE-12-SP5 | %if 0%{?sle_version} == 120500 && 0%{?is_backports} | |
| Backports:SLE-12-SP4 | %if 0%{?sle_version} == 120400 && 0%{?is_backports} | |
| Backports:SLE-12-SP3 | %if 0%{?sle_version} == 120300 && 0%{?is_backports} | |
| Backports:SLE-12-SP2 | %if 0%{?sle_version} == 120200 && 0%{?is_backports} | |
| Backports:SLE-12-SP1 | %if 0%{?sle_version} == 120100 && 0%{?is_backports} | |
| Backports:SLE-12 | %if 0%{?sle_version} == 120000 && 0%{?is_backports} | |
| SLE 15 SP4 | %if 0%{?sle_version} == 150400 && !0%{?is_opensuse} | |
| SLE 15 SP3 | %if 0%{?sle_version} == 150300 && !0%{?is_opensuse} | |
| SLE 15 SP2 | %if 0%{?sle_version} == 150200 && !0%{?is_opensuse} | |
| SLE 15 SP1 | %if 0%{?sle_version} == 150100 && !0%{?is_opensuse} | |
| SLE 15 GA | %if 0%{?sle_version} == 150000 && !0%{?is_opensuse} | |
| SLE 12 SP5 | %if 0%{?sle_version} == 120500 && !0%{?is_opensuse} | |
| SLE 12 SP4 | %if 0%{?sle_version} == 120400 && !0%{?is_opensuse} | |
| SLE 12 SP3 | %if 0%{?sle_version} == 120300 && !0%{?is_opensuse} | |
| SLE 12 SP2 | %if 0%{?sle_version} == 120200 && !0%{?is_opensuse} | |
| SLE 12 SP1 | %if 0%{?sle_version} == 120100 && !0%{?is_opensuse} | |
| SLE 12 GA | %if 0%{?sle_version} == 120000 && !0%{?is_opensuse} | |
| SLE 12 | %if 0%{?suse_version} == 1315 && !0%{?is_opensuse} | 删除 "is_opensuse" 检查以获取 Leap 42 和 SLE 12 |
| SLE 11 | %if 0%{?sles_version} == 11 | 也可以检查 "suse_version" 是否为 1110 |
| SLE 10 | %if 0%{?sles_version} == 10 | 也可以检查 "suse_version" 是否为 1010 |
| SLES 9 | %if 0%{?sles_version} == 9 | 也可以检查 "suse_version" 是否为 910 |
| 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 | |
| RHEL 8 | %if 0%{?rhel} == 8 | |
| Scientific Linux 6 | %if 0%{?scientificlinux_version} == 600 | |
| Scientific Linux 7 | %if 0%{?scientificlinux_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 | |
| Fedora 36 | %if 0%{?fedora} == 36 | fedora_version 宏不可用。 |
| 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 | |
| Arch Linux | %if 0%{?arch_linux} | 仅在项目配置中有效 |
| Debian | %if 0%{?debian} | 仅在项目配置中有效 |
* 使用 0%{?is_opensuse} 以避免与 SLE 版本冲突
¹ 使用 %if !0%{?is_backports} 来区分 Leap 15 和 Backports:SLE-15
leap_version 宏(已弃用)
"leap_version" 宏现已弃用,并且已被 Leap 15.0 删除。
不应将此宏用于新的 RPM spec 文件:而是同时使用 "sle_version" 和 "is_opensuse" 宏。
请参阅下表以获取可能的值。如果未列出发行版,则未定义该宏。
| 发行版 | 值 |
|---|---|
| openSUSE Leap 42.1 | 未定义 |
| openSUSE Leap 42.2 | 420200 |
| openSUSE Leap 42.3 | 420300 |
| openSUSE Leap 15.0 | 未定义 |
服务包只能区分 SLES12。SLES11 SP1 设置完全相同的变量,如 SLES11。
您还应该查看 Leap/SLES 这里:openSUSE:How_to_contribute_to_Leap
安装信息文件
应使用 %info_add 和 %info_del 宏安装信息文件。例如
%post
%info_add %{name}.info
%preun
%info_del %{name}.info
请注意,信息文件在某些发行版上被压缩为 .gz 和 .bz2 甚至 .lzma(最新的 Mandriva/Mageia)。您可以使用 %ext_info 获取文件列表中的文件后缀。
安装 man 文件
man 文件在某些发行版上被压缩为 .gz 和 .bz2 甚至 .lzma(最新的 Mandriva/Mageia)。您可以使用 %ext_man 获取文件列表中的文件后缀。
ext_info 和 ext_man 宏未为 Mageia 或 Fedora 定义,因此您需要在 prjconf 中添加它们。
%if 0%{?mageia} == 6
Macros:
%ext_info .xz
%ext_man .xz
:Macros
%endif
%if 0%{?fedora_version} && 0%{?fedora_version} >= 25
Macros:
%ext_info .gz
%ext_man .gz
:Macros
%endif
处理依赖关系
不同的发行版通常对软件包使用不同的名称,因此 Requires: 和 BuildRequires: 标签可能需要从仓库到仓库有所不同。可以在项目的配置中指定软件包名称替换,例如
%if 0%{?fedora_version}
Substitute: libnetcdf-devel netcdf
%endif
这将“替换” libnetcdf-devel 为 netcdf 在所有受影响的 spec 文件中。
为了更改您的项目配置,请使用 osc meta prjconf <project-name> -e,这将启动 $EDITOR。在 Web 客户端中,这隐藏在中央项目菜单的高级部分中。
如果您在 build.opensuse.org 上执行此操作,并且认为您的替换对其他人也有用(并且可能添加到中央配置中),请发送消息到 opensuse-buildservice@opensuse.org。
如果您想查看特定发行版的现有替换项,请查看该发行版的项目配置,例如 https://build.opensuse.org/project/prjconf?project=CentOS%3ACentOS-6
推荐:和建议:
Suggests: 是 SUSE(>=10)和 Fedora(>=24) 中可用的一项功能。这是 "Requires:" 的一个弱版本。
# the package does not need vi or graphviz to run.
%if 0%{?suse_version} >= 1000
Suggests: vim graphviz
%endif
同样适用于推荐:
update-alternatives 包仅适用于 SUSE
update-alternatives 是一个 SUSE 包,但在 Fedora/RHEL 上不可用,在那里 chkconfig 包提供了相同的功能。解决方案:直接使用二进制文件的完整路径
Requires(post): /usr/sbin/update-alternatives Requires(postun): /usr/sbin/update-alternatives
代替
# Requires(post): update-alternatives # Requires(postun): update-alternatives
另一种解决方案是将以下宏添加到 构建配置
%if ! 0%{?suse_version}
Substitute: update-alternatives chkconfig
%endif
在 Fedora/RHEL 上查找 Qt 3.x
Redhat/Fedora 使用不同的命名方案和构建设置来使用 Qt 构建其他应用程序。以下是一个示例 spec 文件,用于在 SUSE 和 Fedora 上使用一个 spec 文件构建基于 Qt 的应用程序
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
然后
%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
默认情况下,Qt3 会在 Qt4 之前被找到,因此只需将以下内容添加到 spec 文件的 %build 部分
%build
%if 0%{?mandriva_version} > 2006
export PATH=/usr/lib/qt4/bin:$PATH
export QTDIR=%{_prefix}/lib/qt4/
%endif
- 这可能在 Mdv 2008 上已经改变
处理 Mandriva Provides/Obsoletes
处理 Mandriva 时需要特别小心,因为与 CentOS、RHEL、Fedora 或 SUSE 不同,他们通常为许多私下使用这些库的应用程序创建单独的库 rpm。应用程序 foo 可能还依赖于 libfoo 或 libfoo-0。因此,您需要检查 Mandriva 原始 spec 文件,看看它们是否有明确的 Provides 和 Obsoletes,以防止安装时的冲突。即使 RPM 会自动处理依赖关系,您可能仍然需要像下面这样显式地添加它们
%if 0%{?mandriva_version}
Provides: foo libfoo-0
Obsoletes: foo libfoo-0
%endif
在较旧的发行版上构建
虽然软件包中的源代码可以在较旧的发行版上构建,但软件包的构建方式有时会以不兼容的方式演变。
例如,一些 spec 文件有时会调用 `autoreconf -fi`, 有可能的是 tarball 的版本的config.sub, config.guess和ltmain.sh文件会被构建主机的 autoconf 包中的副本替换,这是-i选项的结果。当构建主机的软件足够旧,而要构建的软件足够新时,这可能会导致 config 文件的降级,这可能会产生负面影响,甚至导致错误编译,例如在 SLE10 上构建 libapr1 时。
因此,最好甚至需要您手动调用autoheader, autoconf或者其他需要的命令,而不是autoreconf在 Factory 之前的目标上。一个例子是
%if 0%{?suse_version} > 1010
autoreconf -fi
%else
autoheader
autoconf
%endif
Debian 和 xUbuntu 包
对于这些类型的软件包,请阅读 debian builds 页面。
CentOS 和 RHEL EPEL 仓库
对于 CentOS 和 RHEL,您可能需要使用 EPEL 仓库。它们在 OBS 中可用,地址为 Fedora:EPEL:7