How to build source RPMS under your home directory as non-root

Most of the tips for building RPM as non-root says to rewrite ~/.rpmmacros to set %_topdir $HOME/rpmbuild.

Don't. You are locking yourself into single build directory, which you do not want when building more than one RPM package.

Setting %_topdir should be done in other ways.


Directory preparation

(as in other tips)
for d in RPMS/i686 RPMS/i486 RPMS/i586 RPMS/noarch RPMS/i386 BUILD SPECS SRPMS SOURCES; do mkdir -p $d; done

CentOS 6, CentOS 7

Pass option like rpmbuild -D "_topdir `pwd`" explicitly. This will make %_topdir change.

Expanding the .src.rpm

To expand the .src.rpm in the build directory, pass options to rpm :

rpm -ivh -D "_topdir `pwd`" gzip-1.5-8.el7.src.rpm
You don't need root priviledge for installing the source RPM under your directory.

Invoking rpmbuild

If you are using CentOS, it tends to add .el7.centos as %{dist} macro, resulting in package names like gzip-1.5-8.el7.centos.i586.rpm . If you don't like this, add -D "dist .el7" to the options.

Passing options every time will quickly be tedious, so you should write a Makefile, like

gzip:
	rpmbuild --target=i586 \
	-D "_topdir `pwd`" \
	-D "dist .el7" \
	-bb SPECS/$@.spec


CentOS 5

On CentOS 5 things get tricky. -D "_topdir `pwd`" won't work as expected; you have to pass it via rpmmacros file.

Prepare ./rpmmacros

%_topdir	$HOME/rpmbuild.gzip
%dist	.el5
%el5	1

Prepare ./rpmrc

macrofiles:	/usr/lib/rpm/macros:/usr/lib/rpm/redhat/macros:/usr/lib/rpm/%{_target}/macros:/etc/rpm/macros.*:/etc/rpm/macros:/etc/rpm/%{_target}/macros:/home/kabe/rpmbuld.gzip/rpmmacros:~/.rpmmacros
(this should be on single line)

Invoke rpm and rpmbuild

rcfile=""
for d in /usr/lib/rpm/rpmrc /usr/lib/rpm/redhat/rpmrc `pwd`/rpmrc ~/.rpmrc; do
	test -r "$d" && rcfile="${rcfile}${rcfile:+:}$d"
done
rpm -ivh --rcfile "$rcfile" gzip-1.3.5-13.el5.centos.src.rpm
rpmbuild --rcfile "$rcfile" -bb SPECS/gzip.spec

The reason for checking existence of $rcfile in the for loop, is that rpmbuild will fail silently when given nonexistent file as --rcfile list.

This will quickly grow burdensome, so you should write a Makefile.

Shellscript for preparing RPM build directory

If you're preparing multiple RPM build directories, you would like to use a shellscript, as below. This script prepares RPM build directory under current directory, and sets up ./rpm ./rpmbuild commands which you will use instead of the standard ones.

#!/bin/sh
# mkrpmdir.c5

### mkdir
for d in RPMS/i686 RPMS/i486 RPMS/i586 RPMS/noarch RPMS/i386 BUILD SPECS SRPMS SOURCES; do mkdir -p $d; done

### ./rpmbin
cat > ./rpmbin << 'EOF'
#!/bin/sh

D=${0%/*}
test x"$D" = x"." && D="`pwd`"
# explicit --rcfile needs existence??
rcfile=""
for d in /usr/lib/rpm/rpmrc /usr/lib/rpm/redhat/rpmrc ${D}/rpmrc ~/.rpmrc; do
	test -r "$d" && rcfile="${rcfile}${rcfile:+:}$d"
done
exec ${0##*/} --rcfile "$rcfile" \
	--macros=/usr/lib/rpm/macros:/usr/lib/rpm/redhat/macros:/usr/lib/rpm/%{_target}/macros:/etc/rpm/macros.*:/etc/rpm/macros:/etc/rpm/%{_target}/macros:`pwd`/rpmmacros:~/.rpmmacros \
	"$@"
EOF
chmod +x ./rpmbin

### symlink ./rpmbuild, ./rpm -> rpmbin
for i in rpmbuild rpm; do rm -f ./$i; ln -s rpmbin ./$i; done

### ./rpmrc
cat > ./rpmrc << EOF
# rpmrc
macrofiles:	/usr/lib/rpm/macros:/usr/lib/rpm/redhat/macros:/usr/lib/rpm/%{_target}/macros:/etc/rpm/macros.*:/etc/rpm/macros:/etc/rpm/%{_target}/macros:`pwd`/rpmmacros:~/.rpmmacros
EOF

### ./rpmmacros
cat > ./rpmmacros << EOF
# rpmmacros
%_topdir	`pwd`
##RHEL5: doesn't define dist,el5
%dist	.el5
%el5 1
EOF

Expanding the .src.rpm

To expand the .src.rpm, you would use ./rpm in the build directory:

./rpm -ivh gzip-1.3.5-13.el5.centos.src.rpm

Invoking rpmbuild

./rpmbuild --target=i586 -bb SPECS/gzip.spec

kabe.sra-tohoku.co.jp