如何为项目引入Kconfig配置系统

前情提要

项目中经常会有通过宏配置或选择参数:

c 复制代码
#ifdef CFG_ENABLE
#define CFG_ARGS    "test"
void printf_args(void)
{
    printf("args: %s\n", CFG_ARGS);
}
#endif

当项目规模较小,配置项和依赖关系相对简单时,我们可以通过手动修改源代码来实现配置功能。但是,随着项目规模的增长和配置复杂度的增加,这种方式也会出现一些问题。

随着代码体量和调用关系的增多,对配置者来说很难完全熟悉代码结构及各模块之间的依赖关系。同时,如果配置项设置较为随意且缺乏约束,也很可能导致错误配置。这对项目质量和维护都带来一定难度。

对于规模较大的项目来说,需要一套专业的配置管理系统来解决这些问题。Kconfig正是为了应对这种需求而产生的。它通过配置脚本定义各配置选项及其依赖关系,并提供图形化界面供配置者操作。同时还会检查配置合理性,帮助我们实现定制化构建的同时防止错误配置

如果有接触过Linux内核或者嵌入式操作系统RTTHREAD等,相信对Kconfig系统都不陌生。Kconfig是Linux内核和许多其他系统广泛使用的一款配置管理工具。它可以让开发人员在编译时选择性地包含或排除某些功能模块。

Kconfig 使用配置脚本定义各种配置选项及其依赖关系。通过图形或字符型用户界面,开发者可以查看并设置各种配置。然后Kconfig会生成 .config 文件保存选择结果。在编译的时候,会根据 .config 文件里设置的符号自动包含或排除对应的源代码。

环境搭建

验证 python 环境

Kconfig依赖于 python ,如果没有 python 环境请自行安装。

在命令行中使用所示命令验证:

cmd 复制代码
python --version

显示(正确显示版本即可):

cmd 复制代码
Python 3.11.4

安装Kconfig

cmd 复制代码
python -m pip install windows-curses
python -m pip install kconfiglib

在命令行中使用所示命令验证:

cmd 复制代码
menuconfig -h

显示信息即安装成功。

C语言头文件生成脚本

Kconfiglib 生成的是 .config 文件,并非C语言文件,需要使用脚本生成,将以下代码复制到文件中并命名为kconfig.py

python 复制代码
import os
import re
import sys
import textwrap

from kconfiglib import Kconfig, split_expr, expr_value, expr_str, BOOL, \
                       TRISTATE, TRI_TO_STR, AND, OR

def generate_config(kconfig_file,config_in, config_out, header_out):

    print("Parsing " + kconfig_file)
    kconf = Kconfig(kconfig_file, warn_to_stderr=False, 
                    suppress_traceback=True)

    # Load config files
    print(kconf.load_config(config_in))

    # Write merged config        
    print(kconf.write_config(config_out))
    
    # Write headers
    print(kconf.write_autoconf(header_out))

    with open(header_out, 'r+') as header_file:

        content = header_file.read()
        header_file.truncate(0)
        header_file.seek(0)
        
        # Remove CONFIG_ and MR_USING_XXX following number
        content = content.replace("#define CONFIG_", "#define ")

        # Add the micro
        header_file.write("#ifndef _CONFIG_H_\n") 
        header_file.write("#define _CONFIG_H_\n\n")
        
        header_file.write("#ifdef __cplusplus\n")
        header_file.write("extern \"C\" {\n") 
        header_file.write("#endif /* __cplusplus */\n\n")

        # Write back the original data
        header_file.write(content)

        # Add the micro
        header_file.write("\n#ifdef __cplusplus\n")
        header_file.write("}\n")
        header_file.write("#endif /* __cplusplus */\n\n")
        header_file.write("#endif /* _CONFIG_H_*/\n")

def main():
    kconfig_file = 'Kconfig' 
    config_in = '.config'
    config_out = '.config'
    header_out = 'config.h'
    generate_config(kconfig_file, config_in, config_out, header_out)

if __name__ == "__main__":
    main()

修改main函数中header_out 可修改生成的函数文件名。此脚本去除了Kconfig默认添加的CONFIG_前缀,并为其加上了_CONFIG_H_C声明。

Kconfig语法

具体语法请参考其他文章,此文主讲如何搭建。

应用

创建Kconfig

新建一个名字为 Kconfig 的文件(注意没有后缀名),和上一步中中创建的 kconfig.py 的文件放在一起。

Kconfig 复制代码
mainmenu "Demo"

menu "Args configure"
config CFG_ARG1
    bool "Enable arg1"
    default n
    
config CFG_ARG2
	int "Arg2 number"
	default 8
	range 0 64

endmenu

在当前目录下调用命令行,输入:

cmd 复制代码
menuconfig

就可以看到我们刚刚写的Demo界面

回车后就可以看到配置的2个参数:

设置的范围也在输入时生效了:

配置完成后按Q退出,Y保存配置。

在当前目录下调用命令行,输入:

cmd 复制代码
python kconfig.py

运行 python 脚本生成.h文件。

运行结果:

cmd 复制代码
Parsing Kconfig
Loaded configuration '.config'
Configuration saved to '.config'
Kconfig header saved to 'config.h'

显示生成config.h成功。打开这个文件:

Kconfig搭建完成

代码仓库链接,如果觉得教程不错请帮忙点一个star

相关推荐
tan180°2 小时前
MySQL表的操作(3)
linux·数据库·c++·vscode·后端·mysql
AI生存日记3 小时前
百度文心大模型 4.5 系列全面开源 英特尔同步支持端侧部署
人工智能·百度·开源·open ai大模型
优创学社23 小时前
基于springboot的社区生鲜团购系统
java·spring boot·后端
why技术3 小时前
Stack Overflow,轰然倒下!
前端·人工智能·后端
幽络源小助理3 小时前
SpringBoot基于Mysql的商业辅助决策系统设计与实现
java·vue.js·spring boot·后端·mysql·spring
步、步、为营4 小时前
.net开源库SignalR
开源·.net
ai小鬼头4 小时前
AIStarter如何助力用户与创作者?Stable Diffusion一键管理教程!
后端·架构·github
简佐义的博客5 小时前
破解非模式物种GO/KEGG注释难题
开发语言·数据库·后端·oracle·golang
Code blocks5 小时前
使用Jenkins完成springboot项目快速更新
java·运维·spring boot·后端·jenkins