从零到一搭建Kconfig配置系统

背景说明

最早接触到Kconfig是在zephyr项目中,之后陆续知道linuxRT-Thread等项目都是用Kconfig来管理编译的,而自己也陆续有大型项目开发需要,了解过后对其使用愈发感兴趣起来。

在实际项目开发中,通常会有需要去使能/关闭一些代码模块或者修改一些配置参数。

项目代码都放在GitHub上,bobwenstudy/test_kconfig_system (github.com)

代码管理

使能或者关闭代码,可以通过#define+#ifdef就可以实现这一目的。

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

调整配置参数,直接通过#define就可以实现这一目的。

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

但是通过这个方式有个问题,就是不直观,如果就几个参数还好,但是当参数越来越多,并之前存在先后关系时,管理难度会呈指数上升。

如下面的例子,CONFIG_TEST_SUB_1_ENABLE的开启前提是CONFIG_TEST_TOP_ENABLE开启,当CONFIG_TEST_SUB_0_ENABLECONFIG_TEST_SUB_1_ENABLE都开启的情况下CONFIG_TEST_SHOW_INT = 123,否则CONFIG_TEST_SHOW_INT = 456

这些宏之间的关系都用代码来描述,需要开发人员熟悉所有代码行为,才能很好的配置这些功能。

#define CONFIG_TEST_TOP_ENABLE
#define CONFIG_TEST_SUB_0_ENABLE#ifdef CONFIG_TEST_TOP_ENABLE
#define CONFIG_TEST_SUB_1_ENABLE
#endif#if defined(CONFIG_TEST_SUB_0_ENABLE) && defined(CONFIG_TEST_SUB_1_ENABLE)
#define CONFIG_TEST_SHOW_SUB_INT (123)
#else
#define CONFIG_TEST_SHOW_SUB_INT (456)
#endif

预编译管理

除了在代码中配置外,也可以通过-D预编译来管理,然后编译全局都有这些配置参数了,对应代码中的宏定义。

gcc xxx -DCONFIG_TEST_ENABLE -DCONFIG_TEST_SHOW_INIT=123#define CONFIG_TEST_ENABLE
#define CONFIG_TEST_SHOW_INIT (123)

问题

如果是小型项目通过上述两种方式管理都还好,当项目越来越大时,所需配置的参数越来越多时,希望有一个工具专门来管理这些配置参数,并且能够可视化这些编译配置。

而Kconfig就是这样一个通用的工具来解决这一问题。

环境搭建

Kconfig是一个配置描述文件,而其配置界面程序需要通过GUI来完成,不然看到的只是一些文本文件,并且这个文件并不能被c所识别。

这里推荐用python的kconfiglib · PyPI库来使用。

Kconfiglib安装

直接python安装即可。由于要使用menuconfig,在windows环境下还需要安装windows-curses

python -m pip install windows-curses
python -m pip install kconfiglib

安装完成后,会在python路径下生成menuconfig.exe执行程序。输入menuconfig -h,出现下面的信息说明已经安装好了。

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

使用Kconfiglib生成的是.config文件,而c代码要使用,必须要提供头文件。其实生成功能主要还是依靠kconfiglib中提供的class Kconfig中的write_autoconf方法,但是也需要一个脚本来调用这个库。

源码所在路径为:Kconfiglib/kconfiglib.py at master · ulfalizer/Kconfiglib (github.com)

kconfig 实例1: 基于 python 的 kconfig 系统 - 简书 (jianshu.com)这个里面提供了一个简单的实现版本,但是有点太简单了,不符合我们实际项目的需要。

这里还是推荐用zephyr项目的版本:zephyr/kconfig.py at main · zephyrproject-rtos/zephyr (github.com)。这个使用需要输入如下参数:

  • kconfig_file,顶层的Kconfig配置文件路径
  • config_out,输出.config文件路径
  • header_out,输出c头文件路径
  • kconfig_list_out,日志文件
  • configs_in,1个或多个输入.config文件

