Apologies for missing this when the recommendation of %global over %define in Fedora guidelines was being discussed, but better late than never...
https://fedoraproject.org/wiki/Packaging/Guidelines#.25global_preferred_over... says "The two macro defining statements behave the same when they are a the top level of rpm's nesting level" but this is not correct:
The body of a %global macro is expanded at definition time, whereas the body of a %define is expanded only when used. For many uses it doesn't make any difference but identical they are not, even on top level - for example see the attached example spec:
$ rpmbuild -bp macroex.spec 2>/dev/null|grep ^case case1: first - second case2: second - %{xxx}
Another example of this difference (in case of parametrized macros): https://bugzilla.redhat.com/show_bug.cgi?id=495658
- Panu -
On 05/20/2009 03:23 AM, Panu Matilainen wrote:
Apologies for missing this when the recommendation of %global over %define in Fedora guidelines was being discussed, but better late than never...
https://fedoraproject.org/wiki/Packaging/Guidelines#.25global_preferred_over...
says "The two macro defining statements behave the same when they are a the top level of rpm's nesting level" but this is not correct:
The body of a %global macro is expanded at definition time, whereas the body of a %define is expanded only when used. For many uses it doesn't make any difference but identical they are not, even on top level - for example see the attached example spec:
$ rpmbuild -bp macroex.spec 2>/dev/null|grep ^case case1: first - second case2: second - %{xxx}
Another example of this difference (in case of parametrized macros): https://bugzilla.redhat.com/show_bug.cgi?id=495658
Hi Panu, How does this look? (Note, I haven't tested any of this code yet as I'm running out the door. I wrote it just from how I understand your message and bz#495658). Also note that I don't know what causes rpm to clear the %defines that have been defined. If you can fill that in that would be great. If it's too complex, we can figure out some way to rephrase around it.
""" %global and %define are both used to define macros inside rpm spec files. We generally prefer using %global over %define.
%define created macros when they are used in nested macro expansions (like in %{!?foo: ... } constructs theoretically only lasts until the end brace (local scope), while %global definitions have global scope. However, rpm currently doesn't clear the scope for the macros unless [Accurate information needed here]. So %define'd macros often last throughout a spec file. However, when they don't, it's often non-obvious why the spec file is failing as the failure is caused by something changing in another part of the spec file.
%global has another major difference from %define that can cause problems when you first write the macro. %global is evaluated at the time that it is written whereas %define is evaluated separately everytime it occurs in a spec file. As an example, if you do the following in a spec file::
<pre> %build
%global foo FOO %global bar %foo %define baz %foo echo %{bar} - %{baz}
%global foo FOOBAR echo %{bar} - %{baz}
You get this:
FOO - FOO FOO - FOOBAR </pre>
One place this becomes apparent is parameterized macros: <pre> %build %global print_arg echo "Hello %1" %print_arg World </pre> because the %1 is evaluated when print_arg is defined, this prints <code>Hello</code> rather than "Hello World".
Escaping the % fixes this usage:
<pre> %global print_arg echo "Hello %%1" </pre> """
-Toshio
2009/5/20 Toshio Kuratomi a.badger@gmail.com:
On 05/20/2009 03:23 AM, Panu Matilainen wrote:
Apologies for missing this when the recommendation of %global over %define in Fedora guidelines was being discussed, but better late than never...
https://fedoraproject.org/wiki/Packaging/Guidelines#.25global_preferred_over...
says "The two macro defining statements behave the same when they are a the top level of rpm's nesting level" but this is not correct:
The body of a %global macro is expanded at definition time, whereas the body of a %define is expanded only when used. For many uses it doesn't make any difference but identical they are not, even on top level - for example see the attached example spec:
$ rpmbuild -bp macroex.spec 2>/dev/null|grep ^case case1: first - second case2: second - %{xxx}
Another example of this difference (in case of parametrized macros): https://bugzilla.redhat.com/show_bug.cgi?id=495658
Hi Panu, How does this look? (Note, I haven't tested any of this code yet as I'm running out the door. I wrote it just from how I understand your message and bz#495658). Also note that I don't know what causes rpm to clear the %defines that have been defined. If you can fill that in that would be great. If it's too complex, we can figure out some way to rephrase around it.
""" %global and %define are both used to define macros inside rpm spec files. We generally prefer using %global over %define.
%define created macros when they are used in nested macro expansions (like in %{!?foo: ... } constructs theoretically only lasts until the end brace (local scope), while %global definitions have global scope. However, rpm currently doesn't clear the scope for the macros unless [Accurate information needed here]. So %define'd macros often last throughout a spec file. However, when they don't, it's often non-obvious why the spec file is failing as the failure is caused by something changing in another part of the spec file.
This is somewhat strange behavior to a packager who is not the most skilled developers. Granted RPM spec files are pretty much a programming language, how often do we see it with all these different scoping and evaluation rules? Even more so when we use more complex macros to make the job easier for the packager and hide these details?
%global has another major difference from %define that can cause problems when you first write the macro. %global is evaluated at the time that it is written whereas %define is evaluated separately everytime it occurs in a spec file. As an example, if you do the following in a spec file::
With my limited understanding of RPM internals, in order to maintain consistency, would we need perhaps another form of global? Just asking. What are the cons at looking at a '%macro' macro that will delay evaluation, unlike %global?
-Yaakov
On 05/20/2009 06:08 PM, Toshio Kuratomi wrote:
One place this becomes apparent is parameterized macros:
<pre> %build %global print_arg echo "Hello %1" %print_arg World </pre>
because the %1 is evaluated when print_arg is defined, this prints <code>Hello</code> rather than "Hello World".
nit: there would technically be a space after Hello, so <code>Hello </code> though that's probably not easy to see... Perhaps some tricks with punctuation could help.
On Wed, 20 May 2009, Toshio Kuratomi wrote:
On 05/20/2009 03:23 AM, Panu Matilainen wrote:
Apologies for missing this when the recommendation of %global over %define in Fedora guidelines was being discussed, but better late than never...
https://fedoraproject.org/wiki/Packaging/Guidelines#.25global_preferred_over...
says "The two macro defining statements behave the same when they are a the top level of rpm's nesting level" but this is not correct:
The body of a %global macro is expanded at definition time, whereas the body of a %define is expanded only when used. For many uses it doesn't make any difference but identical they are not, even on top level - for example see the attached example spec:
$ rpmbuild -bp macroex.spec 2>/dev/null|grep ^case case1: first - second case2: second - %{xxx}
Another example of this difference (in case of parametrized macros): https://bugzilla.redhat.com/show_bug.cgi?id=495658
Hi Panu, How does this look? (Note, I haven't tested any of this code yet as I'm running out the door. I wrote it just from how I understand your message and bz#495658). Also note that I don't know what causes rpm to clear the %defines that have been defined. If you can fill that in that would be great. If it's too complex, we can figure out some way to rephrase around it.
""" %global and %define are both used to define macros inside rpm spec files. We generally prefer using %global over %define.
%define created macros when they are used in nested macro expansions (like in %{!?foo: ... } constructs theoretically only lasts until the end brace (local scope), while %global definitions have global scope. However, rpm currently doesn't clear the scope for the macros unless [Accurate information needed here]. So %define'd macros often last throughout a spec file. However, when they don't, it's often non-obvious why the spec file is failing as the failure is caused by something changing in another part of the spec file.
Locally scoped macros get freed (well, popped) on exit from parametrized macros - think of local variables in a function. The conditional construct %{!?bar: %define bar defined} is the special case where the define ends up on non-global scope but doesn't get freed immediately as this is not a parametrized macro. Note "immediately": it will get freed eventually if a "call" to parametrized macro happens:
--- %prep %define myecho() echo %1 %2 %{!?bar: %define bar defined}
echo 1: %{bar} %{myecho 2: %{bar}} echo 3: %{bar} ---
gives:
1: defined 2: defined 3: %{bar}
but if you use "%{!?bar: %global bar defined}" you get what you expect. I'm not sure if explaining details of such quirks of rpm macro language really belongs to packaging guidelines, to put it simply:
Inside %{ } blocks you need to use %global to define global macros.
This is not entirely unlike python variable scoping: by default variables only exist in the scope (local or global) they are created, unless "global" statement is used to force glocal scope.
%global has another major difference from %define that can cause problems when you first write the macro. %global is evaluated at the time that it is written whereas %define is evaluated separately everytime it occurs in a spec file. As an example, if you do the following in a spec file::
[snip]
Again I doubt spelling out the crazy details is terribly useful, the rules are basically:
- Always create parametrized macros with %define. - Inside %{ } blocks you need to use %global to define global macros. - %define'd macro is evaluated at time of use, %global macro is evaluated at time of definition (otherwise it might have references to macros that have gone out of scope at time of use)
- Panu -
packaging@lists.fedoraproject.org