はじめての自作レシピ: ライブラリにないプログラムを QTS パッケージに
App Builder のレシピライブラリは数多くのプログラムをビルドします。使いたいプログラムがその中にない場合は、プロジェクトに独自のレシピを持たせることができます。ライブラリと同じ形式で、プロジェクトの recipes/ フォルダーに置く 2 つのファイルです。このガイドでは、ライブラリの ncurses を必要とする小さなターミナルプログラム cmatrix 2.0 を、x86_64 と ARM 64 ビットの NAS 向けの QTS パッケージにします。
- プロジェクトソースからのパッケージ
- レシピrecipe.json、build.sh
- 検査エディターでの lint
- ビルドアプリ 2 つ、プロセッサー 2 種類
- パッケージmake qpkg
画像は Bucket & Code Server IDE のパネルとエディターのもので、各ステップをこのガイドの説明どおりに行っています。データフォルダーは /share/ZFS530_DATA/BucketVS です。
01プロジェクトを作る
プロジェクト ページでは、新しいプロジェクト を押すと、最初にテンプレートを選ぶよう求められます。ソースからのパッケージ を選びます。自作のレシピでソースからコンパイルするプログラムを収めた、x86_64 と arm64 向けの QTS パッケージです。
名前は cmatrix にします。プロジェクトの名前はパッケージの名前になり、それを小文字にしてレシピ名に使えない文字を除いたものが、スターターレシピと 2 つのアプリの名前になります。サービス のステップでは、パッケージが動作中に何をするかを決めます。ステップを開いたときに選ばれている コマンドラインツール は、パッケージが起動している間、パッケージの bin/cmatrix を /usr/bin にリンクします。作成後、プロジェクトのフォルダーには次のものがあります:
| パス | 内容 |
|---|---|
recipes/<name>/ | スターターレシピ: recipe.json と build.sh |
recipes.txt | 2 つのアプリがビルドするレシピ (1 行に 1 つの名前): このプロジェクトのレシピとライブラリのレシピ |
Makefile | make app、make build、make lint、make qpkg |
licenses.txt | パッケージに含まれるライセンス (1 レシピにつき 1 行) |
qpkg/ | パッケージ: qpkg.cfg と、サービス のステップで作られた起動・停止スクリプト |
Makefile は 2 つのアプリをビルドします。この NAS のプロセッサー向けの <name> と、ARM 64 ビットの NAS 向けの <name>-arm64 で、後者は x86_64 の NAS ではクロスビルドになります。どちらも Ubuntu 24.04 builder でビルドし、静的にリンクします。その環境がない場合は、ツールチェーンページの この環境を作成 で作成します。このテンプレートでは 作成後すぐにビルド はオフです。スターターレシピは仮のソースを指定していて、その sha256 は 64 個のゼロです。そのため、レシピに自分のプログラムを指定するまで、ビルドは失敗します。
02スターターレシピ
プロジェクトビューの エディターで開く を押すと、プロジェクトのフォルダーがエディターで開きます。recipe.json は何をビルドするかを、build.sh はどうビルドするかを記述します。
| フィールド | 記述する内容 |
|---|---|
name、version | レシピの名前 (フォルダーの名前) とプログラムのバージョン |
summary、category、license、homepage | パネルに表示される、そのレシピの情報 |
source | ソースアーカイブのアドレスとその sha256。一致しないダウンロードは拒否されます |
deps | 先に必要なレシピ。ライブラリのものか、このプロジェクトのもの |
env_packages | ビルダー環境がこのレシピのためにインストールするビルドツール (ライブラリは含めません) |
static、nss | 静的にリンクするかどうか、ユーザーやホスト名を参照するかどうか |
check | 完成したプレフィックスで実行し、プログラムが動作することを確かめるコマンド |
build.sh は 3 つのフェーズを定義し、それぞれ展開したソースの中で実行されます。スターターのフェーズは CMake 用で、コメントがそれぞれの autoconf と Meson での書き方を示します:
do_configure() {
# an autoconf source: configure_std; meson: meson_std. In a static app CMake ends the link line with -Wl,-Bdynamic
# after a library it found as a file (lib<name>.a), and the link then asks for a shared libc;
# CMAKE_LINK_SEARCH_END_STATIC keeps the line static to its end (D312)
if [ "$STATIC" = 1 ]; then cmake_std -DCMAKE_LINK_SEARCH_END_STATIC=ON; else cmake_std; fi
}
do_build() {
cmake --build _build -j"$JOBS" # autoconf: make_j; meson: meson compile -C _build
}
do_install() {
cmake --install _build # autoconf: make install; meson: meson install -C _build
}
cmake_std、configure_std、meson_std は、アプリのプレフィックス、リンクモード、ARM のアプリではクロスターゲットを渡すため、同じファイルで両方のアプリに対応できます。
03自分のプログラムのソース
リリースアーカイブのアドレスを取得し、エディターのターミナルでその sha256 を計算します:
curl -fsSL https://github.com/abishekvashok/cmatrix/archive/refs/tags/v2.0.tar.gz | sha256sum
ad93ba39acd383696ab6a9ebbed1259ecf2d3cf9f49d6b97038c66f80749e99a -
cmatrix は CMake でビルドし、ライブラリにある ncurses で描画します。cmatrix の CMake スクリプトは、ncurses をファイル libncurses.a として見つけます。静的なアプリでは、CMake はリンク行のその後ろに -Wl,-Bdynamic を付けて行を終えるため、そのままではリンクが共有の libc を求めて止まります。スターターの do_configure はリンク行を最後まで静的に保つので、build.sh は変更不要です:
do_configure() {
if [ "$STATIC" = 1 ]; then cmake_std -DCMAKE_LINK_SEARCH_END_STATIC=ON; else cmake_std; fi
}
recipe.json では、チェックを bin/cmatrix -V にします。cmatrix 2.0 のバージョンを表示するオプションです (--version にはヘルプテキストで応答します):
{
"name": "cmatrix",
"version": "2.0",
"summary": "cmatrix: the falling characters of The Matrix in a terminal",
"category": "tool",
"license": "GPL-3.0-or-later",
"homepage": "https://github.com/abishekvashok/cmatrix",
"source": {
"url": "https://github.com/abishekvashok/cmatrix/archive/refs/tags/v2.0.tar.gz",
"sha256": "ad93ba39acd383696ab6a9ebbed1259ecf2d3cf9f49d6b97038c66f80749e99a"
},
"deps": ["ncurses"],
"env_packages": [],
"static": true,
"nss": false,
"check": "bin/cmatrix -V"
}
- レシピのフォルダーに置けるのは、
recipe.json、build.sh、recipe.jsonが指定できるベンダーファイルだけです。パッチはヒアドキュメントとしてbuild.shに入れます。 recipes.txtにはすでにスターターレシピの名前があります。このレシピが依存するライブラリのレシピは、必要な順序でビルドに加わります。
04検査する
レシピのファイルを保存するたびにプロジェクトのレシピが検査され、検出結果がファイルと行ごとに 問題 ビューに一覧表示されます。検査は recipe.json を読み、build.sh を bash -n で構文解析します。レシピを実行することはありません。スターターの 64 個のゼロもそうした検出結果の 1 つで、本当のチェックサムが入るまで sha256 の行に警告が出ます。
同じ検査をターミナルや CI ジョブでも実行できます:
make lint # bvs recipe lint . (the project folder) bvs recipe lint --json . # the findings as JSON, for a CI step
プロジェクトビューの レシピ カードは、プロジェクトのレシピをアプリが使うとおりに一覧表示し、それぞれに検査の結果と検出内容を添えます。行をクリックするとレシピのフォルダーがエディターで開き、行のメニューから検査のコマンドをコピーできます。
052 つのアプリをビルドする
プロジェクトビューの ビルド は、プロジェクトの Makefile を実行します。2 つのアプリがなければ作成し、1 つずつ順にビルドします。アプリ ページにある各アプリのページには、レシピの取得元のプロジェクトが表示され、ビルドのログには、各レシピがビルドの順に ncurses から並びます。
- ビルドはプロジェクトのレシピを開始時に 1 回だけ読みます。その後に保存したファイルは、次のビルドまで反映されません。
- ライブラリのレシピと同じ名前のプロジェクトのレシピは、このプロジェクトのアプリの中でだけそのレシピを置き換え、ビルドのログにもそのことが出ます。
- 最後のレシピの後、完成したプレフィックスに対して各レシピのチェックがもう一度実行されます。このレシピでは
bin/cmatrix -Vです。x86_64 の NAS では ARM のアプリはクロスビルドで、そのチェックは qemu-user が登録されている環境でのみ実行されます。登録されていなければ、ビルドはチェックを未実行として記録します。
06パッケージにしてインストールする
licenses.txt は、パッケージの share/licenses/ に入るものを指定します。パッケージに含まれるレシピごとに 1 行で、そのライセンスと、ソースアーカイブ内のライセンスファイルを書きます。スターターの行には仮の値が入っています。cmatrix には ncurses がリンクされるため、2 行必要です:
cmatrix GPL-3.0-or-later COPYING ncurses X11 COPYING
エディターのターミナルで make qpkg を実行すると、ツールチェーンページの QDK を使って、各アプリの成功した最新のビルドを、アーキテクチャーごとに 1 つのファイルとしてパッケージにします。成功したビルドがないアプリは含めません。動的にリンクしたアプリは拒否されます。そのプログラムはアプリのプレフィックスでライブラリを探しますが、パッケージはそのプレフィックスを作らないためです。
make qpkg
パッケージは build/qpkg/build/ にでき、qpkg.cfg の QPKG_NAME と QPKG_VER から cmatrix_0.1.0_x86_64.qpkg、cmatrix_0.1.0_arm_64.qpkg と名付けられます。それぞれにアプリの bin/、sbin/、share/ (man、doc、info を除く)、etc/ が入ります。ここでは cmatrix と、ncurses がそこにインストールしたもの、つまりそのツールと端末データベースです。代わりにパッケージに含めるパスは、scripts/make-qpkg.sh の先頭の KEEP で指定します。例えば bin/cmatrix share/terminfo です。
コード署名用のファイルを qpkg/ の qpkg.cfg の隣、または QPKG_CERT_DIR が指すフォルダーに置くと、パッケージは署名され、プロジェクトビューの テストデプロイ (管理者用) でこの NAS にインストールできます。署名と公開については 独自の App Center で詳しく説明しています。ゼロから作る Transmission では、5 つのレシピを持つ「ソースからのパッケージ」のプロジェクトを最初から最後までたどります。何も設定していない NAS から始めて、署名済みのパッケージをインストールし、ブラウザーで応答するところまで進めます。
072 つ目のレシピ
Bucket: New recipe は、同じスターターからレシピを追加します。プロジェクトのファイルを開いた状態で コマンド パレット (Ctrl+Shift+P) から実行するか、エクスプローラーで recipes フォルダーまたはレシピのフォルダーを右クリックします。コマンドは名前 (小文字、数字、+ . _ -) を尋ね、recipe.json と build.sh を書き出し、recipe.json を開いて、プロジェクトを検査します。
- これから作るアプリのために、新しい名前を
recipes.txtに書き加えます。以前に作ったアプリは元の一覧のままです。そのアプリのページの 変更 でレシピを追加します。 - ビルドに npm、Go、Cargo のパッケージが必要なレシピは、それらをベンダーファイルに列挙します。この一覧は
/usr/bin/bucketvs/share/bucketvs/tools/のnpm-vendor.py、go-vendor.py、cargo-vendor.pyが書き出します。これらにはツールチェーンページの Python ランタイムが必要です。 - プロジェクトのレシピは、ライブラリのレシピと同じくビルダー環境の中で root として実行され、developer なら誰でも書いてビルドできます。viewer はアプリのビルドログでレシピの名前を見られますが、レシピのファイルは見られません。
- プロジェクトのレシピはそのプロジェクトの中にとどまります。レシピライブラリと、すべての NAS が受け取る署名付きカタログに入るのは、Bucket & Code Server IDE 自体へのレビュー済みの変更を通した場合だけです。