在 RPM 规范文件中使用脚本定义版本
Define Version with script in RPM spec file
我有一个 RPM 规范文件,使用 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 = "\(.*\)"||p' /fullfilepath/values.txt | sed 's/^\(.*\)-.*$//')")
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 = "\(.*\)"||p' /fullfilepath/values.txt | sed 's/^\(.*\)-.*$//')"
//returns 1.2
这些效果很好,所以我不知道是什么导致它失败。当我在规范文件的定义标签中调用相同的东西时,有什么可能导致它失败的想法吗?
更新
我尝试用实际值替换文件名,所以它看起来像这样
echo "$(sed -n 's|^[ ]*appVersion = "\(.*\)"||p' <<< "appVersion = \"1.2-SNAPSHOT\"" | sed 's/^\(.*\)-.*$//')"
在终端中调用时有效,但作为
%(echo "$(sed -n 's|^[ ]*appVersion = "\(.*\)"||p' <<< "appVersion = \"1.2-SNAPSHOT\"" | sed 's/^\(.*\)-.*$//')")
但我仍然得到
Empty tag: Version: Error
更新 2
我测试了一个不同的更复杂的命令 echo "12"
:
%define version %(echo "$(git log -1 | grep commit | awk -F"commit " '{print }' | cut -c1-8)")
这也行!使版本成为提交哈希的前 7 位数字。
更新 3
谜团还在继续,我做了一个测试来检查它是否是 sed 命令的原因,但以下命令给我 1.2 作为版本
%define version %(echo "$( sed 's/.*= //' <<< "appVersion = 1.2" )")
如果此命令有效但我的第一个命令无效,那么它必须与我的第一个命令中的某些内容一起使用,该命令仅在直接在终端而不是在 %(cmd) 中调用时有效。越来越近了!
更新 4
好的,所以我似乎已经隔离了它必须是什么,很好奇,看起来它可能是 rpmbuild 不喜欢的 -n
或 s| | |p
语法。我做了一个更简单的版本。看看:
#Error, doesn`t set version to 1.2
%define version %(echo "$( sed -n 's|^.*-\(-*\)||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 }' <<< "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 }' <<< "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 }' <<< "appVersion = \"1.2-SNAPSHOT\"")"| cut -d'-' -f1)
因此,从这个角度来看,我认为可能有一种类似的幕后解析,对我从 rpm 发出的第一个 sed 命令的结果进行了解析。我们将有我们的方式 rpm!
最终更新
使用 rpm 休战,我将改用此命令:
%define version %(echo "$(awk '/ appVersion =/{ print }' /filepath/values.txt" | sed 's/\"//g' | cut -d'-' -f1)
它与我的第一个命令执行相同的操作,并在 specfile 中正确设置版本号。如果有人猜到为什么第一个命令不会 运行,我会很高兴阅读它。和平!
您必须有一个调用 rpmbuild 命令的 shell 脚本。您可以使用该脚本来计算版本(或者就此而言,您尝试在 rpm 规范文件中使用的任何命令)。
更改您的原始代码,
%define version %(echo "$(sed -n 's|^[ ]*appVersion = "\(.*\)"||p' /fullfilepath/values.txt | sed 's/^\(.*\)-.*$//')")
Version: %{version}
到,
%define version _VERSION_
Version: %{version}
并 sed VERSION 到其在调用 rpmbuild 的 shell 脚本中的计算值(在调用 rpmbuild 之前)。在将实际规范内容转储到某个文件后,将该生成的文件传递给同一 shell 脚本中的 rpmbuild。
步骤总结如下:
假设您有一个 builder.sh shell 调用 rpmbuild 的脚本,请执行以下步骤:
- 更新您的规格文件以具有 VERSION 占位符 string/macro,如上所示
- 将当前的 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 命令的用法。
我会做一个包装脚本。这使您可以决定它是常规版本还是开发版本等。然后您可以使用 --define
选项传递变量 - 请参阅 this question for more options.
回应@Herrgott 的评论“如果你 %define
它在规范中并尝试用 --define
重新定义它不会覆盖它”(评论中不能有换行符) - 你可以设置一个与--define
.
同名的“_override
”变量
%if 0%{?val_override:1}
%define val %{val_override}
%else
%define val whatever
%endif
我有一个 RPM 规范文件,使用 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 = "\(.*\)"||p' /fullfilepath/values.txt | sed 's/^\(.*\)-.*$//')")
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 = "\(.*\)"||p' /fullfilepath/values.txt | sed 's/^\(.*\)-.*$//')"
//returns 1.2
这些效果很好,所以我不知道是什么导致它失败。当我在规范文件的定义标签中调用相同的东西时,有什么可能导致它失败的想法吗?
更新
我尝试用实际值替换文件名,所以它看起来像这样
echo "$(sed -n 's|^[ ]*appVersion = "\(.*\)"||p' <<< "appVersion = \"1.2-SNAPSHOT\"" | sed 's/^\(.*\)-.*$//')"
在终端中调用时有效,但作为
%(echo "$(sed -n 's|^[ ]*appVersion = "\(.*\)"||p' <<< "appVersion = \"1.2-SNAPSHOT\"" | sed 's/^\(.*\)-.*$//')")
但我仍然得到
Empty tag: Version: Error
更新 2
我测试了一个不同的更复杂的命令 echo "12"
:
%define version %(echo "$(git log -1 | grep commit | awk -F"commit " '{print }' | cut -c1-8)")
这也行!使版本成为提交哈希的前 7 位数字。
更新 3
谜团还在继续,我做了一个测试来检查它是否是 sed 命令的原因,但以下命令给我 1.2 作为版本
%define version %(echo "$( sed 's/.*= //' <<< "appVersion = 1.2" )")
如果此命令有效但我的第一个命令无效,那么它必须与我的第一个命令中的某些内容一起使用,该命令仅在直接在终端而不是在 %(cmd) 中调用时有效。越来越近了!
更新 4
好的,所以我似乎已经隔离了它必须是什么,很好奇,看起来它可能是 rpmbuild 不喜欢的 -n
或 s| | |p
语法。我做了一个更简单的版本。看看:
#Error, doesn`t set version to 1.2
%define version %(echo "$( sed -n 's|^.*-\(-*\)||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 }' <<< "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 }' <<< "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 }' <<< "appVersion = \"1.2-SNAPSHOT\"")"| cut -d'-' -f1)
因此,从这个角度来看,我认为可能有一种类似的幕后解析,对我从 rpm 发出的第一个 sed 命令的结果进行了解析。我们将有我们的方式 rpm!
最终更新
使用 rpm 休战,我将改用此命令:
%define version %(echo "$(awk '/ appVersion =/{ print }' /filepath/values.txt" | sed 's/\"//g' | cut -d'-' -f1)
它与我的第一个命令执行相同的操作,并在 specfile 中正确设置版本号。如果有人猜到为什么第一个命令不会 运行,我会很高兴阅读它。和平!
您必须有一个调用 rpmbuild 命令的 shell 脚本。您可以使用该脚本来计算版本(或者就此而言,您尝试在 rpm 规范文件中使用的任何命令)。
更改您的原始代码,
%define version %(echo "$(sed -n 's|^[ ]*appVersion = "\(.*\)"||p' /fullfilepath/values.txt | sed 's/^\(.*\)-.*$//')")
Version: %{version}
到,
%define version _VERSION_
Version: %{version}
并 sed VERSION 到其在调用 rpmbuild 的 shell 脚本中的计算值(在调用 rpmbuild 之前)。在将实际规范内容转储到某个文件后,将该生成的文件传递给同一 shell 脚本中的 rpmbuild。
步骤总结如下:
假设您有一个 builder.sh shell 调用 rpmbuild 的脚本,请执行以下步骤:
- 更新您的规格文件以具有 VERSION 占位符 string/macro,如上所示
- 将当前的 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 命令的用法。
我会做一个包装脚本。这使您可以决定它是常规版本还是开发版本等。然后您可以使用 --define
选项传递变量 - 请参阅 this question for more options.
回应@Herrgott 的评论“如果你 %define
它在规范中并尝试用 --define
重新定义它不会覆盖它”(评论中不能有换行符) - 你可以设置一个与--define
.
_override
”变量
%if 0%{?val_override:1}
%define val %{val_override}
%else
%define val whatever
%endif