2、开发环境搭建:交叉编译工具链安装、CMake与Makefile入门、Docker镜像制作与使用
说实话,嵌入式视觉项目最让人头疼的,往往不是算法本身,而是开发环境。我见过太多新手把时间浪费在「装环境」上,一装就是两三天,最后还跑不起来。这一章,我就带你把这套环境彻底搞定。
2.1 交叉编译工具链:为什么需要它?
你想想看,你的开发电脑是 x86 架构,但嵌入式板子通常是 ARM 架构。你在电脑上编译出来的程序,板子根本跑不了。怎么办?
交叉编译就是干这个的。说白了,就是在你的电脑上,用一套特殊的工具链,编译出能在 ARM 板子上运行的程序。
2.1.1 安装 ARM 交叉编译工具链
我个人习惯用 Linaro 提供的工具链,稳定且社区活跃。以 ARM Cortex-A 系列为例:
# 下载工具链
wget https://releases.linaro.org/components/toolchain/binaries/latest-7/arm-linux-gnueabihf/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf.tar.xz
# 解压到指定目录
tar -xvf gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf.tar.xz -C /opt/
# 配置环境变量
export PATH=/opt/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf/bin:$PATH
~/.bashrc 或 ~/.zshrc 里,这样每次打开终端就不用重新 export 了。
2.1.2 验证安装
arm-linux-gnueabihf-gcc --version
如果看到版本号输出,说明安装成功。嗯,这里要注意:不同板子的架构可能不一样,比如 Cortex-M 系列要用 arm-none-eabi,别搞混了。
2.2 CMake 与 Makefile:构建系统的选择
有了工具链,接下来就是怎么组织代码编译了。你当然可以用一条条 gcc 命令手动编译,但项目一复杂,这方式就彻底崩了。我建议你至少掌握 Makefile 和 CMake 中的一种。
2.2.1 Makefile 入门
Makefile 是 Linux 下最经典的构建工具。它的核心思想很简单:定义目标、依赖和命令。
# 一个简单的 Makefile 示例
CC = arm-linux-gnueabihf-gcc
CFLAGS = -Wall -O2
all: hello
hello: hello.c
$(CC) $(CFLAGS) -o hello hello.c
clean:
rm -f hello
运行 make 就能编译,make clean 清理。是不是很直观?
但 Makefile 有个问题:跨平台时很痛苦。你想想看,如果要在 x86 上调试,在 ARM 上发布,你得维护两套 Makefile。这时候,CMake 就派上用场了。
2.2.2 CMake:更现代的构建方式
CMake 不直接编译,它先生成 Makefile(或其他构建文件),然后再调用 make。它的优势在于:一次编写,到处编译。
# CMakeLists.txt 示例
cmake_minimum_required(VERSION 3.10)
project(HelloWorld)
set(CMAKE_C_COMPILER arm-linux-gnueabihf-gcc)
set(CMAKE_CXX_COMPILER arm-linux-gnueabihf-g++)
add_executable(hello hello.c)
编译步骤:
mkdir build
cd build
cmake ..
make
我个人习惯用 CMake,因为它对大型项目支持更好。比如你要添加 OpenCV、TensorFlow Lite 这些库,CMake 的 find_package 命令能自动帮你找到路径,省心不少。
2.3 Docker 镜像制作与使用:环境一致性神器
你有没有遇到过这种情况:代码在同事电脑上编译通过,到你这就报错。或者,部署到板子上时发现少了个库。Docker 就是解决这个问题的。
Docker 可以把整个开发环境打包成一个镜像。你只要拉下来,就能在任意机器上复现完全一样的环境。
2.3.1 编写 Dockerfile
以嵌入式视觉项目为例,我们需要交叉编译工具链、CMake、OpenCV 等。下面是一个典型的 Dockerfile:
FROM ubuntu:18.04
# 安装基础工具
RUN apt-get update && apt-get install -y \
build-essential \
cmake \
git \
wget \
libopencv-dev \
&& rm -rf /var/lib/apt/lists/*
# 安装交叉编译工具链
RUN wget -q https://releases.linaro.org/components/toolchain/binaries/latest-7/arm-linux-gnueabihf/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf.tar.xz \
&& tar -xJf gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf.tar.xz -C /opt/ \
&& rm gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf.tar.xz
# 设置环境变量
ENV PATH="/opt/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf/bin:${PATH}"
# 创建工作目录
WORKDIR /workspace
2.3.2 构建与使用镜像
# 构建镜像
docker build -t embedded-vision-env:1.0 .
# 运行容器,挂载本地代码
docker run -it --rm \
-v $(pwd):/workspace \
embedded-vision-env:1.0 \
/bin/bash
进入容器后,你就可以像在本地一样编译代码了。而且,不管换到哪台机器,环境都是一模一样的。
docker build 一下,就能开始干活。省去了「帮我装一下这个库」的沟通成本。
2.3.3 多阶段构建:减小镜像体积
你可能会发现,一个包含完整工具链的镜像,体积轻松超过 1GB。这其实没必要。我们可以用多阶段构建,只把最终产物拷贝出来。
# 第一阶段:编译
FROM embedded-vision-env:1.0 AS builder
COPY . /workspace
RUN mkdir build && cd build && cmake .. && make
# 第二阶段:运行
FROM arm64v8/ubuntu:18.04
COPY --from=builder /workspace/build/hello /app/hello
CMD ["/app/hello"]
这样,最终镜像只包含可执行文件和运行时依赖,体积能缩小 10 倍以上。
arm64v8/ubuntu,别用 ubuntu(那是 x86 的)。
2.4 总结
这一章我们搞定了三件事:
- 交叉编译工具链:让 x86 电脑编译出 ARM 程序
- CMake 与 Makefile:让项目构建自动化、跨平台
- Docker 镜像:让开发环境可复现、可移植
这三样东西,是嵌入式视觉项目开发的「基础设施」。我建议你花点时间,把 Dockerfile 写好,把 CMakeLists.txt 配好。后面写代码的时候,你会发现这些前期投入,真的值。
下一章,我们开始搭建视觉算法的基础框架。到时候,这些环境配置就能派上大用场了。
公众号:蓝海资料掘金营,微信deep3321