ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

ESP-IDF 项目配置指南:Kconfig 体系与 sdkconfig 文件的完整解析

ESP-IDF 项目配置指南:Kconfig 体系与 sdkconfig 文件的完整解析 ESP-IDF 项目配置指南Kconfig 体系与 sdkconfig 文件的完整解析【免费下载链接】esp-idfEspressif IoT Development Framework. Official development framework for Espressif SoCs.项目地址: https://gitcode.com/GitHub_Trending/es/esp-idf本篇指南讲解 ESP-IDFEspressif IoT Development Framework如何用一个统一的工具链管理项目、构建系统、框架本体及外部组件的全部配置项Kconfig。读完本文你将掌握idf.py menuconfig的完整用法、Kconfig/Kconfig.projbuild/sdkconfig/sdkconfig.defaults/sdkconfig.rename五类文件的职责与优先级关系、如何在 C 代码和 CMake 脚本中消费配置值以及如何为自己的组件或应用定义新的配置项并保证向后兼容。1. 为什么需要 Kconfig统一的配置体系在小型项目例如grep这类命令行工具中用命令行参数完成配置往往就够了。但当项目规模扩大后人们通常会引入专用配置文件C/C 头文件、YAML、JSON 等来承载改变代码行为的参数。随着配置项数量增长管理难度急剧上升更麻烦的是项目的不同部分比如 IDE 插件可能各有各的配置方式。ESP-IDF 为此做了一次统一无论是配置项目、构建系统、ESP-IDF 框架本身还是外部组件都走同一套名为Kconfig的配置工具Kconfig 语言源自 Linux 内核配置系统。其整体架构可以概括为三层配置项定义层采用分布式结构的同名配置文件Kconfig与Kconfig.projbuild其中包含配置项的定义名称、类型等以及可选的默认值。每个项目可以有自己的Kconfig或Kconfig.projbuild文件配置工具会自动发现这些文件。当前取值层当前已经赋值的配置项统一保存在项目根目录的 sdkconfig 文件 中。该文件针对具体项目每当用户修改任何配置项的值时都会随之更新。默认值覆盖层用于设置用户自定义默认值的sdkconfig.defaults文件。当项目纳入版本管理时推荐这种方式——它在项目第一次配置且不存在sdkconfig时替换Kconfig文件中设置的默认值但这些值仍然可以通过idf.py menuconfig等工具继续修改。配置保存后取值还会以sdkconfig.h和sdkconfig.cmake两种形式传播给 C 代码与 CMake 脚本。构建系统侧的实现入口位于 tools/cmake/kconfig.cmake 和 tools/kconfig_new 目录confgen.py、confserver.py、menuconfig_dispatcher.py、prepare_kconfig_files.py等模块负责把 Kconfig 树、sdkconfig 文件与 CMake 构建目标连接起来。2. 如何编辑配置idf.py menuconfig 与 IDE 插件当前赋值的配置项都存储在sdkconfig文件中。这个文件不应手工编辑因为配置项之间可能存在相互依赖依赖与反向依赖手工修改可能破坏这些关系。正确做法是使用idf.py menuconfig或所用 IDE 提供的等效功能。如果你只是想重定义Kconfig文件中设置的默认值可以使用sdkconfig.defaults文件其中的值会覆盖Kconfig文件中的默认值但用户仍可通过idf.py menuconfig修改。用户修改后的值保存在sdkconfig中sdkconfig.defaults保持不动。配置值的加载顺序无论使用哪种工具配置值都按以下顺序加载。默认情况下同名配置项的默认值可被后续步骤中的默认值和用户设定值覆盖而用户设定值只能被后续步骤中的其他用户设定值覆盖加载所有Kconfig默认文件以及它们之间的依赖关系。若发现sdkconfig.defaults文件从中加载用户设定值注意下文说明sdkconfig.defaults里存的其实是用户设定值而非默认值。若存在sdkconfig文件则加载它接下来取决于其中的值是默认值还是用户设定值若sdkconfig中的值是默认值如果sdkconfig.defaults已设置了该配置项则采用sdkconfig.defaults的值sdkconfig.defaults中的值被视为用户设定值否则检查sdkconfig的默认值与Kconfig的默认值是否一致不一致会打印一条 info 提示。两种情况下默认都使用sdkconfig的默认值。若值不是默认值则直接采用。保存配置时sdkconfig以及sdkconfig.h、sdkconfig.cmake、sdkconfig.json中的值都会被同步更新。一个容易误解的点尽管名字叫sdkconfig.defaults该文件里保存的不是配置项的默认值而是用户设定的值。此处的 defaults 指的是该项目初始化时的初始值而不是Kconfig文件中定义的默认值。使用 idf.py menuconfig在终端执行idf.py menuconfig是最系统化、与 IDE 无关的配置方式。命令会打开一个 TUI基于文本的用户界面配置通过方向键导航窗口底部列出了其他热键说明例如用R恢复默认值。IDE 插件方式除了命令行也可以借助 IDE 插件Visual Studio Code 的 ESP-IDF 扩展提供了图形化的 Project Configuration EditorEclipse 生态有官方 idf-eclipse-plugin其中包含 SDK 配置编辑器。使用其他 IDE/插件时请查阅对应文档或直接回退到idf.py menuconfig。3. 默认值处理Kconfig 默认值、sdkconfig 默认值与用户设定值配置项的值分两种类型默认值default与用户设定值user-set。默认值定义在Kconfig文件中由配置系统自动设定例如首次构建时用户设定值则是用户通过idf.py menuconfig等工具或通过sdkconfig.defaults文件手动设置的值。用户可以随时通过 menuconfig 修改任意配置项此时值即变为用户设定。若想撤销自己的设定、让配置系统重新决定默认值可在 menuconfig 中对该项按快捷键Rrestore。注意默认值并不是锁定的。当某个默认值的生效条件发生变化时配置系统会自动更新该配置项的值。官方文档给出的经典示例config DEPENDENT int Dependent option default 1 if CONDITION default 0 if !CONDITION config CONDITION bool Condition option default y只要DEPENDENT仍是默认值用户没有手动设置过当用户把CONDITION设为n时DEPENDENT会自动变为0再把CONDITION设回yDEPENDENT又自动变回1。而一旦用户手动设置了DEPENDENT此后CONDITION如何变化它都不会再变——除非用户在配置工具中按R恢复默认。保存配置时sdkconfig、sdkconfig.h、sdkconfig.cmake、sdkconfig.json都会被更新。两种默认值及其不一致时的处理默认值来源于Kconfig文件成功配置后会被写入sdkconfig。由此产生两种默认值Kconfig 默认值配置项定义中设置的默认值在没有sdkconfig文件时使用sdkconfig 默认值sdkconfig创建时从Kconfig复制过去的默认值。此后sdkconfig已存在、只是被加载时配置系统会检查二者是否一致但不会自动更新。多数时候两者相同但在切换 ESP-IDF 或组件版本Kconfig中的默认值被改动、或有人手工编辑过sdkconfig等场景下可能不一致。此时会打印一条 info 提示告知用户出于构建可复现性系统默认采用sdkconfig的默认值。如果希望改用Kconfig默认值可运行idf.py refresh-config --policyPOLICYPOLICY可取sdkconfig使用sdkconfig的默认值默认行为interactive逐个询问用户是使用Kconfig默认值还是保留sdkconfig默认值kconfig使用Kconfig默认值。从源码可以看到refresh-config、save-defconfig、config-report、confserver都是构建系统在 tools/cmake/kconfig.cmake 中注册的 CMake 自定义目标统一通过kconfgen模块tools/kconfig_new/confgen.py只是转发到python -m kconfgen驱动配置生成与后处理。4. 在 C 代码与 CMake 中使用配置值配置保存到sdkconfig时会同时以sdkconfig.h、sdkconfig.cmake等多种格式输出供 C 代码和 CMake 脚本消费。C 代码中的用法sdkconfig.h为自动生成切勿手改// Contents of sdkconfig.h file (generated automatically, it should NOT be changed manually) //(…) #define CONFIG_USE_WARP 1 #define CONFIG_WARP_SPEED 42 //(…)// Contents of C code file #include sdkconfig.h (…) #if CONFIG_USE_WARP set_warp_speed(CONFIG_WARP_SPEED); #else set_warp_speed(0); #endifCMake 脚本中的用法# Contents of sdkconfig.cmake file (generated automatically, it should NOT be changed manually) #(…) set(CONFIG_USE_WARP 1) set(CONFIG_WARP_SPEED 42) #(…)# Contents of CMakeLists.txt file #(…) if(CONFIG_USE_WARP) set(WARP_SPEED ${CONFIG_WARP_SPEED}) else() set(WARP_SPEED 0) endif() #(…)5. 配置文件体系详解5.1 Kconfig 与 Kconfig.projbuild 文件Kconfig.*文件保存配置项、它们的属性、相互关系以及可选的默认值。每个项目都可以有自己的Kconfig和/或Kconfig.projbuild文件。两者的唯一区别是内容在 menuconfig 界面中的出现位置Kconfig内容出现在配置界面的Component config窗口下Kconfig.projbuild内容出现在配置界面的根菜单top menu下。示例mainmenu Motors configuration config SUBLIGHT_DRIVE_ENABLED bool Enable sublight drive default y help This option enables sublight on our spaceship.5.2 sdkconfig 与 sdkconfig.oldsdkconfig存储当前赋值的所有配置项值由系统自动生成、不应手工编辑原因同第 2 节配置项之间存在依赖关系。它同时包含用户设定值与默认值因此构成了一份完整的配置项清单及其当前取值。每行遵循以下格式之一CONFIG_NAMEvalue配置名及其值# CONFIG_NAME is not set布尔配置项CONFIG_NAME可见但被设为n。非布尔配置项则会出现CONFIG_NAME其他#注释行与空行。每次生成sdkconfig时都会同步生成一份sdkconfig.old作为上一版配置的备份。此外项目中还有sdkconfig.h、sdkconfig.cmake、sdkconfig.json等衍生文件内容与sdkconfig相同、只是格式不同分别供 C/C 代码、CMake、JSON 工具链消费。5.3 sdkconfig.rename 与 sdkconfig.rename.sdkconfig.rename文件用于保证向后兼容由组件或 ESP-IDF 开发者创建维护应用开发者无需编辑。文件规则#开头的行与空行被忽略其余每行必须是以下两种格式之一CONFIG_DEPRECATED_NAME CONFIG_NEW_NAME旧配置名在新版 ESP-IDF 中被重命名为新名CONFIG_DEPRECATED_NAME !CONFIG_NEW_INVERTED_NAME新名是旧配置名逻辑值的布尔取反。若同一个废弃名存在多条映射即被重命名多次以最后一次出现为准系统只在配置报告详细度设为verbose例如通过环境变量KCONFIG_REPORT_VERBOSITY时才会报告该情况。仓库根目录就有一份真实的 sdkconfig.rename 示例# old name new name CONFIG_WARP_DRIVE CONFIG_HYPERDRIVE CONFIG_ENABLE_WARP_DRIVE !CONFIG_DISABLE_HYPERDRIVE经该机制处理后的sdkconfig会附加兼容块(…) CONFIG_HYPERDRIVEy CONFIG_DISABLE_HYPERDRIVEn (…) # Deprecated options for backward compatibility CONFIG_WARP_DRIVEy CONFIG_ENABLE_WARP_DRIVEy # End of deprecated options5.4 sdkconfig.defaults 与 sdkconfig.defaults.Kconfig语言本身通过default子句提供默认值但当Kconfig文件位于其他项目、在版本管理之下或其他原因不便直接编辑时就可以用sdkconfig.defaults文件覆盖默认值。其结构与sdkconfig相同每行写完整的配置名含CONFIG_前缀与值且优先级高于Kconfig中default声明的默认值。也可以只针对特定目标芯片覆盖默认值创建sdkconfig.defaults.chipchip为目标名如esp32s2。此时必须同时存在sdkconfig.defaults文件可以为空否则sdkconfig.defaults.chip会被忽略。生成sdkconfig.defaults的推荐步骤cd到项目目录在idf.py menuconfig中把所有需要的配置项设置好执行idf.py save-defconfig该命令会生成sdkconfig.defaults其中只包含所有与默认值不同的取值。对应实现即 tools/cmake/kconfig.cmake 中的save-defconfig目标调用kconfgen --dont-write-deprecated --output savedefconfig ${CMAKE_SOURCE_DIR}/sdkconfig.defaults正是只导出非默认值的行为来源。优先级示例若sdkconfig.defaults写了CONFIG_SUBLIGHT_SPEED42而用户在 GUI 中改为 10则sdkconfig中保存的是 10sdkconfig.defaults的值被忽略——即sdkconfig 中的用户设定值优先于 sdkconfig.defaults。# Kconfig: config SUBLIGHT_SPEED int Sublight speed default 10 # sdkconfig.defaults: CONFIG_SUBLIGHT_SPEED42此时执行idf.py menuconfigSUBLIGHT_SPEED会被设为 42若在 GUI 中改动则以 GUI 的值为准并写入sdkconfig。文件名可以通过环境变量自定义多个 defaults 文件并存时的处理顺序可参阅构建系统文档中 Custom Sdkconfig Defaults 一节。5.5 sdkconfig.ci部分 ESP-IDF 示例工程带有sdkconfig.ci文件它属于 CI 测试框架的一部分正常构建流程会忽略它。6. 为项目定义新的配置项复杂应用往往需要大量配置项。与组件类似应用也可以拥有自己的配置项定义方式为在项目main目录下放置Kconfig或Kconfig.projbuild文件。流程与组件配置完全相同唯一区别是文件位置在main而不是组件根目录。7. 组件配置指南定义、依赖与向后兼容7.1 ESP-IDF 中配置是如何运作的配置项定义在Kconfig文件中。ESP-IDF 在框架根目录有一个顶层Kconfig文件每个组件还可以有自己的Kconfig文件定义该组件专属的配置项及选项之间的关系。这些关系可以跨多个来源的 Kconfig 文件传播——也就是说Component_A的配置项可以依赖Component_B的配置项哪怕后者由另一位开发者维护。保存配置时sdkconfig、sdkconfig.h、sdkconfig.cmake、sdkconfig.json中的值都会被更新。7.2 为组件定义新配置项在组件根目录创建Kconfig和/或Kconfig.projbuild文件在其中定义配置项一般建议用menu/endmenu代码块包裹menu Motors configuration config SUBLIGHT_DRIVE_ENABLED bool Enable sublight drive default n depends on SPACE_SHIP help This option enables sublight on our spaceship. endmenu当组件被某个项目使用时其中的Kconfig/Kconfig.projbuild会被自动发现并显示在 menuconfig 中。再次强调两种文件的位置差异Kconfig选项显示在 menuconfig 的Component configuration下Kconfig.projbuild选项显示在 menuconfig 顶层菜单。可见性与依赖上例中SUBLIGHT_DRIVE_ENABLED依赖SPACE_SHIP该选项可能来自其他组件。若SPACE_SHIP未被设置或未在当前配置中定义例如包含它的组件没有进入项目依赖不满足SUBLIGHT_DRIVE_ENABLED就不会出现在 menuconfig 中。7.3 保证向后兼容在组件开发中重命名 Kconfig 选项等同于破坏性 API 变更和重命名函数一样。ESP-IDF 提供了基于sdkconfig.rename文件的兼容机制在组件根目录创建该文件每行写一对配置名CONFIG_OLD_NAME CONFIG_NEW_NAME新选项直接替代旧选项CONFIG_OLD_NAME !CONFIG_NEW_NAME新选项是旧选项的布尔取反。配置工具idf.py menuconfig触发的流程会自动发现该文件并为重命名项在sdkconfig中生成兼容语句。机制细节若用户已经为旧配置项赋过值旧名出现在sdkconfig或sdkconfig.defaults中而没有sdkconfig.rename文件该值会被静默忽略——这是 Kconfig 系统源自 Linux 内核的默认行为并非缺陷。ESP-IDF 通过配置工具抑制了这种意外行为具体做法分两步配置工具在整个 ESP-IDF 目录中搜索所有sdkconfig.rename文件若项目目标芯片chip与某个sdkconfig.rename.chip的后缀匹配该文件同样会被纳入收集完成后sdkconfig以及存在的sdkconfig.h/json/cmake会被后处理在所有文件末尾追加一段兼容语句块以# Deprecated options for backward compatibility开始、以# End of deprecated options结束。7.4 抑制 Kconfig 的 Info/Warning 信息有时需要抑制配置报告中的特定信息或警告。# ignore: ignore-code注释pragma可以做到这一点其中ignore-code对应配置报告中的某个报告区域report area且长短两种写法均可。当前支持的 ignore codemultiple-definition/MD抑制Multiple Symbol/Choice Definitions区域中该配置项所有出现位置的消息。只需要在其中一处定义上加 pragma 即可。# Even though the LED_PIN option is defined multiple times, the info message about this will be suppressed config LED_PIN # ignore: multiple-definition int Pin for LED default 1 # (…) config LED_PIN # here, the pragma is not needed (but it is allowed) int Pin for LED default 38. 配置报告Configuration Report配置报告是一种半结构化文本用于在项目配置出现问题时提供统一概览它把与项目配置相关的所有消息、警告、错误聚合在一起帮助定位配置类问题。每次项目配置重新构建时——通常是首次构建或运行idf.py menuconfig时——报告会自动打印到控制台。报告由一个头部解析器版本、详细度、状态加零个或多个报告区域组成每个区域聚合一个特定问题的相关消息。需要更详细的输出时在构建或idf.py menuconfig前设置环境变量KCONFIG_REPORT_VERBOSITYverbose即可。一个典型的文本报告示例实际输出带颜色Configuration report -------------------- Parser Version: 1 Verbosity: default Status: Finished with notifications Multiple Symbol/Choice Definitions ---------------------------------- SYMBOL_NAME path/to/first/Kconfig_with_definition:line_number path/to/second/Kconfig_with_definition:line_number ANOTHER_SYMBOL_NAME another/path/to/first/Kconfig_with_definition:line_number another/path/to/second/Kconfig_with_definition:line_number生成 JSON 格式的配置报告idf.py config-report命令可以生成 JSON 格式的报告输出到build/config目录、文件名为kconfig_parse_report.jsonidf.py config-report注意该 JSON 文件结构仍处于实验阶段未来可能变化。JSON 文件包含两个主要部分header报告总体信息——报告类型、Kconfig 解析器版本、详细度、状态、唯一符号数量、默认值策略defaults policyareas报告区域列表每个区域包含与特定问题相关的错误、警告和 info 消息例如配置项在多处被定义。示例{ header: { report_type: kconfig, parser_version: 1, verbosity: default, status: Finished with notifications, number_of_unique_symbols: 100, defaults_policy: sdkconfig }, areas: [ { title: Multiple Symbol/Choice Definitions, severity: Info, data: { EXAMPLE_SYMBOL_NAME: [ path/to/Kconfig:42, path/to/another/Kconfig:32 ] } } ] }在构建系统实现中该命令对应 tools/cmake/kconfig.cmake 中的config-report自定义目标kconfgen --output report ${config_dir}/kconfig_parse_report.json与--env KCONFIG_REPORT_VERBOSITY...联动与上文文档描述完全一致。9. 相关文件速查文件作用谁维护Kconfig配置项定义、关系、默认值显示于 menuconfig 的 Component config 下组件/应用开发者Kconfig.projbuild同上但显示于 menuconfig 根菜单组件/应用开发者sdkconfig当前所有配置项的取值自动生成勿手改构建系统sdkconfig.old上一版sdkconfig的备份构建系统sdkconfig.h/sdkconfig.cmake/sdkconfig.json供 C/C、CMake、JSON 工具消费的同数据不同格式构建系统sdkconfig.defaults及.defaults.chip项目初始化时的用户设定值覆盖 Kconfig 默认值应用开发者sdkconfig.rename及.rename.chip配置项重命名/取反的向后兼容映射组件/ESP-IDF 开发者sdkconfig.ciCI 测试框架专用正常构建忽略CI 框架更多进阶内容Kconfig 语言本身的完整语法、esp-idf-kconfig工具包的实现细节参阅 esp-idf-kconfig 的官方文档全部配置项清单则见 ESP-IDF 文档的 Configuration Options Reference可按芯片与版本组合筛选。本文所有事实依据均来自当前仓库中的 Kconfig 配置文档、构建系统实现与 kconfgen 工具入口可直接按路径回溯验证。【免费下载链接】esp-idfEspressif IoT Development Framework. Official development framework for Espressif SoCs.项目地址: https://gitcode.com/GitHub_Trending/es/esp-idf创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表