Jenkins 集成 QNX 编译、GTest 单元测试及权限配置全指南
本文基于实际项目场景(parkingplanningprocess 代码仓库开发、QNX 编译、产物自动上传至 Algorithm Integration 仓库),整理 Jenkins 从插件安装、环境配置、任务创建到权限分配、单元测试集成的完整流程,全程使用免费插件,可直接落地复用。已提前安装核心插件,无需额外付费,适配小团队协同开发需求。
一、前置准备:已安装的 Jenkins 插件(核心+可选)
本次配置已完成以下插件安装,无需重复操作,插件均为免费开源,可满足项目全流程需求:
核心必备插件(缺一不可)
Git Plugin:核心功能为拉取 parkingplanningprocess 代码仓库代码,支持分支、tag 拉取。
Git Parameter Plugin:关键插件,实现 Jenkins 网页端下拉选择分支或 tag,无需手动输入,提升操作便捷性。
Pipeline Plugin:流水线核心插件,通过 Jenkinsfile 实现构建流程的代码化、可维护、可版本化。
Pipeline: Git:配合 Pipeline 插件使用,实现流水线中 Git 相关操作(拉取代码、获取 commit 信息等)。
Credentials Plugin:管理 Git 账号密码、SSH 密钥等敏感信息,避免明文暴露,提升安全性。
SSH Agent Plugin:若使用 SSH 方式拉取/推送代码,该插件可自动加载 SSH 密钥,无需手动配置。
Timestamper:为 Jenkins 构建日志添加时间戳,便于定位构建过程中的问题,快速排查报错。
可选推荐插件(提升体验)
Generic Webhook Trigger:如需实现自动触发构建(如代码提交后自动构建),可启用该插件,支持通过 webhook 触发。
Build Name and Description Setter:美化构建名称和描述,可自定义构建显示信息(如分支名称、构建时间),便于快速识别构建记录。
二、Jenkins 环境前置要求
Jenkins 执行机需提前配置以下环境,确保构建流程正常运行:
安装 QNX 编译环境(如 qnx7xx),确保能正常运行项目根目录下的 Build.sh 编译脚本。
配置 Git 环境,确保 Jenkins 能正常 git clone、pull、push 两个核心仓库(parkingplanningprocess 和 Algorithm Integration)。
赋予 Jenkins 执行机对 Algorithm Integration 仓库的写权限(用于上传编译产物)。
(可选)安装 Jenkins 中文插件 Localization: Chinese (Simplified),将界面汉化,降低操作门槛(安装后重启 Jenkins 即可生效)。
三、Jenkins 任务创建(Pipeline 流水线,推荐)
采用 Pipeline 流水线模式,通过 Jenkinsfile 固化构建流程,支持版本化管理,后续修改只需调整脚本,无需重复配置界面。
步骤 1:创建参数化构建(网页端选分支/tag)
新建任务 → 选择「Pipeline 流水线」,输入任务名称(如 parkingplanningprocess-build)。
勾选「参数化构建过程」,点击「添加参数」,选择「Git Parameter」。
配置 Git Parameter:
Name:填写 BRANCH_TAG(后续 Jenkinsfile 会引用该参数)。
Parameter Type:选择「Branch or Tag」,支持下拉选择分支或 tag。
Repository URL:填写 parkingplanningprocess 仓库的 Git 地址。
Default Value:填写 master(默认拉取 master 分支,可修改)。
保存参数配置,此时构建页面会出现下拉框,可选择任意分支或 tag 进行构建。
步骤 2:完整 Jenkinsfile 脚本(直接复制使用)
该脚本实现以下功能:拉取代码 → 运行 GTest 单元测试 → QNX 编译 → 生成版本追溯头文件 → 上传产物至 Algorithm Integration 仓库 → 提交推送产物及追溯信息。
pipeline {
agent any
parameters {
gitParameter(name: 'BRANCH_TAG', type: 'BRANCH_TAG', defaultValue: 'master', description: '选择分支或tag(如master、feature/xxx、v1.0)')
}
environment {
// 源仓库:parkingplanningprocess(代码开发仓库)
SRC_REPO = 'git@xxx:parkingplanningprocess.git' // 替换为实际仓库地址
// 目标仓库:Algorithm Integration(产物存放仓库)
DEST_REPO = 'git@xxx:AlgorithmIntegration.git' // 替换为实际仓库地址
// 目标分支:个人开发分支
DEST_BRANCH = 'dev/xuejun.liu/develop'
// QNX 编译产物目录(与项目 Build.sh 输出目录一致)
BUILD_OUTPUT = 'build/install'
}
stages {
// 阶段1:拉取 parkingplanningprocess 对应分支/Tag 代码
stage('代码拉取') {
steps {
git branch: "${params.BRANCH_TAG}", url: "${SRC_REPO}"
script {
// 记录当前构建的 commit、分支、构建时间(用于追溯)
GIT_COMMIT = sh(script: 'git rev-parse --short HEAD', returnStdout: true).trim()
GIT_BRANCH = "${params.BRANCH_TAG}"
BUILD_TIME = sh(script: 'date "+%Y-%m-%d %H:%M:%S"', returnStdout: true).trim()
}
}
}
// 阶段2:GTest 单元测试(新增,测试不通过则终止构建)
stage('单元测试') {
steps {
sh './Build.sh test' // 运行自定义的测试模式,需提前配置 Build.sh
}
}
// 阶段3:QNX 编译(执行项目原有 Build.sh 脚本)
stage('QNX 编译') {
steps {
sh '''
chmod +x Build.sh
./Build.sh // 执行 QNX 编译,产物输出至 BUILD_OUTPUT 目录
'''
}
}
// 阶段4:生成版本追溯头文件(记录构建信息,便于后续追溯)
stage('生成版本追溯头文件 build_info.h') {
steps {
sh '''
cat > ${BUILD_OUTPUT}/build_info.h << EOF
#ifndef BUILD_INFO_H
#define BUILD_INFO_H
#define SRC_REPO "parkingplanningprocess"
#define BRANCH "${GIT_BRANCH}"
#define COMMIT "${GIT_COMMIT}"
#define BUILD_TIME "${BUILD_TIME}"
#define JOB_NAME "${JOB_NAME}"
#define BUILD_NUMBER "${BUILD_NUMBER}"
#endif
EOF
'''
}
}
// 阶段5:拉取目标仓库 Algorithm Integration 对应分支
stage('拉取目标 Algorithm Integration 仓库') {
steps {
dir('AlgorithmIntegration') {
git branch: "${DEST_BRANCH}", url: "${DEST_REPO}"
sh 'git pull' // 拉取最新代码,避免冲突
}
}
}
// 阶段6:拷贝 QNX 编译产物至目标仓库
stage('拷贝编译产物') {
steps {
sh '''
// 清空原有产物,避免旧文件残留
rm -rf AlgorithmIntegration/parkingplanningprocess_output
mkdir -p AlgorithmIntegration/parkingplanningprocess_output
// 拷贝所有产物(config、.a静态库、include头文件、build_info.h)
cp -r ${BUILD_OUTPUT}/* AlgorithmIntegration/parkingplanningprocess_output/
'''
}
}
// 阶段7:提交产物并推送到目标分支
stage('提交并推送到目标分支') {
steps {
dir('AlgorithmIntegration') {
sh '''
git add parkingplanningprocess_output/
git commit -m "CI: 自动更新 parkingplanningprocess 编译产物
分支:${GIT_BRANCH}
提交:${GIT_COMMIT}
时间:${BUILD_TIME}"
git push origin ${DEST_BRANCH}
'''
}
}
}
}
// 构建后通知(成功/失败提示)
post {
success {
echo "✅ 构建成功!产物已推送到 AlgorithmIntegration: ${DEST_BRANCH}"
}
failure {
echo "❌ 构建失败!请查看控制台日志排查问题(重点关注单元测试、QNX 编译步骤)"
}
}
}
四、GTest 单元测试集成(不影响原有 QNX 编译)
为项目添加 GTest 单元测试,确保代码质量,测试不通过则终止构建,避免不合格产物上传。
步骤 1:添加 GTest 源码至项目
进入 parkingplanningprocess 仓库根目录,执行以下命令,将 GTest 源码放入第三方依赖目录:
git clone https://github.com/google/googletest.git thirdparty/googletest步骤 2:修改 CMakeLists.txt(添加测试配置)
在项目根目录的 CMakeLists.txt 底部添加以下内容,启用 GTest 构建:
# --------------------------
# GTest 单元测试集成
# --------------------------
if(BUILD_TESTS)
add_subdirectory(thirdparty/googletest)
include_directories(${gtest_SOURCE_DIR}/include ${gmock_SOURCE_DIR}/include)
# 测试可执行文件(添加需要测试的源文件和测试用例文件)
add_executable(unit_test
test/test_your_code.cpp # 测试用例文件,需自行编写
src/xxx.c # 待测试的业务源文件,替换为实际文件
)
# 链接 GTest 库和线程库
target_link_libraries(unit_test gtest gtest_main pthread)
endif()步骤 3:修改 Build.sh(增加测试模式)
在 Build.sh 底部添加测试模式,单独编译并运行单元测试,不影响原有 QNX 编译:
# ==============================
# GTest 单元测试(x86模式,单独运行)
# ==============================
if [ "$1" = "test" ]; then
mkdir -p build_test
cd build_test
cmake .. -DBUILD_TESTS=ON # 启用测试构建
make -j8 # 多线程编译测试用例
./unit_test # 运行单元测试,失败则退出
exit 0
fi手动测试命令:\./Build\.sh test,测试通过则继续,失败则终止。
步骤 4:Jenkins 显示测试报告(可选)
安装免费插件 JUnit Plugin(显示测试结果)和 Cobertura Plugin(显示代码覆盖率),在 Jenkinsfile 的 post 阶段添加以下内容,即可在 Jenkins 网页查看测试报告:
post {
always {
junit 'build_test/*.xml' // 展示测试用例执行结果
cobertura 'build_test/coverage.xml' // 展示代码覆盖率
}
}五、Jenkins 重启方法(常用3种)
配置插件、修改核心设置后,需重启 Jenkins 使配置生效,推荐以下3种方式,按需选择:
方式 1:网页端图形化重启(最简单)
打开 Jenkins 首页,在地址栏后添加:http://你的Jenkins地址/restart,点击确认重启即可。
备用地址: - 安全重启(等待当前构建完成后重启):/safeRestart - 强制停止:/stop
方式 2:网页菜单重启(中文界面)
进入 Jenkins → 系统管理 → 找到「重启 Jenkins」按钮,点击确认即可(安装中文插件后可见)。
方式 3:服务器命令行重启(Linux/Docker)
Linux(systemd 安装):
systemctl restart jenkins \# 重启 systemctl status jenkins \# 查看重启状态Docker 部署:
docker ps \| grep jenkins \# 查看Jenkins容器名 docker restart 容器名 \# 重启容器
六、队友权限配置(最小权限原则)
为队友开放 Jenkins 权限,仅赋予「构建、查看日志、下载产物」权限,禁止修改配置、删除任务,保障系统安全。
步骤 1:安装权限插件(免费)
安装 Role-based Authorization Strategy 插件(角色权限控制),已安装核心插件后,直接在插件管理中搜索安装即可。
步骤 2:创建队友账号
Jenkins → 系统管理 → 管理用户 → 新建用户。
填写用户名(如 zhang.san)、密码、邮箱,不开启公开注册,由管理员统一创建。
步骤 3:开启角色权限模式
系统管理 → 全局安全配置 → 授权策略 → 选择「Role-Based Strategy」,保存后刷新页面。
步骤 4:创建角色(最小权限)
系统管理 → Manage and Assign Roles → Manage Roles。
全局角色(Global roles):新建角色 dev_global,仅勾选「Overall → Read」(能登录、看界面)、「Credentials → View」(能看凭据,不能改)。
项目角色(Item roles):新建角色 dev_parking,配置如下:
Project pattern:填写 parkingplanningprocess(或 .*parking.* 匹配所有泊车相关任务)。
权限勾选:Job → Read(看任务)、Job → Build(构建)、Run → Read(看日志)、Artifact → Read(下载产物)、Git Parameter → View(看分支下拉框)。
不勾选:Job/Configure、Job/Delete、Administer(禁止修改配置、删除任务)。
步骤 5:分配角色给队友
Manage and Assign Roles → Assign Roles: - 全局角色:给队友勾选 dev_global。 - 项目角色:给队友勾选 dev_parking。 保存后,队友退出重登即可生效。
七、构建地址分享(3种常用方式)
构建完成后,可将构建地址分享给队友,方便查看日志、下载产物,无需手动传递。
方式 1:直接复制链接(最常用)
项目主页(队友可选分支、构建):
http://你的JenkinsIP:8080/job/parkingplanningprocess/某次构建详情:
http://你的JenkinsIP:8080/job/parkingplanningprocess/构建号/(构建号为数字,如 123)控制台日志直达:
http://你的JenkinsIP:8080/job/parkingplanningprocess/构建号/console
方式 2:匿名只读(内网推荐)
若只想让队友查看、不允许操作,可开启匿名只读:
系统管理 → 全局安全配置 → 匿名用户权限,勾选「Overall → Read」「Job → Read」「Run → Read」「Artifact → Read」,不勾选 Build、Configure,保存后队友无需登录即可查看。
方式 3:自动推送链接至群聊(高级)
安装对应聊天工具插件(钉钉:DingTalk Notification;企业微信:WeChat Work Notification),在 Jenkinsfile 的 post 阶段添加推送代码,构建完成后自动将链接发送至群聊。
八、常见问题排查
插件搜不到:网络问题导致,可通过 Jenkins 插件官网(https://plugins.jenkins.io/)下载 .hpi 离线包,在「插件管理 → Advanced → 上传 .hpi」安装,重启生效。
队友看不到分支下拉框:确认给队友分配的角色勾选了「Git Parameter → View」权限,退出重登即可。
构建失败:优先查看控制台日志,重点排查单元测试失败、QNX 编译报错、Git 权限不足(凭据配置错误)。
产物上传失败:确认 Jenkins 执行机有 Algorithm Integration 仓库的写权限,目标分支正确。
总结
本文基于已安装的 Jenkins 核心插件,完成了 parkingplanningprocess 项目的全流程配置,涵盖「分支选择 → 单元测试 → QNX 编译 → 产物上传 → 权限管理 → 地址分享」,所有操作均使用免费插件,不破坏原有项目结构和编译流程,可直接落地复用。后续可根据团队需求,添加自动触发、测试报告优化等功能,
评论区