LoginSignup
1
0

[zig] ビルドスクリプト内でパッケージのモジュールを直接使用する方法

Last updated at Posted at 2023-12-07

はじめに

zig バージョン0.11系でパッケージ管理がサポートされ、外部依存のモジュールをカジュアルに扱えるようになった。
しかし、0.11.0のリリースノート (https://ziglang.org/download/0.11.0/release-notes.html#Package-Management) を見ても、実行バイナリに対してパッケージを適用する方法しか書かれてなく、ビルドスクリプト内からパッケージのモジュールを直接使用する方法は明記されていない。

NodeJSnpmにおけるdev dependencyを思い浮かべていただくと理解しやすいかも。

ビルドスクリプト内で、パッケージとして公開された機能を使用する方法1 が見つかったため記録として残す。

方法

2023-11-2時点のnightly buildで確認しているため、安定版の0.11.xでは動かないかもしれない。

方法は、いったって簡単で、build.zigbuild関数内でbuild.zig.zonで指定した依存パッケージをインポートするだけ。
対象バッケージのbuild.zigがインポートされる。

build.zigで型やメソッドを公開(pub const〜pub fn〜を記述)すれば、呼び出し元で使用できるようになる。

例えばbuild.zig.zonfooと名付けたパッケージを依存として追加した場合

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の指定も不要)。

  1. 経緯は、mitchellh/zig-objcのレポジトリで使ってて、ナンジャラホイかと調べてみた

1
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0