GCC安装

这里调试用的是windows环境,直接自行下载msys2+mingw即可。

https://blog.csdn.net/qq_31985307/article/details/114235846

Kconfig基本概念&语法

Kconfig简介

Kconfig语言定义了一套完整的规则来表述配置项及配置项间的关系。

之前安装的Kconfiglib只是用来显示Kconfig的,实际工程中通常会包含Kconfig.config文件。

  • Kconfig,是配置项的描述文件,支持设置配置项及其默认值,依赖关系等等,该文件还会继续依赖各个模块的Kconfig文件。
  • .config,产品配置文件,提供配置项及在产品中这些配置项的设置值,可能和Kconfig配置项的默认取值不一致,属于产品对配置项的定制。这些配置文件在可以在makefile文件中使用。
  • autoconfig.h,生成的C语言头文件,提供配置项的宏定义版,在C语言程序中使用。

Kconfig语法

由于本文重点是讲Kconfig环境的搭建,所以语法就不展开。

linux的原版可以看这个:Kconfig Language — The Linux Kernel documentation

zephyr项目的介绍:Configuration System (Kconfig) — Zephyr Project Documentation

中文的一些说明:

Kconfig 语法 - fluidog - 博客园 (cnblogs.com)

kconfig语法整理 - 简书 (jianshu.com)

Kconfig实战

这里围绕实际使用的几个场景来进行说明

直接配置版本

准备

需要提供main.c,Makefile,Kconfig。下面分别进行描述:

Kconfig

这里我们将最开始背景说明中的宏定义配置改成Kconfig写法。

mainmenu "Kconfig Demo"menu "Test Params setting"
config TEST_ENABLEbool "Enable test work"default nhelpWill print debug information if enable.config TEST_SHOW_STRINGstring "The show string info"default "Test 123"config TEST_SHOW_INTint "The show int info"range 0 255default 123config TEST_TOP_ENABLEbool "Test Top Func"default nhelpFunction Test Topconfig TEST_SUB_0_ENABLEbool "Test Sub 0 Func"default nhelpFunction Test Sub 0config TEST_SUB_1_ENABLEbool "Test Sub 1 Func"default ndepends on TEST_TOP_ENABLEhelpFunction Test Sub 1config TEST_SHOW_SUB_INTintdefault 456 if TEST_SUB_0_ENABLE && TEST_SUB_1_ENABLEdefault 123endmenu
Makefile

相比于传统的makefile,加入了autoconfig.h.configmenuconfig编译目标。

menuconfig,用于显示menuconfig页面,让用户通过GUI选择当前配置参数。

.config,如果用户第一次没有.config文件时,调用menuconfig来配置Kconfig并生成.config

autoconfig.h,如果.config有更新就需要执行,实际是调用kconfig.py脚本来生成autoconfig.h头文件。

all: main.ogcc main.o -o main
main.o: main.c autoconfig.hgcc main.c -c -o main.o
clean:del main.o main.exeautoconfig.h:.configpython ../scripts/kconfig.py Kconfig .config autoconfig.h log.txt .config
.config:menuconfig
menuconfig:menuconfig
main.c

比较简单,一个是引用生成的autoconfig.h头文件,然后再根据不同的配置打印当前的信息

#include <stdio.h>
#include "autoconfig.h"
int main()
{printf("hello, world\n");
#ifdef CONFIG_TEST_ENABLEprintf("CONFIG_TEST_ENABLE\n");
#endifprintf("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_ENABLEprintf("CONFIG_TEST_TOP_ENABLE\n");
#endif
#ifdef CONFIG_TEST_SUB_0_ENABLEprintf("CONFIG_TEST_SUB_0_ENABLE\n");
#endif
#ifdef CONFIG_TEST_SUB_1_ENABLEprintf("CONFIG_TEST_SUB_1_ENABLE\n");
#endifprintf("CONFIG_TEST_SHOW_SUB_INT: %d\n", CONFIG_TEST_SHOW_SUB_INT);return 0;
}

