@@ -25,8 +25,12 @@ pub fn build(b: *std.Build) !void {
.optimize = optimize,
});
var compiler = Compiler.init(b);
if (std.fs.cwd().access("src/fallback_html/index.html", .{})) {
const comptime_templates = Compiler.buildTemplates(b, "src/fallback_html/") catch unreachable;
compiler.addDir("src/fallback_html/");
compiler.collect() catch unreachable;
const comptime_templates = compiler.buildTemplates() catch unreachable;
// Zig build time doesn't expose it's state in a way I know how to check...
// so we yolo it like python :D
lib_unit_tests.root_module.addImport("comptime_templates", comptime_templates);
@@ -67,65 +71,115 @@ pub fn build(b: *std.Build) !void {
}
pub const Compiler = struct {
pub fn buildTemplates(b: *std.Build, srcdir: []const u8) !*std.Build.Module {
const list = try buildList(b, srcdir);
b: *std.Build,
dirs: std.ArrayList([]const u8),
files: std.ArrayList([]const u8),
collected: std.ArrayList([]const u8),
templates: ?*std.Build.Module = null,
structs: ?*std.Build.Module = null,
pub fn init(b: *std.Build) Compiler {
return .{
.b = b,
.dirs = std.ArrayList([]const u8).init(b.allocator),
.files = std.ArrayList([]const u8).init(b.allocator),
.collected = std.ArrayList([]const u8).init(b.allocator),
};
}
pub fn raze(self: Compiler) void {
for (self.dirs.items) |each| self.b.allocator.free(each);
self.dirs.deinit();
for (self.files.items) |each| self.b.allocator.free(each);
self.files.deinit();
for (self.collected.items) |each| self.b.allocator.free(each);
self.collected.deinit();
}
pub fn addDir(self: *Compiler, dir: []const u8) void {
const copy = self.b.allocator.dupe(u8, dir) catch @panic("OOM");
self.dirs.append(copy) catch @panic("OOM");
self.templates = null;
self.structs = null;
}
pub fn addFile(self: *Compiler, file: []const u8) void {
const copy = self.b.allocator.dupe(u8, file) catch @panic("OOM");
self.files.append(copy) catch @panic("OOM");
self.templates = null;
self.structs = null;
}
pub fn buildTemplates(self: *Compiler) !*std.Build.Module {
if (self.templates) |t| return t;
//std.debug.print("building for {}\n", .{self.collected.items.len});
const local_dir = std.fs.path.dirname(@src().file) orelse ".";
const compiled = b.createModule(.{
const compiled = self.b.createModule(.{
.root_source_file = .{
.cwd_relative = b.pathJoin(&.{ local_dir, "src/template/comptime.zig" }),
.cwd_relative = self.b.pathJoin(&.{ local_dir, "src/template/comptime.zig" }),
},
});
const found = b.addOptions();
found.addOption([]const []const u8, "names", list.items);
const found = self.b.addOptions();
found.addOption([]const []const u8, "names", self.collected.items);
compiled.addOptions("config", found);
for (list.items) |file| {
for (self.collected.items) |file| {
_ = compiled.addAnonymousImport(file, .{
.root_source_file = b.path(file),
.root_source_file = self.b.path(file),
});
}
self.templates = compiled;
return compiled;
}
pub fn buildStructs(b: *std.Build, srcdir: []const u8) !*std.Build.Module {
pub fn buildStructs(self: *Compiler) !*std.Build.Module {
if (self.structs) |s| return s;
//std.debug.print("building structs for {}\n", .{self.collected.items.len});
const local_dir = std.fs.path.dirname(@src().file) orelse ".";
const t_compiler = b.addExecutable(.{
const t_compiler = self.b.addExecutable(.{
.name = "template-compiler",
.root_source_file = .{
.cwd_relative = b.pathJoin(&.{ local_dir, "src/template-compiler.zig" }),
.cwd_relative = self.b.pathJoin(&.{ local_dir, "src/template-compiler.zig" }),
},
.target = b.host,
.target = self.b.host,
});
const comptime_templates = try buildTemplates(b, srcdir);
const comptime_templates = try self.buildTemplates();
t_compiler.root_module.addImport("comptime_templates", comptime_templates);
const tc_build_run = b.addRunArtifact(t_compiler);
const tc_build_run = self.b.addRunArtifact(t_compiler);
const tc_structs = tc_build_run.addOutputFileArg("compiled-structs.zig");
const tc_build_step = b.step("templates", "Compile templates down into struct");
const tc_build_step = self.b.step("templates", "Compile templates down into struct");
tc_build_step.dependOn(&tc_build_run.step);
const module = b.createModule(.{
const module = self.b.createModule(.{
.root_source_file = tc_structs,
});
self.structs = module;
return module;
}
fn buildList(b: *std.Build, srcdir: []const u8) !std.ArrayList([]const u8) {
pub fn collect(self: *Compiler) !void {
var cwd = std.fs.cwd();
var idir = cwd.openDir(srcdir, .{ .iterate = true }) catch |err| {
std.debug.print("template build error {} for srcdir {s}\n", .{ err, srcdir });
return err;
};
var list = std.ArrayList([]const u8).init(b.allocator);
errdefer list.deinit();
var itr = idir.iterate();
while (try itr.next()) |file| {
if (!std.mem.endsWith(u8, file.name, ".html")) continue;
try list.append(b.pathJoin(&[2][]const u8{ srcdir, file.name }));
}
for (self.dirs.items) |srcdir| {
var idir = cwd.openDir(srcdir, .{ .iterate = true }) catch |err| {
std.debug.print("template build error {} for srcdir {s}\n", .{ err, srcdir });
return err;
};
defer idir.close();
return list;
var itr = idir.iterate();
while (try itr.next()) |file| {
if (!std.mem.endsWith(u8, file.name, ".html")) continue;
try self.collected.append(self.b.pathJoin(&[2][]const u8{ srcdir, file.name }));
}
}
for (self.files.items) |file| {
try self.collected.append(file);
}
}
};