私は最近、OpenEmbedded ベースの Linux プロジェクトのビルド環境の再構築に時間を費やしました。Buildroot を直接使用した経験はありませんが、OpenEmbedded はあなたが使用しているものと十分に似ていると思います。私のセットアップについて説明します。運が良ければ、ここで役立つものを見つけることができます...
問題
個別に (つまり、互いに独立して) インストールできる 3 つのソフトウェア コンポーネントがあります。カーネル (Linux); およびファイルシステム イメージ。最終製品は、これら 3 つのコンポーネントのパッケージ リリースと共に出荷されます。つまり、u-boot、linux、およびファイル システム イメージの QA テスト済みで、連携して動作することがわかっているバージョンです。ただし、いずれかのコンポーネントを個別にアップグレードして (新しいカーネル イメージをインストールするなど)、一緒にテストされていないソフトウェア コンポーネントの組み合わせを作成することは可能です。
この問題は、ユーザー空間アプリケーションにも存在します。ファイルシステム イメージがターゲットにインストールされると、他のファイル システム オブジェクトとは無関係に、1 つまたは複数のユーザー空間バイナリを更新できるようになります (ファイル システムが読み取り専用ではない場合)。現在インストールされているユーザー空間アプリケーションの特定の組み合わせが連携できることをどのように判断しますか? この特定のユニットで実行されているバイナリの組み合わせが、QA 認定済みのバイナリの組み合わせと同じであることをどのように確認できますか? ソフトウェアの「バージョン」を知るにはどうすればよいですか?
私が解決する必要があったもう 1 つの問題は、質問で説明したのと同じ問題ですが、ソフトウェア スタックのさまざまな部分 (カーネル、ルート ファイルシステム、ユーザー空間 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 リポジトリはその親のサブモジュールです。
git submodule init
ビルド環境は、基本的に再帰的なandを実行する最上位の Makefile から初期化されます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.
ソフトウェアのバージョン管理
最上位のメイクファイル ( proj/Makefile
) から、すべてのソフトウェア コンポーネント (カーネル、u-boot、ファイル システム イメージ) をビルドできます。次の git コマンドを使用すると、makefile はすべてのサブ make プロセスにVER_TAG
、現在のソフトウェア バージョンを記述する単一の環境変数 (例: ) をエクスポートします。バージョンは、git リポジトリのタグまたは SHA (例: 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?
プロジェクトのサブディレクトリのいずれかのファイルが 1 つでも変更された場合、VER_TAG
常にxxxx-modified
. この単一のVER_TAG
変数は、コンパイル時の定数としてすべてのビルド (u-boot、カーネル、ユーザー空間アプリなど) に渡されます。
実行時に、カスタム ユーザー空間アプリケーションVER_TAG
はすべてのコンポーネントから値を蓄積し、それらがすべて同じ値を報告する場合、その文字列は製品によって報告される正式なバージョンになります。1 つの値でもVER_TAG
他の値と異なる場合、ソフトウェア スタックは同じトップレベル SHA から構築されておらず、実際にリリースすることはできません (テストのための QA、製造のためのプロダクションなど)。
ソフトウェア コンポーネントが最上位の makefile (例: make --directory proj/fs/apps all
)からビルドされていない場合、VER_TAG
そのコンポーネントの は未定義になり、結果として得られるソフトウェア スタックは「内部使用のみ」になります。つまり、すべてのソフトウェア コンポーネントの「リリース」は、最上位の makefile からビルドすることによってのみ行うことができます。
参考までに、linuxVER_TAG
は procfs のカスタム ファイルを介してレポートし、u-boot は Linux コマンド ラインを介してレポートし ( /proc/cmdline
)、各ユーザー空間アプリケーションはプロセス間通信を介してレポートします。
概要
警告。私はこのビルド環境を 1 か月前に開発したばかりなので、その堅牢性を主張することはできませんが、今のところはうまくいっているようです...
特定の質問や明確にしたい点がある場合は、喜んで回答を更新します。