首次编译

直接键入make all,由于初始环境没有.config文件,会调用menuconfig进行配置生成.config文件。

如下图配置完成后输入Q,会提示保存.config文件,直接保存即可。

.config文件后,就会执行python脚本生成autoconfig.h文件,最后调用gcc生成main.exe

执行编译之后,生成的autoconfig.h文件信息如下。如上图所示,main.exe的执行结果和锁配置的autoconfig.h参数相同。

#define CONFIG_TEST_ENABLE 1
#define CONFIG_TEST_SHOW_STRING "Test 567"
#define CONFIG_TEST_SHOW_INT 123
#define CONFIG_TEST_TOP_ENABLE 1
#define CONFIG_TEST_SHOW_SUB_INT 123

生成的.config文件如下,可以看到默认值通过#注释了,其他就是我们在menuconfig所指定的值。


#
# Test Params setting
#
CONFIG_TEST_ENABLE=y
CONFIG_TEST_SHOW_STRING="Test 567"
CONFIG_TEST_SHOW_INT=123
CONFIG_TEST_TOP_ENABLE=y
# CONFIG_TEST_SUB_0_ENABLE is not set
# CONFIG_TEST_SUB_1_ENABLE is not set
CONFIG_TEST_SHOW_SUB_INT=123
# end of Test Params setting

如上图所示的执行完程序之后,生成了很多中间文件,和目标文件。真正有用的是.configautoconfig.h文件。

调整参数

第一次编译完毕以后,之后我们想修改参数可以通过输入make menuconfig进配置页面,需要注意的是,这时候打开时,不再是默认值,而是我们之前调整后的值

按照如下配置后。

修改后,再键入make all,由于autoconfig.h所依赖的.config变化了,会触发再次运行python脚本生成autoconfig.h,再生成main.exe

生成的autoconfig.h文件如下所示,从上图的执行结果可以看出行为一致。

#define CONFIG_TEST_ENABLE 1
#define CONFIG_TEST_SHOW_STRING "Test 567"
#define CONFIG_TEST_SHOW_INT 78
#define CONFIG_TEST_TOP_ENABLE 1
#define CONFIG_TEST_SUB_0_ENABLE 1
#define CONFIG_TEST_SUB_1_ENABLE 1
#define CONFIG_TEST_SHOW_SUB_INT 456

生成的.config文件如下所示,和我们GUI配置的参数一致。


#
# Test Params setting
#
CONFIG_TEST_ENABLE=y
CONFIG_TEST_SHOW_STRING="Test 567"
CONFIG_TEST_SHOW_INT=78
CONFIG_TEST_TOP_ENABLE=y
CONFIG_TEST_SUB_0_ENABLE=y
CONFIG_TEST_SUB_1_ENABLE=y
CONFIG_TEST_SHOW_SUB_INT=456
# end of Test Params setting

总结

上述的方案算是一个最常用的方式了,发布的时候只提供Kconfig.config为默认值生成的,用户需要改的时候自己通过make menuconfig来修改,以便生成不同的应用程序。

这个方式已经可以满足绝大数应用场景的需要了。

Zephyr提出的持久化版本/多应用版本

虽然上述版本已经满足大多数场景需要了,但是对于像Zephyr这种项目,项目非常大,有多个驱动,并且其会提供很多例程,这些例程都是预先配置好参数给客户直接编译下载的。

不同例程之间所使用的参数各不相同,而且还想让客户可以通过GUI调整某个例程的参数信息,这时候如何管理呢。

这对应芯片厂来讲是一个很普遍的需求,芯片厂所提供的SDK一般包含多个例程,不同例程公用驱动库,只是所使用参数不同。

Zephyr原文:Configuration System (Kconfig) — Zephyr Project Documentation

