3、持续集成初探:Jenkins 安装与第一个自动化构建任务

说到持续集成,我脑子里第一个蹦出来的工具就是 Jenkins。说实话,这玩意儿在嵌入式圈子里有点被低估了。很多人觉得 Jenkins 是互联网后端用的,跟单片机、RTOS 不沾边。但我在几个量产项目里试过之后,发现它简直是嵌入式团队的「救星」。

为什么这么说?你想想看,嵌入式开发最头疼的是什么?编译环境不一致、固件版本混乱、手动烧录容易出错。Jenkins 能把这些痛点全给管起来。今天我们就从零开始,把 Jenkins 装好,跑通第一个自动化构建任务。

3.1 Jenkins 是什么?为什么嵌入式要用它?

Jenkins 是一个开源的自动化服务器。说白了,它就是个「调度中心」。你告诉它什么时候该干什么活,它就会按时按点去执行。比如每天凌晨自动拉代码、编译、跑测试、打包固件。

我在一个车载项目里遇到过这种情况:团队 5 个人,每人本地编译环境都不一样。有人用 GCC 9,有人用 GCC 11,结果同样的代码,有人编译通过,有人报错。后来我把 Jenkins 搭起来,统一了编译环境,这种问题再也没出现过。

核心价值: Jenkins 能帮你把「手动重复劳动」变成「自动化流水线」。对于嵌入式开发,这意味着更少的低级错误和更快的迭代速度。

3.2 安装 Jenkins:两种主流方式

安装 Jenkins 其实不复杂。我个人习惯用 Docker 部署,干净利落,想换版本也方便。但如果你对 Docker 不熟,直接用系统包管理器安装也行。

方式一:Docker 安装(推荐)

前提是你已经装好了 Docker。没装的话先去官网下个 Docker Desktop,Windows/Mac/Linux 都支持。

# 拉取 Jenkins 镜像(LTS 长期支持版)
docker pull jenkins/jenkins:lts

# 启动容器
docker run -d \
  --name jenkins \
  -p 8080:8080 \
  -p 50000:50000 \
  -v jenkins_home:/var/jenkins_home \
  jenkins/jenkins:lts

启动后,打开浏览器访问 http://localhost:8080。第一次进入会让你输入初始密码。

# 查看初始密码
docker exec jenkins cat /var/jenkins_home/secrets/initialAdminPassword
小技巧: 我习惯把 jenkins_home 挂载到宿主机的一个固定目录,比如 /data/jenkins。这样即使容器挂了,配置和任务都不会丢。

方式二:直接安装(Linux 为例)

如果你不想用 Docker,直接在 Ubuntu 上装也很简单。

# 添加 Jenkins 源
wget -q -O - https://pkg.jenkins.io/debian/jenkins.io.key | sudo apt-key add -
sudo sh -c 'echo deb http://pkg.jenkins.io/debian-stable binary/ > /etc/apt/sources.list.d/jenkins.list'

# 安装
sudo apt update
sudo apt install jenkins

# 启动服务
sudo systemctl start jenkins
sudo systemctl enable jenkins

安装完成后,同样访问 http://localhost:8080。初始密码在 /var/lib/jenkins/secrets/initialAdminPassword 里。

注意: 直接安装方式下,Jenkins 默认以 jenkins 用户运行。如果你需要访问 USB 设备(比如烧录器),记得把 jenkins 用户加到 dialout 组里。我曾经因为这个折腾了半天,烧录器死活连不上。

3.3 初始化配置:插件与管理员

第一次登录后,Jenkins 会引导你安装插件。这里我建议选「安装推荐的插件」,省心。等后面有需要再单独装。

插件安装完,创建管理员账号。记住这个账号密码,后面所有操作都靠它。

嗯,这里要注意:如果你是在公司内网用,建议把 Jenkins 的端口改成 8081 或者别的,避免跟其他服务冲突。我遇到过 Jenkins 和 Tomcat 抢 8080 端口的情况,挺尴尬的。

3.4 第一个自动化构建任务:编译嵌入式固件

