- 一、准备工作
- 1. 环境要求
- 2. 基础工具安装
- 二、Jenkins部署与初始化
- 1. Jenkins安装(Ubuntu版)
- 2. Jenkins初始化配置
- 3. 安装嵌入式开发必备插件
- 三、Jenkins Pipeline核心语法
- 1. 声明式Pipeline基本结构
- 2. 核心指令说明
- 四、嵌入式项目自动构建/测试/部署实战
- 1. 项目准备
- 2. 编写Pipeline流水线脚本
- 3. 执行流水线与结果验证
- 五、常见问题与解决方案
在嵌入式开发中,手动编译固件、逐个测试功能、手动烧录部署的方式不仅效率低下,还容易因环境不一致导致“本地能跑,设备上崩”的问题。而基于Jenkins搭建CI/CD工具链,通过Pipeline实现代码拉取-自动构建-自动化测试-固件部署的全流程自动化,能大幅提升嵌入式项目的开发效率和交付质量。
一、准备工作
1. 环境要求
- 服务器:Linux系统(本文以Ubuntu 22.04 LTS为例,推荐2核4G以上配置),需联网且开放8080端口(Jenkins默认端口)。
- 依赖工具:JDK 11(Jenkins 2.361+要求)、Git(拉取代码)、嵌入式交叉编译工具链(如ARM-linux-gnueabihf-gcc,根据项目架构选择)、CMake(嵌入式项目构建工具)、QEMU(嵌入式模拟器,用于自动化测试)。
- 嵌入式项目:需托管在Git仓库(Gitee/GitHub/GitLab均可),项目需包含CMakeLists.txt构建脚本和单元测试用例(如Unity测试框架)。
2. 基础工具安装
先在Linux服务器上安装必备依赖:
更新软件源
sudo apt update && sudo apt upgrade -y安装JDK 11
sudo apt install openjdk-11-jdk -y
java -version 验证安装安装Git、CMake、QEMU
sudo apt install git cmake qemu-system-arm -y安装ARM交叉编译工具链(以ARMv7为例)
sudo apt install gcc-arm-linux-gnueabihf g++-arm-linux-gnueabihf -y
arm-linux-gnueabihf-gcc -v 验证工具链
二、Jenkins部署与初始化
1. Jenkins安装(Ubuntu版)
采用官方源安装,确保版本最新:
添加Jenkins官方密钥
curl -fsSL https://pkg.jenkins.io/debian-stable/jenkins.io-2023.key | sudo tee /usr/share/keyrings/jenkins-keyring.asc > /dev/null添加Jenkins源
echo deb [signed-by=/usr/share/keyrings/jenkins-keyring.asc] https://pkg.jenkins.io/debian-stable binary/ | sudo tee /etc/apt/sources.list.d/jenkins.list > /dev/null安装Jenkins
sudo apt update && sudo apt install jenkins -y启动Jenkins并设置开机自启
sudo systemctl start jenkins
sudo systemctl enable jenkins
sudo systemctl status jenkins 检查运行状态
2. Jenkins初始化配置
- 访问Jenkins:在浏览器输入
http://服务器IP:8080,等待页面加载后,根据提示从/var/lib/jenkins/secrets/initialAdminPassword文件中获取初始密码:sudo cat /var/lib/jenkins/secrets/initialAdminPassword - 安装插件:选择“安装推荐的插件”,等待插件安装完成后,创建管理员账号(记住账号密码,后续登录用)。
- 配置工具路径:进入Jenkins首页 → 系统管理 → 全局工具配置,分别配置:
- JDK:取消“自动安装”,填写JDK安装路径(如
/usr/lib/jvm/java-11-openjdk-amd64)。 - Git:填写Git路径(如
/usr/bin/git)。 - CMake:填写CMake路径(如
/usr/bin/cmake)。 - 交叉编译工具链:无需单独配置,后续在Pipeline中直接调用命令即可。
- JDK:取消“自动安装”,填写JDK安装路径(如
3. 安装嵌入式开发必备插件
进入Jenkins → 系统管理 → 插件管理 → 可选插件,搜索并安装以下插件:
- Pipeline:核心Pipeline插件,支持流水线编写。
- Git Plugin:拉取Git仓库代码。
- SSH Plugin:通过SSH部署固件到嵌入式开发板。
- JUnit Plugin:解析测试报告,展示测试结果。
- Pipeline Utility Steps:方便处理Pipeline中的文件和变量。
三、Jenkins Pipeline核心语法
Jenkins Pipeline有两种类型:声明式Pipeline(推荐,语法简洁、易维护)和脚本式Pipeline(灵活性高,适合复杂场景)。本文以嵌入式项目为例,重点讲解声明式Pipeline。
1. 声明式Pipeline基本结构
声明式Pipeline以pipeline为根节点,核心包含agent(执行节点)、stages(流水线阶段)、steps(阶段执行步骤)、post(执行后操作)等部分,基本结构如下:
pipeline {agent any // 任意Jenkins节点执行environment {// 定义全局环境变量,如项目路径、固件名称PROJECT_PATH = "/var/lib/jenkins/workspace/embedded_project"FIRMWARE_NAME = "app.elf"}stages {stage("拉取代码") { // 阶段1:从Git拉取代码steps {// 执行步骤,如git clone}}stage("自动构建") { // 阶段2:交叉编译嵌入式固件steps {// 执行cmake、make编译}}stage("自动化测试") { // 阶段3:QEMU模拟测试+单元测试steps {// 执行测试用例,生成测试报告}}stage("自动部署") { // 阶段4:部署固件到开发板/私服steps {// 通过SCP/SSH推送固件}}}post { // 执行后操作,如发送通知、清理环境success {echo "流水线执行成功!固件已构建并部署完成。"}failure {echo "流水线执行失败,请检查日志!"}}
}
2. 核心指令说明
- agent:指定流水线执行的节点,
agent any表示任意节点,agent { label 'embedded-node' }表示指定标签为embedded-node的节点(适合多节点部署)。 - environment:定义全局环境变量,可在整个流水线中调用。
- stages/stage:
stages包含多个stage,每个stage代表一个流水线阶段(如构建、测试、部署)。 - steps:每个
stage下的具体执行步骤,支持执行shell命令、Jenkins内置步骤等。 - post:流水线执行完成后的操作,支持
success(成功)、failure(失败)、always(始终执行)等条件。
四、嵌入式项目自动构建/测试/部署实战
本文以ARM Cortex-A7架构的嵌入式Linux项目为例,项目使用CMake构建,Unity做单元测试,QEMU模拟运行测试,最终通过SSH将固件部署到开发板。
1. 项目准备
假设嵌入式项目托管在Gitee仓库https://gitee.com/yourname/embedded_demo.git,项目结构如下:
embedded_demo/
├── CMakeLists.txt 构建脚本
├── src/ 源码目录
│ ├── main.c
│ └── driver/ 驱动源码
├── test/ 测试用例目录
│ ├── test_main.c 单元测试入口
│ └── unity/ Unity测试框架
└── deploy/ 部署脚本└── push_to_board.sh 推送固件到开发板的脚本
2. 编写Pipeline流水线脚本
进入Jenkins首页 → 新建任务 → 输入任务名称(如embedded_cicd_demo)→ 选择“流水线” → 确定。在任务配置页面的“流水线”部分,选择“Pipeline脚本”,输入以下脚本(根据实际项目修改仓库地址、开发板IP等信息):
pipeline {agent anyenvironment {// 定义环境变量GIT_REPO = "https://gitee.com/yourname/embedded_demo.git"PROJECT_NAME = "embedded_demo"BOARD_IP = "192.168.1.100" // 嵌入式开发板IPBOARD_USER = "root" // 开发板登录用户名BOARD_PATH = "/root/firmware/" // 开发板固件存放路径}stages {stage("拉取代码") {steps {echo "开始拉取代码..."git url: "${GIT_REPO}", branch: "master" // 拉取master分支代码}}stage("自动构建(交叉编译)") {steps {echo "开始交叉编译嵌入式固件..."sh """创建构建目录mkdir -p buildcd build交叉编译配置:指定ARM交叉编译器cmake -DCMAKE_C_COMPILER=arm-linux-gnueabihf-gcc -DCMAKE_BUILD_TYPE=Release ..编译项目(-j后接核心数,加快编译速度)make -j4检查固件是否生成if [ -f ${PROJECT_NAME}.elf ]; thenecho "固件编译成功:${PROJECT_NAME}.elf"cp ${PROJECT_NAME}.elf ../${PROJECT_NAME}_\$(date +%Y%m%d).elf 重命名固件,添加日期elseecho "固件编译失败!"exit 1fi"""}}stage("自动化测试") {steps {echo "开始执行自动化测试..."sh """cd build执行单元测试(假设测试程序为test_app)./test_app > test_report.xml 生成JUnit格式测试报告使用QEMU模拟ARM环境运行固件,验证功能qemu-arm -L /usr/arm-linux-gnueabihf/ ../${PROJECT_NAME}.elf --test"""// 解析JUnit测试报告,在Jenkins中展示测试结果junit 'build/test_report.xml'}}stage("自动部署到开发板") {steps {echo "开始部署固件到开发板 ${BOARD_IP}..."sh """通过SCP将固件推送到开发板scp ../${PROJECT_NAME}_\$(date +%Y%m%d).elf ${BOARD_USER}@${BOARD_IP}:${BOARD_PATH}通过SSH执行开发板上的命令,重启应用ssh ${BOARD_USER}@${BOARD_IP} "cd ${BOARD_PATH} && chmod +x ${PROJECT_NAME}_\$(date +%Y%m%d).elf && ./${PROJECT_NAME}_\$(date +%Y%m%d).elf &""""}}}post {always {echo "流水线执行完成,开始清理构建目录..."sh "rm -rf build" // 清理构建目录}success {echo "✅ 嵌入式固件构建、测试、部署全流程成功!"}failure {echo "❌ 流水线执行失败,请查看控制台日志排查问题!"// 可添加邮件通知、企业微信/钉钉通知等}}
}
3. 执行流水线与结果验证
- 保存配置:填写完Pipeline脚本后,点击“保存”。
- 构建流水线:点击任务页面的“立即构建”,等待流水线执行。可通过“控制台输出”查看每一步的执行日志。
- 结果验证:
- 若流水线执行成功,可在开发板的
/root/firmware/目录下看到新推送的固件,且应用正常运行。 - 在Jenkins任务页面的“测试结果”中,可查看单元测试的通过率、失败用例等信息。
- 若执行失败,根据控制台日志排查问题(如交叉编译工具链缺失、开发板SSH连接失败、测试用例执行报错等)。
- 若流水线执行成功,可在开发板的
五、常见问题与解决方案
- Jenkins启动失败:查看日志
journalctl -u jenkins,若提示“端口8080被占用”,修改/etc/default/jenkins文件中的HTTP_PORT为其他端口(如8081),重启Jenkins。 - 交叉编译失败:检查交叉编译工具链是否安装成功,或在Pipeline中指定工具链的绝对路径(如
/usr/bin/arm-linux-gnueabihf-gcc)。 - QEMU运行固件报错:确保安装了对应架构的QEMU(如
qemu-system-arm),且固件编译时未开启硬件相关的特有功能(如MMU、外设驱动)。 - SSH部署到开发板失败:检查开发板是否开启SSH服务、服务器与开发板网络是否互通,或配置Jenkins免密登录开发板(将Jenkins服务器的公钥添加到开发板的
~/.ssh/authorized_keys)。 - 测试报告解析失败:确保测试程序生成的是JUnit格式的XML报告,且路径与Pipeline中
junit指令的路径一致。