Zephyr持久化方案实现代码:zephyr/kconfig.cmake at main · zephyrproject-rtos/zephyr (github.com)

好的Zephyr Kconfig使用思路文档:

  • Zephyr Devicetree 与 Kconfig 配置指南 — PAN1080 DK Documentation (panchip.com)
  • Zephyr-系统配置(Kconfig)_只想.静静的博客-CSDN博客_zephyr如何配置

Zephyr项目有点大,他的一些理念可以学习,但本文会给大家准备一个精简版的例程,借鉴其思路来实现类似其工作效果(学习zephyr可以参考下)。

准备

假定有2个例程,每个例程有一个main函数,共同使用一个模块Test。Makefile通过APP参数来指定不同的编译目标,每个应用有其配置参数。项目的目录结构如下图所示。

  • app,应用路径,下面包含2个例程,分别为test1和test2。每个应用有其独立的配置参数prj.conf。

  • driver,公用的驱动路径,例程会调用这个驱动。

  • output,输出路径,生成的一些文件都放在这,.o为了省事就不放了。

  • Kconfig,kconfig的配置文件,和上一个一样。

  • Makefile,makefile文件。

代码分析-app

test1

main.c文件比较简单,就是打印一个printf,而后就是调用驱动库的函数。

#include <stdio.h>
#include "driver_test.h"
int main()
{printf("hello, test1\n");test_driver();return 0;
}

prj.conf文件设定了针对test1的配置参数

CONFIG_TEST_ENABLE=y
CONFIG_TEST_SHOW_STRING="Test 444"
test2

main.c文件比较简单,就是打印一个printf(注意:输出是hello, test2),而后就是调用驱动库的函数。

#include <stdio.h>
#include "driver_test.h"
int main()
{printf("hello, test2\n");test_driver();return 0;
}

prj.conf文件设定了针对test2的配置参数

CONFIG_TEST_TOP_ENABLE=y
CONFIG_TEST_SUB_0_ENABLE=y
CONFIG_TEST_SUB_1_ENABLE=n

代码分析-driver

driver_test.c

其实和上一个例程差不多,就是将配置参数打印出来。

#include <stdio.h>
#include "autoconfig.h"
void test_driver()
{#ifdef CONFIG_TEST_ENABLEprintf("CONFIG_TEST_ENABLE\n");
#endifprintf("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_ENABLEprintf("CONFIG_TEST_TOP_ENABLE\n");
#endif
#ifdef CONFIG_TEST_SUB_0_ENABLEprintf("CONFIG_TEST_SUB_0_ENABLE\n");
#endif
#ifdef CONFIG_TEST_SUB_1_ENABLEprintf("CONFIG_TEST_SUB_1_ENABLE\n");
#endifprintf("CONFIG_TEST_SHOW_SUB_INT: %d\n", CONFIG_TEST_SHOW_SUB_INT);
}
driver_test.h

没什么东西,就是一个函数声明罢了。

#ifndef _DRIVER_TEST_H_
#define _DRIVER_TEST_H_
void test_driver(void);
#endif //_DRIVER_TEST_H_

代码分析-Kconfig

和之前一模一样,就不重复占页数了。

代码分析-Makefile

整个文件如下所示,相比上一个东西多了不少,需要大家具备一定的makefile的功底,下面简单进行分析。

