Linux Kernel 编译流程 (一)

2023-11-03

1 .config 文件产生

  • 研究Linux Kernel .config文件的产生, 添加自己的配置
  • Linux Kernel 4.18.20
  • Source Insight 3.5
  • Ubuntu 18.04
  • arm-linux-gnueabi-xxx

1.1 find %config

当我们执行sudo make ARCH=arm vexpress_defconfig命令行后,make会进入顶层Makefile文件,执行下面的语句. 而%config依赖scripts_basicouputmakefile, 所以我问首先去看scripts_basic

#SRCARCH := arm
SRCARCH 	:= $(ARCH)
#include arch/arm/Makefile
include arch/$(SRCARCH)/Makefile
%config: scripts_basic outputmakefile FORCE	
	$(Q)$(MAKE) $(build)=scripts/kconfig $@

1.2 find scripts_basic

在顶层Makefile中会发现如下代码段

scripts_basic:
	$(Q)$(MAKE) $(build)=scripts/basic
	$(Q)rm -f .tmp_quiet_recordmcount

make 直接执行命令行$(Q)$(MAKE) $(build)=scripts/basic, 展开后得到下面的片段,默认目标是all

#build := -f $(srctree)/scripts/Makefile.build obj
$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.build obj=scripts/basic
1.2.1 进入Makefile.build 执行
  • 包含 ./tools/build/Build
  • 包含scripts/Makefile.host

Makefile.build, 展开后得到下面的语句.其中dir=.中的".",是make进入Makefile.build的目录./tools/build/

PHONY := __build
__build:
src := scripts/basic
include scripts/Kbuild.include

# For backward compatibility check that these variables do not change
save-cflags := $(CFLAGS)

#kbuild-dir := ./scripts/basic
kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src))
#kbuild-file := ./scripts/basic/Makefile
kbuild-file := $(if $(wildcard $(kbuild-dir)/Kbuild),$(kbuild-dir)/Kbuild,$(kbuild-dir)/Makefile)
#include ./scripts/basic/Makefile
include $(kbuild-file)

ifneq ($(hostprogs-y)$(hostprogs-m)$(hostlibs-y)$(hostlibs-m)$(hostcxxlibs-y)$(hostcxxlibs-m),)
include scripts/Makefile.host
endif

__build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y)) \
	 $(if $(KBUILD_MODULES),$(obj-m) $(modorder-target)) \
	 $(subdir-ym) $(always)
	@:

我们查看下./scripts/basic/Makefile内容

hostprogs-y	:= fixdep
hostprogs-$(CONFIG_BUILD_BIN2C)     += bin2c
always		:= $(hostprogs-y)

#scripts/basic/bin2c: scripts/basic/fixdep
$(addprefix $(obj)/,$(filter-out fixdep,$(always))): $(obj)/fixdep

从上面我们得知hostprogs-y := fixdep, 不为空,接着继续执行命令行.include scripts/Makefile.host

ifneq ($(hostprogs-y)$(hostprogs-m)$(hostlibs-y)$(hostlibs-m)$(hostcxxlibs-y)$(hostcxxlibs-m),)
include scripts/Makefile.host
endif
1.2.2产生fixdep

当Make将Makefile.hostMakefile包含进来后,就会执行默认的目标__build, 而__build 依赖 $(always), 即fixdep,
而Makefile.host就是去产生fixdep

__hostprogs := $(sort $(hostprogs-y) $(hostprogs-m))								
# C code
# host-csingle := fixdep
host-csingle	:= $(foreach m,$(__hostprogs), \
			$(if $($(m)-objs)$($(m)-cxxobjs)$($(m)-sharedobjs),,$(m)))							
#host-csingle := scripts/basic/fixdep
host-csingle	:= $(addprefix $(obj)/,$(host-csingle))

hostc_flags    = -Wp,-MD,$(depfile) $(__hostc_flags)

#####
# Compile programs on the host

# Create executable from a single .c file
# host-csingle -> Executable
quiet_cmd_host-csingle 	= HOSTCC  $@
      cmd_host-csingle	= $(HOSTCC) $(hostc_flags) -o $@ $< \
	  	$(HOST_LOADLIBES) $(HOSTLOADLIBES_$(@F))
