2. 搭建DRIVE CI基础环境

持续集成要跑得起来,第一步不是写流水线脚本,而是把“能编译、能运行、能验证”的底座搭好。NVIDIA DRIVE 的 CI 基础环境由三层构成:最底层是 NVIDIA DRIVE SDK 及其许可,中间层是 SIL 与 HIL 两类执行环境,最上层是 Jenkins 或 GitLab CI 的调度与流水线。三层缺一不可——SDK 没装好,编译直接失败;许可没配好,交叉编译工具链和仿真器无法启动;SIL/HIL 没接好,测试只能停在静态检查。

一、SDK 安装与许可管理

NVIDIA DRIVE SDK 通过 NVIDIA 开发者账号授权分发,典型组件包括 DRIVE OS(含 QNX/Linux 目标系统)、CUDA/cuDNN/TensorRT、DriveWorks、DRIVE AV 感知与规划栈,以及交叉编译工具链(aarch64 目标)。安装前先确认宿主机版本与 SDK 版本匹配,例如 Ubuntu 20.04 对应 DRIVE OS 6.x 系列。安装通常分两步:先用 SDK Manager 或离线包安装宿主机侧工具链与仿真依赖,再把目标镜像刷写到 DRIVE 开发板或仿真目标。

# 示例:宿主机侧 SDK 组件安装(版本与路径为示例)
sudo apt-get install -y build-essential cmake ninja-build
sudo ./driveos_sdk_installer.run --target aarch64 --prefix /opt/nvidia/drive
export DRIVE_SDK_ROOT=/opt/nvidia/drive
export PATH=$DRIVE_SDK_ROOT/bin:$PATH
export LD_LIBRARY_PATH=$DRIVE_SDK_ROOT/lib:$LD_LIBRARY_PATH

许可管理是 CI 环境最容易踩坑的地方。NVIDIA DRIVE 的许可通常绑定到 License Server(如 FlexLM 风格)或通过 NVIDIA 授权文件激活。CI 节点需要能访问许可服务器,且环境变量要指向正确的许可端口。建议在 CI 节点上做一次“许可自检”,把结果作为流水线的前置门禁:

# 示例:许可可用性检查
export NVIDIA_LICENSE_FILE=27000@license-server.internal
/opt/nvidia/drive/bin/drive_license_check --feature drive_av
# 期望输出:Feature drive_av: OK (expires 2025-12-31)

如果许可检查失败,流水线应直接失败并给出明确错误码,而不是让后续编译在“找不到库”的模糊报错中浪费时间。许可文件不要硬编码在仓库里,应通过 CI 的 Secret 变量或节点本地配置文件注入。

二、SIL 环境配置

SIL(Software-in-the-Loop)在 x86 宿主机上运行 DRIVE 软件栈的仿真版本,适合做单元测试、感知模型推理验证和规划算法回归。SIL 环境的关键是“可复现”:固定 SDK 版本、固定依赖、固定测试数据。推荐用容器或虚拟环境隔离,避免不同流水线互相污染。

一个可用的 SIL 配置示例:在 CI 节点上准备 /opt/drive-sil 目录,安装 SDK 的仿真运行时,并设置仿真目标为 sim。测试时通过 drive_sim 启动虚拟传感器输入,把预录制的传感器数据(如 H.264 视频、点云)回放给感知模块。判断 SIL 是否配置成功,可以跑一个最小冒烟测试:加载一个已知的 TensorRT 引擎,对一张示例图像做推理,检查输出张量形状和数值范围是否符合预期。

# 示例:SIL 冒烟测试
cd /opt/drive-sil
./run_sil_test --model resnet50.plan --input sample.jpg --output out.bin
python3 -c "import numpy as np; a=np.fromfile('out.bin',dtype=np.float32); print(a.shape, a.min(), a.max())"
# 期望:形状与模型输出一致,数值在合理范围(如 0~1 或 logits 范围)

三、HIL 环境配置

HIL(Hardware-in-the-Loop)把真实 DRIVE 开发板接入测试回路,传感器数据由 HIL 台架注入,执行器信号由台架采集。HIL 环境比 SIL 复杂得多,涉及电源、冷却、网络、时间同步和刷写。CI 中接入 HIL 时,通常把 HIL 台架作为“受控资源”,通过 Jenkins Agent 或 GitLab Runner 的标签(tag)绑定,避免多个流水线同时抢占同一台架。

