* rpmbuildを使ってrpmを自作してみる

自作のプログラムをrpm化する場合のtips。確認はCentOS6.3。

1. rpmbuildをインストール

rpmbuildがない場合はインストールしておく。

# yum -y install rpm-build

事前準備

$ echo "%_topdir $HOME/rpmbuild" >~/.rpmmacros
$ mkdir -p ~/rpmbuild/{BUILD,RPMS,SOURCES,SPECS,SRPMS}

SPECファイルを書く

helloworld.specという名前でファイルを作成した。

Name: helloworld
Summary: Helloworld is a sample package for an exercise building RPM package.
Version: 0.1
Release: 0.1
License: GPL
Group:   Development/Tools
Source: %name-%version.tar.gz
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root
BuildRequires: make gcc gcc-c++

%description
%{summary}

%prep
%setup -q -n %{name}-%{version}

%build
make

%install
install -d $RPM_BUILD_ROOT/usr/local/bin
install -d $RPM_BUILD_ROOT/usr/local/etc
install -s helloworld $RPM_BUILD_ROOT/usr/local/bin
echo "This is test for rpm-build" > $RPM_BUILD_ROOT/usr/local/etc/helloworld.conf

%clean
[ "$RPM_BUILD_ROOT" != "/" ] && rm -rf $RPM_BUILD_ROOT

%files
%defattr(-,root,root)
/usr/local/bin/helloworld
%config /usr/local/etc/helloworld.conf

%changelog
* Sun Nov 24 2013 kohchi kohchi@example.com
- This is the first release
- This is test
  • Summaryは一行で。
  • %prepの%setupの-nはデフォルトも%{name}-%{version}とのこと。tarballをBUILDに展開する場合にこの名前を使うらしい。
  • $RPM_BUILD_ROOTは%{buildroot}とのことだが普通このように書くらしい。
  • %installで「仮想ルート」にインストールする。なお、ここと%filesを1:1で一致させておくこと。つまり実際のインストール時に仮想ルートのファイルを%filesのパスにコピーするようなイメージになっているのかも。
  • %cleanは不安なので念のため"/"をチェック。
  • %filesの%defattrはデフォルトの属性指定。各ファイルに指定したい場合はパスの前に%attrを書く。
  • %filesの%configはすでのファイルがある場合はそれを*.rpmsaveにリネームしてからコピーする。そのまま残したい、つまり、ファイルがあり上書きしたくない場合は%config(noreplace)とするらしい。
  • %changelogは例のとおり最初の行(*)に日付、作成者、メールアドレスを書いてそれ以降の行(-)にメッセージを書くようなフォーマットで。

テスト用ファイル

バイナリリリースであればバイナリをtarballにしたものを用意する。今回はテストのCプログラムを用意。
Makefileではあえてコンパイルしかしない。というのは、Makefile中にinstallセクションを書く場合は外部から今回の「仮想ルート」配下にインストールさせるようにしておく必要がありそうなため(make install INSTALL=$RPM_BUILD_ROOT のような感じ)。

#
# helloworld/Makefile
#
PROG=helloworld
OBJS=helloworld.o

all: $(PROG)

$(PROG) : $(OBJS)
	cc -o $@ $(OBJS)

clean:
	@rm -f a.out *.o $(PROG)
/* helloworld/helloworld.c */
#include <stdio.h>

int main(void) {
	fprintf(stdout, "Hello World!\n");
	return 0;
}
$

rpm作成

いよいよrpm作成。必要なファイルをtarballにまとめてSOURCES配下に置く。tarballの中身は%setupで指定したディレクトリ名内に配置し、tarballのファイル名自体はSource:で指定した名前にする。
その後、rpmbuildを実行する。-bbだとバイナリのみのRPMの作成。-bsだとSRPMのみ。-baだとRPM/SRPM両方とのこと。

