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?
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.
%{version}
which does not get expanded (rpm 4.10.1) –
Cowans Since rpm 4.9 you can use:
rpmspec -P <spec_file>
This will print out expanded spec file on stdout
rpmspec
is available on RHEL/CentOS 7 but not on RHEL/CentOS 6 or earlier. –
Tsosie 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
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"
spectool
is not available on your machine. –
Dickenson 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.
We wrote that parser in Python :)
https://github.com/packit/specfile/
$ python3 -c 'import specfile; print(specfile.Specfile("units.spec").expand("%version"))'
2.21
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.
%{version}
which does not get expanded (rpm 4.10.1) –
Cowans © 2022 - 2024 — McMap. All rights reserved.
rpmspec -E
would do what you want, but it doesn't seem to eval the macro in the specfile context. Insane. – Sarene