2. 开发环境搭建:交叉编译工具链配置、Android源码编译环境、V4L2驱动调试工具安装

说实话,做Camera HAL层开发,环境搭建这一步要是没弄好,后面全是坑。我见过太多同事花了一周时间调一个bug,最后发现是交叉编译工具链版本不对。嗯,咱们今天就把这事一次性说清楚。

2.1 交叉编译工具链配置

为什么需要交叉编译?说白了,你的开发机是x86架构,但目标设备是ARM或AArch64。你不可能在手机上跑gcc吧?所以我们需要在PC上编译出能在ARM上运行的二进制文件。

2.1.1 工具链选择

我个人习惯用Linaro提供的工具链,稳定且社区活跃。Android官方其实也推荐这个。

目标架构 工具链名称 下载地址
ARM 32位 gcc-arm-linux-gnueabihf releases.linaro.org
AArch64 gcc-aarch64-linux-gnu releases.linaro.org
Android NDK android-ndk-r25c developer.android.com
我的经验:别用太新的工具链。我在项目中遇到过gcc 12编译出来的V4L2程序在Android 11上段错误,换成gcc 9就没事。稳定比版本新更重要。

2.1.2 环境变量配置

配置环境变量其实就三步,但很多人栽在路径上。我建议你这样写:

# 解压工具链
tar -xvf gcc-arm-9.2-2019.12-x86_64-arm-none-linux-gnueabihf.tar.xz
sudo mv gcc-arm-9.2-2019.12-x86_64-arm-none-linux-gnueabihf /opt/

# 配置环境变量(写入 ~/.bashrc)
export PATH=/opt/gcc-arm-9.2-2019.12-x86_64-arm-none-linux-gnueabihf/bin:$PATH
export CROSS_COMPILE=arm-none-linux-gnueabihf-
export ARCH=arm

# 验证
arm-none-linux-gnueabihf-gcc --version
注意:我曾经因为忘记export ARCH=arm,导致编译出来的内核模块加载失败。这个变量直接影响V4L2驱动的编译行为。

2.2 Android源码编译环境

Android源码编译,说白了就是一场资源消耗战。我第一次编译AOSP时,8GB内存的机器直接卡死。后来换了32GB内存+SSD,才勉强能跑。

2.2.1 硬件要求

  • CPU:至少8核,16核以上更佳。我用的AMD Ryzen 9 5950X,16核32线程,一次完整编译约40分钟。
  • 内存:最低16GB,推荐32GB。Android 13以上建议64GB。
  • 磁盘:至少250GB空闲空间,SSD必须。我曾经用机械硬盘编译,一次要6小时...
  • 系统:Ubuntu 20.04 LTS或22.04 LTS。别用CentOS,坑太多。

2.2.2 依赖安装

嗯,这里有个坑。不同Android版本依赖不同,我建议直接用Google官方脚本:

# Ubuntu 20.04
sudo apt-get update
sudo apt-get install -y git-core gnupg flex bison build-essential \
  zip curl zlib1g-dev gcc-multilib g++-multilib libc6-dev-i386 \
  libncurses5 lib32ncurses5-dev x11proto-core-dev libx11-dev \
  lib32z1-dev libgl1-mesa-dev libxml2-utils xsltproc unzip fontconfig

# 安装repo工具
mkdir ~/bin
curl https://storage.googleapis.com/git-repo-downloads/repo > ~/bin/repo
chmod a+x ~/bin/repo
export PATH=~/bin:$PATH
避坑指南:我曾经在Ubuntu 22.04上编译Android 12,发现python2缺失。Android 12以下需要python2,13以上才支持python3。建议装个pyenv管理版本。

2.2.3 源码下载与编译

# 初始化仓库(以Android 13为例)
mkdir aosp-13
cd aosp-13
repo init -u https://android.googlesource.com/platform/manifest -b android-13.0.0_r41
repo sync -j16  # 根据你的CPU核心数调整

# 编译
source build/envsetup.sh
lunch aosp_arm64-userdebug
make -j16 2>&1 | tee build.log

你想想看,第一次同步源码大概要下载80GB数据,网络不好能同步三天。我建议用国内镜像:

repo init -u git://mirrors.ustc.edu.cn/aosp/platform/manifest -b android-13.0.0_r41

2.3 V4L2驱动调试工具安装

V4L2调试,说白了就是跟设备节点打交道。我调试Camera HAL时,90%的问题都能用这些工具定位。

2.3.1 核心工具列表

