如何为项目引入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

相关推荐
2401_857622661 小时前
SpringBoot框架下校园资料库的构建与优化
spring boot·后端·php
2402_857589361 小时前
“衣依”服装销售平台:Spring Boot框架的设计与实现
java·spring boot·后端
哎呦没2 小时前
大学生就业招聘:Spring Boot系统的架构分析
java·spring boot·后端
_.Switch3 小时前
Python Web 应用中的 API 网关集成与优化
开发语言·前端·后端·python·架构·log4j
杨哥带你写代码4 小时前
足球青训俱乐部管理:Spring Boot技术驱动
java·spring boot·后端
AskHarries5 小时前
读《show your work》的一点感悟
后端
A尘埃5 小时前
SpringBoot的数据访问
java·spring boot·后端
yang-23075 小时前
端口冲突的解决方案以及SpringBoot自动检测可用端口demo
java·spring boot·后端
Marst Code5 小时前
(Django)初步使用
后端·python·django
代码之光_19805 小时前
SpringBoot校园资料分享平台:设计与实现
java·spring boot·后端