曲径通幽论坛

 找回密码
 立即注册
搜索
查看: 6130|回复: 0
打印 上一主题 下一主题

[Kernel] 跟踪 "You have not yet configured your kernel!" 错误

[复制链接]

4918

主题

5880

帖子

3万

积分

GROAD

曲径通幽,安觅芳踪。

Rank: 6Rank: 6

积分
34397
跳转到指定楼层
楼主
发表于 2011-6-29 00:11:27 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
Makefile 对应内核版本:2.6.35.13

在未配置内核时(没有 .config 这样的配置文件) 就执行如 make vmlinux 这样的构建命令会看到下面的错误提示:
$ make vmlinux
/bin/sh: cannot open ncurses.h: No such file
scripts/kconfig/conf -s arch/x86/Kconfig
***
*** You have not yet configured your kernel!
*** (missing kernel config file ".config")
***
*** Please run some configurator (e.g. "make oldconfig" or
*** "make menuconfig" or "make xconfig").
***
make[2]: *** [silentoldconfig] Error 1
make[1]: *** [silentoldconfig] Error 2
make: *** No rule to make target `include/config/auto.conf', needed by `include/config/kernel.release'.  Stop.
下面跟踪上面的出错产生流程。

在执行 make vmlinux 这样的内核目标时,在顶层 Makefile 里 $(dot-config) 变量( dog-config 目标是与 .config 配置相关的或依赖于 .config 文件的构建的目标)会设为 1,这样在顶层 Makefile 的 487 行判断通过:
ifeq ($(dot-config),1)

因为在构建内核时,在 make 处理任何目标之前,它会努力生成 include/cofig/auto.conf 这个文件;在 489 ,494行看到:
[code=Makefile]
489 -include include/config/auto.conf
494 -include include/config/auto.conf.cmd[/mw_shl_code]
这里尝试将 auto.conf 和 auto.conf.cmd 这两个文件包含进来,注意这里用的是 -include ,它表示此时即使现在没有这个 auto.conf 和 autu.conf.cmd,make 也不会理会,它仍然会继续往下走其余的流程。

在 497 行,499-504 行有:
[code=Makefile]
497 $(KCONFIG_CONFIG) include/config/auto.conf.cmd: ;
499 # If .config is newer than include/config/auto.conf, someone tinkered
500 # with it and forgot to run make oldconfig.
501 # if auto.conf.cmd is missing then we are probably in a cleaned tree so
502 # we execute the config step to be sure to catch updated Kconfig files
503 include/config/%.conf: $(KCONFIG_CONFIG) include/config/auto.conf.cmd
504         $(Q)$(MAKE) -f $(srctree)/Makefile silentoldconfig
[/mw_shl_code]
上面的 $(KCONFIG_CONFIG) 变量就是 .config 文件。这里就是说, auto.conf 的生成依赖于 .config 和 auto.conf.cmd 这两个文件。如果 .config 和 auto.conf.cmd 如果比 auto.conf 要新,那么会重新构建 auto.conf 目标,这时会执行底下的语句。实际上这里,即使一个全新的还未配置过的内核,自然不会有 .config 和 auto.conf.cmd 这两个文件。然而,在 497 行我们看到 $(KCONFIG_CONFIG) include/config/auto.conf.cmd: ; 这条语句,它后面有个分号,是个空依赖,它的作用是让 $(KCONFIG_CONFIG) 和  include/config/auto.conf.cmd 这两个目标看起来仍然是最新的(注意,这里的最新和它们是否实际存在并不冲突,当作普通的变量看待即可)。所以,这一定会执行 504 行的命令:$(Q)$(MAKE) -f $(srctree)/Makefile silentoldconfig

为什么这里 -f $(srctree)/Makefile 一下呢?
原因是我们执行的是 make vmlinux 命令,这不是在构建 *config 目标,所以 $(config-targets) 变量为空,那它就不会进到 458-464 行这里来。然而使用 -f 选项再重新走一遍顶层 Makefile ,因为这时是在构建 silentoldconfig 目标(*config) ,所以 $(config-targets) 变量会为 1,从而会进入 462-464 行中来:
[code=Makefile]462 %config: scripts_basic outputmakefile FORCE
463         $(Q)mkdir -p include/linux include/config
464         $(Q)$(MAKE) $(build)=scripts/kconfig $@[/mw_shl_code]
进到这里来后,又看到了 $(Q)$(MAKE) $(build) 命令,这实际是调用 Makefile.build 文件,而在 Makefile.build 中又包含了 scrpits/kconfig/Makefile ,所以自然能够找到 silentoldconfig 这个目标了。

在 scrpits/kconfig/Makefile 中 silentoldconfig 的实现为:
[code=Makefile] 32 silentoldconfig: $(obj)/conf
33         $(Q)mkdir -p include/generated
34         $< -s $(Kconfig)[/mw_shl_code]
从上面可以看到,我们调用  conf 这个程序并以 -s 参数来处理  Kconfig 文件。下面来看一下 conf.c 这个文件中的相关代码片段:
[C++] 纯文本查看 复制代码
while ((opt = getopt(ac, av, "osdD:nmyrh")) != -1) {
        switch (opt) {
        case 'o':
            input_mode = ask_silent;
            break;
        case 's':
            input_mode = ask_silent;
            sync_kconfig = 1;
            break;

在使用 -s 选项时 sync_kconfig 会为 1 ,接着:
[C++] 纯文本查看 复制代码
    if (sync_kconfig) {
        name = conf_get_configname();
        if (stat(name, &tmpstat)) {
            fprintf(stderr, _("***\n"
                "*** You have not yet configured your kernel!\n"
                "*** (missing kernel config file \"%s\")\n"
                "***\n"
                "*** Please run some configurator (e.g. \"make oldconfig\" or\n"
                "*** \"make menuconfig\" or \"make xconfig\").\n"
                "***\n"), name);
            exit(1);
        }
    }

其中 conf_get_configname() 函数在 confdata.c (同在 scripts/kconfig 下) 中实现:
[C++] 纯文本查看 复制代码
const char *conf_get_configname(void)
{
        char *name = getenv("KCONFIG_CONFIG");

        return name ? name : ".config";
}

这里使用 getenv() 函数获取环境变量并存到 name 中,最后返回的是 .config 。然后再用 stat(name, &tmpstat); 测试 .config 文件是否存在,stat() 函数在测试的文件存在时返回 0 ,而这里我们没有对内核配置过,也就是不会产生 .config ,所以 stat() 返回非 0,所以接下来就打印上面的出错信息。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|曲径通幽 ( 琼ICP备11001422号-1|公安备案:46900502000207 )

GMT+8, 2025-6-18 03:15 , Processed in 0.083377 second(s), 23 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表