mcpField
Z
zig-0.16

zig-0.16

github.com/zigcc開発52228 回インストール2 週間前に更新
リポジトリ

zig-0.16 について

zig-0.16は、Zig 0.16.0を使う開発者向けのプログラミングガイドスキルです。言語と標準ライブラリの変更点、移行例、ローカルドキュメントの参照方法をまとめています。

主な機能

  1. 01Zig 0.16.0を対象
  2. 02言語レベルの変更点を整理
  3. 03std.Ioと標準ライブラリAPIの更新を解説
  4. 04旧APIから新APIへの移行例を掲載
  5. 05言語および標準ライブラリのローカル文書参照を案内

活用シーン

  1. 01Zigプロジェクトを0.16.0へ移行
  2. 02標準ライブラリAPIのバージョン差を確認
  3. 03I/O、ネットワーク、ファイル操作のコードを更新
  4. 04Zig 0.16.0のエントリーポイントや環境変数の扱いを確認

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/zigcc/skills --skill zig-0.16

インストール後、Claude Code で/zig-0.16を入力して読み込まれたか確認します。

同梱ファイルscripts/check-zig-version.sh

詳細

Zig 0.16.0 プログラミングガイド

対象バージョン:このスキルは Zig 0.16.0(安定版)に固定されています。 リリースノート:https://ziglang.org/download/0.16.0/release-notes.html

Zig 0.16.0 は、統一 I/O インターフェースとして std.Io を導入し、@Type を削除し、@cImport を非推奨にし、ビルドシステムのパッケージ管理を大幅に再構成するメジャーリリースです。


ローカルドキュメントを最初に確認

zig env を実行してインストールパスを確認してください。パスをハードコードしてはいけません。主なフィールドは .lib_dir、.std_dir、.version です。

  • 言語リファレンス:<lib_dir>/../doc/langref.html
  • 標準ライブラリのソース:API を確認するには、.std_dir 以下のファイルを読んでください。
  • 標準ライブラリのドキュメント:zig std を実行してローカル HTTP サーバーを起動してください。

ウェブ検索の前に、必ずローカルドキュメントを確認してください。


クイックリファレンス:主な破壊的変更

旧(0.15.x)新(0.16.0)
@Type(.Int(...))@Int(.signed, bits)
@Type(.Struct(...))@Struct(layout, BackingInt, field_names, field_types, field_defaults, field_is_comptime, field_alignments)
@Type(.Pointer(...))@Pointer(size, attrs, Element, sentinel)
@Type(.Fn(...))@Fn(param_types, param_attrs, ReturnType, attrs)
@Type(.Tuple(...))@Tuple(field_types)
@cImport({...})b.addTranslateC(...) + @import("c")(非推奨)
std.netstd.Io.net
std.ArrayList.init(allocator)std.ArrayList.initCapacity(allocator, n)
std.crypto.randomstd.Io.randomSecure(io, buf)
std.meta.intToEnumstd.enums.fromInt
std.fmt.FormatOptionsstd.fmt.Options
std.fmt.bufPrintZstd.fmt.bufPrintSentinel
std.io.fixedBufferStreamstd.Io.Writer.fixed(buf)
error.RenameAcrossMountPointserror.CrossDevice
error.NotSameFileSystemerror.CrossDevice
error.SharingViolationerror.FileBusy
error.EnvironmentVariableNotFounderror.EnvironmentVariableMissing
std.Build.Step.ConfigHeader の cmake 処理先頭の空白を修正

言語の変更点

@Type の削除 — 個別の組み込み関数を使用

@Type は削除されました。次の組み込み関数に置き換えてください。

// Integer type
const MyInt = @Int(.signed, 32);

// Struct type
const MyStruct = @Struct(
    .auto,           // layout
    null,            // BackingInt (for packed)
    &.{"x", "y"},    // field_names
    &.{ i32, i32 },  // field_types
    &.{ null, null },// field_defaults
    &.{ false, false }, // field_is_comptime
    &.{ null, null },// field_alignments
);

// Pointer type
const MyPtr = @Pointer(.one, .{
    .alignment = 8,
    .address_space = .generic,
    .is_const = false,
    .is_volatile = false,
}, u8, null);

// Function type
const MyFn = @Fn(&.{i32, i32}, &.{.{}, .{}}, i32, .{});

// Tuple type
const MyTuple = @Tuple(&.{ i32, bool });

