mirror of
https://github.com/Colorado-Mesh/meshcore-bot-firmware.git
synced 2026-08-11 08:10:29 +00:00
build: enable bot on all companion_radio_(usb|ble) envs
Upstream MeshCore only added ${cmesh_bot_production.build_flags} to
Heltec V3 and RAK 4631 companion envs. Every other companion build
target (~129 envs across 64 boards) compiled without CMESH_BOT_ENABLED,
so the bot code was stripped at preprocessing and the firmware behaved
like stock MeshCore (no replies on #bot).
Caught when a tester reported the Heltec V4 build wouldn't respond to
commands. The fix isn't board-specific -- it applies to every variant
in the release matrix.
Adds scripts/enable-bot-on-companion-envs.py: scans
vendor/MeshCore/variants/*/platformio.ini, finds every
*_companion_radio_(usb|ble) env, injects ${cmesh_bot_production.build_flags}
into its build_flags block (idempotent). Hooks into apply-patches.sh
so every local / CI build picks it up.
Choosing a script over a vendor patch keeps us robust to upstream
adding new boards: we don't have to maintain a per-variant patch.
This commit is contained in:
@@ -29,3 +29,5 @@ for patch in "${patches[@]}"; do
|
|||||||
done
|
done
|
||||||
|
|
||||||
echo "Applied ${#patches[@]} MeshCore patch(es) to $(meshcore_commit)"
|
echo "Applied ${#patches[@]} MeshCore patch(es) to $(meshcore_commit)"
|
||||||
|
|
||||||
|
python3 "${MESHCORE_FW_ROOT}/scripts/enable-bot-on-companion-envs.py"
|
||||||
|
|||||||
102
scripts/enable-bot-on-companion-envs.py
Executable file
102
scripts/enable-bot-on-companion-envs.py
Executable file
@@ -0,0 +1,102 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Inject ${cmesh_bot_production.build_flags} into every
|
||||||
|
*_companion_radio_(usb|ble) env across vendor/MeshCore/variants/.
|
||||||
|
|
||||||
|
Run after scripts/apply-patches.sh. Idempotent: skips envs that already
|
||||||
|
include the flag.
|
||||||
|
|
||||||
|
Upstream MeshCore only includes cmesh_bot_production in Heltec V3 and
|
||||||
|
RAK 4631 variants. For our release matrix (133 companion envs) we want
|
||||||
|
the bot enabled everywhere, and we don't want to maintain a patch
|
||||||
|
that has to be kept in sync with every new upstream board.
|
||||||
|
"""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
ROOT = Path(__file__).resolve().parents[1] / "vendor" / "MeshCore" / "variants"
|
||||||
|
ENV_HEADER = re.compile(r"^\[env:[A-Za-z0-9_-]+_companion_radio_(?:usb|ble)\]\s*$")
|
||||||
|
NEW_SECTION = re.compile(r"^\[")
|
||||||
|
INJECT_LINE = " ${cmesh_bot_production.build_flags}"
|
||||||
|
|
||||||
|
|
||||||
|
def process_file(path: Path) -> int:
|
||||||
|
lines = path.read_text().splitlines()
|
||||||
|
out: list[str] = []
|
||||||
|
i = 0
|
||||||
|
injected = 0
|
||||||
|
while i < len(lines):
|
||||||
|
line = lines[i]
|
||||||
|
if ENV_HEADER.match(line):
|
||||||
|
# Collect this env block until the next [section] header (or EOF).
|
||||||
|
j = i + 1
|
||||||
|
while j < len(lines) and not NEW_SECTION.match(lines[j]):
|
||||||
|
j += 1
|
||||||
|
block = lines[i:j]
|
||||||
|
|
||||||
|
if "${cmesh_bot_production.build_flags}" in "\n".join(block):
|
||||||
|
out.extend(block)
|
||||||
|
else:
|
||||||
|
# Find the last indented continuation line of the build_flags block
|
||||||
|
# so we can append the injection after it.
|
||||||
|
in_flags = False
|
||||||
|
last_flag_idx = -1
|
||||||
|
for k, ln in enumerate(block):
|
||||||
|
stripped = ln.lstrip()
|
||||||
|
if stripped.startswith("build_flags"):
|
||||||
|
in_flags = True
|
||||||
|
last_flag_idx = k
|
||||||
|
elif in_flags:
|
||||||
|
# A continuation line of build_flags must be indented
|
||||||
|
# with whitespace; comments and blanks don't count.
|
||||||
|
if (ln.startswith(" ") or ln.startswith("\t")) and not stripped.startswith(";"):
|
||||||
|
last_flag_idx = k
|
||||||
|
elif ln.startswith(" ") or ln.startswith("\t"):
|
||||||
|
# An indented comment - stays inside the block but doesn't
|
||||||
|
# change the insertion point.
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
# Hit a non-indented line (likely build_src_filter or lib_deps).
|
||||||
|
in_flags = False
|
||||||
|
if last_flag_idx >= 0:
|
||||||
|
block = block[: last_flag_idx + 1] + [INJECT_LINE] + block[last_flag_idx + 1 :]
|
||||||
|
injected += 1
|
||||||
|
out.extend(block)
|
||||||
|
i = j
|
||||||
|
continue
|
||||||
|
out.append(line)
|
||||||
|
i += 1
|
||||||
|
|
||||||
|
if injected > 0:
|
||||||
|
path.write_text("\n".join(out) + "\n")
|
||||||
|
return injected
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> int:
|
||||||
|
if not ROOT.is_dir():
|
||||||
|
print(f"variants dir not found: {ROOT}", file=sys.stderr)
|
||||||
|
return 1
|
||||||
|
|
||||||
|
total = 0
|
||||||
|
files_touched = 0
|
||||||
|
for ini in sorted(ROOT.rglob("platformio.ini")):
|
||||||
|
n = process_file(ini)
|
||||||
|
if n:
|
||||||
|
print(f" + {ini.relative_to(ROOT.parent.parent.parent)}: injected into {n} env(s)")
|
||||||
|
files_touched += 1
|
||||||
|
total += n
|
||||||
|
|
||||||
|
if total == 0:
|
||||||
|
print("All companion_radio_(usb|ble) envs already include cmesh_bot_production.build_flags.")
|
||||||
|
else:
|
||||||
|
print(
|
||||||
|
f"Injected cmesh_bot_production.build_flags into {total} env(s) "
|
||||||
|
f"across {files_touched} variant file(s)."
|
||||||
|
)
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
sys.exit(main())
|
||||||
Reference in New Issue
Block a user