我是从事embedded式Linux项目的一个小团队(4-5)的一员。 我们正在使用Buildroot和Linaro工具链来构build我们的目标。 我们使用git进行版本控制,并使用Jenkins进行夜间编译。
这是我们第一次参与这样的项目,而且在这种环境下,我找不到任何描述开发模型的资源。
现在,在每晚构build之后,我创build一个Buildroot“输出”目录的tarball,其中包含u-boot映像和根文件系统。 这可以直接从Jenkins'档案'页面下载最后的成功构build。
我们中的一些人将在较低层次的开发和一些用户空间开发(QT)上工作。 我们的问题是决定在这样的环境中,最有效率/简化的方法是什么,因为人们将在项目范围内的不同领域工作。 用户们可以下载tarball的一切,并将其应用程序纳入到rfs中以在板上运行和debugging,但是我们应该如何处理在底层开发中所做的工作呢? 基本上,我们应该如何将文物分发给团队? 我非常感谢任何想法。
我最近花了一些时间重构基于OpenEmbedded的linux项目的构建环境。 我没有与Buildroot的直接经验,但我期望OpenEmbedded足够类似于你正在使用的。 我会描述我的设置,如果有幸运的话,你会在这里找到有用的东西。
有三个软件组件可以分开安装(即彼此独立):bootloader(u-boot); 内核(linux); 和文件系统映像。 我们的最终产品随附了这三个组件的打包版本。 也就是说,u-boot,linux和文件系统映像的版本已经过QA测试,并且已知可以一起工作。 但是,可以独立升级任何一个组件(例如,安装新的内核映像),以创建尚未一起测试的软件组件的组合。
用户空间应用程序也存在此问题。 一旦将文件系统映像安装到目标中,就可以独立于其他文件系统对象更新一个或多个用户空间二进制文件(假定您的文件系统不是只读的)。 您如何知道现在安装的用户空间应用程序的特定组合可以一起工作? 我怎么能确定运行在这个特定单元中的二进制文件的组合是经过QA认证的二进制文件的组合? 我如何知道软件的“版本”?
我需要解决的另一个问题是,如何让软件堆栈(内核,根文件系统,用户空间Qt应用等)的不同部分的开发人员一起工作?
我通过以下方式解决了这个问题和“版本”问题:
将目标的根文件系统和系统根文件存储在一个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 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过程导出到一个描述当前软件版本的环境变量(例如VER_TAG
)。 该版本是来自git仓库或SHA的标签(例如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?
如果任何项目子目录中的单个文件都被修改了,那么VER_TAG
将始终被xxxx-modified
。 然后这个单一的VER_TAG
变量作为编译VER_TAG
量传递给所有的构建(u-boot,内核,用户空间应用程序等)。
在运行时,自定义用户空间应用程序将累积所有组件的VER_TAG
值,如果它们都报告相同的值,则该字符串将成为产品报告的正式版本。 如果只有一个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报告,并通过进程间通信报告每个用户空间应用程序。
一个警告。 我只在一个月前开发了这个构建环境,所以不能为它的健壮性提出要求,但现在它似乎在一起…
如果你有特定的问题或要澄清的问题,我会很乐意更新我的答案。