#iterate over files in a directory in build.zig

1 messages · Page 1 of 1 (latest)

harsh goblet
#

Hello.

I cannot figure out the API for LazyPath and how they'd interact with std.fs

I have a path for a directory, and I would like to iterate over every file in that directory and pass it to exe_mod. I know I can create a RunArtifact and whatnot. it is is the iteration I am stuck on.

harsh goblet
#

sure but what would be the first argument

#

how do I go from LazyPath to Dir

valid pollen
#

Then open it as a dir

harsh goblet
#

getPath or getPath3?

valid pollen
#

getPath3 will be removed

#

Wait

#

Sorry

harsh goblet
#

hm? getPath is the one it says Deprecated

valid pollen
#

getPath will be removed

#

Use 3 yeah

harsh goblet
#

i got it mostly working but I still a couple of problems

#
    { // `zig build eye` command
        const eye_step = b.step("eye", "eye test all the files in a given directory");
        const args: []const []const u8 = b.args orelse
            &.{ "./c_files/", "--lex" }; // least harmful default;

        const path = b.path(args[0]).getPath3(b, null);

        const dir = try path.openDir("", .{ .access_sub_paths = false });
        var walker = try dir.walk(b.allocator);
        defer walker.deinit();

        while (try walker.next()) |entry| {
            if (entry.kind == .file) {
                const file = b.pathJoin(&.{ path.root_dir.path.?, path.basename(), entry.path });

                const bat = b.addSystemCommand(&.{ "bat", file });

                const run_cmd = b.addRunArtifact(exe);
                run_cmd.addArg(file);
                run_cmd.addArgs(args[1..]);

                run_cmd.step.dependOn(&bat.step);
                eye_step.dependOn(&run_cmd.step);
            }
        }
    }```
#

the first problem is that the output for bat and the output for the run steps are not happening next to each other.

#

The second problem is that the dir walk seems to happen regardless of step and i'd like to only run if that's the step I am invoking

#

@valid pollen sorry for ping but do you have any tips?

valid pollen
harsh goblet
#

?

valid pollen
#

custom build step

#

I do it here

#

it creates a step called CompileCommandStep

#

so it only runs the code when the step is depended on

#

makeCdb

harsh goblet
#

so basically just pass a function that takes a *std.Build.Step to a bare step's makeFn ?

#

@valid pollen so how to make sure the bat command and the run command run sequentially ?

valid pollen
#

make run depend on the bat

harsh goblet
#

it does

#

hmm

#

i guess i can make bat depend on the previous run

#

@valid pollen do you just add step.dependOn at the end there or not? ```ts
fn make_eye_step(step: *std.Build.Step, _: std.Build.Step.MakeOptions) !void {
const b = step.owner;
const closure: *const Closure = @fieldParentPtr("step", step);
const exe = closure.exe;

const args: []const []const u8 = b.args orelse
    &.{ "./c_files/", "--lex" }; // least harmful default;

const path = b.path(args[0]).getPath3(b, null);

const dir = try path.openDir("", .{ .access_sub_paths = false });
var walker = try dir.walk(b.allocator);
defer walker.deinit();

while (try walker.next()) |entry| {
    if (entry.kind == .file and std.mem.endsWith(u8, entry.basename, ".c")) {
        const file = b.pathJoin(&.{ path.root_dir.path.?, path.basename(), entry.path });

        const bat = b.addSystemCommand(&.{ "bat", file });

        const run_cmd = b.addRunArtifact(exe);
        run_cmd.addArg(file);
        run_cmd.addArgs(args[1..]);

        run_cmd.step.dependOn(&bat.step);
        step.dependOn(&run_cmd.step); // <-- here
    }
}

}```

#

build crashed 😮

harsh goblet
#

ok i fixed the crashing part

#

but now i dont see any output from the commands and i can't tell if they run or not

#
    { // `zig build eye` command
        const eye_step = b.step("eye", "eye test all the files in a given directory");

        var closure = b.allocator.create(Closure) catch unreachable;
        closure.* = .{ .exe = exe, .step = std.Build.Step.init(.{
            .id = .custom,
            .name = "inner_eye",
            .makeFn = make_eye_step,
            .owner = b,
        }) };

        eye_step.dependOn(&closure.step);
    }
}

const Closure = struct {
    exe: *std.Build.Step.Compile,
    step: std.Build.Step,
};

fn make_eye_step(step: *std.Build.Step, _: std.Build.Step.MakeOptions) !void {
    const b = step.owner;
    const closure: *const Closure = @fieldParentPtr("step", step);
    const exe = closure.exe;

    const args: []const []const u8 = b.args orelse
        &.{ "./c_files/", "--lex" }; // least harmful default;

    const path = b.path(args[0]).getPath3(b, null);

    const dir = try path.openDir("", .{ .access_sub_paths = false });
    var walker = try dir.walk(b.allocator);
    defer walker.deinit();

    var prev_run_cmd: ?*std.Build.Step.Run = null;

    while (try walker.next()) |entry| {
        if (entry.kind == .file and std.mem.endsWith(u8, entry.basename, ".c")) {
            const file = b.pathJoin(&.{ path.root_dir.path.?, path.basename(), entry.path });

            const bat = b.addSystemCommand(&.{ "bat", file });
            bat.stdio = .inherit;

            if (prev_run_cmd) |c|
                bat.step.dependOn(&c.step);

            const run_cmd = b.addRunArtifact(exe);
            run_cmd.addArg(file);
            run_cmd.addArgs(args[1..]);
            run_cmd.stdio = .inherit;

            run_cmd.step.dependOn(&bat.step);
            prev_run_cmd = run_cmd;
        }
    }

    step.dependOn(&prev_run_cmd.?.step);
}```
vapid shuttle
harsh goblet
# vapid shuttle to run them all sequentially, you could keep a "previous run step" then dependOn...

yeah i figured as much, but the commands arent running at all when they are steps inside that function. std.debug.print prints fine .. a better writeup is here

valid pollen
valid pollen
harsh goblet
#

Good luck with the exam i hope you scored well.