On branch main
modified: src/ch09.md new file: src/zig-build/build.zig new file: src/zig-build/program.zig
This commit is contained in:
121
src/ch09.md
121
src/ch09.md
@@ -564,9 +564,126 @@ pub const User = struct {
|
||||
Обычно `@TypeOf` используется в паре с `@typeInfo`, которая возвращает
|
||||
`std.builtin.Type`. Это весьма интересное маркированное объединение,
|
||||
которое полностью описывает тип. Функция `std.json.stringify` (к примеру)
|
||||
рекурсивно использует такие описания для того, чтобы выяснить,
|
||||
как именно нужно сериализвать значения.
|
||||
рекурсивно использует такие описания для того, чтобы выяснить, как именно
|
||||
нужно сериализвать значения.
|
||||
|
||||
## Система сборки
|
||||
|
||||
Если вы читали всю эту книгу и при этом ожидали каких-то рецептов для
|
||||
работы с более сложными проектами (множественные зависимости, поддержка
|
||||
разных целевых архитектур и т.п), то увы, вас ждёт разочарование. Zig на
|
||||
самом деле имеет очень мощную систему сборки, настолько мощную, что она
|
||||
начала использоваться для проектов, написаннных не на Zig. К сожалению,
|
||||
вся эта мощь означает, что для более простых нужд система сборки Zig не
|
||||
самая простая в использовании.
|
||||
|
||||
Тем не менее, небольшой обзор мы всё же сделаем. Чтобы запускать наши
|
||||
примеры, мы использовали `zig run file.zig`. Однажды мы также
|
||||
использовали `zig test file.zig` для запуска теста. Команды `run` и
|
||||
`test` хороши для всяких простых упражнений, но для чего-то более
|
||||
серьёзного вам понадобится команда `build`. Для этой команды нужно, чтобы
|
||||
в корневом каталоге проекта был файл `build.zig` со специальной
|
||||
одноимённой точкой входа:
|
||||
|
||||
```zig
|
||||
// build.zig
|
||||
|
||||
const std = @import("std");
|
||||
|
||||
pub fn build(b: *std.Build) !void {
|
||||
_ = b;
|
||||
}
|
||||
```
|
||||
|
||||
Каждая сборка имеет по умолчанию этап "install", который можно
|
||||
выполнить при помощи `zig build install`, но поскольку наш файл
|
||||
`build.zig` практически пуст, на выходе ничего особо значимого и не
|
||||
будет. Как минимум, мы должны сообщить, где у нас файл с функцией `main`
|
||||
(тут предполагается, что это `program.zig`):
|
||||
|
||||
```zig
|
||||
const std = @import("std");
|
||||
|
||||
pub fn build(b: *std.Build) !void {
|
||||
const target = b.standardTargetOptions(.{});
|
||||
const optimize = b.standardOptimizeOption(.{});
|
||||
|
||||
// setup executable
|
||||
const exe = b.addExecutable(.{
|
||||
.name = "program",
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
.root_source_file = .{ .path = "program.zig" },
|
||||
});
|
||||
b.installArtifact(exe);
|
||||
}
|
||||
```
|
||||
|
||||
Теперь, если вы выполните `zig build install`, то получите
|
||||
скомпилированный исполнимый файл `./zig-out/bin/program`. Целевую
|
||||
платформу и вид оптимизации при этом можно указать в аргументах командной
|
||||
строки. Например, если мы хотим оптимизацию по размеру и делаем
|
||||
исполнимый файл для ОС Windows на архитектуре x86_64, то делаем так:
|
||||
|
||||
```
|
||||
zig build install -Doptimize=ReleaseSmall -Dtarget=x86_64-windows-gnu
|
||||
```
|
||||
|
||||
Помимо этапа "install", процесс сборки может включать в себя ещё два,
|
||||
"run" и "test". Если это библиотека, то только один, "test". Чтобы
|
||||
включить этап "run", в простейшем случае, то есть без передачи программе
|
||||
аргументов, нужно добавить 4 строчки:
|
||||
|
||||
```zig
|
||||
// add after: b.installArtifact(exe);
|
||||
|
||||
const run_cmd = b.addRunArtifact(exe);
|
||||
run_cmd.step.dependOn(b.getInstallStep());
|
||||
|
||||
const run_step = b.step("run", "Start learning!");
|
||||
run_step.dependOn(&run_cmd.step);
|
||||
```
|
||||
|
||||
Это создаёт две зависимости, путём двух вызовов `dependOn`. Первый из них
|
||||
привязывает команду "run" к встроенному этапу "install". Второй
|
||||
привязывает этап "run" к созданной команде "run". Вы, наверное, спросите,
|
||||
зачем нужны как команда "run", так и этап "run". Надо полагать, такое
|
||||
разделение существует для возможности более сложных конфигураций: этапы,
|
||||
которые зависят от более чем одной команды или команды, которые
|
||||
исппользуются на разных этапах. Если вы выполните `zig build --help` и
|
||||
посмотрите на начало вывода, то увидите наш новый этап "run". Теперь вы
|
||||
можете запускать программу при помощи `zig build run`.
|
||||
|
||||
Для добавления этапа "test" нужно продублировать практически весь код для
|
||||
этапов "install" и "run", только вместо `b.addExecutable` надо
|
||||
использовать `b.addTest`:
|
||||
|
||||
```zig
|
||||
const tests = b.addTest(.{
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
.root_source_file = .{ .path = "program.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);
|
||||
```
|
||||
|
||||
Тут мы дали этапу имя "test". При запуске `zig build --help`
|
||||
теперь мы должны увидеть новый доступный этап. Если в нашей
|
||||
`program.zig` никаких тестов нет, сложно сказать, что тут
|
||||
получится, поэтому добавим в `program.zig` заглушку:
|
||||
|
||||
```zig
|
||||
test "dummy build test" {
|
||||
try std.testing.expectEqual(false, true);
|
||||
}
|
||||
```
|
||||
|
||||
Теперь, если вы выполните `zig build test`, то увидите,
|
||||
что тест не прошёл, как и должно было быть, поскольку `true != false`.
|
||||
|
||||
|
||||
## Сторонние зависимости
|
||||
|
||||
34
src/zig-build/build.zig
Normal file
34
src/zig-build/build.zig
Normal file
@@ -0,0 +1,34 @@
|
||||
|
||||
const std = @import("std");
|
||||
|
||||
pub fn build(b: *std.Build) !void {
|
||||
const target = b.standardTargetOptions(.{});
|
||||
const optimize = b.standardOptimizeOption(.{});
|
||||
|
||||
// setup executable
|
||||
const exe = b.addExecutable(.{
|
||||
.name = "program",
|
||||
.target = target,
|
||||
.optimize = optimize,
|
||||
.root_source_file = .{ .path = "program.zig" },
|
||||
});
|
||||
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" },
|
||||
});
|
||||
|
||||
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);
|
||||
}
|
||||
11
src/zig-build/program.zig
Normal file
11
src/zig-build/program.zig
Normal file
@@ -0,0 +1,11 @@
|
||||
|
||||
const std = @import("std");
|
||||
|
||||
pub fn main() void {
|
||||
std.debug.print("test\n", .{});
|
||||
}
|
||||
|
||||
test "dummy build test" {
|
||||
//try std.testing.expectEqual(false, true); // failed
|
||||
try std.testing.expectEqual(false, false); // passed
|
||||
}
|
||||
Reference in New Issue
Block a user