好,环境搭好了,我们来干点正事。创建一个「自由风格」的任务,让它帮我们自动编译一个嵌入式项目。

步骤 1:创建任务

  1. 点击「新建任务」
  2. 输入任务名称,比如 firmware-build
  3. 选择「自由风格项目」
  4. 点击确定

步骤 2:配置源码管理

在任务配置页面,找到「源码管理」部分,选择 Git。填入你的仓库地址。如果你的仓库是私有的,还需要添加凭据。

Repository URL: https://github.com/your-org/your-firmware.git
Branches to build: */main
个人经验: 嵌入式项目经常有子模块(submodule),记得勾上「高级」里的「递归克隆子模块」。不然编译时会报头文件找不到。

步骤 3:配置构建触发器

这里我推荐两种方式:

  • 定时构建: 比如每天凌晨 2 点自动编译一次
  • 轮询 SCM: 每隔几分钟检查一次代码仓库,有变化就触发构建

定时构建的语法跟 Linux 的 cron 类似:

# 每天凌晨 2 点执行
H 2 * * *

轮询 SCM 的写法:

# 每 5 分钟检查一次
H/5 * * * *
避坑指南: 我曾经在一个项目里设置了每 1 分钟轮询一次,结果团队 10 个人频繁提交代码,Jenkins 被活活累垮了。建议轮询间隔至少 5 分钟以上。

步骤 4:配置构建环境

嵌入式编译通常需要交叉编译工具链。你需要在 Jenkins 所在的机器上装好工具链,然后在构建环境里配置环境变量。

在「构建环境」部分,勾选「Add timestamps to the Console Output」。这个很有用,能帮你定位编译耗时。

步骤 5:添加构建步骤

点击「增加构建步骤」,选择「执行 shell」。然后输入你的编译命令。

#!/bin/bash
# 进入项目目录
cd $WORKSPACE

# 清理之前的编译产物
make clean

# 开始编译
make all

# 如果编译成功,打包固件
if [ $? -eq 0 ]; then
    tar -czf firmware.tar.gz build/
    echo "编译成功,固件已打包"
else
    echo "编译失败,请检查日志"
    exit 1
fi

步骤 6:保存并运行

点击保存。回到任务页面,点击「立即构建」。你会看到构建队列里出现一个任务,点击进去就能看到实时控制台输出。

第一次构建可能会慢一些,因为要拉代码、下载依赖。后面就快了。

3.5 查看构建结果与产物

构建完成后,你会看到状态变成蓝色(成功)或红色(失败)。点击具体的构建号,可以查看:

  • 控制台输出: 完整的编译日志
  • 构建产物: 我们刚才打包的 firmware.tar.gz
  • 测试结果: 如果有单元测试,这里会显示通过率
关键点: 构建产物默认只保留最近几次。如果你需要长期保存,可以在「构建后操作」里配置「归档制品」,指定要保留的文件模式,比如 **/*.tar.gz

3.6 常见问题与解决

问题 原因 解决方法
构建一直卡在「等待」状态 执行器数量不足 在系统管理 → 节点管理中增加执行器数量
编译报错:找不到头文件 工具链路径未配置 在构建步骤中 export PATH 或使用全局环境变量
Git 拉取代码失败 凭据失效或网络问题 检查凭据是否正确,或改用 SSH 方式
构建产物为空 归档路径配置错误 检查「归档制品」中的通配符是否匹配实际文件路径

3.7 小结与下一步

到这,你已经完成了 Jenkins 的安装和第一个自动化构建任务。说白了,就是让 Jenkins 帮你自动拉代码、编译、打包。别小看这一步,它能让你的团队从「手动编译 → 手动打包 → 手动测试」的泥潭里解脱出来。

下一步,我会带你给这个流水线加上自动化测试和固件烧录。嗯,那才是真正让 Jenkins 发挥价值的地方。

记住,持续集成不是一蹴而就的。先跑通一个简单的编译任务,再慢慢往上加东西。我见过太多团队一上来就想搞全自动化,结果把自己搞崩溃了。

慢慢来,比较快。