zig-0.16 について
zig-0.16は、Zig 0.16.0を使う開発者向けのプログラミングガイドスキルです。言語と標準ライブラリの変更点、移行例、ローカルドキュメントの参照方法をまとめています。
主な機能
- 01Zig 0.16.0を対象
- 02言語レベルの変更点を整理
- 03std.Ioと標準ライブラリAPIの更新を解説
- 04旧APIから新APIへの移行例を掲載
- 05言語および標準ライブラリのローカル文書参照を案内
活用シーン
- 01Zigプロジェクトを0.16.0へ移行
- 02標準ライブラリAPIのバージョン差を確認
- 03I/O、ネットワーク、ファイル操作のコードを更新
- 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.net | std.Io.net |
std.ArrayList.init(allocator) | std.ArrayList.initCapacity(allocator, n) |
std.crypto.random | std.Io.randomSecure(io, buf) |
std.meta.intToEnum | std.enums.fromInt |
std.fmt.FormatOptions | std.fmt.Options |
std.fmt.bufPrintZ | std.fmt.bufPrintSentinel |
std.io.fixedBufferStream | std.Io.Writer.fixed(buf) |
error.RenameAcrossMountPoints | error.CrossDevice |
error.NotSameFileSystem | error.CrossDevice |
error.SharingViolation | error.FileBusy |
error.EnvironmentVariableNotFound | error.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、parsePathPosixgetWin32PathTypeが追加されました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.AutoStringArrayHashMapUnmanaged→array_hash_map.StringArrayHashMapUnmanaged→array_hash_map.Custom
PriorityQueue
var queue = std.PriorityQueue(u32, void, lessThan).empty;
init→initContextadd→pushaddSlice→pushSliceremove/removeOrNull→popremoveIndex→popIndex
PriorityDequeue
var dq = std.PriorityDequeue(u32, void, lessThan).empty;
init→.emptyadd→pushremoveMinOrNull/removeMin→popMinremoveMaxOrNull/removeMax→popMaxremoveIndex→popIndex
BitSet / EnumSet
initEmpty / initFull の代わりに宣言リテラルを使用してください。
var set = std.EnumSet(MyEnum).empty;
var full = std.EnumSet(MyEnum).full;
SegmentedList
std.SegmentedListは廃止されました。
削除された API(一覧)
| 削除された API | 代替 |
|---|---|
std.Thread.Pool | std.Io.Group、Io.async、Io.concurrent |
std.heap.ThreadSafe | std.heap.ArenaAllocator(スレッドセーフになりました) |
std.io.fixedBufferStream | std.Io.Reader.fixed(data) / std.Io.Writer.fixed(buf) |
std.Io.GenericReader | std.Io.Reader |
std.Io.AnyReader | std.Io.Reader |
std.Io.GenericWriter | std.Io.Writer |
std.Io.AnyWriter | std.Io.Writer |
std.Io.null_writer | std.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.ArrayHashMap | array_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 1 | ArrayList のメソッドにアロケーターが指定されていません | アロケーターを最初の引数として追加します |
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)
@Typeの呼び出しを置き換える:新しい組み込み関数のうち、用途に合ったものを使用してください。@cImportを置き換える:build.zigでaddTranslateCを使用してください。build.zig.zonにfingerprintを追加し、nameを修正する。- アプリ全体に
std.Ioを渡す — I/O、スリープ、乱数、時刻を扱う関数にはioパラメーターが必要です。 std.netの使用箇所を更新する:std.Io.netまたは生のシステムコールを使用してください。ArrayListの呼び出しを更新する:アロケーターを明示的に渡し、initCapacityを使用してください。- エラーセット名を修正する(CrossDevice、FileBusy、EnvironmentVariableMissing、DirNotEmpty)。
zig build test --test-timeout 500msを実行する:ハングするテストを早期に検出できます。
新しい Zig 0.16.0 コードを書く場合や、0.15.x からアップグレードする場合に、このスキルを使用してください。