#产生fixdep	  	
$(host-csingle): $(obj)/%: $(src)/%.c FORCE											
	$(call if_changed_dep,host-csingle)

1.3 find outputmakefile

当fixdep完了后,make就返回执行第二个依赖outputmakefile ,目前没有对KBUILD_SRC赋值,所以没有执行任何语句

outputmakefile:
ifneq ($(KBUILD_SRC),)
	$(Q)ln -fsn $(srctree) source
	$(Q)$(CONFIG_SHELL) $(srctree)/scripts/mkmakefile \
	    $(srctree) $(objtree) $(VERSION) $(PATCHLEVEL)
endif

1.4 执行命令行

当make将所有的依赖scripts_basicoutputmakefile都产生了,就去执行命令行$(Q)$(MAKE) $(build)=scripts/kconfig $@,展开后得到, 目标是vexpress_defconfig

$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.build obj=scripts/kconfig smdk5250_defconfig
1.4.1 进入Makefile.build
  • 包含scripts/kconfig/Makefile
  • 包含scripts/Makefile.host
    进入Makefile.build后,展开后得到,下面的语句
PHONY := __build
__build:
src := scripts/kconfig
include scripts/Kbuild.include

# For backward compatibility check that these variables do not change
save-cflags := $(CFLAGS)

#kbuild-dir := ./scripts/kconfig
kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src))
#kbuild-file := ./scripts/kconfig/Makefile
kbuild-file := $(if $(wildcard $(kbuild-dir)/Kbuild),$(kbuild-dir)/Kbuild,$(kbuild-dir)/Makefile)
#include ./scripts/kconfig/Makefile
include $(kbuild-file)

ifneq ($(hostprogs-y)$(hostprogs-m),)
include scripts/Makefile.host
endif

从上面可以看出需要scripts/kconfig/Makefile, 其内容如下, 这里的SRCARCH:=arm

ifdef KBUILD_KCONFIG
Kconfig := $(KBUILD_KCONFIG)
else
Kconfig := Kconfig
endif

%_defconfig: $(obj)/conf
	@echo "eric_debug----------------start "$@
	#scripts/kconfig/conf --defconfig=arch/arm/configs/vexpress_defconfig Kconfig
	$(Q)$< $(silent) --defconfig=arch/$(SRCARCH)/configs/$@ $(Kconfig)
	@echo "eric_debug----------------end "$@
	
conf-objs	:= conf.o  zconf.tab.o
hostprogs-y := conf nconf mconf kxgettext qconf gconf

可以看出%_defconfig依赖 conf,所以应该首先产生conf, conf的产生会促使nconf mconf kxgettext qconf gconf的产生,其原理和fixdep产生一样,都需要借助Makefile.host,不做解释了

1.4.2 执行scripts/kconfig/Makefile中命令行

当conf产生后就需要执行命令行$(Q)$< $(silent) --defconfig=arch/$(SRCARCH)/configs/$@ $(Kconfig), 展开后得到

scripts/kconfig/conf  --defconfig=arch/arm/configs/vexpress_defconfig Kconfig

我们分析下此时此刻的conf.c


NOTE: getopt_long method

int main(int ac, char **av)
{
	while ((opt = getopt_long(ac, av, "s", long_opts, NULL)) != -1) {
		input_mode = (enum input_mode)opt;
		switch (opt) {
		case defconfig:
			//defconfig_file = smdk5250_defconfig
			defconfig_file = optarg;
			break;
		}
	}
	switch (input_mode) {
	case defconfig:
		//将smdk5250_defconfig中内容读入
		if (conf_read(defconfig_file)) {...}
		break;
	}
	switch (input_mode) {
	case defconfig:
		//设置新的symbols
		conf_set_all_new_symbols(def_default);
		break;
	}
	//写入---
	if (conf_write(NULL)) {...}

}

最终通过conf_write将信息写入.config中

