はじめに
zig バージョン0.11系でパッケージ管理がサポートされ、外部依存のモジュールをカジュアルに扱えるようになった。
しかし、0.11.0のリリースノート (https://ziglang.org/download/0.11.0/release-notes.html#Package-Management) を見ても、実行バイナリに対してパッケージを適用する方法しか書かれてなく、ビルドスクリプト内からパッケージのモジュールを直接使用する方法は明記されていない。
NodeJS
のnpm
におけるdev dependency
を思い浮かべていただくと理解しやすいかも。
ビルドスクリプト内で、パッケージとして公開された機能を使用する方法1 が見つかったため記録として残す。
方法
2023-11-2時点のnightly buildで確認しているため、安定版の0.11.xでは動かないかもしれない。
方法は、いったって簡単で、build.zig
のbuild
関数内でbuild.zig.zon
で指定した依存パッケージをインポートするだけ。
対象バッケージのbuild.zig
がインポートされる。
build.zig
で型やメソッドを公開(pub const〜
や pub fn〜
を記述)すれば、呼び出し元で使用できるようになる。
例えばbuild.zig.zon
にfoo
と名付けたパッケージを依存として追加した場合
pub fn build(b: *std.Build) void {
....
const foo = @import("foo");
....
}
具体例
一つのビルド環境で複数の実行バイナリがビルドでき、そのバイナリを選択して実行(再ビルド)できるビルドステップであるzig-example-step
を作成したので、これを用いてより具体的な手順の説明を行う。
zig-example-step
は以下に公開している。
- アプリケーション作成のための環境構築
以下のコマンドを実行する
zig init-exe
- build.zig.zonファイルをフォルダルートに作成する
build.zig.zon
の内容
.{
.name = "sample",
.version = "0.0.0",
.paths = .{ // pathsは0.12系で追加予定。0.11系では不要(なはず
"build.zig",
"build.zig.zon",
"src/",
},
.dependencies = .{
.example_step = "https://github.com/ritalin/zig-example-step/archive/main.tar.gz",
// hash値は2023-12-07時点のもの
.hash = "122062deb341bae70b230bb447bdad522ff2e3538124153bcf72028935d392ef6496"
}
}
作成後のフォルダ構成
/
📁src
🗒️main.zig
🗒️build.zig
🗒️build.zig.zon
- build.zigでパッケージを使用する
build.zig
の内容
const std = @import("std");
pub fn build(b: *std.Build) void {
const optimize = b.standardOptimizeOption(.{});
const exe = b.addExecutable(.{
.name = "sample",
.root_source_file = .{ .path = "src/main.zig" },
.target = target,
.optimize = optimize,
});
// zig buildで一括インポートできるよう以下の行は残す
b.installArtifact(exe);
// ↓↓↓↓以下を追加
// パッケージをインポートする
const example_package = @import("example_step");
// インスタンス化
const example_cmd = example_package.RunExample.create(b);
// exampleとして登録する
example_cmd.addExample(exe, .{});
// ↑↑↑↑追加ここまで
const run_cmd = b.addRunArtifact(exe);
run_cmd.step.dependOn(b.getInstallStep());
if (b.args) |args| {
run_cmd.addArgs(args);
}
const run_step = b.step("run", "Run the app");
run_step.dependOn(&run_cmd.step);
// unit testは変更なしのため省略
}
- 以下のコマンドが実行可能となる
zig example -- sample
パッケージ管理についてのおまけ
zig
言語のバージョン0.12系で、URL
でのアーカイブファイルの指定に加え、以下の指定が追加されている。
- path
-
ローカルファイルに展開されたパッケージを直接使用する。
指定先は、対象パッケージの
build.zig
が存在するフォルダ.dependencies = .{ .path = "/path/to" }
- githubなどからレポジトリを直接参照
-
URLとして、git+httpもしくはgit+httpsでURLを記述する。
.dependencies = .{ .url = "git+https://github.com/ritalin/zig-example-step#HEAD" }
レポジトリを直接参照は一見便利そうに見えるが、レポジトリをクローンしてくるのではなく、レポジトリのファイルをダウンロードしてくれるだけ。
しかも.hash
も適切に指定しなければならない(間違ってたらビルド時に教えてはくれるが)
個人的には別途パッケージをクローンし、親レポジトリでサブモジュールとして追加した上で、.path
でフォルダを指定するのが楽だと思う(.hashの指定も不要)。
-
経緯は、mitchellh/zig-objcのレポジトリで使ってて、ナンジャラホイかと調べてみた ↩