2.10. 转换一个一致的 Spec 文件


本节讨论将传统 spec 文件转换为 Software Collection spec 文件,以便在传统软件包和 Software Collection 中使用转换的 spec 文件。

2.10.1. 转换的 Spec 文件示例

要查看 diff 文件将传统 spec 文件与转换的 spec 文件进行比较,请参考以下示例:
--- a/less.spec
+++ b/less.spec
@@ -1,10 +1,14 @@
+%{?scl:%global _scl_prefix /opt/provider}
+%{?scl:%scl_package less}
+%{!?scl:%global pkg_name %{name}}
+
 Summary: A text file browser similar to more, but better
-Name: less
+Name: %{?scl_prefix}less
 Version: 444
 Release: 7%{?dist}
 License: GPLv3+
 Group: Applications/Text
-Source: http://www.greenwoodsoftware.com/less/%{name}-%{version}.tar.gz
+Source: http://www.greenwoodsoftware.com/less/%{pkg_name}-%{version}.tar.gz
 Source1: lesspipe.sh
 Source2: less.sh
 Source3: less.csh
@@ -19,6 +22,7 @@ URL: http://www.greenwoodsoftware.com/less/
 Requires: groff
 BuildRequires: ncurses-devel
 BuildRequires: autoconf automake libtool
-Obsoletes: lesspipe < 1.0
+Obsoletes: %{?scl_prefix}lesspipe < 1.0
+%{?scl:Requires: %scl_runtime}
 
 %description
 The less utility is a text file browser that resembles more, but has
@@ -31,7 +35,7 @@ You should install less because it is a basic utility for viewing text
 files, and you'll use it frequently.
 
 %prep
-%setup -q
+%setup -q -n %{pkg_name}-%{version}
 %patch1 -p1 -b .Foption
 %patch2 -p1 -b .search
 %patch4 -p1 -b .time
@@ -51,16 +55,16 @@ make CC="gcc $RPM_OPT_FLAGS -D_GNU_SOURCE -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOU
 %install
 rm -rf $RPM_BUILD_ROOT
 make DESTDIR=$RPM_BUILD_ROOT install
-mkdir -p $RPM_BUILD_ROOT/etc/profile.d
+mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/profile.d
 install -p -c -m 755 %{SOURCE1} $RPM_BUILD_ROOT/%{_bindir}
-install -p -c -m 644 %{SOURCE2} $RPM_BUILD_ROOT/etc/profile.d
-install -p -c -m 644 %{SOURCE3} $RPM_BUILD_ROOT/etc/profile.d
-ls -la $RPM_BUILD_ROOT/etc/profile.d
+install -p -c -m 644 %{SOURCE2} $RPM_BUILD_ROOT%{_sysconfdir}/profile.d
+install -p -c -m 644 %{SOURCE3} $RPM_BUILD_ROOT%{_sysconfdir}/profile.d
+ls -la $RPM_BUILD_ROOT%{_sysconfdir}/profile.d
 
 %files
 %defattr(-,root,root,-)
 %doc LICENSE
