这篇文章是 极简 RPM 打包指南 的补充文档。
宏 (Macro) 是 RPM .spec 文件中使用的一种特殊的语法,和 C 语言中的宏类似,它被嵌入到.spec 文件中,经过 rpmbuild 预处理之后,转换为真正的 shell 脚本。
宏的作用
宏包含两种,简单宏和包含参数的宏。简单的宏可以当作字符串变量使用。复杂的宏可以接受参数,可以类比为函数。
宏是递归定义的,也即宏可以包含宏。
宏的使用
宏的使用语法有两种,比如:
$<name>
或者
${<name>}
<name>
是宏的名字。
这两种语法各有优劣。第二种语法可以安全地与嵌入到 bash 脚本之中,比如:
cd %{_prefix}/bin/
它等价于:
cd /usr/bin
第一种语法则在调用宏函数(可以接受参数的宏)的时候很有用。假如我定义了一个宏:
%define mymacro() (echo -n "My arg is %1" ; sleep %1 ; echo done.)
那么我可以这样调用它:
%mymacro 5
内置宏
在安装有 rpm 的系统中,有很多内置的宏可以直接使用。下面的命令可以告诉你这些内置宏都来自哪里:
rpm --showrc|grep "^Macro path"
如果你想知道这些内置宏是如何定义的,你可以:
rpmbuild --eval "%{macro_name}"
最后,下面是最常见的内置宏和它们的作用:
%define ... 定义一个宏
%undefine ... 删除一个宏
%global ... 类似于编程语言中的 global 标记,使一个宏全局可用,而不只是作用于它的作用域
需要注意,%define 和%global 除了作用域,还有第二个区别。因为宏可以嵌套定义,所以展开时就分为两种:使用时展开,定义时展开。
%define 定义的宏是在使用时才展开的,%global 则在定义时就展开了。
编写宏
正如前面所说,宏分为两种,变量宏(简单不接受参数的宏)和函数宏(接收参数的宏),它们的定义也各不相同。
变量宏:
%define
比如:
%define maintainer example@example.com
函数宏:
%define
(opts)
比如:
%define mymacro() (echo -n "My arg is %1" ; sleep %1 ; echo done.)
函数宏的参数处理,与 bash 脚本编程中的 getopt 完全一致。在编写函数宏时,下面的变量(宏)可以直接使用:
%0 the name of the macro being invoked
%* all arguments (unlike shell, not including any processed flags)
%** all arguments (including processed flags)
%# the number of arguments
%{-f} if present at invocation, the flag f itself
%{-f*} if present at invocation, the argument to flag f
%1, %2 the arguments themselves (after getopt(3) processing)
逻辑判断
RPM 宏支持一些简单的条件判断语句。
%if…%else…%endif
%if %{my_macro} 如果宏 my_macro 存在
%define my_new_macro 12345 定义一个新宏
%undefine my_macro 删掉旧宏
%else 否则
%define my_macro 54321 定义 my_macro
%endif 结束 if 语句
只有%if 和%endif 是必须的
!
%if !%{my_macro} 如果宏 my_macro 不存在
?
fedora@localhost ~> rpm --eval "%{macro_to_test}" 当访问一个宏,但宏不存在时,会返回整个语句本身
%{macro_to_test}
fedora@localhost ~> rpm --eval "%{?macro_to_test}" 使用?语法之后,如果宏不存在,返回空
fedora@localhost ~> rpm --eval "%{?_prefix}" 如果宏存在,则返回宏的值
/usr
fedora@localhost ~> rpm --eval "%{?_prefix:hello world}" 甚至可以自定义宏的返回值
hello world
这里只是一些简单的语法,实际打包时会用到其他更具体的宏,功能都是类似的。
参考
这篇文章的大部分内容来自 RPM 官方文档 Macro syntax。