2020-01-17 10:22:00 -08:00
|
|
|
import os
|
|
|
|
|
import subprocess
|
|
|
|
|
import sys
|
2020-12-14 00:46:07 -08:00
|
|
|
import sysconfig
|
2026-02-17 15:02:06 -08:00
|
|
|
import platform
|
2025-09-25 20:55:14 -07:00
|
|
|
import shlex
|
2026-03-08 20:54:31 -07:00
|
|
|
import importlib
|
2020-11-11 21:14:51 +01:00
|
|
|
import numpy as np
|
2020-01-17 10:22:00 -08:00
|
|
|
|
2023-04-06 20:42:19 -07:00
|
|
|
import SCons.Errors
|
2026-03-13 20:12:13 -07:00
|
|
|
from SCons.Defaults import _stripixes
|
2023-04-06 20:42:19 -07:00
|
|
|
|
2023-04-22 15:24:45 -07:00
|
|
|
SCons.Warnings.warningAsException(True)
|
|
|
|
|
|
2020-10-12 18:46:37 +02:00
|
|
|
Decider('MD5-timestamp')
|
2020-09-24 19:24:14 +02:00
|
|
|
|
2025-08-02 16:50:45 -07:00
|
|
|
SetOption('num_jobs', max(1, int(os.cpu_count()/2)))
|
2024-01-03 11:16:54 -08:00
|
|
|
|
2025-09-25 20:55:14 -07:00
|
|
|
AddOption('--ccflags', action='store', type='string', default='', help='pass arbitrary flags over the command line')
|
2026-02-27 08:05:06 -08:00
|
|
|
AddOption('--verbose', action='store_true', default=False, help='show full build commands')
|
2023-08-24 14:58:30 -07:00
|
|
|
AddOption('--minimal',
|
2022-08-25 16:22:52 -07:00
|
|
|
action='store_false',
|
2023-08-24 14:58:30 -07:00
|
|
|
dest='extras',
|
2025-11-05 16:34:19 -08:00
|
|
|
default=os.path.exists(File('#.gitattributes').abspath), # minimal by default on release branch (where there's no LFS)
|
2023-08-24 14:58:30 -07:00
|
|
|
help='the minimum build to run openpilot. no tests, tools, etc.')
|
2022-08-25 16:22:52 -07:00
|
|
|
|
2026-02-17 15:02:06 -08:00
|
|
|
# Detect platform
|
|
|
|
|
arch = subprocess.check_output(["uname", "-m"], encoding='utf8').rstrip()
|
|
|
|
|
if platform.system() == "Darwin":
|
|
|
|
|
arch = "Darwin"
|
|
|
|
|
elif arch == "aarch64" and os.path.isfile('/TICI'):
|
|
|
|
|
arch = "larch64"
|
|
|
|
|
assert arch in [
|
|
|
|
|
"larch64", # linux tici arm64
|
|
|
|
|
"aarch64", # linux pc arm64
|
|
|
|
|
"x86_64", # linux pc x64
|
|
|
|
|
"Darwin", # macOS arm64 (x86 not supported)
|
|
|
|
|
]
|
2023-11-17 22:53:16 +01:00
|
|
|
|
2026-03-08 20:54:31 -07:00
|
|
|
pkg_names = ['bzip2', 'capnproto', 'eigen', 'ffmpeg', 'libjpeg', 'libyuv', 'ncurses', 'zeromq', 'zstd']
|
|
|
|
|
pkgs = [importlib.import_module(name) for name in pkg_names]
|
2026-02-22 19:15:11 -08:00
|
|
|
|
2026-03-13 20:12:13 -07:00
|
|
|
|
|
|
|
|
# ***** enforce a whitelist of system libraries *****
|
|
|
|
|
# this prevents silently relying on a 3rd party package,
|
|
|
|
|
# e.g. apt-installed libusb. all libraries should either
|
|
|
|
|
# be distributed with all Linux distros and macOS, or
|
|
|
|
|
# vendored in commaai/dependencies.
|
|
|
|
|
allowed_system_libs = {
|
2026-03-21 16:49:57 -07:00
|
|
|
"EGL", "GLESv2", "GL",
|
|
|
|
|
"Qt5Charts", "Qt5Core", "Qt5Gui", "Qt5Widgets",
|
2026-03-25 19:49:38 -07:00
|
|
|
"dl", "drm", "gbm", "m", "pthread",
|
2026-03-13 20:12:13 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
def _resolve_lib(env, name):
|
|
|
|
|
for d in env.Flatten(env.get('LIBPATH', [])):
|
|
|
|
|
p = Dir(str(d)).abspath
|
|
|
|
|
for ext in ('.a', '.so', '.dylib'):
|
|
|
|
|
f = File(os.path.join(p, f'lib{name}{ext}'))
|
|
|
|
|
if f.exists() or f.has_builder():
|
2026-03-14 13:42:57 -07:00
|
|
|
return name
|
2026-03-13 20:12:13 -07:00
|
|
|
if name in allowed_system_libs:
|
|
|
|
|
return name
|
|
|
|
|
raise SCons.Errors.UserError(f"Unexpected non-vendored library '{name}'")
|
|
|
|
|
|
|
|
|
|
def _libflags(target, source, env, for_signature):
|
|
|
|
|
libs = []
|
|
|
|
|
lp = env.subst('$LIBLITERALPREFIX')
|
|
|
|
|
for lib in env.Flatten(env.get('LIBS', [])):
|
|
|
|
|
if isinstance(lib, str):
|
|
|
|
|
if os.sep in lib or lib.startswith('#'):
|
|
|
|
|
libs.append(File(lib))
|
|
|
|
|
elif lib.startswith('-') or (lp and lib.startswith(lp)):
|
|
|
|
|
libs.append(lib)
|
|
|
|
|
else:
|
|
|
|
|
libs.append(_resolve_lib(env, lib))
|
|
|
|
|
else:
|
|
|
|
|
libs.append(lib)
|
|
|
|
|
return _stripixes(env['LIBLINKPREFIX'], libs, env['LIBLINKSUFFIX'],
|
|
|
|
|
env['LIBPREFIXES'], env['LIBSUFFIXES'], env, env['LIBLITERALPREFIX'])
|
|
|
|
|
|
2020-01-17 10:22:00 -08:00
|
|
|
env = Environment(
|
2025-09-25 20:55:14 -07:00
|
|
|
ENV={
|
|
|
|
|
"PATH": os.environ['PATH'],
|
|
|
|
|
"PYTHONPATH": Dir("#").abspath + ':' + Dir(f"#third_party/acados").abspath,
|
|
|
|
|
"ACADOS_SOURCE_DIR": Dir("#third_party/acados").abspath,
|
|
|
|
|
"ACADOS_PYTHON_INTERFACE_PATH": Dir("#third_party/acados/acados_template").abspath,
|
|
|
|
|
"TERA_PATH": Dir("#").abspath + f"/third_party/acados/{arch}/t_renderer"
|
|
|
|
|
},
|
2020-01-17 10:22:00 -08:00
|
|
|
CCFLAGS=[
|
|
|
|
|
"-g",
|
|
|
|
|
"-fPIC",
|
|
|
|
|
"-O2",
|
2020-07-09 09:25:32 -07:00
|
|
|
"-Wunused",
|
2020-05-26 13:27:01 -07:00
|
|
|
"-Werror",
|
2026-02-23 16:34:42 -08:00
|
|
|
"-Wshadow" if arch in ("Darwin", "larch64") else "-Wshadow=local",
|
2020-09-30 14:58:56 +02:00
|
|
|
"-Wno-unknown-warning-option",
|
2020-05-26 13:27:01 -07:00
|
|
|
"-Wno-inconsistent-missing-override",
|
2020-09-30 14:58:56 +02:00
|
|
|
"-Wno-c99-designator",
|
|
|
|
|
"-Wno-reorder-init-list",
|
2024-04-28 16:24:04 -07:00
|
|
|
"-Wno-vla-cxx-extension",
|
2025-09-25 20:55:14 -07:00
|
|
|
],
|
|
|
|
|
CFLAGS=["-std=gnu11"],
|
|
|
|
|
CXXFLAGS=["-std=c++1z"],
|
|
|
|
|
CPPPATH=[
|
2020-01-17 10:22:00 -08:00
|
|
|
"#",
|
2025-09-25 20:55:14 -07:00
|
|
|
"#msgq",
|
|
|
|
|
"#third_party",
|
|
|
|
|
"#third_party/json11",
|
|
|
|
|
"#third_party/linux/include",
|
2021-10-07 16:32:44 -07:00
|
|
|
"#third_party/acados/include",
|
|
|
|
|
"#third_party/acados/include/blasfeo/include",
|
|
|
|
|
"#third_party/acados/include/hpipm/include",
|
|
|
|
|
"#third_party/catch2/include",
|
2026-02-22 19:15:11 -08:00
|
|
|
[x.INCLUDE_DIR for x in pkgs],
|
2020-01-17 10:22:00 -08:00
|
|
|
],
|
2025-09-25 20:55:14 -07:00
|
|
|
LIBPATH=[
|
|
|
|
|
"#common",
|
2024-06-10 13:18:47 -07:00
|
|
|
"#msgq_repo",
|
2021-10-07 16:32:44 -07:00
|
|
|
"#third_party",
|
2024-06-04 19:16:55 -07:00
|
|
|
"#selfdrive/pandad",
|
2023-11-22 13:25:29 -08:00
|
|
|
"#rednose/helpers",
|
2025-09-25 20:55:14 -07:00
|
|
|
f"#third_party/acados/{arch}/lib",
|
2026-02-22 19:15:11 -08:00
|
|
|
[x.LIB_DIR for x in pkgs],
|
2020-11-11 21:14:51 +01:00
|
|
|
],
|
2025-09-25 20:55:14 -07:00
|
|
|
RPATH=[],
|
2020-11-11 21:14:51 +01:00
|
|
|
CYTHONCFILESUFFIX=".cpp",
|
2020-12-14 00:46:07 -08:00
|
|
|
COMPILATIONDB_USE_ABSPATH=True,
|
2023-11-22 13:25:29 -08:00
|
|
|
REDNOSE_ROOT="#",
|
|
|
|
|
tools=["default", "cython", "compilation_db", "rednose_filter"],
|
2024-07-30 13:11:05 -07:00
|
|
|
toolpath=["#site_scons/site_tools", "#rednose_repo/site_scons/site_tools"],
|
2020-01-17 10:22:00 -08:00
|
|
|
)
|
2026-03-13 20:26:32 -07:00
|
|
|
if arch != "larch64":
|
|
|
|
|
env['_LIBFLAGS'] = _libflags
|
2020-11-16 21:33:33 -08:00
|
|
|
|
2025-09-25 20:55:14 -07:00
|
|
|
# Arch-specific flags and paths
|
|
|
|
|
if arch == "larch64":
|
2026-02-23 16:34:42 -08:00
|
|
|
env["CC"] = "clang"
|
|
|
|
|
env["CXX"] = "clang++"
|
2025-09-25 20:55:14 -07:00
|
|
|
env.Append(LIBPATH=[
|
|
|
|
|
"/usr/lib/aarch64-linux-gnu",
|
|
|
|
|
])
|
|
|
|
|
arch_flags = ["-D__TICI__", "-mcpu=cortex-a57"]
|
|
|
|
|
env.Append(CCFLAGS=arch_flags)
|
|
|
|
|
env.Append(CXXFLAGS=arch_flags)
|
|
|
|
|
elif arch == "Darwin":
|
|
|
|
|
env.Append(LIBPATH=[
|
|
|
|
|
"/System/Library/Frameworks/OpenGL.framework/Libraries",
|
|
|
|
|
])
|
|
|
|
|
env.Append(CCFLAGS=["-DGL_SILENCE_DEPRECATION"])
|
|
|
|
|
env.Append(CXXFLAGS=["-DGL_SILENCE_DEPRECATION"])
|
2020-12-14 00:46:07 -08:00
|
|
|
|
2025-09-25 20:55:14 -07:00
|
|
|
_extra_cc = shlex.split(GetOption('ccflags') or '')
|
|
|
|
|
if _extra_cc:
|
|
|
|
|
env.Append(CCFLAGS=_extra_cc)
|
2020-01-17 10:22:00 -08:00
|
|
|
|
2025-09-25 20:55:14 -07:00
|
|
|
# no --as-needed on mac linker
|
|
|
|
|
if arch != "Darwin":
|
|
|
|
|
env.Append(LINKFLAGS=["-Wl,--as-needed", "-Wl,--no-undefined"])
|
|
|
|
|
|
2026-02-27 08:05:06 -08:00
|
|
|
# Shorter build output: show brief descriptions instead of full commands.
|
|
|
|
|
# Full command lines are still printed on failure by scons.
|
|
|
|
|
if not GetOption('verbose'):
|
|
|
|
|
for action, short in (
|
|
|
|
|
("CC", "CC"),
|
|
|
|
|
("CXX", "CXX"),
|
|
|
|
|
("LINK", "LINK"),
|
|
|
|
|
("SHCC", "CC"),
|
|
|
|
|
("SHCXX", "CXX"),
|
|
|
|
|
("SHLINK", "LINK"),
|
|
|
|
|
("AR", "AR"),
|
|
|
|
|
("RANLIB", "RANLIB"),
|
|
|
|
|
("AS", "AS"),
|
|
|
|
|
):
|
|
|
|
|
env[f"{action}COMSTR"] = f" [{short}] $TARGET"
|
|
|
|
|
|
2025-09-25 20:55:14 -07:00
|
|
|
# progress output
|
2020-01-17 10:22:00 -08:00
|
|
|
node_interval = 5
|
|
|
|
|
node_count = 0
|
|
|
|
|
def progress_function(node):
|
|
|
|
|
global node_count
|
|
|
|
|
node_count += node_interval
|
|
|
|
|
sys.stderr.write("progress: %d\n" % node_count)
|
|
|
|
|
if os.environ.get('SCONS_PROGRESS'):
|
|
|
|
|
Progress(progress_function, interval=node_interval)
|
|
|
|
|
|
2025-09-25 20:55:14 -07:00
|
|
|
# ********** Cython build environment **********
|
2020-11-11 21:14:51 +01:00
|
|
|
envCython = env.Clone()
|
2026-03-10 10:58:21 -07:00
|
|
|
envCython["CPPPATH"] += [sysconfig.get_paths()['include'], np.get_include()]
|
2026-02-23 16:34:42 -08:00
|
|
|
envCython["CCFLAGS"] += ["-Wno-#warnings", "-Wno-cpp", "-Wno-shadow", "-Wno-deprecated-declarations"]
|
2023-07-20 21:56:57 -07:00
|
|
|
envCython["CCFLAGS"].remove("-Werror")
|
2020-11-11 21:14:51 +01:00
|
|
|
|
2020-12-14 00:46:07 -08:00
|
|
|
envCython["LIBS"] = []
|
2020-11-11 21:14:51 +01:00
|
|
|
if arch == "Darwin":
|
2025-09-25 20:55:14 -07:00
|
|
|
envCython["LINKFLAGS"] = env["LINKFLAGS"] + ["-bundle", "-undefined", "dynamic_lookup"]
|
2020-11-11 21:14:51 +01:00
|
|
|
else:
|
2020-12-14 00:46:07 -08:00
|
|
|
envCython["LINKFLAGS"] = ["-pthread", "-shared"]
|
2020-11-11 21:14:51 +01:00
|
|
|
|
2024-07-30 13:11:05 -07:00
|
|
|
np_version = SCons.Script.Value(np.__version__)
|
|
|
|
|
Export('envCython', 'np_version')
|
2020-11-11 21:14:51 +01:00
|
|
|
|
2025-10-22 22:18:07 -07:00
|
|
|
Export('env', 'arch')
|
2025-09-25 20:55:14 -07:00
|
|
|
|
|
|
|
|
# Setup cache dir
|
|
|
|
|
cache_dir = '/data/scons_cache' if arch == "larch64" else '/tmp/scons_cache'
|
|
|
|
|
CacheDir(cache_dir)
|
|
|
|
|
Clean(["."], cache_dir)
|
|
|
|
|
|
|
|
|
|
# ********** start building stuff **********
|
2020-01-17 10:22:00 -08:00
|
|
|
|
2023-09-13 14:39:06 -07:00
|
|
|
# Build common module
|
2022-05-18 14:11:57 -07:00
|
|
|
SConscript(['common/SConscript'])
|
2025-09-25 20:55:14 -07:00
|
|
|
Import('_common')
|
2024-08-19 15:25:05 -07:00
|
|
|
common = [_common, 'json11', 'zmq']
|
2025-09-25 20:55:14 -07:00
|
|
|
Export('common')
|
2021-07-29 13:13:47 +02:00
|
|
|
|
2024-06-09 17:44:34 -07:00
|
|
|
# Build messaging (cereal + msgq + socketmaster + their dependencies)
|
2024-08-24 01:46:37 +08:00
|
|
|
# Enable swaglog include in submodules
|
|
|
|
|
env_swaglog = env.Clone()
|
|
|
|
|
env_swaglog['CXXFLAGS'].append('-DSWAGLOG="\\"common/swaglog.h\\""')
|
|
|
|
|
SConscript(['msgq_repo/SConscript'], exports={'env': env_swaglog})
|
|
|
|
|
|
2020-01-17 10:22:00 -08:00
|
|
|
SConscript(['cereal/SConscript'])
|
2024-08-24 01:46:37 +08:00
|
|
|
|
2024-06-09 17:44:34 -07:00
|
|
|
Import('socketmaster', 'msgq')
|
2025-01-31 02:30:54 +08:00
|
|
|
messaging = [socketmaster, msgq, 'capnp', 'kj',]
|
2024-06-09 17:44:34 -07:00
|
|
|
Export('messaging')
|
|
|
|
|
|
2023-09-13 14:39:06 -07:00
|
|
|
|
|
|
|
|
# Build other submodules
|
2024-08-24 01:46:37 +08:00
|
|
|
SConscript(['panda/SConscript'])
|
2021-04-08 13:09:11 +02:00
|
|
|
|
2023-11-22 13:25:29 -08:00
|
|
|
# Build rednose library
|
2021-04-08 13:09:11 +02:00
|
|
|
SConscript(['rednose/SConscript'])
|
2020-12-20 19:39:59 -08:00
|
|
|
|
2022-06-02 17:02:25 -07:00
|
|
|
# Build system services
|
2022-06-06 13:27:45 -07:00
|
|
|
SConscript([
|
2023-05-12 13:01:00 -07:00
|
|
|
'system/loggerd/SConscript',
|
2022-06-06 13:27:45 -07:00
|
|
|
])
|
2022-06-02 17:02:25 -07:00
|
|
|
|
2024-04-17 16:33:13 -07:00
|
|
|
if arch == "larch64":
|
|
|
|
|
SConscript(['system/camerad/SConscript'])
|
|
|
|
|
|
2020-12-20 19:39:59 -08:00
|
|
|
# Build openpilot
|
2021-10-07 16:32:44 -07:00
|
|
|
SConscript(['third_party/SConscript'])
|
2020-12-20 19:39:59 -08:00
|
|
|
|
2026-03-13 19:20:33 -07:00
|
|
|
# Build selfdrive
|
|
|
|
|
SConscript([
|
|
|
|
|
'selfdrive/pandad/SConscript',
|
|
|
|
|
'selfdrive/controls/lib/lateral_mpc_lib/SConscript',
|
|
|
|
|
'selfdrive/controls/lib/longitudinal_mpc_lib/SConscript',
|
|
|
|
|
'selfdrive/locationd/SConscript',
|
|
|
|
|
'selfdrive/modeld/SConscript',
|
|
|
|
|
'selfdrive/ui/SConscript',
|
|
|
|
|
])
|
2020-05-14 10:53:19 -07:00
|
|
|
|
2026-03-21 16:49:57 -07:00
|
|
|
# Build tools
|
|
|
|
|
if arch != "larch64":
|
|
|
|
|
SConscript([
|
|
|
|
|
'tools/replay/SConscript',
|
|
|
|
|
'tools/cabana/SConscript',
|
2026-03-25 19:49:38 -07:00
|
|
|
'tools/jotpluggler/SConscript',
|
2026-03-21 16:49:57 -07:00
|
|
|
])
|
2025-09-25 20:55:14 -07:00
|
|
|
|
|
|
|
|
|
|
|
|
|
env.CompilationDatabase('compile_commands.json')
|