// Enum literal type
const EnumLitType = @EnumLiteral();
@cImport の非推奨化 — ビルドシステムで変換

@cImport は非推奨です。build.zig で addTranslateC を使用してください。

// build.zig
const translate_c = b.addTranslateC(.{
    .root_source_file = b.path("src/c.h"),
    .target = target,
    .optimize = optimize,
});
translate_c.linkSystemLibrary("glfw", .{});

const exe = b.addExecutable(.{
    .name = "myapp",
    .root_module = b.createModule(.{
        .root_source_file = b.path("src/main.zig"),
        .optimize = optimize,
        .target = target,
        .imports = &.{
            .{ .name = "c", .module = translate_c.createModule() },
        },
    }),
});

その後、Zig では const c = @import("c"); とします。

注:C トランスレーターは、libclang ではなく arocc を基盤とするようになりました。

Switch の改善
  • packed struct と packed union を switch の prong 項目として使用できるようになりました(バッキング整数で比較されます)。
  • decl リテラルと結果型に依存する式(例:@enumFromInt)を switch の prong 項目として使用できるようになりました。
  • union タグのキャプチャが、inline の prong だけでなく、すべての prong で許可されるようになりました。
  • switch の prong キャプチャをすべて破棄することはできなくなりました。
  • .awake のアトミック順序が削除されました。.monotonic または .seq_cst を使用してください。
その他、言語レベルで注意すべき点
  • 小さな整数型から浮動小数点数型への型強制が可能になりました — 例:u8 → f32 が許可されます。
  • 実行時のベクトルインデックスは禁止されています — ベクトルのインデックスは comptime で既知でなければなりません。
  • ベクトルと配列は、メモリ上の型強制に対応しなくなりました — 要素ごとに明示的にキャストする必要があります。
  • 自明なローカル変数のアドレスを関数から返すことはできません — 例:return &local; は、より一貫して拒否されます。
  • packed union に未使用ビットがあってはなりません — すべてのビットパターンが有効でなければなりません。
  • packed struct/union 内のポインターは禁止されています。
  • 明示的にアラインメントを指定したポインター型は、自然にアラインメントされた型とは型システム上で別の型になりました。
  • 依存ループの規則が簡素化されました — ほとんどのコードは引き続き動作しますが、自身を参照するアラインメントの問い合わせはエラーになります。

標準ライブラリ:std.Io

ネットワーキング
  • std.net は削除されました。std.Io.net を使用してください(型:IpAddress、Stream、Server、UnixAddress)。
  • tcpConnectToHost、Address.parseIp、Stream.connect などの高水準ヘルパーは削除されました。Io の vtable を使用してください:io.vtable.netConnectIp、netRead、netWrite、netListenIp、netAccept。
  • 生の fd 操作には、std.os.linux.socket、accept4、connect、bind、listen、write、read、close を使用してください。
  • posix.socket、posix.bind、posix.accept、posix.shutdown、posix.writev、posix.listen、posix.pipe2、posix.getrandom、std.net.has_unix_sockets は削除されました。
  • Epoll:std.os.linux.epoll_create1/epoll_ctl/epoll_wait を直接使用してください。
  • 新機能:テストでの socketpair の使用に、std.Io.net.Socket.createPair を使用できます。