int conf_write(const char *name)
{
	FILE *out;
	struct symbol *sym;
	struct menu *menu;
	const char *basename;
	const char *str;
	char dirname[PATH_MAX+1], tmpname[PATH_MAX+1], newname[PATH_MAX+1];
	char *env;
	/*
	const char *conf_get_configname(void)
	{
		char *name = getenv("KCONFIG_CONFIG");
		return name ? name : ".config";
	}
	*/
	//文件.config的由来
	basename = conf_get_configname();
	sprintf(newname, "%s%s", dirname, basename);

	conf_write_heading(out, &kconfig_printer_cb, NULL);

	menu = rootmenu.list;
	while (menu) {...}
	fclose(out);
	//最终看见的信息
	conf_message(_("configuration written to %s"), newname);
}

1.5 如何添加自己的CONFIG

当make生成.config后,整个sudo make ARCH=arm vexpress_defconfig, 就执行完了,但是如何添加自己的编译选项和文件到Makefile中呢?
以drivers/usb/host为例
(1) 首先我们找到该目录下的Kconfig, 然后添加下面的语句

config USB_ERIC_DEBUG
	bool "eric_debug usb support"
	#默认是开启的,没有任何依赖
	default y

在这里插入图片描述
(2) 然后在drivers/usb/host/ 目录下添加eric_debug_usb.c 并且在 drivers/usb/host/Makefile中添加下面的语句,

obj-$(CONFIG_USB_ERIC_DEBUG) += eric_debug_usb.o

NoteMakefileCONFIG_USB_ERIC_DEBUGCONF_后的字符串(USB_ERIC_DEBUG)一定要和 KconfigUSB_ERIC_DEBUG一样,

我们直接看看编译的部分结果(vmlinux), 如下所示
在这里插入图片描述
.config文件的产生以及怎样添加自己的文件,已经讲完了.请移步Linux Kernel编译流程(二)vmlinux的产生

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Linux Kernel 编译流程 (一) 的相关文章

