Files
StarPilot/opendbc_repo/opendbc/dbc/generator/generator.py
T
firestar5683 22a8575199 Vendor dependencies and resources for standalone builds
Keep official openpilot ancestry and dependency licenses. Store resources directly in Git, remove LFS setup requirements, and leave the downloadable big model outside the source tree.
2026-10-03 21:01:18 +00:00

93 lines
3.0 KiB
Python
Executable File

#!/usr/bin/env python3
import importlib
import os
import re
from pathlib import Path
generator_path = os.path.dirname(os.path.realpath(__file__))
include_pattern = re.compile(r'CM_ "IMPORT (.*?)";\n')
def _read_dbc(src_dir: str, filename: str, extra_files: dict[str, str] | None = None) -> str:
if extra_files and filename in extra_files:
return extra_files[filename]
with open(os.path.join(src_dir, filename), encoding='utf-8') as file_in:
return file_in.read()
def _create_dbc_content(src_dir: str, filename: str, extra_files: dict[str, str] | None = None) -> str:
dbc_file_in = _read_dbc(src_dir, filename, extra_files)
includes = include_pattern.findall(dbc_file_in)
parts = ['CM_ "AUTOGENERATED FILE, DO NOT EDIT";\n']
for include_filename in includes:
parts.append(f'\n\nCM_ "Imported file {include_filename} starts here";\n')
parts.append(_read_dbc(src_dir, include_filename, extra_files))
parts.append(f'\nCM_ "{filename} starts here";\n')
core_dbc = include_pattern.sub('', dbc_file_in)
parts.append(core_dbc)
return ''.join(parts)
def _collect_script_outputs() -> dict[str, dict[str, str]]:
"""Import and call generate() from each sub-generator script.
Returns {dir_name: {filename: content}}."""
outputs: dict[str, dict[str, str]] = {}
for py_file in sorted(Path(generator_path).rglob("*.py")):
if py_file.name.startswith("test_") or py_file.name == "generator.py":
continue
dir_name = py_file.parent.name
module_name = f"opendbc.dbc.generator.{dir_name}.{py_file.stem}"
mod = importlib.import_module(module_name)
if hasattr(mod, 'generate'):
outputs.setdefault(dir_name, {}).update(mod.generate())
return outputs
def generate_all() -> dict[str, str]:
"""Generate all DBC content in memory. Returns {name: content} where name has no .dbc extension."""
script_outputs = _collect_script_outputs()
result = {}
for src_dir, _, filenames in os.walk(generator_path):
if src_dir == generator_path:
continue
dir_name = os.path.basename(src_dir)
extra = script_outputs.get(dir_name, {})
# all non-_ .dbc files: on-disk templates + script-generated
all_dbc_files = {f for f in filenames if f.endswith('.dbc') and not f.startswith('_')}
all_dbc_files |= {f for f in extra if not f.startswith('_')}
for filename in sorted(all_dbc_files):
output_name = filename.replace('.dbc', '_generated')
content = _create_dbc_content(src_dir, filename, extra)
result[output_name] = content
return result
def create_all(output_path: str):
"""Generate all DBC files and write them to output_path (for backward compatibility)."""
import glob
generated_suffix = '_generated.dbc'
# clear out old generated DBCs
for f in glob.glob(os.path.join(output_path, f"*{generated_suffix}")):
os.remove(f)
for name, content in generate_all().items():
with open(os.path.join(output_path, name + '.dbc'), 'w', encoding='utf-8') as f:
f.write(content)
if __name__ == "__main__":
opendbc_root = os.path.join(generator_path, '../')
create_all(opendbc_root)