在 RPM 规范文件中使用脚本定义版本



我有一个RPM规范文件,建立在带有rpmbuild的rhel7上,我想用脚本定义版本。

我在这里读到 http://www.techrepublic.com/article/rpmproc-spec-file/,我可以这样做:

%define version 1.2
Version: %{version}

这里RPM规范文件 - 是否可以动态填充一个spec文件变量,我可以用脚本定义:

%define whoami %(cmd)

所以我尝试在我的规范文件中执行此操作:

%define version %(echo "$(sed -n 's|^[ ]*appVersion = "(.*)"|1|p' /fullfilepath/values.txt | sed 's/^(.*)-.*$/1/')")
Version: %{version}  **Line 23**

但我得到一个

error: line 23: Empty tag: Version:

到目前为止,我已经测试过的东西:

%define version %(echo "12") --basic script works ok, version becomes 12
//As a command straight in terminal
$ echo "$(sed -n 's|^[ ]*appVersion = "(.*)"|1|p' /fullfilepath/values.txt | sed 's/^(.*)-.*$/1/')"
//returns 1.2

这些工作得很好,所以我不知道是什么导致它失败。 任何想法,当我在规范文件中定义标签中调用相同的东西时,会导致它失败?

更新

我尝试将文件名替换为实际值,因此看起来像这样

echo "$(sed -n 's|^[ ]*appVersion = "(.*)"|1|p' <<< "appVersion = "1.2-SNAPSHOT"" | sed 's/^(.*)-.*$/1/')"

这在终端中调用时有效,但作为

%(echo "$(sed -n 's|^[ ]*appVersion = "(.*)"|1|p' <<< "appVersion = "1.2-SNAPSHOT"" | sed 's/^(.*)-.*$/1/')") 

但我仍然得到

Empty tag: Version: Error

更新 2

我测试了一个更复杂的命令,然后echo "12"

%define version %(echo "$(git log -1 | grep commit | awk -F"commit " '{print $2}' | cut -c1-8)")

这也行得通!使版本成为提交哈希的前 7 位数字。

更新 3

谜团还在继续,我做了一个测试来检查是否是 sed 命令是原因,但以下命令给了我 1.2 作为版本

%define version %(echo "$( sed 's/.*= //' <<< "appVersion = 1.2" )")

