master
 1//! This script updates the .c, .h, .s, and .S files that make up the start
 2//! files such as crt1.o.
 3//!
 4//! Example usage:
 5//! `zig run tools/update_freebsd_libc.zig -- ~/Downloads/freebsd-src .`
 6
 7const std = @import("std");
 8
 9const exempt_files = [_][]const u8{
10    // This file is maintained by a separate project and does not come from FreeBSD.
11    "abilists",
12};
13
14pub fn main() !void {
15    var arena_instance = std.heap.ArenaAllocator.init(std.heap.page_allocator);
16    defer arena_instance.deinit();
17    const arena = arena_instance.allocator();
18
19    const args = try std.process.argsAlloc(arena);
20    const freebsd_src_path = args[1];
21    const zig_src_path = args[2];
22
23    const dest_dir_path = try std.fmt.allocPrint(arena, "{s}/lib/libc/freebsd", .{zig_src_path});
24
25    var dest_dir = std.fs.cwd().openDir(dest_dir_path, .{ .iterate = true }) catch |err| {
26        std.log.err("unable to open destination directory '{s}': {s}", .{
27            dest_dir_path, @errorName(err),
28        });
29        std.process.exit(1);
30    };
31    defer dest_dir.close();
32
33    var freebsd_src_dir = try std.fs.cwd().openDir(freebsd_src_path, .{});
34    defer freebsd_src_dir.close();
35
36    // Copy updated files from upstream.
37    {
38        var walker = try dest_dir.walk(arena);
39        defer walker.deinit();
40
41        walk: while (try walker.next()) |entry| {
42            if (entry.kind != .file) continue;
43            if (std.mem.startsWith(u8, entry.basename, ".")) continue;
44            for (exempt_files) |p| {
45                if (std.mem.eql(u8, entry.path, p)) continue :walk;
46            }
47
48            std.log.info("updating '{s}/{s}' from '{s}/{s}'", .{
49                dest_dir_path,    entry.path,
50                freebsd_src_path, entry.path,
51            });
52
53            freebsd_src_dir.copyFile(entry.path, dest_dir, entry.path, .{}) catch |err| {
54                std.log.warn("unable to copy '{s}/{s}' to '{s}/{s}': {s}", .{
55                    freebsd_src_path, entry.path,
56                    dest_dir_path,    entry.path,
57                    @errorName(err),
58                });
59                if (err == error.FileNotFound) {
60                    try dest_dir.deleteFile(entry.path);
61                }
62            };
63        }
64    }
65}