Files
unleashed-firmware/scripts/fbt
Mykhailo ShevchukandClaude Opus 5 83fbee38f1 fbt: fix built-in app source exclusions, and move the SubGHz feature plugins under the app (#1135)
* fbt: make a built-in app's source exclusions actually exclude

GatherSources() splits the list it is given into includes and "!exclusions" and
applies the second to the first, so an exclusion only ever filters the patterns
handed over in the same call. External apps pass their whole source list at once
(fbt_extapps.py) and get what they asked for. The built-in path did not:
get_builtin_app_folders() flattened each app to one (folder, pattern) pair per
source entry, and firmware.scons called GatherSources() once per pair - so
"*.c*" was gathered with no exclusions in sight and "!plugins" arrived alone
with nothing to filter.

Merging per app is not enough either. Sources are gathered per folder and a
folder can hold more than one built-in app: applications/main/subghz has an APP
beside a STARTUP hook, and the hook's default "*.c*" would re-glob whatever the
app excluded. So collect one list per folder, merged across the built-in apps
that live there, and pass it in a single call.

That merge is also why GatherSources() now de-duplicates with dict.fromkeys()
instead of a set(). Its result is the link order, and a folder that merges to
more than one include pattern - applications/services/cli and
applications/system/find_my_flipper both do - would otherwise have that order
decided by PYTHONHASHSEED. Two builds of one tree could differ in ~10 KB of
firmware.bin. External apps were already exposed to this; they no longer are.

No built-in app in the tree declares an exclusion today, so this changes no
output: with the version blob pinned (WORKFLOW_BRANCH_OR_TAG, DIST_SUFFIX,
FORCE_NO_DIRTY, SOURCE_DATE_EPOCH) the firmware differs from dev only in the
8-byte embedded git hash and 2 bytes that track it, and two builds at different
PYTHONHASHSEED values are byte-identical. What it unblocks is a built-in app
keeping plugin sources in a subfolder the way NFC does.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* SubGHz: move the feature plugins into the app they belong to

subghz_add_manually and subghz_frequency_analyzer sat in applications/main as
siblings of nfc, lfrfid and the rest - directories that read as main apps, are
not in the main_apps metapackage, and are not apps at all. They were there
because a built-in app could not exclude sources: everything under
applications/main/subghz is compiled into the firmware, and the six scene
thunks the app keeps in scenes/ carry the same symbol names as the bodies that
moved into the plugin, so the image would not have linked at all. The previous
commit is a hard prerequisite, not an optimisation.

They now live in applications/main/subghz/plugins/, declared in the app's own
manifest with sources= pointing at their folders, which is how NFC keeps its
plugins - 45 card parsers under plugins/supported_cards and 16 protocol-support
plugins under helpers/protocol_support. The app excludes plugins/ from its own
sources.

Nothing about the output changes: same appids, so the same .fal files still
deploy to apps_data/subghz/plugins, and with the version blob pinned the
firmware differs from the previous commit only in the embedded git hash. The
.fal files keep their size; their bytes differ only in the .gnu_debuglink CRC,
which follows the debug ELF's DWARF now carrying the new source paths.

The plugin sources keep including <subghz/...>, which still resolves -
applications/main is on the global include path either way.

One developer-facing wrinkle, shared with every other co-located plugin in the
tree: fbt launch APPSRC=<path to the plugin folder> no longer resolves, because
the path lookup matches the parent directory name and finds the built-in app.
APPSRC=subghz_add_manually, by appid, still works.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Changelog

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-08 22:24:21 +03:00
..
2024-03-22 23:43:09 +03:00