有子串的rpm条件吗?

时间:2018-09-21 13:38:01

标签: if-statement conditional rpm rpmbuild rpm-spec

我有一个规范文件,它使用类似条件的条件

%if "%{pkgname}" = "wobble"
  Requires: extra-thing
  ....
%endif

,现在需要将wobble-thingwobble-otherthing和任何其他wobble*视为满足相同条件。很容易,您会认为。

在不放弃规范文件和对文件进行预处理的情况下,我找不到任何方法。

不幸的是,在这种情况下无法对文件进行预处理,它将使整个构建链望尘莫及,而整个构建链有望仅通过rpm构建规范。

rpmrpmbuild中有许多未公开的魔法,例如${error:blah}%{expand:..othermacros...}%global之类的东西。甚至%if %{value} < 42之类的简单关系操作似乎也没有实际记录在任何地方。

有人知道字符串前缀或字符串前缀模式匹配运算符吗?

我正在寻找与bash的if [[ "${VAR}" == *"substring"* ]]; then构造等效的规范。

编辑:需要明确的是,我不仅仅使用shell条件语句的原因是,我需要影响rpm元数据。我认为很明显,如果可以的话,我会使用shell if。我进行了编辑,以使上面的内容更加清晰。

编辑:为了帮助其他人找到它,这与rpm中的字符串模式匹配有关。 rpm的复杂条件。规格文件中的条件部分。字符串前缀,后缀或后缀运算符以及rpmbuild中的测试。

4 个答案:

答案 0 :(得分:2)

您不能使用正则表达式或通配符。但是您可以使用“或”。

%if "%{pkgname}" == "wobble" || "%{pkgname}" == "wobble-thing"
..
%endif

或者您可以在外壳中进行评估

%global yourmacro   %(/usr/bin/perl ...%{pkgname}... )

其中/usr/bin/perl ...可以是任何脚本,并且yourmacro设置为此脚本的stdout值。

答案 1 :(得分:0)

这是在规范中使用%define的一种方法。

%global original_string  SomeLongStringHere
%global matching_string  LongString
%global nomatch_string   NoMatchHere

%define matchTwoStrings(n:) \
string_one=%1 \
string_two=%2 \
if [[ "${string_one}" = *"${string_two}"* ]]; then \
   echo "It matches" \
else \
     echo "It doesn't match" \
fi \
%{nil}

#然后在.spec的某个地方,例如,我使用了%post部分

%post
%matchTwoStrings "%{original_string}" "%{matching_string}"
%matchTwoStrings "%{original_string}" "%{nomatch_string}"

因为它在%post部分中,它将在.rpm安装期间打印出来。

It matches
It doesn't match

答案 2 :(得分:0)

您确实可以使用Lua脚本,尽管它需要一些奇特的技巧。以下是向您的rpm规范文件中添加uniqueConstraints式宏的方法,您可以在starts_with条件下使用该宏。

%if

这里发生的是:

