master
 1const std = @import("std");
 2
 3pub fn build(b: *std.Build) void {
 4    const target = b.standardTargetOptions(.{});
 5
 6    const test_step = b.step("test", "Test it");
 7    b.default_step = test_step;
 8
 9    const touch_src = b.path("touch.zig");
10
11    const touch = b.addExecutable(.{
12        .name = "touch",
13        .root_module = b.createModule(.{
14            .root_source_file = touch_src,
15            .optimize = .Debug,
16            .target = target,
17        }),
18    });
19    const generated = b.addRunArtifact(touch).addOutputFileArg("subdir" ++ std.fs.path.sep_str ++ "generated.txt");
20
21    const exists_in = b.addExecutable(.{
22        .name = "exists_in",
23        .root_module = b.createModule(.{
24            .root_source_file = b.path("exists_in.zig"),
25            .optimize = .Debug,
26            .target = target,
27        }),
28    });
29
30    const has_basename = b.addExecutable(.{
31        .name = "has_basename",
32        .root_module = b.createModule(.{
33            .root_source_file = b.path("has_basename.zig"),
34            .optimize = .Debug,
35            .target = target,
36        }),
37    });
38
39    // Known path:
40    addTestRun(test_step, exists_in, touch_src.dirname(), &.{"touch.zig"});
41
42    // Generated file:
43    addTestRun(test_step, exists_in, generated.dirname(), &.{"generated.txt"});
44
45    // Generated file multiple levels:
46    addTestRun(test_step, exists_in, generated.dirname().dirname(), &.{
47        "subdir" ++ std.fs.path.sep_str ++ "generated.txt",
48    });
49
50    // Cache root:
51    const cache_dir = b.cache_root.path orelse
52        (b.cache_root.join(b.allocator, &.{"."}) catch @panic("OOM"));
53    addTestRun(
54        test_step,
55        has_basename,
56        generated.dirname().dirname().dirname().dirname(),
57        &.{std.fs.path.basename(cache_dir)},
58    );
59
60    // Absolute path:
61    const abs_path = setup_abspath: {
62        const temp_dir = b.makeTempPath();
63
64        var dir = std.fs.cwd().openDir(temp_dir, .{}) catch @panic("failed to open temp dir");
65        defer dir.close();
66
67        var file = dir.createFile("foo.txt", .{}) catch @panic("failed to create file");
68        file.close();
69
70        break :setup_abspath std.Build.LazyPath{ .cwd_relative = temp_dir };
71    };
72    addTestRun(test_step, exists_in, abs_path, &.{"foo.txt"});
73}
74
75// Runs exe with the parameters [dirname, args...].
76// Expects the exit code to be 0.
77fn addTestRun(
78    test_step: *std.Build.Step,
79    exe: *std.Build.Step.Compile,
80    dirname: std.Build.LazyPath,
81    args: []const []const u8,
82) void {
83    const run = test_step.owner.addRunArtifact(exe);
84    run.addDirectoryArg(dirname);
85    run.addArgs(args);
86    run.expectExitCode(0);
87    test_step.dependOn(&run.step);
88}