[Rpm-maint] Fixing macro scoping

Panu Matilainen pmatilai at laiskiainen.org
Mon Jan 23 10:30:21 UTC 2017

Consider the following snippet, originating from

%{!?foo: %define foo bar}
%define dofoo() true
echo 1: %{foo}
echo 2: %{foo}

I'd assume everybody agrees both %{foo}'s should evaluate to the same 
value, but that is not the case currently. Using a cli-variant of the above:

[pmatilai at sopuli rpm]$ rpm --define 'dofoo() true' --eval '%{!?foo: 
%define foo bar}' --eval '%foo' --eval '%dofoo' --eval '%foo'
warning: Macro %foo defined but not used within scope


The flaw here is that rpm supposedly implements block level scoping for 
macros (so in the above example, "foo" would only exist in the 
{!?foo:...} block), but doesn't actually enforce that, unless a 
parametric macro is "called". Current rpm warns about it, but warnings 
or not this behavior doesn't make the slightest sense.

The question is, what do you think %{foo} should evaluate to in this case?

Fixing it to honor the strict "block scoping" concept is not hard, now 
that the scoping level is honored from Lua too (see 
In this case the above reproducer would emit


Another option is slightly changing the whole scoping notion: parametric 
macros require locally scoped macros for the automatic argument macros 
like %#, %* and %1 anyway (it's flawed too currently, see below). So 
perhaps the macro scoping should follow the current "call level", ie a 
macro defined inside a parametric macro body is local to that macro, and 
everything else is global. In this case the reproducer would emit


I have implementations for both and also a personal opinion, but I'd 
like to hear what others think.

The related flaw is whether locally scoped macros should be visible to 
deeper nesting levels. Currently everything is, including those 
automatic macros:

$ rpm --define '%bar() Bar %#: %{?1} %{?2}' --define '%foo() Foo %#: 
%{?1} %{?2} %bar a' --eval '%foo 1 2'
Foo 2: 1 2 Bar 1: a 2

I'd consider this a bug, %2 should not be defined within %bar() since it 
did not receive two arguments. So IMO the correct output in the above 
should be:
Foo 2: 1 2 Bar 1: a

But what about a macro manually %define'd within %foo() - should that be 
visible in %bar()?

	- Panu -

More information about the Rpm-maint mailing list