工具名 用途 安装方式
v4l2-ctl 查询/设置设备参数 apt install v4l-utils
media-ctl 配置media controller拓扑 apt install media-utils
yavta 测试视频采集/显示 源码编译
gstreamer pipeline调试 apt install gstreamer1.0-tools

2.3.2 v4l2-ctl实战

这个工具我几乎每天用。看看设备信息:

# 列出所有V4L2设备
v4l2-ctl --list-devices

# 查看某个设备的能力
v4l2-ctl -d /dev/video0 --all

# 列出支持的格式
v4l2-ctl -d /dev/video0 --list-formats-ext

# 抓一帧数据
v4l2-ctl -d /dev/video0 --set-fmt-video=width=1920,height=1080,pixelformat=NV12 \
  --stream-mmap --stream-count=1 --stream-to=frame.raw
我的经验:有一次Sensor输出格式是SBGGR10,但HAL层配置成了NV12。用v4l2-ctl --list-formats-ext一看,发现Sensor根本不支持NV12。这种问题不用工具排查,光看代码能看一天。

2.3.3 media-ctl与拓扑调试

现代Camera子系统都用media controller。我建议先画拓扑图:

# 查看media拓扑
media-ctl -d /dev/media0 -p

# 设置pipeline
media-ctl -d /dev/media0 -l '"msm_cam_sensor0":0->"msm_csiphy0":0[1]'
media-ctl -d /dev/media0 -V '"msm_cam_sensor0":0[fmt:SBGGR10/1920x1080]'

为什么会这样?因为V4L2子设备之间需要通过media controller建立连接。我曾经调试一个ISP问题,发现pipeline没连上,导致数据流中断。用media-ctl -p一看,link状态是0,改过来就好了。

2.3.4 yavta编译与使用

yavta是个轻量级测试工具,我建议源码编译:

git clone git://git.ideasonboard.org/yavta.git
cd yavta
make CROSS_COMPILE=aarch64-linux-gnu-
# 或者本地编译
make

# 测试采集
./yavta -f NV12 -s 1920x1080 -n 4 --capture=30 /dev/video0
注意:yavta默认使用MMAP模式。如果你用USERPTR或DMABUF,需要加参数。我在项目中遇到过MMAP模式正常但DMABUF崩溃的问题,最后发现是ION分配器配置不对。

2.4 环境验证清单

搭建完环境后,我建议你跑一遍这个验证脚本:

#!/bin/bash
echo "=== 交叉编译工具链验证 ==="
aarch64-linux-gnu-gcc --version && echo "OK" || echo "FAIL"

echo "=== Android编译环境验证 ==="
source build/envsetup.sh 2>/dev/null && lunch 2>/dev/null && echo "OK" || echo "FAIL"

echo "=== V4L2工具验证 ==="
v4l2-ctl --version && echo "OK" || echo "FAIL"
media-ctl --version && echo "OK" || echo "FAIL"

echo "=== 编译一个测试程序 ==="
cat > test.c << EOF
#include <stdio.h>
#include <linux/videodev2.h>
int main() { printf("V4L2 version: %d\n", LINUX_VERSION_CODE); return 0; }
EOF
aarch64-linux-gnu-gcc test.c -o test && echo "编译成功" || echo "编译失败"
避坑指南:我曾经在验证时发现v4l2-ctl能运行,但交叉编译的程序在目标板上段错误。最后发现是glibc版本不匹配。建议用file命令检查二进制文件:file test,确认是ARM架构且动态链接库路径正确。

2.5 知识体系总览

下面这张图是我自己总结的环境搭建知识体系,你照着这个思路来,基本不会漏东西:

Camera HAL开发环境搭建知识体系 交叉编译工具链 • 工具链选择 Linaro / NDK / 官方 • 环境变量配置 PATH / CROSS_COMPILE / ARCH • 验证方法 gcc --version / file命令 • 常见问题 glibc版本不匹配 工具链过新导致ABI问题 Android源码编译 • 硬件要求 16核CPU / 32GB内存 / SSD • 依赖安装 Ubuntu 20.04 / python管理 • 源码同步 repo init / repo sync 国内镜像加速 • 编译流程 lunch / make -jN V4L2调试工具 • v4l2-ctl 设备查询 / 格式设置 / 抓帧 • media-ctl 拓扑查看 / pipeline配置 • yavta 采集测试 / 多buffer模式 • gstreamer pipeline调试 / 格式转换 三者缺一不可,建议按顺序搭建并逐一验证

嗯,环境搭建这部分就这些。记住一个原则:先验证工具链,再编译源码,最后调试驱动。顺序搞反了,你会浪费大量时间在排查环境问题上。

可可精品资料库