diff --git a/CopyStep.zig b/CopyStep.zig deleted file mode 100644 index f0fc604..0000000 --- a/CopyStep.zig +++ /dev/null @@ -1,36 +0,0 @@ -const std = @import("std"); -const CopyStep = @This(); - -step: std.build.Step, -builder: *std.build.Builder, -from_path: ?[]const u8 = null, -to_path: ?[]const u8 = null, - -pub fn create( - b: *std.build.Builder, - from_path_relative: []const u8, - to_path_relative: []const u8, -) *CopyStep { - var result = b.allocator.create(CopyStep) catch @panic("memory"); - result.* = CopyStep{ - .step = std.build.Step.init(.custom, "copy a file", b.allocator, make), - .builder = b, - .from_path = std.fs.path.resolve(b.allocator, &[_][]const u8{ - b.build_root, - from_path_relative, - }) catch @panic("memory"), - .to_path = std.fs.path.resolve(b.allocator, &[_][]const u8{ - b.build_root, - to_path_relative, - }) catch @panic("memory"), - }; - return result; -} - -fn make(step: *std.build.Step) !void { - const self = @fieldParentPtr(CopyStep, "step", step); - std.fs.copyFileAbsolute(self.from_path.?, self.to_path.?, .{}) catch |e| { - std.log.err("Error copying {s} to {s}: {}", .{ self.from_path.?, self.to_path.?, e }); - std.os.exit(1); - }; -} diff --git a/GitRepoStep.zig b/GitRepoStep.zig deleted file mode 100644 index 20c365d..0000000 --- a/GitRepoStep.zig +++ /dev/null @@ -1,218 +0,0 @@ -//! Publish Date: 2021_10_17 -//! This file is hosted at github.com/marler8997/zig-build-repos and is meant to be copied -//! to projects that use it. -const std = @import("std"); -const GitRepoStep = @This(); - -pub const ShaCheck = enum { - none, - warn, - err, - - pub fn reportFail(self: ShaCheck, comptime fmt: []const u8, args: anytype) void { - switch (self) { - .none => unreachable, - .warn => std.log.warn(fmt, args), - .err => { - std.log.err(fmt, args); - std.os.exit(0xff); - }, - } - } -}; - -step: std.build.Step, -builder: *std.build.Builder, -url: []const u8, -name: []const u8, -branch: ?[]const u8 = null, -sha: []const u8, -path: ?[]const u8 = null, -sha_check: ShaCheck = .warn, -fetch_enabled: bool, - -var cached_default_fetch_option: ?bool = null; -pub fn defaultFetchOption(b: *std.build.Builder) bool { - if (cached_default_fetch_option) |_| {} else { - cached_default_fetch_option = if (b.option(bool, "fetch", "automatically fetch network resources")) |o| o else false; - } - return cached_default_fetch_option.?; -} - -pub fn create(b: *std.build.Builder, opt: struct { - url: []const u8, - branch: ?[]const u8 = null, - sha: []const u8, - path: ?[]const u8 = null, - sha_check: ShaCheck = .warn, - fetch_enabled: ?bool = null, -}) *GitRepoStep { - var result = b.allocator.create(GitRepoStep) catch @panic("memory"); - const name = std.fs.path.basename(opt.url); - result.* = GitRepoStep{ - .step = std.build.Step.init(.custom, "clone a git repository", b.allocator, make), - .builder = b, - .url = opt.url, - .name = name, - .branch = opt.branch, - .sha = opt.sha, - .path = if (opt.path) |p| (b.allocator.dupe(u8, p) catch @panic("memory")) else (std.fs.path.resolve(b.allocator, &[_][]const u8{ - b.build_root, - "libs", - name, - })) catch @panic("memory"), - .sha_check = opt.sha_check, - .fetch_enabled = if (opt.fetch_enabled) |fe| fe else defaultFetchOption(b), - }; - return result; -} - -// TODO: this should be included in std.build, it helps find bugs in build files -fn hasDependency(step: *const std.build.Step, dep_candidate: *const std.build.Step) bool { - for (step.dependencies.items) |dep| { - // TODO: should probably use step.loop_flag to prevent infinite recursion - // when a circular reference is encountered, or maybe keep track of - // the steps encounterd with a hash set - if (dep == dep_candidate or hasDependency(dep, dep_candidate)) - return true; - } - return false; -} - -fn make(step: *std.build.Step) !void { - const self = @fieldParentPtr(GitRepoStep, "step", step); - - std.fs.accessAbsolute(self.path.?, .{ .mode = .read_only }) catch { - const branch_args = if (self.branch) |b| &[2][]const u8{ " -b ", b } else &[2][]const u8{ "", "" }; - if (!self.fetch_enabled) { - std.debug.print("Error: git repository '{s}' does not exist\n", .{self.path.?}); - std.debug.print(" Use -Dfetch to download it automatically, or run the following to clone it:\n", .{}); - std.debug.print(" git clone {s}{s}{s} {s} && git -C {3s} checkout {s} -b for_ziget\n", .{ self.url, branch_args[0], branch_args[1], self.path.?, self.sha }); - std.os.exit(1); - } - - { - var args = std.ArrayList([]const u8).init(self.builder.allocator); - defer args.deinit(); - try args.append("git"); - try args.append("clone"); - // This is a bad idea, because we really want to get to the correct - // revision before we go updating submodules - // try args.append("--recurse-submodules"); - try args.append(self.url); - // TODO: clone it to a temporary location in case of failure - // also, remove that temporary location before running - try args.append(self.path.?); - if (self.branch) |branch| { - try args.append("-b"); - try args.append(branch); - } - try run(self.builder, args.items); - } - try run(self.builder, &[_][]const u8{ - "git", - "-C", - self.path.?, - "checkout", - self.sha, - "-b", - "fordep", - }); - - // Now that we're on the correct revision, we can update submodules - try run(self.builder, &[_][]const u8{ - "git", - "-C", - self.path.?, - "submodule", - "update", - "--init", - "--recursive", - }); - }; - - try self.checkSha(); -} - -fn checkSha(self: GitRepoStep) !void { - if (self.sha_check == .none) - return; - - const result: union(enum) { failed: anyerror, output: []const u8 } = blk: { - const result = std.ChildProcess.exec(.{ - .allocator = self.builder.allocator, - .argv = &[_][]const u8{ - "git", - "-C", - self.path.?, - "rev-parse", - "HEAD", - }, - .cwd = self.builder.build_root, - .env_map = self.builder.env_map, - }) catch |e| break :blk .{ .failed = e }; - try std.io.getStdErr().writer().writeAll(result.stderr); - switch (result.term) { - .Exited => |code| { - if (code == 0) break :blk .{ .output = result.stdout }; - break :blk .{ .failed = error.GitProcessNonZeroExit }; - }, - .Signal => break :blk .{ .failed = error.GitProcessFailedWithSignal }, - .Stopped => break :blk .{ .failed = error.GitProcessWasStopped }, - .Unknown => break :blk .{ .failed = error.GitProcessFailed }, - } - }; - switch (result) { - .failed => |err| { - return self.sha_check.reportFail("failed to retreive sha for repository '{s}': {s}", .{ self.name, @errorName(err) }); - }, - .output => |output| { - if (!std.mem.eql(u8, std.mem.trimRight(u8, output, "\n\r"), self.sha)) { - return self.sha_check.reportFail("repository '{s}' sha does not match\nexpected: {s}\nactual : {s}\n", .{ self.name, self.sha, output }); - } - }, - } -} - -fn run(builder: *std.build.Builder, argv: []const []const u8) !void { - { - var msg = std.ArrayList(u8).init(builder.allocator); - defer msg.deinit(); - const writer = msg.writer(); - var prefix: []const u8 = ""; - for (argv) |arg| { - try writer.print("{s}\"{s}\"", .{ prefix, arg }); - prefix = " "; - } - std.log.debug("[RUN] {s}", .{msg.items}); - } - - var child = std.ChildProcess.init(argv, builder.allocator); - - child.stdin_behavior = .Ignore; - child.stdout_behavior = .Inherit; - child.stderr_behavior = .Inherit; - child.cwd = builder.build_root; - child.env_map = builder.env_map; - - try child.spawn(); - const result = try child.wait(); - switch (result) { - .Exited => |code| if (code != 0) { - std.log.err("git clone failed with exit code {}", .{code}); - std.os.exit(0xff); - }, - else => { - std.log.err("git clone failed with: {}", .{result}); - std.os.exit(0xff); - }, - } -} - -// Get's the repository path and also verifies that the step requesting the path -// is dependent on this step. -pub fn getPath(self: *const GitRepoStep, who_wants_to_know: *const std.build.Step) []const u8 { - if (!hasDependency(who_wants_to_know, &self.step)) - @panic("a step called GitRepoStep.getPath but has not added it as a dependency"); - return self.path; -} diff --git a/VersionStep.zig b/VersionStep.zig deleted file mode 100644 index 9344ca4..0000000 --- a/VersionStep.zig +++ /dev/null @@ -1,229 +0,0 @@ -//! Publish Date: 2022-01-12 -//! This file is hosted at ??? and is meant to be copied -//! to projects that use it. Sample usage: -//! -//! const version = VersionStep.create(b, null); -//! exe.step.dependOn(&version.step); - -const std = @import("std"); -const Step = @This(); - -step: std.build.Step, -builder: *std.build.Builder, -version_path: []const u8, - -// Creates a step that will add the git version info in a file in src/ -// so it can be consumed by additional code. If version_path is not specified, -// it will default to "git_version.zig". This should be part of .gitignore -pub fn create(b: *std.build.Builder, version_path: ?[]const u8) *Step { - var result = b.allocator.create(Step) catch @panic("memory"); - result.* = Step{ - .step = std.build.Step.init(.custom, "create version file", b.allocator, make), - .builder = b, - .version_path = std.fs.path.resolve(b.allocator, &[_][]const u8{ - b.build_root, - "src", - version_path orelse "git_version.zig", - }) catch @panic("memory"), - }; - return result; -} - -fn make(step: *std.build.Step) !void { - const self = @fieldParentPtr(Step, "step", step); - const file = try std.fs.createFileAbsolute(self.version_path, .{}); - defer file.close(); - const version = try getGitVersion( - self.builder.allocator, - self.builder.build_root, - self.builder.env_map, - ); - defer version.deinit(); - try file.writer().print( - \\pub const hash = "{s}"; - \\pub const abbreviated_hash = "{s}"; - \\pub const commit_date = "{s}"; - \\pub const branch = "{s}"; - \\pub const dirty = {}; - \\pub const pretty_version = "{s}"; - , .{ - version.hash, - version.abbreviated_hash, - version.commit_date, - version.branch, - version.dirty, - version.pretty_version, - }); -} - -const GitVersion = struct { - hash: []const u8, - abbreviated_hash: []const u8, - commit_date: []const u8, - branch: []const u8, - dirty: bool, - pretty_version: []const u8, - - allocator: std.mem.Allocator, - - const Self = @This(); - - pub fn deinit(self: Self) void { - self.allocator.free(self.hash); - self.allocator.free(self.abbreviated_hash); - self.allocator.free(self.commit_date); - self.allocator.free(self.branch); - self.allocator.free(self.pretty_version); - } -}; - -fn getGitVersion(allocator: std.mem.Allocator, git_working_root: ?[]const u8, env: anytype) !GitVersion { - // git log -1 --pretty="%H%n%h%n%ci%n%D" - // 3bf6adc13e4aa653a7b75b1b5e9c9db5215df8e1 - // 3bf6adc - // 2022-01-12 12:21:28 -0800 - // HEAD -> zig-native - - const log_output = run( - allocator, - &[_][]const u8{ - "git", - "log", - "-1", - "--pretty=%H%n%h%n%ci%n%D", - }, - git_working_root, - env, - ) catch |e| { - if (std.os.getenv("DRONE_COMMIT_SHA") != null) - return getGitVersionFromDrone(allocator); - return e; - }; - defer allocator.free(log_output); - const line_data = try getLines(allocator, 4, log_output); - const hash = line_data[0]; - const abbrev_hash = line_data[1]; - const date = line_data[2]; - const branch = line_data[3]; - - // git status --porcelain - const status_output = try run( - allocator, - &[_][]const u8{ - "git", - "status", - "--porcelain", - }, - git_working_root, - env, - ); - const dirty = blk: { - if (status_output.len > 0) { - allocator.free(status_output); - break :blk true; - } - break :blk false; - }; - const dirty_str = blk: { - if (dirty) { - break :blk " (dirty)"; - } - break :blk ""; - }; - - return GitVersion{ - .hash = hash, - .abbreviated_hash = abbrev_hash, - .commit_date = date, - .branch = branch, - .allocator = allocator, - .dirty = dirty, - .pretty_version = try prettyVersion(allocator, abbrev_hash, date, dirty_str), - }; -} -fn prettyVersion(allocator: std.mem.Allocator, abbrev_hash: []const u8, date: []const u8, dirty_str: []const u8) ![]const u8 { - const pretty_version: []const u8 = try std.fmt.allocPrint( - allocator, - "version {s}, committed at {s}{s}", - .{ - abbrev_hash, - date, - dirty_str, - }, - ); - return pretty_version; -} - -fn getGitVersionFromDrone(allocator: std.mem.Allocator) !GitVersion { - const abbrev_hash = std.os.getenv("DRONE_COMMIT_SHA").?[0..7]; // This isn't quite how git works, but ok - const date = std.os.getenv("DRONE_BUILD_STARTED").?; // this is a timestamp :( - return GitVersion{ - .hash = std.os.getenv("DRONE_COMMIT_SHA").?, - .abbreviated_hash = abbrev_hash, - .commit_date = date, - .branch = std.os.getenv("DRONE_COMMIT_BRANCH").?, - .allocator = allocator, - .dirty = false, - .pretty_version = try prettyVersion(allocator, abbrev_hash, date, ""), - }; -} -fn getLines(allocator: std.mem.Allocator, comptime line_count: u32, data: []const u8) ![line_count][]u8 { - var line: u32 = 0; - var start: u32 = 0; - var current: u32 = 0; - var line_data: [line_count][]u8 = undefined; - errdefer { - while (line > 0) { - allocator.free(line_data[line]); - line -= 1; - } - } - for (data) |c| { - // try std.io.getStdErr().writer().print("line: {d}, c: {c}, cur: {d}, strt: {d}\n", .{ line, c, current, start }); - if (c == '\n') { - line_data[line] = try allocator.dupe(u8, data[start..current]); - // try std.io.getStdErr().writer().print("c: {d}, s: {d}, data: '{s}'\n", .{ current, start, line_data[line] }); - start = current + 1; - line += 1; - } - current += 1; - } - return line_data; -} - -// env is a std.process.BufMap, but that's private, which is a little weird tbh -fn run(allocator: std.mem.Allocator, argv: []const []const u8, cwd: ?[]const u8, env: anytype) ![]const u8 { - { - var msg = std.ArrayList(u8).init(allocator); - defer msg.deinit(); - const writer = msg.writer(); - var prefix: []const u8 = ""; - for (argv) |arg| { - try writer.print("{s}\"{s}\"", .{ prefix, arg }); - prefix = " "; - } - // std.log.debug("[RUN] {s}", .{msg.items}); - } - - const result = try std.ChildProcess.exec(.{ - .allocator = allocator, - .argv = argv, - .cwd = cwd, - .env_map = env, - }); - defer if (result.stderr.len > 0) allocator.free(result.stderr); - try std.io.getStdErr().writer().writeAll(result.stderr); - - switch (result.term) { - .Exited => |code| if (code != 0) { - std.log.err("process failed with exit code: {}", .{code}); - - std.os.exit(0xff); - }, - else => { - std.log.err("process failed due to exception: {}", .{result}); - std.os.exit(0xff); - }, - } - return result.stdout; -} diff --git a/build_test.zig b/build_test.zig deleted file mode 100644 index 5a8c026..0000000 --- a/build_test.zig +++ /dev/null @@ -1,32 +0,0 @@ -//! Publish Date: 2022-01-12 -//! This file is hosted at ??? and is meant to be copied -//! to projects that use it. Sample usage: -//! -//! const @"test" = @import("build_test.zig"); -//! var test_step = try @"test".addTestStep(b, mode, exe.packages.items); -const std = @import("std"); - -pub fn addTestStep(b: *std.build.Builder, mode: std.builtin.Mode, packages: []std.build.Pkg) !*std.build.Step { - const test_step = b.step("test", "Run all tests"); - const src_path = try std.fs.path.resolve(b.allocator, &[_][]const u8{ - b.build_root, - "src", - }); - defer b.allocator.free(src_path); - var src_dir = try std.fs.openDirAbsolute(src_path, .{}); - defer src_dir.close(); - var iterable = try src_dir.openIterableDir(".", .{}); - defer iterable.close(); - var iterator = iterable.iterate(); - while (try iterator.next()) |entry| { - if (std.mem.endsWith(u8, entry.name, ".zig")) { - const name = try std.fmt.allocPrint(b.allocator, "src/{s}", .{entry.name}); - defer b.allocator.free(name); - const t = b.addTest(name); - for (packages) |package| t.addPackage(package); - t.setBuildMode(mode); - test_step.dependOn(&t.step); - } - } - return test_step; -} diff --git a/zfetch_deps.zig b/zfetch_deps.zig deleted file mode 100644 index 820efbd..0000000 --- a/zfetch_deps.zig +++ /dev/null @@ -1 +0,0 @@ -const use_submodules = 1;