Read the root ``platformio.ini`` and return ``build_flags`` for the matching ``[env: ]`` section, with ``extends`` and ``[env]`` inheritance resolved. This exists to fix issue #2664: ``bash compile --backend platformio`` synthesises a fresh PIO project at ``.build/pio/<en
(board_name: str, project_root: Path)
| 31 | |
| 32 | |
| 33 | def get_root_platformio_build_flags(board_name: str, project_root: Path) -> list[str]: |
| 34 | """Read the root ``platformio.ini`` and return ``build_flags`` for the |
| 35 | matching ``[env:<board_name>]`` section, with ``extends`` and ``[env]`` |
| 36 | inheritance resolved. |
| 37 | |
| 38 | This exists to fix issue #2664: ``bash compile --backend platformio`` |
| 39 | synthesises a fresh PIO project at ``.build/pio/<env>/platformio.ini`` |
| 40 | from ``ci/boards.py`` and was silently discarding ``build_flags`` defined |
| 41 | in the user's root ``platformio.ini``. Anyone editing the root file |
| 42 | reasonably expects those flags to take effect; without this merge step |
| 43 | they vanish, producing subtle "flags work under fbuild but not under |
| 44 | --backend=platformio" bugs. |
| 45 | |
| 46 | Behaviour: |
| 47 | - Returns an empty list if the root ``platformio.ini`` is missing, |
| 48 | malformed, or has no matching ``[env:<board_name>]`` section. |
| 49 | - Substitution variables like ``${env:generic-esp.build_flags}`` and |
| 50 | ``extends = env:generic-esp`` are resolved using the existing |
| 51 | :class:`PlatformIOIni` parser, which already implements PlatformIO's |
| 52 | inheritance semantics. |
| 53 | - Never raises: parse errors are swallowed and logged so that a broken |
| 54 | root file cannot block a build. |
| 55 | |
| 56 | Args: |
| 57 | board_name: The PlatformIO env name (e.g. ``"esp32c6"``). Matches |
| 58 | ``[env:<board_name>]`` in the root ini. |
| 59 | project_root: FastLED project root containing ``platformio.ini``. |
| 60 | |
| 61 | Returns: |
| 62 | Ordered list of build_flags strings, or ``[]`` when nothing applies. |
| 63 | """ |
| 64 | root_ini = project_root / "platformio.ini" |
| 65 | if not root_ini.exists(): |
| 66 | return [] |
| 67 | |
| 68 | try: |
| 69 | # Local import to avoid a circular import at module load. |
| 70 | from ci.compiler.platformio_ini import PlatformIOIni |
| 71 | |
| 72 | pio_ini = PlatformIOIni.parseFile(root_ini) |
| 73 | parsed = pio_ini.parsed |
| 74 | env = parsed.environments.get(board_name) |
| 75 | if env is None: |
| 76 | return [] |
| 77 | # `parsed` already has extends + [env] inheritance applied, and |
| 78 | # ${env:...} substitutions resolved (see _resolve_list_variables in |
| 79 | # ci/compiler/platformio_ini.py). |
| 80 | return list(env.build_flags) |
| 81 | except KeyboardInterrupt as ki: |
| 82 | handle_keyboard_interrupt(ki) |
| 83 | raise |
| 84 | except Exception as e: |
| 85 | # Never let a malformed root platformio.ini block a build. |
| 86 | print( |
| 87 | f"Warning: failed to read root platformio.ini for env '{board_name}': {e}" |
| 88 | ) |
| 89 | return [] |
| 90 |