嵌入式Linux开发模型与Jenkins

Phi*_*Bot 12 linux embedded continuous-integration build jenkins

我是一个从事嵌入式Linux项目的小团队(4-5人)的一员.我们正在使用Buildroot和Linaro工具链来构建我们的目标.我们使用git进行版本控制,使用Jenkins进行夜间构建.

这是我们第一次参加这样的项目,但是我找不到任何用这种环境描述开发模型的资源是不成功的.

现在,在每晚构建之后,我创建了一个Buildroot'output'目录的tarball,其中包含u-boot映像和根文件系统.这可以直接从Jenkins'archive'页面下载,以便上次成功构建.

我们中的一些人将致力于低级开发,一些用于用户空间开发(QT).我们的问题是决定什么是最有效/简化的方法是在这样的环境中开发,因为人们将在项目范围内的不同领域开展工作.用户专家可以下载所有内容的tarball并将他们的应用程序合并到rfs中以在板上运行并进行调试,但是我们应该如何处理在较低级别开发上完成的工作?基本上,我们应该如何将工件分发给团队?我非常感谢任何想法.

Ben*_*Ben 19

我最近花了一些时间来重构基于OpenEmbedded的linux项目的构建环境.我没有使用Buildroot的直接经验,但我希望OpenEmbedded与你正在使用的相似.我将描述我的设置,如果运气好,你会发现这里有用的东西......

问题

有三个软件组件可以单独安装(即彼此独立):引导加载程序(u-boot); 内核(linux); 和文件系统映像.我们的最终产品随附这三个组件的打包版本.也就是说,u-boot,linux和文件系统映像的一个版本经过QA测试并且已知可以协同工作.但是,可以独立升级任何一个组件(例如,安装新的内核映像)以创建未经过一起测试的软件组件的组合.

用户空间应用程序也存在此问题.一旦将文件系统映像安装到目标中,就可以独立于其他文件系统对象更新一个或多个用户空间二进制文件(假设您的文件系统不是只读的).您如何知道现在安装的用户空间应用程序的特定组合可以一起工作?我怎样才能确定在这个特定单元中运行的二进制文件的组合是否经过QA认证的二进制文件的组合?我怎么知道软件的"版本"是什么?

我需要解决的另一个问题,就是你在问题中提出的同样问题,是如何让开发人员在软件堆栈的不同部分(内核,根文件系统,用户空间Qt应用程序等)协同工作?

一个办法

我通过以下方式解决了这个问题和"版本"问题:

  1. 将rootfs和sysroot存储在git存储库中.
  2. 自由使用git子模块.

将目标的根文件系统和系统根文件存储在git存储库中最初是以错误的方式(在版本控制中存储输出文件,什么!?!)但是它提供了以下优点:

  1. 只要构建用户空间应用程序(即数十秒),就可以构建JFFS2文件系统映像(rootfs +我们的自定义用户空间应用程序).不再需要开发人员首先从头开始构建rootfs(使用OpenEmbedded需要几个小时).
  2. 版本控制的所有其他优点(rootfs的更改可以随着时间的推移轻松跟踪,发布的标签,分支等).
  3. 我最初考虑将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).
Run Code Online (Sandbox Code Playgroud)

每个星号目录[*]都是一个git存储库,每个git存储库都是其父级的子模块.

构建环境是从顶级Makefile初始化的,它基本上是递归git submodule initgit submodule update.所有开发人员都会:

$ git clone git@your.url:proj proj
$ cd proj
$ make git-init
Run Code Online (Sandbox Code Playgroud)

然后,用户空间开发人员可以立即构建:

$ make --directory proj/fs/apps all       # Build apps
$ make --directory proj/fs install        # Create JFFS2 image
Run Code Online (Sandbox Code Playgroud)

文件系统维护者可以更新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.
Run Code Online (Sandbox Code Playgroud)

软件版本控制

从顶级makefile(proj/Makefile)可以构建所有软件组件(内核,u-boot,文件系统映像).使用以下git命令,makefile向所有子make进程导出VER_TAG描述当前软件版本的单个环境变量(例如).该版本是来自git存储库的标签或SHA(例如v1.0,471087ec254e8e353bb46c533823fc4ece3485b4471087ec254e8e353bb46c533823fc4ece3485b4-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?
Run Code Online (Sandbox Code Playgroud)

如果甚至修改了任何项目子目录中的单个文件,那么VER_TAG将始终如此xxxx-modified.VER_TAG然后将此单个变量作为编译时常量传递给所有构建(u-boot,内核,用户空间应用程序等).

在运行时,自定义用户空间应用程序会累积VER_TAG所有组件的值,如果它们都报告相同的值,则该字符串将成为产品报告的正式版本.如果即使一个VER_TAG值与其他值不同,那么软件堆栈不是从相同的顶级SHA构建的,并且不能被释放到野外(用于QA用于测试,用于生产用于制造等).

如果软件组件不是从顶级makefile(例如make --directory proj/fs/apps all)VER_TAG构建的,则该组件的未定义和所得到的软件堆栈仅用于"内部使用".也就是说,只能通过从顶级makefile构建来"释放"所有软件组件.

作为参考,linux VER_TAG通过procfs中的自定义文件,通过linux命令行(/proc/cmdline)的u-boot报告以及通过进程间通信的每个用户空间应用程序进行报告.

摘要

一个警告.我只在一个月前开发了这个构建环境,所以不能声称它的稳健性,但是现在它似乎在一起......

如果您有特定的问题或要点,请澄清我很乐意更新我的答案.