2017-03-15 64 views
0

我想从另一个宏调用一个参数的RPM宏。在m4,这将是平凡的就像这样(只是一个例子,不是我真正想做的事情):RPM:使用参数从另一个宏的参数调用宏

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”两个宏,它无法像为例在上面。我也不太喜欢这个解决方案,因为在这里使用选项似乎不直观。

什么是实现预期效果的首选方式?

回答

1

我发现了一个更优雅的解决方案。我不明白为什么它的工作原理,我不知道这是否是普遍适用的:

%define path() /mnt/%1/lib 
%global mkd() mkdir %{path %%1}/stuff 
%mkd usr 
=> mkdir /mnt/usr/lib/stuff 

它的工作原理只有在mkd%global定义。 path可以用%define%global来定义。也节点引用的百分比字符。

+1

这因为%global不是在被解析时被评估(如%define),而是在它被调用的时候。基本上任何时候你写%定义你通常要使用%全局。 – msuchy

+0

@msuchy这是另一种方式。使用时定义'%define'宏,定义时'%global'。这就是为什么这是有效的:'mkd'的定义被冻结,'path'已经被扩展,所以当参数被替换时不会发生递归。 – matejcik

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