評価14: ビルドシステム - 評価基準

評価の目的

この評価では、Zigのビルドシステム(build.zig)の理解と活用能力を確認します。実行ファイル、ライブラリのビルド、テスト実行、カスタムビルドオプション、マルチターゲットビルドなど、実践的なビルド設定スキルを評価します。

学習目標

この評価を通じて、以下の能力を確認します:

  • build.zigの基本構造と機能の理解
  • ライブラリと実行ファイルのビルド設定
  • カスタムビルドオプションの追加
  • クロスコンパイルとマルチターゲットビルド
  • カスタムビルドステップの実装

評価項目

1. 基本的なbuild.zigの作成(20点)

項目 配点 評価基準
静的ライブラリのビルド 5点 addStaticLibrary で正しくライブラリを生成
実行ファイルのビルド 5点 addExecutable とライブラリのリンクが適切
実行ステップの追加 5点 run ステップが正しく動作
テストステップの追加 5点 test ステップでテストが実行される

確認ポイント:

  • [ ] zig build でライブラリと実行ファイルが生成される
  • [ ] zig build run で実行ファイルが実行される
  • [ ] zig build test でテストが実行される
  • [ ] すべてのパスが正しく設定されている

良いbuild.zig例:

pub fn build(b: *std.Build) void {
    const target = b.standardTargetOptions(.{});
    const optimize = b.standardOptimizeOption(.{});

    // ライブラリのビルド
    const lib = b.addStaticLibrary(.{
        .name = "mathlib",
        .root_source_file = b.path("src/lib.zig"),
        .target = target,
        .optimize = optimize,
    });
    b.installArtifact(lib);

    // 実行ファイルのビルド
    const exe = b.addExecutable(.{
        .name = "calculator",
        .root_source_file = b.path("src/main.zig"),
        .target = target,
        .optimize = optimize,
    });
    exe.linkLibrary(lib);  // ライブラリをリンク
    b.installArtifact(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 calculator");
    run_step.dependOn(&run_cmd.step);

    // テストステップ
    const lib_tests = b.addTest(.{
        .root_source_file = b.path("tests/lib_test.zig"),
        .target = target,
        .optimize = optimize,
    });

    const run_tests = b.addRunArtifact(lib_tests);
    const test_step = b.step("test", "Run library tests");
    test_step.dependOn(&run_tests.step);
}

2. カスタムビルドオプション(20点)

項目 配点 評価基準
bool オプションの追加 5点 enable-logging などのフラグが機能
enum オプションの追加 5点 log-level などの列挙型オプションが機能
文字列オプションの追加 5点 app-name、version が正しく渡される
オプションのコード利用 5点 @import("config") でアクセス可能

確認ポイント:

  • [ ] b.option でオプションを定義
  • [ ] addOptions でモジュールを作成
  • [ ] コマンドラインから -D でオプション指定可能
  • [ ] デフォルト値が適切に設定されている

オプション設定の例:

pub fn build(b: *std.Build) void {
    const target = b.standardTargetOptions(.{});
    const optimize = b.standardOptimizeOption(.{});

    // カスタムビルドオプション
    const enable_logging = b.option(
        bool,
        "enable-logging",
        "Enable logging"
    ) orelse false;

    const log_level = b.option(
        enum { Debug, Info, Warning, Error },
        "log-level",
        "Log level"
    ) orelse .Info;

    const app_name = b.option(
        []const u8,
        "app-name",
        "Application name"
    ) orelse "MyApp";

    const exe = b.addExecutable(.{
        .name = "myapp",
        .root_source_file = b.path("src/main.zig"),
        .target = target,
        .optimize = optimize,
    });

    // ビルドオプションをコードに渡す
    const options = b.addOptions();
    options.addOption(bool, "enable_logging", enable_logging);
    options.addOption(@TypeOf(log_level), "log_level", log_level);
    options.addOption([]const u8, "app_name", app_name);

    exe.root_module.addOptions("config", options);

    b.installArtifact(exe);
}

// コードでの使用
// const config = @import("config");
// if (config.enable_logging) { ... }

3. マルチターゲットビルド(20点)

項目 配点 評価基準
複数ターゲットの定義 6点 Linux、Windows、macOS向けにビルド設定
ターゲット別ディレクトリ 6点 各ターゲットが別ディレクトリに出力
build-allステップ 4点 すべてのターゲットを一度にビルド
クロスコンパイル 4点 異なるアーキテクチャ向けにビルド可能

確認ポイント:

  • [ ] resolveTargetQuery で各ターゲットを解決
  • [ ] ターゲット別のインストール先が設定されている
  • [ ] zig build build-all ですべてビルド
  • [ ] WebAssembly などの特殊ターゲットも含む

マルチターゲットビルド例:

pub fn build(b: *std.Build) void {
    const optimize = b.standardOptimizeOption(.{});

    // 複数ターゲット
    const targets = [_]std.Target.Query{
        .{ .cpu_arch = .x86_64, .os_tag = .linux },
        .{ .cpu_arch = .x86_64, .os_tag = .windows },
        .{ .cpu_arch = .aarch64, .os_tag = .macos },
        .{ .cpu_arch = .wasm32, .os_tag = .freestanding },
    };

    const build_all_step = b.step("build-all", "Build for all targets");

    for (targets) |target_query| {
        const resolved_target = b.resolveTargetQuery(target_query);

        const exe = b.addExecutable(.{
            .name = "multiplatform",
            .root_source_file = b.path("src/main.zig"),
            .target = resolved_target,
            .optimize = optimize,
        });

        // ターゲット別ディレクトリにインストール
        const target_triple = try resolved_target.result.zigTriple(b.allocator);

        const install = b.addInstallArtifact(exe, .{
            .dest_dir = .{
                .override = .{
                    .custom = target_triple,
                },
            },
        });

        build_all_step.dependOn(&install.step);
    }
}

4. カスタムビルドステップ(20点)

項目 配点 評価基準
ファイル生成ステップ 6点 addWriteFiles でバージョンファイルなどを生成
フォーマットステップ 6点 addFmt でコード整形
クリーンステップ 4点 addRemoveDirTree でビルド成果物を削除
ステップ依存関係 4点 step.dependOn で正しく依存関係を設定

確認ポイント:

  • [ ] カスタムステップが正しく動作
  • [ ] 依存関係が適切に設定されている
  • [ ] zig build で実行可能
  • [ ] ステップの説明が適切

カスタムステップの例:

pub fn build(b: *std.Build) void {
    const target = b.standardTargetOptions(.{});
    const optimize = b.standardOptimizeOption(.{});

    // バージョンファイルを生成
    const version_step = b.addWriteFiles();
    const version_content = b.fmt("1.0.0-{}", .{std.time.timestamp()});
    const version_file = version_step.add("version.txt", version_content);

    // 設定ファイルを生成
    const config_step = b.addWriteFiles();
    const config_content =
        \\{
        \\  "name": "MyApp",
        \\  "debug": true
        \\}
    ;
    const config_file = config_step.add("config.json", config_content);

    const exe = b.addExecutable(.{
        .name = "myapp",
        .root_source_file = b.path("src/main.zig"),
        .target = target,
        .optimize = optimize,
    });

    // ビルド前にファイル生成
    exe.step.dependOn(&version_step.step);
    exe.step.dependOn(&config_step.step);

    b.installArtifact(exe);
    b.installFile(version_file, "version.txt");
    b.installFile(config_file, "config.json");

    // フォーマットステップ
    const fmt_step = b.addFmt(.{
        .paths = &[_][]const u8{ "src", "build.zig" },
        .check = false,
    });

    const fmt_cmd = b.step("fmt", "Format source code");
    fmt_cmd.dependOn(&fmt_step.step);

    // クリーンステップ
    const clean_step = b.step("clean", "Remove build artifacts");
    const rm_cmd = b.addRemoveDirTree(b.install_path);
    clean_step.dependOn(&rm_cmd.step);
}

5. ボーナス課題(20点)

項目 配点 評価基準
パッケージシステム 10点 addModule で複数モジュールを管理
完全なテンプレート 10点 実用的なビルド設定一式

ボーナス評価ポイント:

  • [ ] モジュールの依存関係が適切
  • [ ] ドキュメント生成機能がある
  • [ ] ベンチマーク実行ステップがある
  • [ ] 再利用可能な構造になっている

チェックリスト

ビルド設定前の確認

  • [ ] プロジェクト構造を理解している
  • [ ] 必要なビルド成果物を特定している
  • [ ] ターゲットプラットフォームを決定している
  • [ ] 依存関係を洗い出している

ビルド実行の確認

  • [ ] zig build でエラーなくビルド
  • [ ] zig build run で実行ファイルが動作
  • [ ] zig build test でテストが通る
  • [ ] カスタムステップが正しく動作

ビルドスクリプトの品質確認

  • [ ] コードが読みやすい
  • [ ] ステップの説明が適切
  • [ ] エラーメッセージが分かりやすい
  • [ ] 拡張性がある
  • 合格基準

    レベル 点数 説明
    優秀 90-100 すべての機能を完璧に実装、ボーナス課題も完了
    良好 80-89 マンダトリー課題を完全実装、ボーナス課題の一部完了
    合格 64-79 マンダトリー課題の80%以上を正しく実装
    要再提出 0-63 ビルドが失敗または機能が不十分

    最低合格ライン: 64点以上(マンダトリー80点満点の80%)

    よくある減点ポイント

    1. パス指定の誤り(-5〜10点)

    // NG: 古いAPI(0.11以前)
    .root_source_file = .{ .path = "src/main.zig" }
    
    // OK: 新しいAPI(0.12以降)
    .root_source_file = b.path("src/main.zig")
    

    2. 依存関係の設定ミス(-5点)

    // NG: 依存関係がない
    const run_step = b.step("run", "Run the app");
    run_step.dependOn(&run_cmd.step);
    // installステップへの依存が抜けている
    
    // OK: 正しい依存関係
    const run_cmd = b.addRunArtifact(exe);
    run_cmd.step.dependOn(b.getInstallStep());  // 必須
    
    const run_step = b.step("run", "Run the app");
    run_step.dependOn(&run_cmd.step);
    

    3. ターゲット解決の誤り(-5点)

    // NG: 古い方法
    const target = std.zig.CrossTarget{
        .cpu_arch = .x86_64,
        .os_tag = .linux,
    };
    
    // OK: 新しい方法
    const target_query = std.Target.Query{
        .cpu_arch = .x86_64,
        .os_tag = .linux,
    };
    const resolved_target = b.resolveTargetQuery(target_query);
    

    学習の手引き

    ビルドシステムの基礎

  • build.zigの基本構造
- build関数の理解 - std.Buildの機能 - アーティファクトの種類

  • ステップシステム
- ステップの作成と登録 - 依存関係の設定 - カスタムステップの実装

  • クロスコンパイル
- ターゲットの指定方法 - プラットフォーム固有の設定 - 成果物の管理

効果的な学習方法

  • シンプルから始める
- 最小限のbuild.zig - 徐々に機能を追加

  • 公式例を参考にする
- Zig標準ライブラリのbuild.zig - 公式サンプルプロジェクト

  • 実践的な応用
- 実際のプロジェクトで試す - 複雑な構成に挑戦

ピアレビューのポイント

評価者は以下の点を確認してください:

1. ビルド実行

# 基本ビルド
cd part1
zig build
zig build run
zig build test

# カスタムオプション
cd part2
zig build run -Denable-logging=true -Dlog-level=Debug

# マルチターゲット
cd part3
zig build build-all
ls zig-out/

# カスタムステップ
cd part4
zig build fmt
zig build clean

2. コード確認

  • ビルドスクリプトの完全性
  • オプションの設定と使用
  • ターゲット設定の正確性
  • カスタムステップの実装

3. 理解度の確認

質問例:
  • 「このステップの依存関係は何ですか?」
  • 「クロスコンパイルの仕組みを説明してください」
  • 「カスタムオプションはどう使われますか?」
  • フィードバックの例

    良いフィードバック

    > 「build.zigの実装が非常に良く設計されています。基本的なライブラリと実行ファイルのビルドが正しく設定され、テストステップも適切に実装されています。カスタムビルドオプションの使用も適切で、コマンドラインから柔軟に設定を変更できます。マルチターゲットビルドでは、各プラットフォーム向けに正しくビルドされ、成果物も整理されています。カスタムステップも実用的で、フォーマットやクリーンが正しく動作します。」

    改善が必要な場合のフィードバック

    > 「基本的なビルド設定は良いですが、実行ステップでgetInstallStepへの依存が抜けているため、zig build runが失敗する可能性があります。また、マルチターゲットビルドでresolveTargetQueryの使い方が古いAPIになっています。最新のAPIに更新してください。カスタムビルドオプションは動作していますが、デフォルト値の設定が不適切です。」

    参考資料

  • Zig Language Reference - Build System: https://ziglang.org/documentation/master/#Build-System
  • Zig Build System: https://ziglang.org/learn/build-system/
  • Ziglearn - Build System: https://ziglearn.org/chapter-3/
  • Official Examples: https://github.com/ziglang/zig/tree/master/lib/std/Build

まとめ

Zigのビルドシステムは、シンプルでありながら強力です。この評価を通じて、基本的なビルド設定からクロスコンパイル、カスタムステップまで、実践的なビルドスクリプト作成スキルを習得しました。これらの知識は、実際のプロジェクト開発において、効率的なビルド環境の構築に不可欠です。