1。新增双语文档。

This commit is contained in:
MacRsh
2023-12-28 01:19:05 +08:00
parent aa3620c919
commit 0d35810272
22 changed files with 2825 additions and 77 deletions

208
document/Kconfig/Kconfig.md Normal file
View File

@@ -0,0 +1,208 @@
# 如何为项目引入Kconfig配置系统
[English](Kconfig_EN.md)
<!-- TOC -->
* [如何为项目引入Kconfig配置系统](#如何为项目引入kconfig配置系统)
* [验证 python 环境](#验证-python-环境)
* [C语言头文件生成脚本](#c语言头文件生成脚本)
* [应用](#应用)
* [创建Kconfig](#创建kconfig)
<!-- TOC -->
项目中经常会有通过宏配置或选择参数:
```c
#ifdef CFG_ENABLE
#define CFG_ARGS "test"
void printf_args(void)
{
printf("args: %s\n", CFG_ARGS);
}
#endif
```
当项目规模较小,配置项和依赖关系相对简单时,我们可以通过手动修改源代码来实现配置功能。但是,随着项目规模的增长和配置复杂度的增加,这种方式也会出现一些问题。
随着代码体量和调用关系的增多,对配置者来说`很难完全熟悉`
代码结构及各模块之间的依赖关系。同时,如果配置项设置较为`随意且缺乏约束`,也很可能导致`错误配置`。这对项目质量和维护都带来一定难度。
对于规模较大的项目来说需要一套专业的配置管理系统来解决这些问题。Kconfig正是为了应对这种需求而产生的。它通过配置脚本定义各配置选项及其依赖关系并提供`图形化界面`
供配置者操作。同时还会检查配置`合理性`,帮助我们实现定制化构建的同时`防止错误配置`
如果有接触过Linux或者RT-Thread等相信对Kconfig系统都不陌生。Kconfig是Linux内核和许多其他系统广泛使用的一款配置管理工具。它可以让开发人员在编译时选择性地包含或排除某些功能模块。
Kconfig使用配置脚本定义各种配置选项及其依赖关系。通过图形或字符型用户界面开发者可以查看并设置各种配置。然后Kconfig会生成 `.config`
文件保存选择结果。在编译的时候,会根据 `.config` 文件里设置的符号自动包含或排除对应的源代码。
![Kconfig](../picture/Kconfig/Kconfig.png)
## 验证 python 环境
Kconfig依赖于 ` python` ,如果没有 ` python` 环境请自行安装。
在命令行中使用所示命令验证:
```cmd
python --version
```
显示(正确显示版本即可):
```cmd
Python 3.11.4
```
## C语言头文件生成脚本
Kconfiglib 生成的是 `.config` 文件并非C语言文件需要使用脚本生成`将以下代码复制到文件中并命名为kconfig.py`
```python
import re
import pip
def log_print(level, text):
# Log level colors
LEVEL_COLORS = {
'error': '\033[31m',
'success': '\033[32m',
'warning': '\033[33m',
'info': '\033[34m',
}
RESET_COLOR = '\033[0m'
# Log level name
LEVEL_NAME = {
'error': 'ERROR',
'success': 'SUCCESS',
'warning': 'WARNING',
'info': 'INFO',
}
print(LEVEL_COLORS[level] + LEVEL_NAME[level] + ': ' + text + RESET_COLOR)
def install_package(package):
log_print('info', "%s package installing..." % package)
pip.main(['install', package])
try:
from kconfiglib import Kconfig
except ImportError:
install_package('kconfiglib')
from kconfiglib import Kconfig
try:
import curses
except ImportError:
install_package('windows-curses')
import curses
def generate_config(kconfig_file, config_in, config_out, header_out):
kconf = Kconfig(kconfig_file, warn=False, warn_to_stderr=False)
# Load config
kconf.load_config(config_in)
kconf.write_config(config_out)
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 ")
content = re.sub(r'#define MR_USING_(\w+) (\d+)', r'#define MR_USING_\1', content)
# Add the micro
header_file.write("#ifndef _MR_CONFIG_H_\n")
header_file.write("#define _MR_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 /* _MR_CONFIG_H_ */\n")
header_file.close()
log_print('success', "menuconfig %s make success" % header_out)
def main():
kconfig_file = ''
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.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界面
![Kconfig1](../picture/Kconfig/Kconfig1.png)
回车后就可以看到配置的2个参数
![Kconfig2](../picture/Kconfig/Kconfig2.png)
设置的范围也在输入时生效了:
![Kconfig3](../picture/Kconfig/Kconfig3.png)
配置完成后按`Q`退出,`Y`保存配置。
在当前目录下调用命令行,输入:
```cmd
python kconfig.py
```
运行 `python` 脚本生成`.h`文件。
显示生成`config.h`成功。打开这个文件:
![Kconfig4](../picture/Kconfig/Kconfig4.png)

View File

@@ -0,0 +1,219 @@
# How to introduce the Kconfig configuration system into a project
[中文](Kconfig.md)
<!-- TOC -->
* [How to introduce the Kconfig configuration system into a project](#how-to-introduce-the-kconfig-configuration-system-into-a-project)
* [Verify Python Environment](#verify-python-environment)
* [C Header File Generation Script](#c-header-file-generation-script)
* [Application](#application)
* [Create Kconfig](#create-kconfig)
<!-- TOC -->
There are often macro configurations or parameter selections in projects:
```c
#ifdef CFG_ENABLE
#define CFG_ARGS "test"
void printf_args(void)
{
printf("args: %s\n", CFG_ARGS);
}
#endif
```
When the project scale is relatively small and the dependency relationships are relatively simple, we can manually
modify the source code to implement configuration functions. However, as the project scale increases and configuration
complexity increases, this approach will also have some problems.
As the code volume and call relations increase, it becomes `difficult` for configurers to fully understand
the `code structure` and dependencies between modules. At the same time, if the configuration items are set in
a `casual` and `lack of constraints` manner, it is also very likely to lead to `incorrect configuration`. This brings
certain difficulties to project quality and maintenance.
For large-scale projects, a professional configuration management system is needed to solve these problems. Kconfig is
designed to address this need. It defines various configuration options and their dependencies through configuration
scripts, and provides a `graphical interface` for configurers to operate. It also checks the `rationality` of
configurations to help us achieve customized builds while `preventing incorrect configurations`.
If you have experience with the Linux or RT-Thread, Kconfig system should not be unfamiliar. Kconfig is a widely used
configuration management tool in Linux kernel and many other systems. It allows
developers to selectively include or exclude some functional modules during compilation.
Kconfig uses configuration scripts to define various configuration options and their dependencies. Through graphical or
character-based user interfaces, developers can view and set various configurations. Then Kconfig will generate
a `.config` file to save the selection results. During compilation, it will automatically include or exclude the
corresponding source code according to the settings in the `.config` file.
![Kconfig](../picture/Kconfig/Kconfig.png)
## Verify Python Environment
Kconfig depends on `python`. If there is no `python` environment, please install it yourself.
Use the following command in the command line to verify:
```cmd
python --version
```
Display (Correctly displaying the version is okay):
```cmd
Python 3.11.4
```
## C Header File Generation Script
Kconfiglib generates a `.config` file instead of a C language file. A script is needed to generate header
files. `Copy the following code to a file and name it kconfig.py.`
```python
import re
import pip
def log_print(level, text):
# Log level colors
LEVEL_COLORS = {
'error': '\033[31m',
'success': '\033[32m',
'warning': '\033[33m',
'info': '\033[34m',
}
RESET_COLOR = '\033[0m'
# Log level name
LEVEL_NAME = {
'error': 'ERROR',
'success': 'SUCCESS',
'warning': 'WARNING',
'info': 'INFO',
}
print(LEVEL_COLORS[level] + LEVEL_NAME[level] + ': ' + text + RESET_COLOR)
def install_package(package):
log_print('info', "%s package installing..." % package)
pip.main(['install', package])
try:
from kconfiglib import Kconfig
except ImportError:
install_package('kconfiglib')
from kconfiglib import Kconfig
try:
import curses
except ImportError:
install_package('windows-curses')
import curses
def generate_config(kconfig_file, config_in, config_out, header_out):
kconf = Kconfig(kconfig_file, warn=False, warn_to_stderr=False)
# Load config
kconf.load_config(config_in)
kconf.write_config(config_out)
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 ")
content = re.sub(r'#define MR_USING_(\w+) (\d+)', r'#define MR_USING_\1', content)
# Add the micro
header_file.write("#ifndef _MR_CONFIG_H_\n")
header_file.write("#define _MR_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 /* _MR_CONFIG_H_ */\n")
header_file.close()
log_print('success', "menuconfig %s make success" % header_out)
def main():
kconfig_file = ''
config_in = '.config'
config_out = '.config'
header_out = 'config.h'
generate_config(kconfig_file, config_in, config_out, header_out)
if __name__ == "__main__":
main()
```
Modify `header_out` in the `main` function to modify the generated function file name.
This script removes the `CONFIG_` prefix added by Kconfig by default and adds `_CONFIG_H_` and `C` declarations to it.
# Application
## Create Kconfig
Create a new file named `Kconfig` (without extension), and put it together with the `kconfig.py` file created in the
previous step.
```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
```
Call menuconfig in the command line:
```cmd
menuconfig
```
Configure and generate header file.
![Kconfig1](../picture/Kconfig/Kconfig1.png)
Press enter, you can see the two parameters configured:
![Kconfig2](../picture/Kconfig/Kconfig2.png)
The range of Settings also takes effect when entering:
![Kconfig3](../picture/Kconfig/Kconfig3.png)
After the configuration is complete, press `Q` to exit and `Y` to save the configuration.
In the current directory, call up the command line and type:
```cmd
python kconfig.py
```
Run the `python` script to generate the `.h` file.
The `config.h` is successfully generated. Open this file:
![Kconfig4](../picture/Kconfig/Kconfig4.png)