使用Jenkins嵌入式Linux开发模型

时间:2012-06-22 12:34:55

标签: linux build embedded continuous-integration jenkins

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

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

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

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

1 个答案:

答案 0 :(得分:19)

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

问题

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

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

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

解决方案

我解决了这个和#34;版本"问题:

  1. 将rootfs和sysroot存储在git存储库中。
  2. 自由使用git子模块。
  3. 将目标的根文件系统和系统根文件存储在git存储库中最初以错误的方式存在(将输出文件存储在版本控制中,什么!?!)但它具有以下优点:

    1. 只要构建用户空间应用程序(即数十秒),就可以构建JFFS2文件系统映像(rootfs +我们的自定义用户空间应用程序)。开发人员不再需要首先从头开始构建rootfs(使用OpenEmbedded需要几个小时)。
    2. 版本控制的所有其他优点(可以轻松跟踪对rootfs的更改,发布标记,分支等)。
    3. 我最初考虑将rootfs和sysroot存储为tarball,但我喜欢基于每个文件的git跟踪更改的想法。
    4. 目录结构看起来像这样(某些名称已被更改以保护无辜者):

      \---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 initgit submodule update。所有开发人员都会这样做:

      $ git clone git@your.url: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(proj/Makefile)可以构建所有软件组件(内核,u-boot,文件系统映像)。使用以下git命令,makefile向所有子make进程导出描述当前软件版本的单个环境变量(例如VER_TAG)。该版本是git存储库中的标记或SHA(例如v1.0471087ec254e8e353bb46c533823fc4ece3485b4471087ec254e8e353bb46c533823fc4ece3485b4-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?
      

      如果修改了任何项目子目录中的单个文件,则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通过procfs中的自定义文件报告VER_TAG,通过linux命令行(/proc/cmdline)报告u-boot报告,并通过进程间通信报告每个用户空间应用程序。

      摘要

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

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