mirror of
https://github.com/herizon1054/openpilot.git
synced 2026-04-06 12:14:06 +08:00
246 lines
8.6 KiB
Python
246 lines
8.6 KiB
Python
import os
|
|
import subprocess
|
|
import sys
|
|
import sysconfig
|
|
import platform
|
|
import shlex
|
|
import importlib
|
|
import numpy as np
|
|
|
|
import SCons.Errors
|
|
from SCons.Defaults import _stripixes
|
|
|
|
# 嚴格模式:將所有編譯警告視為錯誤
|
|
SCons.Warnings.warningAsException(True)
|
|
|
|
# 依據 MD5 校驗碼與時間戳記來決定是否需要重新編譯
|
|
Decider('MD5-timestamp')
|
|
|
|
# 設定並行編譯的執行緒數量,預設為 CPU 核心數的一半
|
|
SetOption('num_jobs', max(1, int(os.cpu_count()/2)))
|
|
|
|
# 註冊命令列可用選項
|
|
AddOption('--ccflags', action='store', type='string', default='', help='pass arbitrary flags over the command line')
|
|
AddOption('--verbose', action='store_true', default=False, help='show full build commands')
|
|
AddOption('--minimal',
|
|
action='store_false',
|
|
dest='extras',
|
|
default=os.path.exists(File('#.gitattributes').abspath),
|
|
help='the minimum build to run openpilot. no tests, tools, etc.')
|
|
|
|
# =====================================================================
|
|
# 偵測作業系統與硬體架構
|
|
# =====================================================================
|
|
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)
|
|
]
|
|
|
|
pkg_names = ['bzip2', 'capnproto', 'eigen', 'ffmpeg', 'libjpeg', 'libyuv', 'ncurses', 'zeromq', 'zstd']
|
|
pkgs = [importlib.import_module(name) for name in pkg_names]
|
|
|
|
# =====================================================================
|
|
# 系統函式庫白名單:防止不小心引入非預期的第三方套件
|
|
# =====================================================================
|
|
allowed_system_libs = {
|
|
"EGL", "GLESv2", "GL",
|
|
"Qt5Charts", "Qt5Core", "Qt5Gui", "Qt5Widgets",
|
|
"dl", "drm", "gbm", "m", "pthread",
|
|
"X11", "vdpau", "va", "va-drm", "va-x11"
|
|
}
|
|
|
|
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():
|
|
return name
|
|
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)
|
|
|
|
# 核彈級解法:確保硬體加速庫永遠在最後面載入,避免符號解析錯誤
|
|
if arch != "Darwin":
|
|
for hw_lib in ["X11", "vdpau", "va", "va-drm", "va-x11", "drm"]:
|
|
if hw_lib not in libs:
|
|
libs.append(hw_lib)
|
|
|
|
return _stripixes(env['LIBLINKPREFIX'], libs, env['LIBLINKSUFFIX'],
|
|
env['LIBPREFIXES'], env['LIBSUFFIXES'], env, env['LIBLITERALPREFIX'])
|
|
|
|
# =====================================================================
|
|
# SCons 全域編譯環境設定
|
|
# =====================================================================
|
|
env = Environment(
|
|
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"
|
|
},
|
|
CCFLAGS=[
|
|
"-g", "-fPIC", "-O2", "-Wunused", "-Werror",
|
|
"-Wshadow" if arch in ("Darwin", "larch64") else "-Wshadow=local",
|
|
"-Wno-unknown-warning-option",
|
|
"-Wno-inconsistent-missing-override",
|
|
"-Wno-c99-designator",
|
|
"-Wno-reorder-init-list",
|
|
"-Wno-vla-cxx-extension",
|
|
],
|
|
CFLAGS=["-std=gnu11"],
|
|
CXXFLAGS=["-std=c++1z"],
|
|
CPPPATH=[
|
|
"#", "#msgq", "#third_party", "#third_party/json11", "#third_party/linux/include",
|
|
"#third_party/acados/include", "#third_party/acados/include/blasfeo/include",
|
|
"#third_party/acados/include/hpipm/include", "#third_party/catch2/include",
|
|
[x.INCLUDE_DIR for x in pkgs],
|
|
],
|
|
LIBPATH=[
|
|
"#common", "#msgq_repo", "#third_party", "#selfdrive/pandad", "#rednose/helpers",
|
|
f"#third_party/acados/{arch}/lib",
|
|
[x.LIB_DIR for x in pkgs],
|
|
],
|
|
RPATH=[],
|
|
CYTHONCFILESUFFIX=".cpp",
|
|
COMPILATIONDB_USE_ABSPATH=True,
|
|
REDNOSE_ROOT="#",
|
|
tools=["default", "cython", "compilation_db", "rednose_filter"],
|
|
toolpath=["#site_scons/site_tools", "#rednose_repo/site_scons/site_tools"],
|
|
)
|
|
if arch != "larch64":
|
|
env['_LIBFLAGS'] = _libflags
|
|
|
|
# 特定架構的編譯旗標
|
|
if arch == "larch64":
|
|
env["CC"] = "clang"
|
|
env["CXX"] = "clang++"
|
|
env.Append(LIBPATH=["/usr/lib/aarch64-linux-gnu"])
|
|
arch_flags = ["-D__TICI__", "-mcpu=cortex-a57", "-DQCOM2"]
|
|
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"])
|
|
|
|
_extra_cc = shlex.split(GetOption('ccflags') or '')
|
|
if _extra_cc:
|
|
env.Append(CCFLAGS=_extra_cc)
|
|
|
|
if arch != "Darwin":
|
|
env.Append(LINKFLAGS=["-Wl,--as-needed", "-Wl,--no-undefined"])
|
|
|
|
# 縮短終端機輸出,使其更易讀
|
|
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"
|
|
|
|
# 編譯進度提示
|
|
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)
|
|
|
|
# =====================================================================
|
|
# Cython 編譯環境
|
|
# =====================================================================
|
|
envCython = env.Clone()
|
|
envCython["CPPPATH"] += [sysconfig.get_paths()['include'], np.get_include()]
|
|
envCython["CCFLAGS"] += ["-Wno-#warnings", "-Wno-cpp", "-Wno-shadow", "-Wno-deprecated-declarations"]
|
|
envCython["CCFLAGS"].remove("-Werror")
|
|
|
|
envCython["LIBS"] = []
|
|
if arch == "Darwin":
|
|
envCython["LINKFLAGS"] = env["LINKFLAGS"] + ["-bundle", "-undefined", "dynamic_lookup"]
|
|
else:
|
|
envCython["LINKFLAGS"] = ["-pthread", "-shared"]
|
|
|
|
np_version = SCons.Script.Value(np.__version__)
|
|
Export('envCython', 'np_version')
|
|
Export('env', 'arch')
|
|
|
|
# 設定 SCons 快取目錄
|
|
default_cache_dir = '/data/scons_cache' if arch == "larch64" else '/tmp/scons_cache'
|
|
cache_dir = ARGUMENTS.get('cache_dir', default_cache_dir)
|
|
CacheDir(cache_dir)
|
|
Clean(["."], cache_dir)
|
|
|
|
# ********** 開始編譯各模組 **********
|
|
SConscript(['common/SConscript'])
|
|
Import('_common')
|
|
common = [_common, 'json11', 'zmq']
|
|
Export('common')
|
|
|
|
env_swaglog = env.Clone()
|
|
env_swaglog['CXXFLAGS'].append('-DSWAGLOG="\\"common/swaglog.h\\""')
|
|
SConscript(['msgq_repo/SConscript'], exports={'env': env_swaglog})
|
|
SConscript(['cereal/SConscript'])
|
|
|
|
Import('socketmaster', 'msgq')
|
|
messaging = [socketmaster, msgq, 'capnp', 'kj',]
|
|
Export('messaging')
|
|
|
|
# =====================================================================
|
|
# 🐼 雙 Panda 編譯核心邏輯 🐼
|
|
# 不做任何硬體判斷,直接編譯預設的 panda (產出 H7 新版韌體)
|
|
# 以及舊版的 panda_tici (產出 F4 舊版韌體)
|
|
# 兩者的編譯結果都會被放入共用的 FW_PATH 中,供 Python 動態取用
|
|
# =====================================================================
|
|
SConscript(['panda/SConscript'])
|
|
SConscript(['panda_tici/SConscript'])
|
|
|
|
SConscript(['rednose/SConscript'])
|
|
SConscript(['system/loggerd/SConscript'])
|
|
|
|
if arch == "larch64":
|
|
SConscript(['system/camerad/SConscript'])
|
|
|
|
SConscript(['third_party/SConscript'])
|
|
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',
|
|
])
|
|
SConscript(['sunnypilot/SConscript'])
|
|
|
|
if arch != "larch64":
|
|
SConscript([
|
|
'tools/replay/SConscript',
|
|
'tools/cabana/SConscript',
|
|
'tools/jotpluggler/SConscript',
|
|
])
|
|
|
|
env.CompilationDatabase('compile_commands.json') |