fix(espidf): copy extras/ header fragments into merged libs (never their sources)

FastLED's unity build (src/fl/build/extras+.cpp) includes
"extras/_build.cpp.hpp", but extras/ was in the excluded_dirs set so the
fragment was never copied and the merged-component build died with
'No such file or directory'. Treat extras/ as header-only instead: copy
.h/.hpp/.inl fragments so unity includes resolve, but keep compiling
nothing from it — extras/ traditionally holds repo-only content.
This commit is contained in:
David Montero Crespo 2026-08-19 19:51:10 +02:00
parent 39b2ccf515
commit b6e84c5d71
1 changed files with 20 additions and 2 deletions

View File

@ -1633,13 +1633,25 @@ class ESPIDFCompiler:
excluded_dirs = { excluded_dirs = {
'.git', '.github', '.vscode', '__pycache__', '.git', '.github', '.vscode', '__pycache__',
'docs', 'doc', 'example', 'examples', 'test', 'tests', 'docs', 'doc', 'example', 'examples', 'test', 'tests',
'extras', 'ci', 'fuzz', 'fuzzing', 'benchmark', 'benchmarks', 'ci', 'fuzz', 'fuzzing', 'benchmark', 'benchmarks',
} }
# `extras/` is header-only in the merge: FastLED's unity build
# (src/fl/build/extras+.cpp) does #include
# "extras/_build.cpp.hpp", so dropping the whole dir breaks the
# build with "No such file". Its opt-in shims are all
# .cpp.hpp/.h fragments; copy those, but never compile a
# .c/.cpp that happens to live there (extras/ traditionally
# holds repo-only content).
header_only_dirs = {'extras'}
def _should_include(rel_path: Path) -> bool: def _should_include(rel_path: Path) -> bool:
parts = rel_path.parts parts = rel_path.parts
if any(part.lower() in excluded_dirs for part in parts[:-1]): if any(part.lower() in excluded_dirs for part in parts[:-1]):
return False return False
if (rel_path.suffix.lower() in ('.c', '.cpp')
and any(p.lower() in header_only_dirs
for p in parts[:-1])):
return False
# Copy compiled sources (.c/.cpp) AND every flavour of header # Copy compiled sources (.c/.cpp) AND every flavour of header
# or text-included fragment. `.inl`/`.inc`/`.ipp`/`.tcc` are # or text-included fragment. `.inl`/`.inc`/`.ipp`/`.tcc` are
# `#include`d verbatim from a sibling source (e.g. M5Unified's # `#include`d verbatim from a sibling source (e.g. M5Unified's
@ -2077,18 +2089,24 @@ class ESPIDFCompiler:
'examples', 'examples',
'test', 'test',
'tests', 'tests',
'extras',
'ci', 'ci',
'fuzz', 'fuzz',
'fuzzing', 'fuzzing',
'benchmark', 'benchmark',
'benchmarks', 'benchmarks',
} }
# Same header-only treatment of extras/ as _generate_merged_component:
# unity builds may #include "extras/..." fragments.
header_only_dirs = {'extras'}
def should_include(relative_path: Path) -> bool: def should_include(relative_path: Path) -> bool:
parts = relative_path.parts parts = relative_path.parts
if any(part.lower() in excluded_dirs for part in parts[:-1]): if any(part.lower() in excluded_dirs for part in parts[:-1]):
return False return False
if (relative_path.suffix.lower() in ('.c', '.cpp')
and any(p.lower() in header_only_dirs
for p in parts[:-1])):
return False
if relative_path.suffix not in ('.h', '.hpp', '.c', '.cpp'): if relative_path.suffix not in ('.h', '.hpp', '.c', '.cpp'):
return False return False