mboot/kernel 自动化编译流程分析

在我们开发好软件之后,发布固件,ROM 包时,需要自动化编译。 这个时候要解决一个问题,就是编译过程中交互输入完成配置项选择。

我们先看一下传统的编译方式,如图
mboot/kernel 自动化编译流程分析_第1张图片
mboot/kernel 自动化编译流程分析_第2张图片
都是先拷贝一个 .config*** 配置文件覆盖当前的 .config 文件,接着make menuconfig < … ,重定向输入一个文件,
mboot/kernel 自动化编译流程分析_第3张图片
来代替手动选择流程, 最后make clean && make。

流程比较简单,但是如果碰到不支持图形界面的服务器,那么执行make menuconfig 会失败,从而导致构建失败。

我们这里可以对mboot 的编译流程稍作分析:

1. makefile 分析

vendor\mstar\mboot\MBoot\sboot\scripts\kconfig\Makefile

help:
	@echo  '  config	  - Update current config utilising a line-oriented program'
	@echo  '  menuconfig	  - Update current config utilising a menu based program'
	@echo  '  xconfig	  - Update current config utilising a QT based front-end'
	@echo  '  gconfig	  - Update current config utilising a GTK based front-end'
	@echo  '  oldconfig	  - Update current config utilising a provided .config as base'
	@echo  '  randconfig	  - New config with random answer to all options'
	@echo  '  defconfig	  - New config with default answer to all options'
	@echo  '  allmodconfig	  - New config selecting modules when possible'
	@echo  '  allyesconfig	  - New config where all options are accepted with yes'
	@echo  '  allnoconfig	  - New config where all options are answered with no'

其中xconfig,gconfig,menuconfig 分别使用的是qconf,gconf,mconf工具,如下:
mboot/kernel 自动化编译流程分析_第4张图片
而其它的config,oldconfig,randconfig,defconfig,allmodconfig,allyesconfig,allnoconfig,silentoldconfig,都使用的是conf 工具,只是传给conf 的参数不同而已。
每个配置项的详细说明可以参看另外一篇博友的文章。

2. conf 工具

vendor\mstar\mboot\MBoot\sboot\scripts\kconfig\conf.c分析
首先makefile 如下目标会调用conf工具

config: $(obj)/conf
	$< Config.in

oldconfig: $(obj)/conf
	$< -o Config.in

silentoldconfig: $(obj)/conf
	$< -s Config.in

randconfig: $(obj)/conf
	$< -r Config.in

allyesconfig: $(obj)/conf
	$< -y Config.in

allnoconfig: $(obj)/conf
	$< -n Config.in

allmodconfig: $(obj)/conf
	$< -m Config.in

defconfig: $(obj)/conf
	$(Q)rm -f ./UConfig.in
	if [ -a ./../u-boot-2011.06/UConfig.in ]; then \
	ln -s -v ./../u-boot-2011.06/UConfig.in ./UConfig.in;\
	else \
	touch ./UConfig.in;\
	fi;
ifeq ($(KBUILD_DEFCONFIG),)
	$< -d Config.in
else
	@echo *** Default configuration is based on '$(KBUILD_DEFCONFIG)'
	$(Q)$< -D $(KBUILD_DEFCONFIG) Config.in
endif

%_defconfig: $(obj)/conf
	$(Q)$< -D $@ Config.in

不同配置目标传入的不同的参数(-D,-s,-o,-d,-m,-y,-r),工具参数解析如下:

int main(int ac, char **av)
{
     
	int i = 1;
	const char *name;
	struct stat tmpstat;

	if (ac > i && av[i][0] == '-') {
     
		switch (av[i++][1]) {
     
		case 'o':
			input_mode = ask_new;
			break;
		case 's':
			input_mode = ask_silent;
			valid_stdin = isatty(0); //bbox: && isatty(1) && isatty(2);
			break;
		case 'd':
			input_mode = set_default;
			break;
		case 'D':
			input_mode = set_default;
			defconfig_file = av[i++];
			if (!defconfig_file) {
     
				printf(_("%s: No default config file specified\n"),
					av[0]);
				exit(1);
			}
			break;
		case 'n':
			input_mode = set_no;
			break;
		case 'm':
			input_mode = set_mod;
			break;
		case 'y':
			input_mode = set_yes;
			break;
		case 'r':
			input_mode = set_random;
			srandom(time(NULL));
			break;
		case 'h':
		case '?':
			fprintf(stderr, "See README for usage info\n");
			exit(0);
		}
	}
	name = av[i];
	if (!name) {
     
		printf(_("%s: Kconfig file missing\n"), av[0]);
	}
	conf_parse(name);

	......
}

解析完conf 参数之后,给input_mode赋以下值:

enum {
     
	ask_all,
	ask_new,
	ask_silent,
	set_default,
	set_yes,
	set_mod,
	set_no,
	set_random
} input_mode = ask_all;

3. 解析UConfig.in 文件

vendor\mstar\mboot\MBoot\u-boot-2011.06\UConfig.in
文件主要是解析MCU_ARM,USB,AMP,LAN,FLASH,MMC,NAND,SPI,FILE_SYSTEM,KEYPAD,IR,SECURITY_BOOT,主频,ddr 型号等等

conf.c中
	name = av[i];
	if (!name) {
     
		printf(_("%s: Kconfig file missing\n"), av[0]);
	}
	conf_parse(name);

zconf.tab.c 解析UConfig.in 文件

void conf_parse(const char *name)
{
     
	struct symbol *sym;
	int i;

	zconf_initscan(name);

	sym_init();
	menu_init();
	modules_sym = sym_lookup("MODULES", 0);
	rootmenu.prompt = menu_add_prompt(P_MENU, "SBoot Configuration", NULL);

#if YYDEBUG
	if (getenv("ZCONF_DEBUG"))
		zconfdebug = 1;
#endif
	zconfparse();
	if (zconfnerrs)
		exit(1);
	menu_finalize(&rootmenu);
	for_all_symbols(i, sym) {
     
		sym_check_deps(sym);
        }

	sym_change_count = 1;
}

4. 配置导入

conf 导入UConfig.in 的菜单树,根据传入的参数进行选择yes,no 等等。

	if (input_mode != ask_silent) {
     
		rootEntry = &rootmenu;
		conf(&rootmenu);
		if (input_mode == ask_all) {
     
			input_mode = ask_silent;
			valid_stdin = 1;
		}
	}
	do {
     
		conf_cnt = 0;
		check_conf(&rootmenu);
	} while (conf_cnt);

5. 默认配置导入

mboot

Step 1:cp configs/M7221/.config.xxxx.xx.optee.kdrv scripts/defconfig
Step 2: make defconfig
Step 3: make clean;make;

kernel

Step 1: cp .config_m7221_SMP_arm64_android_emmc_nand .config
Step 2: cp .config_m7221_SMP_arm64_android_emmc_nand arch/arm64/configs/mstar_config
Step 3: sh genlink.sh
Step 4: make defconfig KBUILD_DEFCONFIG=mstar_config
Step 4: make clean; make -j32

你可能感兴趣的:(makefile,商显,uboot)