I/O リーダー/ライター
  • ライター/リーダーのインターフェースは std.Io の下にあります。TLS では *std.Io.Reader/*std.Io.Writer(構造体フィールド .interface)が必要です。インターフェースへのポインターを渡し、interface() を関数として呼び出さないでください。
  • std.time.sleep は削除されました。std.Io.sleep(io, Duration, Clock) を使用してください。
  • std.Io.GenericWriter、std.Io.AnyWriter、std.Io.null_writer、std.Io.CountingReader は削除されました。
時刻/乱数/環境変数/終了
  • std.time.milliTimestamp は削除されました。std.time.Timer または std.Io.Clock.now(clock, io) を使用し、Timestamp.nanoseconds を比較してください。
  • セキュアなランダムバイトには、std.Io.randomSecure(io, buf) を使用してください。std.crypto.random や std.posix.getrandom の便利関数はありません。
  • std.process.getEnvVarOwned は削除されました。std.c.getenv を使用してコピーしてください。
  • std.posix.exit は削除されました。std.process.exit を使用してください。
TLS クライアントオプション
  • std.crypto.tls.Client.Options には、entropy: *const [entropy_len]u8 と realtime_now_seconds: i64 が必要です。std.Io.randomSecure でエントロピーを生成し、Io.Clock.now(.real, io)/ns_per_s で秒数を計算してください。
MemoryPool API の変更
  • std.heap.MemoryPool(T).initCapacity(allocator, n) はプールを返します。
  • create/destroy には、現在アロケーターが必要です。引数なしの init() や deinit() はありません。
フォーマットオプション
  • FormatOptions は std.fmt.Options に置き換えられました。
  • std.fmt.format ヘルパーは削除されました。writer.print を直接呼び出してください(ライターは std.Io.Writer の下にあります)。
  • std.fmt.Formatter は Alt に名前が変更されました。
  • std.fmt.bufPrintZ は std.fmt.bufPrintSentinel に名前が変更されました。
乱数/暗号
  • std.crypto.random は削除されました。std.Io インスタンスを使用してください:const io = std.Io.Threaded.global_single_threaded.ioBasic(); io.random(&buf);。
  • Ed25519.KeyPair.generate には、現在 io: std.Io 引数が必要です。
列挙型の変換
  • std.meta.intToEnum は削除されました。std.enums.fromInt(EnumType, value) を使用してください(?EnumType を返します)。
  • meta.declList は削除されました。
テストでの固定バッファーライター
  • std.io.fixedBufferStream は削除されました。メモリー上への書き込みには var w = std.Io.Writer.fixed(buf); を使用し、std.Io.Writer.buffered(&w) でバイトを読み取ってください。
  • std.ArrayList には .init(allocator) という省略形がなくなりました。.initCapacity(allocator, n) を使用してください。
コレクション
  • SegmentedList は削除されました。
  • BitSet、EnumSet:initEmpty、initFull を宣言リテラル(例: .{}、.{ .a = true })に置き換えてください。
  • 新機能:Io.Dir.renamePreserve — 宛先を置き換えずに名前を変更します。
  • std.Io.Dir.rename は error.PathAlreadyExists ではなく error.DirNotEmpty を返します。
エラーセットの名前変更
// Old -> New
error.RenameAcrossMountPoints -> error.CrossDevice
error.NotSameFileSystem       -> error.CrossDevice
error.SharingViolation        -> error.FileBusy
error.EnvironmentVariableNotFound -> error.EnvironmentVariableMissing
数学
  • math.sign は、現在、取り得る値を格納できる最小の整数型を返します。
スレッド処理
  • Thread.Mutex.Recursive は削除されました。
圧縮
  • lzma、lzma2、xz は Io.Reader/Io.Writer インターフェースに更新されました。
動的ライブラリ
  • DynLib では Windows サポートが削除されました。LoadLibraryExW と GetProcAddress を直接使用してください。

新しい実行モデル:Juicy Main

Zig 0.16.0 では、推奨される main のパラメーターとして std.process.Init が導入されました。これは、このリリースにおける最大のエントリーポイントの変更です。

main のシグネチャ
// 1. Bare (no args/env available)
pub fn main() !void { }

// 2. Minimal (raw argv + environ only)
pub fn main(init: std.process.Init.Minimal) !void { }

// 3. Juicy Main (recommended)
pub fn main(init: std.process.Init) !void { }
std.process.Init の内容
pub const Init = struct {
    minimal: Minimal,
    arena: *std.heap.ArenaAllocator,  // process-lifetime arena, threadsafe
    gpa: Allocator,                     // general-purpose allocator
    io: Io,                             // default Io implementation
    environ_map: *Environ.Map,          // env vars (not threadsafe)
    preopens: Preopens,                 // WASI-style preopened files

    pub const Minimal = struct {
        environ: Environ,
        args: Args,
    };
};
例
const std = @import("std");

pub fn main(init: std.process.Init) !void {
    const gpa = init.gpa;
    const io = init.io;

    try std.Io.File.stdout().writeStreamingAll(io, "Hello, world!\n");

    const args = try init.minimal.args.toSlice(init.arena.allocator());
    for (args, 0..) |arg, i| {
        std.log.info("arg[{d}] = {s}", .{ i, arg });
    }

    std.log.info("{d} env vars", .{init.environ_map.count()});
}

目安:プログラムで I/O、メモリー割り当て、または環境変数が必要な場合は、std.process.Init を使用してください。

環境変数とプロセス引数はグローバルではありません

グローバル状態としての std.os.environ と std.process.args は廃止されました。これらは現在、main の init パラメーターからのみ利用できます。

環境変数
// Juicy Main
for (init.environ_map.keys(), init.environ_map.values()) |key, value| {
    std.log.info("env: {s}={s}", .{ key, value });
}

// Minimal main
std.log.info("HOME: {?s}", .{init.environ.getPosix("HOME")});
std.log.info("EDITOR: {s}", .{ try init.environ.getAlloc(arena, "EDITOR") });
const map = try init.environ.createMap(arena);
CLI 引数
// Iterate lazily
var args = init.args.iterate();
while (args.next()) |arg| {
    std.log.info("arg: {s}", .{arg});
}

// To slice (needs allocator)
const args = try init.args.toSlice(arena);

環境変数を必要とする関数は、*const process.Environ.Map または process.Environ をパラメーターとして受け取る必要があります。


Thread.Pool は廃止されました → std.Io を使用してください

std.Thread.Pool は廃止されました。std.Io.Group、std.Io.async、または std.Io.concurrent に置き換えてください。

移行例
// OLD (0.15)
fn doAllTheWork(pool: *std.Thread.Pool) void {
    var wg: std.Thread.WaitGroup = .{};
    pool.spawnWg(wg, doSomeWork, .{ pool, &wg, first_work_item });
    wg.wait();
}

// NEW (0.16)
fn doAllTheWork(io: std.Io) void {
    var g: std.Io.Group = .init;
    errdefer g.cancel(io);
    g.async(io, doSomeWork, .{ io, &g, first_work_item });
    g.wait(io);
}

fn doSomeWork(io: std.Io, g: *std.Io.Group, foo: Foo) void {
    foo.doTheThing();
    for (foo.new_work_items) |new| {
        g.async(io, doSomeWork, .{ io, g, new });
    }
}

重要:Thread.Pool から Io へ移行する際は、Thread.Mutex、Thread.Condition、Thread.ResetEvent を Io.Mutex、Io.Condition、Io.Event に置き換えてください。


ファイル I/O と fs API の変更

readFileAlloc / readToEndAlloc
// OLD
const contents = try std.fs.cwd().readFileAlloc(allocator, file_name, 1234);

// NEW
const contents = try std.Io.Dir.cwd().readFileAlloc(io, file_name, allocator, .limited(1234));
// Note: FileTooBig -> StreamTooLong when limit reached.
// OLD
const contents = try file.readToEndAlloc(allocator, 1234);

// NEW
var file_reader = file.reader(&.{});
const contents = try file_reader.interface.allocRemaining(allocator, .limited(1234));
setTimestamps
// OLD
try atomic_file.file_writer.file.setTimestamps(io, src_stat.atime, src_stat.mtime);

// NEW
try atomic_file.file_writer.file.setTimestamps(io, .{
    .access_timestamp = .init(src_stat.atime),
    .modify_timestamp = .init(src_stat.mtime),
});

Io.File.Stat.atime は ?Timestamp になりました(ZFS などでは null になることがあります)。

ディレクトリの走査
  • std.Io.Dir.walk は引き続き利用できます。
  • 新機能:std.Io.Dir.walkSelectively — ディレクトリごとに再帰を選択でき、不要な open/close システムコールを回避できます。
  • Walker と SelectiveWalker の両方に leave() と depth() が追加されました。
fs.path.relative は純粋関数になりました
// OLD
const relative = try std.fs.path.relative(gpa, from, to);

// NEW
const cwd_path = try std.process.currentPathAlloc(io, gpa);
const relative = try std.fs.path.relative(gpa, cwd_path, environ_map, from, to);
fs.path の Windows に関する変更
  • windowsParsePath/diskDesignator/diskDesignatorWindows → parsePath、parsePathWindows、parsePathPosix
  • getWin32PathType が追加されました
  • componentIterator/ComponentIterator.init は失敗しなくなりました
カレントディレクトリ API の名称変更
// OLD
std.process.getCwd(buffer)
std.process.getCwdAlloc(allocator)

// NEW
std.process.currentPath(io, buffer)
std.process.currentPathAlloc(io, allocator)

Preopens とアトミックファイル/一時ファイル

Preopens
// OLD (WASI)
const wasi_preopens: std.fs.wasi.Preopens = try .preopensAlloc(arena);

// NEW
const preopens: std.process.Preopens = try .init(arena);
// Or simply use init.preopens from Juicy Main.

Preopens は WASI 以外のターゲットでは void です。ゼロコスト抽象化です。

アトミックファイル/一時ファイル

std.Io.File.Atomic は、アトミックなファイル書き込みと一時ファイルのための新しい API です。

  • Linux:可能な場合は O_TMPFILE と連携します。
  • 新機能:std.Io.File.hardLink
  • 一時ファイル名やランダムなファイル名は、std.crypto.random ではなく Io vtable 経由で生成されます。

メモリとアロケーターの変更

ArenaAllocator はロックフリーかつスレッドセーフになりました

std.heap.ArenaAllocator を ThreadSafeAllocator でラップする必要はなくなりました。シングルスレッド時のパフォーマンスは同等で、競合時(約 7 スレッド)にはより高速です。

ThreadSafe アロケーターは廃止されました

std.heap.ThreadSafe は廃止されました。ArenaAllocator を直接使用するか、手動でアクセスを同期してください。

メモリのロック/保護機能は std.process に移動しました
// OLD
try std.posix.mlock();
try std.posix.mlock2(slice, std.posix.MLOCK_ONFAULT);
try std.posix.mlockall(slice, std.posix.MCL_CURRENT | std.posix.MCL_FUTURE);

// NEW
try std.process.lockMemory(slice, .{});
try std.process.lockMemory(slice, .{ .on_fault = true });
try std.process.lockMemoryAll(.{ .current = true, .future = true });

mmap/mprotect フラグは、ビット単位の OR ではなく、型安全な構造体になりました。

// OLD
std.posix.PROT.READ | std.posix.PROT.WRITE

// NEW
.{ .READ = true, .WRITE = true }
MemoryPool
  • std.heap.MemoryPool(T).initCapacity(allocator, n) はプールを返します。
  • create/destroy はアロケーター・パラメーターが必要になりました。
  • 新しい非管理型のバリアント:MemoryPoolUnmanaged、MemoryPoolAlignedUnmanaged、MemoryPoolExtraUnmanaged
Io.Writer.Allocating の alignment フィールド
alignment: std.mem.Alignment,  // new field

コンテナーとコレクションの変更

「Unmanaged」への移行

Allocator フィールドを埋め込んだ管理型のバリアントは、段階的に廃止されています。

  • ArrayHashMap、AutoArrayHashMap、StringArrayHashMap は廃止されました。
  • AutoArrayHashMapUnmanaged → array_hash_map.Auto
  • StringArrayHashMapUnmanaged → array_hash_map.String
  • ArrayHashMapUnmanaged → array_hash_map.Custom
PriorityQueue
var queue = std.PriorityQueue(u32, void, lessThan).empty;
  • init → initContext
  • add → push
  • addSlice → pushSlice
  • remove / removeOrNull → pop
  • removeIndex → popIndex
PriorityDequeue
var dq = std.PriorityDequeue(u32, void, lessThan).empty;
  • init → .empty
  • add → push
  • removeMinOrNull / removeMin → popMin
  • removeMaxOrNull / removeMax → popMax
  • removeIndex → popIndex
BitSet / EnumSet

initEmpty / initFull の代わりに宣言リテラルを使用してください。

var set = std.EnumSet(MyEnum).empty;
var full = std.EnumSet(MyEnum).full;
SegmentedList
  • std.SegmentedList は廃止されました。

削除された API(一覧)

削除された API代替
std.Thread.Poolstd.Io.Group、Io.async、Io.concurrent
std.heap.ThreadSafestd.heap.ArenaAllocator(スレッドセーフになりました)
std.io.fixedBufferStreamstd.Io.Reader.fixed(data) / std.Io.Writer.fixed(buf)
std.Io.GenericReaderstd.Io.Reader
std.Io.AnyReaderstd.Io.Reader
std.Io.GenericWriterstd.Io.Writer
std.Io.AnyWriterstd.Io.Writer
std.Io.null_writerstd.Io.Writer を直接使用します
std.Io.CountingReader直接の代替はありません。バイト数を手動で記録してください
std.SegmentedListなし
std.meta.declListなし
std.fs.getAppDataDirなし
std.posix.getCwd*std.process.currentPath*
std.posix.mlock*std.process.lockMemory*
std.posix.PROT_* ビット演算フラグ構造体リテラルのフラグ
std.ArrayHashMaparray_hash_map.Auto / .String / .Custom

Zig 0.16.0 でよく使われる慣用表現

ArrayList
const std = @import("std");

pub fn main(init: std.process.Init) !void {
    const gpa = init.gpa;

    var list = try std.ArrayList(u8).initCapacity(gpa, 16);
    defer list.deinit(gpa);

    try list.append(gpa, 'a');
    try list.appendSlice(gpa, "hello");
    try list.ensureTotalCapacity(gpa, 100);

    const owned = try list.toOwnedSlice(gpa);
    defer gpa.free(owned);
}
HashMap(デフォルト/非管理スタイル)
var map = std.StringHashMap(u32).empty;
defer map.deinit(gpa);

try map.put(gpa, "key", 42);
const val = map.get("key") orelse 0;
Juicy Main での stdout / stderr
pub fn main(init: std.process.Init) !void {
    const io = init.io;

    // Direct streaming write
    try std.Io.File.stdout().writeStreamingAll(io, "Hello, world!\n");

    // Or via writer interface
    var stdout_writer = std.Io.File.stdout().writer(&.{});
    try stdout_writer.interface.print("value: {d}\n", .{42});
}
固定バッファーの Reader / Writer
// Reader from byte slice
var data = "line1\nline2\n";
var reader: std.Io.Reader = .fixed(data);

// Writer into a stack buffer
var buf: [256]u8 = undefined;
var writer: std.Io.Writer = .fixed(&buf);
try writer.interface.print("count: {d}", .{7});
ファイル I/O
// Read entire file
const contents = try std.Io.Dir.cwd().readFileAlloc(io, "input.txt", gpa, .limited(1024 * 1024));
defer gpa.free(contents);

// Write file atomically
var atomic = try std.Io.File.Atomic.init(io, gpa, "output.txt");
try atomic.file_writer.interface.print("data: {s}\n", .{"hello"});
try atomic.commit(io);
JSON
const MyStruct = struct {
    name: []const u8,
    value: u32,
};

// Parsing
const json_str =
    \\{"name": "test", "value": 42}
;
const parsed = try std.json.parseFromSlice(MyStruct, gpa, json_str, .{});
defer parsed.deinit();

// Serialization to string (via Io.Writer.Allocating)
var out: std.Io.Writer.Allocating = .init(gpa);
defer out.deinit();
var stringify: std.json.Stringify = .{
    .writer = &out.writer,
    .options = .{},
};
try stringify.write(parsed.value);
const json_output = out.written();
型リフレクション(Comptime)
const info = @typeInfo(T);
if (info == .pointer) { ... }
if (info == .slice) { ... }
if (info == .@"struct") { ... }
if (info == .@"enum") { ... }
if (info == .@"union") { ... }
if (info == .optional) { ... }
テスト
test "basic arithmetic" {
    const std = @import("std");
    try std.testing.expectEqual(4, 2 + 2);
    try std.testing.expectError(error.OutOfMemory, mightFail());
}

test "no leaks" {
    const std = @import("std");
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    defer std.testing.expect(gpa.deinit() == .ok) catch @panic("leak");
    const allocator = gpa.allocator();

    const ptr = try allocator.create(u32);
    defer allocator.destroy(ptr);
}
Leb128(バイナリ形式)
// OLD: std.leb.readUleb128(reader)
// NEW:
const value = try reader.takeLeb128(u64);

よくあるエラーメッセージと修正方法(0.16)

エラー原因修正方法
no field named 'getStdOut'古い std.io.getStdOut() を使用していますstd.Io.File.stdout() を使用します
expected 2 argument(s), found 1ArrayList のメソッドにアロケーターが指定されていませんアロケーターを最初の引数として追加します
no member named 'Pool' in 'Thread'std.Thread.Pool が削除されましたstd.Io.Group + Io.async を使用します
expected type '*const process.Environ.Map'関数に env map パラメーターが必要ですmain(init) から渡します
no member named 'fixedBufferStream'古い stream API が削除されましたstd.Io.Reader.fixed(...) または std.Io.Writer.fixed(...) を使用します
no field named 'getCwd' in 'process'名前が変更されましたstd.process.currentPath* を使用します
fingerprint field missing古い build.zig.zon です.fingerprint = 0x... を追加し、.name = "x" を .name = .x に変更します
type depends on itself for alignment自己参照型のアラインメント照会です@alignOf(@This()) を削除するか、構造を変更します

ビルドシステムの変更

build.zig.zon で Fingerprint が必須

build.zig.zon では fingerprint フィールドが必須になりました。また、name は文字列ではなく enum リテラルでなければなりません。

.{
    .name = .myproject,  // enum literal, not "myproject"
    .fingerprint = 0x123456789abcdef0,
    .version = "0.1.0",
    .dependencies = .{},
}

これらが設定されていない場合、zig build は失敗します。

ローカルパッケージのオーバーライド:--fork

一時的なローカルオーバーライド用の新しい CLI フラグです。

zig build --fork=/path/to/local/fork

name と fingerprint が一致する依存関係は、取得されずにローカルパスへ解決されます。これは一時的な設定です。元に戻すには、このフラグを削除してください。

パッケージの取得先は zig-pkg ディレクトリ

依存関係はグローバルキャッシュではなく、ローカルの zig-pkg/ ディレクトリ(build.zig と同じ場所)に取得されるようになりました。フィルタリング後、今後再利用できるようグローバルキャッシュに再圧縮して格納されます。

ユニットテストのタイムアウト

テストごとにタイムアウトを指定します。

zig build test --test-timeout 500ms

タイムアウト後、テストプロセスは終了され、次のテストのために再起動されます。

ConfigHeader
  • std.Build.Step.ConfigHeader は、cmake 形式の設定ヘッダーの先頭にある空白を正しく処理するようになりました。

コンパイラー/ツールチェーン

C の変換
  • @cImport は引き続き利用できますが、非推奨となり、libclang ではなく arocc を内部で使用するようになりました。
  • 新しいコードでは、常に build.zig で addTranslateC を使用してください。
型解決
  • 内部の型解決が再設計されました。以前は動作していたコードのほとんどは引き続き動作し、一部の「依存関係ループ」エラーは解決されています。
  • 自己参照型のアラインメント照会(例:align(@alignOf(@This())))は、正しくエラーになるようになりました。
LLVM バックエンド
  • 実験的なインクリメンタルコンパイルに対応しました。
  • エラーセット型はデバッグ情報内で enum として変換されるようになり、実行時にエラー名を確認できます。

対象プラットフォームのサポート

主な追加項目:

  • aarch64-freebsd、aarch64-netbsd、loongarch64-linux、powerpc64le-linux、s390x-linux、x86_64-freebsd、x86_64-netbsd、x86_64-openbsd が CI でテストされるようになりました。
  • aarch64-maccatalyst、x86_64-maccatalyst のクロスコンパイルが追加されました。
  • loongarch32-linux の初期サポートが追加されました(libc はまだありません)。
  • Alpha、KVX、MicroBlaze、OpenRISC、PA-RISC、SuperH の基本的なサポートが追加されました。
  • Solaris、AIX、z/OS のサポートが削除されました。
  • ほぼすべての主要なターゲットで、スタックトレースが改善されました。

テストに関する調整

  • プロセス内のクライアント/サーバーテストでは、Io vtable のネットワークへの依存を避けるため、std.Io.net.Socket.createPair または生の socketpair(AF.UNIX, SOCK.STREAM|CLOEXEC, 0, &fds) を使用してください(Threaded ネットワークは接続されていない場合、NetworkDown を返します)。
  • 多くの std.Io 関数でエラーセットが厳密化されました。該当する到達不能な分岐を削除してください。

移植戦略(0.15 → 0.16)

  1. @Type の呼び出しを置き換える:新しい組み込み関数のうち、用途に合ったものを使用してください。
  2. @cImport を置き換える:build.zig で addTranslateC を使用してください。
  3. build.zig.zon に fingerprint を追加し、name を修正する。
  4. アプリ全体に std.Io を渡す — I/O、スリープ、乱数、時刻を扱う関数には io パラメーターが必要です。
  5. std.net の使用箇所を更新する:std.Io.net または生のシステムコールを使用してください。
  6. ArrayList の呼び出しを更新する:アロケーターを明示的に渡し、initCapacity を使用してください。
  7. エラーセット名を修正する(CrossDevice、FileBusy、EnvironmentVariableMissing、DirNotEmpty)。
  8. zig build test --test-timeout 500ms を実行する:ハングするテストを早期に検出できます。

新しい Zig 0.16.0 コードを書く場合や、0.15.x からアップグレードする場合に、このスキルを使用してください。

コメント