如果这个命令有效但不是我的第一个命令,那么它必须与我的第一个命令中的某些内容一起使用,该命令仅在直接在终端中而不是在 %(cmd( 中调用时才有效。越来越近!

更新 4

好的,所以我似乎已经隔离了它必须是什么,好奇,看起来它可能是 rpmbuild 不喜欢的-ns| | 1 |p语法。我做了一个更简单的原始版本。看看吧:

#Error, doesn`t set version to 1.2
%define version %(echo "$( sed -n 's|^.*-(-*)|1|p' <<< "foo-1.2" )") 
#Works ok! sets version to 1.2
%define version %(echo "$( sed 's/.*= //' <<< "appVersion = 1.2" )") 

不幸的是,尽管我认为我无法再做隔离并找出问题所在。在第二个命令的样式中使用 sed 没有错,但对于为什么第一个命令不起作用仍然非常有趣。

更新 5

我发现在 %(( 中使用规范文件和 rpmbuild 中的任何脚本时,这里存在一些深层次的问题。我尝试使用 awk 只是为了看看会发生什么,它也坏了!这比我最初想的要深得多,就像发现了一个阴谋:

#In terminal it prints 1.2-SNAPSHOT, but in Spec it's an error 
%define version %(echo "$(awk '/appVersion /{ print $3 }' <<< "appVersion = "1.2-SNAPSHOT"" | tr -d ")")
sh: -c: line 0: unexpected EOF while looking for matching `)'
sh: -c: line 1: syntax error: unexpected end of file
error: line 23: Empty tag: Version:

更新 6

对大家来说是好消息和坏消息,我发现 rpm 似乎在后台做一些自己的工作,并没有显示它的作用,我终于找到了一个命令,当通过 rpm 调用时给出不同的值:

%define version %(echo "$(awk '/midonetVersion /{ print $3 }' <<< "midonetVersion = "5.1-SNAPSHOT"")")
#In terminal it echos "5.1-SNAPSHOT" (literally wrapped in "" )
#When in spec it set version to 5.1-SNAPSHOT , rpmbuild is removing the ""

所以现在我做了一个调整,称之为:

#echos "5.1 in terminal and sets version to 5.1 in spec
%define version %(echo "$(awk '/appVersion /{ print $3 }' <<< "appVersion = "1.2-SNAPSHOT"")"| cut -d'-' -f1)

因此,从这个来看,我认为可能有类似的幕后解析我的第一个 rpm sed 命令的结果。我们会有我们的方式 rpm!

最终更新

使用

rpm 休战,我将改用以下命令:

%define version %(echo "$(awk '/ appVersion =/{ print $3 }' /filepath/values.txt" | sed 's/"//g' | cut -d'-' -f1)

它与我的第一个命令执行相同的操作,并在规范文件中正确设置版本号。如果有人猜测为什么第一个命令无法运行,我会很高兴阅读它。和平!

你必须有一个调用 rpmbuild 命令的 shell 脚本。您可以使用该脚本来计算版本(或者就此而言,您尝试在 rpm 规范文件中使用的任何命令(。

更改您的原始代码,

%define version %(echo "$(sed -n 's|^[ ]*appVersion = "(.*)"|1|p' /fullfilepath/values.txt | sed 's/^(.*)-.*$/1/')")
Version: %{version}

%define version _VERSION_
Version: %{version}

和 sed VERSION 到它在调用 rpmbuild 的 shell 脚本中的计算值(在调用 rpmbuild 之前(。将实际规范内容转储到某个文件后,将生成的文件传递给同一 shell 脚本中的 rpmbuild。

以下是步骤摘要:

假设您有一个调用 rpmbuild 的 builder.sh shell 脚本,请执行以下步骤:

  1. 更新您的规范文件以具有 VERSION 占位符字符串/宏,如上所示
  2. 将当前转速规范文件移至 my_package_template.spec
  3. 在 builder.sh 中,运行命令以获取版本并将版本保存到变量
  4. 对 my_package_template.spec 文件使用 sed 命令将 VERSION 替换为此计算版本,并将 sed 输出保存到 my_package.spec
  5. 将 my_package.spec 传递给 rpmbuild 命令。

重复步骤 1、3 和 4 以替换 spec 文件中任何其他 shell 命令的使用。

我会做一个包装脚本。这使您可以决定它是常规版本还是开发版本等。然后,您可以使用--define选项传递变量 - 有关更多选项,请参阅此问题。

为了回应@Herrgott的评论"如果你在规范中%define它并尝试用--define重新定义它不会覆盖它"(注释中不能有换行符( - 你可以设置一个同名的"_override"变量与--define

%if 0%{?val_override:1}
%define val %{val_override}
%else
%define val whatever
%endif

Necro,但我们开始了。

首先,所有都必须转义,因此您需要将它们全部切换到 .
\其次,当您调用:

%define version %(echo "$(sed -n 's|^[ ]*appVersion = "(.*)"|1|p' /fullfilepath/values.txt | sed 's/^(.*)-.*$/1/')")

您实际上是在调用一个子shell,用于打印要运行的命令的文本。 但是,当您使用:

Version: %{version}

您需要%{version}计算为就地字符串,而不是命令才能获取它。 可能您只需要删除echo部分,这也简化了命令。

如果我没记错的话,我相信您在 sed 命令中使用了仅可用于扩展正则表达式的正则表达式语法,因此您需要它的-E选项。 但是,您使用第一个 sed 命令所做的是从文件中提取appVersion = "到最后一"后的所有内容,然后尝试删除该行上最后一个-之后的所有内容。 假设您确实希望在第一个版本号之前-部分,这更容易通过利用K运算符仅返回匹配内容的grep -Po来实现。

%define version %(grep -P '^[ ]*appVersion = "\K([^"-]+)' /fullfilepath/values.txt)

现在,%{version}设置为运行分析命令时返回的值,而不是命令本身。 如果解析有任何问题,它将投注设置为 %{nil}(空(。

但是,您需要记住,/fullfilepath/values.txt路径是调用rpmbuildrpmspec时的路径。 如果运行它的主机系统没有恰好/fullfilepath/values.txt的文件,那么它将无法找到要解析的文件。

<小时 />

如果您确实需要将其设置为要运行的命令而不是运行它的值,则可以省略周围的%(),而只需将其设置为

%define version grep -P '^[ ]*appVersion = "\K([^"-]+)' /fullfilepath/values.txt

相关内容

  • 没有找到相关文章

最新更新