在我们开发好软件之后,发布固件,ROM 包时,需要自动化编译。 这个时候要解决一个问题,就是编译过程中交互输入完成配置项选择。
我们先看一下传统的编译方式,如图
都是先拷贝一个 .config*** 配置文件覆盖当前的 .config 文件,接着make menuconfig < … ,重定向输入一个文件,
来代替手动选择流程, 最后make clean && make。
流程比较简单,但是如果碰到不支持图形界面的服务器,那么执行make menuconfig 会失败,从而导致构建失败。
我们这里可以对mboot 的编译流程稍作分析:
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工具,如下:
而其它的config,oldconfig,randconfig,defconfig,allmodconfig,allyesconfig,allnoconfig,silentoldconfig,都使用的是conf 工具,只是传给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;
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;
}
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);
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