Kconfig: autoconf.h 的生成
1. 前言
限于作者能力水平,本文可能存在谬误,因此而给读者带来的损失,作者不做任何承诺。
2. autoconf.h 的生成
本文以 busybox 生成 autoconf.h 的过程为例,说明 Kconfig 生成 autoconf.h 的过程。
# busybox/Makefile
# If .config is newer than include/autoconf.h, someone tinkered
# with it and forgot to run make oldconfig.
# If kconfig.d is missing then we are probarly in a cleaned tree so
# we execute the config step to be sure to catch updated Kconfig files
include/autoconf.h: .kconfig.d .config $(wildcard $(srctree)/*/*.c) $(wildcard $(srctree)/*/*/*.c) | gen_build_files
$(Q)$(MAKE) -f $(srctree)/Makefile silentoldconfig
调用 busybox/scripts/kconfig/{*.c,*.h} 生成的 conf 程序生成 autoconf.h(.tmpconfig.h -> autoconf.h):
# busybox/scripts/kconfig/Makefile
silentoldconfig: $(obj)/conf
$< -s Config.in
$(MTIME_IS_COARSE) && sleep 1
busybox 的编译过程会对每一个配置项生成两个宏到 autoconf.h,如 busybox/networking/Config.in 中的配置:
config FEATURE_IFUPDOWN_IP
bool "Use ip tool (else ifconfig/route is used)"
default y
depends on IFUP || IFDOWN
help
Use the iproute "ip" command to implement "ifup" and "ifdown", rather
than the default of using the older "ifconfig" and "route" utilities.
If Y: you must install either the full-blown iproute2 package
or enable "ip" applet in Busybox, or the "ifup" and "ifdown" applets
will not work.
If N: you must install either the full-blown ifconfig and route
utilities, or enable these applets in Busybox.
在 include/autoconf.h 中生成:
...
#undef CONFIG_FEATURE_IFUPDOWN_IP
#define ENABLE_FEATURE_IFUPDOWN_IP 0
...
具体生成代码为 busybox/scripts/kconfig/confdata.c 中的函数 conf_write():
int conf_write(const char *name)
{
...
menu = rootmenu.list;
while (menu) {
sym = menu->sym;
if (!sym) {
...
} else if (!(sym->flags & SYMBOL_CHOICE)) {
...
type = sym->type;
...
switch (type) {
case S_BOOLEAN:
case S_TRISTATE:
switch (sym_get_tristate_value(sym)) {
case no:
fprintf(out, "# CONFIG_%s is not set\n", sym->name);
if (out_h) {
fprintf(out_h, "#undef CONFIG_%s\n", sym->name);
/* bbox */
fprintf(out_h, "#define ENABLE_%s 0\n", sym->name);
fprintf(out_h, "#define IF_%s(...)\n", sym->name);
fprintf(out_h, "#define IF_NOT_%s(...) __VA_ARGS__\n", sym->name);
}
break;
case mod:
fprintf(out, "CONFIG_%s=m\n", sym->name);
if (out_h)
fprintf(out_h, "#define CONFIG_%s_MODULE 1\n", sym->name);
break;
case yes:
fprintf(out, "CONFIG_%s=y\n", sym->name);
if (out_h) {
fprintf(out_h, "#define CONFIG_%s 1\n", sym->name);
/* bbox */
fprintf(out_h, "#define ENABLE_%s 1\n", sym->name);
fprintf(out_h, "#ifdef MAKE_SUID\n");
fprintf(out_h, "# define IF_%s(...) __VA_ARGS__ \"CONFIG_%s\"\n", sym->name, sym->name);
fprintf(out_h, "#else\n");
fprintf(out_h, "# define IF_%s(...) __VA_ARGS__\n", sym->name);
fprintf(out_h, "#endif\n");
fprintf(out_h, "#define IF_NOT_%s(...)\n", sym->name);
}
break;
}
break;
case S_STRING:
// fix me
str = sym_get_string_value(sym);
fprintf(out, "CONFIG_%s=\"", sym->name);
if (out_h)
fprintf(out_h, "#define CONFIG_%s \"", sym->name);
do {
l = strcspn(str, "\"\\");
if (l) {
fwrite(str, l, 1, out);
if (out_h)
fwrite(str, l, 1, out_h);
}
str += l;
while (*str == '\\' || *str == '"') {
fprintf(out, "\\%c", *str);
if (out_h)
fprintf(out_h, "\\%c", *str);
str++;
}
} while (*str);
fputs("\"\n", out);
if (out_h) {
fputs("\"\n", out_h);
/* bbox */
fprintf(out_h, "#define ENABLE_%s 1\n", sym->name);
fprintf(out_h, "#ifdef MAKE_SUID\n");
fprintf(out_h, "# define IF_%s(...) __VA_ARGS__ \"CONFIG_%s\"\n", sym->name, sym->name);
fprintf(out_h, "#else\n");
fprintf(out_h, "# define IF_%s(...) __VA_ARGS__\n", sym->name);
fprintf(out_h, "#endif\n");
fprintf(out_h, "#define IF_NOT_%s(...)\n", sym->name);
}
break;
case S_HEX:
str = sym_get_string_value(sym);
if (str[0] != '0' || (str[1] != 'x' && str[1] != 'X')) {
fprintf(out, "CONFIG_%s=%s\n", sym->name, str);
if (out_h) {
fprintf(out_h, "#define CONFIG_%s 0x%s\n", sym->name, str);
/* bbox */
fprintf(out_h, "#define ENABLE_%s 1\n", sym->name);
fprintf(out_h, "#ifdef MAKE_SUID\n");
fprintf(out_h, "# define IF_%s(...) __VA_ARGS__ \"CONFIG_%s\"\n", sym->name, sym->name);
fprintf(out_h, "#else\n");
fprintf(out_h, "# define IF_%s(...) __VA_ARGS__\n", sym->name);
fprintf(out_h, "#endif\n");
fprintf(out_h, "#define IF_NOT_%s(...)\n", sym->name);
}
break;
}
case S_INT:
str = sym_get_string_value(sym);
if (!str[0])
str = "0";
fprintf(out, "CONFIG_%s=%s\n", sym->name, str);
if (out_h) {
fprintf(out_h, "#define CONFIG_%s %s\n", sym->name, str);
/* bbox */
fprintf(out_h, "#define ENABLE_%s 1\n", sym->name);
fprintf(out_h, "#ifdef MAKE_SUID\n");
fprintf(out_h, "# define IF_%s(...) __VA_ARGS__ \"CONFIG_%s\"\n", sym->name, sym->name);
fprintf(out_h, "#else\n");
fprintf(out_h, "# define IF_%s(...) __VA_ARGS__\n", sym->name);
fprintf(out_h, "#endif\n");
fprintf(out_h, "#define IF_NOT_%s(...)\n", sym->name);
}
break;
}
}
...
}
...
}

浙公网安备 33010602011771号