HIL 配置的核心检查项包括:开发板能否被 CI 节点通过 SSH/串口访问;目标镜像版本是否与待测代码匹配;传感器注入通道(如 GMSL、以太网)是否正常;时间同步(PTP/gPTP)是否锁定。建议在流水线中先执行“台架健康检查”,再刷写镜像,最后跑测试。刷写失败或健康检查不通过时,应释放台架并标记为不可用,防止后续任务继续排队。

四、Jenkins 与 GitLab CI 集成

Jenkins 和 GitLab CI 的集成思路一致:把 SIL 节点和 HIL 台架注册为执行器,用标签区分能力,用流水线阶段串联“许可检查→编译→SIL 测试→HIL 测试→报告归档”。Jenkins 侧可用 agent { label 'sil || hil' } 声明式语法;GitLab CI 侧用 tags: [sil] 或 tags: [hil]。关键是把环境准备做成可复用的脚本,而不是散落在每个 job 里。

# GitLab CI 示例片段
stages: [precheck, build, sil_test, hil_test]

license_check:
  stage: precheck
  tags: [sil]
  script:
    - source /opt/nvidia/drive/env.sh
    - drive_license_check --feature drive_av

build_drive:
  stage: build
  tags: [sil]
  script:
    - cmake -B build -G Ninja -DCMAKE_TOOLCHAIN_FILE=$DRIVE_SDK_ROOT/toolchain.cmake
    - ninja -C build

sil_regression:
  stage: sil_test
  tags: [sil]
  script:
    - ./run_sil_test --suite perception_regression

hil_smoke:
  stage: hil_test
  tags: [hil]
  script:
    - ./hil_health_check.sh && ./flash_target.sh && ./run_hil_smoke.sh

下面这张图把本节的三层关系与关键检查点串起来,便于在搭建时对照排查。

DRIVE CI 基础环境三层结构 调度层:Jenkins / GitLab CI precheck 许可 + 环境自检 build 交叉编译 aarch64 sil_test 感知/规划回归 hil_test 台架冒烟 执行层:SIL 与 HIL SIL(软件在环) • x86 宿主机 + 仿真运行时 • 回放传感器数据,验证感知/规划 • 容器隔离,保证可复现 HIL(硬件在环) • 真实 DRIVE 开发板 + 台架 • 传感器注入 / 执行器采集 • 健康检查 → 刷写 → 冒烟测试 基础层:NVIDIA DRIVE SDK 与许可 SDK 组件 DRIVE OS / CUDA / TensorRT DriveWorks / 交叉工具链 许可服务 License Server / 授权文件 NVIDIA_LICENSE_FILE 指向 自检门禁 drive_license_check 失败即阻断流水线 三层自上而下依赖:调度层调用执行层,执行层依赖 SDK 与许可

五、搭建顺序与常见问题

建议按“先许可、再 SDK、再 SIL、最后 HIL”的顺序搭建。许可和 SDK 是硬前提,SIL 可以在单机上快速验证,HIL 成本最高、调试最慢,放在最后接入。常见问题有三类:一是许可过期或端口不通,表现为编译工具链报“feature not available”;二是 SIL 与 HIL 的 SDK 版本不一致,导致同一份代码在 SIL 通过、HIL 失败;三是 HIL 台架被占用或刷写失败,流水线卡在等待资源。对第一类问题,把许可检查做成 precheck 阶段;对第二类问题,在流水线中打印 SDK 版本并做版本比对;对第三类问题,给台架加锁和超时释放机制。

建议把 SDK 版本、许可服务器地址、SIL 镜像标签、HIL 台架编号统一记录在 CI 的配置变量中,任何一次回归测试都能追溯到具体环境组合,避免“上次能过这次不能过”却查不到原因。

完成本节搭建后,你应当能在 CI 中稳定执行一次“许可检查→编译→SIL 冒烟→HIL 冒烟”的最小闭环。这个闭环是后续所有回归测试、性能测试和 nightly 流水线的基础,先把环境钉死,再谈测试覆盖率和自动化程度。