Tuesday, March 29, 2016

Creating noarch RPM with minimal spec file

Suppose you have some files that should be packaged and distributed as a small noarch RPM, but you do not want to depend on ~/.rpmmacros or rpm build tree somewhere. Idea is that one can clone the repo with your files, run something like make and he will get the ready runme-1.1-noarch.rpm that contains /opt/runme, without additional actions.
README.txt
runme.sh
runscripts.d/
runscripts.d/001_script.sh
runscripts.d/002_another_script.sh
 
README.txt and runme.sh are the only files that exist in the top directory; contents of runscripts.d changes very often, and you don't want to carefully mention each file. To satisfy all our requirements, we will do the following:

1. RPM buildtree will be created on the fly in the current dir in the folder named _build

2. The only .rpmmacros directive that we really need (%_topdir) can be specified as an argument for rpmbuild: rpmbuild --define="%_topdir `pwd`/_build"

3. We will also override %_sourcedir macros to avoid copying sources to _build/SOURCE dir

4. %prep stage can be skipped, everything will be extracted directly to _build/BUILDROOT

5. We have to list all files in runscripts.d in the Source tag in spec, so we just archive them

6. We do set of actions and provide complex arguments to rpmbuild, Makefile is an obvious way to do all the thing.

7. %define __jar_repack %{nil} is a useful trick to avoid searching and repacking jar files. In our case, it just a small speedup, but when you are repacking something like apache-tomcat, it saves a lot of time and does not touch original files.
Do not forget to install rpm-build package that contains /usr/bin/rpmbuild and friends: yum install rpm-build. Firstly, create the Makefile for building the RPM.
all: clean
        mkdir -p _build && \
        tar czf runscripts.tgz runscripts.d && \
        rpmbuild --define="%_topdir `pwd`/_build"  --define "%_sourcedir `pwd`" -bb runme.spec && \
        cp _build/RPMS/noarch/*rpm .

clean:
        rm -rf _build runscripts.tgz *rpm
Now, the specfile for our noarch RPM. Pre- and post-install scriptlets are omitted:
%define __jar_repack %{nil}
Name: runme
Version: 1
Release: 1
Summary: Example set of files
BuildArch: noarch
License: GPL
URL: http://plastilinux.blogspot.com
Source0: runscripts.tgz
Source1: README.txt
Source2: runme.sh

%description
Example noarch rpm

%install
mkdir -p %{buildroot}/opt/runme
tar -C %{buildroot}/opt/runme -xf %SOURCE0
install -m 644 %SOURCE1 %{buildroot}/opt/runme
install -m 755 %SOURCE2 %{buildroot}/opt/runme

%files
%defattr(-, root, root)
%dir /opt/runme
%dir /opt/runme/runscripts.d
/opt/runme/README.txt
%attr(755,root,root) /opt/runme/runme.sh
%attr(755,root,root) /opt/runme/runscripts.d/*

Get all the files from the repo, run "make" and get the ready rpm in two seconds.

1 comment:

  1. Hi,

    I found the post very useful and easy to follow. Maybe it was only my config issue but initially I got "Group field must be present in package" error. I need to add in the spec file the "Group:" info as below(but could be any name)

    License: GPL
    Group: System Environment/Base
    URL: http://plastilinux.blogspot.com

    ReplyDelete