Kconfig,.config,Makefile的关系

 

2016年5月23日 
一.通过Kconfig控制我们的模块编译 
通常我们编写完驱动code后,还需要将驱动加入到内核当中来,此时要明确两点目标: 
1:我们需要控制是否需要将驱动加入编译链接 
2:我们要决定是将驱动直接编译进内核还是将驱动编译为内核 
上面这两点都是需要在Makefile中去进行配置的,例如我们的驱动是my_driver.c那么我们在Makefile中的对他的编译命令就是: 
obj-y += my_driver.o #编译进内核 
obj-m += my_driver.o #编译为驱动模块,即.ko文件 
obj-n += my_driver.o #不进行编译 
如果我们要灵活的配值它们,则可以使用一个变量去控制即:

CONFIG_MODULE = y或者
CONFIG_MODULE = m或者
CONFIG_MODULE = n
obj-$(CONFIG_MODULE) += mydriver.o

这样我们可以通过在Makefile里面改变量来控制编译的进行,但是这种方式和第一种方式对比并没有什么便利的地方。 
此时我们可以使用Kconfig文件 
在Kconfig文件中定义:CONFIG MODULE(具体要遵循Kconfig的语法),我们通过Make menuconfig来配置MODULE的属性 
当执行Make menuconfig后会由autoconfig工具(脚本)生成一个配置文件config.in文件,这个脚本会将Kconfig中的使用 
CONFIG定义的变量(eg: CONFIG MODULE)转换为CONFIG_XX (eg:CONFIG_MODULE),并且将选择的属性赋值给这个新变量 
CONFIG_XX = y 或者 
CONFIG_XX = m 或者 
CONFIG_XX = n 
eg: CONFIG_MODULE = y 

配置完成生成这个.config文件后,在编译的时候会层层调用到我们这一级的Makefile去编译,此时我们的Makefile会自动的读取我们当前目录的.config文件 
从而获取这个 
obj-$(CONFIG_MODULE) += mydriver.o 
CONFIG_MODULE 的变量的属性,这样就很方便,每次编译之前通过图形界面就可以配置一次,然后再编译 
所以Makefile中的变量是要和.config中的这个值保持一致 
二.通过Kconfig控制我们的程序中(.c中)的宏的开启 
有的时候我们希望在程序中使用一些宏来控制我们的程序,但我们希望这个宏不是在驱动本地被定义,最好是作为一种半自动化的,不需要我们在本地去开启关闭这个宏。 
大概有两种思路: 

1.在makefile中向程序传入这个值。 
2,使用kconfig来向程序中传入这个值。 
这里我们总结下第二种即配置menuconfig的方式去关联的控制我们程序中宏的开启和关闭 
使用第二种的原因是,在Kconfig中定义的宏在.c中使用的时候是全局的,在任何一个.c文件中都可以使用。 
在上面的已经知道了通过书写Kconfig来控制menuconfig的显示效果,通过配置menuconfig来生成.config文件,它的格式是:

  1. CONFIG_MXL331=y
  2. # CONFIG_SHARP_VZ7306 is not set

其实在make menuconfig的时候我们还生成了一个\include\generated\Autoconf.h文件,它的格式是: #define CONFIG_MXL331 1 我想之所以能够在.c中全局的使用这个宏,就是因为生成的这个Autoconf.h文件,这个.h被很多文件层层包含成为一个全局的文件安。 例如在配置完Kconfig文件后,生成的.config文件中 CONFIG_MXL331=y 和Autoconf.h中 #define CONFIG_MXL331 1 我们就可以在任意的.c中使用

  1. #ifdef CONFIG_MXL331`
  2. xxxxx
  3. #endif

这样我们就可以通过去配置menuconfig在最外层来控制这些宏的开启和关闭。 
三.续篇:Kconfig文件中什么样的宏才可以成为我们最终在.config中的控制宏 
这个问题其实和Kconfig的语法有关系,如果清楚语法这个就不是问题,我还是给自己总结一下吧

  1. menuconfig DVB_SUPPORT
  2. bool "NIM Driver For LEO App" //如果在页面选上"NIM Driver For LEO App,则.config中 CONFIG_DVB_SUPPORT = y
  3. help
  4. NIM Driver Selection.
  5.  
  6. if DVB_SUPPORT
  7.  
  8. menuconfig DVBS_DVBS2
  9. tristate "DVBS_DVBS2 Demod Driver Selection" //相当于 NIM Driver For LEO App目录的二级目录,若选中,CONFIG_DVBS_DVBS2 = y,使用tristate表示该级可以选为M/Y/N
  10. depends on DVB_SUPPORT
  11. help
  12. This provides NIM driver for DVBS_DVBS2.
  13.  
  14. config LEO_DVBS_COMMON
  15. bool
  16. depends on DVBS_DVBS2 //若NIM Driver For LEO App选中,则CONFIG_DVBS_DVBS2 = y,而LEO_DVBS_COMMON依赖于DVBS_DVBS2 ,此时CONFIG_LEO_DVBS_COMMON = y。
  17. help
  18. This provides dvbs demod common file.
  19.  
  20. config M3533
  21. tristate "Support LEO M3533 Demod Driver"
  22. depends on DVBS_DVBS2
  23. select LEO_DVBS_COMMON //若选中Support LEO M3533 Demod Driver,则CONFIG_M3533 = y,CONFIG_LEO_DVBS_COMMON = y
  24. help
  25. This provides m3501 demod driver.

四,反选依赖 

当有这种同级之间,若选中A则B不被选中这种反逻辑(通常逻辑都是B依赖A)此时可以这样写:

  1. config A
  2. bool XXX
  3. depends on !B

