| author | |
| committer | |
| log | ba2f2e139306618b8beaa8e833b1f9845309df73 |
| tree | a0d0d184a7a3070bca4161d2760e66a57a4256b1 |
| parent | ccdb81fb31f3fa1384b44b74ecdae345457bd0b5 |
| parent | fa09c3a5e7ab855026ae10f9e1f61b05611a2275 |
| signature |
stage2: free Package resources, print package path on --pkg-begin failure 2 files changed, 61 insertions(+), 57 deletions(-)
src/Package.zig+34-22| ... | @@ -1,3 +1,12 @@ | ... | @@ -1,3 +1,12 @@ |
| 1 | const Package = @This(); | ||
| 2 | |||
| 3 | const std = @import("std"); | ||
| 4 | const fs = std.fs; | ||
| 5 | const mem = std.mem; | ||
| 6 | const Allocator = mem.Allocator; | ||
| 7 | |||
| 8 | const Compilation = @import("Compilation.zig"); | ||
| 9 | |||
| 1 | pub const Table = std.StringHashMapUnmanaged(*Package); | 10 | pub const Table = std.StringHashMapUnmanaged(*Package); |
| 2 | 11 | ||
| 3 | root_src_directory: Compilation.Directory, | 12 | root_src_directory: Compilation.Directory, |
| ... | @@ -6,57 +15,60 @@ root_src_path: []const u8, | ... | @@ -6,57 +15,60 @@ root_src_path: []const u8, |
| 6 | table: Table = .{}, | 15 | table: Table = .{}, |
| 7 | parent: ?*Package = null, | 16 | parent: ?*Package = null, |
| 8 | 17 | ||
| 9 | const std = @import("std"); | 18 | /// Allocate a Package. No references to the slices passed are kept. |
| 10 | const mem = std.mem; | ||
| 11 | const Allocator = std.mem.Allocator; | ||
| 12 | const assert = std.debug.assert; | ||
| 13 | const Package = @This(); | ||
| 14 | const Compilation = @import("Compilation.zig"); | ||
| 15 | |||
| 16 | /// No references to `root_src_dir` and `root_src_path` are kept. | ||
| 17 | pub fn create( | 19 | pub fn create( |
| 18 | gpa: *Allocator, | 20 | gpa: *Allocator, |
| 19 | base_directory: Compilation.Directory, | 21 | /// Null indicates the current working directory |
| 20 | /// Relative to `base_directory`. | 22 | root_src_dir_path: ?[]const u8, |
| 21 | root_src_dir: []const u8, | 23 | /// Relative to root_src_dir_path |
| 22 | /// Relative to `root_src_dir`. | ||
| 23 | root_src_path: []const u8, | 24 | root_src_path: []const u8, |
| 24 | ) !*Package { | 25 | ) !*Package { |
| 25 | const ptr = try gpa.create(Package); | 26 | const ptr = try gpa.create(Package); |
| 26 | errdefer gpa.destroy(ptr); | 27 | errdefer gpa.destroy(ptr); |
| 27 | 28 | ||
| 28 | const root_src_dir_path = try base_directory.join(gpa, &[_][]const u8{root_src_dir}); | 29 | const owned_dir_path = if (root_src_dir_path) |p| try gpa.dupe(u8, p) else null; |
| 29 | errdefer gpa.free(root_src_dir_path); | 30 | errdefer if (owned_dir_path) |p| gpa.free(p); |
| 30 | 31 | ||
| 31 | const root_src_path_dupe = try mem.dupe(gpa, u8, root_src_path); | 32 | const owned_src_path = try gpa.dupe(u8, root_src_path); |
| 32 | errdefer gpa.free(root_src_path_dupe); | 33 | errdefer gpa.free(owned_src_path); |
| 33 | 34 | ||
| 34 | ptr.* = .{ | 35 | ptr.* = .{ |
| 35 | .root_src_directory = .{ | 36 | .root_src_directory = .{ |
| 36 | .path = root_src_dir_path, | 37 | .path = owned_dir_path, |
| 37 | .handle = try base_directory.handle.openDir(root_src_dir, .{}), | 38 | .handle = if (owned_dir_path) |p| try fs.cwd().openDir(p, .{}) else fs.cwd(), |
| 38 | }, | 39 | }, |
| 39 | .root_src_path = root_src_path_dupe, | 40 | .root_src_path = owned_src_path, |
| 40 | }; | 41 | }; |
| 42 | |||
| 41 | return ptr; | 43 | return ptr; |
| 42 | } | 44 | } |
| 43 | 45 | ||
| 46 | /// Free all memory associated with this package and recursively call destroy | ||
| 47 | /// on all packages in its table | ||
| 44 | pub fn destroy(pkg: *Package, gpa: *Allocator) void { | 48 | pub fn destroy(pkg: *Package, gpa: *Allocator) void { |
| 45 | pkg.root_src_directory.handle.close(); | ||
| 46 | gpa.free(pkg.root_src_path); | 49 | gpa.free(pkg.root_src_path); |
| 47 | if (pkg.root_src_directory.path) |p| gpa.free(p); | 50 | |
| 51 | // If root_src_directory.path is null then the handle is the cwd() | ||
| 52 | // which shouldn't be closed. | ||
| 53 | if (pkg.root_src_directory.path) |p| { | ||
| 54 | gpa.free(p); | ||
| 55 | pkg.root_src_directory.handle.close(); | ||
| 56 | } | ||
| 57 | |||
| 48 | { | 58 | { |
| 49 | var it = pkg.table.iterator(); | 59 | var it = pkg.table.iterator(); |
| 50 | while (it.next()) |kv| { | 60 | while (it.next()) |kv| { |
| 61 | kv.value.destroy(gpa); | ||
| 51 | gpa.free(kv.key); | 62 | gpa.free(kv.key); |
| 52 | } | 63 | } |
| 53 | } | 64 | } |
| 65 | |||
| 54 | pkg.table.deinit(gpa); | 66 | pkg.table.deinit(gpa); |
| 55 | gpa.destroy(pkg); | 67 | gpa.destroy(pkg); |
| 56 | } | 68 | } |
| 57 | 69 | ||
| 58 | pub fn add(pkg: *Package, gpa: *Allocator, name: []const u8, package: *Package) !void { | 70 | pub fn add(pkg: *Package, gpa: *Allocator, name: []const u8, package: *Package) !void { |
| 59 | try pkg.table.ensureCapacity(gpa, pkg.table.items().len + 1); | 71 | try pkg.table.ensureCapacity(gpa, pkg.table.count() + 1); |
| 60 | const name_dupe = try mem.dupe(gpa, u8, name); | 72 | const name_dupe = try mem.dupe(gpa, u8, name); |
| 61 | pkg.table.putAssumeCapacityNoClobber(name_dupe, package); | 73 | pkg.table.putAssumeCapacityNoClobber(name_dupe, package); |
| 62 | } | 74 | } |
src/main.zig+27-35| ... | @@ -568,12 +568,15 @@ fn buildOutputType( | ... | @@ -568,12 +568,15 @@ fn buildOutputType( |
| 568 | var test_exec_args = std.ArrayList(?[]const u8).init(gpa); | 568 | var test_exec_args = std.ArrayList(?[]const u8).init(gpa); |
| 569 | defer test_exec_args.deinit(); | 569 | defer test_exec_args.deinit(); |
| 570 | 570 | ||
| 571 | var root_pkg_memory: Package = .{ | 571 | const pkg_tree_root = try gpa.create(Package); |
| 572 | .root_src_directory = undefined, | 572 | // This package only exists to clean up the code parsing --pkg-begin and |
| 573 | .root_src_path = undefined, | 573 | // --pkg-end flags. Use dummy values that are safe for the destroy call. |
| 574 | pkg_tree_root.* = .{ | ||
| 575 | .root_src_directory = .{ .path = null, .handle = fs.cwd() }, | ||
| 576 | .root_src_path = &[0]u8{}, | ||
| 574 | }; | 577 | }; |
| 575 | defer root_pkg_memory.table.deinit(gpa); | 578 | defer pkg_tree_root.destroy(gpa); |
| 576 | var cur_pkg: *Package = &root_pkg_memory; | 579 | var cur_pkg: *Package = pkg_tree_root; |
| 577 | 580 | ||
| 578 | switch (arg_mode) { | 581 | switch (arg_mode) { |
| 579 | .build, .translate_c, .zig_test, .run => { | 582 | .build, .translate_c, .zig_test, .run => { |
| ... | @@ -627,22 +630,15 @@ fn buildOutputType( | ... | @@ -627,22 +630,15 @@ fn buildOutputType( |
| 627 | i += 1; | 630 | i += 1; |
| 628 | const pkg_path = args[i]; | 631 | const pkg_path = args[i]; |
| 629 | 632 | ||
| 630 | const new_cur_pkg = try arena.create(Package); | 633 | const new_cur_pkg = Package.create( |
| 631 | new_cur_pkg.* = .{ | 634 | gpa, |
| 632 | .root_src_directory = if (fs.path.dirname(pkg_path)) |dirname| | 635 | fs.path.dirname(pkg_path), |
| 633 | .{ | 636 | fs.path.basename(pkg_path), |
| 634 | .path = dirname, | 637 | ) catch |err| { |
| 635 | .handle = try fs.cwd().openDir(dirname, .{}), // TODO close this fd | 638 | fatal("Failed to add package at path {}: {}", .{ pkg_path, @errorName(err) }); |
| 636 | } | ||
| 637 | else | ||
| 638 | .{ | ||
| 639 | .path = null, | ||
| 640 | .handle = fs.cwd(), | ||
| 641 | }, | ||
| 642 | .root_src_path = fs.path.basename(pkg_path), | ||
| 643 | .parent = cur_pkg, | ||
| 644 | }; | 639 | }; |
| 645 | try cur_pkg.table.put(gpa, pkg_name, new_cur_pkg); | 640 | new_cur_pkg.parent = cur_pkg; |
| 641 | try cur_pkg.add(gpa, pkg_name, new_cur_pkg); | ||
| 646 | cur_pkg = new_cur_pkg; | 642 | cur_pkg = new_cur_pkg; |
| 647 | } else if (mem.eql(u8, arg, "--pkg-end")) { | 643 | } else if (mem.eql(u8, arg, "--pkg-end")) { |
| 648 | cur_pkg = cur_pkg.parent orelse | 644 | cur_pkg = cur_pkg.parent orelse |
| ... | @@ -1600,26 +1596,22 @@ fn buildOutputType( | ... | @@ -1600,26 +1596,22 @@ fn buildOutputType( |
| 1600 | .yes => |p| p, | 1596 | .yes => |p| p, |
| 1601 | }; | 1597 | }; |
| 1602 | 1598 | ||
| 1603 | var cleanup_root_dir: ?fs.Dir = null; | ||
| 1604 | defer if (cleanup_root_dir) |*dir| dir.close(); | ||
| 1605 | |||
| 1606 | const root_pkg: ?*Package = if (root_src_file) |src_path| blk: { | 1599 | const root_pkg: ?*Package = if (root_src_file) |src_path| blk: { |
| 1607 | if (main_pkg_path) |p| { | 1600 | if (main_pkg_path) |p| { |
| 1608 | const dir = try fs.cwd().openDir(p, .{}); | 1601 | const rel_src_path = try fs.path.relative(gpa, p, src_path); |
| 1609 | cleanup_root_dir = dir; | 1602 | defer gpa.free(rel_src_path); |
| 1610 | root_pkg_memory.root_src_directory = .{ .path = p, .handle = dir }; | 1603 | break :blk try Package.create(gpa, p, rel_src_path); |
| 1611 | root_pkg_memory.root_src_path = try fs.path.relative(arena, p, src_path); | ||
| 1612 | } else if (fs.path.dirname(src_path)) |p| { | ||
| 1613 | const dir = try fs.cwd().openDir(p, .{}); | ||
| 1614 | cleanup_root_dir = dir; | ||
| 1615 | root_pkg_memory.root_src_directory = .{ .path = p, .handle = dir }; | ||
| 1616 | root_pkg_memory.root_src_path = fs.path.basename(src_path); | ||
| 1617 | } else { | 1604 | } else { |
| 1618 | root_pkg_memory.root_src_directory = .{ .path = null, .handle = fs.cwd() }; | 1605 | break :blk try Package.create(gpa, fs.path.dirname(src_path), fs.path.basename(src_path)); |
| 1619 | root_pkg_memory.root_src_path = src_path; | ||
| 1620 | } | 1606 | } |
| 1621 | break :blk &root_pkg_memory; | ||
| 1622 | } else null; | 1607 | } else null; |
| 1608 | defer if (root_pkg) |p| p.destroy(gpa); | ||
| 1609 | |||
| 1610 | // Transfer packages added with --pkg-begin/--pkg-end to the root package | ||
| 1611 | if (root_pkg) |pkg| { | ||
| 1612 | pkg.table = pkg_tree_root.table; | ||
| 1613 | pkg_tree_root.table = .{}; | ||
| 1614 | } | ||
| 1623 | 1615 | ||
| 1624 | const self_exe_path = try fs.selfExePathAlloc(arena); | 1616 | const self_exe_path = try fs.selfExePathAlloc(arena); |
| 1625 | var zig_lib_directory: Compilation.Directory = if (override_lib_dir) |lib_dir| | 1617 | var zig_lib_directory: Compilation.Directory = if (override_lib_dir) |lib_dir| |