在 RPM 规范文件中使用脚本定义版本
Posted
技术标签:
【中文标题】在 RPM 规范文件中使用脚本定义版本【英文标题】:Define Version with script in RPM spec file 【发布时间】:2016-02-19 16:43:41 【问题描述】:我有一个 RPM Spec 文件,使用 rpmbuild 在 rhel7 上构建,我想在其中使用脚本定义版本。
我在这里读到http://www.techrepublic.com/article/rpmproc-spec-file/,我可以这样做:
%define version 1.2
Version: %version
这里是RPM spec file - Is it possible to dynamically populate a spec file variable,我可以用脚本来定义:
%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 不喜欢的 -n
或 s| | \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)
因此,从这个角度来看,我认为在后台解析我的第一个 sed 命令从 rpm 的结果可能存在类似的类型。我们将有自己的方式 rpm!
最终更新
已与 rpm 休战,我将使用此命令代替:
%define version %(echo "$(awk '/ appVersion =/ print $3 ' /filepath/values.txt" | sed 's/\"//g' | cut -d'-' -f1)
它与我的第一个命令执行相同的操作,并在 specfile 中正确设置版本号。如果有人对为什么第一个命令不会运行有任何猜测,我会很高兴阅读它。和平!
【问题讨论】:
可能是因为/fullfilepath/values.txt
的权限问题。尝试用实际(或简化)值替换它。
【参考方案1】:
您必须有一个调用 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 脚本,请执行以下步骤:
-
更新您的规范文件,使其具有 VERSION 占位符字符串/宏,如上所示
将当前 rpm 规范文件移动到 my_package_template.spec
在 builder.sh 中,运行命令以获取您的版本并将版本保存到变量中
在 my_package_template.spec 文件上使用 sed 命令将 VERSION 替换为此计算的版本,并将 sed 输出保存到 my_package.spec
将 my_package.spec 传递给 rpmbuild 命令。
重复第 1 步、第 3 步和第 4 步以替换规范文件中任何其他 shell 命令的使用。
【讨论】:
rpmbuild
允许从命令行设置变量,这比需要sed
和临时文件要容易得多。【参考方案2】:
我会做一个包装脚本。这使您可以决定是常规版本还是开发版本等。然后您可以使用--define
选项传递变量 - 请参阅this question for more options。
要回应@Herrgott 的评论“如果你在规范中%define
它并尝试用--define
重新定义它不会覆盖它”(在 cmets 中不能有换行符) - 你可以设置一个“@987654325 @" 与--define
同名的变量。
%if 0%?val_override:1
%define val %val_override
%else
%define val whatever
%endif
【讨论】:
如果你在规范中%define
它并尝试用 --define
重新定义它不会覆盖它
@Herrgott 在主要回复中回复;不能在 cmets 中换行。以上是关于在 RPM 规范文件中使用脚本定义版本的主要内容,如果未能解决你的问题,请参考以下文章