kernel rpm 制作


制作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}' 還沒理解

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM