🔨

Zigの非公式パッケージマネージャー、zigmodとgyroを使ってみる

2023/06/04に公開

先日、Nightlyで導入予定の公式パッケージマネージャーを少しみてみたけれど、Zig v0.11.0-dev自体も含めてまだまだNightlyなので、現状使える非公式なパッケージマネージャーを見ていこうと思う。

現時点で一番使われているのはたぶんzigmodで、次点がgyroという印象。

非公式である以上、Package Index (例えばAquilaなど)に全てのライブラリが登録されていることは望めないわけで、GitHubなどを使えるかどうかがポイントなのだけれど、現在両者ともGit URLの指定に対応している。

詳しい使い方は、zigmodの場合はTutorial、gyroの場合はREADMEが詳しい。

実際の使い方 (コマンド)

では、どういう風に使い方が違うかを、Zigstrライブラリを例にみていこうと思う。(Zig v0.10.1を前提に解説する。)

まず、Zigstrは過去にzigmodに対応していて、Aquilaにも旧バージョンは登録されているので、zigmodの場合は次のコマンドだけでインストールできる。

bash (zigmod)
$ zigmod aq add 1/jecolon/zigstr
$ zigmod fetch

なお注意として、zigmodの最新版だとZigのmasterに追従していてエラーしてしまうので、v0.10.1対応版は以下からダウンロードできる。(exe等の実行可能バイナリなので、ダウンロードしてパスの通ったフォルダにコピーすれば使える。)

https://github.com/nektro/zigmod/releases/tag/r83

また、zigmodでPackage IndexではなくてGitHubのリポジトリを使う場合は、addコマンドは使えず、直接設定ファイルに記述する必要がある。これに関しては後述。

一方gyroの場合は、astrolabe.pmに登録されていれば下記コマンドで実行できるのだけれど、Zigstrは残念ながら登録されていない。

bash (gyro)
$ gyro add jecolon/zigstr # 実際はできない
$ gyro fetch

ではどうするかというと、GitHubに設定ファイルがあればGitHub経由でインストールできるので、仮に自分が設定ファイルをつけた、フォークした版を使って以下のようにインストールできる。

bash (gyro)
$ gyro add --src github funatsufumiya/zigstr
$ gyro fetch

設定ファイルの話はあとからするとして、これを build.zig に反映させるには、まずgyroの場合は以下のようにする。

build.zig (gyro)
const pkgs = @import("deps.zig").pkgs; // この行を追加

