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
This commit is contained in:
zed
2023-11-20 20:54:55 +03:00
parent d10ed54174
commit e47b671b12
6 changed files with 222 additions and 4 deletions

View File

@@ -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);
```

40
src/ex-ch09-08/build.zig Normal file
View File

@@ -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);
}

View File

@@ -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));
}

View File

@@ -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);
}

View File

@@ -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());
}

View File

@@ -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
}