From e47b671b12298c8adba2d899e5ea1521297c9aa1 Mon Sep 17 00:00:00 2001 From: zed Date: Mon, 20 Nov 2023 20:54:55 +0300 Subject: [PATCH] On branch main modified: src/ch09.md new file: src/ex-ch09-08/build.zig new file: src/ex-ch09-08/calc/add.zig new file: src/ex-ch09-08/calc/build.zig new file: src/ex-ch09-08/calc/calc.zig new file: src/ex-ch09-08/program.zig --- src/ch09.md | 132 ++++++++++++++++++++++++++++++++-- src/ex-ch09-08/build.zig | 40 +++++++++++ src/ex-ch09-08/calc/add.zig | 12 ++++ src/ex-ch09-08/calc/build.zig | 17 +++++ src/ex-ch09-08/calc/calc.zig | 9 +++ src/ex-ch09-08/program.zig | 16 +++++ 6 files changed, 222 insertions(+), 4 deletions(-) create mode 100644 src/ex-ch09-08/build.zig create mode 100644 src/ex-ch09-08/calc/add.zig create mode 100644 src/ex-ch09-08/calc/build.zig create mode 100644 src/ex-ch09-08/calc/calc.zig create mode 100644 src/ex-ch09-08/program.zig diff --git a/src/ch09.md b/src/ch09.md index 5b61b69..5465239 100644 --- a/src/ch09.md +++ b/src/ch09.md @@ -686,10 +686,134 @@ test "dummy build test" { прошёл, как и должно было быть, поскольку `true != false`. Если вы подправите тест и снова запустите `zig build test`, то ничего не выведется, что и будет означать, что тест прошёл. По умолчанию система -что либо выводит только в случае неудавшегося теста. Если нужно в любом -случае что-то увидеть, используйте `zig build test --summary all`. - - +тестов Zig что либо выводит только в случае неудавшегося теста. Если +нужно в любом случае что-то увидеть, используйте `zig build test --summary all`. +В заключение отметим, что начинать проект можно (и, наверное, нужно) с +выполнения `zig init-exe` или `zig init-lib` для запускаемых программ и +библиотек, соответственно. Эти команды создадут надлежащий `build.zig` +автоматически, причём хорошо документированный. ## Сторонние зависимости + +Встроенный в Zig менеджер пакетов пока ещё относительно новый и, как +следствие, несколько недоработан. Тем не менее, его вполне можно +использовать в том виде, какой он есть на данный момент. Далее мы +рассмотрим два вопроса, создание пакетов и использование пакетов. + +Сначала создадим каталог `calc` и в нём три файла, первый из которых +назовём `add.zig`, вот его содержимое: + +```zig +// Oh, a hidden lesson, look at the type of b +// and the return type!! + +pub fn add(a: anytype, b: @TypeOf(a)) @TypeOf(a) { + return a + b; +} + +const testing = @import("std").testing; +test "add" { + try testing.expectEqual(@as(i32, 32), add(30, 2)); +} +``` + +Конечно, делать пакет ради сложения двух чисел это глуповато, +но такая предельная простота позволит нам сосредоточиться +исключительно на вещах, связанных с пакетами, а не на функциональности пакетов. +Второй файл, который мы добавим (`calc.zig`) будет такой же простяцкий: + +```zig +pub const add = @import("add.zig").add; + +test { + // By default, only tests in the specified file + // are included. This magic line of code will + // cause a reference to all nested containers + // to be tested. + @import("std").testing.refAllDecls(@This()); +} +``` + +Мы разместили эти два кусочка кода в разных файлах +для того, чтобы `zig build` автоматически собрал +и "упаковал" все файлы нашего проекта. Добавляем `build.zig`: + +```zig +const std = @import("std"); + +pub fn build(b: *std.Build) !void { + const target = b.standardTargetOptions(.{}); + const optimize = b.standardOptimizeOption(.{}); + + const tests = b.addTest(.{ + .target = target, + .optimize = optimize, + .root_source_file = .{ .path = "calc.zig" }, + }); + + const test_cmd = b.addRunArtifact(tests); + test_cmd.step.dependOn(b.getInstallStep()); + const test_step = b.step("test", "Run the tests"); + test_step.dependOn(&test_cmd.step); +} +``` + +Всё это повторение того, что мы уже видели в предыдущем разделе. +В частности, имея эти три файла, уже можно запустить `zig build test --summary all`: + +``` +Build Summary: 4/4 steps succeeded; 2/2 tests passed +test success +└─ run test 2 passed 1ms MaxRSS:1M + ├─ zig test Debug native success 2s MaxRSS:185M + └─ install cached +``` + +Вернёмся теперь к примеру из предыдущего раздела и к файлу +`build.zig`, который мы там сделали. Начнём с добавления +в него нашего локального `calc` в качестве зависимости, +для чего нужно 3 дополнения. Сначала создадим модуль, +указывающий на `calc`: + +```zig +// You can put this near the top of the build +// function, before the call to addExecutable. + +const calc_module = b.addModule("calc", .{ + .source_file = .{ .path = "PATH_TO_CALC_PROJECT/calc.zig" }, +}); +``` + +Теперь нужно добавить этот модуль к переменным `exe` и `tests`: + +```zig +const exe = b.addExecutable(.{ + .name = "learning", + .target = target, + .optimize = optimize, + .root_source_file = .{ .path = "learning.zig" }, +}); +// add this +exe.addModule("calc", calc_module); +b.installArtifact(exe); + +.... + +const tests = b.addTest(.{ + .target = target, + .optimize = optimize, + .root_source_file = .{ .path = "learning.zig" }, +}); +// add this +tests.addModule("calc", calc_module); +``` + +Теперь в вашем проекте можно импортировать модуль: + +```zig +const calc = @import("calc"); +... +calc.add(1, 2); +``` + diff --git a/src/ex-ch09-08/build.zig b/src/ex-ch09-08/build.zig new file mode 100644 index 0000000..404f757 --- /dev/null +++ b/src/ex-ch09-08/build.zig @@ -0,0 +1,40 @@ + +const std = @import("std"); + +pub fn build(b: *std.Build) !void { + const target = b.standardTargetOptions(.{}); + const optimize = b.standardOptimizeOption(.{}); + + const calc_module = b.addModule("calc", .{ + .source_file = .{ .path = "calc/calc.zig" }, + }); + + // setup executable + const exe = b.addExecutable(.{ + .name = "program", + .target = target, + .optimize = optimize, + .root_source_file = .{ .path = "program.zig" }, + }); + exe.addModule("calc", calc_module); + b.installArtifact(exe); + + // run step + const run_cmd = b.addRunArtifact(exe); + run_cmd.step.dependOn(b.getInstallStep()); + const run_step = b.step("run", "test run"); + run_step.dependOn(&run_cmd.step); + + // test step + const tests = b.addTest(.{ + .target = target, + .optimize = optimize, + .root_source_file = .{ .path = "program.zig" }, + }); + tests.addModule("calc", calc_module); + + const test_cmd = b.addRunArtifact(tests); + test_cmd.step.dependOn(b.getInstallStep()); + const test_step = b.step("test", "Run the tests"); + test_step.dependOn(&test_cmd.step); +} diff --git a/src/ex-ch09-08/calc/add.zig b/src/ex-ch09-08/calc/add.zig new file mode 100644 index 0000000..2d4f885 --- /dev/null +++ b/src/ex-ch09-08/calc/add.zig @@ -0,0 +1,12 @@ + +// Oh, a hidden lesson, look at the type of b +// and the return type!! + +pub fn add(a: anytype, b: @TypeOf(a)) @TypeOf(a) { + return a + b; +} + +const testing = @import("std").testing; +test "add" { + try testing.expectEqual(@as(i32, 32), add(30, 2)); +} diff --git a/src/ex-ch09-08/calc/build.zig b/src/ex-ch09-08/calc/build.zig new file mode 100644 index 0000000..4c325ca --- /dev/null +++ b/src/ex-ch09-08/calc/build.zig @@ -0,0 +1,17 @@ +const std = @import("std"); + +pub fn build(b: *std.Build) !void { + const target = b.standardTargetOptions(.{}); + const optimize = b.standardOptimizeOption(.{}); + + const tests = b.addTest(.{ + .target = target, + .optimize = optimize, + .root_source_file = .{ .path = "calc.zig" }, + }); + + const test_cmd = b.addRunArtifact(tests); + test_cmd.step.dependOn(b.getInstallStep()); + const test_step = b.step("test", "Run the tests"); + test_step.dependOn(&test_cmd.step); +} diff --git a/src/ex-ch09-08/calc/calc.zig b/src/ex-ch09-08/calc/calc.zig new file mode 100644 index 0000000..7d3eb4e --- /dev/null +++ b/src/ex-ch09-08/calc/calc.zig @@ -0,0 +1,9 @@ +pub const add = @import("add.zig").add; + +test { + // By default, only tests in the specified file + // are included. This magic line of code will + // cause a reference to all nested containers + // to be tested. + @import("std").testing.refAllDecls(@This()); +} diff --git a/src/ex-ch09-08/program.zig b/src/ex-ch09-08/program.zig new file mode 100644 index 0000000..7ce932e --- /dev/null +++ b/src/ex-ch09-08/program.zig @@ -0,0 +1,16 @@ + +const std = @import("std"); +const calc = @import("calc"); + +pub fn main() void { + const a: u32 = 3; + const b: u32 = 4; + const c: u32 = calc.add(a, b); + std.debug.print("{} + {} = {}\n", .{a, b, c}); +} + +test "calc.add() test" { + const a: u32 = 3; + const b: u32 = 4; + try std.testing.expectEqual(calc.add(a, b), 8); // will fail +}