說明如何在 Fedora 21 或更新的系統上對最簡單的 project - hello (無外部相依) 進行打包.
安裝 rpm 開發相關工具
$ sudo dnf install fedora-packager @development-tools
將自己加到 mock 群中
$ sudo usermod -a -G mock derekdai
產生工作目錄
$ rpmdev-setuptree
上面的指令會在 ~/
下產生一個叫 rpmbuild
的目錄
$ ls rpmbuild/
BUILD BUILDROOT RPMS SOURCES SPECS SRPMS
接下來, 準備我們的 source code, 建立 SOURCES/hello-1.0/
$ cd rpmbuild/SOURCES
$ mkdir hello-1.0
在 hello-1.0/
下保存以下檔案
/* hello.c */
#include <stdio.h>
int main()
{
printf("hello\n");
return 0;
}
# Makefile
all: hello
hello: hello.o
hello.o: hello.c
.PHONY: clean
clean:
rm -rf hello hello.o
接著產生 tar 包
$ tar zcvpf hello-1.0.tar.gz hello-1.0
有了 hello-1.0.tar.gz
, 就可以產生 .spec
檔的模板了
$ cd ../SPECS
$ rpmdev-newspec hello
$ cat hello.spec
Name: hello
Version:
Release: 1%{?dist}
Summary:
License:
URL:
Source0:
BuildRequires:
Requires:
%description
%prep
%setup -q
%build
%configure
make %{?_smp_mflags}
%install
rm -rf $RPM_BUILD_ROOT
%make_install
%files
%doc
%changelog
* Thu Sep 24 2015 Derek Dai
-
試 build 看能否通過
$ rpmbuild -ba hello.spec
error: line 2: Empty tag: Version:
看起來有幾個資訊必給, 修改 hello.spec
...
Version: 1.0
Release: 1%{?dist}
Summary: Say hello to world
License: GPLv3
URL: http://no.upstream.im
Source0: http://no.upstream.im/hello-1.0.tar.gz
#BuildRequires:
#Requires:
Version
指的是 upstream 的版本, Release
是指 rpm 打包的版本. Sammary
的第一個字母一定要大小, 不然會有 warning. Source0
的最後如果跟 tar 包名字相同 (hello-1.0.tar.gz
) 則不用另外指定 archive 檔名.
再試 build 看看
$ rpmbuild -ba hello.spec
Executing(%prep): /bin/sh -e /var/tmp/rpm-tmp.9d19xj
+ umask 022
+ cd /home/derekdai/rpmbuild/BUILD
+ cd /home/derekdai/rpmbuild/BUILD
+ rm -rf hello-1.0
+ /usr/bin/gzip -dc /home/derekdai/rpmbuild/SOURCES/hello-1.0.tar.gz
+ /usr/bin/tar -xf -
+ STATUS=0
+ '[' 0 -ne 0 ']'
+ cd hello-1.0
+ /usr/bin/chmod -Rf a+rX,u+w,g-w,o-w .
+ exit 0
Executing(%build): /bin/sh -e /var/tmp/rpm-tmp.4XUqDb
+ umask 022
+ cd /home/derekdai/rpmbuild/BUILD
+ cd hello-1.0
+ CFLAGS='-O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic'
+ export CFLAGS
+ CXXFLAGS='-O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic'
+ export CXXFLAGS
+ FFLAGS='-O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic -I/usr/lib64/gfortran/modules'
+ export FFLAGS
+ FCFLAGS='-O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic -I/usr/lib64/gfortran/modules'
+ export FCFLAGS
+ LDFLAGS='-Wl,-z,relro '
+ export LDFLAGS
+ '[' 1 = 1 ']'
++ find . -name config.guess -o -name config.sub
+ '[' 1 = 1 ']'
+ '[' x '!=' x ']'
+ ./configure --build=x86_64-redhat-linux-gnu --host=x86_64-redhat-linux-gnu --program-prefix= --disable-dependency-tracking --prefix=/usr --exec-prefix=/usr --bindir=/usr/bin --sbindir=/usr/sbin --sysconfdir=/etc --datadir=/usr/share --includedir=/usr/include --libdir=/usr/lib64 --libexecdir=/usr/libexec --localstatedir=/var --sharedstatedir=/var/lib --mandir=/usr/share/man --infodir=/usr/share/info
/var/tmp/rpm-tmp.4XUqDb: line 44: ./configure: No such file or directory
error: Bad exit status from /var/tmp/rpm-tmp.4XUqDb (%build)
RPM build errors:
Bad exit status from /var/tmp/rpm-tmp.4XUqDb (%build)
在執行 configure
時失敗了, 嗯~ 本來我們就只有簡單的 Makefile
, 去掉這行試試
...
%configure
...
再試 build
...
+ /usr/bin/make install DESTDIR=/home/derekdai/rpmbuild/BUILDROOT/hello-1.0-1.fc21.x86_64
make: *** No rule to make target 'install'. Stop.
error: Bad exit status from /var/tmp/rpm-tmp.hn1Er4 (%install)
RPM build errors:
Bad exit status from /var/tmp/rpm-tmp.hn1Er4 (%install)
執行到 make install
時失敗, 因為我們的 Makefile
只有 build & clean 的部份, 修改後的內容如下
# Makefile
all: hello
hello: hello.o
hello.o: hello.c
install:
/usr/bin/install -d $(DESTDIR)/usr/bin
/usr/bin/install hello $(DESTDIR)/usr/bin
.PHONY: clean
clean:
rm -rf hello hello.o
一般在 make install
時通常可傳入 DESTDIR
變量指定安全路徑的 prefix, 所以我們在安裝路徑前加上了 $(DESTDIR)
. 重新產生 SOURCES/hello-1.0.tar.gz
, 再試 build
...
Processing files: hello-1.0-1.fc21.x86_64
Processing files: hello-debuginfo-1.0-1.fc21.x86_64
Checking for unpackaged file(s): /usr/lib/rpm/check-files /home/derekdai/rpmbuild/BUILDROOT/hello-1.0-1.fc21.x86_64
error: Installed (but unpackaged) file(s) found:
/usr/bin/hello
RPM build errors:
Installed (but unpackaged) file(s) found:
/usr/bin/hello
這是因為我們沒有在 hello.spec
中指明會安裝進系統的檔案清單. hello
會裝到 /usr/bin
目錄下, 但 hardcode 路徑不是好的做法, .spec
檔中可改用變量 %{_bindir}
, 修改如下
...
%file
%{_bindir}/hello
%doc
...
試 build
$ rpmbuild -ba hello.spec
Executing(%prep): /bin/sh -e /var/tmp/rpm-tmp.Rh1JXQ
+ umask 022
+ cd /home/derekdai/rpmbuild/BUILD
+ cd /home/derekdai/rpmbuild/BUILD
+ rm -rf hello-1.0
+ /usr/bin/gzip -dc /home/derekdai/rpmbuild/SOURCES/hello-1.0.tar.gz
+ /usr/bin/tar -xf -
+ STATUS=0
+ '[' 0 -ne 0 ']'
+ cd hello-1.0
+ /usr/bin/chmod -Rf a+rX,u+w,g-w,o-w .
+ exit 0
Executing(%build): /bin/sh -e /var/tmp/rpm-tmp.BFJA61
+ umask 022
+ cd /home/derekdai/rpmbuild/BUILD
+ cd hello-1.0
+ make -j4
cc -c -o hello.o hello.c
cc hello.o -o hello
+ exit 0
Executing(%install): /bin/sh -e /var/tmp/rpm-tmp.PIDlqd
+ umask 022
+ cd /home/derekdai/rpmbuild/BUILD
+ '[' /home/derekdai/rpmbuild/BUILDROOT/hello-1.0-1.fc21.x86_64 '!=' / ']'
+ rm -rf /home/derekdai/rpmbuild/BUILDROOT/hello-1.0-1.fc21.x86_64
++ dirname /home/derekdai/rpmbuild/BUILDROOT/hello-1.0-1.fc21.x86_64
+ mkdir -p /home/derekdai/rpmbuild/BUILDROOT
+ mkdir /home/derekdai/rpmbuild/BUILDROOT/hello-1.0-1.fc21.x86_64
+ cd hello-1.0
+ rm -rf /home/derekdai/rpmbuild/BUILDROOT/hello-1.0-1.fc21.x86_64
+ /usr/bin/make install DESTDIR=/home/derekdai/rpmbuild/BUILDROOT/hello-1.0-1.fc21.x86_64
/usr/bin/install -d /home/derekdai/rpmbuild/BUILDROOT/hello-1.0-1.fc21.x86_64/usr/bin
/usr/bin/install hello /home/derekdai/rpmbuild/BUILDROOT/hello-1.0-1.fc21.x86_64/usr/bin
+ /usr/lib/rpm/find-debuginfo.sh --strict-build-id -m --run-dwz --dwz-low-mem-die-limit 10000000 --dwz-max-die-limit 110000000 /home/derekdai/rpmbuild/BUILD/hello-1.0
extracting debug info from /home/derekdai/rpmbuild/BUILDROOT/hello-1.0-1.fc21.x86_64/usr/bin/hello
dwz: Too few files for multifile optimization
/usr/lib/rpm/sepdebugcrcfix: Updated 0 CRC32s, 1 CRC32s did match.
+ '[' '%{buildarch}' = noarch ']'
+ QA_CHECK_RPATHS=1
+ case "${QA_CHECK_RPATHS:-}" in
+ /usr/lib/rpm/check-rpaths
+ /usr/lib/rpm/check-buildroot
+ /usr/lib/rpm/brp-compress
+ /usr/lib/rpm/brp-strip-static-archive /usr/bin/strip
+ /usr/lib/rpm/brp-python-bytecompile /usr/bin/python 1
+ /usr/lib/rpm/brp-python-hardlink
+ /usr/lib/rpm/redhat/brp-java-repack-jars
Processing files: hello-1.0-1.fc21.x86_64
Provides: hello = 1.0-1.fc21 hello(x86-64) = 1.0-1.fc21
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: hello-debuginfo-1.0-1.fc21.x86_64
Checking for unpackaged file(s): /usr/lib/rpm/check-files /home/derekdai/rpmbuild/BUILDROOT/hello-1.0-1.fc21.x86_64
Wrote: /home/derekdai/rpmbuild/SRPMS/hello-1.0-1.fc21.src.rpm
Wrote: /home/derekdai/rpmbuild/RPMS/x86_64/hello-1.0-1.fc21.x86_64.rpm
Wrote: /home/derekdai/rpmbuild/RPMS/x86_64/hello-debuginfo-1.0-1.fc21.x86_64.rpm
Executing(%clean): /bin/sh -e /var/tmp/rpm-tmp.Z7vGMp
+ umask 022
+ cd /home/derekdai/rpmbuild/BUILD
+ cd hello-1.0
+ /usr/bin/rm -rf /home/derekdai/rpmbuild/BUILDROOT/hello-1.0-1.fc21.x86_64
+ exit 0
過啦! 確認下
$ ls ../RPMS/x86_64/
hello-1.0-1.fc21.x86_64.rpm hello-debuginfo-1.0-1.fc21.x86_64.rpm
試安裝
$ sudo dnf install ../RPMS/x86_64/hello-1.0-1.fc21.x86_64.rpm
Fedora 21 - x86_64 - Updates 951 kB/s | 22 MB 00:23
Using metadata from Tue Sep 22 13:12:46 2015 (2 days, 4:47:13 hours old)
Dependencies resolved.
=============================================================================================================================================================================
Package Arch Version Repository Size
=============================================================================================================================================================================
Installing:
hello x86_64 1.0-1.fc21 @commandline 8.7 k
Transaction Summary
=============================================================================================================================================================================
Install 1 Package
Total size: 8.7 k
Installed size: 7.0 k
Is this ok [y/N]: y
Downloading Packages:
Running transaction check
Transaction check succeeded.
Running transaction test
Transaction test succeeded.
Running transaction
Installing : hello-1.0-1.fc21.x86_64 1/1
Verifying : hello-1.0-1.fc21.x86_64 1/1
Installed:
hello.x86_64 1.0-1.fc21
Complete!
執行看看
$ which hello
/usr/bin/hello
$ hello
hello
移除
$ sudo dnf remove hello
Dependencies resolved.
=============================================================================================================================================================================
Package Arch Version Repository Size
=============================================================================================================================================================================
Removing:
hello x86_64 1.0-1.fc21 @System 7.0 k
Transaction Summary
=============================================================================================================================================================================
Remove 1 Package
Installed size: 7.0 k
Is this ok [y/N]: y
Running transaction check
Transaction check succeeded.
Running transaction test
Transaction test succeeded.
Running transaction
Erasing : hello-1.0-1.fc21.x86_64 1/1
Verifying : hello-1.0-1.fc21.x86_64 1/1
Removed:
hello.x86_64 1.0-1.fc21
Complete!
$ which hello
/usr/bin/which: no hello in (/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/home/derekdai/.local/bin:/home/derekdai/bin)
參考資料