随机推荐

  • c语言字符串做为函数参数传递,c语言:字符串做为函数参数传递

    1 值传递 void swap int x int y int temp x x y y temp void main int a 10 b 20 swap a b 执行后 并不会交换 2 引用传递 void swap int x int
  • C# 连接mySQL数据库访问异常:“给定关键字不在字典中”解决方案

    在自己电脑上开发的软件连接本机mysql数据库一切正常 部署到客户那边 运行时报异常 给定关键字不在字典中 原因 本机MySql数据库和客户那边的数据库版本不一致 使用的mysql data dll版本太低导致的 解决 更换mysql da
  • 深入理解Java内存模型

    作者 谢照东 链接 https www zhihu com question 29037280 answer 43136323 来源 知乎 著作权归作者所有 商业转载请联系作者获得授权 非商业转载请注明出处 我只是编码界的搬运工 深入理解J
  • 淘宝APP用户行为数据分析案例(附python代码及注释)

    淘宝APP用户行为数据分析案例 一 分析背景与目的 1 1背景与数据限制 电商平台的最核心的功能就是为买卖双方提供高效和体验良好的交易服务 得益于算法技术的发展 淘宝APP给买方提供了搜索 推荐及广告等系统和功能 使用户能高效地触达感兴趣或
  • 电力电子技术笔记-整流电路5

    电容滤波的不可控整流电路 在交 直 交变频器 不间断电源 开关电源等应用场合中 大量应用 最常用的是单相桥和三相桥两种接法 由于电路中的电力电子器件采用整流二极管 故也称这类电路为二极管整流电路 1 电容滤波的单相不可控整流电路 常用于小功
  • hugging face 官方文档——datasets、optimizer

    文章目录 一 Load dataset 1 1 Hugging Face Hub 1 2 本地和远程文件 1 2 1 CSV 1 2 2 JSON 1 2 3 text 1 2 4 Parquet 1 2 5 内存数据 python字典和D
  • 关于操作系统学习路线分析

    自己学习操作系统的时间也挺长了 虽然目前的成果还不是特别明显 但是在这段时间中还是学习了很多 今天想在这里和大家分享一下如何学习操作系统 以及如何制定学习操作系统的路线 以下是针对有过编程经历的 1 首先操作系统是人机交互的代理 那么作为操
  • 记录错误:cv2.error: OpenCV(4.4.0) C:\Users\appveyor\AppData\Local\Temp\1\pip-req-build-h4wtvo23\opencv\m

    使用Opencv时出现错误 cv2 error OpenCV 4 4 0 C Users appveyor AppData Local Temp 1 pip req build h4wtvo23 opencv modules imgproc
  • LTE学习笔记2:DMA多分址,制式,速率,性能指标

    1 DMA division multiple access 分多址 多址方式 TDMA 时分多址 FDMA 频分多址 CDMA 码分多址 SDMA 空分多址 PDMA 包分多址 3G技术 TD SCDMA TDD WCDMA FDD CD
  • windows通过wsl2安装ubuntu系统

    wsl Windows Subsystem for Linux 即用于Windows的安装Linux子系统 实现了在windows 10 或 windows 11上运行原生Linux系统的功能 wsl2 为其最新版本 可以更好的在Windo
  • 华为OD机试 - 消消乐游戏(Java)

    题目描述 游戏规则 输入一个只包含英文字母的字符串 字符串中的两个字母如果相邻且相同 就可以消除 在字符串上反复执行消除的动作 直到无法继续消除为止 此时游戏结束 输出最终得到的字符串长度 输入描述 输入原始字符串 str 只能包含大小写英
  • python音频分析工具_python – 鸟鸣音频分析 – 查找两个剪辑的匹配程度

    要做出这个答案 因为评论太久了 我基本上在这个领域工作 所以我觉得我有一些知识 显然 从我的立场来看 我建议使用音频而不是图像 我还建议使用MFCC作为特征提取 您可以将其视为总结 表征音频特定子带的系数 因为它们 GMM是去的 要执行此任
  • SSM入门—SpringMVC框架

    1 SpringMVC概述 Spring Web MVC 是一种基于Java的实现Web MVC设计模式的请求驱动类型的轻量级Web框架 2 MVC的设计模式 M model 模型 业务模型 数据模型 实体 业务代码 数据代码 V View
  • websocket(一)--握手

    最近在琢磨怎么实现服务端的消息推送 因为以前都是通过客户端请求来获取信息的 如果需要实时信息就得轮询 比如通过ajax不停的请求 websocket相当于对HTTP协议进行了升级 客户端和服务端通过websocket协议握手成功后 两者之间
  • 动态内存管理—(malloc、calloc、realloc、free)及常见使用错误

    目录 存在动态内存分配的意义 动态内存函数的介绍 malloc和free calloc realloc realloc在调整内存空间的是存在两种情况 由于上述的两种情况 realloc函数的使用就要注意一些 补充一点 常见的动态内存错误 对
  • 关于Q格式数据总结

    Q格式表示为 Qm n 表示数据用m比特表示整数部分 n比特表示小数部分 共需要 m n 1位来表示这个数据 多余的一位用作符合位 假设小数点在 n位的左边 从右向左数 从而确定小数的精度 例如Q15表示小数部分有15位 一个short 型
  • 为什么有些人年纪轻轻就赚到了很多钱?富人的底层逻辑是什么?

    在 史记 司马迁的书中 除开项羽本纪 秦始皇本纪 高祖本纪英雄的叙述以外 还有一个十分关键的章节目录 那便是 货殖列传 这一章节 十分详尽的纪录那时候商业服务 经济发展 买卖的状况 也体现了司马迁对财富和化学物质的观点 简言之 便是一部有关
  • 安全服务工程师面试题

    文章目录 你如何保护系统和网络免受恶意攻击 你会使用哪些工具和技术 你对密码安全有什么了解 你如何确保用户密码的安全 你如何保护敏感数据和机密信息的安全性 你会使用哪些技术 你如何识别和应对网络威胁 你使用哪些工具和技术 你如何进行网络安全
  • 运行应用程序,提示无法正常启动(0xc000007b)的解决办法

    本文转载自VBcom大牛的博客 感谢VBcom 最后更新 2019 2 28 如图 0xc000007b这个错误使无数玩家烦恼 问题描述 出现这个错误 可能是硬件的问题 也可能是软件的问题 但是 由于硬件引起该问题的概率很小 并且除了更换硬
  • Linux Kernel 编译流程 (一)

    1 config 文件产生 研究Linux Kernel config文件的产生 添加自己的配置 Linux Kernel 4 18 20 Source Insight 3 5 Ubuntu 18 04 arm linux gnueabi