Can I use rpm to expand the macros in a specfile?
Asked Answered
D

6

24

The concrete example being I have lots of specfiles with Source0: or other Source lines containing macros. How can I have these macros expanded without actually starting a build on the specfile or writing my own parser?

Doublehung answered 3/9, 2010 at 9:56 Comment(2)
Did you ever get a better answer to this? I would like to expand all the macros in a spec file to show approximately how the script will look before it get's parsed in the next step.Stitch
You'd think that rpmspec -E would do what you want, but it doesn't seem to eval the macro in the specfile context. Insane.Sarene
E
-4

You could grep to get the Source lines, sed to extract the string containing the macro and then rpm --eval 'string' to evaluate it. Note that this will only expand the global macros, not the ones defined in this spec.

To expand those as well you'd probably need to grep for them and feed them to rpm as your custom macros file.

Ernest answered 12/9, 2010 at 2:11 Comment(2)
Usually the urls contain at leas %{version} which does not get expanded (rpm 4.10.1)Cowans
This is actively wrong: wiki.merproject.org/wiki/Packaging_guidelines/ParsingSpecFilesSarene
C
44

Since rpm 4.9 you can use:

rpmspec -P <spec_file>

This will print out expanded spec file on stdout

Coldblooded answered 26/10, 2011 at 10:19 Comment(3)
This would be awesome, if only it would be available in current enterprise distributions (RHEL/CentOS).Nataline
rpm 4.10.1- this fails and requires the sources to be downloaded ahead, which renders it pretty useless. Can anyone confirm that (rule out a borked setup).Cowans
To clarify @Guss's comment, rpmspec is available on RHEL/CentOS 7 but not on RHEL/CentOS 6 or earlier.Tsosie
M
12

If its only the source lines you need parsed, spectool will do that for you. It's part of Fedora's rpmdevtools.

$ spectool ./mg.spec 
Source0: http://homepage.boetes.org/software/mg/mg-20110120.tar.gz
$ 

Here's its help screen

Usage: spectool [<options>] <specfile>
Options:
operating mode:
-l, --lf, --list-files        lists the expanded sources/patches (default)
-g, --gf, --get-files         gets the sources/patches that are listed with
                              a URL
-h, --help                    display this help screen

files on which to operate:
-A, --all                     all files, sources and patches (default)
-S, --sources                 all sources
-P, --patches                 all patches
-s, --source x[,y[,...]]      specified sources
-p, --patch a[,b[,...]]       specified patches

misc:
-d, --define 'macro value'    defines RPM macro 'macro' to be 'value'
-C, --directory dir           download into specified directory (default '.')
-R, --sourcedir               download into rpm's %{_sourcedir}
-n, --dryrun, --dry-run       don't download anything, just show what would be
                              done
-D, --debug                   output debug info, don't clean up when done
Marchpast answered 18/4, 2011 at 1:14 Comment(2)
This is the recommended option to extract and evaluate source files for most RPM based distribution.Nataline
Indeed this is a better way to handle SourceX lines then my solution (which is more generic on the other hand)Coldblooded
N
2

If you look at the /usr/bin/spectool script in rpmdevtools that @mmckinst talks about, you'll see it's just an elaborate hack. It creates a tmp spec file that essentially does what script below does. This is what we're using to expand the spec file and then grep for the parts of the file we need. In our case, we wanted more than the sources and patches.

Here's a sample bash script that simulates this behavior. It will expand all macros up through the %prep section.

#!/bin/bash
spec_file="$1" # pass in the path to the spec file as the first argument
tmp_spec="/tmp/eval-$$.spec"
cat "$spec_file" | sed '/^%prep/,$d' > "$tmp_spec"
echo '%prep' >> "$tmp_spec"
echo 'cat<<__EOF__' >> $tmp_spec
cat "$spec_file" | sed '/^%prep/,$d' >> "$tmp_spec"
echo '__EOF__' >> "$tmp_spec"
rpmbuild -bp "$tmp_spec" 2>/dev/null
rm -f "$tmp_spec"  
Nisen answered 23/6, 2012 at 2:35 Comment(2)
This is indeed a useful workaround when spectool is not available on your machine.Dickenson
I tried the script without success (it returned an exit code of 0 without printing anything); I think it's interesting but the "--nodeps" option should be added to rpmbuild (otherwise an unsatisfied BuildRequires will prevent rpmbuild from working), and an explicit message and exit code should be propagated in the event rpmbuild fails. I'm proposing an edit to the post with such changes.Daren
S
1

Expand macros in scripts

If you're interested in what the scripts in your RPM look like after macro expansion, you can just build the RPM and then get RPM to extract the scripts:

rpmbuild -bi my-package.spec
rpm -qp --scripts my-package.rpm

This works because RPM expands the macros at build-time.

Spanishamerican answered 19/9, 2011 at 13:41 Comment(0)
G
0

We wrote that parser in Python :)

https://github.com/packit/specfile/

$ python3 -c 'import specfile; print(specfile.Specfile("units.spec").expand("%version"))'
2.21
Galliwasp answered 19/4, 2023 at 14:59 Comment(0)
E
-4

You could grep to get the Source lines, sed to extract the string containing the macro and then rpm --eval 'string' to evaluate it. Note that this will only expand the global macros, not the ones defined in this spec.

To expand those as well you'd probably need to grep for them and feed them to rpm as your custom macros file.

Ernest answered 12/9, 2010 at 2:11 Comment(2)
Usually the urls contain at leas %{version} which does not get expanded (rpm 4.10.1)Cowans
This is actively wrong: wiki.merproject.org/wiki/Packaging_guidelines/ParsingSpecFilesSarene

© 2022 - 2024 — McMap. All rights reserved.