APP ?= app/test1
OUTPUT_PATH := outputINCLUDE_PATH := -I$(APP) -Idriver -I$(OUTPUT_PATH)# define user .config setting
USER_CONFIG_SET :=
USER_CONFIG_SET += $(APP)/prj.conf# define menuconfig .config path
DOTCONFIG_PATH := $(OUTPUT_PATH)/.config# define user merged path
USER_RECORD_CONFIG_PATH := $(OUTPUT_PATH)/user_record.conf# define autoconfig.h path
AUTOCONFIG_H := $(OUTPUT_PATH)/autoconfig.h#define Kconfig path
KCONFIG_ROOT_PATH := Kconfig#For windows work.
FIXPATH = $(subst /,\,$1)all: $(APP)/main.o driver/driver_test.ogcc $^ -o $(OUTPUT_PATH)/main.exe
$(APP)/main.o: $(APP)/main.cgcc $< $(INCLUDE_PATH) -c -o $@
driver/driver_test.o: driver/driver_test.c $(AUTOCONFIG_H)gcc $< $(INCLUDE_PATH) -c -o $@clean:del /q /s $(call FIXPATH, $(APP)/main.o driver/driver_test.o $(OUTPUT_PATH))$(AUTOCONFIG_H):$(DOTCONFIG_PATH)python ../scripts/kconfig.py $(KCONFIG_ROOT_PATH) $(DOTCONFIG_PATH) $(AUTOCONFIG_H) $(OUTPUT_PATH)/log.txt $(DOTCONFIG_PATH)$(USER_RECORD_CONFIG_PATH): $(USER_CONFIG_SET)@echo Using user config.
#   create user_record.conf to record current setting.@copy $(call FIXPATH, $^) $(call FIXPATH, $@)
#   create .config by user config setting.python ../scripts/kconfig.py --handwritten-input-configs $(KCONFIG_ROOT_PATH) $(DOTCONFIG_PATH) $(AUTOCONFIG_H) $(OUTPUT_PATH)/log.txt $(USER_CONFIG_SET)export KCONFIG_CONFIG=$(DOTCONFIG_PATH)
$(DOTCONFIG_PATH):$(USER_RECORD_CONFIG_PATH)@echo .config updatedmenuconfig:$(DOTCONFIG_PATH)
#   set KCONFIG_CONFIG=$(DOTCONFIG_PATH)menuconfig $(KCONFIG_ROOT_PATH)
编译应用部分

将生成autoconfig.h的部分给删除掉,可以看到还是比较清晰的。由于APP可能不一样,默认选中app/test1,后续可以调用make的时候调整。

  • all,依赖2个.o文件,最终生成main.exe
  • main.o,依赖main.c,最终生成main.o
  • driver_test.o,依赖driver_test.c和**autoconfig.h**,最终生成driver_test.o
  • clean,删除中间文件
APP ?= app/test1
OUTPUT_PATH := outputINCLUDE_PATH := -I$(APP) -Idriver -I$(OUTPUT_PATH)# define autoconfig.h path
AUTOCONFIG_H := $(OUTPUT_PATH)/autoconfig.h#For windows work.
FIXPATH = $(subst /,\,$1)all: $(APP)/main.o driver/driver_test.ogcc $^ -o $(OUTPUT_PATH)/main.exe
$(APP)/main.o: $(APP)/main.cgcc $< $(INCLUDE_PATH) -c -o $@
driver/driver_test.o: driver/driver_test.c $(AUTOCONFIG_H)gcc $< $(INCLUDE_PATH) -c -o $@clean:del /q /s $(call FIXPATH, $(APP)/main.o driver/driver_test.o $(OUTPUT_PATH))
autoconfig.h部分

生成autoconfig.h相关的代码也不少,先对基本的参数做一些说明。

USER_CONFIG_SET,用户定义的初始化prj.conf,不同例程配置的参数各不相同,当然也可以分成多个文件,这里只使用一个。

DOTCONFIG_PATH,配置用户menuconfigkconfig.py来使用的文件,.h文件的生成都是用这个文件进行的。

USER_RECORD_CONFIG_PATH,记录用户定义的config参数,本质就是为了利用makefile的文件依赖关系,来记录USER_CONFIG_SET有没有改变,如果有改变,就记录改变后的文件,并基于这些配置生成新的.config文件。

AUTOCONFIG_H,最终要生成的autoconfig.h文件路径。

KCONFIG_ROOT_PATHKconfig的路径。

FIXPATH,windows的反斜杠相关问题处理。

