Skip to main content
 首页 » 操作系统

Linux 驱动模块(5)_autoconf.h

2022年07月19日178cloudgamer

1. autoconf.h文件

       老版本的Linux内核中,执行 make menuconfig 后,编译系统会去  defconfig 文件中读取默认配置,然后把所有的配置信息保存到源码顶层目录下的 .config 文件中,然后将 .config 中的内容转换为C语言能识别的宏定义更新到编译目录下的 include/generated 目录下的 autoconf.h文件中。比如会将CONFIG_XXX = y 的定义转换为 #define CONFIG_XXX 1 的模式写到 autoconf.h 文件当中,CONFIG_XXX = m 的定义转换为 #define CONFIG_XXX_MODULE 1 的模式写到 autoconf.h 文件当中。autoconf.h文件是被自动包含,不需要C代码文件中显式包含。在内核源码的根目录下的Makefile中实现了自动包含,顶层Makefile中相关的内容如下:

# Use LINUXINCLUDE when you must reference the include/ directory. 
# Needed to be compatible with the O= option 
LINUXINCLUDE := -I$(srctree)/arch/$(hdr-arch)/include -Iarch/$(hdr-arch)/include/generated  -Iinclude $(if $(KBUILD_SRC), -I$(srctree)/include)  -include include/generated/autoconf.h  
...... 
export KBUILD_CPPFLAGS NOSTDINC_FLAGS LINUXINCLUDE OBJCOPYFLAGS LDFLAGS

在 LINUXINCLUDE 赋值的最后一行包含了autoconf.h文件,然后通过 export 导出给其它的Makefile文件使用

新内核中(4.14)中$(Q)test -e include/generated/autoconf.h

注意:在Makefile文件中统一使用 CONFIG_XXX,就算是编译成模块,也是 obj-$(CONFIG_XXX) 而不是 obj-$(CONFIG_XXX_MODULE)。但是若是编译成模块,在生成的 autoconf.h 中就变成了#define CONFIG_XXX_MODULE 1 了。

2. 代码中使用生成的宏做判断

// kconfig.h 
 
/* 
 * IS_BUILTIN(CONFIG_FOO) evaluates to 1 if CONFIG_FOO is set to 'y', 0 
 * otherwise. For boolean options, this is equivalent to 
 * IS_ENABLED(CONFIG_FOO). 
 */ 
#define IS_BUILTIN(option) __is_defined(option) 
 
/* 
 * IS_MODULE(CONFIG_FOO) evaluates to 1 if CONFIG_FOO is set to 'm', 0 
 * otherwise. 
 */ 
#define IS_MODULE(option) __is_defined(option##_MODULE) 
 
/* 
 * IS_REACHABLE(CONFIG_FOO) evaluates to 1 if the currently compiled 
 * code can call a function defined in code compiled based on CONFIG_FOO. 
 * This is similar to IS_ENABLED(), but returns false when invoked from 
 * built-in code when CONFIG_FOO is set to 'm'. 
 */ 
#define IS_REACHABLE(option) __or(IS_BUILTIN(option), __and(IS_MODULE(option), __is_defined(MODULE))) 
 
/* 
 * IS_ENABLED(CONFIG_FOO) evaluates to 1 if CONFIG_FOO is set to 'y' or 'm', 0 otherwise. 
 */ 
#define IS_ENABLED(option) __or(IS_BUILTIN(option), IS_MODULE(option))

使用 #if IS_ENABLED(XXX) 就等于 __is_defined(XXX) || __is_defined(XXX_MODULE), 无论编译进内核还是编译成模块都有效。


本文参考链接:https://www.cnblogs.com/hellokitty2/p/9101744.html