pub fn build(b: *std.build.Builder) void {
    // 中略
    const exe = b.addExecutable("gyro-test", "src/main.zig");
    exe.setTarget(target);
    exe.setBuildMode(mode);
    pkgs.addAllTo(exe); // この行を追加
    exe.install();
    // 後略

zigmodの場合もほぼ同じ。

build.zig (zigmod)
const pkgs = @import("deps.zig"); // この行を追加

pub fn build(b: *std.build.Builder) void {
    // 中略
    const exe = b.addExecutable("zigmod-test", "src/main.zig");
    exe.setTarget(target);
    exe.setBuildMode(mode);
    pkgs.addAllTo(exe); // この行を追加
    exe.install();
    // 後略

ちなみにこのbuild.zigの雛形は、zig init-exeを実行すると雛形が作れる。

また、deps.zigというのは、zigmod fetchgyro fetchで自動生成されるので、.gitignoreの対象にしていてOK。

ここまでだと、結構簡単に使えるという印象。

設定ファイルの書き方

では、実際の設定ファイルをどう書けば良いのかについて軽く触れておく。

gyroのZigstr側のgyro.zzz (設定ファイル) はこうなっている。[1]

gyro.zzz
pkgs:
  Zigstr:
    version: 0.0.0
    root: src/Zigstr.zig

deps:
  ziglyph:
    git:
      url: "https://github.com/jecolon/ziglyph.git"
      ref: 1202293092d440ea8d4d2533f11cbb7a52e0078b
      root: src/ziglyph.zig
  cow_list:
    git:
      url: "https://github.com/jecolon/cow_list.git"
      ref: de31646626b059d9ee8a88bee7f6f24163595e59
      root: src/main.zig

refが示しているのはコミットID、rootは呼び出したいファイルで、gyro add --src github jecolon/ziglyph -r src/ziglyph.zig とすれば最新版が自動登録される。ちなみにリポジトリ名とライブラリ名が違う場合は別名にでき、コマンドでは例えば gyro add --src github funatsufumiya/zigstr -a Zigstr -r src/Zigstr.zig となる。

zigmodの場合もほぼ同じで、Zigstr側のzigmod.yml (以前はzig.modだったらしい) は以下の通り。

zigmod.yml
id: 45i25coe64lei15gwafrnsmdvawuwomzugfqmfqdjeoz6nds
name: Zigstr
main: src/Zigstr.zig
license: MIT
description: UTF-8 string type
dependencies:
  - src: git https://github.com/jecolon/ziglyph
    name: ziglyph
    version: commit-1202293092d440ea8d4d2533f11cbb7a52e0078b
    main: src/ziglyph.zig
  - src: git https://github.com/jecolon/cow_list
    name: cow_list
    version: commit-de31646626b059d9ee8a88bee7f6f24163595e59
    main: src/main.zig

さっきとの違いは、コミットIDの指定方法と、ファイル自体に識別用のidがあることと、rootがmainになっていることくらい。ちなみにidはzigmod initで自動生成される。

zigmodでGitリポジトリを指定する場合は残念ながらaddコマンドは使えないので、手動で書くことになる。これが辛かったりするっぽいけれど、addコマンドのようなスクリプトを自分で書くことはそんなに難しくはなさそう。[2]

なお、zigmod.ymlzig.modがちゃんと設定されているリポジトリを指すときは- src: git https://github.com/funatsufumiya/zigstrだけでOKで、例えばzigstrを利用するサンプルにおけるzigmod.ymlは以下のように簡単になる。[3]

zigmod.yml
id: o4vu9ogu6bajvm03okdfhqi2nbqdvn69qq89pqq6zxoonjnd
name: zigmod-test
license: none
description: none
root_dependencies:
  - src: git https://github.com/funatsufumiya/zigstr

gyroでは同様の設定ファイルを前述のaddコマンド(gyro add --src github funatsufumiya/zigstr)だけで生成できて便利なのだけれど、あえてgyro.zzzを手で書くなら以下の通り。

gyro.zzz
deps:
  Zigstr:
    git:
      url: "https://github.com/funatsufumiya/zigstr.git"
      ref: 8aacd78885fc53f1c3b4d4c1b6af094c64c368be
      root: src/Zigstr.zig

こう見ていくと、zigmodとgyroの違いはGitHubリポジトリの扱いくらいのように思えるけれど、実はzigmodの方はC言語の依存関係を適切に設定ファイルに書くことができ、それらもzigmod fetchでビルドスクリプトの自動生成に対応しているため、その点が人気がある様子。今回は割愛するけれど、たぶんこうした機能は今後公式パッケージマネージャーにも取り入れられていくと思う。

まとめ

zigmodとgyroは、どちらもパッケージマネージャーとしては似たような手順で使えるということがわかった。両者はとても良く似ているので、今回あえて2つまとめて紹介した。

zigmodはgyroに比べるとaddコマンドの対応が限定的で、一方でzigmodの方が現状ではC言語関係の対応に強いので、その点で好みが分かれそう。

ただ、繰り返しになるけれどサードパーティ製なので、Package Indexに登録されているかどうかや、そもそも設定ファイルをライブラリごとに書いてもらえるかが微妙で、多くを自分自身で書くことになると思うと、ちょっと面倒かもしれない。(一応パターンがあるのでチートシートとかを準備しておくと便利そう。)

なので、個人的には公式パッケージマネージャーの登場を待つのが良いかなと思っているのだけれど、Zig v0.11.0では多くの破壊的変更が予定されているので、どれくらいの数のライブラリが対応するかは不明。Zigではまだまだ破壊的変更が多いので、様子見するライブラリ開発者もいそうだし、公式パッケージマネージャーが完成に至るにはv0.13.0まで待つことになると思うと先が長い。

したがって、公式パッケージマネージャーが出るまでにどうするかは悩みどころで、Zigstrのように、過去はzigmodに対応していたけれどgit submoduleでの管理に切り替えたりなど、開発者によって対応が分かれてくることと思われる。

ちなみに、zigmodもgyroもZig自体のバージョンの違いは吸収しきれないので、公式パッケージマネージャーが出たとしてもバージョン問題は出るはず[4]。Zigはどんどん破壊的変更がなされるので、バージョン1に達して長期サポート版が出るまでは、公式版があっても手放しに安心はできないかも。

脚注
  1. 自作した設定ファイルで、Zigstr公式のものではない。以降も同様。 ↩︎

  2. 個人的にはJavaのMavenやGradleを思い出す。ライブラリをネットで検索すると、いろんなビルドツール用の設定がサイトに記載されている。 (Spring Bootの例: https://mvnrepository.com/artifact/org.springframework.boot/spring-boot/2.5.2) ↩︎

  3. dependenciesとroot_dependenciesの違いは、ライブラリ開発用かアプリケーション開発用かの違い。 ↩︎

  4. zigのバージョン切り替えは、zvmなどが使えるけれど、公式パッケージマネージャーがまだないのでpythonのvenvやcondaのような便利さはまだない。 ↩︎

Discussion