.config
文件产生.config
文件的产生, 添加自己的配置当我们执行sudo make ARCH=arm vexpress_defconfig
命令行后,make会进入顶层Makefile文件,执行下面的语句. 而%config依赖scripts_basic
和 ouputmakefile
, 所以我问首先去看scripts_basic
#SRCARCH := arm
SRCARCH := $(ARCH)
#include arch/arm/Makefile
include arch/$(SRCARCH)/Makefile
%config: scripts_basic outputmakefile FORCE
$(Q)$(MAKE) $(build)=scripts/kconfig $@
在顶层Makefile中会发现如下代码段
scripts_basic:
$(Q)$(MAKE) $(build)=scripts/basic
$(Q)rm -f .tmp_quiet_recordmcount
make 直接执行命令行$(Q)$(MAKE) $(build)=scripts/basic
, 展开后得到下面的片段,默认目标是all
#build := -f $(srctree)/scripts/Makefile.build obj
$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.build obj=scripts/basic
将Makefile.build
, 展开后得到下面的语句.其中dir=.
中的"."
,是make进入Makefile.build
的目录./tools/build/
PHONY := __build
__build:
src := scripts/basic
include scripts/Kbuild.include
# For backward compatibility check that these variables do not change
save-cflags := $(CFLAGS)
#kbuild-dir := ./scripts/basic
kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src))
#kbuild-file := ./scripts/basic/Makefile
kbuild-file := $(if $(wildcard $(kbuild-dir)/Kbuild),$(kbuild-dir)/Kbuild,$(kbuild-dir)/Makefile)
#include ./scripts/basic/Makefile
include $(kbuild-file)
ifneq ($(hostprogs-y)$(hostprogs-m)$(hostlibs-y)$(hostlibs-m)$(hostcxxlibs-y)$(hostcxxlibs-m),)
include scripts/Makefile.host
endif
__build: $(if $(KBUILD_BUILTIN),$(builtin-target) $(lib-target) $(extra-y)) \
$(if $(KBUILD_MODULES),$(obj-m) $(modorder-target)) \
$(subdir-ym) $(always)
@:
我们查看下./scripts/basic/Makefile
内容
hostprogs-y := fixdep
hostprogs-$(CONFIG_BUILD_BIN2C) += bin2c
always := $(hostprogs-y)
#scripts/basic/bin2c: scripts/basic/fixdep
$(addprefix $(obj)/,$(filter-out fixdep,$(always))): $(obj)/fixdep
从上面我们得知hostprogs-y := fixdep, 不为空,接着继续执行命令行.include scripts/Makefile.host
ifneq ($(hostprogs-y)$(hostprogs-m)$(hostlibs-y)$(hostlibs-m)$(hostcxxlibs-y)$(hostcxxlibs-m),)
include scripts/Makefile.host
endif
当Make将Makefile.host
和Makefile
包含进来后,就会执行默认的目标__build
, 而__build
依赖 $(always)
, 即fixdep
,
而Makefile.host就是去产生fixdep
__hostprogs := $(sort $(hostprogs-y) $(hostprogs-m))
# C code
# host-csingle := fixdep
host-csingle := $(foreach m,$(__hostprogs), \
$(if $($(m)-objs)$($(m)-cxxobjs)$($(m)-sharedobjs),,$(m)))
#host-csingle := scripts/basic/fixdep
host-csingle := $(addprefix $(obj)/,$(host-csingle))
hostc_flags = -Wp,-MD,$(depfile) $(__hostc_flags)
#####
# Compile programs on the host
# Create executable from a single .c file
# host-csingle -> Executable
quiet_cmd_host-csingle = HOSTCC $@
cmd_host-csingle = $(HOSTCC) $(hostc_flags) -o $@ $< \
$(HOST_LOADLIBES) $(HOSTLOADLIBES_$(@F))
#产生fixdep
$(host-csingle): $(obj)/%: $(src)/%.c FORCE
$(call if_changed_dep,host-csingle)
当fixdep完了后,make就返回执行第二个依赖outputmakefile
,目前没有对KBUILD_SRC
赋值,所以没有执行任何语句
outputmakefile:
ifneq ($(KBUILD_SRC),)
$(Q)ln -fsn $(srctree) source
$(Q)$(CONFIG_SHELL) $(srctree)/scripts/mkmakefile \
$(srctree) $(objtree) $(VERSION) $(PATCHLEVEL)
endif
当make将所有的依赖scripts_basic
和outputmakefile
都产生了,就去执行命令行$(Q)$(MAKE) $(build)=scripts/kconfig $@
,展开后得到, 目标是vexpress_defconfig
$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.build obj=scripts/kconfig smdk5250_defconfig
PHONY := __build
__build:
src := scripts/kconfig
include scripts/Kbuild.include
# For backward compatibility check that these variables do not change
save-cflags := $(CFLAGS)
#kbuild-dir := ./scripts/kconfig
kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src))
#kbuild-file := ./scripts/kconfig/Makefile
kbuild-file := $(if $(wildcard $(kbuild-dir)/Kbuild),$(kbuild-dir)/Kbuild,$(kbuild-dir)/Makefile)
#include ./scripts/kconfig/Makefile
include $(kbuild-file)
ifneq ($(hostprogs-y)$(hostprogs-m),)
include scripts/Makefile.host
endif
从上面可以看出需要scripts/kconfig/Makefile
, 其内容如下, 这里的SRCARCH:=arm
ifdef KBUILD_KCONFIG
Kconfig := $(KBUILD_KCONFIG)
else
Kconfig := Kconfig
endif
%_defconfig: $(obj)/conf
@echo "eric_debug----------------start "$@
#scripts/kconfig/conf --defconfig=arch/arm/configs/vexpress_defconfig Kconfig
$(Q)$< $(silent) --defconfig=arch/$(SRCARCH)/configs/$@ $(Kconfig)
@echo "eric_debug----------------end "$@
conf-objs := conf.o zconf.tab.o
hostprogs-y := conf nconf mconf kxgettext qconf gconf
可以看出%_defconfig
依赖 conf
,所以应该首先产生conf
, conf的产生会促使nconf mconf kxgettext qconf gconf
的产生,其原理和fixdep
产生一样,都需要借助Makefile.host
,不做解释了
当conf产生后就需要执行命令行$(Q)$< $(silent) --defconfig=arch/$(SRCARCH)/configs/$@ $(Kconfig)
, 展开后得到
scripts/kconfig/conf --defconfig=arch/arm/configs/vexpress_defconfig Kconfig
我们分析下此时此刻的conf.c
NOTE: getopt_long method
int main(int ac, char **av)
{
while ((opt = getopt_long(ac, av, "s", long_opts, NULL)) != -1) {
input_mode = (enum input_mode)opt;
switch (opt) {
case defconfig:
//defconfig_file = smdk5250_defconfig
defconfig_file = optarg;
break;
}
}
switch (input_mode) {
case defconfig:
//将smdk5250_defconfig中内容读入
if (conf_read(defconfig_file)) {...}
break;
}
switch (input_mode) {
case defconfig:
//设置新的symbols
conf_set_all_new_symbols(def_default);
break;
}
//写入---
if (conf_write(NULL)) {...}
}
最终通过conf_write将信息写入.config中
int conf_write(const char *name)
{
FILE *out;
struct symbol *sym;
struct menu *menu;
const char *basename;
const char *str;
char dirname[PATH_MAX+1], tmpname[PATH_MAX+1], newname[PATH_MAX+1];
char *env;
/*
const char *conf_get_configname(void)
{
char *name = getenv("KCONFIG_CONFIG");
return name ? name : ".config";
}
*/
//文件.config的由来
basename = conf_get_configname();
sprintf(newname, "%s%s", dirname, basename);
conf_write_heading(out, &kconfig_printer_cb, NULL);
menu = rootmenu.list;
while (menu) {...}
fclose(out);
//最终看见的信息
conf_message(_("configuration written to %s"), newname);
}
当make生成.config后,整个sudo make ARCH=arm vexpress_defconfig
, 就执行完了,但是如何添加自己的编译选项和文件到Makefile
中呢?
以drivers/usb/host为例
(1) 首先我们找到该目录下的Kconfig, 然后添加下面的语句
config USB_ERIC_DEBUG
bool "eric_debug usb support"
#默认是开启的,没有任何依赖
default y
(2) 然后在drivers/usb/host/
目录下添加eric_debug_usb.c
并且在 drivers/usb/host/Makefile
中添加下面的语句,
obj-$(CONFIG_USB_ERIC_DEBUG) += eric_debug_usb.o
Note: Makefile
中CONFIG_USB_ERIC_DEBUG
中 CONF_
后的字符串(USB_ERIC_DEBUG
)一定要和 Kconfig
中USB_ERIC_DEBUG
一样,
我们直接看看编译的部分结果(vmlinux
), 如下所示
.config
文件的产生以及怎样添加自己的文件,已经讲完了.请移步Linux Kernel编译流程(二)—vmlinux
的产生