authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-10-17 20:20:22-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-10-17 20:20:22-04:00
log299991019dddb2acd076d4b2698a4fd6a7a6ae94
tree340707c9bf119b7e3cbb5b425cf6b3de533b15fa
parenta73c7bcaf997fddd3aa746104e930cef8b08a934
signaturelock-open Commit is signed but in an unrecognized format.

rework the progress module and integrate with stage1


13 files changed, 464 insertions(+), 167 deletions(-)

lib/std/fmt.zig+10-3
......@@ -1055,14 +1055,21 @@ const BufPrintContext = struct {
10551055};
10561056
10571057fn bufPrintWrite(context: *BufPrintContext, bytes: []const u8) !void {
1058 if (context.remaining.len < bytes.len) return error.BufferTooSmall;
1058 if (context.remaining.len < bytes.len) {
1059 mem.copy(u8, context.remaining, bytes[0..context.remaining.len]);
1060 return error.BufferTooSmall;
1061 }
10591062 mem.copy(u8, context.remaining, bytes);
10601063 context.remaining = context.remaining[bytes.len..];
10611064}
10621065
1063pub fn bufPrint(buf: []u8, comptime fmt: []const u8, args: ...) ![]u8 {
1066pub const BufPrintError = error{
1067 /// As much as possible was written to the buffer, but it was too small to fit all the printed bytes.
1068 BufferTooSmall,
1069};
1070pub fn bufPrint(buf: []u8, comptime fmt: []const u8, args: ...) BufPrintError![]u8 {
10641071 var context = BufPrintContext{ .remaining = buf };
1065 try format(&context, error{BufferTooSmall}, bufPrintWrite, fmt, args);
1072 try format(&context, BufPrintError, bufPrintWrite, fmt, args);
10661073 return buf[0 .. buf.len - context.remaining.len];
10671074}
10681075
lib/std/progress.zig+212-77
......@@ -1,107 +1,242 @@
11const std = @import("std");
22const testing = std.testing;
3const assert = std.debug.assert;
4
5/// This API is non-allocating and non-fallible. The tradeoff is that users of
6/// this API must provide the storage for each `Progress.Node`.
7/// Initialize the struct directly, overriding these fields as desired:
8/// * `refresh_rate_ms`
9/// * `initial_delay_ms`
10pub const Progress = struct {
11 /// `null` if the current node (and its children) should
12 /// not print on update()
13 terminal: ?std.fs.File = undefined,
14
15 root: Node = undefined,
16
17 /// Keeps track of how much time has passed since the beginning.
18 /// Used to compare with `initial_delay_ms` and `refresh_rate_ms`.
19 timer: std.time.Timer = undefined,
20
21 /// When the previous refresh was written to the terminal.
22 /// Used to compare with `refresh_rate_ms`.
23 prev_refresh_timestamp: u64 = undefined,
24
25 /// This buffer represents the maximum number of bytes written to the terminal
26 /// with each refresh.
27 output_buffer: [100]u8 = undefined,
28
29 /// Keeps track of how many columns in the terminal have been output, so that
30 /// we can move the cursor back later.
31 columns_written: usize = undefined,
32
33 /// How many nanoseconds between writing updates to the terminal.
34 refresh_rate_ns: u64 = 50 * std.time.millisecond,
35
36 /// How many nanoseconds to keep the output hidden
37 initial_delay_ns: u64 = 500 * std.time.millisecond,
38
39 done: bool = true,
40
41 /// Represents one unit of progress. Each node can have children nodes, or
42 /// one can use integers with `update`.
43 pub const Node = struct {
44 context: *Progress,
45 parent: ?*Node,
46 completed_items: usize,
47 name: []const u8,
48 recently_updated_child: ?*Node = null,
49
50 /// This field may be updated freely.
51 estimated_total_items: ?usize,
52
53 /// Create a new child progress node.
54 /// Call `Node.end` when done.
55 /// TODO solve https://github.com/ziglang/zig/issues/2765 and then change this
56 /// API to set `self.parent.recently_updated_child` with the return value.
57 /// Until that is fixed you probably want to call `activate` on the return value.
58 pub fn start(self: *Node, name: []const u8, estimated_total_items: ?usize) Node {
59 return Node{
60 .context = self.context,
61 .parent = self,
62 .completed_items = 0,
63 .name = name,
64 .estimated_total_items = estimated_total_items,
65 };
66 }
367
4pub const PrintConfig = struct {
5 /// If the current node (and its children) should
6 /// print to stderr on update()
7 flag: bool = false,
68 /// This is the same as calling `start` and then `end` on the returned `Node`.
69 pub fn completeOne(self: *Node) void {
70 if (self.parent) |parent| parent.recently_updated_child = self;
71 self.completed_items += 1;
72 self.context.maybeRefresh();
73 }
874
9 /// If all output should be suppressed instead
10 /// serves the same practical purpose as `flag` but supposed to be used
11 /// by separate parts of the user program.
12 suppress: bool = false,
13};
75 pub fn end(self: *Node) void {
76 self.context.maybeRefresh();
77 if (self.parent) |parent| {
78 if (parent.recently_updated_child) |parent_child| {
79 if (parent_child == self) {
80 parent.recently_updated_child = null;
81 }
82 }
83 parent.completeOne();
84 } else {
85 self.context.done = true;
86 self.context.refresh();
87 }
88 }
1489
15pub const ProgressNode = struct {
16 completed_items: usize = 0,
17 total_items: usize,
90 /// Tell the parent node that this node is actively being worked on.
91 pub fn activate(self: *Node) void {
92 if (self.parent) |parent| parent.recently_updated_child = self;
93 }
94 };
1895
19 print_config: PrintConfig,
96 /// Create a new progress node.
97 /// Call `Node.end` when done.
98 /// TODO solve https://github.com/ziglang/zig/issues/2765 and then change this
99 /// API to return Progress rather than accept it as a parameter.
100 pub fn start(self: *Progress, name: []const u8, estimated_total_items: ?usize) !*Node {
101 if (std.io.getStdErr()) |stderr| {
102 const is_term = stderr.isTty();
103 self.terminal = if (is_term) stderr else null;
104 } else |_| {
105 self.terminal = null;
106 }
107 self.root = Node{
108 .context = self,
109 .parent = null,
110 .completed_items = 0,
111 .name = name,
112 .estimated_total_items = estimated_total_items,
113 };
114 self.prev_refresh_timestamp = 0;
115 self.columns_written = 0;
116 self.timer = try std.time.Timer.start();
117 self.done = false;
118 return &self.root;
119 }
20120
21 // TODO maybe instead of keeping a prefix field, we could
22 // select the proper prefix at the time of update(), and if we're not
23 // in a terminal, we use warn("/r{}", lots_of_whitespace).
24 prefix: []const u8,
121 /// Updates the terminal if enough time has passed since last update.
122 pub fn maybeRefresh(self: *Progress) void {
123 const now = self.timer.read();
124 if (now < self.initial_delay_ns) return;
125 if (now - self.prev_refresh_timestamp < self.refresh_rate_ns) return;
126 self.refresh();
127 }
25128
26 /// Create a new progress node.
27 pub fn start(
28 parent_opt: ?ProgressNode,
29 total_items_opt: ?usize,
30 ) !ProgressNode {
31
32 // inherit the last set print "configuration" from the parent node
33 var print_config = PrintConfig{};
34 if (parent_opt) |parent| {
35 print_config = parent.print_config;
129 /// Updates the terminal and resets `self.next_refresh_timestamp`.
130 pub fn refresh(self: *Progress) void {
131 const file = self.terminal orelse return;
132
133 const prev_columns_written = self.columns_written;
134 var end: usize = 0;
135 if (self.columns_written > 0) {
136 end += (std.fmt.bufPrint(self.output_buffer[end..], "\x1b[{}D", self.columns_written) catch unreachable).len;
137 self.columns_written = 0;
36138 }
37139
38 var stderr = try std.io.getStdErr();
39 const is_term = std.os.isatty(stderr.handle);
140 if (!self.done) {
141 self.bufWriteNode(self.root, &end);
142 self.bufWrite(&end, "...");
143 }
40144
41 // if we're in a terminal, use vt100 escape codes
42 // for the progress.
43 var prefix: []const u8 = undefined;
44 if (is_term) {
45 prefix = "\x21[2K\r";
46 } else {
47 prefix = "\n";
145 if (prev_columns_written > self.columns_written) {
146 const amt = prev_columns_written - self.columns_written;
147 std.mem.set(u8, self.output_buffer[end .. end + amt], ' ');
148 end += amt;
149 end += (std.fmt.bufPrint(self.output_buffer[end..], "\x1b[{}D", amt) catch unreachable).len;
48150 }
49151
50 return ProgressNode{
51 .total_items = total_items_opt orelse 0,
52 .print_config = print_config,
53 .prefix = prefix,
152 _ = file.write(self.output_buffer[0..end]) catch |e| {
153 // Stop trying to write to this file once it errors.
154 self.terminal = null;
54155 };
156 self.prev_refresh_timestamp = self.timer.read();
55157 }
56158
57 /// Signal an update on the progress node.
58 /// The user of this function is supposed to modify
59 /// ProgressNode.PrintConfig.flag when update() is supposed to print.
60 pub fn update(
61 self: *ProgressNode,
62 current_action: ?[]const u8,
63 items_done_opt: ?usize,
64 ) void {
65 if (items_done_opt) |items_done| {
66 self.completed_items = items_done;
67
68 if (items_done > self.total_items) {
69 self.total_items = items_done;
159 fn bufWriteNode(self: *Progress, node: Node, end: *usize) void {
160 if (node.name.len != 0 or node.estimated_total_items != null) {
161 if (node.name.len != 0) {
162 self.bufWrite(end, "{}", node.name);
163 if (node.recently_updated_child != null or node.estimated_total_items != null or
164 node.completed_items != 0)
165 {
166 self.bufWrite(end, "...");
167 }
168 }
169 if (node.estimated_total_items) |total| {
170 self.bufWrite(end, "[{}/{}] ", node.completed_items, total);
171 } else if (node.completed_items != 0) {
172 self.bufWrite(end, "[{}] ", node.completed_items);
70173 }
71174 }
72
73 var cfg = self.print_config;
74 if (cfg.flag and !cfg.suppress and current_action != null) {
75 std.debug.warn(
76 "{}[{}/{}] {}",
77 self.prefix,
78 self.completed_items,
79 self.total_items,
80 current_action,
81 );
175 if (node.recently_updated_child) |child| {
176 self.bufWriteNode(child.*, end);
82177 }
83178 }
84179
85 pub fn end(self: *ProgressNode) void {
86 if (!self.print_config.flag) return;
87
88 // TODO emoji?
89 std.debug.warn("\n[V] done!");
180 fn bufWrite(self: *Progress, end: *usize, comptime format: []const u8, args: ...) void {
181 if (std.fmt.bufPrint(self.output_buffer[end.*..], format, args)) |written| {
182 const amt = written.len;
183 end.* += amt;
184 self.columns_written += amt;
185 } else |err| switch (err) {
186 error.BufferTooSmall => {
187 self.columns_written += self.output_buffer.len - end.*;
188 end.* = self.output_buffer.len;
189 },
190 }
191 const bytes_needed_for_esc_codes_at_end = 11;
192 const max_end = self.output_buffer.len - bytes_needed_for_esc_codes_at_end;
193 if (end.* > max_end) {
194 const suffix = "...";
195 self.columns_written = self.columns_written - (end.* - max_end) + suffix.len;
196 std.mem.copy(u8, self.output_buffer[max_end..], suffix);
197 end.* = max_end + suffix.len;
198 }
90199 }
91200};
92201
93202test "basic functionality" {
94 var node = try ProgressNode.start(null, 100);
95
96 var buf: [100]u8 = undefined;
203 var progress = Progress{};
204 const root_node = try progress.start("", 100);
205 defer root_node.end();
206
207 const sub_task_names = [_][]const u8{
208 "reticulating splines",
209 "adjusting shoes",
210 "climbing towers",
211 "pouring juice",
212 };
213 var next_sub_task: usize = 0;
97214
98215 var i: usize = 0;
99 while (i < 100) : (i += 6) {
100 if (i > 50) node.print_config.flag = true;
101 const msg = try std.fmt.bufPrint(buf[0..], "action at i={}", i);
102 node.update(msg, i);
216 while (i < 100) : (i += 1) {
217 var node = root_node.start(sub_task_names[next_sub_task], 5);
218 node.activate();
219 next_sub_task = (next_sub_task + 1) % sub_task_names.len;
220
221 node.completeOne();
222 std.time.sleep(5 * std.time.millisecond);
223 node.completeOne();
224 node.completeOne();
225 std.time.sleep(5 * std.time.millisecond);
226 node.completeOne();
227 node.completeOne();
228 std.time.sleep(5 * std.time.millisecond);
229
230 node.end();
231
232 std.time.sleep(5 * std.time.millisecond);
233 }
234 {
235 var node = root_node.start("this is a really long name designed to activate the truncation code. let's find out if it works", null);
236 node.activate();
103237 std.time.sleep(10 * std.time.millisecond);
238 progress.maybeRefresh();
239 std.time.sleep(10 * std.time.millisecond);
240 node.end();
104241 }
105
106 node.end();
107242}
lib/std/std.zig+6-5
......@@ -6,20 +6,21 @@ pub const BufMap = @import("buf_map.zig").BufMap;
66pub const BufSet = @import("buf_set.zig").BufSet;
77pub const Buffer = @import("buffer.zig").Buffer;
88pub const BufferOutStream = @import("io.zig").BufferOutStream;
9pub const ChildProcess = @import("child_process.zig").ChildProcess;
910pub const DynLib = @import("dynamic_library.zig").DynLib;
1011pub const HashMap = @import("hash_map.zig").HashMap;
1112pub const Mutex = @import("mutex.zig").Mutex;
12pub const PackedIntArrayEndian = @import("packed_int_array.zig").PackedIntArrayEndian;
1313pub const PackedIntArray = @import("packed_int_array.zig").PackedIntArray;
14pub const PackedIntSliceEndian = @import("packed_int_array.zig").PackedIntSliceEndian;
14pub const PackedIntArrayEndian = @import("packed_int_array.zig").PackedIntArrayEndian;
1515pub const PackedIntSlice = @import("packed_int_array.zig").PackedIntSlice;
16pub const PackedIntSliceEndian = @import("packed_int_array.zig").PackedIntSliceEndian;
1617pub const PriorityQueue = @import("priority_queue.zig").PriorityQueue;
17pub const SinglyLinkedList = @import("linked_list.zig").SinglyLinkedList;
18pub const StaticallyInitializedMutex = @import("statically_initialized_mutex.zig").StaticallyInitializedMutex;
18pub const Progress = @import("progress.zig").Progress;
1919pub const SegmentedList = @import("segmented_list.zig").SegmentedList;
20pub const SinglyLinkedList = @import("linked_list.zig").SinglyLinkedList;
2021pub const SpinLock = @import("spinlock.zig").SpinLock;
22pub const StaticallyInitializedMutex = @import("statically_initialized_mutex.zig").StaticallyInitializedMutex;
2123pub const StringHashMap = @import("hash_map.zig").StringHashMap;
22pub const ChildProcess = @import("child_process.zig").ChildProcess;
2324pub const TailQueue = @import("linked_list.zig").TailQueue;
2425pub const Thread = @import("thread.zig").Thread;
2526
src-self-hosted/stage1.zig+49
......@@ -456,3 +456,52 @@ export fn stage2_attach_segfault_handler() void {
456456 std.debug.attachSegfaultHandler();
457457 }
458458}
459
460// ABI warning
461export fn stage2_progress_create() *std.Progress {
462 const ptr = std.heap.c_allocator.create(std.Progress) catch @panic("out of memory");
463 ptr.* = std.Progress{};
464 return ptr;
465}
466
467// ABI warning
468export fn stage2_progress_destroy(progress: *std.Progress) void {
469 std.heap.c_allocator.destroy(progress);
470}
471
472// ABI warning
473export fn stage2_progress_start_root(progress: *std.Progress, name_ptr: [*]const u8, name_len: usize, estimated_total_items: usize) *std.Progress.Node {
474 return progress.start(
475 name_ptr[0..name_len],
476 if (estimated_total_items == 0) null else estimated_total_items,
477 ) catch @panic("timer unsupported");
478}
479
480// ABI warning
481export fn stage2_progress_start(
482 node: *std.Progress.Node,
483 name_ptr: [*]const u8,
484 name_len: usize,
485 estimated_total_items: usize,
486) *std.Progress.Node {
487 const child_node = std.heap.c_allocator.create(std.Progress.Node) catch @panic("out of memory");
488 child_node.* = node.start(
489 name_ptr[0..name_len],
490 if (estimated_total_items == 0) null else estimated_total_items,
491 );
492 child_node.activate();
493 return child_node;
494}
495
496// ABI warning
497export fn stage2_progress_end(node: *std.Progress.Node) void {
498 node.end();
499 if (&node.context.root != node) {
500 std.heap.c_allocator.destroy(node);
501 }
502}
503
504// ABI warning
505export fn stage2_progress_complete_one(node: *std.Progress.Node) void {
506 node.completeOne();
507}
src/all_types.hpp+2
......@@ -2010,6 +2010,8 @@ struct CodeGen {
20102010
20112011 ZigFn *largest_frame_fn;
20122012
2013 Stage2ProgressNode *progress_node;
2014
20132015 WantPIC want_pic;
20142016 WantStackCheck want_stack_check;
20152017 CacheHash cache_hash;
src/codegen.cpp+45-6
......@@ -7610,7 +7610,7 @@ static void zig_llvm_emit_output(CodeGen *g) {
76107610 if (g->bundle_compiler_rt && (g->out_type == OutTypeObj ||
76117611 (g->out_type == OutTypeLib && !g->is_dynamic)))
76127612 {
7613 zig_link_add_compiler_rt(g);
7613 zig_link_add_compiler_rt(g, g->progress_node);
76147614 }
76157615 break;
76167616
......@@ -9453,7 +9453,7 @@ Error create_c_object_cache(CodeGen *g, CacheHash **out_cache_hash, bool verbose
94539453}
94549454
94559455// returns true if it was a cache miss
9456static void gen_c_object(CodeGen *g, Buf *self_exe_path, CFile *c_file) {
9456static void gen_c_object(CodeGen *g, Buf *self_exe_path, CFile *c_file, Stage2ProgressNode *parent_prog_node) {
94579457 Error err;
94589458
94599459 Buf *artifact_dir;
......@@ -9464,6 +9464,10 @@ static void gen_c_object(CodeGen *g, Buf *self_exe_path, CFile *c_file) {
94649464 Buf *c_source_file = buf_create_from_str(c_file->source_path);
94659465 Buf *c_source_basename = buf_alloc();
94669466 os_path_split(c_source_file, nullptr, c_source_basename);
9467
9468 Stage2ProgressNode *child_prog_node = stage2_progress_start(parent_prog_node, buf_ptr(c_source_basename),
9469 buf_len(c_source_basename), 0);
9470
94679471 Buf *final_o_basename = buf_alloc();
94689472 os_path_extname(c_source_basename, final_o_basename, nullptr);
94699473 buf_append_str(final_o_basename, target_o_file_ext(g->zig_target));
......@@ -9580,6 +9584,8 @@ static void gen_c_object(CodeGen *g, Buf *self_exe_path, CFile *c_file) {
95809584
95819585 g->link_objects.append(o_final_path);
95829586 g->caches_to_release.append(cache_hash);
9587
9588 stage2_progress_end(child_prog_node);
95839589}
95849590
95859591// returns true if we had any cache misses
......@@ -9596,11 +9602,16 @@ static void gen_c_objects(CodeGen *g) {
95969602 }
95979603
95989604 codegen_add_time_event(g, "Compile C Code");
9605 const char *c_prog_name = "compiling C objects";
9606 Stage2ProgressNode *c_prog_node = stage2_progress_start(g->progress_node, c_prog_name, strlen(c_prog_name),
9607 g->c_source_files.length);
95999608
96009609 for (size_t c_file_i = 0; c_file_i < g->c_source_files.length; c_file_i += 1) {
96019610 CFile *c_file = g->c_source_files.at(c_file_i);
9602 gen_c_object(g, self_exe_path, c_file);
9611 gen_c_object(g, self_exe_path, c_file, c_prog_node);
96039612 }
9613
9614 stage2_progress_end(c_prog_node);
96049615}
96059616
96069617void codegen_add_object(CodeGen *g, Buf *object_path) {
......@@ -10320,6 +10331,10 @@ void codegen_build_and_link(CodeGen *g) {
1032010331 init(g);
1032110332
1032210333 codegen_add_time_event(g, "Semantic Analysis");
10334 const char *progress_name = "Semantic Analysis";
10335 Stage2ProgressNode *child_progress_node = stage2_progress_start(g->progress_node,
10336 progress_name, strlen(progress_name), 0);
10337 (void)child_progress_node;
1032310338
1032410339 gen_root_source(g);
1032510340
......@@ -10343,13 +10358,31 @@ void codegen_build_and_link(CodeGen *g) {
1034310358
1034410359 if (need_llvm_module(g)) {
1034510360 codegen_add_time_event(g, "Code Generation");
10361 {
10362 const char *progress_name = "Code Generation";
10363 Stage2ProgressNode *child_progress_node = stage2_progress_start(g->progress_node,
10364 progress_name, strlen(progress_name), 0);
10365 (void)child_progress_node;
10366 }
1034610367
1034710368 do_code_gen(g);
1034810369 codegen_add_time_event(g, "LLVM Emit Output");
10370 {
10371 const char *progress_name = "LLVM Emit Output";
10372 Stage2ProgressNode *child_progress_node = stage2_progress_start(g->progress_node,
10373 progress_name, strlen(progress_name), 0);
10374 (void)child_progress_node;
10375 }
1034910376 zig_llvm_emit_output(g);
1035010377
1035110378 if (!g->disable_gen_h && (g->out_type == OutTypeObj || g->out_type == OutTypeLib)) {
1035210379 codegen_add_time_event(g, "Generate .h");
10380 {
10381 const char *progress_name = "Generate .h";
10382 Stage2ProgressNode *child_progress_node = stage2_progress_start(g->progress_node,
10383 progress_name, strlen(progress_name), 0);
10384 (void)child_progress_node;
10385 }
1035310386 gen_h_file(g);
1035410387 }
1035510388 }
......@@ -10446,10 +10479,15 @@ ZigPackage *codegen_create_package(CodeGen *g, const char *root_src_dir, const c
1044610479}
1044710480
1044810481CodeGen *create_child_codegen(CodeGen *parent_gen, Buf *root_src_path, OutType out_type,
10449 ZigLibCInstallation *libc)
10482 ZigLibCInstallation *libc, const char *name, Stage2ProgressNode *child_progress_node)
1045010483{
10484 if (!child_progress_node) {
10485 child_progress_node = stage2_progress_start(parent_gen->progress_node, name, strlen(name), 0);
10486 }
10487
1045110488 CodeGen *child_gen = codegen_create(nullptr, root_src_path, parent_gen->zig_target, out_type,
10452 parent_gen->build_mode, parent_gen->zig_lib_dir, libc, get_stage1_cache_path(), false);
10489 parent_gen->build_mode, parent_gen->zig_lib_dir, libc, get_stage1_cache_path(), false, child_progress_node);
10490 child_gen->root_out_name = buf_create_from_str(name);
1045310491 child_gen->disable_gen_h = true;
1045410492 child_gen->want_stack_check = WantStackCheckDisabled;
1045510493 child_gen->verbose_tokenize = parent_gen->verbose_tokenize;
......@@ -10478,9 +10516,10 @@ CodeGen *create_child_codegen(CodeGen *parent_gen, Buf *root_src_path, OutType o
1047810516
1047910517CodeGen *codegen_create(Buf *main_pkg_path, Buf *root_src_path, const ZigTarget *target,
1048010518 OutType out_type, BuildMode build_mode, Buf *override_lib_dir,
10481 ZigLibCInstallation *libc, Buf *cache_dir, bool is_test_build)
10519 ZigLibCInstallation *libc, Buf *cache_dir, bool is_test_build, Stage2ProgressNode *progress_node)
1048210520{
1048310521 CodeGen *g = allocate<CodeGen>(1);
10522 g->progress_node = progress_node;
1048410523
1048510524 codegen_add_time_event(g, "Initialize");
1048610525
src/codegen.hpp+3-3
......@@ -18,10 +18,10 @@
1818
1919CodeGen *codegen_create(Buf *main_pkg_path, Buf *root_src_path, const ZigTarget *target,
2020 OutType out_type, BuildMode build_mode, Buf *zig_lib_dir,
21 ZigLibCInstallation *libc, Buf *cache_dir, bool is_test_build);
21 ZigLibCInstallation *libc, Buf *cache_dir, bool is_test_build, Stage2ProgressNode *progress_node);
2222
2323CodeGen *create_child_codegen(CodeGen *parent_gen, Buf *root_src_path, OutType out_type,
24 ZigLibCInstallation *libc);
24 ZigLibCInstallation *libc, const char *name, Stage2ProgressNode *progress_node);
2525
2626void codegen_set_clang_argv(CodeGen *codegen, const char **args, size_t len);
2727void codegen_set_llvm_argv(CodeGen *codegen, const char **args, size_t len);
......@@ -46,7 +46,7 @@ void codegen_set_lib_version(CodeGen *g, size_t major, size_t minor, size_t patc
4646void codegen_add_time_event(CodeGen *g, const char *name);
4747void codegen_print_timing_report(CodeGen *g, FILE *f);
4848void codegen_link(CodeGen *g);
49void zig_link_add_compiler_rt(CodeGen *g);
49void zig_link_add_compiler_rt(CodeGen *g, Stage2ProgressNode *progress_node);
5050void codegen_build_and_link(CodeGen *g);
5151
5252ZigPackage *codegen_create_package(CodeGen *g, const char *root_src_dir, const char *root_src_path,
src/glibc.cpp+2-3
......@@ -169,7 +169,7 @@ Error glibc_load_metadata(ZigGLibCAbi **out_result, Buf *zig_lib_dir, bool verbo
169169}
170170
171171Error glibc_build_dummies_and_maps(CodeGen *g, const ZigGLibCAbi *glibc_abi, const ZigTarget *target,
172 Buf **out_dir, bool verbose)
172 Buf **out_dir, bool verbose, Stage2ProgressNode *progress_node)
173173{
174174 Error err;
175175
......@@ -332,8 +332,7 @@ Error glibc_build_dummies_and_maps(CodeGen *g, const ZigGLibCAbi *glibc_abi, con
332332 return err;
333333 }
334334
335 CodeGen *child_gen = create_child_codegen(g, zig_file_path, OutTypeLib, nullptr);
336 codegen_set_out_name(child_gen, buf_create_from_str(lib->name));
335 CodeGen *child_gen = create_child_codegen(g, zig_file_path, OutTypeLib, nullptr, lib->name, progress_node);
337336 codegen_set_lib_version(child_gen, lib->sover, 0, 0);
338337 child_gen->is_dynamic = true;
339338 child_gen->is_dummy_so = true;
src/glibc.hpp+1-1
......@@ -41,7 +41,7 @@ struct ZigGLibCAbi {
4141
4242Error glibc_load_metadata(ZigGLibCAbi **out_result, Buf *zig_lib_dir, bool verbose);
4343Error glibc_build_dummies_and_maps(CodeGen *codegen, const ZigGLibCAbi *glibc_abi, const ZigTarget *target,
44 Buf **out_dir, bool verbose);
44 Buf **out_dir, bool verbose, Stage2ProgressNode *progress_node);
4545
4646// returns ErrorUnknownABI when glibc is not the native libc
4747Error glibc_detect_native_version(ZigGLibCVersion *glibc_ver);
src/link.cpp+76-66
......@@ -594,11 +594,13 @@ struct LinkJob {
594594 ZigList<const char *> args;
595595 bool link_in_crt;
596596 HashMap<Buf *, bool, buf_hash, buf_eql_buf> rpath_table;
597 Stage2ProgressNode *build_dep_prog_node;
597598};
598599
599static const char *build_libc_object(CodeGen *parent_gen, const char *name, CFile *c_file) {
600 CodeGen *child_gen = create_child_codegen(parent_gen, nullptr, OutTypeObj, nullptr);
601 codegen_set_out_name(child_gen, buf_create_from_str(name));
600static const char *build_libc_object(CodeGen *parent_gen, const char *name, CFile *c_file,
601 Stage2ProgressNode *progress_node)
602{
603 CodeGen *child_gen = create_child_codegen(parent_gen, nullptr, OutTypeObj, nullptr, name, progress_node);
602604 ZigList<CFile *> c_source_files = {0};
603605 c_source_files.append(c_file);
604606 child_gen->c_source_files = c_source_files;
......@@ -622,9 +624,8 @@ static const char *path_from_libunwind(CodeGen *g, const char *subpath) {
622624 return path_from_zig_lib(g, "libunwind", subpath);
623625}
624626
625static const char *build_libunwind(CodeGen *parent) {
626 CodeGen *child_gen = create_child_codegen(parent, nullptr, OutTypeLib, nullptr);
627 codegen_set_out_name(child_gen, buf_create_from_str("unwind"));
627static const char *build_libunwind(CodeGen *parent, Stage2ProgressNode *progress_node) {
628 CodeGen *child_gen = create_child_codegen(parent, nullptr, OutTypeLib, nullptr, "unwind", progress_node);
628629 LinkLib *new_link_lib = codegen_add_link_lib(child_gen, buf_create_from_str("c"));
629630 new_link_lib->provided_explicitly = false;
630631 enum SrcKind {
......@@ -1017,9 +1018,8 @@ static bool is_musl_arch_name(const char *name) {
10171018 return false;
10181019}
10191020
1020static const char *build_musl(CodeGen *parent) {
1021 CodeGen *child_gen = create_child_codegen(parent, nullptr, OutTypeLib, nullptr);
1022 codegen_set_out_name(child_gen, buf_create_from_str("c"));
1021static const char *build_musl(CodeGen *parent, Stage2ProgressNode *progress_node) {
1022 CodeGen *child_gen = create_child_codegen(parent, nullptr, OutTypeLib, nullptr, "c", progress_node);
10231023
10241024 // When there is a src/<arch>/foo.* then it should substitute for src/foo.*
10251025 // Even a .s file can substitute for a .c file.
......@@ -1175,7 +1175,7 @@ static void add_mingwex_os_dep(CodeGen *parent, CodeGen *child_gen, const char *
11751175 child_gen->c_source_files.append(c_file);
11761176}
11771177
1178static const char *get_libc_crt_file(CodeGen *parent, const char *file) {
1178static const char *get_libc_crt_file(CodeGen *parent, const char *file, Stage2ProgressNode *progress_node) {
11791179 if (parent->libc == nullptr && parent->zig_target->os == OsWindows) {
11801180 if (strcmp(file, "crt2.o") == 0) {
11811181 CFile *c_file = allocate<CFile>(1);
......@@ -1188,7 +1188,7 @@ static const char *get_libc_crt_file(CodeGen *parent, const char *file) {
11881188 //c_file->args.append("-DUNICODE");
11891189 //c_file->args.append("-D_UNICODE");
11901190 //c_file->args.append("-DWPRFLAG=1");
1191 return build_libc_object(parent, "crt2", c_file);
1191 return build_libc_object(parent, "crt2", c_file, progress_node);
11921192 } else if (strcmp(file, "dllcrt2.o") == 0) {
11931193 CFile *c_file = allocate<CFile>(1);
11941194 c_file->source_path = buf_ptr(buf_sprintf(
......@@ -1196,10 +1196,9 @@ static const char *get_libc_crt_file(CodeGen *parent, const char *file) {
11961196 mingw_add_cc_args(parent, c_file);
11971197 c_file->args.append("-U__CRTDLL__");
11981198 c_file->args.append("-D__MSVCRT__");
1199 return build_libc_object(parent, "dllcrt2", c_file);
1199 return build_libc_object(parent, "dllcrt2", c_file, progress_node);
12001200 } else if (strcmp(file, "mingw32.lib") == 0) {
1201 CodeGen *child_gen = create_child_codegen(parent, nullptr, OutTypeLib, nullptr);
1202 codegen_set_out_name(child_gen, buf_create_from_str("mingw32"));
1201 CodeGen *child_gen = create_child_codegen(parent, nullptr, OutTypeLib, nullptr, "mingw32", progress_node);
12031202
12041203 static const char *deps[] = {
12051204 "mingw" OS_SEP "crt" OS_SEP "crt0_c.c",
......@@ -1256,8 +1255,7 @@ static const char *get_libc_crt_file(CodeGen *parent, const char *file) {
12561255 codegen_build_and_link(child_gen);
12571256 return buf_ptr(&child_gen->output_file_path);
12581257 } else if (strcmp(file, "msvcrt-os.lib") == 0) {
1259 CodeGen *child_gen = create_child_codegen(parent, nullptr, OutTypeLib, nullptr);
1260 codegen_set_out_name(child_gen, buf_create_from_str("msvcrt-os"));
1258 CodeGen *child_gen = create_child_codegen(parent, nullptr, OutTypeLib, nullptr, "msvcrt-os", progress_node);
12611259
12621260 for (size_t i = 0; i < array_length(msvcrt_common_src); i += 1) {
12631261 add_msvcrt_os_dep(parent, child_gen, msvcrt_common_src[i]);
......@@ -1274,8 +1272,7 @@ static const char *get_libc_crt_file(CodeGen *parent, const char *file) {
12741272 codegen_build_and_link(child_gen);
12751273 return buf_ptr(&child_gen->output_file_path);
12761274 } else if (strcmp(file, "mingwex.lib") == 0) {
1277 CodeGen *child_gen = create_child_codegen(parent, nullptr, OutTypeLib, nullptr);
1278 codegen_set_out_name(child_gen, buf_create_from_str("mingwex"));
1275 CodeGen *child_gen = create_child_codegen(parent, nullptr, OutTypeLib, nullptr, "mingwex", progress_node);
12791276
12801277 for (size_t i = 0; i < array_length(mingwex_generic_src); i += 1) {
12811278 add_mingwex_os_dep(parent, child_gen, mingwex_generic_src[i]);
......@@ -1318,7 +1315,7 @@ static const char *get_libc_crt_file(CodeGen *parent, const char *file) {
13181315 c_file->args.append("-DASSEMBLER");
13191316 c_file->args.append("-g");
13201317 c_file->args.append("-Wa,--noexecstack");
1321 return build_libc_object(parent, "crti", c_file);
1318 return build_libc_object(parent, "crti", c_file, progress_node);
13221319 } else if (strcmp(file, "crtn.o") == 0) {
13231320 CFile *c_file = allocate<CFile>(1);
13241321 c_file->source_path = glibc_start_asm_path(parent, "crtn.S");
......@@ -1329,7 +1326,7 @@ static const char *get_libc_crt_file(CodeGen *parent, const char *file) {
13291326 c_file->args.append("-DASSEMBLER");
13301327 c_file->args.append("-g");
13311328 c_file->args.append("-Wa,--noexecstack");
1332 return build_libc_object(parent, "crtn", c_file);
1329 return build_libc_object(parent, "crtn", c_file, progress_node);
13331330 } else if (strcmp(file, "start.os") == 0) {
13341331 CFile *c_file = allocate<CFile>(1);
13351332 c_file->source_path = glibc_start_asm_path(parent, "start.S");
......@@ -1347,7 +1344,7 @@ static const char *get_libc_crt_file(CodeGen *parent, const char *file) {
13471344 c_file->args.append("-DASSEMBLER");
13481345 c_file->args.append("-g");
13491346 c_file->args.append("-Wa,--noexecstack");
1350 return build_libc_object(parent, "start", c_file);
1347 return build_libc_object(parent, "start", c_file, progress_node);
13511348 } else if (strcmp(file, "abi-note.o") == 0) {
13521349 CFile *c_file = allocate<CFile>(1);
13531350 c_file->source_path = path_from_libc(parent, "glibc" OS_SEP "csu" OS_SEP "abi-note.S");
......@@ -1360,19 +1357,17 @@ static const char *get_libc_crt_file(CodeGen *parent, const char *file) {
13601357 c_file->args.append("-DASSEMBLER");
13611358 c_file->args.append("-g");
13621359 c_file->args.append("-Wa,--noexecstack");
1363 return build_libc_object(parent, "abi-note", c_file);
1360 return build_libc_object(parent, "abi-note", c_file, progress_node);
13641361 } else if (strcmp(file, "Scrt1.o") == 0) {
1365 const char *start_os = get_libc_crt_file(parent, "start.os");
1366 const char *abi_note_o = get_libc_crt_file(parent, "abi-note.o");
1367 CodeGen *child_gen = create_child_codegen(parent, nullptr, OutTypeObj, nullptr);
1368 codegen_set_out_name(child_gen, buf_create_from_str("Scrt1"));
1362 const char *start_os = get_libc_crt_file(parent, "start.os", progress_node);
1363 const char *abi_note_o = get_libc_crt_file(parent, "abi-note.o", progress_node);
1364 CodeGen *child_gen = create_child_codegen(parent, nullptr, OutTypeObj, nullptr, "Scrt1", progress_node);
13691365 codegen_add_object(child_gen, buf_create_from_str(start_os));
13701366 codegen_add_object(child_gen, buf_create_from_str(abi_note_o));
13711367 codegen_build_and_link(child_gen);
13721368 return buf_ptr(&child_gen->output_file_path);
13731369 } else if (strcmp(file, "libc_nonshared.a") == 0) {
1374 CodeGen *child_gen = create_child_codegen(parent, nullptr, OutTypeLib, nullptr);
1375 codegen_set_out_name(child_gen, buf_create_from_str("c_nonshared"));
1370 CodeGen *child_gen = create_child_codegen(parent, nullptr, OutTypeLib, nullptr, "c_nonshared", progress_node);
13761371 {
13771372 CFile *c_file = allocate<CFile>(1);
13781373 c_file->source_path = path_from_libc(parent, "glibc" OS_SEP "csu" OS_SEP "elf-init.c");
......@@ -1401,7 +1396,8 @@ static const char *get_libc_crt_file(CodeGen *parent, const char *file) {
14011396 c_file->args.append("-DPIC");
14021397 c_file->args.append("-DLIBC_NONSHARED=1");
14031398 c_file->args.append("-DTOP_NAMESPACE=glibc");
1404 codegen_add_object(child_gen, buf_create_from_str(build_libc_object(parent, "elf-init", c_file)));
1399 codegen_add_object(child_gen, buf_create_from_str(
1400 build_libc_object(parent, "elf-init", c_file, progress_node)));
14051401 }
14061402 static const struct {
14071403 const char *name;
......@@ -1445,7 +1441,8 @@ static const char *get_libc_crt_file(CodeGen *parent, const char *file) {
14451441 c_file->args.append("-DPIC");
14461442 c_file->args.append("-DLIBC_NONSHARED=1");
14471443 c_file->args.append("-DTOP_NAMESPACE=glibc");
1448 codegen_add_object(child_gen, buf_create_from_str(build_libc_object(parent, deps[i].name, c_file)));
1444 codegen_add_object(child_gen, buf_create_from_str(
1445 build_libc_object(parent, deps[i].name, c_file, progress_node)));
14491446 }
14501447 codegen_build_and_link(child_gen);
14511448 return buf_ptr(&child_gen->output_file_path);
......@@ -1458,20 +1455,20 @@ static const char *get_libc_crt_file(CodeGen *parent, const char *file) {
14581455 c_file->source_path = musl_start_asm_path(parent, "crti.s");
14591456 musl_add_cc_args(parent, c_file, false);
14601457 c_file->args.append("-Qunused-arguments");
1461 return build_libc_object(parent, "crti", c_file);
1458 return build_libc_object(parent, "crti", c_file, progress_node);
14621459 } else if (strcmp(file, "crtn.o") == 0) {
14631460 CFile *c_file = allocate<CFile>(1);
14641461 c_file->source_path = musl_start_asm_path(parent, "crtn.s");
14651462 c_file->args.append("-Qunused-arguments");
14661463 musl_add_cc_args(parent, c_file, false);
1467 return build_libc_object(parent, "crtn", c_file);
1464 return build_libc_object(parent, "crtn", c_file, progress_node);
14681465 } else if (strcmp(file, "crt1.o") == 0) {
14691466 CFile *c_file = allocate<CFile>(1);
14701467 c_file->source_path = path_from_libc(parent, "musl" OS_SEP "crt" OS_SEP "crt1.c");
14711468 musl_add_cc_args(parent, c_file, false);
14721469 c_file->args.append("-fno-stack-protector");
14731470 c_file->args.append("-DCRT");
1474 return build_libc_object(parent, "crt1", c_file);
1471 return build_libc_object(parent, "crt1", c_file, progress_node);
14751472 } else if (strcmp(file, "Scrt1.o") == 0) {
14761473 CFile *c_file = allocate<CFile>(1);
14771474 c_file->source_path = path_from_libc(parent, "musl" OS_SEP "crt" OS_SEP "Scrt1.c");
......@@ -1479,7 +1476,7 @@ static const char *get_libc_crt_file(CodeGen *parent, const char *file) {
14791476 c_file->args.append("-fPIC");
14801477 c_file->args.append("-fno-stack-protector");
14811478 c_file->args.append("-DCRT");
1482 return build_libc_object(parent, "Scrt1", c_file);
1479 return build_libc_object(parent, "Scrt1", c_file, progress_node);
14831480 } else {
14841481 zig_unreachable();
14851482 }
......@@ -1491,10 +1488,11 @@ static const char *get_libc_crt_file(CodeGen *parent, const char *file) {
14911488 }
14921489}
14931490
1494static Buf *build_a_raw(CodeGen *parent_gen, const char *aname, Buf *full_path, OutType child_out_type) {
1495 CodeGen *child_gen = create_child_codegen(parent_gen, full_path, child_out_type,
1496 parent_gen->libc);
1497 codegen_set_out_name(child_gen, buf_create_from_str(aname));
1491static Buf *build_a_raw(CodeGen *parent_gen, const char *aname, Buf *full_path, OutType child_out_type,
1492 Stage2ProgressNode *progress_node)
1493{
1494 CodeGen *child_gen = create_child_codegen(parent_gen, full_path, child_out_type, parent_gen->libc, aname,
1495 progress_node);
14981496
14991497 // This is so that compiler_rt and libc.zig libraries know whether they
15001498 // will eventually be linked with libc. They make different decisions
......@@ -1511,18 +1509,18 @@ static Buf *build_a_raw(CodeGen *parent_gen, const char *aname, Buf *full_path,
15111509 return &child_gen->output_file_path;
15121510}
15131511
1514static Buf *build_compiler_rt(CodeGen *parent_gen, OutType child_out_type) {
1512static Buf *build_compiler_rt(CodeGen *parent_gen, OutType child_out_type, Stage2ProgressNode *progress_node) {
15151513 Buf *full_path = buf_alloc();
15161514 os_path_join(parent_gen->zig_std_special_dir, buf_create_from_str("compiler_rt.zig"), full_path);
15171515
1518 return build_a_raw(parent_gen, "compiler_rt", full_path, child_out_type);
1516 return build_a_raw(parent_gen, "compiler_rt", full_path, child_out_type, progress_node);
15191517}
15201518
1521static Buf *build_c(CodeGen *parent_gen, OutType child_out_type) {
1519static Buf *build_c(CodeGen *parent_gen, OutType child_out_type, Stage2ProgressNode *progress_node) {
15221520 Buf *full_path = buf_alloc();
15231521 os_path_join(parent_gen->zig_std_special_dir, buf_create_from_str("c.zig"), full_path);
15241522
1525 return build_a_raw(parent_gen, "c", full_path, child_out_type);
1523 return build_a_raw(parent_gen, "c", full_path, child_out_type, progress_node);
15261524}
15271525
15281526static const char *get_darwin_arch_string(const ZigTarget *t) {
......@@ -1616,7 +1614,7 @@ static void add_glibc_libs(LinkJob *lj) {
16161614
16171615 Buf *artifact_dir;
16181616 if ((err = glibc_build_dummies_and_maps(lj->codegen, glibc_abi, lj->codegen->zig_target,
1619 &artifact_dir, true)))
1617 &artifact_dir, true, lj->build_dep_prog_node)))
16201618 {
16211619 fprintf(stderr, "%s\n", err_str(err));
16221620 exit(1);
......@@ -1692,9 +1690,9 @@ static void construct_linker_job_elf(LinkJob *lj) {
16921690 } else {
16931691 crt1o = "Scrt1.o";
16941692 }
1695 lj->args.append(get_libc_crt_file(g, crt1o));
1693 lj->args.append(get_libc_crt_file(g, crt1o, lj->build_dep_prog_node));
16961694 if (target_libc_needs_crti_crtn(g->zig_target)) {
1697 lj->args.append(get_libc_crt_file(g, "crti.o"));
1695 lj->args.append(get_libc_crt_file(g, "crti.o", lj->build_dep_prog_node));
16981696 }
16991697 }
17001698
......@@ -1759,11 +1757,11 @@ static void construct_linker_job_elf(LinkJob *lj) {
17591757
17601758 if (!g->is_dummy_so && (g->out_type == OutTypeExe || is_dyn_lib)) {
17611759 if (g->libc_link_lib == nullptr) {
1762 Buf *libc_a_path = build_c(g, OutTypeLib);
1760 Buf *libc_a_path = build_c(g, OutTypeLib, lj->build_dep_prog_node);
17631761 lj->args.append(buf_ptr(libc_a_path));
17641762 }
17651763
1766 Buf *compiler_rt_o_path = build_compiler_rt(g, OutTypeLib);
1764 Buf *compiler_rt_o_path = build_compiler_rt(g, OutTypeLib, lj->build_dep_prog_node);
17671765 lj->args.append(buf_ptr(compiler_rt_o_path));
17681766 }
17691767
......@@ -1823,15 +1821,15 @@ static void construct_linker_job_elf(LinkJob *lj) {
18231821 }
18241822 } else if (target_is_glibc(g->zig_target)) {
18251823 if (target_supports_libunwind(g->zig_target)) {
1826 lj->args.append(build_libunwind(g));
1824 lj->args.append(build_libunwind(g, lj->build_dep_prog_node));
18271825 }
18281826 add_glibc_libs(lj);
1829 lj->args.append(get_libc_crt_file(g, "libc_nonshared.a"));
1827 lj->args.append(get_libc_crt_file(g, "libc_nonshared.a", lj->build_dep_prog_node));
18301828 } else if (target_is_musl(g->zig_target)) {
18311829 if (target_supports_libunwind(g->zig_target)) {
1832 lj->args.append(build_libunwind(g));
1830 lj->args.append(build_libunwind(g, lj->build_dep_prog_node));
18331831 }
1834 lj->args.append(build_musl(g));
1832 lj->args.append(build_musl(g, lj->build_dep_prog_node));
18351833 } else {
18361834 zig_unreachable();
18371835 }
......@@ -1840,9 +1838,9 @@ static void construct_linker_job_elf(LinkJob *lj) {
18401838 // crt end
18411839 if (lj->link_in_crt) {
18421840 if (target_is_android(g->zig_target)) {
1843 lj->args.append(get_libc_crt_file(g, "crtend_android.o"));
1841 lj->args.append(get_libc_crt_file(g, "crtend_android.o", lj->build_dep_prog_node));
18441842 } else if (target_libc_needs_crti_crtn(g->zig_target)) {
1845 lj->args.append(get_libc_crt_file(g, "crtn.o"));
1843 lj->args.append(get_libc_crt_file(g, "crtn.o", lj->build_dep_prog_node));
18461844 }
18471845 }
18481846
......@@ -1887,10 +1885,10 @@ static void construct_linker_job_wasm(LinkJob *lj) {
18871885 }
18881886
18891887 if (g->out_type != OutTypeObj) {
1890 Buf *libc_o_path = build_c(g, OutTypeObj);
1888 Buf *libc_o_path = build_c(g, OutTypeObj, lj->build_dep_prog_node);
18911889 lj->args.append(buf_ptr(libc_o_path));
18921890
1893 Buf *compiler_rt_o_path = build_compiler_rt(g, OutTypeObj);
1891 Buf *compiler_rt_o_path = build_compiler_rt(g, OutTypeObj, lj->build_dep_prog_node);
18941892 lj->args.append(buf_ptr(compiler_rt_o_path));
18951893 }
18961894}
......@@ -2170,14 +2168,14 @@ static void add_mingw_link_args(LinkJob *lj, bool is_library) {
21702168 }
21712169
21722170 if (is_dll) {
2173 lj->args.append(get_libc_crt_file(g, "dllcrt2.o"));
2171 lj->args.append(get_libc_crt_file(g, "dllcrt2.o", lj->build_dep_prog_node));
21742172 } else {
2175 lj->args.append(get_libc_crt_file(g, "crt2.o"));
2173 lj->args.append(get_libc_crt_file(g, "crt2.o", lj->build_dep_prog_node));
21762174 }
21772175
2178 lj->args.append(get_libc_crt_file(g, "mingw32.lib"));
2179 lj->args.append(get_libc_crt_file(g, "mingwex.lib"));
2180 lj->args.append(get_libc_crt_file(g, "msvcrt-os.lib"));
2176 lj->args.append(get_libc_crt_file(g, "mingw32.lib", lj->build_dep_prog_node));
2177 lj->args.append(get_libc_crt_file(g, "mingwex.lib", lj->build_dep_prog_node));
2178 lj->args.append(get_libc_crt_file(g, "msvcrt-os.lib", lj->build_dep_prog_node));
21812179
21822180 for (size_t def_i = 0; def_i < array_length(mingw_def_list); def_i += 1) {
21832181 const char *name = mingw_def_list[def_i].name;
......@@ -2319,12 +2317,12 @@ static void construct_linker_job_coff(LinkJob *lj) {
23192317
23202318 if (g->out_type == OutTypeExe || (g->out_type == OutTypeLib && g->is_dynamic)) {
23212319 if (g->libc_link_lib == nullptr && !g->is_dummy_so) {
2322 Buf *libc_a_path = build_c(g, OutTypeLib);
2320 Buf *libc_a_path = build_c(g, OutTypeLib, lj->build_dep_prog_node);
23232321 lj->args.append(buf_ptr(libc_a_path));
23242322 }
23252323
23262324 // msvc compiler_rt is missing some stuff, so we still build it and rely on weak linkage
2327 Buf *compiler_rt_o_path = build_compiler_rt(g, OutTypeLib);
2325 Buf *compiler_rt_o_path = build_compiler_rt(g, OutTypeLib, lj->build_dep_prog_node);
23282326 lj->args.append(buf_ptr(compiler_rt_o_path));
23292327 }
23302328
......@@ -2563,7 +2561,7 @@ static void construct_linker_job_macho(LinkJob *lj) {
25632561
25642562 // compiler_rt on darwin is missing some stuff, so we still build it and rely on LinkOnce
25652563 if (g->out_type == OutTypeExe || is_dyn_lib) {
2566 Buf *compiler_rt_o_path = build_compiler_rt(g, OutTypeLib);
2564 Buf *compiler_rt_o_path = build_compiler_rt(g, OutTypeLib, lj->build_dep_prog_node);
25672565 lj->args.append(buf_ptr(compiler_rt_o_path));
25682566 }
25692567
......@@ -2621,16 +2619,22 @@ static void construct_linker_job(LinkJob *lj) {
26212619 }
26222620}
26232621
2624void zig_link_add_compiler_rt(CodeGen *g) {
2625 Buf *compiler_rt_o_path = build_compiler_rt(g, OutTypeObj);
2622void zig_link_add_compiler_rt(CodeGen *g, Stage2ProgressNode *progress_node) {
2623 Buf *compiler_rt_o_path = build_compiler_rt(g, OutTypeObj, progress_node);
26262624 g->link_objects.append(compiler_rt_o_path);
26272625}
26282626
26292627void codegen_link(CodeGen *g) {
26302628 codegen_add_time_event(g, "Build Dependencies");
2631
26322629 LinkJob lj = {0};
26332630
2631 {
2632 const char *progress_name = "Build Dependencies";
2633 lj.build_dep_prog_node = stage2_progress_start(g->progress_node,
2634 progress_name, strlen(progress_name), 0);
2635 }
2636
2637
26342638 // even though we're calling LLD as a library it thinks the first
26352639 // argument is its own exe name
26362640 lj.args.append("lld");
......@@ -2656,6 +2660,12 @@ void codegen_link(CodeGen *g) {
26562660 }
26572661 ZigLLVM_OSType os_type = get_llvm_os_type(g->zig_target->os);
26582662 codegen_add_time_event(g, "LLVM Link");
2663 {
2664 const char *progress_name = "linking";
2665 Stage2ProgressNode *child_progress_node = stage2_progress_start(g->progress_node,
2666 progress_name, strlen(progress_name), 0);
2667 (void)child_progress_node;
2668 }
26592669 if (g->verbose_link) {
26602670 fprintf(stderr, "ar rcs %s", buf_ptr(&g->output_file_path));
26612671 for (size_t i = 0; i < file_names.length; i += 1) {
src/main.cpp+11-3
......@@ -506,6 +506,8 @@ int main(int argc, char **argv) {
506506 ZigList<const char *> llvm_argv = {0};
507507 llvm_argv.append("zig (LLVM option parsing)");
508508
509 Stage2ProgressNode *root_progress_node = stage2_progress_start_root(stage2_progress_create(), "", 0, 0);
510
509511 if (argc >= 2 && strcmp(argv[1], "build") == 0) {
510512 Buf zig_exe_path_buf = BUF_INIT;
511513 if ((err = os_self_exe_path(&zig_exe_path_buf))) {
......@@ -589,7 +591,7 @@ int main(int argc, char **argv) {
589591 }
590592
591593 CodeGen *g = codegen_create(main_pkg_path, build_runner_path, &target, OutTypeExe,
592 BuildModeDebug, override_lib_dir, nullptr, &full_cache_dir, false);
594 BuildModeDebug, override_lib_dir, nullptr, &full_cache_dir, false, root_progress_node);
593595 g->valgrind_support = valgrind_support;
594596 g->enable_time_report = timing_info;
595597 codegen_set_out_name(g, buf_create_from_str("build"));
......@@ -1034,17 +1036,19 @@ int main(int argc, char **argv) {
10341036 ZigLibCInstallation libc;
10351037 if ((err = zig_libc_parse(&libc, buf_create_from_str(in_file), &target, true)))
10361038 return EXIT_FAILURE;
1039 stage2_progress_end(root_progress_node);
10371040 return EXIT_SUCCESS;
10381041 }
10391042 ZigLibCInstallation libc;
10401043 if ((err = zig_libc_find_native(&libc, true)))
10411044 return EXIT_FAILURE;
10421045 zig_libc_render(&libc, stdout);
1046 stage2_progress_end(root_progress_node);
10431047 return EXIT_SUCCESS;
10441048 }
10451049 case CmdBuiltin: {
10461050 CodeGen *g = codegen_create(main_pkg_path, nullptr, &target,
1047 out_type, build_mode, override_lib_dir, nullptr, nullptr, false);
1051 out_type, build_mode, override_lib_dir, nullptr, nullptr, false, root_progress_node);
10481052 codegen_set_strip(g, strip);
10491053 for (size_t i = 0; i < link_libs.length; i += 1) {
10501054 LinkLib *link_lib = codegen_add_link_lib(g, buf_create_from_str(link_libs.at(i)));
......@@ -1060,6 +1064,7 @@ int main(int argc, char **argv) {
10601064 fprintf(stderr, "unable to write to stdout: %s\n", strerror(ferror(stdout)));
10611065 return EXIT_FAILURE;
10621066 }
1067 stage2_progress_end(root_progress_node);
10631068 return EXIT_SUCCESS;
10641069 }
10651070 case CmdRun:
......@@ -1148,7 +1153,7 @@ int main(int argc, char **argv) {
11481153 cache_dir_buf = buf_create_from_str(cache_dir);
11491154 }
11501155 CodeGen *g = codegen_create(main_pkg_path, zig_root_source_file, &target, out_type, build_mode,
1151 override_lib_dir, libc, cache_dir_buf, cmd == CmdTest);
1156 override_lib_dir, libc, cache_dir_buf, cmd == CmdTest, root_progress_node);
11521157 if (llvm_argv.length >= 2) codegen_set_llvm_argv(g, llvm_argv.items + 1, llvm_argv.length - 2);
11531158 g->valgrind_support = valgrind_support;
11541159 g->want_pic = want_pic;
......@@ -1276,6 +1281,7 @@ int main(int argc, char **argv) {
12761281 if (printf("%s\n", buf_ptr(&g->output_file_path)) < 0)
12771282 return EXIT_FAILURE;
12781283 }
1284 stage2_progress_end(root_progress_node);
12791285 return EXIT_SUCCESS;
12801286 } else {
12811287 zig_unreachable();
......@@ -1284,6 +1290,7 @@ int main(int argc, char **argv) {
12841290 codegen_translate_c(g, in_file_buf, stdout, cmd == CmdTranslateCUserland);
12851291 if (timing_info)
12861292 codegen_print_timing_report(g, stderr);
1293 stage2_progress_end(root_progress_node);
12871294 return EXIT_SUCCESS;
12881295 } else if (cmd == CmdTest) {
12891296 codegen_set_emit_file_type(g, emit_file_type);
......@@ -1338,6 +1345,7 @@ int main(int argc, char **argv) {
13381345 fprintf(stderr, "\nTests failed. Use the following command to reproduce the failure:\n");
13391346 fprintf(stderr, "%s\n", buf_ptr(test_exe_path));
13401347 }
1348 stage2_progress_end(root_progress_node);
13411349 return (term.how == TerminationIdClean) ? term.code : -1;
13421350 } else {
13431351 zig_unreachable();
src/userland.cpp+28
......@@ -59,3 +59,31 @@ stage2_DepNextResult stage2_DepTokenizer_next(stage2_DepTokenizer *self) {
5959 const char *msg = "stage0 called stage2_DepTokenizer_next";
6060 stage2_panic(msg, strlen(msg));
6161}
62
63
64struct Stage2Progress {
65 int trash;
66};
67
68struct Stage2ProgressNode {
69 int trash;
70};
71
72Stage2Progress *stage2_progress_create(void) {
73 return nullptr;
74}
75
76void stage2_progress_destroy(Stage2Progress *progress) {}
77
78Stage2ProgressNode *stage2_progress_start_root(Stage2Progress *progress,
79 const char *name_ptr, size_t name_len, size_t estimated_total_items)
80{
81 return nullptr;
82}
83Stage2ProgressNode *stage2_progress_start(Stage2ProgressNode *node,
84 const char *name_ptr, size_t name_len, size_t estimated_total_items)
85{
86 return nullptr;
87}
88void stage2_progress_end(Stage2ProgressNode *node) {}
89void stage2_progress_complete_one(Stage2ProgressNode *node) {}
src/userland.h+19
......@@ -156,4 +156,23 @@ ZIG_EXTERN_C void stage2_DepTokenizer_deinit(stage2_DepTokenizer *self);
156156// ABI warning
157157ZIG_EXTERN_C stage2_DepNextResult stage2_DepTokenizer_next(stage2_DepTokenizer *self);
158158
159// ABI warning
160struct Stage2Progress;
161// ABI warning
162struct Stage2ProgressNode;
163// ABI warning
164ZIG_EXTERN_C Stage2Progress *stage2_progress_create(void);
165// ABI warning
166ZIG_EXTERN_C void stage2_progress_destroy(Stage2Progress *progress);
167// ABI warning
168ZIG_EXTERN_C Stage2ProgressNode *stage2_progress_start_root(Stage2Progress *progress,
169 const char *name_ptr, size_t name_len, size_t estimated_total_items);
170// ABI warning
171ZIG_EXTERN_C Stage2ProgressNode *stage2_progress_start(Stage2ProgressNode *node,
172 const char *name_ptr, size_t name_len, size_t estimated_total_items);
173// ABI warning
174ZIG_EXTERN_C void stage2_progress_end(Stage2ProgressNode *node);
175// ABI warning
176ZIG_EXTERN_C void stage2_progress_complete_one(Stage2ProgressNode *node);
177
159178#endif