#using `embedFile` on an artifact generated by build.zig

1 messages · Page 1 of 1 (latest)

vast lily
#

I'm writing a web backend, and I want to serve some JS program that is transpiled from another language (think typescript). The buildscript invokes the transpiler, but where should it put the generated JS code and, more importantly, how do I get that embedded into the server?

#

This is especially a problem because @embedFile doesn't seem to accept paths outside of src/ (and thats not exactly a good place for generated files :P)

junior island
#

wrote this up in 10 minutes, to generate a file, direct the transpilation output to it, and make you able to get the output as a FileSource:

const TranspileStep = struct {
    step: std.build.Step,
    builder: *std.build.Builder,
    out_name: []const u8,
    transpile_cmd: *std.build.RunStep,
    generated_file: std.build.GeneratedFile,
    make_output_step: *std.build.WriteFileStep,

    pub fn create(
        b: *std.build.Builder,
        out_name: []const u8,
        inputs: []const std.build.FileSource,
    ) *TranspileStep {
        const self = b.allocator.create(TranspileStep) catch unreachable;
        self.* = .{
            .step = std.build.Step.init(.custom, "transpile files", b.allocator, make),
            .builder = b,
            .out_name = out_name,
            .transpile_cmd = b.addSystemCommand(&.{"tsc"}),
            .generated_file = .{ .step = &self.step },
            .make_output_step = b.addWriteFile(out_name, ""),
        };
        for (inputs) |input| self.transpile_cmd.addFileSourceArg(input);

        // Step 1: generate file 'out_name'
        // Step 2: run tsc, with '--outFile path/to/out_name'
        // Step 3: this step, make generated file available

        self.transpile_cmd.addArg("--outFile");
        self.transpile_cmd.addFileSourceArg(self.make_output_step.getFileSource(out_name).?);
        self.step.dependOn(&self.transpile_cmd.step);

        return self;
    }

    pub fn getOutputFileSource(self: *TranspileStep) std.build.FileSource {
        return std.build.FileSource{
            .generated = &self.generated_file,
        };
    }

    fn make(step: *std.build.Step) anyerror!void {
        const self = @fieldParentPtr(TranspileStep, "step", step);
        self.generated_file.path = self.make_output_step.getFileSource(self.out_name).?.getPath(self.builder);
    }
};
vast lily
#

neat, how do i embed that file source then?

junior island
#

from there, you could do something like

const transpile = TranspileStep.create(b, "output.js", &.{ .{ .path = "input.ts" } });
const options = b.addOptions();
options.addOptionFileSource("output_path", options.getOutputFileSource());
options.contents.writer().print(
    \\pub const output = @embedFile(output_path);
    \\
, .{}) catch unreachable;

and then add options to your LibExeObjStep, which could @import it and then access the output decl

vast lily
#

that is cursed, but i guess if it works 😛

junior island
#

yee

#

waiting on RunStep to be able to generate files properly

vast lily
#

just got around to implementing this, just wanted to note that i had to put the transpiler output into zig-cache/options/ so that its in the package path of the options file.

vast lily