简介
menuconfig是Linux平台用于管理代码工程、模块及功能的实用工具。上至决定某一程序模块是否编译,下到某一行具体的代码是否需要编译以及某个项的值在本次编译时该是什么都可由menuconfig来定义。
menuconfig的使用方式通常是在编译系统之前在系统源代码根目录下执行 make menuconfig 命令从而打开一个图形化配置界面,再通过对各项的值按需配置从而达到影响系统编译结果的目的。一个典型的 menuconfig 配置界面如下图所示:
menuconfig 配置后的结果将会保存在对应模块根目录下的 .config 文件中。如kernel源码根目录或应用程序源码根目录。Linux在编译系统镜像时会加载这些 .config 文件中的配置项来决定编译结果。
menuconfig 其实只能算是一个“前端”,用于支撑它、决定它拥有什么配置项的“后端”则被称为 Kconfig。
Kconfig 严格来讲是一种编程语言,它拥有自己的语法及结构。正是这些语法和结构组成了menuconfig在用户眼前不同的表现形式。
不过幸好,Kconfig这门“编程语言”的内容很少,通常只需花上半个小时就能掌握大半了。而这篇博文主要也是在介绍Kconfig的知识。
总得来说,menuconfig是Linux平台基于Kconfig用于管控代码实用工具。
常用的Kconfig语法
Kconfig的语法及代码结构非常简单。本博文只介绍Kconfig中常用的几个知识点。更详尽的内容可以参阅Linux官方提供的帮助文档。这份文档们于内核源码目录下的 ./Document/kbuild/kconfig-language.txt 。
所谓 Kconfig,其实就是一个位于要被控制的程序模块源码目录下的文件名为 Kconfig 的普通的文本文件而已。
Kconfig文件在Linux系统中的数量是不确定的。我们既可以将所有配置项写在一个Kconfig文件上,又可以分模块分功能将它们分别写在不同的Kconfig文件中。一般来讲,都是在各个程序或模块的根目录下创建一个Kconfig用于记录所有配置该程序/模块的配置项。然后再在其父级目录的Kconfig中通过 souce absolute_path/Kconfig 的形式将其引入到menuconfig系统中去。
Kconfig常用的一些模块如下所示:
- mainmenu模块
- menu模块
- config模块
- if模块
- choice模块
- comment模块
- source模块
mainmenu模块
在Kconfig中,
mainmenu
是一个重要的配置项,用于定义图形化配置界面中的主菜单名称。所谓主菜单,就是执行make menuconfig
命令后打开的图形化配置界面的主菜单名称。这个主菜单是用户进入配置界面后看到的第一个菜单,通常包含了系统或项目的主要配置选项和子菜单。比如在linux源码顶层有如下内容:
对应主界面的菜单名
更多待补充。
menu模块
如果不是主菜单,那么我们就使用menu就可以了,menu 就是一个纯粹的菜单项,menu本身不可配置,只是用来标记其内部可能拥有子配置项。
比如drivers目录下的Kconfig中
以menu开头,后面加上菜单的描述字符串,用双引号括起来,注意,menu结束时,需要以endmenu作为结尾
这中间的内容就是该菜单里的内容
menu对应的界面如下
它是个菜单项,后面用--->表示,按Enter键可以查看它中间的内容
menu项在.config中会将菜单提示语作为注释一并写入,如下所示:
# #Device Drivers #
更多待补充。
config模块
config模块是Kconfig最基础最重要的知识点。一个config就表示一个配置项。其语法如下所示:
其中,配置项名、配置项类型、配置项提示语是必选的,其他选项按需选择。
配置项名表示最终保存在 .config 文件中的键值对项的键名,通常用全大写和单词之间以下划线隔开的形式书写。
配置项类型就是基础类型,可选的类型有:bool、tristate、string、hex、int。
bool 表示布尔型在.config中以 y 和 n 表示。
tristate是三态类型,通常用在内核驱动控制中。在.config中以 y 、n和m表示。y表示将驱动编译进内核镜像,n表示不编译,m表示将驱动编译为ko形式。
string是普通字符串类型,直接将在menuconfig图形界面中用户输入的值原样保存在.config中。
hex是十六进制形式,只能输入0~F的内容。
int是十进制整数形式,只能输入数字。
配置项提示语以prompt开头,后跟一个空格字符,然后就是用双引号包围的文字提示语。作用就是在menuconfig图形界面中作为配置项的提示语。所以,不要以为我们界面上看到的就是配置项,其实不是的,真正显示的是提示语,而最终写到.config里的,是CONFIG_配置项名,配置项类型决定的是当前宏定义可以赋予什么类型的值。
另外,配置项提示语其实可以和类型合并在一起从而省略 prompt 关键字。以下示例中的两个配置效果是等价的:
我们可以在linux的Kconfig中找到很多config配置项,这也是Kconfig最基本的内容了,比如drivers/i2c下的Kconfig文件里
对应的配置项界面如下所示
如果配置项是 bool、tristate 类型,则通过空格键来切换它们的选项值。其它类型值则通过回车键打开输入框来键入对应的值完成配置。
好了,讲完基础的config,我们就来讲讲这里面的其他选项吧
default
配置项的其它选项中可以通过 default 关键字来配置选项的默认值,如:
if与depends on
if 与 depends on 模块都属于 config 配置项中的”其它选项“。
它们的作用是等价的,都是根据指定的配置项是否被配置来决定本配置项的显示与否。
示例如下:
if
depends on
此配置项表示只有依赖的配置项为y时,才可以配置当前配置项
select
select表示当前配置项被哪些配置项所选择,和if或者depends on是反向的依赖关系,比如
help
在配置项的其它选项中还有一个 help 关键字。它的作用是为配置项添加一个更详细的说明文档。用户在menuconfig图形配置界面通过 ? 键来唤出详细文档的展示。
其语法如下所示:
或者
"help"模块还有一种写法"---help---"
---help---
与help
在功能上没有本质区别,它们都用于定义配置选项的帮助文本。然而,---help---
的使用有助于将文件中的配置逻辑与给开发人员的提示分开,从而提高代码的可读性和可维护性。也就是排版上分割性更好。
if模块
if模块和if选项略有不同,if选项是属于config模块的一部分,而if模块是独立的,类似于C语言里的条件编译,只有某个配置项配置好了,才能配置接下来的内容,比如:
怎么限制包含的范围呢?
类似于menu,我们if模块要以endif结尾
choice模块
choice是单选模块。具体语法如下所示:
注意,要以endchoice来限制范围
在menuconfig中的显示效果如下图所示:
comment模块
Kconfig中还有一个模块被称为 comment,其作用就是单纯的为在其之后的配置项添加注释说明。并且会将说明内容一并写进 .config 文件中。具体效果与上面 2.3 节menu模块的注释一样。
示例:
在menuconfig中的效果如下图所示,前面有三条杠---:
在.config中的效果如下所示:
source模块
source条目用于读取另一个Kconfig文件,一般都是上级目录中的Kconfig包含下级目录中的Kconfig,从而形成层级结构,在menuconfig的体现就是菜单展开
看看dirvers这层目录里的Kconfig
这一层没有任何配置项,全是source导入,导入的都是下一级目录里的Kconfig,在界面上显示就是menu菜单展开后列出各子级目录里Kconfig里的内容。
source就是用来关联各层级Kconfig的。
以上即是menuconfig与Kconfig中最常用的知识点的简要介绍了。更多完整详尽的知识请参阅官方文档。
更多待补充。