Is there a kind of "include" directive in RPM spec? I couldn't find an answer by googling.
Motivation: I have a RPM spec template which the build process modifies with the version, revision and other build-specific data. This is done by sed
currently. I think it would be cleaner if the spec would #include
a build-specific definitions file, which would be generated by the build process, so I don't need to search and replace in the spec.
If there is no include
, is there an idiomatic way to do this (quite common, I believe) task?
RPM does not support includes.
I have solved similar problems with either m4 macro processor or by just concatenating parts of spec (when the "include" was at the beginning).
If you only need to pass a few variables at build time, and not include several lines from another file, you can run
rpmbuild --define 'myvar SOMEVALUE' -bb myspec.spec
and you can use %myvar in the spec.
Sufficiently recent versions of rpmbuild certainly do support %include:
%include common.inc
Unfortunately, they aren't very smart about it -- there is no known set of directories, in which it will look for the requested files, for example. But it is there and variables are expanded, for example:
%include %{_topdir}/Common/common.inc
I faced this same issue recently. I wanted to define multiple sub-packages that were similar, but each varied just slightly (they were language-specific RPMs). I didn't want to repeat the same boiler-plate stuff for each sub-package.
Here's a generic version of what I did:
%define foo_spec() %{expand:%(cat '%{myloc}/main-foo.spec')}
%{foo_spec bar}
%{foo_spec baz}
%{foo_spec qux}
The use of %{expand}
ensures that %(cat)
is only executed a single time, when the macro is defined. The content of the main-foo.spec file is then three times, and each time %1
in the main-foo.spec file expands to each of bar
, baz
and qux
, in turn, allowing me to treat it as a template. You could easily expand this to more than one parameter, if you have the need (I did not).
For the underlying issue, there maybe two additional solutions that are present in all rpm versions that I am aware of.
- Subpackages
macro
and rpmrc
files.
Subpackages
Another alternative (and perhaps the "RPM way") is to use sub-packages. Maximum RPM also has information and examples of subpackages.
I think the question is trying to structure something like,
- two spec files; say rpm_debug.spec and rpm_production.spec
- both use
%include common.spec
debug and production could also be client and server, etc. For the examples of redefining a variable, each subpackage can have it's own list of variables.
Limitations
The main advantage of subpackages is that only one build takes place; This may also be a disadvantage. The debug and production example may highlight this. That can be worked around using strip
to create variants or compiling twice with different output; perhaps using VPATH
with Gnu Make). Having to compile large packages and then only have simple variations, like with/without developer info, like headers
, static libraries, etc. can make you appreciate this approach.
Macros and Rpmrc
Subpackages don't solve the problem of structural defines that you wish for an entire rootfs hierarchy, or larger collection of RPMs. We have rpmbuild --showrc
for this. You can have a large amount of variables and macros defined by altering rpmrc
and macros
when you run rpm
and rpmbuild
. From the man
page,
rpmrc Configuration
/usr/lib/rpm/rpmrc
/usr/lib/rpm/redhat/rpmrc
/etc/rpmrc
~/.rpmrc
Macro Configuration
/usr/lib/rpm/macros
/usr/lib/rpm/redhat/macros
/etc/rpm/macros
~/.rpmmacros
I think these two features can solve all the problems that %include
can. However, %include
is a familiar concept and was probably added to make rpm more full-featured and developer friendly.
You can include the *.inc
files from the SOURCES directory (%_sourcedir
):
Source1: common.inc
%include %{SOURCE1}
In this way they will go automatically into SRPMS.
Which version are you talking about? I currently have %include filename.txt in my spec file and it seems to work just like the C #include directive.
> rpmbuild --version
RPM version 4.8.1
I've used scripts (name your favorite) to take a template and create the spec file from that. Also, the %files
tag can import a file that is created by another process, e.g. Python's bdist-rpm
.