Hi. I’m trying to use Ziggy and zmime dependencies in the build time. My goal is reading the user configuration file with Ziggy and detecting mime type of the frontend path that i got from Ziggy with zmime and writing the result to a file.
I tried something. But my code has some problems.
src/services/assets.zig:23:31: error: root source file struct 'build' has no member named 'detectFileInfoByFile'
const info = try zmime.detectFileInfoByFile(file, name);
~~~~~^~~~~~~~~~~~~~~~~~~~~
zig-pkg/zmime-0.3.0-Mse7gaeBAAAWfPAQjBEKQj7qBVofDgLHESoYxxsk_nI6/build.zig:1:1: note: struct declared here
const std = @import("std");
^~~~~
referenced by:
setup: src/build_helper.zig:9:69
build: build.zig:64:25
6 reference(s) hidden; use '-freference-trace=8' to see all references
src/types/config.zig:113:25: error: root source file struct 'build' has no member named 'Deserializer'
var meta: ziggy.Deserializer.Meta = .init;
^~~~~~~~~~~~
zig-pkg/ziggy-0.2.0-kTg8v5XyBwAL-S3Ci2S2QXYbe0m30-xUIbblJHdFFkKd/build.zig:1:1: note: struct declared here
const std = @import("std");
^~~~~
Probably the error: root source file struct 'build' has no member named 'detectFileInfoByFile' error occurring because theres no export in zmime and ziggy inside build thing or something. i dont know.
here is my files:
build.zig
const std = @import("std");
const assets_service = @import("src/services/assets.zig");
pub fn build(b: *std.Build) void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
const ziggy = b.dependency("ziggy", .{
.target = target,
.optimize = optimize,
});
const zmime = b.dependency("zmime", .{
.target = target,
.optimize = optimize,
});
const solenoid_build = @import("src/build_helper.zig");
const mod = b.addModule("solenoid", .{
.root_source_file = b.path("src/root.zig"),
.target = target,
.imports = &.{
.{ .name = "ziggy", .module = ziggy.module("ziggy") },
.{ .name = "zmime", .module = zmime.module("zmime") },
},
});
const hello = b.addExecutable(.{
.name = "hello_world",
.root_module = b.createModule(.{
.root_source_file = b.path("examples/hello-world/backend/src/main.zig"),
.target = target,
.optimize = optimize,
.imports = &.{
.{ .name = "solenoid", .module = mod },
},
}),
});
solenoid_build.setup(b, hello) catch |err| {
std.debug.print("Solenoid build error: {}\n", .{err});
};
b.installArtifact(hello);
const run_cmd = b.addRunArtifact(hello);
run_cmd.step.dependOn(b.getInstallStep());
run_cmd.addPassthruArgs();
const run_step = b.step("run", "Run hello-world example");
run_step.dependOn(&run_cmd.step);
}
src/build_helper.zig
const std = @import("std");
const assets_service = @import("services/assets.zig");
const Config = @import("types/config.zig").Config;
pub fn setup(b: *std.Build, exe: *std.Build.Step.Compile) !void {
const config, _ = Config.load(b.graph.io, b.graph.arena, .{ .auto = true });
if (config.build.?.dir) |assets_path| {
const assets_mod = try assets_service.generateFrontendAssets(b, assets_path);
exe.root_module.addImport("assets", assets_mod);
}
}
src/services/assets.zig
const std = @import("std");
const zmime = @import("zmime");
pub fn generateFrontendAssets(b: *std.Build, assets_dir: []const u8) !*std.Build.Module {
var filenames = try std.ArrayList([]const u8).initCapacity(b.allocator, 0);
var dir = try b.root.openDir(b.graph.io, assets_dir, .{ .iterate = true });
defer dir.close(b.graph.io);
var it = dir.iterate();
while (try it.next(b.graph.io)) |entry| {
if (entry.kind == .file) try filenames.append(b.allocator, try b.allocator.dupe(u8, entry.name));
}
var code = try std.ArrayList(u8).initCapacity(b.allocator, 0);
try code.appendSlice(b.allocator, "pub const assets = [_]Asset{\n");
for (filenames.items) |name| {
const full_path = b.fmt("{s}/{s}", .{ assets_dir, name });
const file = try b.root.openFile(b.graph.io, full_path, .{});
defer file.close();
const info = try zmime.detectFileInfoByFile(file, name);
const mime = zmime.mimeToString(info.mime);
try code.appendSlice(b.allocator, b.fmt("\n .{ .path = \"/{s}\", .data = @embedFile(\"{s}\"), .mime = \"{s}\" },", .{ name, full_path, mime }));
}
try code.appendSlice(b.allocator, "\n};\n");
const write_files_step = b.addWriteFiles();
const generated_file = write_files_step.add("assets.zig", code.items);
return b.createModule(.{ .root_source_file = generated_file });
}
src/types/config.zig (only needed area of code)
var meta: ziggy.Deserializer.Meta = .init;
const cfg = ziggy.deserializeLeaky(Config, arena, src, &meta, .{}) catch |err| {
if (err == error.OutOfMemory) fatal.oom();
fatal.msg(
\\Error while loading the Solenoid config file:
\\
\\{f}
\\
\\
, .{meta.reportErrorsFmt(arena, .{}, config_file_basename, src, err)});
};
cfg.validate();
I read this post and tried its solution.
I dont wanna hardcode the path instead of reading config file with Ziggy. And using basical if-else chain for detecting mimetype. Hope theres a way for it.
Zig version: v0.17.0-dev.2320+1e770dbef