$ tar cf - ./helloworld-0.1/ | gzip >~/rpmbuild/SOURCES/helloworld-0.1.tar.gz 
$ zcat ~/rpmbuild/SOURCES/helloworld-0.1.tar.gz | tar tvf -
drwxrwxr-x kohchi/kohchi     0 2013-11-24 11:02 ./helloworld-0.1/
-rw-rw-r-- kohchi/kohchi   145 2013-11-24 11:02 ./helloworld-0.1/Makefile
-rw-rw-r-- kohchi/kohchi   116 2013-11-24 11:02 ./helloworld-0.1/helloworld.c
$ rpmbuild -bb helloworld.spec
実行中(%prep): /bin/sh -e /var/tmp/rpm-tmp.XrkPut
+ umask 022
+ cd /home/kohchi/rpmbuild/BUILD
+ LANG=C
+ export LANG
+ unset DISPLAY
+ cd /home/kohchi/rpmbuild/BUILD
+ rm -rf helloworld-0.1
+ /bin/tar -xf -
+ /usr/bin/gzip -dc /home/kohchi/rpmbuild/SOURCES/helloworld-0.1.tar.gz
+ STATUS=0
+ '[' 0 -ne 0 ']'
+ cd helloworld-0.1
+ /bin/chmod -Rf a+rX,u+w,g-w,o-w .
+ exit 0
実行中(%build): /bin/sh -e /var/tmp/rpm-tmp.HKkixA
+ umask 022
+ cd /home/kohchi/rpmbuild/BUILD
+ cd helloworld-0.1
+ LANG=C
+ export LANG
+ unset DISPLAY
+ make
cc    -c -o helloworld.o helloworld.c
cc -o helloworld helloworld.o
+ exit 0
実行中(%install): /bin/sh -e /var/tmp/rpm-tmp.4TQWEH
+ umask 022
+ cd /home/kohchi/rpmbuild/BUILD
+ '[' /home/kohchi/rpmbuild/BUILDROOT/helloworld-0.1-0.1.x86_64 '!=' / ']'
+ rm -rf /home/kohchi/rpmbuild/BUILDROOT/helloworld-0.1-0.1.x86_64
++ dirname /home/kohchi/rpmbuild/BUILDROOT/helloworld-0.1-0.1.x86_64
+ mkdir -p /home/kohchi/rpmbuild/BUILDROOT
+ mkdir /home/kohchi/rpmbuild/BUILDROOT/helloworld-0.1-0.1.x86_64
+ cd helloworld-0.1
+ LANG=C
+ export LANG
+ unset DISPLAY
+ install -d /home/kohchi/rpmbuild/BUILDROOT/helloworld-0.1-0.1.x86_64/usr/local/bin
+ install -d /home/kohchi/rpmbuild/BUILDROOT/helloworld-0.1-0.1.x86_64/usr/local/etc
+ install -s helloworld /home/kohchi/rpmbuild/BUILDROOT/helloworld-0.1-0.1.x86_64/usr/local/bin
+ echo 'This is test for rpm-build'
+ /usr/lib/rpm/find-debuginfo.sh --strict-build-id /home/kohchi/rpmbuild/BUILD/helloworld-0.1
+ /usr/lib/rpm/check-buildroot
+ /usr/lib/rpm/redhat/brp-compress
+ /usr/lib/rpm/redhat/brp-strip-static-archive /usr/bin/strip
+ /usr/lib/rpm/redhat/brp-strip-comment-note /usr/bin/strip /usr/bin/objdump
+ /usr/lib/rpm/brp-python-bytecompile
+ /usr/lib/rpm/redhat/brp-python-hardlink
+ /usr/lib/rpm/redhat/brp-java-repack-jars
Processing files: helloworld-0.1-0.1.x86_64
Provides: config(helloworld) = 0.1-0.1
Requires(rpmlib): rpmlib(CompressedFileNames) <= 3.0.4-1 rpmlib(FileDigests) <= 4.6.0-1 rpmlib(PayloadFilesHavePrefix) <= 4.0-1
Requires: libc.so.6()(64bit) libc.so.6(GLIBC_2.2.5)(64bit) rtld(GNU_HASH)
Processing files: helloworld-debuginfo-0.1-0.1.x86_64
伸張ファイルの検査中: /usr/lib/rpm/check-files /home/kohchi/rpmbuild/BUILDROOT/helloworld-0.1-0.1.x86_64
書き込み完了: /home/kohchi/rpmbuild/RPMS/x86_64/helloworld-0.1-0.1.x86_64.rpm
書き込み完了: /home/kohchi/rpmbuild/RPMS/x86_64/helloworld-debuginfo-0.1-0.1.x86_64.rpm
実行中(%clean): /bin/sh -e /var/tmp/rpm-tmp.fvY994
+ umask 022
+ cd /home/kohchi/rpmbuild/BUILD
+ cd helloworld-0.1
+ '[' /home/kohchi/rpmbuild/BUILDROOT/helloworld-0.1-0.1.x86_64 '!=' / ']'
+ rm -rf /home/kohchi/rpmbuild/BUILDROOT/helloworld-0.1-0.1.x86_64
+ exit 0
$ ls -alFR rpmbuild/RPMS
rpmbuild/RPMS:
合計 12
drwxrwxr-x 3 kohchi kohchi 4096 1124 11:25 2013 ./
drwxrwxr-x 8 kohchi kohchi 4096 1124 11:13 2013 ../
drwxr-xr-x 2 kohchi kohchi 4096 1124 11:25 2013 x86_64/

