提问人:PhilBot 提问时间:6/22/2012 更新时间:6/25/2012 访问量:4942
使用 Jenkins 的嵌入式 Linux 开发模型
Embedded Linux Develoment Model with Jenkins
问:
我是一个小型团队(4 - 5 人)的一员,从事嵌入式 linux 项目。我们正在使用 Buildroot 和 Linaro 工具链来构建我们的目标。我们使用 git 进行版本控制,使用 Jenkins 进行夜间构建。
这是我们第一次尝试这样的项目,我一直没有找到任何描述这种环境开发模型的资源。
现在,在每晚构建之后,我创建了一个 Buildroot 'output' 目录的压缩包,其中包含 u-boot 映像和根文件系统。这可以直接从 Jenkins 的“存档”页面下载,以获取上次成功的构建。
我们中的一些人将从事较低级别的开发,一些人将从事用户空间开发(QT)。我们的问题是决定在这样的环境中开发最有效/最简化的方法,因为人们将在项目范围内的不同领域工作。用户空间的家伙们可以下载包含所有内容的压缩包,并将他们的应用程序合并到 rfs 中以在板上运行和调试,但是我们应该如何处理在较低级别的开发中完成的工作?基本上,我们应该如何将工件分发给团队?我非常感谢任何想法。
答:
我最近花了一些时间为一个基于 OpenEmbedded 的 linux 项目重组构建环境。我对 Buildroot 没有直接经验,但我希望 OpenEmbedded 与您正在使用的足够相似。我将描述我的设置,如果幸运的话,您会在这里找到一些有用的东西......
问题
有三个软件组件可以单独安装(即彼此独立):引导加载程序(u-boot);内核 (Linux);和文件系统映像。我们的最终产品随附这三个组件的打包版本。也就是说,已经过 QA 测试并已知可以协同工作的 u-boot、linux 和文件系统映像版本。但是,可以独立升级任何一个组件(例如安装新的内核映像),以创建尚未一起测试的软件组件的组合。
用户空间应用程序也存在此问题。将文件系统映像安装到目标中后,可以独立于其他文件系统对象更新一个或多个用户空间二进制文件(假设您的文件系统不是只读的)。您如何知道现在安装的用户空间应用程序的特定组合可以协同工作?如何确定在此特定单元中运行的二进制文件的组合是否与经过 QA 认证的二进制文件的组合相同?我如何知道软件的“版本”是什么?
我需要解决的另一个问题,与您在问题中概述的问题相同,是如何允许在软件堆栈的不同部分(内核、根文件系统、用户空间 Qt 应用程序等)上工作的开发人员一起工作?
解决方案
我通过以下方式解决了这个问题和“版本”问题:
- 将 rootfs 和 sysroot 存储在 git 存储库中。
- 自由使用 git 子模块。
将目标的根文件系统和系统根文件存储在 git 存储库中最初以错误的方式摩擦我(将输出文件存储在版本控制中,什么?!),但它提供了以下优点:
- 只要构建用户空间应用程序所需的时间(即几十秒),就可以内置 JFFS2 文件系统映像(rootfs + 我们的自定义用户空间应用程序)。开发人员不再需要首先从头开始构建 rootfs(使用 OpenEmbedded 需要几个小时)。
- 版本控制的所有其他优点(随着时间的推移可以很容易地跟踪对 rootfs 的更改、发布标签、分支等)。
- 我最初考虑将 rootfs 和 sysroot 存储为 tarball,但我喜欢 git 在每个文件的基础上跟踪更改的想法。
目录结构如下所示(为了保护无辜者,一些名称已更改):
\---proj [*] # Name of your project
+---u-boot [*]
+---linux [*]
+---toolchain [*]
\---fs [*] # Filesystem stuff.
+---oe [*] # OpenEmbedded.
+---qt [*] # Qt framework.
+---apps [*] # Custom user-space applications.
\---bin [*] # Revision controlled binaries
+---rootfs # Target root filesystem, output of OpenEmbedded.
\---sysroot # System root, output of OpenEmbedded (headers, etc).
每个加星标的目录 [*] 都是一个 git 仓库,每个 git 仓库都是其父级的一个子模块。
构建环境是从顶级 Makefile 初始化的,它本质上是递归的 和 .所有开发人员都会这样做:git submodule init
git submodule update
$ git clone [email protected]:proj proj
$ cd proj
$ make git-init
然后,用户空间开发人员可以立即构建:
$ make --directory proj/fs/apps all # Build apps
$ make --directory proj/fs install # Create JFFS2 image
文件系统维护者可以更新 rootfs:
$ cd proj/fs/oe
$ # Modify build recipes and other OpenEmbedded black magic stuff.
$ make
$ # Go make coffee while oe builds every package on the planet.
$ cd proj/bin # OE writes output files here.
$ git commit # Commit latest rootfs and sysroot.
软件版本控制
从顶级 makefile () 可以构建所有软件组件(内核、u-boot、文件系统映像)。使用以下 git 命令,makefile 将描述当前软件版本的单个环境变量(例如)导出到所有子 make 进程。版本要么是来自 git 存储库的标签,要么是 SHA(例如 ,或 )。proj/Makefile
VER_TAG
v1.0
471087ec254e8e353bb46c533823fc4ece3485b4
471087ec254e8e353bb46c533823fc4ece3485b4-modified
git rev-parse HEAD # Get current SHA
git status --porcelain | wc -c # Is working copy modified?
git describe --exact-match HEAD # Is the working copy a tag?
如果任何项目子目录中的单个文件已被修改,则始终是 。然后,这个单一变量作为编译时常量传递给所有构建(u-boot、内核、用户空间应用程序等)。VER_TAG
xxxx-modified
VER_TAG
在运行时,自定义用户空间应用程序会累积所有组件的值,如果它们都报告相同的值,则该字符串将成为产品报告的正式版本。如果即使一个值与其他值不同,那么软件堆栈就不是从相同的顶级 SHA 构建的,并且不能发布到野外(用于测试的 QA、用于制造的生产等)。VER_TAG
VER_TAG
如果软件组件不是从顶级生成文件(例如)构建的,那么该组件将是未定义的,并且生成的软件堆栈仅供“内部使用”。也就是说,所有软件组件的“发布”只能通过从顶级 makefile 构建来实现。make --directory proj/fs/apps all
VER_TAG
作为参考,linux 通过 procfs 中的自定义文件进行报告,u-boot 通过 linux 命令行 () 报告,每个用户空间应用程序通过进程间通信进行报告。VER_TAG
/proc/cmdline
总结
一个警告。我一个月前才开发了这个构建环境,所以不能声称它的健壮性,但现在它似乎保持在一起......
如果您有具体问题或要点想要澄清,我很乐意更新我的答案。
评论