# Define the Lua starts_with function we want to expose
%{lua:
  function starts_with(str, start)
   return str:sub(1, #start) == start
  end
}

# Define the rpm parametric macro starts_with(str,prefix) that
# calls Lua and maps "false"=>"0" and "true"=>"1"
#
# Note that we need to inject the parameters %1 and %2 to a
# string-quoted version of the Lua macro, then expand the whole
# thing.
#
%define starts_with(str,prefix) (%{expand:%%{lua:print(starts_with(%1, %2) and "1" or "0")}})

# Finally we can use the parametric macro
#
%if %{starts_with "wobble-boo" "wobble"}
  Requires: wobble
%endif

扩展到

%{starts_with "wobble-boo", "wobble}

扩展为

%{expand:%%{lua:print(starts_with("wobble-boo", "wobble") and "1" or "0")}}

执行Lua函数%{lua:print(starts_with("wobble-boo", "wobble") and "1" or "0")} ,该函数测试长度与“ start”相同的“ str”的左锚子字符串是否等于“ start”。如果是这样,则返回“ 1”;如果为假,则返回“ 0”。这是因为rpm无法识别starts_with为假。

所以我们在这里要做的是从参数rpm宏调用Lua函数并调整返回值。

好。令人痛苦的是,rpm需要这种技巧来完成这样的简单任务,而且几乎完全没有记录在案。但是很漂亮。

答案 3 :(得分:0)

实际上,您无需Lua就可以做到这一点,并且可以在BASH中完全使用您提到的要在原始问题中使用的if [[ ... ]]构造。

为说明如何,让我们看一下我使用的tmux RPM的规范文件的标题部分。它必须在运行RHEL / CentOS版本6、7和8(和/或任何其他重建版本,如Oracle)的任何主机上未经修改地构建。这就是我所拥有的:

%global name tmux
%global version 3.1b
%global release 1%{?dist}

%global _hardened_build 1

Summary:        A terminal multiplexer
Name:           %{name}
Version:        %{version}
Release:        %{release}
# Mostly ISC-licensed, but some files in compat/ are 2-/3-clause BSD.
License:        ISC/BSD
URL:            https://tmux.github.io/
Source0:        https://github.com/tmux/%{name}/releases/download/%{version}/%{name}-%{version}.tar.gz
Source1:        bash_completion_tmux.sh
BuildRequires:  %(/bin/bash -fc 'if [[ %{name} == tmux* ]]; then echo make ; else echo nomake ; fi') %(/bin/bash -fc 'if [[ %{name} == wobble* ]]; then echo wobble ; fi')
BuildRequires:  gcc, ncurses-devel, %{expand:%(/bin/bash -c 'if [[ %{?rhel}%{!?rhel:9} -le 6 ]]; then echo libevent2-devel ; else echo libevent-devel ; fi')}
Requires:       %{expand:%(/bin/bash -c 'if [[ %{?rhel}%{!?rhel:9} -le 6 ]]; then echo libevent2 ; else echo libevent ; fi')} >= 2.0

此RPM的棘手部分是RHEL6提供了libevent软件包,但它的版本是1.4.13,对于tmux而言,它太旧了,无法成功构建。 (它需要libevent2.x。)但是,好消息是RHEL6实际上具有两个版本! libevent2 RPM的版本为2.0.21,最新版本足以用于tmux。但是我不能仅仅将libevent2-devel列为我的构建依赖项。该软件包不适用于RHEL 7或8,因为它们的默认libevent RPM已经是版本2。我也不能将libevent-devel列为构建依赖项,因为虽然libeventlibevent2软件包可以并排安装,但libevent-devellibevent2-devel RPM冲突。

正如您在上面的规格文件中所看到的那样,我针对此挑战的解决方案是使用RPM宏根据以下内容将字符串libevent-devellibevent2-devel注入到BuildRequires:标头值中基于BASH的%{rhel}宏值的比较(/etc/rpm/macros.dist在RHEL 6、7上向其分配678的值,或分别为8)。对于RHEL6(以及以前的理论上... RHEL5已死,而RHEL4和更早的版本则是超级死机!),使用后一个值,而将前一个值用于RHEL7和RHEL8。

我还添加了一些人为设计的字符串匹配宏调用,以说明它可以正常工作。我的实际specfile既不包含第一行BuildRequires:也不包含最后Requires:行(因为它是不必要的/多余的);我专门为此练习添加了它们,以说明条件对构建时和运行时依赖项均有效。

我怎么知道他们工作了?我检查了:

$ rpm -qp --qf '[%|SOURCERPM?{%25{=NEVRA}}:{%21{=NEVR}.src}|.rpm:  %{REQUIREFLAGS:deptype}: %{REQUIRENEVRS}\n]' tmux-3.1b-1.el6.x86_64.rpm tmux-3.1b-1.el6.src.rpm tmux-3.1b-1.el8.x86_64.rpm tmux-3.1b-1.el8.src.rpm | fgrep 'manual:'
   tmux-3.1b-1.el6.x86_64.rpm:  manual: libevent2 >= 2.0
      tmux-3.1b-1.el6.src.rpm:  manual: make
      tmux-3.1b-1.el6.src.rpm:  manual: gcc
      tmux-3.1b-1.el6.src.rpm:  manual: ncurses-devel
      tmux-3.1b-1.el6.src.rpm:  manual: libevent2-devel
   tmux-3.1b-1.el8.x86_64.rpm:  manual: libevent >= 2.0
      tmux-3.1b-1.el8.src.rpm:  manual: gcc
      tmux-3.1b-1.el8.src.rpm:  manual: libevent-devel
      tmux-3.1b-1.el8.src.rpm:  manual: make
      tmux-3.1b-1.el8.src.rpm:  manual: ncurses-devel

请注意,正确的libevent2 >= 2.0依赖项(在末尾为2)显示在RHEL6 RPM中;另一方面,RHEL8 RPM再次正确显示libevent >= 2.0(末尾为 2)。另外,在两个SRPM中都显示了对make的构建依赖性,并且nomakewobble均不存在,证明了模式与tmux*和{{1}上的条件匹配}发挥了应有的作用。