From 5e68974bc40efd3ec9169764a30f084dca764e22 Mon Sep 17 00:00:00 2001 From: Meili C Date: Fri, 31 Jan 2025 11:48:02 -0900 Subject: [PATCH 1/4] zig init: add compiler version to build.zig.zon by default --- lib/init/build.zig.zon | 2 +- src/main.zig | 24 +++++++++++++++++++----- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/lib/init/build.zig.zon b/lib/init/build.zig.zon index cb7229042fc8..75c325c3ad22 100644 --- a/lib/init/build.zig.zon +++ b/lib/init/build.zig.zon @@ -15,7 +15,7 @@ // This field is optional. // This is currently advisory only; Zig does not yet do anything // with this value. - //.minimum_zig_version = "0.11.0", + .minimum_zig_version = "*", // This field is optional. // Each dependency must either provide a `url` and `hash`, or a `path`. diff --git a/src/main.zig b/src/main.zig index a00261cc3083..a5f58858b315 100644 --- a/src/main.zig +++ b/src/main.zig @@ -7479,13 +7479,27 @@ const Templates = struct { const contents = templates.dir.readFileAlloc(arena, template_path, max_bytes) catch |err| { fatal("unable to read template file '{s}': {s}", .{ template_path, @errorName(err) }); }; + templates.buffer.clearRetainingCapacity(); try templates.buffer.ensureUnusedCapacity(contents.len); - for (contents) |c| { - if (c == '$') { - try templates.buffer.appendSlice(root_name); - } else { - try templates.buffer.append(c); + + if (mem.eql(u8, template_path, Package.Manifest.basename)) { + for (contents) |c| { + if (c == '$') { + try templates.buffer.appendSlice(root_name); + } else if (c == '*') { + try templates.buffer.appendSlice(build_options.version); + } else { + try templates.buffer.append(c); + } + } + } else { + for (contents) |c| { + if (c == '$') { + try templates.buffer.appendSlice(root_name); + } else { + try templates.buffer.append(c); + } } } From 79e612341b3ac502fdbe4c569ff11f2dff52eb95 Mon Sep 17 00:00:00 2001 From: Meili C Date: Sun, 2 Feb 2025 11:23:35 -0900 Subject: [PATCH 2/4] zig init: allow the use of variables in templates like $root and $version --- lib/init/build.zig | 6 ++-- lib/init/build.zig.zon | 4 +-- lib/init/src/main.zig | 7 ++-- src/main.zig | 81 +++++++++++++++++++++++++++++++++--------- 4 files changed, 72 insertions(+), 26 deletions(-) diff --git a/lib/init/build.zig b/lib/init/build.zig index 9be615ac31d0..135ecb6aa71d 100644 --- a/lib/init/build.zig +++ b/lib/init/build.zig @@ -42,14 +42,14 @@ pub fn build(b: *std.Build) void { // Modules can depend on one another using the `std.Build.Module.addImport` function. // This is what allows Zig source code to use `@import("foo")` where 'foo' is not a // file path. In this case, we set up `exe_mod` to import `lib_mod`. - exe_mod.addImport("$_lib", lib_mod); + exe_mod.addImport("$root_lib", lib_mod); // Now, we will create a static library based on the module we created above. // This creates a `std.Build.Step.Compile`, which is the build step responsible // for actually invoking the compiler. const lib = b.addLibrary(.{ .linkage = .static, - .name = "$", + .name = "$root", .root_module = lib_mod, }); @@ -61,7 +61,7 @@ pub fn build(b: *std.Build) void { // This creates another `std.Build.Step.Compile`, but this one builds an executable // rather than a static library. const exe = b.addExecutable(.{ - .name = "$", + .name = "$root", .root_module = exe_mod, }); diff --git a/lib/init/build.zig.zon b/lib/init/build.zig.zon index 75c325c3ad22..c391fa9e419d 100644 --- a/lib/init/build.zig.zon +++ b/lib/init/build.zig.zon @@ -6,7 +6,7 @@ // // It is redundant to include "zig" in this name because it is already // within the Zig package namespace. - .name = "$", + .name = "$root", // This is a [Semantic Version](https://semver.org/). // In a future version of Zig it will be used for package deduplication. @@ -15,7 +15,7 @@ // This field is optional. // This is currently advisory only; Zig does not yet do anything // with this value. - .minimum_zig_version = "*", + .minimum_zig_version = "$version", // This field is optional. // Each dependency must either provide a `url` and `hash`, or a `path`. diff --git a/lib/init/src/main.zig b/lib/init/src/main.zig index caf8f4f37a96..f2e0cbc45a1d 100644 --- a/lib/init/src/main.zig +++ b/lib/init/src/main.zig @@ -1,6 +1,9 @@ //! By convention, main.zig is where your main function lives in the case that //! you are building an executable. If you are making a library, the convention //! is to delete this file and start with root.zig instead. +const std = @import("std"); +/// This imports the separate module containing `root.zig`. Take a look in `build.zig` for details. +const lib = @import("$root_lib"); pub fn main() !void { // Prints to stderr (it's a shortcut based on `std.io.getStdErr()`) @@ -39,7 +42,3 @@ test "fuzz example" { try std.testing.fuzz(global.testOne, .{}); } -const std = @import("std"); - -/// This imports the separate module containing `root.zig`. Take a look in `build.zig` for details. -const lib = @import("$_lib"); diff --git a/src/main.zig b/src/main.zig index a5f58858b315..baf21b688ee6 100644 --- a/src/main.zig +++ b/src/main.zig @@ -4739,8 +4739,14 @@ fn cmdInit(gpa: Allocator, arena: Allocator, args: []const []const u8) !void { }; var ok_count: usize = 0; + // default replacements for templates + const replacements = &[_]Replacement{ + .{ .variable = "$root", .replacement = cwd_basename }, + .{ .variable = "$version", .replacement = build_options.version }, + }; + for (template_paths) |template_path| { - if (templates.write(arena, fs.cwd(), cwd_basename, template_path)) |_| { + if (templates.write(arena, fs.cwd(), template_path, replacements)) |_| { std.log.info("created {s}", .{template_path}); ok_count += 1; } else |err| switch (err) { @@ -7410,7 +7416,12 @@ fn loadManifest( var templates = findTemplates(gpa, arena); defer templates.deinit(); - templates.write(arena, options.dir, options.root_name, Package.Manifest.basename) catch |e| { + const replacements = &[_]Replacement{ + .{ .variable = "$root", .replacement = options.root_name }, + .{ .variable = "$version", .replacement = build_options.version }, + }; + + templates.write(arena, options.dir, Package.Manifest.basename, replacements) catch |e| { fatal("unable to write {s}: {s}", .{ Package.Manifest.basename, @errorName(e), }); @@ -7450,6 +7461,19 @@ fn loadManifest( return .{ manifest, ast }; } +/// replace variables for Zig templates +/// $root -> "project_name" +const Replacement = struct { + variable: []const u8, + replacement: []const u8, + + pub inline fn check_variable(self: *@This()) !void { + if (self.variable.len < 2) { + return error.InvalidVariable; + } + } +}; + const Templates = struct { zig_lib_directory: Cache.Directory, dir: fs.Dir, @@ -7466,8 +7490,8 @@ const Templates = struct { templates: *Templates, arena: Allocator, out_dir: fs.Dir, - root_name: []const u8, template_path: []const u8, + replacements: ?[]const Replacement, ) !void { if (fs.path.dirname(template_path)) |dirname| { out_dir.makePath(dirname) catch |err| { @@ -7483,24 +7507,47 @@ const Templates = struct { templates.buffer.clearRetainingCapacity(); try templates.buffer.ensureUnusedCapacity(contents.len); - if (mem.eql(u8, template_path, Package.Manifest.basename)) { - for (contents) |c| { - if (c == '$') { - try templates.buffer.appendSlice(root_name); - } else if (c == '*') { - try templates.buffer.appendSlice(build_options.version); - } else { - try templates.buffer.append(c); - } - } - } else { - for (contents) |c| { - if (c == '$') { - try templates.buffer.appendSlice(root_name); + var iterator = mem.splitScalar(u8, contents, '\n'); + + // replace variables like $root and $version with the project name + // and zig compiler version respectively + while (iterator.next()) |line| { + + var i: usize = 0; + while (i < line.len) : (i += 1) { + const c = line[i]; + + if (replacements) |replace_items| { + if (c == '$') { + var found: bool = false; + + for (replace_items) |replacement| { + try replacement.check_variable(); + + if (line.len - i < replacement.variable.len) { + continue; + } + + // found a match, break out + if (mem.eql(u8, replacement.variable, line[i .. i + replacement.variable.len])) { + try templates.buffer.appendSlice(replacement.replacement); + i += replacement.variable.len - 1; + found = true; + break; + } + } + + if (!found) try templates.buffer.append(c); + } else { + // if we make it out here, no replacement was found, and we write out the literal '$' + try templates.buffer.append(c); + } } else { try templates.buffer.append(c); } } + + try templates.buffer.append('\n'); } return out_dir.writeFile(.{ From 3d427a1f3d984055385c0a5f4646db58c5b00315 Mon Sep 17 00:00:00 2001 From: Meili C Date: Sun, 2 Feb 2025 11:30:14 -0900 Subject: [PATCH 3/4] zig init: allow the use of variables in templates like $root and $version --- src/main.zig | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/main.zig b/src/main.zig index baf21b688ee6..84fcb1d664e7 100644 --- a/src/main.zig +++ b/src/main.zig @@ -7466,12 +7466,6 @@ fn loadManifest( const Replacement = struct { variable: []const u8, replacement: []const u8, - - pub inline fn check_variable(self: *@This()) !void { - if (self.variable.len < 2) { - return error.InvalidVariable; - } - } }; const Templates = struct { @@ -7512,7 +7506,6 @@ const Templates = struct { // replace variables like $root and $version with the project name // and zig compiler version respectively while (iterator.next()) |line| { - var i: usize = 0; while (i < line.len) : (i += 1) { const c = line[i]; @@ -7522,7 +7515,9 @@ const Templates = struct { var found: bool = false; for (replace_items) |replacement| { - try replacement.check_variable(); + if (replacement.variable.len < 2) { + return error.InvalidVariable; + } if (line.len - i < replacement.variable.len) { continue; From 986565b4afef6eea3d288a04a653dd78f5628858 Mon Sep 17 00:00:00 2001 From: Meili C Date: Thu, 6 Feb 2025 10:12:44 -0900 Subject: [PATCH 4/4] zig init templates: run zig fmt such a silly mistake lol --- lib/init/src/main.zig | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/init/src/main.zig b/lib/init/src/main.zig index f2e0cbc45a1d..89bf5da4d103 100644 --- a/lib/init/src/main.zig +++ b/lib/init/src/main.zig @@ -41,4 +41,3 @@ test "fuzz example" { }; try std.testing.fuzz(global.testOne, .{}); } -