我想从另一个宏调用一个RPM宏。在m4
中,这可以像这样简单地完成(只是一个例子,而不是我真正想做的事):
define(`path', `/mnt/$1/lib')
define(`mkd', `mkdir path($1)/stuff')
mkd(`usr')
=> mkdir /mnt/usr/lib/stuff
或CPP
语法:
#define path(x) /mnt/x/lib
#define mkd(x) mkdir path(x)/stuff
mkd(usr)
=> mkdir /mnt/usr/lib/stuff
RPM中的明显等价物(破碎!)将是:
# THIS IS BROKEN
%define path() /mnt/%1/lib
%define mkd() mkdir %{path %1}/stuff
%mkd usr
但是没有工作,RPM打印" 错误:宏扩展中的递归级别太多。它可能是由递归宏声明引起的。"
我已经做到了"工作"使用以下代码:
%define path() /mnt/%1/lib
%define mkd() mkdir %{expand:%%{path %1}}/stuff
%mkd usr
但是,我无法相信这种笨拙的代码是推荐的方法。另一种似乎有用的方法是使用选项参数:
%define path(d:) /mnt/%{-d*}/lib
%define mkd(p:) mkdir %{path -d%{-p*}}/stuff
%mkd -p usr
但这只是因为我使用了不同的选项字符;如果我使用' -d
'对于这两个宏,它都像上面的例子一样失败。我也不喜欢这个解决方案,因为在这里使用选项似乎不直观。
达到预期效果的首选方法是什么?
答案 0 :(得分:1)
我找到了更优雅的解决方案。我不明白为什么它有效,我不确定它是否普遍适用:
...
login() {
this.authService.loginWithGoogle().then((data) => {
this.router.navigate(['']);
}).catch((error) => {
this.error = error;
});
}
仅当%define path() /mnt/%1/lib
%global mkd() mkdir %{path %%1}/stuff
%mkd usr
=> mkdir /mnt/usr/lib/stuff
定义为mkd
时才有效。可以使用%global
或path
来定义%define
。同时节点引用的百分比字符。
答案 1 :(得分:1)
递归宏的RPM处理被破坏。据我所知,没有“推荐”的方式;这根本不起作用,你列出的变通方法就像你将要获得的那样接近。
在我看到的RPM宏集中(包括RPM本身内部的一些),这通常通过条件参数来解决:如果提供,则使用-p
选项,否则为%1
。
%define path(p:) /mnt/%{-p:%{-p*}}%{!-p:%1}/lib
%define mkd(d:) mkdir %{path -p %1}/stuff
echo "making path at %{path hello}"
%{mkd hello}
您还可以使用“非功能”定义 - 这是%define
/ %global
案例中发生的事情。
%define _path /mnt/%1/lib
# note no parentheses at end of `_path`
%define path() %_path
%define mkd() mkdir %{_path}/stuff
这样,%_path
宏内联到path()
和mkd()
定义中,并且没有发生递归。
如果您想使用%2
作为路径,这将无效,但由于这是一个不同的名称,您可以使用旧方式......... o_O
%define maketwo() mkdir %1; mkdir %{path %2}/stuff
答案 2 :(得分:0)
似乎该问题中报告的问题已在最新版本的rpm(4.11和4.14之间)中解决。
~> rpm --version
RPM version 4.14.1
~> rpm --eval '
%define path() /mnt/%1/lib
%define mkd() mkdir %{path %1}/stuff
%define foo bar
%mkd %foo'
=> mkdir /mnt/bar/lib/stuff
在rpm 4.11下,由于“递归级别过多”而失败,因此必须解决上一个答案(%global mkd() mkdir %{path %%1}/stuff
)。