diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml index d9b30a90ca..a6f06a604d 100644 --- a/.github/workflows/tests.yaml +++ b/.github/workflows/tests.yaml @@ -34,6 +34,8 @@ jobs: contents: read steps: - uses: actions/checkout@v7 + - name: Check shipped device runtime dependencies + run: python3 -m unittest tools.laptop_device_build.tests.test_runtime_dependencies -v - name: Validate tracked dependencies run: python3 tools/vendor/check.py --revision HEAD - run: ./tools/op.sh setup diff --git a/tools/laptop_device_build/tests/test_runtime_dependencies.py b/tools/laptop_device_build/tests/test_runtime_dependencies.py new file mode 100644 index 0000000000..a0d22dcc01 --- /dev/null +++ b/tools/laptop_device_build/tests/test_runtime_dependencies.py @@ -0,0 +1,24 @@ +"""Catch device binaries linked to build-environment Cap'n Proto/KJ libraries.""" + +from pathlib import Path +import subprocess +import sys +import unittest + + +ROOT = Path(__file__).resolve().parents[3] + + +@unittest.skipUnless(sys.platform.startswith('linux'), 'Requires Linux readelf') +class DeviceRuntimeDependenciesTest(unittest.TestCase): + def test_capnp_and_kj_are_not_external_dependencies(self): + for binary in ('openpilot/selfdrive/pandad/pandad', + 'openpilot/system/camerad/camerad', + 'openpilot/system/loggerd/bootlog', + 'openpilot/system/loggerd/loggerd', + 'openpilot/system/loggerd/encoderd', + 'openpilot/tools/replay/replay'): + with self.subTest(binary=binary): + dynamic = subprocess.check_output(['readelf', '--dynamic', '--wide', str(ROOT / binary)], text=True) + self.assertNotRegex(dynamic, r'\(NEEDED\).*\[.*lib(?:capnp|kj)', + f"{binary}: link Cap'n Proto/KJ statically for AGNOS")