Shell-lex -L/-l build_flags entries and generate the compile database before the build

This commit is contained in:
J. Nick Koston
2026-08-20 04:59:27 -05:00
parent 7cb22725e3
commit eb3a64829f
5 changed files with 82 additions and 25 deletions
+25 -15
View File
@@ -13,6 +13,7 @@ include path.
from __future__ import annotations
from collections.abc import Iterable
from dataclasses import dataclass, field
import logging
from pathlib import Path
@@ -58,6 +59,21 @@ class ArduinoLibrary:
link_flags: list[str] = field(default_factory=list)
def join_flag_args(tokens: Iterable[str], owner: str) -> list[str]:
"""Join a bare ``-I``/``-L``/``-l`` with its following token (PIO lexing)."""
out: list[str] = []
it = iter(tokens)
for tok in it:
if tok in ("-I", "-L", "-l"):
arg = next(it, None)
if arg is None:
_LOGGER.warning("Ignoring trailing '%s' in %s build flags", tok, owner)
break
tok += arg
out.append(tok)
return out
def _library_info(name: str, read_path: Path, data: dict) -> ArduinoLibrary:
"""Resolve one library's sources, include dirs, and flags (PIO semantics)."""
build = data.get("build", {})
@@ -74,24 +90,18 @@ def _library_info(name: str, read_path: Path, data: dict) -> ArduinoLibrary:
src_filter = ensure_list(build.get("srcFilter", DEFAULT_BUILD_SRC_FILTER))
# PlatformIO shell-lexes each build.flags entry
raw_flags = [
token
for entry in ensure_list(build.get("flags", []))
for token in shlex.split(entry)
]
raw_flags = join_flag_args(
(
token
for entry in ensure_list(build.get("flags", []))
for token in shlex.split(entry)
),
f"library {name}",
)
lib = ArduinoLibrary(name=name)
it = iter(raw_flags)
include_flags: list[str] = []
for tok in it:
if tok in ("-I", "-L", "-l"):
arg = next(it, None)
if arg is None:
_LOGGER.warning(
"Ignoring trailing '%s' in library %s build flags", tok, name
)
break
tok += arg
for tok in raw_flags:
if tok.startswith("-I"):
include_flags.append(tok[2:])
elif tok.startswith("-L"):
+8 -4
View File
@@ -65,6 +65,14 @@ def run_compile(config: ConfigType, verbose: bool) -> int:
build_dir = get_build_dir()
env = framework.get_build_env(paths["toolchain_path"])
# The compile database is a pure function of build.ninja (no compilation
# involved), so regenerate it before the build: a failed build can then
# never leave a stale database behind. Skip the ninja spawn plus MBs of
# text on unchanged builds.
if ninja_changed or not (build_dir / "compile_commands.json").is_file():
_write_compile_commands(paths["ninja_path"], build_dir, env)
cmd = [str(paths["ninja_path"]), "-C", str(build_dir)]
if verbose:
cmd.append("-v")
@@ -76,10 +84,6 @@ def run_compile(config: ConfigType, verbose: bool) -> int:
if rc != 0:
return rc
# The compile database is a pure function of build.ninja; skip its
# regeneration (a ninja spawn plus MBs of text) on unchanged builds.
if ninja_changed or not (build_dir / "compile_commands.json").is_file():
_write_compile_commands(paths["ninja_path"], build_dir, env)
_print_size_summary(build_dir)
get_idedata()
return 0
+15 -4
View File
@@ -18,9 +18,11 @@ from dataclasses import dataclass, field
import os
from pathlib import Path
import re
import shlex
import subprocess
import sys
from esphome.arduino8266.component import join_flag_args
from esphome.components.esp8266 import build_surgery
from esphome.components.esp8266.boards import (
BOARDS,
@@ -308,10 +310,19 @@ def _project_flags() -> tuple[list[str], list[str], list[Path], list[str]]:
for flag in flags:
if flag.startswith("-Wl,"):
link_flags.append(flag)
elif flag.startswith("-L") and len(flag) > 2:
lib_dirs.append(Path(flag[2:]))
elif flag.startswith("-l") and len(flag) > 2:
libs.append(flag[2:])
elif flag.startswith(("-L", "-l")):
# Shell-lex only linker entries so forms like "-L /opt/blobs"
# work as they do under PlatformIO. Other entries pass verbatim:
# lexing them would strip the quotes in defines like -DBOARD="...".
for tok in join_flag_args(shlex.split(flag), "esphome"):
if tok.startswith("-L") and len(tok) > 2:
lib_dirs.append(Path(tok[2:]))
elif tok.startswith("-l") and len(tok) > 2:
libs.append(tok[2:])
elif tok.startswith("-Wl,"):
link_flags.append(tok)
else:
compile_flags.append(tok)
else:
compile_flags.append(flag)
return compile_flags, link_flags, lib_dirs, libs