(AUTOCONFIGH):(AUTOCONFIG_H):(AUTOCONFIGH​):(DOTCONFIG_PATH),要生成autoconfig.h,就会去看.config目标是否存在或更新,最终调用kconfig.py使用.config来生成autoconfig.h

$(USER_RECORD_CONFIG_PATH): $(USER_CONFIG_SET),利用makefile的规则来记录用户配置的config文件是否有更新,如果有更新会利用windows的copy指令记录当前用户的config配置,并调用kconfig.py,将用户的config组合生成最终用于生成autoconfig.h.config–handwritten-input-configszephyr项目kconfig.py的配置参数,一些检查overwrite相关的处理。

export KCONFIG_CONFIG=$(DOTCONFIG_PATH)menuconfig所需的参数,如果要修改.config的路径,必须配置该环境变量。

(DOTCONFIGPATH):(DOTCONFIG_PATH):(DOTCONFIGP​ATH):(USER_RECORD_CONFIG_PATH),主要就是为了看用户config是否有修改,如果有就重新生成.config。当然如果刚使用时,没有默认的.config,就用用户config来生成.config

menuconfig:$(DOTCONFIG_PATH),调用menuconfig来临时配置参数。之前没写这个依赖,是因为所有的配置都是用menuconfig生成和管理的。而在这里所有的配置参数需要围绕于用户配置参数来进行,所以第一次打开没有.config时需要用用户当前配置作为menuconfig的显示参数,要临时修改也要基于当前应用配置来调整。

OUTPUT_PATH := output# define user .config setting
USER_CONFIG_SET :=
USER_CONFIG_SET += $(APP)/prj.conf# define menuconfig .config path
DOTCONFIG_PATH := $(OUTPUT_PATH)/.config# define user merged path
USER_RECORD_CONFIG_PATH := $(OUTPUT_PATH)/user_record.conf# define autoconfig.h path
AUTOCONFIG_H := $(OUTPUT_PATH)/autoconfig.h#define Kconfig path
KCONFIG_ROOT_PATH := Kconfig#For windows work.
FIXPATH = $(subst /,\,$1)$(AUTOCONFIG_H):$(DOTCONFIG_PATH)python ../scripts/kconfig.py $(KCONFIG_ROOT_PATH) $(DOTCONFIG_PATH) $(AUTOCONFIG_H) $(OUTPUT_PATH)/log.txt $(DOTCONFIG_PATH)$(USER_RECORD_CONFIG_PATH): $(USER_CONFIG_SET)@echo Using user config.
#   create user_record.conf to record current setting.@copy $(call FIXPATH, $^) $(call FIXPATH, $@)
#   create .config by user config setting.python ../scripts/kconfig.py --handwritten-input-configs $(KCONFIG_ROOT_PATH) $(DOTCONFIG_PATH) $(AUTOCONFIG_H) $(OUTPUT_PATH)/log.txt $(USER_CONFIG_SET)export KCONFIG_CONFIG=$(DOTCONFIG_PATH)
$(DOTCONFIG_PATH):$(USER_RECORD_CONFIG_PATH)@echo .config updatedmenuconfig:$(DOTCONFIG_PATH)
#   set KCONFIG_CONFIG=$(DOTCONFIG_PATH)menuconfig $(KCONFIG_ROOT_PATH)

autoconfig.h生成分析

上面讲了一堆的参数,相信大家有点晕了,那回到我们的主题,设计这个复杂的makefile最终的目的的参考zephyr的持久化版本以及解决多应用版本的需要。

  • 一方面,我们希望多个例程之间有不同的配置参数,是在Kconfig的初始值基础上的不同配置。
  • 另一方面,我们希望用户可以直接通过menuconfig看当前的应用最终的配置参数,并且可以通过menuconfig来基于当前应用配置参数进行调整。

为了解决上述功能需要才设计了上述那么复杂的东西。

