-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbuild.zig
More file actions
287 lines (261 loc) · 13.2 KB
/
build.zig
File metadata and controls
287 lines (261 loc) · 13.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
//! Purpose: Define the project build graph and public build steps.
//! Owns: Module wiring, test roots, conformance, coverage, Valgrind, docs, and aggregate build steps.
//! Does not own: Reusable build-step helper implementations.
//! Depends on: tools/build_steps.zig and std.Build.
//! Tested by: tests/structure/docs_tooling_test.zig and zig build test.
const std = @import("std");
const build_steps = @import("tools/build_steps.zig");
const minimum_zig_version = @import("build.zig.zon").minimum_zig_version;
const addTestRun = build_steps.addTestRun;
const addTestRunAndArtifact = build_steps.addTestRunAndArtifact;
comptime {
const required = std.SemanticVersion.parse(minimum_zig_version) catch unreachable;
if (@import("builtin").zig_version.order(required) == .lt) {
@compileError("This project requires Zig " ++ minimum_zig_version ++ " or newer.");
}
}
pub fn build(b: *std.Build) void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
const test_filter = b.option([]const u8, "test-filter", "Run only tests whose names contain this text.");
const test_filters: []const []const u8 = if (test_filter) |filter| &.{filter} else &.{};
// The self-hosted x86_64 backend (default on Linux since Zig 0.15) emits DWARF
// that kcov v43 cannot parse, producing empty coverage reports. Opt into the
// LLVM backend with -Duse-llvm=true for the coverage and valgrind CI steps.
// See ziglang/zig#24463 and #25368.
const use_llvm = b.option(bool, "use-llvm", "Build test binaries with the LLVM backend (needed for kcov coverage on Zig 0.16+).");
const coverage_threshold = b.option(u8, "coverage-threshold", "Minimum line coverage percent required by test-coverage.") orelse 100;
const yaml_test_suite_dir = b.option(
[]const u8,
"yaml-test-suite-dir",
"Path to the yaml-test-suite data directory used by conformance tests.",
) orelse "vendor/yaml-test-suite";
const libfyaml_fy_tool = b.option(
[]const u8,
"libfyaml-fy-tool",
"Path to libfyaml's fy-tool executable for the optional libfyaml-compare step.",
);
const using_pinned_yaml_test_suite = std.mem.eql(u8, yaml_test_suite_dir, "vendor/yaml-test-suite");
const yaml_mod = b.addModule("yaml", .{
.root_source_file = b.path("src/lib.zig"),
.target = target,
.optimize = optimize,
});
const yaml_unit_mod = b.createModule(.{
.root_source_file = b.path("src/lib.zig"),
.target = target,
.optimize = optimize,
.error_tracing = false,
});
const unit_tests = b.addTest(.{
.root_module = yaml_unit_mod,
.filters = test_filters,
.use_llvm = use_llvm,
});
const run_unit_tests = b.addRunArtifact(unit_tests);
const unit_step = b.step("test-unit", "Run library unit tests");
unit_step.dependOn(&run_unit_tests.step);
const yaml_imports: []const std.Build.Module.Import = &.{.{ .name = "yaml", .module = yaml_mod }};
build_steps.addBenchmarkStep(b, target);
const yaml_internal_mod = b.createModule(.{
.root_source_file = b.path("src/internal.zig"),
.target = target,
.optimize = optimize,
});
const internal_imports: []const std.Build.Module.Import = &.{.{ .name = "yaml_internal", .module = yaml_internal_mod }};
const schema_step = b.step("test-schema", "Run schema resolver unit tests");
const FocusedUnitRoot = struct {
root_source_file: []const u8,
imports: []const std.Build.Module.Import,
};
const focused_unit_roots = [_]FocusedUnitRoot{
.{ .root_source_file = "tests/unit/api/root_api_test.zig", .imports = yaml_imports },
.{ .root_source_file = "tests/unit/api/load_string_ownership_test.zig", .imports = yaml_imports },
.{ .root_source_file = "tests/unit/scanner/scanner_test.zig", .imports = yaml_imports },
.{ .root_source_file = "tests/unit/reader/reader_test.zig", .imports = internal_imports },
.{ .root_source_file = "tests/unit/api/parser_stream_test.zig", .imports = yaml_imports },
.{ .root_source_file = "tests/unit/compose/composer_test.zig", .imports = internal_imports },
.{ .root_source_file = "tests/unit/loader/loader_test.zig", .imports = internal_imports },
.{ .root_source_file = "tests/unit/loader/direct_test.zig", .imports = internal_imports },
.{ .root_source_file = "tests/unit/schema/schema_test.zig", .imports = internal_imports },
.{ .root_source_file = "tools/benchmark.zig", .imports = internal_imports },
};
var focused_unit_coverage_artifacts: [focused_unit_roots.len + 1]*std.Build.Step.Compile = undefined;
for (focused_unit_roots, 0..) |unit_root, index| {
const focused_tests = addTestRunAndArtifact(b, .{
.root_source_file = unit_root.root_source_file,
.target = target,
.optimize = optimize,
.imports = unit_root.imports,
.filters = test_filters,
.use_llvm = use_llvm,
});
focused_unit_coverage_artifacts[index] = focused_tests.compile;
unit_step.dependOn(&focused_tests.run.step);
if (std.mem.eql(u8, unit_root.root_source_file, "tests/unit/schema/schema_test.zig")) {
schema_step.dependOn(&focused_tests.run.step);
}
}
unit_step.dependOn(schema_step);
const conformance_mod = b.createModule(.{
.root_source_file = b.path("tests/conformance/yaml_suite_runner.zig"),
.target = target,
.optimize = optimize,
.imports = yaml_imports,
});
const conformance_options = b.addOptions();
conformance_options.addOption([]const u8, "yaml_test_suite_dir", yaml_test_suite_dir);
conformance_options.addOption(bool, "using_pinned_yaml_test_suite", using_pinned_yaml_test_suite);
conformance_mod.addOptions("conformance_options", conformance_options);
const conformance_tests = b.addTest(.{
.root_module = conformance_mod,
.filters = test_filters,
.use_llvm = use_llvm,
});
const run_conformance_tests = b.addRunArtifact(conformance_tests);
const conformance_step = b.step("test-conformance", "Run yaml-test-suite conformance tests");
conformance_step.dependOn(&run_conformance_tests.step);
const event_parser_mod = b.createModule(.{
.root_source_file = b.path("src/internal.zig"),
.target = target,
.optimize = optimize,
});
const direct_conformance_mod = b.createModule(.{
.root_source_file = b.path("tests/conformance/direct_conformance.zig"),
.target = target,
.optimize = optimize,
.imports = &.{.{ .name = "yaml_event_parser", .module = event_parser_mod }},
});
const direct_conformance_options = b.addOptions();
direct_conformance_options.addOption([]const u8, "yaml_test_suite_dir", yaml_test_suite_dir);
direct_conformance_options.addOption(bool, "using_pinned_yaml_test_suite", using_pinned_yaml_test_suite);
direct_conformance_mod.addOptions("direct_conformance_options", direct_conformance_options);
const direct_conformance_tests = b.addTest(.{
.root_module = direct_conformance_mod,
.filters = test_filters,
.use_llvm = use_llvm,
});
const run_direct_conformance_tests = b.addRunArtifact(direct_conformance_tests);
const direct_conformance_step = b.step("test-direct-conformance", "Run yaml-test-suite directly through scanner and parser layers");
direct_conformance_step.dependOn(&run_direct_conformance_tests.step);
const conformance_report_mod = b.createModule(.{
.root_source_file = b.path("tools/report_conformance.zig"),
.target = target,
.optimize = optimize,
});
const conformance_report_exe = b.addExecutable(.{
.name = "yaml-conformance-report",
.root_module = conformance_report_mod,
});
const run_conformance_report = b.addRunArtifact(conformance_report_exe);
run_conformance_report.addArg(yaml_test_suite_dir);
run_conformance_report.step.dependOn(conformance_step);
run_conformance_report.step.dependOn(direct_conformance_step);
const conformance_report_step = b.step("conformance-report", "Run conformance tests and print yaml-test-suite coverage counts");
conformance_report_step.dependOn(&run_conformance_report.step);
const libfyaml_compare_step = b.step("libfyaml-compare", "Compare yaml-test-suite behavior with libfyaml fy-tool");
if (b.findProgram(&.{"python3"}, &.{})) |python3| {
if (libfyaml_fy_tool) |fy_tool| {
const run_libfyaml_compare = b.addSystemCommand(&.{ python3, "tools/compare_libfyaml.py", fy_tool, yaml_test_suite_dir });
run_libfyaml_compare.step.dependOn(conformance_report_step);
libfyaml_compare_step.dependOn(&run_libfyaml_compare.step);
} else if (b.findProgram(&.{"fy-tool"}, &.{})) |fy_tool| {
const run_libfyaml_compare = b.addSystemCommand(&.{ python3, "tools/compare_libfyaml.py", fy_tool, yaml_test_suite_dir });
run_libfyaml_compare.step.dependOn(conformance_report_step);
libfyaml_compare_step.dependOn(&run_libfyaml_compare.step);
} else |_| {
const missing_fy_tool = b.addFail("fy-tool is required for 'zig build libfyaml-compare'; pass -Dlibfyaml-fy-tool=/path/to/fy-tool or install fy-tool on PATH.");
libfyaml_compare_step.dependOn(&missing_fy_tool.step);
}
} else |_| {
const missing_python = b.addFail("python3 is required for 'zig build libfyaml-compare'.");
libfyaml_compare_step.dependOn(&missing_python.step);
}
const parser_tokens_unit_tests = addTestRunAndArtifact(b, .{
.root_source_file = "tests/unit/parser/parser_tokens_test.zig",
.target = target,
.optimize = optimize,
.imports = &.{.{ .name = "yaml_event_parser", .module = event_parser_mod }},
.filters = test_filters,
.use_llvm = use_llvm,
});
unit_step.dependOn(&parser_tokens_unit_tests.run.step);
focused_unit_coverage_artifacts[focused_unit_roots.len] = parser_tokens_unit_tests.compile;
const structure_step = b.step("test-structure", "Run repository structure checks");
const structure_test_roots = [_][]const u8{
"tests/structure/file_size_test.zig",
"tests/structure/source_size_test.zig",
"tests/structure/unit_size_test.zig",
"tests/structure/api_boundary_test.zig",
"tests/structure/docs_tooling_test.zig",
"tests/structure/module_comment_test.zig",
"tests/structure/ci_workflow_test.zig",
};
for (structure_test_roots) |root_source_file| {
const run_structure_tests = addTestRun(b, .{
.root_source_file = root_source_file,
.target = target,
.optimize = optimize,
.filters = test_filters,
.use_llvm = use_llvm,
});
structure_step.dependOn(&run_structure_tests.step);
}
const stress_mod = b.createModule(.{
.root_source_file = b.path("tests/stress/stress.zig"),
.target = target,
.optimize = optimize,
.imports = yaml_imports,
});
const stress_tests = b.addTest(.{
.root_module = stress_mod,
.filters = test_filters,
.use_llvm = use_llvm,
});
const run_stress_tests = b.addRunArtifact(stress_tests);
const stress_step = b.step("test-stress", "Run generated stress and limit tests");
stress_step.dependOn(&run_stress_tests.step);
const allocation_mod = b.createModule(.{
.root_source_file = b.path("tests/allocation/allocation_test.zig"),
.target = target,
.optimize = optimize,
.imports = yaml_imports,
});
const allocation_tests = b.addTest(.{
.root_module = allocation_mod,
.filters = test_filters,
.use_llvm = use_llvm,
});
const run_allocation_tests = b.addRunArtifact(allocation_tests);
const allocation_step = b.step("test-allocation", "Run allocator failure and cleanup tests");
allocation_step.dependOn(&run_allocation_tests.step);
const leak_step = b.step("test-leaks", "Run allocator-backed leak detection tests");
leak_step.dependOn(unit_step);
leak_step.dependOn(conformance_step);
leak_step.dependOn(direct_conformance_step);
leak_step.dependOn(stress_step);
leak_step.dependOn(allocation_step);
const extra_coverage_artifacts = focused_unit_coverage_artifacts;
const test_artifacts: build_steps.TestArtifacts = .{
.unit = unit_tests,
.conformance = conformance_tests,
.direct_conformance = direct_conformance_tests,
.stress = stress_tests,
.allocation = allocation_tests,
.extra_coverage = &extra_coverage_artifacts,
};
build_steps.addValgrindStep(b, test_artifacts);
build_steps.addCoverageStep(b, test_artifacts, .{
.target = target,
.optimize = optimize,
.threshold_percent = coverage_threshold,
});
build_steps.addDocsStep(b, yaml_mod);
const test_step = b.step("test", "Run unit, structure, conformance, direct-conformance, stress, and allocation tests");
test_step.dependOn(unit_step);
test_step.dependOn(structure_step);
test_step.dependOn(conformance_step);
test_step.dependOn(direct_conformance_step);
test_step.dependOn(stress_step);
test_step.dependOn(allocation_step);
}