第二章:开发环境搭建——QNX SDP安装与配置、Android Studio与车载SDK、Linux交叉编译工具链搭建
好,咱们直接进入正题。开发环境搭建这事儿,说简单也简单,说复杂也复杂。我见过太多项目,前期环境没搞利索,后面调试时各种翻车。所以这一章,我带你一步步把三个核心环境搭好:QNX SDP、Android Studio 加车载 SDK、还有 Linux 交叉编译工具链。
2.1 QNX SDP 安装与配置
QNX 这玩意儿,说实话,第一次接触时我也觉得有点“高冷”。但做车载 HMI,尤其是仪表和域控,你绕不开它。
2.1.1 下载与安装
首先,你得去黑莓官网申请 QNX SDP 的试用版或正式版。我个人习惯用 7.0 或 7.1 版本,比较稳定。
- 系统要求:建议 Ubuntu 18.04 或 20.04,64位。Windows 上也能跑,但坑多,我不推荐。
- 安装包:一个 .bin 文件,大概 2-3GB。
- 安装命令:
chmod +x qnx-sdp-7.0.0-xxx.bin
sudo ./qnx-sdp-7.0.0-xxx.bin
安装过程中会让你选安装路径。我一般放在 /opt/qnx700 下,方便管理。
2.1.2 环境变量配置
装完只是第一步。你得让系统知道 QNX 在哪。编辑 ~/.bashrc,加上这几行:
export QNX_HOST=/opt/qnx700/host/linux/x86_64
export QNX_TARGET=/opt/qnx700/target/qnx7
export PATH=$QNX_HOST/usr/bin:$PATH
export QNX_CONFIGURATION=/etc/qnx
然后 source ~/.bashrc 让它生效。验证一下:
qcc --version
如果能看到版本号,恭喜你,环境通了。
/opt/qnx700 下建一个 workspace 目录,所有项目都放里面。这样路径清晰,不容易乱。
2.1.3 常见坑与避坑指南
嗯,这里要注意。QNX 的编译器对代码风格比较敏感。比如,有些 Linux 下的 #include 写法,在 QNX 里可能找不到头文件。我曾经在移植一个开源库时,发现 <sys/socket.h> 在 QNX 下路径不一样,得改成 <sys/socket.h> 但加个 -I 参数指定路径。
另外,QNX 的 Makefile 和 Linux 的有点区别。我建议直接用 QNX 自带的 qmake 或 cmake 配合 -DCMAKE_TOOLCHAIN_FILE 来搞。
2.2 Android Studio 与车载 SDK
现在车载中控屏,十有八九是 Android 系统。所以 Android Studio 是必备的。但光有 Studio 不够,还得配上车载 SDK。
2.2.1 Android Studio 安装
这个简单,去官网下载最新版就行。我目前用的是 Arctic Fox 2020.3.1,稳定且功能全。
- JDK:建议用 JDK 11 或 17。别用太老的,否则 Gradle 会报错。
- SDK Manager:安装 Android 10 (API 29) 或 Android 12 (API 31),车载常用这两个版本。
CarService、VehicleHal 这些。
2.2.2 车载 SDK 集成
车载 SDK 一般由车厂或 Tier1 提供。比如,我做过的一个项目,用的是某头部车厂的 SDK,里面封装了空调、车窗、座椅控制等接口。
集成步骤大致如下:
- 把 SDK 的
.aar或.jar文件放到app/libs目录下。 - 在
build.gradle里添加依赖:
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar', '*.aar'])
implementation 'com.android.car:car:1.0.0'
}
- 在
AndroidManifest.xml里声明权限:
<uses-permission android:name="android.car.permission.CAR_CONTROL" />
然后就可以在代码里调用车载 API 了。比如控制空调:
Car car = Car.createCar(context);
CarHvacManager hvac = (CarHvacManager) car.getCarManager(Car.HVAC_SERVICE);
hvac.setTemperature(22.5f);
2.2.3 模拟器与真机调试
模拟器调试很方便,但有些功能模拟不了,比如真实的 CAN 总线信号。所以真机调试是必须的。
连接真机时,记得打开开发者选项和 USB 调试。如果遇到设备识别不了,多半是驱动问题。Windows 下装个 adb 驱动就行,Linux 下加个 udev 规则。
2.3 Linux 交叉编译工具链搭建
做车载 HMI,经常需要把代码编译成 ARM 架构的二进制,然后丢到车机上去跑。这时候交叉编译工具链就派上用场了。
2.3.1 工具链选择
常见的工具链有:
| 工具链 | 适用平台 | 备注 |
|---|---|---|
| gcc-arm-linux-gnueabihf | ARM 32位 | 老平台常用 |
| aarch64-linux-gnu | ARM 64位 | 新平台主流 |
| Linaro 工具链 | ARM 全系列 | 性能优化好 |
我个人偏爱 Linaro 的,因为它在浮点运算上优化得不错。车载 HMI 经常要处理图形和音频,浮点性能很关键。
2.3.2 安装与配置
以 aarch64 为例,安装命令:
sudo apt-get install gcc-aarch64-linux-gnu g++-aarch64-linux-gnu
然后写个测试程序:
// hello.c
#include <stdio.h>
int main() {
printf("Hello from ARM!\n");
return 0;
}
编译:
aarch64-linux-gnu-gcc -o hello hello.c
用 file 命令查看:
file hello
# 输出: ELF 64-bit LSB executable, ARM aarch64
看到 ARM aarch64 字样,说明编译成功了。
--sysroot,结果链接器找不到头文件。后来我建了一个 sysroot 目录,把目标板上的 /usr/include 和 /usr/lib 拷贝过来,再用 --sysroot 指定,才搞定。
2.3.3 与 CMake 集成
实际项目中,我们一般用 CMake 来管理构建。写一个 toolchain.cmake 文件:
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR aarch64)
set(CMAKE_C_COMPILER aarch64-linux-gnu-gcc)
set(CMAKE_CXX_COMPILER aarch64-linux-gnu-g++)
set(CMAKE_FIND_ROOT_PATH /path/to/sysroot)
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
然后编译时:
cmake -DCMAKE_TOOLCHAIN_FILE=toolchain.cmake ..
make
这样就能生成 ARM 架构的可执行文件了。
2.4 三个环境的协同工作
实际开发中,这三个环境不是孤立的。比如,你在 Android Studio 里写 HMI 界面,但底层的车身控制逻辑可能跑在 QNX 上,中间通过 IPC 或网络通信。这时候,你需要在 Linux 上用交叉编译工具链把 QNX 的代码编译好,然后集成到 Android 的 APK 里。
嗯,听起来有点绕。但说白了,就是各司其职:
- QNX SDP:负责实时控制和安全相关的模块。
- Android Studio:负责上层 HMI 和用户交互。
- 交叉编译工具链:负责把 Linux 或 QNX 的代码编译成目标架构的二进制。
我建议你在项目初期就把这三个环境的路径、版本、依赖关系理清楚,写成一个文档。别嫌麻烦,后面调试时能省你大量时间。
好,这一章就到这里。下一章我们开始讲 QNX 下的进程通信和资源管理,那是车身控制的核心。