Share constrained STM32 code while preserving firmware features

Omit unbound forwarding-region callbacks only for exclusive Companion source roles. Reuse the compact neighbor sorter in repeaters for every RPC order and the CLI list, removing duplicate sort implementations while preserving storage and size gates.
This commit is contained in:
mikecarper committed 2026-10-27 08:17:23 -07:00
1 parent 2b55ff6a62
commit c650278fa7
7 files changed
+216 -28

No files matched your search

+40 -3
View File
@@ -1,12 +1,14 @@
"""Use the smaller ClientInfo layout only for an effective repeater source role.
"""Derive feature-preserving role definitions from effective application sources.
One shared compiler definition covers application and helper translation units.
Shared compiler definitions cover application and helper translation units.
Unknown/custom roles keep the complete layout; room and sensor session fields
are never removed from builds that use them.
are never removed from builds that use them. Companions omit only unbound
forwarding-region callbacks because that role has no RegionMap.
"""
import importlib.util
from pathlib import Path
import re
SCRIPT_DIR = Path(__file__).resolve().parent if "__file__" in globals() else Path("scripts").resolve()
@@ -18,6 +20,39 @@ DEFINITION = "MESH_CLIENT_REPEATER_ONLY"
REPEATER_SOURCES = ("../examples/simple_repeater/main.cpp", "../examples/simple_repeater/MyMesh.cpp")
OTHER_ROLES = ("simple_room_server", "simple_sensor", "companion_radio", "simple_secure_chat",
"kiss_modem", "partition_expander", "esp32_partition_migrator", "esp32_partition_legacy_seed")
COMPANION_DEFINITION = "MESH_ROLE_COMPANION"
COMPANION_SOURCES = ("../examples/companion_radio/main.cpp", "../examples/companion_radio/MyMesh.cpp")
def companion_role_policy(src_filter, flags=(), cppdefines=()):
"""Exclude unbound forwarding-scope callbacks, retaining all radio commands.
Companions have no RegionMap. Select the complete exclusive source role,
never an environment-name alias, so every translation unit shares its ABI.
Unknown and mixed roles retain the general callback implementation.
"""
values = SOURCE_POLICY.flag_defines(flags, cppdefines)
selected = SOURCE_POLICY.source_selected
other_roles = ("simple_repeater", *(role for role in OTHER_ROLES
if role != "companion_radio"))
filter_text = src_filter if isinstance(src_filter, str) else " ".join(map(str, src_filter))
example_includes = re.findall(r"\+<\.\./examples/([^>]+)>", filter_text.replace("\\", "/"))
known_companion_only = all(path == "companion_radio" or path.startswith("companion_radio/")
for path in example_includes)
qualified = (known_companion_only
and all(selected(src_filter, source) for source in COMPANION_SOURCES)
and not any(selected(src_filter, "../examples/" + role + "/" + source)
for role in other_roles
for source in ("main.cpp", "MyMesh.cpp", "SensorMesh.cpp")))
if COMPANION_DEFINITION in values:
value = values[COMPANION_DEFINITION]
text = "0" if value is None else str(value).strip("\"'() ")
if text not in ("0", "1"):
raise ValueError(COMPANION_DEFINITION + " override must be 0 or 1")
if text == "1" and not qualified:
raise ValueError(COMPANION_DEFINITION + "=1 requires only the Companion source role")
return {}
return {COMPANION_DEFINITION: 1} if qualified else {}
def role_policy(src_filter, flags=(), cppdefines=()):
@@ -46,6 +81,8 @@ def install(build_env):
src_filter = build_env.GetProjectOption("build_src_filter", "")
definitions = role_policy(src_filter, build_env.get("BUILD_FLAGS", ()),
build_env.get("CPPDEFINES", ()))
definitions.update(companion_role_policy(src_filter, build_env.get("BUILD_FLAGS", ()),
build_env.get("CPPDEFINES", ())))
if definitions:
build_env.AppendUnique(CPPDEFINES=list(definitions.items()))