Kconfig相关

背景

以前准备写一下Linux内核里的Kconfig,但一直迟迟没有动手,最近在看 Openharmony 相关的东西,发现它也可以通过KconfigKconfiglib进行可视化配置,所以想借此机会在这一起记录一下

作用

#define配置宏主要用来使能/关闭代码,如下面:

#define CONFIG_TEST_ENABLE

#ifdef CONFIG_TEST_ENABLE
    ... ... ...
#endif

或来定义配置参数,如下:

#define CONFIG_TEST_SHOW_STRING "Test 123"
#define CONFIG_TEST_SHOW_INT (123)

但是如果参数越来越多,或者配置之间的关系越来越复杂,就会让代码的可读性越来越差,管理越麻烦,且不直观。
所以Kconfig就是用来解决这些问题的,管理这些配置参数,而且能够可视化地去配置它们

Kconfig简介

Kconfig语言定义了一套完整的规则来表述配置项及配置项间的关系
Kconfig是配置项的描述文件,支持设置配置项及其默认值,依赖关系等等,该文件还会继续依赖各个模块的Kconfig文件。而配置(.config)的可视化管理、生成和修改等需要其他工具(Kconfiglib)配合来完成,且C的头文件需要单独的脚本(kconfig.py)来生成

Kconfig相关的语法这里就不展开了,具体可参见Linux内核中文档介绍:Kconfig Language

Kconfiglib

Kconfiglib是读取、修改和生成 Kconfig 文件的工具,其中menuconfig可以图形化来管理相关配置

kconfig.py

kconfig.py:c头文件生成脚本

这里使用zephyr项目中的生成脚本https://github.com/zephyrproject-rtos/zephyr/blob/main/scripts/kconfig/kconfig.py

实践

工具包准备

需要安装以下几个东东:

  • 安装curses库,提供配置GUI能力

    sudo apt-get install libncurses5-dev
  • 安装kconfiglib

    python3 -m pip install kconfiglib

    工程准备

新建目录,在目录中分别创建main.c、Makefile、Kconfig、kconfig.py

main.c

main.c,主要是根据不同的配置打印不同的信息,来测试配置项:

#include <stdio.h>
#include "autoconfig.h"
int main()
{
    printf("hello, world\n");
#ifdef CONFIG_TEST_ENABLE
    printf("CONFIG_TEST_ENABLE\n");
#endif
    printf("CONFIG_TEST_SHOW_STRING: %s\n", CONFIG_TEST_SHOW_STRING);
    printf("CONFIG_TEST_SHOW_INT: %d\n", CONFIG_TEST_SHOW_INT);
#ifdef CONFIG_TEST_TOP_ENABLE
    printf("CONFIG_TEST_TOP_ENABLE\n");
#endif
#ifdef CONFIG_TEST_SUB_0_ENABLE
    printf("CONFIG_TEST_SUB_0_ENABLE\n");
#endif
#ifdef CONFIG_TEST_SUB_1_ENABLE
    printf("CONFIG_TEST_SUB_1_ENABLE\n");
#endif
    printf("CONFIG_TEST_SHOW_SUB_INT: %d\n", CONFIG_TEST_SHOW_SUB_INT);
    return 0;
}

Kconfig

Kconfig,写法跟Linux的Kernel中的Kconfig类似:

mainmenu "Kconfig Demo"

menu "Test Params setting"
config TEST_ENABLE
    bool "Enable test work"
    default n
    help
        Will print debug information if enable.

config TEST_SHOW_STRING
    string "The show string info"
    default "Test 123"

config TEST_SHOW_INT
    int "The show int info"
    range 0 255
    default 123


config TEST_TOP_ENABLE
    bool "Test Top Func"
    default n
    help
        Function Test Top

config TEST_SUB_0_ENABLE
    bool "Test Sub 0 Func"
    default n
    help
        Function Test Sub 0

config TEST_SUB_1_ENABLE
    bool "Test Sub 1 Func"
    default n
    depends on TEST_TOP_ENABLE
    help
        Function Test Sub 1

config TEST_SHOW_SUB_INT
    int
    default 456 if TEST_SUB_0_ENABLE && TEST_SUB_1_ENABLE
    default 123

endmenu

Makefile

Makefile,主要是通过menuconfig图形化配置生成.config,然后通过kconfig.py脚本生成c的头文件autoconfig.h,最后通过gcc编译main生成可执行文件:

all: main.o
    gcc main.o -o main
main.o: main.c autoconfig.h
    gcc main.c -c -o main.o
clean:
    del main.o main

autoconfig.h:.config
    python3 ./scripts/kconfig.py Kconfig .config autoconfig.h log.txt .config
.config:
    menuconfig
menuconfig:
    menuconfig

kconfig.py

kconfig.py,从zephyr项目中拿来的脚本,需要屏蔽掉以下代码,不然会报错:

#    if kconf.syms['WARN_DEPRECATED'].tri_value == 2:
#        check_deprecated(kconf)

#    if kconf.syms['WARN_EXPERIMENTAL'].tri_value == 2:
#        check_experimental(kconf)

编译测试

运行make all,首次编译因开始没有.config文件,会生成.configautoconfig.h,2个文件中的配置项是对应的,只不过形式不一样而已。

后面如需修改配置参数,只需要执行make menuconfig,再make all重新编译。

修改不同的配置项,然后编译运行测试程序,会发现对应的打印输出会发生相应的变化

参考