-/etc/profile.d/*
+%{_sysconfdir}/profile.d/*
 %{_bindir}/*
 %{_mandir}/man1/*

2.10.2. 转换标签和 Macro 定义

以下步骤演示了如何将传统 spec 文件中的标签和宏定义转换为 Software Collection spec 文件。

过程 2.1. 转换标签和宏定义

  1. 您可以通过在 %_scl_prefix 之上定义 %scl_package macro 宏来更改根目录的位置:
    %{?scl:%global _scl_prefix /opt/provider}
  2. 在 spec 文件中添加 %scl_package 宏。将宏放在 spec 文件前,如下所示:
    %{?scl:%scl_package package_name}
  3. 当没有为 Software Collection 构建软件包时,建议您在 spec 文件中定义 %pkg_name 宏:
    %{!?scl:%global pkg_name %{name}}
    因此,您可以使用 %pkg_name 宏定义在 spec 文件中需要的软件包的原始名称,然后可用于构建传统软件包和 Software Collection。
  4. 更改 spec 文件中的 Name 标签,如下所示:
    Name: %{?scl_prefix}package_name
  5. 如果您要与其他 Software Collection 软件包构建或链接,请为 RequiresBuildRequires 标签中的软件集合软件包名称添加前缀,如下所示: %{?scl_prefix}
    Requires: %{?scl_prefix}ifconfig
    当取决于软件包的系统版本时,您应该避免使用版本化的 RequiresBuildRequires。如果您需要依赖于系统更新的软件包,请考虑在 Software Collection 中包含该软件包,或者在系统软件包更新时记住重建您的 Software Collection。
  6. 要检查所有基本 Software Collection 的软件包是否为主 metapackage 的依赖项,请在 spec 文件中的 BuildRequiresRequires 标签中添加以下宏:
    %{?scl:Requires: %scl_runtime}
  7. 使用 ObsoletesConflictsBuildConflicts%{?scl_prefix} 和 标签添加前缀。这是为了确保 Software Collection 可用于将新软件包部署到旧的系统中,而无需指定软件包,例如 Obsolete 从基本系统安装中删除。例如:
    Obsoletes: %{?scl_prefix}lesspipe < 1.0
  8. Provides 标签添加前缀 %{?scl_prefix},如下例所示:
    Provides: %{?scl_prefix}more

2.10.3. 转换子软件包

对于使用 -n 选项定义它们名称的任何子软件包,使用 %{?scl_prefix} 前缀,如下例所示:
%package -n %{?scl_prefix}more
前缀不仅适用于 %package 宏,也适用于 %description%files。例如:
%description -n %{?scl_prefix}rubygems
RubyGems is the Ruby standard for publishing and managing third party
libraries.
如果子软件包需要主软件包,请确保也调整该子软件包中的 Requires 标签,以便标签使用 %{?scl_prefix}%{pkg_name}。例如:
Requires: %{?scl_prefix}%{pkg_name} = %{version}-%{release}

2.10.4. 转换 RPM 脚本

这部分论述了转换 RPM 脚本的常规规则,它们通常可在传统 spec 文件的 %prep%build%install%check%pre%post 部分找到。
  • 将所有出现的 %name 替换为 %pkg_name。最重要的是,这包括调整 %setup 宏。
    • 调整 spec 文件的 %setup 部分中的 %prep 宏,以便宏可以在 Software Collection 环境中处理不同的软件包名称:
      %setup -q -n %{pkg_name}-%{version}
      请注意,%setup 宏是必需的,且您必须始终使用带有 -n 选项的宏才能成功构建软件集合。
  • 如果您使用任何 %_root_ 宏指向系统文件系统层次结构,则必须使用这些宏的条件,以便您可以使用 spec 文件来构建传统软件包和 Software Collection。编辑宏,如下例所示:
    mkdir -p %{?scl:%_root_sysconfdir}%{?!scl:%_sysconfdir}
  • 当构建依赖于其他 Software Collection 软件包的软件集合软件包时,务必要确保 scl 启用 功能链接或运行正确的二进制文件等。需要此示例之一是针对 Software Collection 库进行编译,或使用 Software Collection 中的解释器运行解释脚本。
    使用 %{?scl: 前缀嵌套脚本,如下例所示:
    %{?scl:scl enable %scl - << \EOF}
     set -e
     ruby example.rb
     RUBYOPT="-Ilib" ruby bar.rb
     # The rest of the script contents goes here.
    %{?scl:EOF}
    在脚本中指定 set -e 非常重要,无论脚本是否在 rpm shell 还是 scl 环境中执行,脚本的行为都是一致的。
  • 请注意 Software Collection 软件包安装过程中执行的任何脚本,例如:
    • %pretrans, %pre,
    • %post, %postun, %posttrans,
    • %triggerin%triggerun%triggerpostun
    如果您在这些脚本中使用 scl 启用 功能,建议您从空环境开始,以避免与基本系统安装有任何意外冲突。
    要做到这一点,在启用 Software Collection 前使用 env -i -,如下例所示:
    %posttrans
    %{?scl:env -i - scl enable %{scl} - << \EOF}
    %vagrant_plugin_register %{vagrant_plugin_name}
    %{?scl:EOF}
  • RPM 脚本中找到的所有硬编码路径都必须替换为正确的宏。例如:将所有出现的 /usr/share 替换为 %{_datadir}。这是必要的,因为 $RPM_BUILD_ROOT 变量和 %{build_root} 宏不会被 scl 宏重新定位。

2.10.5. Software Collection Automatic Provides and Requires and Filtering Support

重要
本节中描述的功能在 Red Hat Enterprise Linux 6 中不提供。
Red Hat Enterprise Linux 7 中的 RPM 支持自动 ProvidesRequires 和过滤。例如,对于所有 Python 库,RPM 会自动添加以下 Requires
Requires: python(abi) = (version)
第 2.10 节 “转换一个一致的 Spec 文件” 所述,您应该在转换传统 RPM 软件包时将此 Requires%{?scl_prefix} 前缀:
Requires: %{?scl_prefix}python(abi) = (version))
请记住,搜索这些依赖项的脚本有时必须为您的 Software Collection 进行重写,因为原始 RPM 脚本不足可扩展,因此在某些情况下,过滤不可用。例如,要重写自动 Python ProvidesRequires,请在 macros.%{scl}-config 宏文件中添加以下行:
%__python_provides /usr/lib/rpm/pythondeps-scl.sh --provides %{_scl_root} %{scl_prefix}
%__python_requires /usr/lib/rpm/pythondeps-scl.sh --requires %{_scl_root} %{scl_prefix}
/usr/lib/rpm/pythondeps-scl.sh 文件基于传统软件包中的 pythondeps.sh 文件并调整搜索路径。
如果您有需要调整的 ProvidesRequires,例如 pkg_config Provides,则有两种方法:
  • macros.%{scl}-config 宏中添加以下几行,使其适用于 Software Collection 中的所有软件包:
    %_use_internal_dependency_generator 0
    %__deploop() while read FILE; do /usr/lib/rpm/rpmdeps -%{1} ${FILE}; done | /bin/sort -u
    %__find_provides /bin/sh -c "%{?__filter_prov_cmd} %{__deploop P} %{?__filter_from_prov}"
    %__find_requires /bin/sh -c "%{?__filter_req_cmd}  %{__deploop R} %{?__filter_from_req}"
    
    # Handle pkgconfig's virtual Provides and Requires
    %__filter_from_req | %{__sed} -e 's|pkgconfig|%{?scl_prefix}pkgconfig|g'
    %__filter_from_prov | %{__sed} -e 's|pkgconfig|%{?scl_prefix}pkgconfig|g'
  • 或者,在您要过滤 ProvidesRequires 的每个 spec 文件中的标签定义后添加以下行:
    %{?scl:%filter_from_provides s|pkgconfig|%{?scl_prefix}pkgconfig|g}
    %{?scl:%filter_from_requires s|pkgconfig|%{?scl_prefix}pkgconfig|g}
    %{?scl:%filter_setup}
重要
在使用过滤器时,您需要注意您更改的自动依赖项。例如,如果传统软件包包含 Requires: pkgconfig(package_1)Requires: pkgconfig(package_2),且软件集合中仅包含 package_2,请确保不要为 package_1 过滤 Requires 标签。

2.10.6. Software Collection Macro 文件支持

在某些情况下,您可能需要通过 Software Collection 软件包提供宏文件。它们位于 %{?scl:%{_root_sysconfdir}}%{!?scl:%{_sysconfdir}}/rpm/ 目录中,对应于传统软件包的 /etc/rpm/ 目录。在提供宏文件时,请确保:
  • 通过将 .%{scl} 附加到其名称来重命名宏文件,以便它们不会与基本系统安装中的文件冲突。
  • 宏文件中的宏不能扩展,或者它们正在使用条件,如下例所示:
    %__python2 %{_bindir}/python
    %python2_sitelib %(%{?scl:scl enable %scl '}%{__python2} -c "from distutils.sysconfig import get_python_lib; print(get_python_lib())"%{?scl:'})
再如,在有些情况下,您可能需要创建依赖于 Software Collection python26 的 Software Collection mypythonpython26 Software Collection 定义 %{__python2} 宏,如上例中所示。此宏将评估为 /opt/provider/mypython/root/usr/bin/python2,但 python2 二进制文件仅在 python26 Software Collection (/opt/provider/python26/root/usr/bin/python2)中提供。
要在 mypython Software Collection 环境中构建软件,请确保:
  • macros.python.python26 宏文件,它是 python26-python-devel 软件包的一部分,包含以下行:
    %__python26_python2 /opt/provider/python26/root/usr/bin/python2
  • 以及 python26-build 子软件包中的宏文件,以及任何基于 Software Collection 的 build 子软件包包含以下行:
    %scl_package_override() {%global __python2 %__python26_python2}
    
只有在存在来自相应 Software Collection 的构建子软件包时才重新定义 %{__python2} 宏,这通常意味着您要为该 Software Collection 构建软件。

2.10.7. Software Collection Shebang 支持

shebang 是脚本开头的一系列字符,用作解释器指令。shebang 由自动依赖项生成器处理,指向某个位置,可能在系统根文件系统中。
当自动依赖关系生成器处理 shebang 时,它会根据它们所指向的解释器添加依赖项。在 Software Collection 的角度来看,有两种 shebangs 类型:
#!/usr/bin/env example
这个 shebang 指示 /usr/bin/env 程序运行解释器。
自动依赖关系生成器将如预期对 /usr/bin/env 程序创建一个依赖项。
如果在 enable scriptlet 中正确定义了 $PATH 环境变量,则在 Software Collection 文件系统层次结构中找到 示例 解释器,如预期。
建议您重写 Software Collection 软件包中的 shebang,以便 shebang 指定软件集合文件系统层次结构中的解释器的完整路径。
#!/usr/bin/example
这个 shebang 指定解释器的直接路径。
自动依赖关系生成器将对位于 Software Collection 文件系统层次结构之外的 /usr/bin/example 解释器创建一个依赖项。但是,在为 Software Collection 构建软件包时,您通常希望对位于 Software Collection 文件系统层次结构中的 %{?_scl_root}/usr/bin/example 解释器创建依赖项。
请记住,即使您正确重新定义 $PATH 环境变量,这不会影响使用哪个解释器。始终使用软件集合文件系统层次结构之外的解释器的系统版本。在大多数情况下,这并不是必需的。
如果您使用这种类型的 shebang,并且您希望 shebang 在构建软件集合软件包时指向 Software Collection 文件系统层次结构,请使用类似如下的命令:
find %{buildroot} -type f | \
  xargs sed -i -e '1 s"^#!/usr/bin/example"#!%{?_scl_root}/usr/bin/example"'
其中 /usr/bin/example 是您要使用的解释器。

2.10.8. 在另一软件集合上制作 Software Collection Depend

要使一个 Software Collection 依赖于另一个 Software Collection 中的软件包,您需要调整依赖 Software Collection 的 spec 文件中的 BuildRequiresRequires 标签,以便这些标签正确定义依赖项。
例如,要定义两个名为 software_collection_1software_collection_2 的 Software Collections 的依赖项,请将以下三行添加到应用程序的 spec 文件中:
BuildRequires: scl-utils-build
Requires: %scl_require software_collection_1
Requires: %scl_require software_collection_2
确保 spec 文件还包含 spec 文件前的 %scl_package 宏,例如:
%{?scl:%scl_package less}
请注意,%scl_package 宏必须包含在您的软件集合的每个 spec 文件中。
您还可以使用 %scl_require_package 宏定义特定软件集合中特定软件包的依赖项,如下例所示:
BuildRequires: scl-utils-build
Requires: %scl_require_package software_collection_1 package_name
Red Hat logoGithubRedditYoutubeTwitter

学习

尝试、购买和销售

社区

关于红帽文档

通过我们的产品和服务,以及可以信赖的内容,帮助红帽用户创新并实现他们的目标。

让开源更具包容性

红帽致力于替换我们的代码、文档和 Web 属性中存在问题的语言。欲了解更多详情,请参阅红帽博客.

關於紅帽

我们提供强化的解决方案,使企业能够更轻松地跨平台和环境(从核心数据中心到网络边缘)工作。

© 2024 Red Hat, Inc.