通常在kernel或uboot中, 有很多以CONFIG_*开头的宏配置选项,并且保存在相应的头文件中,那么这些CONFIG_*是怎么生成的呢?
在uboot的顶层Makefile中,有这么一项:
此段的作用就是将相关头文件中的宏CONFIG_*保存在include/autoconf.mk中。
涉及两个大类:
1. gcc 的预处理选项:-dM
不做实际的预处理,仅仅列出所有#define的宏,这些宏大部分与体系结构和GNU相关,或来自所包含的头文件。
2.sed
通过sed,将所有输出的宏过滤,得到需要的宏。
示例:
test.h
1 #include <stdio.h> 2 #define CONFIG_SERIAL_MULTI 1 3 # define CONFIG_AAA 4 #define CONFIG_CACHE_LINE_SIZE (64) 5 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) 6 #define ROUND(a,b) (((a) + (b) - 1) & ~((b) - 1)) 7 #define CONFIG_HAS_POST 8 #define CONFIG_____ 9 #define CONFIG_a "HELLO WORLD" 10 #define CONFIG_B "123"
define2mk.sed
# # Sed script to parse CPP macros and generate output usable by make # # It is expected that this script is fed the output of 'gpp -dM' # which preprocesses the common.h header files and outputs the final # list of CPP macros (and whitespace is sanitized) # # Only process values prefixed with #define CONFIG_ /^#define CONFIG_[A-Za-z0-9_][A-Za-z0-9_]*/ { ## Strip the #define prefix s/#define *//; # Change to form CONFIG_*=VALUE s/ */=/; ## Drop trailing spaces s/ *$//; ## drop quotes around string values s/="(.*)"$/=1/; ## Concatenate string values s/" *"//g; ## Assume strings as default - add quotes around values s/=(..*)/="1"/; ## but remove again from decimal numbers s/="([0-9][0-9]*)"/=1/; ## ... and from hex numbers s/="(0[Xx][0-9a-fA-F][0-9a-fA-F]*)"/=1/; ## Change '1' and empty values to "y" (not perfect, but ## supports conditional compilation in the makefiles s/=$/=y/; s/=1$/=y/; # print the line p }
执行gcc -E -dM test.h | sed -n -f define2mk.sed,得到
对于define2mk.sed的说明:
-f <script文件>或--file=<script文件>:以选项中指定的script文件来处理输入
-n 仅显示<script>处理后的结果,如果没有加上这个选项,没有被处理的输入行也会被输出。
/^#define CONFIG_[A-Za-z0-9_][A-Za-z0-9_]*/---这一部分表示由 #define CONFIG_[任意字母数字下划线][任意字母数字下划线]的任意字符串开头的宏定义 将会被替换处理