简单来讲,autoconfig.h总的有两个修改路径。

  • 一个是直接修改用户config文件,这个是持久化修改方案,此时再编译会冲刷掉menuconfig修改的值。
  • 一个是通过menuconfig修改.config文件,这个是临时修改方案,只对当前编译结果有效,会被用户配置给冲刷掉。
目标文件 依赖 备注
autoconfig.h $(APP)/prj.conf 先生成merge.conf,而后用kconfig.py生成.config,最后再使用kconfig.py利用生成的.config生成autoconfig.h
autoconfig.h menuconfig直接修改 1. 没有.config,先用prj.conf输入kconfig.py生成.config;2. GUI呈现.config的信息,调整后更新.config;3. 使用kconfig.py利用生成的.config生成autoconfig.h

编译

首次编译

直接make all。默认选中的是test1例程,编译过程如下。

由于刚开始没有.config文件,会使用prj.conf文件生成.config文件,而后再用生成.config文件来生成autoconfig.h注意,从图中可以看到,之前就已经生成好了autoconfig.h,后面并没有改变。这里是因为笔者暂时没办法将第一步只做merge动作并生成.config文件,所以只能这样了)。

执行结果如下,会产生一些中间文件,直接使用的是test1的配置。

通过menuconfig修改参数

直接make menuconfig。显示的配置参数就是默认test1的当前配置。

尝试调整值如下,输入Q,会提示保存.config,保存即可。

这时候编译结果如下,可以看出和我们GUI配置的参数一致。

修改user.prj的参数

直接文本操作,将test1目录下的prj.conf进行修改,修改后再通过make all编译,过程如下图。

可以看出刚刚通过menuconfig配置的.config被覆盖了,使用的是最新的用户配置参数,结果如下所示。

不同应用编译

test1的编译结果如上,clean完工程后,我们输入make all APP=app\test2。得到的结果如下:

可以看出这时候用的是test2的配置参数,执行结果也符合预期。

生成持久化所需的prj.conf

从上面的分析可以看出,之后发布给客户的时候不同应用就有其独特的配置了。

但是问题来了,要如何生成prj.conf文件呢,menuconfig提供了一个保存差异的功能,进入GUI修改完参数后,可以输入D就可以输出差异配置了,这个差异配置放到prj.conf中即可。

注意:这里生成的是相对于Kconfig的差异文件,并不是基于当前配置的差异。