rpmbuild/RPMS/x86_64:
合計 16
drwxr-xr-x 2 kohchi kohchi 4096 1124 11:25 2013 ./
drwxrwxr-x 3 kohchi kohchi 4096 1124 11:25 2013 ../
-rw-rw-r-- 1 kohchi kohchi 4076 1124 11:25 2013 helloworld-0.1-0.1.x86_64.rpm
-rw-rw-r-- 1 kohchi kohchi 1716 1124 11:25 2013 helloworld-debuginfo-0.1-0.1.x86_64.rpm

なんだかできているぞ。

インストールの確認

できたRPMでインストールしてみる。

# rpm -Uvh rpmbuild/RPMS/x86_64/helloworld-0.1-0.1.x86_64.rpm 
準備中...                ########################################### [100%]
   1:helloworld             ########################################### [100%]
# exit

$ ls -alF /usr/local/bin/
合計 20
drwxr-xr-x.  2 root root 4096 1124 11:32 2013 ./
drwxr-xr-x. 12 root root 4096  217 20:19 2013 ../
-rwxr-xr-x   1 root root 4232 1124 11:25 2013 helloworld*
-rwxr-xr-x.  1 root root 1253  217 15:08 2013 pqxx-config*
$ ls -alF /usr/local/etc
合計 12
drwxr-xr-x.  2 root root 4096 1124 11:32 2013 ./
drwxr-xr-x. 12 root root 4096  217 20:19 2013 ../
-rw-r--r--   1 root root   27 1124 11:25 2013 helloworld.conf
$ /usr/local/bin/helloworld
Hello World!
$ cat /usr/local/etc/helloworld.conf 
This is test for rpm-build
$ rpm -qi --changelog helloworld
Name        : helloworld                   Relocations: (not relocatable)
Version     : 0.1                               Vendor: (none)
Release     : 0.1                           Build Date: 20131124112515秒
Install Date: 20131124113242秒      Build Host: localhost
Group       : Development/Tools             Source RPM: helloworld-0.1-0.1.src.rpm
Size        : 4259                             License: GPL
Signature   : (none)
Summary     : Helloworld is a sample package for an exercise building RPM package.
Description :
Helloworld is a sample package for an exercise building RPM package.
* 日 1124 2013 kohchi kohchi@example.com
- This is the first release
- This is test
$ rpm -qa | grep hello
helloworld-0.1-0.1.x86_64
$

ちゃんとインストールされていることを確認。念のため、このあとrpm -e helloworldで削除できることも確認した。