Discussion:
%{expand:...} documentation
Jos Vos
2007-08-27 18:26:47 UTC
Permalink
Hi,

Where can I find documentation about how %{expand:...} exactly is
defined and when it is useful?

When browsing through spec files, I have the impression that it is
unnecessarily used in a lot of cases.

Thanks,

--
-- Jos Vos <***@xos.nl>
-- X/OS Experts in Open Systems BV | Phone: +31 20 6938364
-- Amsterdam, The Netherlands | Fax: +31 20 6948204
James Olin Oden
2007-08-27 18:36:20 UTC
Permalink
Post by Jos Vos
Hi,
Where can I find documentation about how %{expand:...} exactly is
defined and when it is useful?
When browsing through spec files, I have the impression that it is
unnecessarily used in a lot of cases.
I don't know of any docs. Where I have found it usefull/necessary, is
when I use the %() operator to run an external command that will
generate output that contains macros and then I want to have those
macros expanded.

Cheers..james
Jos Vos
2007-08-27 18:50:41 UTC
Permalink
Post by James Olin Oden
I don't know of any docs. Where I have found it usefull/necessary, is
when I use the %() operator to run an external command that will
generate output that contains macros and then I want to have those
macros expanded.
Yes, I think the use of "kmodtool" is the best example of this.

But seeing all the "wrong" examples, I started doubting about
the proper use ;-).
--
-- Jos Vos <***@xos.nl>
-- X/OS Experts in Open Systems BV | Phone: +31 20 6938364
-- Amsterdam, The Netherlands | Fax: +31 20 6948204
Jeff Johnson
2007-08-27 18:35:14 UTC
Permalink
Post by Jos Vos
Hi,
Where can I find documentation about how %{expand:...} exactly is
defined and when it is useful?
The macro primitive %{expand:...} is like eval in shell.

All it does is continue a macro expansion from the beginning, not
the end, of whatever was justr expanded.

So if, say, you wanted to define
%define foo bing
%define %{foo} bang
to have the result be
%bing bang
then this construct accomplishes
%{expand:%%define %{foo} bang}

The 1st pass substitutes "bing" for %{foo}, the second pass
accomplishes the define.
Post by Jos Vos
When browsing through spec files, I have the impression that it is
unnecessarily used in a lot of cases.
Likely.

73 de Jeff
Jos Vos
2007-08-27 18:48:14 UTC
Permalink
Post by Jeff Johnson
The macro primitive %{expand:...} is like eval in shell.
That's what I thought...
Post by Jeff Johnson
Post by Jos Vos
When browsing through spec files, I have the impression that it is
unnecessarily used in a lot of cases.
Likely.
Just some excerpts from RHEL5 spec files (some are even used frequently):

%{expand: %%define pyver %(python -c 'import sys;print(sys.version[0:3])')}

%{expand: %%define build_with_freetype %{?_with_freetype:1}%{!?_with_freetype:0}}

I think this is an example of proper use (as there is a recursion), right?

%{expand: %%define _includedir %{_includedir}/%{name}}
--
-- Jos Vos <***@xos.nl>
-- X/OS Experts in Open Systems BV | Phone: +31 20 6938364
-- Amsterdam, The Netherlands | Fax: +31 20 6948204
Michael Jennings
2007-08-27 18:55:25 UTC
Permalink
On Monday, 27 August 2007, at 20:48:14 (+0200),
Post by Jos Vos
%{expand: %%define pyver %(python -c 'import sys;print(sys.version[0:3])')}
This is valid and proper usage, IMHO, because it prevents the subshell
execution (i.e., %(...) expansion) to be invoked every time %{pyver}
is employed in the spec file. I do this too.
Post by Jos Vos
%{expand: %%define build_with_freetype %{?_with_freetype:1}%{!?_with_freetype:0}}
This seems unnecessary, particularly since we already have %bcond_with
and %bcond_without. But I wouldn't call it gratuitous.
Post by Jos Vos
I think this is an example of proper use (as there is a recursion), right?
%{expand: %%define _includedir %{_includedir}/%{name}}
I believe so, yes.

