Files
2026-06-06 13:28:56 -05:00

115 lines
4.1 KiB
Python

import os
import subprocess
import imgui
import libusb
# IQ.Pilot patch: iqpilot's opendbc fork lacks the upstream `get_generated_dbcs()`
# helper. Use the equivalent `create_all(out_dir)` which writes *_generated.dbc
# files directly to disk.
from opendbc.dbc.generator.generator import create_all as _opendbc_create_all
from opendbc.car import Bus
from opendbc.car.fingerprints import MIGRATION
from opendbc.car.values import PLATFORMS
from openpilot.common.basedir import BASEDIR
Import('env', 'arch', 'common', 'messaging', 'visionipc', 'cereal', 'replay_lib')
jot_env = env.Clone()
jot_env["LIBPATH"] += [imgui.MESA_DIR, libusb.LIB_DIR]
jot_env["CPPPATH"] += [imgui.INCLUDE_DIR, libusb.INCLUDE_DIR]
jot_env["CXXFLAGS"] += [
"-DGLFW_INCLUDE_NONE",
'-DJOTP_REPO_ROOT=\'"%s"\'' % os.path.realpath(BASEDIR),
]
def materialize_generated_dbcs(target, source, env):
out_dir = os.path.dirname(str(target[0]))
os.makedirs(out_dir, exist_ok=True)
# IQ.Pilot patch: opendbc's create_all writes *_generated.dbc files directly
# to out_dir (and clears any stale ones first), matching what upstream's
# get_generated_dbcs()-based loop produced.
_opendbc_create_all(out_dir)
with open(str(target[0]), "w") as f:
f.write("ok\n")
return None
def write_car_fingerprint_to_dbc_header(target, source, env):
pairs = {}
for name, platform in sorted(PLATFORMS.items()):
dbc = platform.config.dbc_dict.get(Bus.pt, "")
if not dbc and name.startswith("TESLA_"):
dbc = platform.config.dbc_dict.get(Bus.party, "")
if not dbc and name == "COMMA_BODY":
dbc = "comma_body"
if dbc and name != "MOCK":
pairs[name] = dbc
for fingerprint, car in sorted(MIGRATION.items()):
dbc = pairs.get(str(car), "")
if dbc:
pairs[fingerprint] = dbc
lines = [
"#pragma once",
"",
"#include <string_view>",
"#include <utility>",
"",
"inline constexpr std::pair<std::string_view, std::string_view> kCarFingerprintToDbc[] = {",
]
lines.extend(f' {{"{fingerprint}", "{dbc}"}},' for fingerprint, dbc in sorted(pairs.items()))
lines.extend([
"};",
"",
"inline std::string_view dbc_for_car_fingerprint(std::string_view fingerprint) {",
" for (const auto &[car_fingerprint, dbc] : kCarFingerprintToDbc) {",
" if (car_fingerprint == fingerprint) return dbc;",
" }",
" return {};",
"}",
"",
])
with open(str(target[0]), "w") as f:
f.write("\n".join(lines))
return None
def generate_event_extractors(target, source, env):
subprocess.check_call([
"python3",
"tools/jotpluggler/generate_event_extractors.py",
os.path.realpath(BASEDIR),
str(target[0]),
])
return None
generated_dbc_stamp = jot_env.Command(f"generated_dbcs/.stamp", [], materialize_generated_dbcs)
car_fingerprint_to_dbc = jot_env.Command("car_fingerprint_to_dbc.h", [], write_car_fingerprint_to_dbc_header)
event_extractors = jot_env.Command("generated_event_extractors.h", [
"generate_event_extractors.py",
jot_env.Glob("#cereal/*.capnp"),
jot_env.Glob("#cereal/include/*.capnp"),
],
generate_event_extractors,
)
libs = [replay_lib, common, messaging, visionipc, cereal, File(f"{imgui.LIB_DIR}/libimgui.a"), File(f"{imgui.LIB_DIR}/libglfw3.a"),
# IQ.Pilot patch: iqpilot's replay_lib resolves URL/api work via libcurl
# (vs upstream's Python downloader), so jotpluggler needs to link curl too.
# iqpilot's api.cc additionally uses OpenSSL primitives (PEM/RSA/SHA256) for
# JWT signing, and visionipc references OpenCL — both must also be linked.
"avformat", "avcodec", "avutil", "x264", "yuv", "z", "bz2", "zstd", "curl", "ssl", "crypto", "m", "pthread", "usb-1.0"]
if arch == "Darwin":
jot_env["FRAMEWORKS"] = ["OpenGL", "OpenCL", "Cocoa", "IOKit", "CoreFoundation", "CoreVideo", "CoreMedia", "VideoToolbox"]
else:
libs += ["GL", "OpenCL", "dl", "va", "va-drm", "drm"]
program = jot_env.Program("jotpluggler", jot_env.Glob("*.cc"), LIBS=libs)
jot_env.Depends(program, generated_dbc_stamp)
jot_env.Depends(program, car_fingerprint_to_dbc)
jot_env.Depends(program, event_extractors)