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.
93 lines
4.7 KiB
Python
93 lines
4.7 KiB
Python
"""Derive feature-preserving role definitions from effective application sources.
|
|
|
|
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. 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()
|
|
SPEC = importlib.util.spec_from_file_location("client_acl_source_policy", SCRIPT_DIR / "nrf52_flash_trim.py")
|
|
SOURCE_POLICY = importlib.util.module_from_spec(SPEC)
|
|
SPEC.loader.exec_module(SOURCE_POLICY)
|
|
|
|
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=()):
|
|
values = SOURCE_POLICY.flag_defines(flags, cppdefines)
|
|
selected = SOURCE_POLICY.source_selected
|
|
qualified = (all(selected(src_filter, source) for source in REPEATER_SOURCES)
|
|
and not any(selected(src_filter, "../examples/" + role + "/main.cpp")
|
|
or selected(src_filter, "../examples/" + role + "/MyMesh.cpp")
|
|
or selected(src_filter, "../examples/" + role + "/SensorMesh.cpp")
|
|
for role in OTHER_ROLES)
|
|
and not any(name.startswith("COMPANION_") for name in values))
|
|
if DEFINITION in values:
|
|
value = values[DEFINITION]
|
|
text = "0" if value is None else str(value).strip("\"'() ")
|
|
if text not in ("0", "1"):
|
|
raise ValueError(DEFINITION + " override must be 0 or 1")
|
|
if text == "1" and not qualified:
|
|
raise ValueError(DEFINITION + "=1 requires only the repeater source role")
|
|
return {}
|
|
return {DEFINITION: 1} if qualified else {}
|
|
|
|
|
|
def install(build_env):
|
|
src_filter = build_env.get("SRC_FILTER")
|
|
if src_filter is None:
|
|
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()))
|
|
|
|
|
|
if "Import" in globals():
|
|
Import("env")
|
|
install(env)
|