Michael
--
Michael Jennings (a.k.a. KainX) http://www.kainx.org/ <***@kainx.org>
Linux Server/Cluster Admin, LBL.gov Author, Eterm (www.eterm.org)
-----------------------------------------------------------------------
"I believe God's grace is so incredible that He saves those who so
much as grunt in His general direction, as long as it is from their
heart." -- Rick Durrance, Youth Pastor, Wilmore UMC (paraphrased)
Jos Vos
2007-08-27 19:15:13 UTC
Permalink
Post by Michael Jennings
This is valid and proper usage, IMHO, because it prevents the subshell
execution (i.e., %(...) expansion) to be invoked every time %{pyver}
is employed in the spec file. I do this too.
OK, thank you (and Jeff) for pointing this out, I didn't think of that.
Not that calling python one or two times more worries me a lot ;-),
but it's good to be aware of it.
--
-- Jos Vos <***@xos.nl>
-- X/OS Experts in Open Systems BV | Phone: +31 20 6938364
-- Amsterdam, The Netherlands | Fax: +31 20 6948204
Jeff Johnson
2007-08-27 18:59:08 UTC
Permalink
Post by Jos Vos
Post by Jeff Johnson
The macro primitive %{expand:...} is like eval in shell.
That's what I thought...
Post by Jeff Johnson
Post by Jos Vos
When browsing through spec files, I have the impression that it is
unnecessarily used in a lot of cases.
Likely.
Just some excerpts from RHEL5 spec files (some are even used
%{expand: %%define pyver %(python -c 'import
sys;print(sys.version[0:3])')}
%{expand: %%define build_with_freetype %{?_with_freetype:1}%{!?
_with_freetype:0}}
Ah, this is an optimization. The first pass of the %{expand: ...}
invokes a helper
command, the 2nd pass does the define, so that the helper is not
lazily executed
repeatedly.
Post by Jos Vos
I think this is an example of proper use (as there is a recursion), right?
%{expand: %%define _includedir %{_includedir}/%{name}}
In this case, it really doesn't matter how often "%{_includedir}/%
{name}" is
expanded. Well, it _MAY_matter if the value of %{name} is changing,
but I doubt you can really solve the problem of, say, %{name} possibly
changing
meaningfully by using %{expand:...}.

Invoking a helper repeatedly is what was being avoided by
using %{expand:...} in yr first example.

73 de Jeff
Jos Vos
2007-08-27 19:08:46 UTC
Permalink
Post by Jeff Johnson
Post by Jos Vos
I think this is an example of proper use (as there is a recursion), right?
%{expand: %%define _includedir %{_includedir}/%{name}}
In this case, it really doesn't matter how often "%{_includedir}/%
{name}" is
expanded. Well, it _MAY_matter if the value of %{name} is changing,
but I doubt you can really solve the problem of, say, %{name} possibly
changing
meaningfully by using %{expand:...}.
Uhh... now I'm confused. I tried:

%define foo %{foo}X

and using that (with %{foo} defined on the command line) results in:

error: Recursion depth(17) greater than max(16)
15< (empty)
14< (empty)
13< (empty)
12< (empty)
11< (empty)
10< (empty)
9< (empty)
8< (empty)
7< (empty)
6< (empty)
5< (empty)
4< (empty)
3< (empty)
2< (empty)
1< (empty)
0< echo foo:

While it works with

%{expand: %%define foo %{foo}X}

as long as %{foo} was defined before.
--
-- Jos Vos <***@xos.nl>
-- X/OS Experts in Open Systems BV | Phone: +31 20 6938364
-- Amsterdam, The Netherlands | Fax: +31 20 6948204
Jeff Johnson
2007-08-27 19:39:55 UTC
Permalink
Post by Jeff Johnson
Post by Jos Vos
I think this is an example of proper use (as there is a recursion), right?
%{expand: %%define _includedir %{_includedir}/%{name}}
In this case, it really doesn't matter how often "%{_includedir}/%
{name}" is
expanded. Well, it _MAY_matter if the value of %{name} is changing,
but I doubt you can really solve the problem of, say, %{name}
possibly
changing
meaningfully by using %{expand:...}.
No I missed the recursive expansion. Yes, %{expand:...} needs to be
used,
or the recursion needs to be avoided somehow.

73 de Jeff

Loading...