diff --git a/docs/zig.mod.md b/docs/zig.mod.md index d94a5145bd8571a968c77c4ee2963c135f25aa26..a61d71773f48fb0f060461afc67f308d2749bbb1 100644 --- a/docs/zig.mod.md +++ b/docs/zig.mod.md @@ -30,6 +30,14 @@ This is a list of [`clang`](https://clang.llvm.org/docs/UsersManual.html#command - Type: `[]string` This is a list of relative paths to C source files to compile along with this project. This will be required if you use Zig's [`@cImport`](https://ziglang.org/documentation/master/#cImport), `extern`, etc. +### `files` +- Type: `[]string` +This accepts a list of local directories to embed static assets. These files will be provided through a `self/files` package to `@import(main)`. + +### `root_files` +- Type: `[]string` +This accepts a list of local directories to embed static assets. These files will be provided through a `self/files` package to `@import("root")`. + ### `dependencies` - Type: `[]Dep` This is a list of `Dep` objects. `Dep` objects are how you include the other people's code in your project. See the `Dep` documentation below to learn more about the attributes available here. diff --git a/src/common.zig b/src/common.zig index 9950545e96b710b35b738ac3db56639b308b2255..f5705e6e4d417a4e52704003789b83b342c3f062 100644 --- a/src/common.zig +++ b/src/common.zig @@ -2,6 +2,7 @@ const std = @import("std"); const gpa = std.heap.c_allocator; const u = @import("./util/index.zig"); +const yaml = @import("./util/yaml.zig"); // // @@ -15,6 +16,10 @@ pub fn collect_deps_deep(dir: []const u8, mpath: []const u8, options: CollectOpt const m = try u.ModFile.init(gpa, mpath); const moduledeps = &std.ArrayList(u.Module).init(gpa); defer moduledeps.deinit(); + try std.fs.cwd().makePath(".zigmod/deps/files"); + if (m.root_files.len > 0) { + try add_files_package("root", m.root_files, moduledeps, m.name); + } try moduledeps.append(try collect_deps(dir, mpath, options)); for (m.devdeps) |d| { if (!d.is_for_this()) { @@ -42,6 +47,9 @@ pub fn collect_deps(dir: []const u8, mpath: []const u8, options: CollectOptions) const m = try u.ModFile.init(gpa, mpath); const moduledeps = &std.ArrayList(u.Module).init(gpa); defer moduledeps.deinit(); + if (m.files.len > 0) { + try add_files_package(m.id, m.files, moduledeps, m.name); + } for (m.deps) |d| { if (!d.is_for_this()) { continue; @@ -219,3 +227,66 @@ fn get_module_from_dep(list: *std.ArrayList(u.Module), d: u.Dep, dir: []const u8 }, } } + +fn add_files_package(pkg_name: []const u8, dirs: []const []const u8, list: *std.ArrayList(u.Module), parent_name: []const u8) !void { + const destination = ".zigmod/deps/files"; + const fname = try std.mem.join(gpa, "", &.{ pkg_name, ".zig" }); + + const map = &std.StringHashMap([]const u8).init(gpa); + defer map.deinit(); + + for (dirs) |dir_path| { + var walker = try std.fs.walkPath(gpa, dir_path); + while (try walker.next()) |p| { + if (p.kind == .Directory) { + continue; + } + const path = try std.mem.dupe(gpa, u8, p.path); + try map.put(path[dir_path.len..], path); + } + } + + const rff = try (try std.fs.cwd().openDir(destination, .{})).createFile(fname, .{}); + defer rff.close(); + const w = rff.writer(); + try w.writeAll( + \\const std = @import("std"); + \\ + \\const files = std.ComptimeStringMap([]const u8, .{ + \\ + ); + var iter = map.iterator(); + while (iter.next()) |item| { + try w.print(" .{{ .@\"0\" = \"{}\", .@\"1\" = @embedFile(\"./../../../{}\") }},\n", .{ std.zig.fmtEscapes(item.key_ptr.*), std.zig.fmtEscapes(item.value_ptr.*) }); + } + try w.writeAll("\n"); + try w.writeAll( + \\}); + \\ + \\pub fn open(comptime path: []const u8) ?[]const u8 { + \\ if (path.len == 0) return null; + \\ if (path[0] != '/') return null; + \\ return files.get(path); + \\} + \\ + ); + + const d: u.Dep = .{ + .type = .local, + .path = "files", + .id = "", + .name = "self/files", + .main = fname, + .version = "absolute", + .c_include_dirs = &.{}, + .c_source_flags = &.{}, + .c_source_files = &.{}, + .only_os = &.{}, + .except_os = &.{}, + .yaml = null, + }; + try get_module_from_dep(list, d, destination, parent_name, .{ + .log = false, + .update = false, + }); +} diff --git a/src/util/modfile.zig b/src/util/modfile.zig index 9f516a40f3c40239fe51efec68f07aa58e050550..f2df16324d1e48e34b013228eb5ab508abe286d5 100644 --- a/src/util/modfile.zig +++ b/src/util/modfile.zig @@ -23,6 +23,8 @@ pub const ModFile = struct { deps: []u.Dep, yaml: yaml.Mapping, devdeps: []u.Dep, + root_files: [][]const u8, + files: [][]const u8, pub fn init(alloc: *std.mem.Allocator, fpath: []const u8) !Self { // @@ -42,6 +44,7 @@ pub const ModFile = struct { if (std.mem.indexOf(u8, name, "/")) |_| { u.assert(false, "name may not contain any '/'", .{}); } + const dep_list = try dep_list_by_name(alloc, mapping, "dependencies"); defer dep_list.deinit(); const devdep_list = try dep_list_by_name(alloc, mapping, "dev_dependencies"); @@ -58,6 +61,8 @@ pub const ModFile = struct { .deps = dep_list.toOwnedSlice(), .yaml = mapping, .devdeps = devdep_list.toOwnedSlice(), + .root_files = try mapping.get_string_array(alloc, "root_files"), + .files = try mapping.get_string_array(alloc, "files"), }; } @@ -72,6 +77,7 @@ pub const ModFile = struct { var version: ?[]const u8 = null; var name = item.mapping.get_string("name"); var main = item.mapping.get_string("main"); + if (item.mapping.get("src")) |val| { var src_iter = std.mem.tokenize(val.string, " "); dtype = src_iter.next().?;