Skip to content

Commit 0eff6b0

Browse files
adeebshihadehclaude
andcommitted
replace git submodules with proper Python package dependencies
Convert teleoprtc, panda, opendbc, rednose, and msgq from git submodules/symlinks to git URL dependencies in pyproject.toml. Inline msgq and rednose SCons build logic into the top-level SConstruct, and source opendbc DBC generation from the installed package path. Remove panda firmware SConscript call. Clean up tool config exclusions and CI references for removed submodule dirs. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent a694d05 commit 0eff6b0

File tree

24 files changed

+155
-93
lines changed

24 files changed

+155
-93
lines changed

.github/labeler.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ CI / testing:
44

55
car:
66
- changed-files:
7-
- any-glob-to-all-files: '{selfdrive/car/**,opendbc_repo}'
7+
- any-glob-to-all-files: 'selfdrive/car/**'
88

99
simulation:
1010
- changed-files:

.github/workflows/repo-maintenance.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ jobs:
6868
git add .
6969
- name: update car docs
7070
run: |
71-
scons -j$(nproc) --minimal opendbc_repo
71+
scons -j$(nproc) --minimal
7272
python selfdrive/car/docs.py
7373
git add docs/CARS.md
7474
- name: Create Pull Request

.github/workflows/tests.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ jobs:
142142
- name: Build openpilot
143143
run: scons -j$(nproc)
144144
- name: Run unit tests
145-
timeout-minutes: ${{ contains(runner.name, 'nsc') && ((steps.setup-step.outputs.duration < 18) && 1 || 2) || 20 }}
145+
timeout-minutes: ${{ contains(runner.name, 'nsc') && ((steps.setup-step.outputs.duration < 18) && 3 || 5) || 20 }}
146146
run: |
147147
source selfdrive/test/setup_xvfb.sh
148148
# Pre-compile Python bytecode so each pytest worker doesn't need to
@@ -172,7 +172,7 @@ jobs:
172172
- name: Build openpilot
173173
run: scons -j$(nproc)
174174
- name: Run replay
175-
timeout-minutes: ${{ contains(runner.name, 'nsc') && (steps.dependency-cache.outputs.cache-hit == 'true') && ((steps.setup-step.outputs.duration < 18) && 1 || 2) || 20 }}
175+
timeout-minutes: ${{ contains(runner.name, 'nsc') && (steps.dependency-cache.outputs.cache-hit == 'true') && ((steps.setup-step.outputs.duration < 18) && 3 || 5) || 20 }}
176176
continue-on-error: ${{ github.ref == 'refs/heads/master' }}
177177
run: selfdrive/test/process_replay/test_processes.py -j$(nproc)
178178
- name: Print diff

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ compile_commands.json
4545
compare_runtime*.html
4646

4747
selfdrive/pandad/pandad
48+
cereal/car.capnp
4849
cereal/services.h
4950
cereal/gen
5051
cereal/messaging/bridge

.gitmodules

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,3 @@
1-
[submodule "panda"]
2-
path = panda
3-
url = ../../commaai/panda.git
4-
[submodule "opendbc"]
5-
path = opendbc_repo
6-
url = ../../commaai/opendbc.git
7-
[submodule "msgq"]
8-
path = msgq_repo
9-
url = ../../commaai/msgq.git
10-
[submodule "rednose_repo"]
11-
path = rednose_repo
12-
url = ../../commaai/rednose.git
13-
[submodule "teleoprtc_repo"]
14-
path = teleoprtc_repo
15-
url = ../../commaai/teleoprtc
161
[submodule "tinygrad"]
172
path = tinygrad_repo
183
url = https://github.com/tinygrad/tinygrad.git

SConstruct

Lines changed: 58 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ import sysconfig
55
import platform
66
import shlex
77
import numpy as np
8+
import opendbc
9+
import panda as _panda
10+
import rednose
11+
import msgq as _msgq
812

913
import SCons.Errors
1014