从零到一搭建Kconfig配置系统相关推荐

  1. 容器云原生DevOps学习笔记——第三期:从零搭建CI/CD系统标准化交付流程

    暑期实习期间,所在的技术中台-效能研发团队规划设计并结合公司开源协同实现符合DevOps理念的研发工具平台,实现研发过程自动化.标准化: 实习期间对DevOps的理解一直懵懵懂懂,最近观看了阿里专家带 ...

  2. SLAM导航机器人零基础实战系列:(五)树莓派3开发环境搭建——1.安装系统ubuntu_mate_16.04...

    SLAM导航机器人零基础实战系列:(五)树莓派3开发环境搭建--1.安装系统ubuntu_mate_16.04 摘要 通过前面一系列的铺垫,相信大家对整个miiboo机器人的DIY有了一个清晰整体的认 ...

  3. Linux系统装流媒体服务器,搭建和配置支撑2000人同时观看的流媒体服务器系统(Linux步骤详解)...

    鉴于服务器端的安全性因素,更多的网络管理员更愿意在Linux操作系统下搭建流媒体服务器系统(800Li Media Server)进行互联网的实时直播和点播.那么如何在Linux操作系统下安装和配置流 ...

  4. 【Aurix系列学习】TC264D最小系统搭建—基本配置引脚

    目录 1. 测试引脚 2. 调试引脚 3. 复位/NMI引脚 /PORST引脚 /ESRx引脚 4. 电源引脚 初始引脚的配置是TC264D单片机的重点,这一块的配置关系到单片机能否正常上电并可靠运行 ...

  5. 信息架构和零代码应用搭建

    文/明道云创始人任向晖 本文来自即将出版的<零代码企业应用搭建指南>中的关键章节,指导用户进行相对复杂应用的前期信息架构工作. 零代码平台赋能了业务开发者,让他们可以不写代码就能完成应用实 ...

  6. 【Linux】零成本在家搭建自己的私人服务器解决方案

    我这个人自小时候以来就特喜欢永久且免费的东西,也因此被骗过(花巨款买了永久超级会员最后就十几天). 长大后骨子里也是喜欢永久且免费的东西,所以我不买服务器,用GitHubPage或者GiteePage ...

  7. 基于SSM框架搭建的论坛系统

    基于SSM框架搭建的论坛系统 页面展示: 主页 帖子页面 论坛数据库设计 SSM框架搭建 RootConfig.java WebConfig.java WebInit.java 配置po模型 User ...

  8. Django基础--Django基本命令、路由配置系统(URLconf)、编写视图、Template、数据库与ORM...

    web框架 框架,即framework,特指为解决一个开放性问题而设计的具有一定约束性的支撑结构. 使用框架可以帮你快速开发特定的系统. 简单地说,就是你用别人搭建好的舞台来做表演. 尝试搭建一个简单 ...

  9. apache+tomcat 搭建负载均衡系统

    apache+tomcat+mod_jk 搭建负载均衡系统. 0.os系统采用centos6.8 x64 2.6.32-642.el6.x86_64 1.首先安装好jdk环境本次采用jdk-8u111 ...

  10. mysql slave 详细配置_进击的MysqlSlave环境搭建及配置

    一)环境拓扑今天讨论的是mysql集群这一块,资源如下所示:二)Mysql安装配置这里不一一赘述,可以选择源代码编译安装,也可以参考我之前的一篇博文"懒人"速成 一)环境拓扑 二) ...

最新文章

  1. kafka-manager 的编译和使用(附安装包)
  2. windows下检测网站是否正常运行并自动重启服务
  3. msm8974 camera driver添加新摄像头kernel hal修改
  4. 初来乍到,发布一个杀手应用:snap.com的web预览图功能,我给它取名叫“WebSnap”...
  5. 上海交大计算机网络课件 翁惠玉 ppt,上海交通大学 计算机网络PPT3 翁惠玉.ppt
  6. OpenCV如何启用Halide后端以提高效率
  7. 图解:SQL Server SSIS包和job的部署攻略
  8. BZOJ 3224: Tyvj 1728 普通平衡树
  9. DIV Scroll属性
  10. DataGridView绑定对象数组 c# 1614236580
  11. 2017.9.19 禁忌 失败总结
  12. 苹果发布新应用Find My Friends,轻松追踪朋友和家人的所在位置
  13. 完美:Docker遇到Intellij IDEA这个插件,再次解放生产力~
  14. 机电大作业(第一阶段)
  15. 【Tkinter】常用组件(二)
  16. H3C运维审计系统 Web配置指导(笔记)
  17. 【对比Java学Kotlin】协程-异步流
  18. 这16道题都能答上来?恭喜你,90%的面试都能通过!
  19. Android设置来电号码归属地
  20. canvas实现涂鸦效果--橡皮檫和历史记录

热门文章

  1. 天地图矢量mxd版标准地图
  2. 应急指挥中心整体建设方案(ppt)
  3. win10很多软件显示模糊_win10系统字体模糊的解决方法
  4. C#软件注册与注册机
  5. pktgen-dpdk 进行rfc2544测试
  6. ug齿条插件_NX9.0齿轮齿条运动仿真—齿轮工具箱巧用及渐开线制作
  7. Java 进制转换 代码
  8. SQL中的左连接和右连接
  9. creo扫描选择多条链作为轨迹_Proe/Creo创建扭簧
  10. 软件系统建模、UML