同时Kconfig中也支持if语句例如:if A 除了直接使用depend on 表明依赖关系外也可以这样:

  1. menuconfig ARCH_MVEBU
  2. bool "Marvell Engineering Business Unit (MVEBU) SoCs" if (ARCH_MULTI_V7 || ARCH_MULTI_V5) //如果ARCH_MULTI_V7 || ARCH_MULTI_V5被选中的话,才会去显示
  3. "Marvell Engineering Business Unit (MVEBU) SoCs"同时ARCH_MVEBU有效
  4. select ARCH_SUPPORTS_BIG_ENDIAN
  5. select CLKSRC_MMIO
  6. if ARCH_MVEBU //也可以直接在内部这样判断
  7.  
  8. config MACH_MVEBU_ANY //这种是默认选择的,在界面中是找不到的,想找到有两种方法:1.随便写上bool中的内容这样就会有显示。 2.在顶层.config中查找这个config是否被选中
  9. bool
  10.  
  11. config MACH_MVEBU_V7
  12. bool
  13. select ARMADA_370_XP_TIMER
  14. select CACHE_L2X0
  15. select ARM_CPU_SUSPEND
  16. select MACH_MVEBU_ANY
  17.  
  18. endif

五.comment的用法:类似一个说明和注释

  1. menu "Multiple platform selection"
  2. depends on ARCH_MULTIPLATFORM
  3.  
  4. comment "CPU Core family selection"
  5.  
  6. config ARCH_MULTI_V4
  7. bool "ARMv4 based platforms (FA526)"
  8. depends on !ARCH_MULTI_V6_V7
  9. select ARCH_MULTI_V4_V5
  10. select CPU_FA526
  11.  
  12. config ARCH_MULTI_V6_V7
  13. bool
  14. select MIGHT_HAVE_CACHE_L2X0
  15. endmenu

commnet的效果:

  1. ----------------------------------------------------------     
  2.  *** CPU Core family selection ***
  3. [ ] ARMv6 based platforms (ARM11)
  4. [*] ARMv7 based platforms (Cortex-A, PJ4, Scorpion, Krait)

六:choice的用法:只用于多选一这种情况

  1. choice
  2. prompt "ARM system type"
  3. default ARCH_VERSATILE if !MMU
  4. default ARCH_MULTIPLATFORM if MMU
  5.  
  6. config ARCH_MULTIPLATFORM
  7. bool "Allow multiple platforms to be selected"
  8. depends on MMU
  9. select ARCH_WANT_OPTIONAL_GPIOLIB
  10. select ARM_HAS_SG_CHAIN
  11. config ARCH_GEMINI
  12. bool "Cortina Systems Gemini"
  13. select ARCH_REQUIRE_GPIOLIB
  14. select CLKSRC_MMIO
  15. select CPU_FA526
  16. select GENERIC_CLOCKEVENTS
  17. help
  18. Support for the Cortina Systems Gemini family SoCs
  19. endchoice
  1. | ARM system type (Allow multiple platforms to be selected) --->
  2. 回车进入该项后:
  3. ----------------------- ARM system type -----------------------+
  4. | Use the arrow keys to navigate this window or press the |
  5. | hotkey of the item you wish to select followed by the <SPACE |
  6. | BAR>. Press for additional information about this |
  7. | +-----------------------------------------------------------+ |
  8. | | (X) Allow multiple platforms to be selected | |
  9. | | ( ) ARM Ltd. RealView family | |
  10. | | ( ) ARM Ltd. Versatile family | |
  11. | | ( ) Cirrus Logic CLPS711x/EP721x/EP731x-based | |
  12. | | ( ) Cortina Systems Gemini | |
  13. | | ( ) EBSA-110 | |
  14. | +-----------v(+)--------------------------------------------+ |
  15. +---------------------------------------------------------------+
  16. | <Select> < Help > |
  17. +---------------------------------------------------------------+

七:tristate和bool的区别:

  1. config SI2141
  2. tristate "Support SI2141 tuner driver"
  3. depends on T_MODE
  4. help
  5. This provides a SI2141 tuner driver.
  6. config DCT70701
  7. bool "Support DCT70701 tuner driver"
  8. depends on T_MODE
  9. help
  10. This provides dctT70701 tuner driver.

效果如下:

  1. | | <*> Support SI2141 tuner driver | |
  2. tristate可以将该项选择为M模块或者*编译进内核,选为M时为CONFIG_SI2141=m,选为*时为
  3. CONFIG_SI2141=ymakefile中的编译依赖会去判断依赖是M还是y决定编译为模块还是编译进内核
  4. | | [ ] Support DCT70701 tuner driver | |

bool只有一种选择,即只能为选中和不选中 
八:多级嵌套 
使用menuconfig 
方法1:

  1. menuconifg DVB_SUPPORT
  2. bool "support "
  3. if DVB_SUPPORT
  4. config DVBC
  5. bool "support dvbc"
  6. config DVBS
  7. bool "support dvbs"
  8. endif

 

这种方法一定要有边界,否则解析时有多个menuconfig,没有边界会报错。所以必须使用 if 和 endif,if的判读是menuconifg中定义的宏,这样所有的config定义都依赖于DVB_SUPPORT, 关于menuconfig的边界就很清晰 方法2:

  1. menu "LEO board select"
  2.  
  3. config LEO_M3533_PINMUX
  4. bool "LEO M3533"
  5. config LEO_M3539
  6. bool "LEO M3539"
  7. endmenu

这种方法的边界很清晰,使用menu 和endmenu 
方法3:执行另一个kconfig文件,文件中的方式使用方法1或者方法2 
source "drivers/drivers/modules/mydev/Kconfig"

你可能感兴趣的:(linux知识总结)