11

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?

davka
  • 13,974
  • 11
  • 61
  • 86

7 Answers7

20

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
Міша
  • 201
  • 2
  • 3
  • 1
    thanks Misha, fortunately this is off my hands now to a proper CM :) – davka Jan 22 '12 at 13:19
  • 1
    It would be very much appreciated if somebody would comment about from which version `%include` is fully supported. – Daniel Szalay Jul 16 '15 at 08:41
  • 1
    The earliest mention I can find of `%include` is in the [release notes for 4.8](http://rpm.org/wiki/Releases/4.8.0), and that implies a fix to a feature that already existed. The release notes for 4.4.x, 4.6 and 4.7 don't mention `%include` at all, implying the feature was introduced in 4.4.2 (July 2005) at the latest. As of 2018, I think it is safe to assume your version of RPM is *seriously* in need of upgrading if it does not support `%include`. – chepner May 21 '18 at 14:18
7

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.

m1tk4
  • 3,439
  • 1
  • 22
  • 27
  • thanks! `--define` is the second intuitive solution I felt should be there – davka Jun 05 '11 at 05:39
  • Thanks! `--define` is not documented in my version of rpmbuild (4.9.1.1) but it works. I looked for something like that for hours!!! – DavidGamba Jul 30 '13 at 21:02
  • 2
    recent rpm 4.12+ support load which loads macrofile, for example you can do something like this `%{?load:%{SOURCE1}}` see http://pkgs.fedoraproject.org/cgit/ruby.git/tree/ruby.spec?id=b9da2e689a47e432a4272b43c849a9a818965bbb#n92 – Muayyad Alsadi Mar 31 '15 at 14:36
5

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).

Bob Bell
  • 363
  • 2
  • 5
4

For the underlying issue, there maybe two additional solutions that are present in all rpm versions that I am aware of.

  1. Subpackages
  2. 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.

artless noise
  • 21,212
  • 6
  • 68
  • 105
3

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.

artless noise
  • 21,212
  • 6
  • 68
  • 105
  • 1
    This is a lot like [Міша](http://stackoverflow.com/users/1157384/) and [Digitalsky's answer](http://stackoverflow.com/questions/6136056/can-an-rpm-spec-file-include-other-files/7113577#7113577). I think it only works in newer `rpm` versions; so if you have a newer `rpm`, problem solved. – artless noise Jul 02 '13 at 20:57
3

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
digitalsky
  • 379
  • 4
  • 14
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.

Aaron D. Marasco
  • 6,506
  • 3
  • 26
  • 39