@@ -65,7 +69,9 @@ env = Environment(
6569
CXXFLAGS=["-std=c++1z"],
6670
CPPPATH=[
6771
"#",
68-
"#msgq",
72+
_msgq.INCLUDE_PATH,
73+
_panda.INCLUDE_PATH,
74+
rednose.BASEDIR,
6975
"#third_party",
7076
"#third_party/json11",
7177
"#third_party/linux/include",
@@ -77,19 +83,18 @@ env = Environment(
7783
],
7884
LIBPATH=[
7985
"#common",
80-
"#msgq_repo",
8186
"#third_party",
8287
"#selfdrive/pandad",
83-
"#rednose/helpers",
88+
rednose.HELPERS_PATH,
8489
f"#third_party/libyuv/{arch}/lib",
8590
f"#third_party/acados/{arch}/lib",
8691
],
8792
RPATH=[],
8893
CYTHONCFILESUFFIX=".cpp",
8994
COMPILATIONDB_USE_ABSPATH=True,
90-
REDNOSE_ROOT="#",
95+
REDNOSE_ROOT=rednose.INCLUDE_PATH,
9196
tools=["default", "cython", "compilation_db", "rednose_filter"],
92-
toolpath=["#site_scons/site_tools", "#rednose_repo/site_scons/site_tools"],
97+
toolpath=["#site_scons/site_tools", rednose.SITE_SCONS_TOOLS],
9398
)
9499

95100
# Arch-specific flags and paths
@@ -182,21 +187,61 @@ Export('common')
182187
# Enable swaglog include in submodules
183188
env_swaglog = env.Clone()
184189
env_swaglog['CXXFLAGS'].append('-DSWAGLOG="\\"common/swaglog.h\\""')
185-
SConscript(['msgq_repo/SConscript'], exports={'env': env_swaglog})
186-
SConscript(['opendbc_repo/SConscript'], exports={'env': env_swaglog})
190+
191+
# Build msgq from installed package
192+
msgq_dir = _msgq.BASEDIR
193+
vipc_dir = os.path.join(msgq_dir, 'visionipc')
194+
195+
msgq_sources = [os.path.join(msgq_dir, f) for f in
196+
['ipc.cc', 'event.cc', 'impl_msgq.cc', 'impl_fake.cc', 'msgq.cc']]
197+
msgq_objects = env_swaglog.SharedObject(msgq_sources)
198+
msgq_lib = env.Library('msgq', msgq_objects)
199+
msgq_python = envCython.Program(os.path.join(msgq_dir, 'ipc_pyx.so'),
200+
os.path.join(msgq_dir, 'ipc_pyx.pyx'),
201+
LIBS=envCython["LIBS"]+[msgq_lib, common])
202+
203+
vipc_files = ['visionipc.cc', 'visionipc_server.cc', 'visionipc_client.cc']
204+
vipc_files += ['visionbuf_ion.cc'] if arch == "larch64" else ['visionbuf.cc']
205+
vipc_sources = [os.path.join(vipc_dir, f) for f in vipc_files]
206+
vipc_objects = env.SharedObject(vipc_sources)
207+
visionipc = env.Library('visionipc', vipc_objects)
208+
envCython.Program(os.path.join(vipc_dir, 'visionipc_pyx.so'),
209+
os.path.join(vipc_dir, 'visionipc_pyx.pyx'),
210+
LIBS=envCython["LIBS"] + [visionipc, msgq_lib, common])
211+
Export('visionipc', 'msgq_lib', 'msgq_python')
187212

188213
SConscript(['cereal/SConscript'])
189214

190-
Import('socketmaster', 'msgq')
191-
messaging = [socketmaster, msgq, 'capnp', 'kj',]
215+
Import('socketmaster')
216+
messaging = [socketmaster, msgq_lib, 'capnp', 'kj',]
192217
Export('messaging')
193218

194219

195-
# Build other submodules
196-
SConscript(['panda/SConscript'])
197-
198220
# Build rednose library
199-
SConscript(['rednose/SConscript'])
221+
Import('_common')
222+
rednose_helpers = rednose.HELPERS_PATH
223+
rednose_cc = [os.path.join(rednose_helpers, f) for f in ['ekf_load.cc', 'ekf_sym.cc']]
224+
ekf_objects = env.SharedObject(rednose_cc)
225+
rednose_lib = env.Library(os.path.join(rednose_helpers, 'ekf_sym'), ekf_objects, LIBS=['dl', _common, 'zmq'])
226+
rednose_python = envCython.Program(os.path.join(rednose_helpers, 'ekf_sym_pyx.so'),
227+
[os.path.join(rednose_helpers, 'ekf_sym_pyx.pyx'), ekf_objects],
228+
LIBS=['dl'] + envCython["LIBS"])
229+
Export('rednose_lib', 'rednose_python')
230+
231+
# Build opendbc libsafety for tests
232+
safety_dir = os.path.join(os.path.dirname(opendbc.__file__), 'safety', 'tests', 'libsafety')
233+
if GetOption('extras') and os.path.exists(os.path.join(safety_dir, 'safety.c')):
234+
safety_env = Environment(
235+
CC='clang',
236+
CFLAGS=['-Wall', '-Wextra', '-Werror', '-nostdlib', '-fno-builtin', '-std=gnu11',
237+
'-Wfatal-errors', '-Wno-pointer-to-int-cast', '-g', '-O0',
238+
'-fno-omit-frame-pointer', '-grecord-command-line', '-DALLOW_DEBUG'],
239+
LINKFLAGS=['-fsanitize=undefined', '-fno-sanitize-recover=undefined'],
240+
CPPPATH=[os.path.dirname(opendbc.__file__) + "/.."],
241+
tools=["default"],
242+
)
243+
safety = safety_env.SharedObject(os.path.join(safety_dir, "safety.os"), os.path.join(safety_dir, "safety.c"))
244+
safety_env.SharedLibrary(os.path.join(safety_dir, "libsafety.so"), [safety])
200245

201246
# Build system services
202247
SConscript([

cereal/SConscript

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
Import('env', 'common', 'msgq')
1+
Import('env', 'common', 'msgq_lib')
22

33
cereal_dir = Dir('.')
44
gen_dir = Dir('gen')
@@ -13,7 +13,7 @@ cereal = env.Library('cereal', [f'gen/cpp/{s}.c++' for s in schema_files])
1313

1414
# Build messaging
1515
services_h = env.Command(['services.h'], ['services.py'], 'python3 ' + cereal_dir.path + '/services.py > $TARGET')
16-
env.Program('messaging/bridge', ['messaging/bridge.cc', 'messaging/msgq_to_zmq.cc', 'messaging/bridge_zmq.cc'], LIBS=[msgq, common, 'pthread'])
16+
env.Program('messaging/bridge', ['messaging/bridge.cc', 'messaging/msgq_to_zmq.cc', 'messaging/bridge_zmq.cc'], LIBS=[msgq_lib, common, 'pthread'])
1717

1818
socketmaster = env.Library('socketmaster', ['messaging/socketmaster.cc'])
1919

cereal/__init__.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,13 @@
44

55
capnp.remove_import_hook()
66

7+
# Ensure car.capnp symlink exists (source of truth is opendbc package)
78
with as_file(files("cereal")) as fspath:
89
CEREAL_PATH = fspath.as_posix()
10+
car_capnp = os.path.join(CEREAL_PATH, "car.capnp")
11+
if not os.path.exists(car_capnp):
12+
import opendbc
13+
os.symlink(os.path.join(os.path.dirname(opendbc.__file__), 'car', 'car.capnp'), car_capnp)
914
log = capnp.load(os.path.join(CEREAL_PATH, "log.capnp"))
1015
car = capnp.load(os.path.join(CEREAL_PATH, "car.capnp"))
1116
custom = capnp.load(os.path.join(CEREAL_PATH, "custom.capnp"))

cereal/car.capnp

Lines changed: 0 additions & 1 deletion
This file was deleted.

msgq

Lines changed: 0 additions & 1 deletion
This file was deleted.

0 commit comments

Comments
 (0)