制作kernel rpm步驟:
1.安裝工具
yum install rpm-devel;rpmdevtools
yum groupinstall "Development Tools"
2.rpmdev-setuptree #在當前用戶根目錄下生成rpmbuild目錄
rpmbuild/
├── BUILD
├── BUILDROOT
├── RPMS
├── SOURCES
├── SPECS
└── SRPMS
3.下載kernel package,並解壓
wget http://mirrors.ustc.edu.cn/kernel.org/linux/kernel/v5.x/Linux-5.7.1.tar.gz
tar -zxvf linux-5.7.1.tar.gz
4.生成rpm
cd linux-5.7.1/
make rpm-pkg
可以看到如下信息
Wrote: /root/rpmbuild/SRPMS/kernel-5.7.1-1.src.rpm
Wrote: /root/rpmbuild/RPMS/x86_64/kernel-5.7.1-1.x86_64.rpm
Wrote: /root/rpmbuild/RPMS/x86_64/kernel-headers-5.7.1-1.x86_64.rpm
Wrote: /root/rpmbuild/RPMS/x86_64/kernel-devel-5.7.1-1.x86_64.rpm
Executing(%clean): /bin/sh -e /var/tmp/rpm-tmp.4aODom
+ umask 022
+ cd /root/rpmbuild/BUILD
+ cd kernel-5.7.1
+ rm -rf /root/rpmbuild/BUILDROOT/kernel-5.7.1-1.x86_64
+ exit 0
到這里就ok了,可以看到/root/rpmbuild/RPMS/下生成了kernel,kernel-header,kernel-devel的rpm包,以及SRPMS/下會生成kernel-src的rpm包
命令超級簡單,瞧瞧生成rpm 過程:
1.當我們在linux-5.7.1/下執行make help可以看到:
Kernel packaging: rpm-pkg - Build both source and binary RPM kernel packages binrpm-pkg - Build only the binary kernel RPM package deb-pkg - Build both source and binary deb kernel packages bindeb-pkg - Build only the binary kernel deb package snap-pkg - Build only the binary kernel snap package (will connect to external hosts) dir-pkg - Build the kernel as a plain directory structure tar-pkg - Build the kernel as an uncompressed tarball targz-pkg - Build the kernel as a gzip compressed tarball tarbz2-pkg - Build the kernel as a bzip2 compressed tarball tarxz-pkg - Build the kernel as a xz compressed tarball perf-tar-src-pkg - Build perf-5.7.1.tar source tarball perf-targz-src-pkg - Build perf-5.7.1.tar.gz source tarball perf-tarbz2-src-pkg - Build perf-5.7.1.tar.bz2 source tarball perf-tarxz-src-pkg - Build perf-5.7.1.tar.xz source tarball
這些參數告訴我們可以去build什么樣的packages
當我們進一步打開linux-5.7.1/Makefile可以看到有下面信息:
%src-pkg: FORCE $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.package $@ %pkg: include/config/kernel.release FORCE $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.package $@
%是通配符,不管我們build %src-pkg 或者%pkg,都要去調用Makefile.package文件
因此,可以打開Makefile.package看一下
PHONY += rpm-pkg rpm-pkg: $(MAKE) clean $(CONFIG_SHELL) $(MKSPEC) >$(objtree)/kernel.spec $(call cmd,src_tar,$(KERNELPATH),kernel.spec) +rpmbuild $(RPMOPTS) --target $(UTS_MACHINE) -ta $(KERNELPATH).tar.gz \ --define='_smp_mflags %{nil}' # binrpm-pkg # --------------------------------------------------------------------------- PHONY += binrpm-pkg binrpm-pkg: $(MAKE) -f $(srctree)/Makefile $(CONFIG_SHELL) $(MKSPEC) prebuilt > $(objtree)/binkernel.spec +rpmbuild $(RPMOPTS) --define "_builddir $(objtree)" --target \ $(UTS_MACHINE) -bb $(objtree)/binkernel.spec .............
這里告訴我們要去build package需要執行的步驟,例如build rpm-pkg
變量定義自己去找,下面翻譯每個步驟:
步驟1:make clean
步驟2:./scripts/package/mkspec >./kernel.spec #生成spec文檔
步驟3:rpmbuild --target x86_64 -ta kernel-5.7.1.tar.gz --define='_smp_mflags %{nil}'
步驟1,2好懂,來具體看看步驟3:
首先看下主目錄下Makefile:
ifeq ("$(origin V)", "command line") KBUILD_VERBOSE = $(V) endif ifndef KBUILD_VERBOSE KBUILD_VERBOSE = 0 endif ifeq ($(KBUILD_VERBOSE),1) quiet = Q = else quiet=quiet_ Q = @ endif
origin的語法:$(origin <variable>;) 函數origin並不操作變量的值,只是告訴你你的這個變量是哪里來的。
origin的返回值如下:
(1)返回值為"undefine"時,這個變量沒有被定義過;
(2)返回值為“command line”時,這個變量是被命令行定義的;
(3)返回值為“environment”時,這個變量是定義為環境變量;
(4)返回值為“file”時,這個變量是定義在Makefile中;
(5)返回值為“default”時,變量是默認定義的;
(6)返回值為“override”時,被override指示符重新定義;
(7)返回值為“automatic”時,是一個命令運行中自動化變量
如果是指定V的值,make V=【0|1|2】,0表示quiet build,1表示verbose build,2表示give reason for build,則KBUILD_VERBOSE = V;
否則KBUILD_VERBOSE = 0;決定了quiet和Q的值
在這里顯然是KBUILD_VERBOSe = 0,quiet=quiet_;Q=@
再看下cmd和src_tar的定義,scripts/Kbuild.include:
echo-cmd = $(if $($(quiet)cmd_$(1)),\ echo ' $(call escsq,$($(quiet)cmd_$(1)))$(echo-why)';) # printing commands cmd = @set -e; $(echo-cmd) $(cmd_$(1)) quiet_cmd_src_tar = TAR $(2).tar.gz cmd_src_tar = \ set -e; \ if test "$(objtree)" != "$(srctree)"; then \ echo >&2; \ echo >&2 " ERROR:"; \ echo >&2 " Building source tarball is not possible outside the"; \ echo >&2 " kernel source tree. Don't set KBUILD_OUTPUT, or use the"; \ echo >&2 " binrpm-pkg or bindeb-pkg target instead."; \ echo >&2; \ false; \ fi ; \ $(srctree)/scripts/setlocalversion --save-scmversion; \ tar -cz $(RCS_TAR_IGNORE) -f $(2).tar.gz \ --transform 's:^:$(2)/:S' $(TAR_CONTENT) $(3); \ rm -f $(objtree)/.scmversion
@set -e: @意思是不回顯command,只回顯結果,set -e意思是,如果執行結果不是true則退出
escsq的作用是將單引號'替換成\' ,避免在echo 聲明中使用單引號
echo-why:需要KBUILD_VERBOSE=2時才有效,告訴為什么target被build
echo-cmd作用是打印該命令,以及為什么built target,但echo-why 只在make V=2時才enable
echo的作用是打印該命令,並且執行該命令
就cmd定義的結構來看
cmd = @set -e; $(echo-cmd) $(cmd_$(1))
打開set -e功能 打印quiet_cmd_${1}, 執行命令
前提是quiet_cmd_${1}有定義
$(call cmd,src_tar,$(KERNELPATH),kernel.spec),這里${1}是src_tar,${2}是${KERNELPATH},${3}是kernel.spec,但是在quiet_src_tar是沒有用到kernel.spec這個參數,在src_tar時才用到。
因此翻譯過來就是TAR kernel-5.7.1.tar.gz
對於步驟4:+rpmbuild $(RPMOPTS) --target $(UTS_MACHINE) -ta $(KERNELPATH).tar.gz --define='_smp_mflags %{nil}'
先了解下幾個特殊字符:
+ : 執行命令時不受到make的-n -t -q 三個參數的影響
make:
-n : 僅打印命令而不執行,通常用在需要看自己編寫的makefile是否錯誤,命令是否正確的情況下
-t : 跟新目標文件的時間,只把目標文件變成已經編譯的狀態,而不是真正的編譯目標,偽編譯
-q : 檢查目標文件是否需要跟新
- : 任何命令行的非零退出狀態都被忽略,不會因為執行錯誤,退出狀態為非零而退出
@ : 不顯示命令本身而只顯示結果
$ : 打印makefile中定義的變量
$$ : 打印makefile中定義的shell變量
$@ : 目標文件
$^ : 所有的依賴文件
$< : 第一個依賴文件
-ta的意思:build binary and source package with tarball
--defile='_smp_mflags ${nil}'是優化選項,目前還沒搞懂什么意思~
這句命令翻譯過來就是rpmbuild --target x86_64 -ta kernel-5.7.1.tar.gz --define='_smp_mflags %{nil}'
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
整個make rpm-pkg的過程就是創建kernel.spec,然后執行rpmbuild,我跳過make rpm-pkg過程,直接用rpmbuild也可以,步驟如下:
1.安裝工具
yum install rpm-devel;rpmdevtools
yum groupinstall "Development Tools"
2.rpmdev-setuptree #在當前用戶根目錄下生成rpmbuild目錄
rpmbuild/
├── BUILD
├── BUILDROOT
├── RPMS
├── SOURCES
├── SPECS
└── SRPMS
3.下載kernel package,並解壓
wget http://mirrors.ustc.edu.cn/kernel.org/linux/kernel/v5.x/Linux-5.7.1.tar.gz
tar -zxvf linux-5.7.1.tar.gz
4.cd linux-5.7.1
1).make menuconfig #生成.config文件,只需要點擊save即可
2).修改.config:
CONFIG_SYSTEM_TRUSTED_KEYS="certs/rhel.pem" => #CONFIG_SYSTEM_TRUSTED_KEYS="certs/rhel.pem"
CONFIG_DEBUG_INFO_BTF=y => CONFIG_DEBUG_INFO_BTF=n
不然編譯會報錯
3.修改 scripts/package/mkspec,因為跳過了make,所以不能繼承Makefile里面的變量
KERNELRELEASE=5.7.1
MAKE=make
export RCS_TAR_IGNORE=“--exclude SCCS --exclude BitKeeper --exclude .svn --exclude CVS --exclude .pc --exclude .hg --exclude .git”
然后./scripts/package/mkspec > ./kernel.spec
4.生成.config和kernel.spec后
mv linux-5.7.1 kernel-5.7.1 #這個不是必要的,只是kernel.spec里寫的name是kernel,當然也可以把name改成linux,但是一般是kernel開頭吧
tar -zcvf kernel-5.7.1.tar.gz kernel-5.7.1 #生成tarball
5.rpmbuild --target x86_64 -ta kernel-5.7.1.tar.gz --define='_smp_mflags %{nil}'
只是幫助理解過程,實際中還是make rpm-pkg一個指令就搞定啦
有兩點疑問
1.TAR kernel-5.7.1.tar.gz這個TAR實在找不到哪里來的
2.--define='_smp_mflags %{nil}' 還沒理解