| author | |
| committer | |
| log | 3d33735d73de269278fb87d2c9ae8fb7d83977be |
| tree | 629df23a332d0b78bcd9b374ae51152980a99672 |
| parent | 36b65ab59e5e514ad06a11cde96b87c565d86ac8 |
closes #311245 files changed, 221 insertions(+), 69 deletions(-)
lib/compiler/build_runner.zig+26-23| ... | @@ -1573,6 +1573,23 @@ fn printUsage(b: *std.Build, w: *Writer) !void { | ... | @@ -1573,6 +1573,23 @@ fn printUsage(b: *std.Build, w: *Writer) !void { |
| 1573 | \\ -fsys=[name] Enable a system integration | 1573 | \\ -fsys=[name] Enable a system integration |
| 1574 | \\ -fno-sys=[name] Disable a system integration | 1574 | \\ -fno-sys=[name] Disable a system integration |
| 1575 | \\ | 1575 | \\ |
| 1576 | \\ -fdarling, -fno-darling Integration with system-installed Darling to | ||
| 1577 | \\ execute macOS programs on Linux hosts | ||
| 1578 | \\ (default: no) | ||
| 1579 | \\ -fqemu, -fno-qemu Integration with system-installed QEMU to execute | ||
| 1580 | \\ foreign-architecture programs on Linux hosts | ||
| 1581 | \\ (default: no) | ||
| 1582 | \\ --libc-runtimes [path] Enhances QEMU integration by providing dynamic libc | ||
| 1583 | \\ (e.g. glibc or musl) built for multiple foreign | ||
| 1584 | \\ architectures, allowing execution of non-native | ||
| 1585 | \\ programs that link with libc. | ||
| 1586 | \\ -frosetta, -fno-rosetta Rely on Rosetta to execute x86_64 programs on | ||
| 1587 | \\ ARM64 macOS hosts. (default: no) | ||
| 1588 | \\ -fwasmtime, -fno-wasmtime Integration with system-installed wasmtime to | ||
| 1589 | \\ execute WASI binaries. (default: no) | ||
| 1590 | \\ -fwine, -fno-wine Integration with system-installed Wine to execute | ||
| 1591 | \\ Windows programs on Linux hosts. (default: no) | ||
| 1592 | \\ | ||
| 1576 | \\ Available System Integrations: Enabled: | 1593 | \\ Available System Integrations: Enabled: |
| 1577 | \\ | 1594 | \\ |
| 1578 | ); | 1595 | ); |
| ... | @@ -1592,33 +1609,16 @@ fn printUsage(b: *std.Build, w: *Writer) !void { | ... | @@ -1592,33 +1609,16 @@ fn printUsage(b: *std.Build, w: *Writer) !void { |
| 1592 | try w.writeAll( | 1609 | try w.writeAll( |
| 1593 | \\ | 1610 | \\ |
| 1594 | \\General Options: | 1611 | \\General Options: |
| 1612 | \\ -h, --help Print this help and exit | ||
| 1613 | \\ -l, --list-steps Print available steps | ||
| 1614 | \\ | ||
| 1595 | \\ -p, --prefix [path] Where to install files (default: zig-out) | 1615 | \\ -p, --prefix [path] Where to install files (default: zig-out) |
| 1596 | \\ --prefix-lib-dir [path] Where to install libraries | 1616 | \\ --prefix-lib-dir [path] Where to install libraries |
| 1597 | \\ --prefix-exe-dir [path] Where to install executables | 1617 | \\ --prefix-exe-dir [path] Where to install executables |
| 1598 | \\ --prefix-include-dir [path] Where to install C header files | 1618 | \\ --prefix-include-dir [path] Where to install C header files |
| 1599 | \\ | ||
| 1600 | \\ --release[=mode] Request release mode, optionally specifying a | 1619 | \\ --release[=mode] Request release mode, optionally specifying a |
| 1601 | \\ preferred optimization mode: fast, safe, small | 1620 | \\ preferred optimization mode: fast, safe, small |
| 1602 | \\ | 1621 | \\ |
| 1603 | \\ -fdarling, -fno-darling Integration with system-installed Darling to | ||
| 1604 | \\ execute macOS programs on Linux hosts | ||
| 1605 | \\ (default: no) | ||
| 1606 | \\ -fqemu, -fno-qemu Integration with system-installed QEMU to execute | ||
| 1607 | \\ foreign-architecture programs on Linux hosts | ||
| 1608 | \\ (default: no) | ||
| 1609 | \\ --libc-runtimes [path] Enhances QEMU integration by providing dynamic libc | ||
| 1610 | \\ (e.g. glibc or musl) built for multiple foreign | ||
| 1611 | \\ architectures, allowing execution of non-native | ||
| 1612 | \\ programs that link with libc. | ||
| 1613 | \\ -frosetta, -fno-rosetta Rely on Rosetta to execute x86_64 programs on | ||
| 1614 | \\ ARM64 macOS hosts. (default: no) | ||
| 1615 | \\ -fwasmtime, -fno-wasmtime Integration with system-installed wasmtime to | ||
| 1616 | \\ execute WASI binaries. (default: no) | ||
| 1617 | \\ -fwine, -fno-wine Integration with system-installed Wine to execute | ||
| 1618 | \\ Windows programs on Linux hosts. (default: no) | ||
| 1619 | \\ | ||
| 1620 | \\ -h, --help Print this help and exit | ||
| 1621 | \\ -l, --list-steps Print available steps | ||
| 1622 | \\ --verbose Print commands before executing them | 1622 | \\ --verbose Print commands before executing them |
| 1623 | \\ --color [auto|off|on] Enable or disable colored error messages | 1623 | \\ --color [auto|off|on] Enable or disable colored error messages |
| 1624 | \\ --error-style [style] Control how build errors are printed | 1624 | \\ --error-style [style] Control how build errors are printed |
| ... | @@ -1641,9 +1641,6 @@ fn printUsage(b: *std.Build, w: *Writer) !void { | ... | @@ -1641,9 +1641,6 @@ fn printUsage(b: *std.Build, w: *Writer) !void { |
| 1641 | \\ --skip-oom-steps Instead of failing, skip steps that would exceed --maxrss | 1641 | \\ --skip-oom-steps Instead of failing, skip steps that would exceed --maxrss |
| 1642 | \\ --test-timeout <timeout> Limit execution time of unit tests, terminating if exceeded. | 1642 | \\ --test-timeout <timeout> Limit execution time of unit tests, terminating if exceeded. |
| 1643 | \\ The timeout must include a unit: ns, us, ms, s, m, h | 1643 | \\ The timeout must include a unit: ns, us, ms, s, m, h |
| 1644 | \\ --fetch[=mode] Fetch dependency tree (optionally choose laziness) and exit | ||
| 1645 | \\ needed (Default) Lazy dependencies are fetched as needed | ||
| 1646 | \\ all Lazy dependencies are always fetched | ||
| 1647 | \\ --watch Continuously rebuild when source files are modified | 1644 | \\ --watch Continuously rebuild when source files are modified |
| 1648 | \\ --debounce <ms> Delay before rebuilding after changed file detected | 1645 | \\ --debounce <ms> Delay before rebuilding after changed file detected |
| 1649 | \\ --webui[=ip] Enable the web interface on the given IP address | 1646 | \\ --webui[=ip] Enable the web interface on the given IP address |
| ... | @@ -1656,6 +1653,12 @@ fn printUsage(b: *std.Build, w: *Writer) !void { | ... | @@ -1656,6 +1653,12 @@ fn printUsage(b: *std.Build, w: *Writer) !void { |
| 1656 | \\ -fincremental Enable incremental compilation | 1653 | \\ -fincremental Enable incremental compilation |
| 1657 | \\ -fno-incremental Disable incremental compilation | 1654 | \\ -fno-incremental Disable incremental compilation |
| 1658 | \\ | 1655 | \\ |
| 1656 | \\Package Management Options: | ||
| 1657 | \\ --fetch[=mode] Fetch dependency tree (optionally choose laziness) and exit | ||
| 1658 | \\ needed (Default) Lazy dependencies are fetched as needed | ||
| 1659 | \\ all Lazy dependencies are always fetched | ||
| 1660 | \\ --fork=[path] Override one or more packages from dependency tree | ||
| 1661 | \\ | ||
| 1659 | \\Advanced Options: | 1662 | \\Advanced Options: |
| 1660 | \\ -freference-trace[=num] How many lines of reference trace should be shown per compile error | 1663 | \\ -freference-trace[=num] How many lines of reference trace should be shown per compile error |
| 1661 | \\ -fno-reference-trace Disable reference trace | 1664 | \\ -fno-reference-trace Disable reference trace |
src/Package.zig+37| ... | @@ -137,6 +137,43 @@ pub const Hash = struct { | ... | @@ -137,6 +137,43 @@ pub const Hash = struct { |
| 137 | _ = std.fmt.bufPrint(result.bytes[i..], "{x}", .{&bin_digest}) catch unreachable; | 137 | _ = std.fmt.bufPrint(result.bytes[i..], "{x}", .{&bin_digest}) catch unreachable; |
| 138 | return result; | 138 | return result; |
| 139 | } | 139 | } |
| 140 | |||
| 141 | pub fn projectId(hash: *const Hash) ProjectId { | ||
| 142 | const name = std.mem.sliceTo(&hash.bytes, '-'); | ||
| 143 | const hashplus = hash.bytes[std.mem.findScalarLast(u8, &hash.bytes, '-').? + 1 ..]; | ||
| 144 | var decoded: [6]u8 = undefined; | ||
| 145 | std.base64.url_safe_no_pad.Decoder.decode(&decoded, hashplus[0..8]) catch unreachable; | ||
| 146 | const fingerprint_id = std.mem.readInt(u32, decoded[0..4], .little); | ||
| 147 | return .init(name, fingerprint_id); | ||
| 148 | } | ||
| 149 | |||
| 150 | test projectId { | ||
| 151 | const hash: Hash = .fromSlice("pulseaudio-16.1.1-9-mk_62MZkNwBaFwiZ7ZVrYRIf_3dTqqJR5PbMRCJzSuLw"); | ||
| 152 | const project_id = hash.projectId(); | ||
| 153 | |||
| 154 | var expected_name: [32]u8 = @splat(0); | ||
| 155 | expected_name[0.."pulseaudio".len].* = "pulseaudio".*; | ||
| 156 | try std.testing.expectEqualSlices(u8, &expected_name, &project_id.padded_name); | ||
| 157 | |||
| 158 | try std.testing.expectEqual(0xd8fa4f9a, project_id.fingerprint_id); | ||
| 159 | } | ||
| 160 | }; | ||
| 161 | |||
| 162 | /// Minimum information required to identify whether a package is an artifact | ||
| 163 | /// of a given project. | ||
| 164 | pub const ProjectId = struct { | ||
| 165 | /// Bytes after name.len are set to zero. | ||
| 166 | padded_name: [32]u8, | ||
| 167 | fingerprint_id: u32, | ||
| 168 | |||
| 169 | pub fn init(name: []const u8, fingerprint_id: u32) ProjectId { | ||
| 170 | var padded_name: [32]u8 = @splat(0); | ||
| 171 | @memcpy(padded_name[0..name.len], name); | ||
| 172 | return .{ | ||
| 173 | .padded_name = padded_name, | ||
| 174 | .fingerprint_id = fingerprint_id, | ||
| 175 | }; | ||
| 176 | } | ||
| 140 | }; | 177 | }; |
| 141 | 178 | ||
| 142 | pub const MultihashFunction = enum(u16) { | 179 | pub const MultihashFunction = enum(u16) { |
src/Package/Fetch.zig+16-29| ... | @@ -142,6 +142,8 @@ pub const JobQueue = struct { | ... | @@ -142,6 +142,8 @@ pub const JobQueue = struct { |
| 142 | /// Set of hashes that will be additionally fetched even if they are marked | 142 | /// Set of hashes that will be additionally fetched even if they are marked |
| 143 | /// as lazy. | 143 | /// as lazy. |
| 144 | unlazy_set: UnlazySet = .{}, | 144 | unlazy_set: UnlazySet = .{}, |
| 145 | /// Identifies paths that override all packages in the tree matching | ||
| 146 | fork_set: ForkSet = .{}, | ||
| 145 | 147 | ||
| 146 | pub const Mode = enum { | 148 | pub const Mode = enum { |
| 147 | /// Non-lazy dependencies are always fetched. | 149 | /// Non-lazy dependencies are always fetched. |
| ... | @@ -152,6 +154,7 @@ pub const JobQueue = struct { | ... | @@ -152,6 +154,7 @@ pub const JobQueue = struct { |
| 152 | }; | 154 | }; |
| 153 | pub const Table = std.AutoArrayHashMapUnmanaged(Package.Hash, *Fetch); | 155 | pub const Table = std.AutoArrayHashMapUnmanaged(Package.Hash, *Fetch); |
| 154 | pub const UnlazySet = std.AutoArrayHashMapUnmanaged(Package.Hash, void); | 156 | pub const UnlazySet = std.AutoArrayHashMapUnmanaged(Package.Hash, void); |
| 157 | pub const ForkSet = std.AutoArrayHashMapUnmanaged(Package.ProjectId, Cache.Path); | ||
| 155 | 158 | ||
| 156 | pub fn deinit(jq: *JobQueue) void { | 159 | pub fn deinit(jq: *JobQueue) void { |
| 157 | const io = jq.io; | 160 | const io = jq.io; |
| ... | @@ -801,45 +804,29 @@ fn loadManifest(f: *Fetch, pkg_root: Cache.Path) RunError!void { | ... | @@ -801,45 +804,29 @@ fn loadManifest(f: *Fetch, pkg_root: Cache.Path) RunError!void { |
| 801 | const io = f.job_queue.io; | 804 | const io = f.job_queue.io; |
| 802 | const eb = &f.error_bundle; | 805 | const eb = &f.error_bundle; |
| 803 | const arena = f.arena.allocator(); | 806 | const arena = f.arena.allocator(); |
| 804 | const manifest_bytes = pkg_root.root_dir.handle.readFileAllocOptions( | 807 | const manifest_path = try pkg_root.join(arena, Manifest.basename); |
| 808 | |||
| 809 | f.manifest = @as(Manifest, undefined); | ||
| 810 | |||
| 811 | Manifest.load( | ||
| 805 | io, | 812 | io, |
| 806 | try fs.path.join(arena, &.{ pkg_root.sub_path, Manifest.basename }), | ||
| 807 | arena, | 813 | arena, |
| 808 | .limited(Manifest.max_bytes), | 814 | manifest_path, |
| 809 | .@"1", | 815 | &f.manifest_ast, |
| 810 | 0, | 816 | eb, |
| 817 | &f.manifest.?, | ||
| 818 | f.allow_missing_paths_field, | ||
| 811 | ) catch |err| switch (err) { | 819 | ) catch |err| switch (err) { |
| 812 | error.FileNotFound => return, | 820 | error.FileNotFound => return, |
| 821 | error.Canceled => |e| return e, | ||
| 822 | error.ErrorsBundled => return error.FetchFailed, | ||
| 813 | else => |e| { | 823 | else => |e| { |
| 814 | const file_path = try pkg_root.join(arena, Manifest.basename); | ||
| 815 | try eb.addRootErrorMessage(.{ | 824 | try eb.addRootErrorMessage(.{ |
| 816 | .msg = try eb.printString("unable to load package manifest '{f}': {t}", .{ file_path, e }), | 825 | .msg = try eb.printString("unable to load package manifest '{f}': {t}", .{ manifest_path, e }), |
| 817 | }); | 826 | }); |
| 818 | return error.FetchFailed; | 827 | return error.FetchFailed; |
| 819 | }, | 828 | }, |
| 820 | }; | 829 | }; |
| 821 | |||
| 822 | const ast = &f.manifest_ast; | ||
| 823 | ast.* = try std.zig.Ast.parse(arena, manifest_bytes, .zon); | ||
| 824 | |||
| 825 | if (ast.errors.len > 0) { | ||
| 826 | const file_path = try std.fmt.allocPrint(arena, "{f}" ++ fs.path.sep_str ++ Manifest.basename, .{pkg_root}); | ||
| 827 | try std.zig.putAstErrorsIntoBundle(arena, ast.*, file_path, eb); | ||
| 828 | return error.FetchFailed; | ||
| 829 | } | ||
| 830 | |||
| 831 | const rng: std.Random.IoSource = .{ .io = io }; | ||
| 832 | |||
| 833 | f.manifest = try Manifest.parse(arena, ast.*, rng.interface(), .{ | ||
| 834 | .allow_missing_paths_field = f.allow_missing_paths_field, | ||
| 835 | }); | ||
| 836 | const manifest = &f.manifest.?; | ||
| 837 | |||
| 838 | if (manifest.errors.len > 0) { | ||
| 839 | const src_path = try eb.printString("{f}" ++ fs.path.sep_str ++ "{s}", .{ pkg_root, Manifest.basename }); | ||
| 840 | try manifest.copyErrorsIntoBundle(ast.*, src_path, eb); | ||
| 841 | return error.FetchFailed; | ||
| 842 | } | ||
| 843 | } | 830 | } |
| 844 | 831 | ||
| 845 | fn queueJobsForDeps(f: *Fetch) RunError!void { | 832 | fn queueJobsForDeps(f: *Fetch) RunError!void { |
src/Package/Manifest.zig+44-2| ... | @@ -1,10 +1,13 @@ | ... | @@ -1,10 +1,13 @@ |
| 1 | const Manifest = @This(); | 1 | const Manifest = @This(); |
| 2 | |||
| 2 | const std = @import("std"); | 3 | const std = @import("std"); |
| 4 | const Io = std.Io; | ||
| 3 | const mem = std.mem; | 5 | const mem = std.mem; |
| 4 | const Allocator = std.mem.Allocator; | 6 | const Allocator = std.mem.Allocator; |
| 5 | const assert = std.debug.assert; | 7 | const assert = std.debug.assert; |
| 6 | const Ast = std.zig.Ast; | 8 | const Ast = std.zig.Ast; |
| 7 | const testing = std.testing; | 9 | const testing = std.testing; |
| 10 | |||
| 8 | const Package = @import("../Package.zig"); | 11 | const Package = @import("../Package.zig"); |
| 9 | 12 | ||
| 10 | pub const max_bytes = 10 * 1024 * 1024; | 13 | pub const max_bytes = 10 * 1024 * 1024; |
| ... | @@ -53,7 +56,7 @@ pub const ParseOptions = struct { | ... | @@ -53,7 +56,7 @@ pub const ParseOptions = struct { |
| 53 | 56 | ||
| 54 | pub const Error = Allocator.Error; | 57 | pub const Error = Allocator.Error; |
| 55 | 58 | ||
| 56 | pub fn parse(gpa: Allocator, ast: Ast, rng: std.Random, options: ParseOptions) Error!Manifest { | 59 | pub fn parse(gpa: Allocator, ast: *const Ast, rng: std.Random, options: ParseOptions) Error!Manifest { |
| 57 | const main_node_index = ast.nodeData(.root).node; | 60 | const main_node_index = ast.nodeData(.root).node; |
| 58 | 61 | ||
| 59 | var arena_instance = std.heap.ArenaAllocator.init(gpa); | 62 | var arena_instance = std.heap.ArenaAllocator.init(gpa); |
| ... | @@ -61,7 +64,7 @@ pub fn parse(gpa: Allocator, ast: Ast, rng: std.Random, options: ParseOptions) E | ... | @@ -61,7 +64,7 @@ pub fn parse(gpa: Allocator, ast: Ast, rng: std.Random, options: ParseOptions) E |
| 61 | 64 | ||
| 62 | var p: Parse = .{ | 65 | var p: Parse = .{ |
| 63 | .gpa = gpa, | 66 | .gpa = gpa, |
| 64 | .ast = ast, | 67 | .ast = ast.*, |
| 65 | .arena = arena_instance.allocator(), | 68 | .arena = arena_instance.allocator(), |
| 66 | .errors = .{}, | 69 | .errors = .{}, |
| 67 | 70 | ||
| ... | @@ -578,6 +581,45 @@ const Parse = struct { | ... | @@ -578,6 +581,45 @@ const Parse = struct { |
| 578 | } | 581 | } |
| 579 | }; | 582 | }; |
| 580 | 583 | ||
| 584 | pub fn load( | ||
| 585 | io: Io, | ||
| 586 | arena: Allocator, | ||
| 587 | manifest_path: std.Build.Cache.Path, | ||
| 588 | ast: *std.zig.Ast, | ||
| 589 | error_bundle: *std.zig.ErrorBundle.Wip, | ||
| 590 | manifest: *Manifest, | ||
| 591 | allow_missing_paths_field: bool, | ||
| 592 | ) !void { | ||
| 593 | const manifest_bytes = try manifest_path.root_dir.handle.readFileAllocOptions( | ||
| 594 | io, | ||
| 595 | manifest_path.sub_path, | ||
| 596 | arena, | ||
| 597 | .limited(max_bytes), | ||
| 598 | .@"1", | ||
| 599 | 0, | ||
| 600 | ); | ||
| 601 | |||
| 602 | ast.* = try std.zig.Ast.parse(arena, manifest_bytes, .zon); | ||
| 603 | |||
| 604 | if (ast.errors.len > 0) { | ||
| 605 | const file_path = try manifest_path.joinString(arena, ""); | ||
| 606 | try std.zig.putAstErrorsIntoBundle(arena, ast.*, file_path, error_bundle); | ||
| 607 | return error.ErrorsBundled; | ||
| 608 | } | ||
| 609 | |||
| 610 | const rng: std.Random.IoSource = .{ .io = io }; | ||
| 611 | |||
| 612 | manifest.* = try parse(arena, ast, rng.interface(), .{ | ||
| 613 | .allow_missing_paths_field = allow_missing_paths_field, | ||
| 614 | }); | ||
| 615 | |||
| 616 | if (manifest.errors.len > 0) { | ||
| 617 | const src_path = try error_bundle.printString("{f}", .{manifest_path}); | ||
| 618 | try manifest.copyErrorsIntoBundle(ast.*, src_path, error_bundle); | ||
| 619 | return error.ErrorsBundled; | ||
| 620 | } | ||
| 621 | } | ||
| 622 | |||
| 581 | test "basic" { | 623 | test "basic" { |
| 582 | const gpa = testing.allocator; | 624 | const gpa = testing.allocator; |
| 583 | 625 |
src/main.zig+98-15| ... | @@ -4896,7 +4896,8 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8, | ... | @@ -4896,7 +4896,8 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8, |
| 4896 | var override_global_cache_dir: ?[]const u8 = EnvVar.ZIG_GLOBAL_CACHE_DIR.get(environ_map); | 4896 | var override_global_cache_dir: ?[]const u8 = EnvVar.ZIG_GLOBAL_CACHE_DIR.get(environ_map); |
| 4897 | var override_local_cache_dir: ?[]const u8 = EnvVar.ZIG_LOCAL_CACHE_DIR.get(environ_map); | 4897 | var override_local_cache_dir: ?[]const u8 = EnvVar.ZIG_LOCAL_CACHE_DIR.get(environ_map); |
| 4898 | var override_build_runner: ?[]const u8 = EnvVar.ZIG_BUILD_RUNNER.get(environ_map); | 4898 | var override_build_runner: ?[]const u8 = EnvVar.ZIG_BUILD_RUNNER.get(environ_map); |
| 4899 | var child_argv = std.array_list.Managed([]const u8).init(arena); | 4899 | var child_argv: std.ArrayList([]const u8) = .empty; |
| 4900 | var forks: std.ArrayList(Fork) = .empty; | ||
| 4900 | var reference_trace: ?u32 = null; | 4901 | var reference_trace: ?u32 = null; |
| 4901 | var debug_compile_errors = false; | 4902 | var debug_compile_errors = false; |
| 4902 | var verbose_link = (native_os != .wasi or builtin.link_libc) and | 4903 | var verbose_link = (native_os != .wasi or builtin.link_libc) and |
| ... | @@ -4917,24 +4918,24 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8, | ... | @@ -4917,24 +4918,24 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8, |
| 4917 | var debug_libc_paths_file: ?[]const u8 = null; | 4918 | var debug_libc_paths_file: ?[]const u8 = null; |
| 4918 | 4919 | ||
| 4919 | const argv_index_exe = child_argv.items.len; | 4920 | const argv_index_exe = child_argv.items.len; |
| 4920 | _ = try child_argv.addOne(); | 4921 | _ = try child_argv.addOne(arena); |
| 4921 | 4922 | ||
| 4922 | const self_exe_path = try process.executablePathAlloc(io, arena); | 4923 | const self_exe_path = try process.executablePathAlloc(io, arena); |
| 4923 | try child_argv.append(self_exe_path); | 4924 | try child_argv.append(arena, self_exe_path); |
| 4924 | 4925 | ||
| 4925 | const argv_index_zig_lib_dir = child_argv.items.len; | 4926 | const argv_index_zig_lib_dir = child_argv.items.len; |
| 4926 | _ = try child_argv.addOne(); | 4927 | _ = try child_argv.addOne(arena); |
| 4927 | 4928 | ||
| 4928 | const argv_index_build_file = child_argv.items.len; | 4929 | const argv_index_build_file = child_argv.items.len; |
| 4929 | _ = try child_argv.addOne(); | 4930 | _ = try child_argv.addOne(arena); |
| 4930 | 4931 | ||
| 4931 | const argv_index_cache_dir = child_argv.items.len; | 4932 | const argv_index_cache_dir = child_argv.items.len; |
| 4932 | _ = try child_argv.addOne(); | 4933 | _ = try child_argv.addOne(arena); |
| 4933 | 4934 | ||
| 4934 | const argv_index_global_cache_dir = child_argv.items.len; | 4935 | const argv_index_global_cache_dir = child_argv.items.len; |
| 4935 | _ = try child_argv.addOne(); | 4936 | _ = try child_argv.addOne(arena); |
| 4936 | 4937 | ||
| 4937 | try child_argv.appendSlice(&.{ | 4938 | try child_argv.appendSlice(arena, &.{ |
| 4938 | "--seed", | 4939 | "--seed", |
| 4939 | try std.fmt.allocPrint(arena, "0x{x}", .{randInt(io, u32)}), | 4940 | try std.fmt.allocPrint(arena, "0x{x}", .{randInt(io, u32)}), |
| 4940 | }); | 4941 | }); |
| ... | @@ -4955,7 +4956,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8, | ... | @@ -4955,7 +4956,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8, |
| 4955 | // read this file in the parent to obtain the results, in the case the child | 4956 | // read this file in the parent to obtain the results, in the case the child |
| 4956 | // exits with code 3. | 4957 | // exits with code 3. |
| 4957 | const results_tmp_file_nonce = std.fmt.hex(randInt(io, u64)); | 4958 | const results_tmp_file_nonce = std.fmt.hex(randInt(io, u64)); |
| 4958 | try child_argv.append("-Z" ++ results_tmp_file_nonce); | 4959 | try child_argv.append(arena, "-Z" ++ results_tmp_file_nonce); |
| 4959 | 4960 | ||
| 4960 | var color: Color = .auto; | 4961 | var color: Color = .auto; |
| 4961 | var n_jobs: ?u32 = null; | 4962 | var n_jobs: ?u32 = null; |
| ... | @@ -5000,11 +5001,19 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8, | ... | @@ -5000,11 +5001,19 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8, |
| 5000 | fatal("expected [needed|all] after '--fetch=', found '{s}'", .{ | 5001 | fatal("expected [needed|all] after '--fetch=', found '{s}'", .{ |
| 5001 | sub_arg, | 5002 | sub_arg, |
| 5002 | }); | 5003 | }); |
| 5004 | } else if (mem.cutPrefix(u8, arg, "--fork=")) |sub_arg| { | ||
| 5005 | try forks.append(arena, .{ | ||
| 5006 | .project_id = undefined, | ||
| 5007 | .path = .{ | ||
| 5008 | .root_dir = .cwd(), | ||
| 5009 | .sub_path = sub_arg, | ||
| 5010 | }, | ||
| 5011 | }); | ||
| 5003 | } else if (mem.eql(u8, arg, "--system")) { | 5012 | } else if (mem.eql(u8, arg, "--system")) { |
| 5004 | if (i + 1 >= args.len) fatal("expected argument after '{s}'", .{arg}); | 5013 | if (i + 1 >= args.len) fatal("expected argument after '{s}'", .{arg}); |
| 5005 | i += 1; | 5014 | i += 1; |
| 5006 | system_pkg_dir_path = args[i]; | 5015 | system_pkg_dir_path = args[i]; |
| 5007 | try child_argv.append("--system"); | 5016 | try child_argv.append(arena, "--system"); |
| 5008 | continue; | 5017 | continue; |
| 5009 | } else if (mem.cutPrefix(u8, arg, "-freference-trace=")) |num| { | 5018 | } else if (mem.cutPrefix(u8, arg, "-freference-trace=")) |num| { |
| 5010 | reference_trace = std.fmt.parseUnsigned(u32, num, 10) catch |err| { | 5019 | reference_trace = std.fmt.parseUnsigned(u32, num, 10) catch |err| { |
| ... | @@ -5014,7 +5023,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8, | ... | @@ -5014,7 +5023,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8, |
| 5014 | reference_trace = null; | 5023 | reference_trace = null; |
| 5015 | } else if (mem.eql(u8, arg, "--debug-log")) { | 5024 | } else if (mem.eql(u8, arg, "--debug-log")) { |
| 5016 | if (i + 1 >= args.len) fatal("expected argument after '{s}'", .{arg}); | 5025 | if (i + 1 >= args.len) fatal("expected argument after '{s}'", .{arg}); |
| 5017 | try child_argv.appendSlice(args[i .. i + 2]); | 5026 | try child_argv.appendSlice(arena, args[i .. i + 2]); |
| 5018 | i += 1; | 5027 | i += 1; |
| 5019 | if (!build_options.enable_logging) { | 5028 | if (!build_options.enable_logging) { |
| 5020 | warn("Zig was compiled without logging enabled (-Dlog). --debug-log has no effect.", .{}); | 5029 | warn("Zig was compiled without logging enabled (-Dlog). --debug-log has no effect.", .{}); |
| ... | @@ -5070,7 +5079,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8, | ... | @@ -5070,7 +5079,7 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8, |
| 5070 | color = std.meta.stringToEnum(Color, args[i]) orelse { | 5079 | color = std.meta.stringToEnum(Color, args[i]) orelse { |
| 5071 | fatal("expected [auto|on|off] after {s}, found '{s}'", .{ arg, args[i] }); | 5080 | fatal("expected [auto|on|off] after {s}, found '{s}'", .{ arg, args[i] }); |
| 5072 | }; | 5081 | }; |
| 5073 | try child_argv.appendSlice(&.{ arg, args[i] }); | 5082 | try child_argv.appendSlice(arena, &.{ arg, args[i] }); |
| 5074 | continue; | 5083 | continue; |
| 5075 | } else if (mem.cutPrefix(u8, arg, "-j")) |str| { | 5084 | } else if (mem.cutPrefix(u8, arg, "-j")) |str| { |
| 5076 | const num = std.fmt.parseUnsigned(u32, str, 10) catch |err| { | 5085 | const num = std.fmt.parseUnsigned(u32, str, 10) catch |err| { |
| ... | @@ -5090,11 +5099,11 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8, | ... | @@ -5090,11 +5099,11 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8, |
| 5090 | } else if (mem.eql(u8, arg, "--")) { | 5099 | } else if (mem.eql(u8, arg, "--")) { |
| 5091 | // The rest of the args are supposed to get passed onto | 5100 | // The rest of the args are supposed to get passed onto |
| 5092 | // build runner's `build.args` | 5101 | // build runner's `build.args` |
| 5093 | try child_argv.appendSlice(args[i..]); | 5102 | try child_argv.appendSlice(arena, args[i..]); |
| 5094 | break; | 5103 | break; |
| 5095 | } | 5104 | } |
| 5096 | } | 5105 | } |
| 5097 | try child_argv.append(arg); | 5106 | try child_argv.append(arena, arg); |
| 5098 | } | 5107 | } |
| 5099 | } | 5108 | } |
| 5100 | 5109 | ||
| ... | @@ -5182,6 +5191,25 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8, | ... | @@ -5182,6 +5191,25 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8, |
| 5182 | defer http_client.deinit(); | 5191 | defer http_client.deinit(); |
| 5183 | 5192 | ||
| 5184 | var unlazy_set: Package.Fetch.JobQueue.UnlazySet = .{}; | 5193 | var unlazy_set: Package.Fetch.JobQueue.UnlazySet = .{}; |
| 5194 | var fork_set: Package.Fetch.JobQueue.ForkSet = .{}; | ||
| 5195 | |||
| 5196 | { | ||
| 5197 | // Populate fork_set. | ||
| 5198 | var group: Io.Group = .init; | ||
| 5199 | defer group.cancel(io); | ||
| 5200 | |||
| 5201 | for (forks.items) |*fork| | ||
| 5202 | group.async(io, loadFork, .{ io, gpa, fork, color }); | ||
| 5203 | |||
| 5204 | try group.await(io); | ||
| 5205 | |||
| 5206 | for (forks.items) |*fork| { | ||
| 5207 | const project_id = fork.project_id catch |err| switch (err) { | ||
| 5208 | error.AlreadyReported => process.exit(1), | ||
| 5209 | }; | ||
| 5210 | try fork_set.put(arena, project_id, fork.path); | ||
| 5211 | } | ||
| 5212 | } | ||
| 5185 | 5213 | ||
| 5186 | // This loop is re-evaluated when the build script exits with an indication that it | 5214 | // This loop is re-evaluated when the build script exits with an indication that it |
| 5187 | // could not continue due to missing lazy dependencies. | 5215 | // could not continue due to missing lazy dependencies. |
| ... | @@ -5518,6 +5546,61 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8, | ... | @@ -5518,6 +5546,61 @@ fn cmdBuild(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8, |
| 5518 | } | 5546 | } |
| 5519 | } | 5547 | } |
| 5520 | 5548 | ||
| 5549 | const Fork = struct { | ||
| 5550 | path: Path, | ||
| 5551 | project_id: error{AlreadyReported}!Package.ProjectId, | ||
| 5552 | }; | ||
| 5553 | |||
| 5554 | fn loadFork(io: Io, gpa: Allocator, fork: *Fork, color: Color) Io.Cancelable!void { | ||
| 5555 | fork.project_id = loadForkFallible(io, gpa, fork, color) catch |err| switch (err) { | ||
| 5556 | error.Canceled => |e| return e, | ||
| 5557 | error.AlreadyReported => |e| e, | ||
| 5558 | else => |e| e: { | ||
| 5559 | std.log.err("failed to load fork at {f}: {t}", .{ fork.path, e }); | ||
| 5560 | break :e error.AlreadyReported; | ||
| 5561 | }, | ||
| 5562 | }; | ||
| 5563 | } | ||
| 5564 | |||
| 5565 | fn loadForkFallible(io: Io, gpa: Allocator, fork: *Fork, color: Color) !Package.ProjectId { | ||
| 5566 | var arena_instance = std.heap.ArenaAllocator.init(gpa); | ||
| 5567 | defer arena_instance.deinit(); | ||
| 5568 | const arena = arena_instance.allocator(); | ||
| 5569 | |||
| 5570 | var error_bundle: std.zig.ErrorBundle.Wip = undefined; | ||
| 5571 | try error_bundle.init(gpa); | ||
| 5572 | defer error_bundle.deinit(); | ||
| 5573 | |||
| 5574 | const manifest_path = try fork.path.join(arena, Package.Manifest.basename); | ||
| 5575 | |||
| 5576 | var manifest_ast: std.zig.Ast = undefined; | ||
| 5577 | var manifest: Package.Manifest = undefined; | ||
| 5578 | |||
| 5579 | Package.Manifest.load( | ||
| 5580 | io, | ||
| 5581 | arena, | ||
| 5582 | manifest_path, | ||
| 5583 | &manifest_ast, | ||
| 5584 | &error_bundle, | ||
| 5585 | &manifest, | ||
| 5586 | true, | ||
| 5587 | ) catch |err| switch (err) { | ||
| 5588 | error.Canceled => |e| return e, | ||
| 5589 | error.ErrorsBundled => { | ||
| 5590 | assert(error_bundle.root_list.items.len > 0); | ||
| 5591 | var errors = try error_bundle.toOwnedBundle(""); | ||
| 5592 | errors.renderToStderr(io, .{}, color) catch {}; | ||
| 5593 | return error.AlreadyReported; | ||
| 5594 | }, | ||
| 5595 | else => |e| { | ||
| 5596 | std.log.err("failed to load package manifest {f}: {t}", .{ manifest_path, e }); | ||
| 5597 | return error.AlreadyReported; | ||
| 5598 | }, | ||
| 5599 | }; | ||
| 5600 | |||
| 5601 | return .init(manifest.name, manifest.id); | ||
| 5602 | } | ||
| 5603 | |||
| 5521 | const JitCmdOptions = struct { | 5604 | const JitCmdOptions = struct { |
| 5522 | cmd_name: []const u8, | 5605 | cmd_name: []const u8, |
| 5523 | root_src_path: []const u8, | 5606 | root_src_path: []const u8, |
| ... | @@ -7410,7 +7493,7 @@ fn loadManifest( | ... | @@ -7410,7 +7493,7 @@ fn loadManifest( |
| 7410 | process.exit(2); | 7493 | process.exit(2); |
| 7411 | } | 7494 | } |
| 7412 | 7495 | ||
| 7413 | var manifest = try Package.Manifest.parse(gpa, ast, rng.interface(), .{}); | 7496 | var manifest = try Package.Manifest.parse(gpa, &ast, rng.interface(), .{}); |
| 7414 | errdefer manifest.deinit(gpa); | 7497 | errdefer manifest.deinit(gpa); |
| 7415 | 7498 | ||
| 7416 | if (manifest.errors.len > 0) { | 7499 | if (manifest.errors.len > 0) { |