在 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 不喜欢的 -ns| | |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 的脚本,请执行以下步骤:

  1. 更新您的规格文件以具有 VERSION 占位符 string/macro,如上所示
  2. 将当前的 rpm 规范文件移动到 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 以替换规范文件中任何其他 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