接着上一篇文章继续分析:
scripts/kconfig/conf --defconfig=arch/../configs/imx8qxp_mek_defconfig Kconfig
0 1 2
分析conf.c源码,看conf怎么解析imx8qxp_mek_defconfig和Kconfig
分析main函数
int main(int ac, char **av)
{
const char *progname = av[0]; //progname=scripts/kconfig/conf
int opt;
const char *name, *defconfig_file = NULL /* gcc uninit */;
struct stat tmpstat;
setlocale(LC_ALL, ""); //设置时区函数,此处什么也没做
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
/*static inline void textdomain(const char *domainname) {}
static inline void bindtextdomain(const char *name, const char *dir) {}*/
定义了两个空函数
tty_stdio = isatty(0) && isatty(1); //判断是否为终端
while ((opt = getopt_long(ac, av, "s", long_opts, NULL)) != -1) {
从命令行获取参数,短参数-s,长参数从long_opts中获取
scripts/kconfig/conf --defconfig=arch/../configs/imx8qxp_mek_defconfig Kconfig
可以看到命令行没有-s参数,长参数中定义了defconfig,在long_opts中查找
static struct option long_opts[] = {
{"oldaskconfig", no_argument, NULL, oldaskconfig},
{"oldconfig", no_argument, NULL, oldconfig},
{"syncconfig", no_argument, NULL, syncconfig},
{"defconfig", optional_argument, NULL, defconfig},
{"savedefconfig", required_argument, NULL, savedefconfig},
{"allnoconfig", no_argument, NULL, allnoconfig},
{"allyesconfig", no_argument, NULL, allyesconfig},
{"allmodconfig", no_argument, NULL, allmodconfig},
{"alldefconfig", no_argument, NULL, alldefconfig},
{"randconfig", no_argument, NULL, randconfig},
{"listnewconfig", no_argument, NULL, listnewconfig},
{"olddefconfig", no_argument, NULL, olddefconfig},
{"oldnoconfig", no_argument, NULL, olddefconfig},
{NULL, 0, NULL, 0}
};
得到opt=defconfig, optarg=arch/../configs/imx8qxp_mek_defconfig optind=2
if (opt == 's') { //不执行
conf_set_message_callback(NULL);
continue;
}
input_mode = (enum input_mode)opt; //input_mode =defconfig
switch (opt) {
case syncconfig:
sync_kconfig = 1;
break;
case defconfig: //执行此处
case savedefconfig:
defconfig_file = optarg; //defconfig_file =arch/../configs/imx8qxp_mek_defconfig
break;
case randconfig:
{
struct timeval now;
unsigned int seed;
char *seed_env;
/*
* Use microseconds derived seed,
* compensate for systems where it may be zero
*/
gettimeofday(&now, NULL);
seed = (unsigned int)((now.tv_sec + 1) * (now.tv_usec + 1));
seed_env = getenv("KCONFIG_SEED");
if( seed_env && *seed_env ) {
char *endp;
int tmp = (int)strtol(seed_env, &endp, 0);
if (*endp == '\0') {
seed = tmp;
}
}
fprintf( stderr, "KCONFIG_SEED=0x%X\n", seed );
srand(seed);
break;
}
case oldaskconfig:
case oldconfig:
case allnoconfig:
case allyesconfig:
case allmodconfig:
case alldefconfig:
case listnewconfig:
case olddefconfig:
break;
case '?':
conf_usage(progname);
exit(1);
break;
}
}
if (ac == optind) { //不执行
fprintf(stderr, _("%s: Kconfig file missing\n"), av[0]);
conf_usage(progname);
exit(1);
}
name = av[optind]; //name=Kconfig
conf_parse(name);
此处解析传入的Kconfig的文件,将可选的配置信息,保存到一个链表中
if (sync_kconfig) { //不执行,当opt=syncconfig时执行
name = conf_get_configname();
if (stat(name, &tmpstat)) {
fprintf(stderr, _("***\n"
"*** Configuration file \"%s\" not found!\n"
"***\n"
"*** Please run some configurator (e.g. \"make oldconfig\" or\n"
"*** \"make menuconfig\" or \"make xconfig\").\n"
"***\n"), name);
exit(1);
}
}
switch (input_mode) {
case defconfig: //执行此处
if (!defconfig_file)
defconfig_file = conf_get_default_confname();
if (conf_read(defconfig_file)) { //读取arch/../configs/imx8qxp_mek_defconfig,并且生成新的 配置文件
fprintf(stderr,_("***\n*** Can't find default configuration \"%s\"!\n***\n"),defconfig_file);
exit(1);
}
break;
case savedefconfig:
case syncconfig:
case oldaskconfig:
case oldconfig:
case listnewconfig:
case olddefconfig:
conf_read(NULL);
break;
case allnoconfig:
case allyesconfig:
case allmodconfig:
case alldefconfig:
case randconfig:
name = getenv("KCONFIG_ALLCONFIG");
if (!name)
break;
if ((strcmp(name, "") != 0) && (strcmp(name, "1") != 0)) {
if (conf_read_simple(name, S_DEF_USER)) {
fprintf(stderr,
_("*** Can't read seed configuration \"%s\"!\n"),
name);
exit(1);
}
break;
}
switch (input_mode) {
case allnoconfig: name = "allno.config"; break;
case allyesconfig: name = "allyes.config"; break;
case allmodconfig: name = "allmod.config"; break;
case alldefconfig: name = "alldef.config"; break;
case randconfig: name = "allrandom.config"; break;
default: break;
}
if (conf_read_simple(name, S_DEF_USER) &&
conf_read_simple("all.config", S_DEF_USER)) {
fprintf(stderr,
_("*** KCONFIG_ALLCONFIG set, but no \"%s\" or \"all.config\" file found\n"),
name);
exit(1);
}
break;
default:
break;
}
if (sync_kconfig) { //不执行
if (conf_get_changed()) {
name = getenv("KCONFIG_NOSILENTUPDATE");
if (name && *name) {
fprintf(stderr,
_("\n*** The configuration requires explicit update.\n\n"));
return 1;
}
}
}
switch (input_mode) {
case allnoconfig:
conf_set_all_new_symbols(def_no);
break;
case allyesconfig:
conf_set_all_new_symbols(def_yes);
break;
case allmodconfig:
conf_set_all_new_symbols(def_mod);
break;
case alldefconfig:
conf_set_all_new_symbols(def_default);
break;
case randconfig:
/* Really nothing to do in this loop */
while (conf_set_all_new_symbols(def_random)) ;
break;
case defconfig: //执行此处
conf_set_all_new_symbols(def_default); //更新关系链表
break;
case savedefconfig:
break;
case oldaskconfig:
rootEntry = &rootmenu;
conf(&rootmenu);
input_mode = oldconfig;
/* fall through */
case oldconfig:
case listnewconfig:
case syncconfig:
/* Update until a loop caused no more changes */
do {
conf_cnt = 0;
check_conf(&rootmenu);
} while (conf_cnt);
break;
case olddefconfig:
default:
break;
}
if (sync_kconfig) {
/* syncconfig is used during the build so we shall update autoconf.
* All other commands are only used to generate a config.
*/
if (conf_get_changed() && conf_write(NULL)) {
fprintf(stderr, _("\n*** Error during writing of the configuration.\n\n"));
exit(1);
}
if (conf_write_autoconf()) {
fprintf(stderr, _("\n*** Error during update of the configuration.\n\n"));
return 1;
}
} else if (input_mode == savedefconfig) {
if (conf_write_defconfig(defconfig_file)) {
fprintf(stderr, _("n*** Error while saving defconfig to: %s\n\n"),
defconfig_file);
return 1;
}
} else if (input_mode != listnewconfig) { //执行此处
if (conf_write(NULL)) { //将新的配置写入到.config中
fprintf(stderr, _("\n*** Error during writing of the configuration.\n\n"));
exit(1);
}
}
return 0;
}
scripts/kconfig/conf --defconfig=arch/../configs/imx8qxp_mek_defconfig Kconfig的主要作用就是读取Kconfig的默认配置,根据
arch/../configs/imx8qxp_mek_defconfig更新配置关系链表,最后把新的配置写入到.config文件中