mirror of
https://github.com/meshtastic/firmware.git
synced 2026-09-16 08:30:04 -04:00
* Load optional modules dropped into src/modules/optional/ bin/optional-modules.py scans src/modules/optional/ for a directory <Name>/ holding <Name>.h and generates $BUILD_DIR/OptionalModules.h with an include and a setup<Name>() call for each, which Modules.cpp picks up through __has_include. The directory does not exist in a stock checkout, so a stock build generates a header that defines nothing, OPTIONAL_MODULES_SETUP compiles away, and nothing is registered. Sources under the directory are already covered by the default recursive build_src_filter, so dropping a module in needs no platformio.ini edit. * Address review: skip a module directory that is not a usable identifier The directory name becomes a setup<Name>() call, so foo-bar/ would have generated setupfoo-bar() and failed to compile with the error pointing at generated code rather than at the directory. Names that cannot form an identifier are now skipped with a message that names the directory.
67 lines
2.4 KiB
Python
67 lines
2.4 KiB
Python
#!/usr/bin/env python3
|
|
# trunk-ignore-all(ruff/F821)
|
|
# trunk-ignore-all(flake8/F821): For SConstruct imports
|
|
#
|
|
# Registers optional modules dropped into src/modules/optional/.
|
|
#
|
|
# A module is a directory <Name>/ holding <Name>.h, which declares `void setup<Name>();`. This
|
|
# writes $BUILD_DIR/OptionalModules.h with an include and a setup call for each one found;
|
|
# Modules.cpp picks that header up through __has_include and calls OPTIONAL_MODULES_SETUP().
|
|
#
|
|
# src/modules/optional/ does not exist in a stock checkout, so a stock build generates a header that
|
|
# defines nothing and registers nothing. Sources under the directory are compiled by the default
|
|
# recursive build_src_filter, so dropping a module in needs no platformio.ini edit.
|
|
import os
|
|
import re
|
|
|
|
Import("env")
|
|
|
|
# The directory name becomes a C++ call, so it has to be a usable identifier.
|
|
identifier = re.compile(r"^[A-Za-z_][A-Za-z0-9_]*$")
|
|
|
|
optionalDir = os.path.join(env["PROJECT_DIR"], "src", "modules", "optional")
|
|
|
|
names = []
|
|
if os.path.isdir(optionalDir):
|
|
for entry in sorted(os.listdir(optionalDir)):
|
|
entryDir = os.path.join(optionalDir, entry)
|
|
if not os.path.isdir(entryDir):
|
|
continue
|
|
if not identifier.match(entry):
|
|
print(f"optional-modules: skipping {entry}/, setup{entry}() is not a valid identifier")
|
|
elif os.path.isfile(os.path.join(entryDir, entry + ".h")):
|
|
names.append(entry)
|
|
else:
|
|
print(f"optional-modules: skipping {entry}/, no {entry}.h")
|
|
|
|
lines = ["// Generated by bin/optional-modules.py. Do not edit.", "#pragma once", ""]
|
|
for name in names:
|
|
lines.append(f'#include "modules/optional/{name}/{name}.h"')
|
|
if names:
|
|
lines.append("")
|
|
lines.append("#define OPTIONAL_MODULES_SETUP() \\")
|
|
lines.append(" do { \\")
|
|
for name in names:
|
|
lines.append(f" setup{name}(); \\")
|
|
lines.append(" } while (0)")
|
|
lines.append("")
|
|
content = "\n".join(lines)
|
|
|
|
buildDir = env.subst("$BUILD_DIR")
|
|
os.makedirs(buildDir, exist_ok=True)
|
|
header = os.path.join(buildDir, "OptionalModules.h")
|
|
|
|
# Rewrite only on a change, so an unchanged set of modules does not keep rebuilding Modules.cpp.
|
|
previous = None
|
|
if os.path.isfile(header):
|
|
with open(header, encoding="utf-8") as f:
|
|
previous = f.read()
|
|
if previous != content:
|
|
with open(header, "w", encoding="utf-8") as f:
|
|
f.write(content)
|
|
|
|
env.Append(CPPPATH=[buildDir])
|
|
|
|
if names:
|
|
print("optional-modules: " + ", ".join(names))
|