Code Generation and Build Integration
Before compilation, BMGR parses the board’s YAML description into a set of explicit configuration source files and build inputs. idf.py bmgr is the user-facing entry command.
When running idf.py bmgr -b <board>, BMGR performs the following steps in order:
Scans board directories, collecting candidate boards from the default directory, custom directory, and component directories.
Determines the currently selected board based on the command-line arguments (name or index).
Locates the board’s
board_peripherals.yaml,board_devices.yaml,board_info.yaml,sdkconfig.defaults.board, andKconfig.projbuild.Parses peripherals and devices, generating corresponding configuration structures, handle tables, and board-level metadata.
Generates the
Kconfig.projbuildfor the current board and appends the board directory’sKconfig.projbuild.Generates
board_manager.defaults, connecting the board’s default configuration and capability symbols to the build.Outputs the source files, build files, and tooling summary files under
components/gen_bmgr_codesfor compilation.
In BMGR’s model, board configuration code comes from the YAML file description and the script’s parsing and generation process, not from manually selecting devices or peripherals in menuconfig. components/gen_bmgr_codes is not a cache or a view-only intermediate artifact; it is an actual component that participates in the ESP-IDF build.
Generated Output Files
File |
Description |
|---|---|
|
Peripheral configuration structure definitions generated from |
|
Generated peripheral handle entry points, type mappings, and initialization function hooks. |
|
Device configuration structure definitions generated from |
|
Generated device handle entry points, initialization/deinitialization function mappings, and device linked list. |
|
Generated board-level metadata, such as board name, chip, version, description, and manufacturer. |
|
Configuration struct definitions for |
|
|
|
Kconfig symbol definitions and selection entries for the current board, projecting board-level capabilities into the project configuration system. |
|
Component dependency manifest for the current board; device |
|
A unified board-level summary for tooling and debugging; useful for viewing the devices, peripherals, component dependencies, and occupied I/O of the current board. |
BMGR does not organize compilation by manually selecting devices or peripherals one by one in menuconfig; instead, it first generates board_manager.defaults from the board-level YAML, and the board capability macros contained therein take effect during the subsequent build. When running idf.py, BMGR injects these settings into sdkconfig to drive BMGR’s conditional compilation.
During debugging, it is recommended to triage by symptom:
If the behavior does not match expectations, check
gen_board_periph_config.candgen_board_device_config.cfirst.If the symptom is a build failure or dependency resolution error, check whether the generated files under
components/gen_bmgr_codesare complete, whether the capability symbols inboard_manager.defaultsmatch expectations, and whethersdkconfigis consistent withboard_manager.defaults.
Assembling and Overriding board_manager.defaults and Kconfig.projbuild
board_manager.defaults is the board-level defaults file through which BMGR connects board configuration to ESP-IDF build configuration. Based on the current board YAML, BMGR generates capability symbols such as CONFIG_ESP_BOARD_PERIPH_*_SUPPORT, CONFIG_ESP_BOARD_DEV_*_SUPPORT, and CONFIG_ESP_BOARD_DEV_<DEV>_SUB_<SUB>_SUPPORT. These symbols participate in the subsequent build and control whether device, peripheral, and device sub-type code is compiled. Users should not manually write these BMGR-managed capability symbols in the project sdkconfig.defaults; board-level differences should be managed through sdkconfig.defaults.board or amend.
When running idf.py bmgr -b <board> [-a <amend>], BMGR assembles the final board_manager.defaults and Kconfig.projbuild in the following order, with later entries overriding earlier ones:
BMGR auto-generated section:
CONFIG_IDF_TARGET,CONFIG_ESP_BOARD_<BOARD>=y,CONFIG_ESP_BOARD_NAME, and the capability symbols derived from YAML parsing:CONFIG_ESP_BOARD_PERIPH_*_SUPPORT,CONFIG_ESP_BOARD_DEV_*_SUPPORT, andCONFIG_ESP_BOARD_DEV_<DEV>_SUB_<SUB>_SUPPORT.The
sdkconfig.defaults.boardandKconfig.projbuildin the board directory (if present).The
sdkconfig.defaults.boardandKconfig.projbuildfragments listed underapply:in theboard_amend.yamlmanifest, appended strictly in the order they appear inapply:. To have one fragment override another amend fragment, place it later in theapply:list.
When duplicate CONFIG_* entries appear in board_manager.defaults, BMGR keeps the last occurrence and rewrites earlier duplicate lines as comments in the form # BMGR_CONFIG_OVERRIDE by <section>: <original line>, making override relationships easy to trace. Kconfig.projbuild is assembled by plain-text concatenation; a # --- <label>: <path> --- marker is inserted before each segment to indicate its source.
Note
The sdkconfig.defaults.board and Kconfig.projbuild files listed in the board_amend.yaml manifest must be explicitly listed under apply: to be included in the merge. Files placed in the amend directory but not listed are ignored and an INFO log is emitted. See Using -a/–amend for details.
Build Integration: SDKCONFIG_DEFAULTS Precedence
During the build, ESP-IDF reads a set of SDKCONFIG_DEFAULTS. The files are declared by the SDKCONFIG_DEFAULTS environment variable or CMake variable, and separated by ;.
When the project sdkconfig does not exist, BMGR uses an idf.py global callback to assemble SDKCONFIG_DEFAULTS in the following order. Per the ESP-IDF rule, later entries take precedence:
Project
sdkconfig.defaults(lowest)components/gen_bmgr_codes/board_manager.defaults(board-level, including amend)Environment
SDKCONFIG_DEFAULTS-D SDKCONFIG_DEFAULTS(highest)
Therefore, board-level defaults always take precedence over the project’s sdkconfig.defaults. Project defaults can no longer override ordinary board defaults. For board-specific overrides, use amend (auto-amend or -a/--amend).
Warning
Use amend for board-level hardware/variant overrides; do not rely on the project sdkconfig.defaults to override the board. When the project sdkconfig.defaults sets a symbol also managed by the board, the board value wins, and BMGR prints a non-blocking warning when preparing SDKCONFIG_DEFAULTS (pointing to the board’s precedence and recommending amend for board-level overrides). The previous behavior that raised a FatalError when project defaults touched BMGR-managed symbols has been removed. The project sdkconfig.defaults is best for cross-board policy not set by the board; for CI or temporary overrides use the environment variable or -D SDKCONFIG_DEFAULTS=. Board-specific sdkconfig entries (PSRAM, Flash, partition tables, application-level switches, etc.) should be placed in sdkconfig.defaults.board under the board directory; BMGR will merge them uniformly.
When switching boards, idf.py bmgr -b <other_board> regenerates board_manager.defaults and Kconfig.projbuild, and backs up and cleans up the capability macros written by the previous board from the old sdkconfig.
Note
In addition to explicit -a/--amend, BMGR supports auto-amend: under the same scan paths used for boards (including -c paths), it automatically finds a directory whose name equals the currently selected board, that contains a board_amend.yaml, and that is not itself a full board directory (convention <scan_root>/<board_name>/board_amend.yaml), and applies it as that board’s amend. -c/--customer-path now accepts multiple semicolon-separated paths (for example -c "overlays_a;overlays_b"), where later paths take precedence. By placing each board’s overlay under one root and passing a single -c, every board can share the exact same command. Explicit -a/--amend has the highest precedence and overrides all auto-amend; set ESP_BOARD_MANAGER_DISABLE_AUTO_AMEND=1 to disable auto-discovery. See Using -a/–amend for details.