zigのコメント機能とドキュメント生成機能を理解し最大限活用する

zig

環境

当方の環境は以下である。
zig version: 0.16.0
Windows 11 + x86_64 + wsl2 + ubuntu24.04 + zsh

三種類のコメントとドキュメント

zigには以下のように三種類のコメントがある。コメントは全て開始地点から行末まで有効になる。囲うことで行の中間部分のみであったり改行を跨いだコメントを可能とする機能は無い。当方の好みである。

  • Comments
    //から始まる
  • Doc Comments
    ///から始まる、ドキュメントとして生成される
  • Top-Level Doc Comments
    //!から始まる、ドキュメントとして生成される

折角なので、今回はコメントにて説明を全て記載したにゅんちゅ。

zig: main.zig

//!これは//!から始まるTop-Level Doc Commentsです。
//!`zig build-exe -femit-docs main.zig`でドキュメントが生成されます。
//!ここにはモジュールについての説明を記載します。
//!尚、ビルド時に最初に呼ばれるモジュールをルートモジュールと呼びます。
//!Top-Level Doc Commentsはコンテナの如何なる式よりも先頭に記載する必要があります。
//!zigでは変数や関数の宣言を保持し名前空間として機能する構造をコンテナと呼びます。
//!ソースファイル自体やstruct、enum、union、opaqueが該当します。
//!
//!これは標準出力と標準エラー出力について確認するためのプログラムです。
//!出力処理はoutput.zigのAPIを使用します。

const std = @import("std");
const output = @import("output.zig");
//これは//から始まるただのCommentsです。
//ドキュメントとしては生成されません。
//コメントを開始した場所から行末まで有効になります。
//
//最初に定数(const)として何が定義されているか確認できた方が読み易い気もするが、
//pub(public: 公開)を付けてmainのNamespacesやFunctionsとしてドキュメントに表示させるのは以下の理由で不適切である。
//・APIの再公開はしない、各コンテナで依存関係を明示させる。
//・std(標準ライブラリ)のモジュールや関数について、既存のものか自身で作成したものか一目で分からなくなる。
//一方、ライブラリのルートモジュールであれば各モジュール等を公開するのは適切である。
//尚、namespaceに関しては///のコメントは表示されない。

///これは///から始まるDoc Commentsです。
///zig build-exe -femit-docs main.zigでドキュメントが生成されます。
///ドキュメント生成の対象はpubによりコンテナ外へ公開(public)される名前空間や関数などに限ります。
///Doc Commentsは式の途中には記載できず、別種類のコメントが後に続くこともできません。
pub fn main(init: std.process.Init) !void { //エラーのみ返す場合はvoidではなく!void
    try output.stdout_test(init); //標準出力
    try output.stderr_test(init); //標準エラー出力
    output.debug_test(); //デバッグ用標準エラー出力
}

zig: output.zig

//!標準出力と標準エラー出力について確認するためのモジュールです。
const std = @import("std");
const print = std.debug.print; //処理全体をmutexで排他することで複数スレッドから呼び出されたときにログが混ざるのを防ぐ
//printが何なのか分かりにくくなる懸念はあるが、公式ドキュメント内で使用されていた方法なので暗黙の了解であると認識した。

///標準出力を確認するための関数です。
pub fn stdout_test(init: std.process.Init) !void {
    try std.Io.File.stdout().writeStreamingAll(init.io, "hello, stdout\n"); //フォーマット機能無し
}

///標準エラー出力を確認するための関数です。
pub fn stderr_test(init: std.process.Init) !void {
    try std.Io.File.stderr().writeStreamingAll(init.io, "hello, stderr\n"); //フォーマット機能無し
}

///標準エラー出力を確認するための関数です。
pub fn debug_test() void { // エラー考慮不要(try不要)のためvoid
    print("hello, stderr for debug\n", .{}); //フォーマット機能有り、mutex有り
}

ドキュメント生成方法

以下のようにコマンドを実行する。

zsh

% ls -F
main.zig  output.zig
% zig build-exe -femit-docs main.zig
% ls -F
docs/  main*  main.zig  output.zig
% ls -F docs
index.html  main.js  main.wasm*  sources.tar
%

wasmを生成していてなんか嬉しいにゅんちゅ。標準ライブラリstdの公式ドキュメントもこの機能により生成されている。尚、stdに関しては以下のコマンドでローカルにドキュメント用WEBサーバーを立てることができる。中身は公式標準ライブラリドキュメントと同じである。

zsh

% zig std #ポートは毎回自動付与
http://127.0.0.1:xxxxx/

一方、ここで気づくが、-femit-docsでドキュメントを生成してもWEBサーバーは立たない。zigでも立てられると思うが、とりあえず今回は確認したいだけなので、以下のコマンドでpythonにて立てることにした。

zsh

% cd docs
% python -m http.server
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...

ドキュメントを別途一から作る必要が無いなんてテンション上がるにゅんちゅ。標準ライブラリstdの説明から実装まで、プログラムに関係することは全て納まっていて楽しいにゅんちゅ、勉強になるにゅんちゅ。サンプル画像はコチラ

標準出力、標準エラー出力について

今回のプログラムについても一応確認しておく。やっぱり、プログラミングは出力できた方が楽しいにゅんちゅ。zigは初見だと結局どうやって出力すれば良いのか分かりにくいと当方は感じたので、基本的な出力方法について整理した。ソースについては上述のmain.zigoutput.zigを参照して欲しい。

zsh

% ./main
hello, stdout
hello, stderr
hello, stderr for debug
% ./main 2> /dev/null #標準エラー出力を捨てて標準出力のみとする
hello, stdout
% ./main 1> /dev/null #標準出力を捨てて標準エラー出力のみとする
hello, stderr
hello, stderr for debug
%

あるべき姿とか公式な呼び方とか考えてしまって、調べたり挙動確認したりしながら説明を書いていたら時間が掛かってしまった。ただ、その分少しはzigの全体感について理解も深まったと思う。ここから先は実際のプログラミングが主となる勉強に入っていける予定なので、投稿スピードも上げていきたい。どんどん楽しくなっていくにゅんちゅ!