linux - 使用 Jenkins 的嵌入式 Linux 开发模型

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

这是我们第一次参与这样的项目,我一直没有成功找到任何描述这种环境下开发模型的资源。

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

我们中的一些人将致力于较低级别的开发,一些人将致力于用户空间开发 (QT)。我们的问题是,鉴于人们将在项目范围内的不同领域工作,因此决定在这样的环境中开发最有效/最精简的方法是什么。用户端的人可以下载包含所有内容的 tarball 并将他们的应用程序合并到 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 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 将描述当前软件版本的单个环境变量(例如 VER_TAG)导出到所有子 make 进程。版本是来自 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 报告 VER_TAG通过 procfs 中的自定义文件,u-boot 通过 linux 命令行( /proc/cmdline )进行报告,并且每个用户空间应用程序通过进程间通信进行报告。

    总结

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

    如果您有具体的问题或要澄清的要点,我很乐意更新我的答案。

    https://stackoverflow.com/questions/11156272/

    相关文章:

    c# - Visual Studio 2010 构建错误 - 来自 HRESULT : 0x8003

    java - Maven 构建顺序(多个模块)

    image - Docker:构建你自己的镜像问题

    c++ - Visual Studio 2010 - 在不同的构建配置之间保留项目属性?

    maven - 是否有从 Maven 到 Bazel 的迁移路径?

    android - 仅使用 armeabi 构建的应用程序能否在 armeabi-v7a 设备上运行

    c++ - C++ 项目的 cmake vs waf

    build - Xamarin:使用 NDK 构建的 .so

    .net - IoC 容器,在编译时检查错误

    perl - 有没有最简单的方法来构建 perl 包