【Linux】内核基于GCC裁剪流程-进一步优化版本
当前比较好的流程(编译GCC,编译内核,去冗,编译内核)
操作电脑
比如:使用USB,连接网络等等
编译新的gcc(大概30多分钟,这里笔者在笔记本上安装ubuntu-24.10-live-server-amd64,测试所有流程是成功的,但是在虚拟机编译gcc会卡死。。。虚拟机里未测试基于新的gcc编译内核,是把虚拟机的代码下载到笔记本电脑编译通过的)
下载gcc-14.2.0
wget https://mirrors.aliyun.com/gnu/gcc/gcc-14.2.0/gcc-14.2.0.tar.gz
解压并修改源文件(2个源文件,共修改8行,原来修改的太复杂)
tar -xf gcc-14.2.0.tar.gz,进入解压目录并修改gcc源代码,gcc/gcc.cc,这里在根目录下记录当前编译的源文件名(包含路径):
这里是GCC编译时,会不断提示要不要删除/tmp目录下的.s,.o,.res等等文件,注释掉编译时不问在终端里打Delele xxx.o? (y or n)。
在libcpp/files.cc里,这里主要是记录源文件依赖的头文件目录和文件名,这里在中间打了 空格>>>空格 ,这个很有用,后边会讲到:
安装gcc编译依赖
apt install -y make build-essential libc6-dev libtbb-dev g++ libgmp-dev libmpfr-dev libmpc-dev
配置gcc编译参数
mkdir gcc-build
cd gcc-build
../configure --prefix=$HOME/.local --disable-multilib --disable-bootstrap
gcc编译
make -j8
gcc安装
make install
注意gcc安装后,要把原来的gcc用新编译的gcc替换,建立一个软链接:
rm /usr/bin/gcc
ln -s /root/.local/bin/gcc /usr/bin/gcc
另外,这里编译好的gcc所在的目录/root/.local,这个目录是可以直接压包,后续用到的时候直接解压就可以重复多次使用,很方便。
编译内核(用于记录已使用模块对应使用的源代码到/log.txt中,大概40-50分钟,与使用的模块多少,电脑硬件相关)
下载内核linux-6.14
wget https://mirrors.nju.edu.cn/kernel.org/linux/kernel/v6.x/linux-6.14.tar.gz
解压内核
tar -xf linux-6.14.tar.gz
安装内核编译依赖
apt install -y make libncurses-dev make flex bison libelf-dev libssl-dev
生成.config文件
cd linux-6.14
make localmodconfig
编译、安装内核(安装内核也编译下,因为这里会用到工具的源代码)
make -j16
make -j8 modules_install
make -j8 install
到这里时,基于操作电脑的内核源代码的文件汇总日志基本都记录到/log.txt
处理汇总的log.txt
排序去重(log.txt大约100M-150M,操作后400KB-500KB)
sort log.txt | uniq > log_sort_uniq.txt
进一步操作(针对具体问题具体操作)
1、比如有些只有特殊符号没有文件的行要删除
2、以/usr开头的行、以/root开头的行、空格>>>空格要去掉、目录不规范、去掉多余的空格
3、还有些包含中间生成文件:xxxx.mod.o这类
4、还有那种相对目录头文件包含的
grep "[a-zA-Z]" log_sort_uniq.txt > temp.txt
sed "/^\/usr/d" -i temp.txt
sed "s:^ >>> ::g" -i temp.txt
sed "s:/ >>> :/:g" -i temp.txt
sed "s: >>> :/:g" -i temp.txt
sed "s:/linux-6.14/::g" -i temp.txt
sed "s:^\.\/::g" -i temp.txt
sed "s: ::" -i temp.txt
sort temp.txt | uniq >temp1.txt
mv temp1.txt temp.txt
sed -i "/^\/root\//d" temp.txt
sed -i "/\.mod\.c/d" temp.txt
清空c/h源代码,从新拷贝上一步整理的文件列表到编译目录:
这里把linux-6.14.tar.gz压缩包重新解压到一个init目录,进入编译目录把所有已经编译的.o文件删除,然后进行循环从init目录找到源文件就拷贝到编译目录,其实还是会有一些文件找不到的,大概10来20多个吧(相对于几千上万个源文件来说算比较少的了)
mkdir /linux-6.14-init
tar -xf linux-6.14.tar.gz -C /linux-6.14-init/
mv /linux-6.14-init/linux-6.14/* /linux-6.14-init/cd /linux-6.14#delete old compiled objects
find /linux-6.14 -name "*.o" -deleteecho "the following file does not exist:"
for file in `cat /temp.txt`
doif [ -f "/linux-6.14-init/${file}" ]; thenecho "${file}" >> /file_exist.txtcp -rf /linux-6.14-init/${file} ${file}elseecho "${file}"echo "${file}" >> /file_not_exist.txtfi
done
反复编译验证
编译时报缺文件就去init目录找到并拷贝过来,继续编译,这里都是增量编译的,也算是比较快
编译如果没有问题更新/boot目录initrd.img等等启动文件
mkinitramfs -o /boot/initrd.img-6.14.0
update-initramfs -c -k 6.14.0
update-grub2
reboot
如果重启电脑后版本号与编译时间对得上号,那可以提交代码了。
代码入口地址(仅供参考)
e.gitee.com/rulai_2/repos/rulai_2/tools/blob/master/kernel_tailor%2F0-main.sh
Gitee 企业版https://e.gitee.com/rulai_2/repos/rulai_2/tools/blob/master/kernel_tailor%2F0-main.sh
感谢阅读。