Using -a/–amend
When making minor differences on an existing board (such as modifying a pin or replacing a touch chip) or adding devices not included by default, there is no need to copy the entire board directory. Prepare an amend directory containing a board_amend.yaml manifest, then apply changes as patches on top of the selected board during generation using -a/--amend <dir>:
# The amend directory is an absolute or relative path and must contain board_amend.yaml
idf.py bmgr -b esp32_s3_korvo_2_3 -a path/to/my_amend
# When the amend directory is placed under the selected board directory, pass the subdirectory name directly
# For example: esp_boards/esp32_s3_lcd_ev_board/sub_board_800_480_lcd
idf.py bmgr -b esp32_s3_lcd_ev_board -a sub_board_800_480_lcd
-a accepts absolute or relative paths; relative paths are resolved from the current working directory (cwd). If the amend directory is placed under the selected board directory, only the subdirectory name needs to be passed, and BMGR will look for the corresponding subdirectory inside that board directory.
Different sub-boards, screen modules, or minor hardware variants of the same main board are recommended to be placed uniformly under that board’s subdirectory (for example, esp_boards/esp32_s3_lcd_ev_board/sub_board_800_480_lcd/); only the subdirectory name needs to be passed when using it, and it is not affected by the project path.
Note
Besides the explicit -a above, BMGR can also auto-discover and apply an amend by board name (auto-amend), which is especially handy for keeping a single command across many boards in a multi-board example project. See Auto-amend below.
Basic structure of the amend directory:
my_amend/
board_amend.yaml # Required: manifest file
tweak.yaml # YAML fragment, must be listed under apply:
extra_setup.c # Optional source file, must be listed under apply:
sdkconfig.defaults.board # Optional, must be listed under apply:
Manifest File
board_amend.yaml format:
version: "1.0"
description: "Add external sensor power control"
apply: # Ordered list; later entries override earlier ones
- tweak.yaml
- extra_setup.c
- sdkconfig.defaults.board
Files at the amend root (including sdkconfig.defaults.board and Kconfig.projbuild) must be explicitly listed in apply: to take effect. Files that are placed but not listed will be ignored and an info log will be output. Directory entries are not supported; files in subdirectories must be listed with their full relative paths, such as pack/extra.yaml.
Supported path formats for each entry in apply::
Relative path: Resolved relative to the directory containing
board_amend.yaml, for exampletweak.yaml,pack/extra.yaml,../shared/extra_setup.c.Absolute path: Used directly, for example
/abs/path/to/extra_setup.c.
Regardless of the format, directory entries are not supported. Files in subdirectories must be listed with their full filenames expanded (pack/extra.yaml, not pack).
YAML Fragment Merge Rules
Each YAML fragment must contain devices: or peripherals: at the top level. Merging is performed in the order of apply:. Devices or peripherals with the same name undergo field-level merging (config uses deep merge); names that do not exist are appended to the end of the list.
# Example tweak.yaml: add a peripheral and the corresponding power control device
peripherals:
- name: gpio_sensor_power
type: gpio
role: io
version: default
config:
pin: 4 # [IO]
mode: GPIO_MODE_OUTPUT
devices:
- name: sensor_power
type: power_ctrl
sub_type: gpio
version: default
peripherals:
- name: gpio_sensor_power
active_level: 1
Source File Override
.c, .cpp, .cc, .cxx, and .S files listed in apply: are compiled into the generated component. The generated component sets WHOLE_ARCHIVE, so strong symbols provided by the amend override weak symbol functions of the same name in the base board. The typical usage is to rewrite initialization hooks in setup_device.c. It is recommended that hook functions in the base board uniformly use the __attribute__((weak)) and __has_include combination to facilitate amend replacement; see the setup_device.c section in Board Directory Structure and File Responsibilities.
Cross-Board Module Reuse
apply: supports relative paths, resolved from the directory containing board_amend.yaml, allowing references to files outside the amend directory at other locations in the project. Using this feature, common peripheral and device configurations can be split into independent YAML and source code fragments, stored centrally in a shared directory, and then referenced on demand by different boards’ amend files—effectively assembling a complete board-level configuration from reusable feature modules.
For example, to split the gas sensor adaptation into an independent fragment and place it in the project shared directory:
sensors/
gas_sensor/
gas_sensor.yaml # Peripheral and device declarations
gas_sensor.c # Initialization implementation (optional)
A board’s board_amend.yaml references it via a relative path:
version: "1.0"
description: "Board A: base board + gas sensor"
apply:
- ../sensors/gas_sensor/gas_sensor.yaml
- ../sensors/gas_sensor/gas_sensor.c
Another board that needs the same sensor directly reuses the same files without needing to maintain them again:
version: "1.0"
description: "Board B: base board + gas sensor + extra periph"
apply:
- ../sensors/gas_sensor/gas_sensor.yaml
- ../sensors/gas_sensor/gas_sensor.c
- extra_periph.yaml # Board-specific additional tweaks
As feature modules accumulate in the shared directory, adapting new boards can rely increasingly on existing modules—combining the required fragments in apply: rather than writing repetitive YAML content from scratch.
Auto-amend
Besides the explicit -a, BMGR can auto-discover and apply an amend by board name. Under the scan paths (including directories given via -c/--customer-path), if there is a directory whose name matches the selected board, contains board_amend.yaml , and is not itself a complete board directory, BMGR applies it as that board’s amend automatically, without -a.
The expected layout is <scan_root>/<board_name>/board_amend.yaml:
board_overlays/ # point -c here
esp32_s3_box_3/
board_amend.yaml
box_tweak.yaml
esp32_p4_function_ev_board/
board_amend.yaml
p4_tweak.yaml
The board_amend.yaml inside an auto-amend directory uses the same syntax, fragment merge rules, source override, and cross-board reuse as the explicit -a (apply: is still the single source of truth).
Key points:
-c/--customer-pathaccepts multiple semicolon-separated paths, for example-c "overlays_a;overlays_b"; they are scanned in order and later paths take precedence.Explicit
-aand auto-amend can be combined; explicit-ahas the highest priority (applied last, overriding auto-amend).A complete board directory is treated as a board even if it contains
board_amend.yaml; it is never auto-applied to itself.Auto-discovery recurses up to 3 levels below each scan root.
Set the environment variable
ESP_BOARD_MANAGER_DISABLE_AUTO_AMEND=1to disable auto-discovery and keep only the explicit-a.
Two ways to use amend in a demo
When writing an example project that supports multiple boards, the biggest value of auto-amend is keeping a single command across all boards.
Option 1: All boards share the same amend
When every target board needs the same patch set (for example, enabling a debug option or adding the same external module), point the explicit -a at the same amend directory; the amend part of each command stays identical:
idf.py bmgr -b esp32_s3_box_3 -a path/to/common_amend
idf.py bmgr -b esp32_p4_function_ev_board -a path/to/common_amend
Option 2: Different boards need different amends, with consistent commands
When each board needs its own patch, the old approach required a different -a path per board, so commands varied and were easy to confuse. With auto-amend, simply collect every board’s overlay under one root, with a subdirectory per board name:
board_overlays/
esp32_s3_box_3/board_amend.yaml # box-specific patch
esp32_p4_function_ev_board/board_amend.yaml # p4-specific patch
Then all boards use the exact same command, changing only the -b board name while -c always points to the same overlay root; BMGR matches and applies the right amend by board name:
idf.py bmgr -b esp32_s3_box_3 -c board_overlays
idf.py bmgr -b esp32_p4_function_ev_board -c board_overlays
When no overlay exists for a board, the command generates the base board normally without error. In CI or multi-board demo scripts, you can loop the same command over a list of board names without maintaining per-board amend arguments.