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;
			}
		}
		...
	}
	...
}
posted @ 2025-06-13 16:35  JiMoKuangXiangQu  阅读(38)  评论(0)    收藏  举报