diff --git a/lib/std/fmt.zig b/lib/std/fmt.zig index 3f3e3fca73..d182214aed 100644 --- a/lib/std/fmt.zig +++ b/lib/std/fmt.zig @@ -1055,14 +1055,21 @@ const BufPrintContext = struct { }; fn bufPrintWrite(context: *BufPrintContext, bytes: []const u8) !void { - if (context.remaining.len < bytes.len) return error.BufferTooSmall; + if (context.remaining.len < bytes.len) { + mem.copy(u8, context.remaining, bytes[0..context.remaining.len]); + return error.BufferTooSmall; + } mem.copy(u8, context.remaining, bytes); context.remaining = context.remaining[bytes.len..]; } -pub fn bufPrint(buf: []u8, comptime fmt: []const u8, args: ...) ![]u8 { +pub const BufPrintError = error{ + /// As much as possible was written to the buffer, but it was too small to fit all the printed bytes. + BufferTooSmall, +}; +pub fn bufPrint(buf: []u8, comptime fmt: []const u8, args: ...) BufPrintError![]u8 { var context = BufPrintContext{ .remaining = buf }; - try format(&context, error{BufferTooSmall}, bufPrintWrite, fmt, args); + try format(&context, BufPrintError, bufPrintWrite, fmt, args); return buf[0 .. buf.len - context.remaining.len]; } diff --git a/lib/std/progress.zig b/lib/std/progress.zig index 1fc74ce3fb..75103aaf5a 100644 --- a/lib/std/progress.zig +++ b/lib/std/progress.zig @@ -1,107 +1,242 @@ const std = @import("std"); const testing = std.testing; +const assert = std.debug.assert; -pub const PrintConfig = struct { - /// If the current node (and its children) should - /// print to stderr on update() - flag: bool = false, +/// This API is non-allocating and non-fallible. The tradeoff is that users of +/// this API must provide the storage for each `Progress.Node`. +/// Initialize the struct directly, overriding these fields as desired: +/// * `refresh_rate_ms` +/// * `initial_delay_ms` +pub const Progress = struct { + /// `null` if the current node (and its children) should + /// not print on update() + terminal: ?std.fs.File = undefined, - /// If all output should be suppressed instead - /// serves the same practical purpose as `flag` but supposed to be used - /// by separate parts of the user program. - suppress: bool = false, -}; + root: Node = undefined, -pub const ProgressNode = struct { - completed_items: usize = 0, - total_items: usize, + /// Keeps track of how much time has passed since the beginning. + /// Used to compare with `initial_delay_ms` and `refresh_rate_ms`. + timer: std.time.Timer = undefined, - print_config: PrintConfig, + /// When the previous refresh was written to the terminal. + /// Used to compare with `refresh_rate_ms`. + prev_refresh_timestamp: u64 = undefined, - // TODO maybe instead of keeping a prefix field, we could - // select the proper prefix at the time of update(), and if we're not - // in a terminal, we use warn("/r{}", lots_of_whitespace). - prefix: []const u8, + /// This buffer represents the maximum number of bytes written to the terminal + /// with each refresh. + output_buffer: [100]u8 = undefined, - /// Create a new progress node. - pub fn start( - parent_opt: ?ProgressNode, - total_items_opt: ?usize, - ) !ProgressNode { + /// Keeps track of how many columns in the terminal have been output, so that + /// we can move the cursor back later. + columns_written: usize = undefined, - // inherit the last set print "configuration" from the parent node - var print_config = PrintConfig{}; - if (parent_opt) |parent| { - print_config = parent.print_config; + /// How many nanoseconds between writing updates to the terminal. + refresh_rate_ns: u64 = 50 * std.time.millisecond, + + /// How many nanoseconds to keep the output hidden + initial_delay_ns: u64 = 500 * std.time.millisecond, + + done: bool = true, + + /// Represents one unit of progress. Each node can have children nodes, or + /// one can use integers with `update`. + pub const Node = struct { + context: *Progress, + parent: ?*Node, + completed_items: usize, + name: []const u8, + recently_updated_child: ?*Node = null, + + /// This field may be updated freely. + estimated_total_items: ?usize, + + /// Create a new child progress node. + /// Call `Node.end` when done. + /// TODO solve https://github.com/ziglang/zig/issues/2765 and then change this + /// API to set `self.parent.recently_updated_child` with the return value. + /// Until that is fixed you probably want to call `activate` on the return value. + pub fn start(self: *Node, name: []const u8, estimated_total_items: ?usize) Node { + return Node{ + .context = self.context, + .parent = self, + .completed_items = 0, + .name = name, + .estimated_total_items = estimated_total_items, + }; } - var stderr = try std.io.getStdErr(); - const is_term = std.os.isatty(stderr.handle); - - // if we're in a terminal, use vt100 escape codes - // for the progress. - var prefix: []const u8 = undefined; - if (is_term) { - prefix = "\x21[2K\r"; - } else { - prefix = "\n"; + /// This is the same as calling `start` and then `end` on the returned `Node`. + pub fn completeOne(self: *Node) void { + if (self.parent) |parent| parent.recently_updated_child = self; + self.completed_items += 1; + self.context.maybeRefresh(); } - return ProgressNode{ - .total_items = total_items_opt orelse 0, - .print_config = print_config, - .prefix = prefix, - }; - } - - /// Signal an update on the progress node. - /// The user of this function is supposed to modify - /// ProgressNode.PrintConfig.flag when update() is supposed to print. - pub fn update( - self: *ProgressNode, - current_action: ?[]const u8, - items_done_opt: ?usize, - ) void { - if (items_done_opt) |items_done| { - self.completed_items = items_done; - - if (items_done > self.total_items) { - self.total_items = items_done; + pub fn end(self: *Node) void { + self.context.maybeRefresh(); + if (self.parent) |parent| { + if (parent.recently_updated_child) |parent_child| { + if (parent_child == self) { + parent.recently_updated_child = null; + } + } + parent.completeOne(); + } else { + self.context.done = true; + self.context.refresh(); } } - var cfg = self.print_config; - if (cfg.flag and !cfg.suppress and current_action != null) { - std.debug.warn( - "{}[{}/{}] {}", - self.prefix, - self.completed_items, - self.total_items, - current_action, - ); + /// Tell the parent node that this node is actively being worked on. + pub fn activate(self: *Node) void { + if (self.parent) |parent| parent.recently_updated_child = self; + } + }; + + /// Create a new progress node. + /// Call `Node.end` when done. + /// TODO solve https://github.com/ziglang/zig/issues/2765 and then change this + /// API to return Progress rather than accept it as a parameter. + pub fn start(self: *Progress, name: []const u8, estimated_total_items: ?usize) !*Node { + if (std.io.getStdErr()) |stderr| { + const is_term = stderr.isTty(); + self.terminal = if (is_term) stderr else null; + } else |_| { + self.terminal = null; + } + self.root = Node{ + .context = self, + .parent = null, + .completed_items = 0, + .name = name, + .estimated_total_items = estimated_total_items, + }; + self.prev_refresh_timestamp = 0; + self.columns_written = 0; + self.timer = try std.time.Timer.start(); + self.done = false; + return &self.root; + } + + /// Updates the terminal if enough time has passed since last update. + pub fn maybeRefresh(self: *Progress) void { + const now = self.timer.read(); + if (now < self.initial_delay_ns) return; + if (now - self.prev_refresh_timestamp < self.refresh_rate_ns) return; + self.refresh(); + } + + /// Updates the terminal and resets `self.next_refresh_timestamp`. + pub fn refresh(self: *Progress) void { + const file = self.terminal orelse return; + + const prev_columns_written = self.columns_written; + var end: usize = 0; + if (self.columns_written > 0) { + end += (std.fmt.bufPrint(self.output_buffer[end..], "\x1b[{}D", self.columns_written) catch unreachable).len; + self.columns_written = 0; + } + + if (!self.done) { + self.bufWriteNode(self.root, &end); + self.bufWrite(&end, "..."); + } + + if (prev_columns_written > self.columns_written) { + const amt = prev_columns_written - self.columns_written; + std.mem.set(u8, self.output_buffer[end .. end + amt], ' '); + end += amt; + end += (std.fmt.bufPrint(self.output_buffer[end..], "\x1b[{}D", amt) catch unreachable).len; + } + + _ = file.write(self.output_buffer[0..end]) catch |e| { + // Stop trying to write to this file once it errors. + self.terminal = null; + }; + self.prev_refresh_timestamp = self.timer.read(); + } + + fn bufWriteNode(self: *Progress, node: Node, end: *usize) void { + if (node.name.len != 0 or node.estimated_total_items != null) { + if (node.name.len != 0) { + self.bufWrite(end, "{}", node.name); + if (node.recently_updated_child != null or node.estimated_total_items != null or + node.completed_items != 0) + { + self.bufWrite(end, "..."); + } + } + if (node.estimated_total_items) |total| { + self.bufWrite(end, "[{}/{}] ", node.completed_items, total); + } else if (node.completed_items != 0) { + self.bufWrite(end, "[{}] ", node.completed_items); + } + } + if (node.recently_updated_child) |child| { + self.bufWriteNode(child.*, end); } } - pub fn end(self: *ProgressNode) void { - if (!self.print_config.flag) return; - - // TODO emoji? - std.debug.warn("\n[V] done!"); + fn bufWrite(self: *Progress, end: *usize, comptime format: []const u8, args: ...) void { + if (std.fmt.bufPrint(self.output_buffer[end.*..], format, args)) |written| { + const amt = written.len; + end.* += amt; + self.columns_written += amt; + } else |err| switch (err) { + error.BufferTooSmall => { + self.columns_written += self.output_buffer.len - end.*; + end.* = self.output_buffer.len; + }, + } + const bytes_needed_for_esc_codes_at_end = 11; + const max_end = self.output_buffer.len - bytes_needed_for_esc_codes_at_end; + if (end.* > max_end) { + const suffix = "..."; + self.columns_written = self.columns_written - (end.* - max_end) + suffix.len; + std.mem.copy(u8, self.output_buffer[max_end..], suffix); + end.* = max_end + suffix.len; + } } }; test "basic functionality" { - var node = try ProgressNode.start(null, 100); + var progress = Progress{}; + const root_node = try progress.start("", 100); + defer root_node.end(); - var buf: [100]u8 = undefined; + const sub_task_names = [_][]const u8{ + "reticulating splines", + "adjusting shoes", + "climbing towers", + "pouring juice", + }; + var next_sub_task: usize = 0; var i: usize = 0; - while (i < 100) : (i += 6) { - if (i > 50) node.print_config.flag = true; - const msg = try std.fmt.bufPrint(buf[0..], "action at i={}", i); - node.update(msg, i); - std.time.sleep(10 * std.time.millisecond); - } + while (i < 100) : (i += 1) { + var node = root_node.start(sub_task_names[next_sub_task], 5); + node.activate(); + next_sub_task = (next_sub_task + 1) % sub_task_names.len; - node.end(); + node.completeOne(); + std.time.sleep(5 * std.time.millisecond); + node.completeOne(); + node.completeOne(); + std.time.sleep(5 * std.time.millisecond); + node.completeOne(); + node.completeOne(); + std.time.sleep(5 * std.time.millisecond); + + node.end(); + + std.time.sleep(5 * std.time.millisecond); + } + { + 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); + node.activate(); + std.time.sleep(10 * std.time.millisecond); + progress.maybeRefresh(); + std.time.sleep(10 * std.time.millisecond); + node.end(); + } } diff --git a/lib/std/std.zig b/lib/std/std.zig index f67d0c9320..f41181f6e9 100644 --- a/lib/std/std.zig +++ b/lib/std/std.zig @@ -6,20 +6,21 @@ pub const BufMap = @import("buf_map.zig").BufMap; pub const BufSet = @import("buf_set.zig").BufSet; pub const Buffer = @import("buffer.zig").Buffer; pub const BufferOutStream = @import("io.zig").BufferOutStream; +pub const ChildProcess = @import("child_process.zig").ChildProcess; pub const DynLib = @import("dynamic_library.zig").DynLib; pub const HashMap = @import("hash_map.zig").HashMap; pub const Mutex = @import("mutex.zig").Mutex; -pub const PackedIntArrayEndian = @import("packed_int_array.zig").PackedIntArrayEndian; pub const PackedIntArray = @import("packed_int_array.zig").PackedIntArray; -pub const PackedIntSliceEndian = @import("packed_int_array.zig").PackedIntSliceEndian; +pub const PackedIntArrayEndian = @import("packed_int_array.zig").PackedIntArrayEndian; pub const PackedIntSlice = @import("packed_int_array.zig").PackedIntSlice; +pub const PackedIntSliceEndian = @import("packed_int_array.zig").PackedIntSliceEndian; pub const PriorityQueue = @import("priority_queue.zig").PriorityQueue; -pub const SinglyLinkedList = @import("linked_list.zig").SinglyLinkedList; -pub const StaticallyInitializedMutex = @import("statically_initialized_mutex.zig").StaticallyInitializedMutex; +pub const Progress = @import("progress.zig").Progress; pub const SegmentedList = @import("segmented_list.zig").SegmentedList; +pub const SinglyLinkedList = @import("linked_list.zig").SinglyLinkedList; pub const SpinLock = @import("spinlock.zig").SpinLock; +pub const StaticallyInitializedMutex = @import("statically_initialized_mutex.zig").StaticallyInitializedMutex; pub const StringHashMap = @import("hash_map.zig").StringHashMap; -pub const ChildProcess = @import("child_process.zig").ChildProcess; pub const TailQueue = @import("linked_list.zig").TailQueue; pub const Thread = @import("thread.zig").Thread; diff --git a/src-self-hosted/stage1.zig b/src-self-hosted/stage1.zig index 2f48f2f450..fd6413070d 100644 --- a/src-self-hosted/stage1.zig +++ b/src-self-hosted/stage1.zig @@ -456,3 +456,52 @@ export fn stage2_attach_segfault_handler() void { std.debug.attachSegfaultHandler(); } } + +// ABI warning +export fn stage2_progress_create() *std.Progress { + const ptr = std.heap.c_allocator.create(std.Progress) catch @panic("out of memory"); + ptr.* = std.Progress{}; + return ptr; +} + +// ABI warning +export fn stage2_progress_destroy(progress: *std.Progress) void { + std.heap.c_allocator.destroy(progress); +} + +// ABI warning +export fn stage2_progress_start_root(progress: *std.Progress, name_ptr: [*]const u8, name_len: usize, estimated_total_items: usize) *std.Progress.Node { + return progress.start( + name_ptr[0..name_len], + if (estimated_total_items == 0) null else estimated_total_items, + ) catch @panic("timer unsupported"); +} + +// ABI warning +export fn stage2_progress_start( + node: *std.Progress.Node, + name_ptr: [*]const u8, + name_len: usize, + estimated_total_items: usize, +) *std.Progress.Node { + const child_node = std.heap.c_allocator.create(std.Progress.Node) catch @panic("out of memory"); + child_node.* = node.start( + name_ptr[0..name_len], + if (estimated_total_items == 0) null else estimated_total_items, + ); + child_node.activate(); + return child_node; +} + +// ABI warning +export fn stage2_progress_end(node: *std.Progress.Node) void { + node.end(); + if (&node.context.root != node) { + std.heap.c_allocator.destroy(node); + } +} + +// ABI warning +export fn stage2_progress_complete_one(node: *std.Progress.Node) void { + node.completeOne(); +} diff --git a/src/all_types.hpp b/src/all_types.hpp index 0ce55e598b..f2e614f192 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -2010,6 +2010,8 @@ struct CodeGen { ZigFn *largest_frame_fn; + Stage2ProgressNode *progress_node; + WantPIC want_pic; WantStackCheck want_stack_check; CacheHash cache_hash; diff --git a/src/codegen.cpp b/src/codegen.cpp index f313c6cd1c..ae02676414 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -7610,7 +7610,7 @@ static void zig_llvm_emit_output(CodeGen *g) { if (g->bundle_compiler_rt && (g->out_type == OutTypeObj || (g->out_type == OutTypeLib && !g->is_dynamic))) { - zig_link_add_compiler_rt(g); + zig_link_add_compiler_rt(g, g->progress_node); } break; @@ -9453,7 +9453,7 @@ Error create_c_object_cache(CodeGen *g, CacheHash **out_cache_hash, bool verbose } // returns true if it was a cache miss -static void gen_c_object(CodeGen *g, Buf *self_exe_path, CFile *c_file) { +static void gen_c_object(CodeGen *g, Buf *self_exe_path, CFile *c_file, Stage2ProgressNode *parent_prog_node) { Error err; Buf *artifact_dir; @@ -9464,6 +9464,10 @@ static void gen_c_object(CodeGen *g, Buf *self_exe_path, CFile *c_file) { Buf *c_source_file = buf_create_from_str(c_file->source_path); Buf *c_source_basename = buf_alloc(); os_path_split(c_source_file, nullptr, c_source_basename); + + Stage2ProgressNode *child_prog_node = stage2_progress_start(parent_prog_node, buf_ptr(c_source_basename), + buf_len(c_source_basename), 0); + Buf *final_o_basename = buf_alloc(); os_path_extname(c_source_basename, final_o_basename, nullptr); 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) { g->link_objects.append(o_final_path); g->caches_to_release.append(cache_hash); + + stage2_progress_end(child_prog_node); } // returns true if we had any cache misses @@ -9596,11 +9602,16 @@ static void gen_c_objects(CodeGen *g) { } codegen_add_time_event(g, "Compile C Code"); + const char *c_prog_name = "compiling C objects"; + Stage2ProgressNode *c_prog_node = stage2_progress_start(g->progress_node, c_prog_name, strlen(c_prog_name), + g->c_source_files.length); for (size_t c_file_i = 0; c_file_i < g->c_source_files.length; c_file_i += 1) { CFile *c_file = g->c_source_files.at(c_file_i); - gen_c_object(g, self_exe_path, c_file); + gen_c_object(g, self_exe_path, c_file, c_prog_node); } + + stage2_progress_end(c_prog_node); } void codegen_add_object(CodeGen *g, Buf *object_path) { @@ -10320,6 +10331,10 @@ void codegen_build_and_link(CodeGen *g) { init(g); codegen_add_time_event(g, "Semantic Analysis"); + const char *progress_name = "Semantic Analysis"; + Stage2ProgressNode *child_progress_node = stage2_progress_start(g->progress_node, + progress_name, strlen(progress_name), 0); + (void)child_progress_node; gen_root_source(g); @@ -10343,13 +10358,31 @@ void codegen_build_and_link(CodeGen *g) { if (need_llvm_module(g)) { codegen_add_time_event(g, "Code Generation"); + { + const char *progress_name = "Code Generation"; + Stage2ProgressNode *child_progress_node = stage2_progress_start(g->progress_node, + progress_name, strlen(progress_name), 0); + (void)child_progress_node; + } do_code_gen(g); codegen_add_time_event(g, "LLVM Emit Output"); + { + const char *progress_name = "LLVM Emit Output"; + Stage2ProgressNode *child_progress_node = stage2_progress_start(g->progress_node, + progress_name, strlen(progress_name), 0); + (void)child_progress_node; + } zig_llvm_emit_output(g); if (!g->disable_gen_h && (g->out_type == OutTypeObj || g->out_type == OutTypeLib)) { codegen_add_time_event(g, "Generate .h"); + { + const char *progress_name = "Generate .h"; + Stage2ProgressNode *child_progress_node = stage2_progress_start(g->progress_node, + progress_name, strlen(progress_name), 0); + (void)child_progress_node; + } gen_h_file(g); } } @@ -10446,10 +10479,15 @@ ZigPackage *codegen_create_package(CodeGen *g, const char *root_src_dir, const c } CodeGen *create_child_codegen(CodeGen *parent_gen, Buf *root_src_path, OutType out_type, - ZigLibCInstallation *libc) + ZigLibCInstallation *libc, const char *name, Stage2ProgressNode *child_progress_node) { + if (!child_progress_node) { + child_progress_node = stage2_progress_start(parent_gen->progress_node, name, strlen(name), 0); + } + CodeGen *child_gen = codegen_create(nullptr, root_src_path, parent_gen->zig_target, out_type, - parent_gen->build_mode, parent_gen->zig_lib_dir, libc, get_stage1_cache_path(), false); + parent_gen->build_mode, parent_gen->zig_lib_dir, libc, get_stage1_cache_path(), false, child_progress_node); + child_gen->root_out_name = buf_create_from_str(name); child_gen->disable_gen_h = true; child_gen->want_stack_check = WantStackCheckDisabled; 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 CodeGen *codegen_create(Buf *main_pkg_path, Buf *root_src_path, const ZigTarget *target, OutType out_type, BuildMode build_mode, Buf *override_lib_dir, - ZigLibCInstallation *libc, Buf *cache_dir, bool is_test_build) + ZigLibCInstallation *libc, Buf *cache_dir, bool is_test_build, Stage2ProgressNode *progress_node) { CodeGen *g = allocate(1); + g->progress_node = progress_node; codegen_add_time_event(g, "Initialize"); diff --git a/src/codegen.hpp b/src/codegen.hpp index e290c53d6c..31771cd164 100644 --- a/src/codegen.hpp +++ b/src/codegen.hpp @@ -18,10 +18,10 @@ CodeGen *codegen_create(Buf *main_pkg_path, Buf *root_src_path, const ZigTarget *target, OutType out_type, BuildMode build_mode, Buf *zig_lib_dir, - ZigLibCInstallation *libc, Buf *cache_dir, bool is_test_build); + ZigLibCInstallation *libc, Buf *cache_dir, bool is_test_build, Stage2ProgressNode *progress_node); CodeGen *create_child_codegen(CodeGen *parent_gen, Buf *root_src_path, OutType out_type, - ZigLibCInstallation *libc); + ZigLibCInstallation *libc, const char *name, Stage2ProgressNode *progress_node); void codegen_set_clang_argv(CodeGen *codegen, const char **args, size_t len); void 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 void codegen_add_time_event(CodeGen *g, const char *name); void codegen_print_timing_report(CodeGen *g, FILE *f); void codegen_link(CodeGen *g); -void zig_link_add_compiler_rt(CodeGen *g); +void zig_link_add_compiler_rt(CodeGen *g, Stage2ProgressNode *progress_node); void codegen_build_and_link(CodeGen *g); ZigPackage *codegen_create_package(CodeGen *g, const char *root_src_dir, const char *root_src_path, diff --git a/src/glibc.cpp b/src/glibc.cpp index 50ccf20efe..3361eabe5a 100644 --- a/src/glibc.cpp +++ b/src/glibc.cpp @@ -169,7 +169,7 @@ Error glibc_load_metadata(ZigGLibCAbi **out_result, Buf *zig_lib_dir, bool verbo } Error glibc_build_dummies_and_maps(CodeGen *g, const ZigGLibCAbi *glibc_abi, const ZigTarget *target, - Buf **out_dir, bool verbose) + Buf **out_dir, bool verbose, Stage2ProgressNode *progress_node) { Error err; @@ -332,8 +332,7 @@ Error glibc_build_dummies_and_maps(CodeGen *g, const ZigGLibCAbi *glibc_abi, con return err; } - CodeGen *child_gen = create_child_codegen(g, zig_file_path, OutTypeLib, nullptr); - codegen_set_out_name(child_gen, buf_create_from_str(lib->name)); + CodeGen *child_gen = create_child_codegen(g, zig_file_path, OutTypeLib, nullptr, lib->name, progress_node); codegen_set_lib_version(child_gen, lib->sover, 0, 0); child_gen->is_dynamic = true; child_gen->is_dummy_so = true; diff --git a/src/glibc.hpp b/src/glibc.hpp index 50796197d4..42c2099371 100644 --- a/src/glibc.hpp +++ b/src/glibc.hpp @@ -41,7 +41,7 @@ struct ZigGLibCAbi { Error glibc_load_metadata(ZigGLibCAbi **out_result, Buf *zig_lib_dir, bool verbose); Error glibc_build_dummies_and_maps(CodeGen *codegen, const ZigGLibCAbi *glibc_abi, const ZigTarget *target, - Buf **out_dir, bool verbose); + Buf **out_dir, bool verbose, Stage2ProgressNode *progress_node); // returns ErrorUnknownABI when glibc is not the native libc Error glibc_detect_native_version(ZigGLibCVersion *glibc_ver); diff --git a/src/link.cpp b/src/link.cpp index abb4ca6193..c6286722a6 100644 --- a/src/link.cpp +++ b/src/link.cpp @@ -594,11 +594,13 @@ struct LinkJob { ZigList args; bool link_in_crt; HashMap rpath_table; + Stage2ProgressNode *build_dep_prog_node; }; -static const char *build_libc_object(CodeGen *parent_gen, const char *name, CFile *c_file) { - CodeGen *child_gen = create_child_codegen(parent_gen, nullptr, OutTypeObj, nullptr); - codegen_set_out_name(child_gen, buf_create_from_str(name)); +static const char *build_libc_object(CodeGen *parent_gen, const char *name, CFile *c_file, + Stage2ProgressNode *progress_node) +{ + CodeGen *child_gen = create_child_codegen(parent_gen, nullptr, OutTypeObj, nullptr, name, progress_node); ZigList c_source_files = {0}; c_source_files.append(c_file); child_gen->c_source_files = c_source_files; @@ -622,9 +624,8 @@ static const char *path_from_libunwind(CodeGen *g, const char *subpath) { return path_from_zig_lib(g, "libunwind", subpath); } -static const char *build_libunwind(CodeGen *parent) { - CodeGen *child_gen = create_child_codegen(parent, nullptr, OutTypeLib, nullptr); - codegen_set_out_name(child_gen, buf_create_from_str("unwind")); +static const char *build_libunwind(CodeGen *parent, Stage2ProgressNode *progress_node) { + CodeGen *child_gen = create_child_codegen(parent, nullptr, OutTypeLib, nullptr, "unwind", progress_node); LinkLib *new_link_lib = codegen_add_link_lib(child_gen, buf_create_from_str("c")); new_link_lib->provided_explicitly = false; enum SrcKind { @@ -1017,9 +1018,8 @@ static bool is_musl_arch_name(const char *name) { return false; } -static const char *build_musl(CodeGen *parent) { - CodeGen *child_gen = create_child_codegen(parent, nullptr, OutTypeLib, nullptr); - codegen_set_out_name(child_gen, buf_create_from_str("c")); +static const char *build_musl(CodeGen *parent, Stage2ProgressNode *progress_node) { + CodeGen *child_gen = create_child_codegen(parent, nullptr, OutTypeLib, nullptr, "c", progress_node); // When there is a src//foo.* then it should substitute for src/foo.* // 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 * child_gen->c_source_files.append(c_file); } -static const char *get_libc_crt_file(CodeGen *parent, const char *file) { +static const char *get_libc_crt_file(CodeGen *parent, const char *file, Stage2ProgressNode *progress_node) { if (parent->libc == nullptr && parent->zig_target->os == OsWindows) { if (strcmp(file, "crt2.o") == 0) { CFile *c_file = allocate(1); @@ -1188,7 +1188,7 @@ static const char *get_libc_crt_file(CodeGen *parent, const char *file) { //c_file->args.append("-DUNICODE"); //c_file->args.append("-D_UNICODE"); //c_file->args.append("-DWPRFLAG=1"); - return build_libc_object(parent, "crt2", c_file); + return build_libc_object(parent, "crt2", c_file, progress_node); } else if (strcmp(file, "dllcrt2.o") == 0) { CFile *c_file = allocate(1); c_file->source_path = buf_ptr(buf_sprintf( @@ -1196,10 +1196,9 @@ static const char *get_libc_crt_file(CodeGen *parent, const char *file) { mingw_add_cc_args(parent, c_file); c_file->args.append("-U__CRTDLL__"); c_file->args.append("-D__MSVCRT__"); - return build_libc_object(parent, "dllcrt2", c_file); + return build_libc_object(parent, "dllcrt2", c_file, progress_node); } else if (strcmp(file, "mingw32.lib") == 0) { - CodeGen *child_gen = create_child_codegen(parent, nullptr, OutTypeLib, nullptr); - codegen_set_out_name(child_gen, buf_create_from_str("mingw32")); + CodeGen *child_gen = create_child_codegen(parent, nullptr, OutTypeLib, nullptr, "mingw32", progress_node); static const char *deps[] = { "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) { codegen_build_and_link(child_gen); return buf_ptr(&child_gen->output_file_path); } else if (strcmp(file, "msvcrt-os.lib") == 0) { - CodeGen *child_gen = create_child_codegen(parent, nullptr, OutTypeLib, nullptr); - codegen_set_out_name(child_gen, buf_create_from_str("msvcrt-os")); + CodeGen *child_gen = create_child_codegen(parent, nullptr, OutTypeLib, nullptr, "msvcrt-os", progress_node); for (size_t i = 0; i < array_length(msvcrt_common_src); i += 1) { 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) { codegen_build_and_link(child_gen); return buf_ptr(&child_gen->output_file_path); } else if (strcmp(file, "mingwex.lib") == 0) { - CodeGen *child_gen = create_child_codegen(parent, nullptr, OutTypeLib, nullptr); - codegen_set_out_name(child_gen, buf_create_from_str("mingwex")); + CodeGen *child_gen = create_child_codegen(parent, nullptr, OutTypeLib, nullptr, "mingwex", progress_node); for (size_t i = 0; i < array_length(mingwex_generic_src); i += 1) { 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) { c_file->args.append("-DASSEMBLER"); c_file->args.append("-g"); c_file->args.append("-Wa,--noexecstack"); - return build_libc_object(parent, "crti", c_file); + return build_libc_object(parent, "crti", c_file, progress_node); } else if (strcmp(file, "crtn.o") == 0) { CFile *c_file = allocate(1); 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) { c_file->args.append("-DASSEMBLER"); c_file->args.append("-g"); c_file->args.append("-Wa,--noexecstack"); - return build_libc_object(parent, "crtn", c_file); + return build_libc_object(parent, "crtn", c_file, progress_node); } else if (strcmp(file, "start.os") == 0) { CFile *c_file = allocate(1); 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) { c_file->args.append("-DASSEMBLER"); c_file->args.append("-g"); c_file->args.append("-Wa,--noexecstack"); - return build_libc_object(parent, "start", c_file); + return build_libc_object(parent, "start", c_file, progress_node); } else if (strcmp(file, "abi-note.o") == 0) { CFile *c_file = allocate(1); 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) { c_file->args.append("-DASSEMBLER"); c_file->args.append("-g"); c_file->args.append("-Wa,--noexecstack"); - return build_libc_object(parent, "abi-note", c_file); + return build_libc_object(parent, "abi-note", c_file, progress_node); } else if (strcmp(file, "Scrt1.o") == 0) { - const char *start_os = get_libc_crt_file(parent, "start.os"); - const char *abi_note_o = get_libc_crt_file(parent, "abi-note.o"); - CodeGen *child_gen = create_child_codegen(parent, nullptr, OutTypeObj, nullptr); - codegen_set_out_name(child_gen, buf_create_from_str("Scrt1")); + const char *start_os = get_libc_crt_file(parent, "start.os", progress_node); + const char *abi_note_o = get_libc_crt_file(parent, "abi-note.o", progress_node); + CodeGen *child_gen = create_child_codegen(parent, nullptr, OutTypeObj, nullptr, "Scrt1", progress_node); codegen_add_object(child_gen, buf_create_from_str(start_os)); codegen_add_object(child_gen, buf_create_from_str(abi_note_o)); codegen_build_and_link(child_gen); return buf_ptr(&child_gen->output_file_path); } else if (strcmp(file, "libc_nonshared.a") == 0) { - CodeGen *child_gen = create_child_codegen(parent, nullptr, OutTypeLib, nullptr); - codegen_set_out_name(child_gen, buf_create_from_str("c_nonshared")); + CodeGen *child_gen = create_child_codegen(parent, nullptr, OutTypeLib, nullptr, "c_nonshared", progress_node); { CFile *c_file = allocate(1); 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) { c_file->args.append("-DPIC"); c_file->args.append("-DLIBC_NONSHARED=1"); c_file->args.append("-DTOP_NAMESPACE=glibc"); - codegen_add_object(child_gen, buf_create_from_str(build_libc_object(parent, "elf-init", c_file))); + codegen_add_object(child_gen, buf_create_from_str( + build_libc_object(parent, "elf-init", c_file, progress_node))); } static const struct { const char *name; @@ -1445,7 +1441,8 @@ static const char *get_libc_crt_file(CodeGen *parent, const char *file) { c_file->args.append("-DPIC"); c_file->args.append("-DLIBC_NONSHARED=1"); c_file->args.append("-DTOP_NAMESPACE=glibc"); - codegen_add_object(child_gen, buf_create_from_str(build_libc_object(parent, deps[i].name, c_file))); + codegen_add_object(child_gen, buf_create_from_str( + build_libc_object(parent, deps[i].name, c_file, progress_node))); } codegen_build_and_link(child_gen); return buf_ptr(&child_gen->output_file_path); @@ -1458,20 +1455,20 @@ static const char *get_libc_crt_file(CodeGen *parent, const char *file) { c_file->source_path = musl_start_asm_path(parent, "crti.s"); musl_add_cc_args(parent, c_file, false); c_file->args.append("-Qunused-arguments"); - return build_libc_object(parent, "crti", c_file); + return build_libc_object(parent, "crti", c_file, progress_node); } else if (strcmp(file, "crtn.o") == 0) { CFile *c_file = allocate(1); c_file->source_path = musl_start_asm_path(parent, "crtn.s"); c_file->args.append("-Qunused-arguments"); musl_add_cc_args(parent, c_file, false); - return build_libc_object(parent, "crtn", c_file); + return build_libc_object(parent, "crtn", c_file, progress_node); } else if (strcmp(file, "crt1.o") == 0) { CFile *c_file = allocate(1); c_file->source_path = path_from_libc(parent, "musl" OS_SEP "crt" OS_SEP "crt1.c"); musl_add_cc_args(parent, c_file, false); c_file->args.append("-fno-stack-protector"); c_file->args.append("-DCRT"); - return build_libc_object(parent, "crt1", c_file); + return build_libc_object(parent, "crt1", c_file, progress_node); } else if (strcmp(file, "Scrt1.o") == 0) { CFile *c_file = allocate(1); 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) { c_file->args.append("-fPIC"); c_file->args.append("-fno-stack-protector"); c_file->args.append("-DCRT"); - return build_libc_object(parent, "Scrt1", c_file); + return build_libc_object(parent, "Scrt1", c_file, progress_node); } else { zig_unreachable(); } @@ -1491,10 +1488,11 @@ static const char *get_libc_crt_file(CodeGen *parent, const char *file) { } } -static Buf *build_a_raw(CodeGen *parent_gen, const char *aname, Buf *full_path, OutType child_out_type) { - CodeGen *child_gen = create_child_codegen(parent_gen, full_path, child_out_type, - parent_gen->libc); - codegen_set_out_name(child_gen, buf_create_from_str(aname)); +static Buf *build_a_raw(CodeGen *parent_gen, const char *aname, Buf *full_path, OutType child_out_type, + Stage2ProgressNode *progress_node) +{ + CodeGen *child_gen = create_child_codegen(parent_gen, full_path, child_out_type, parent_gen->libc, aname, + progress_node); // This is so that compiler_rt and libc.zig libraries know whether they // 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, return &child_gen->output_file_path; } -static Buf *build_compiler_rt(CodeGen *parent_gen, OutType child_out_type) { +static Buf *build_compiler_rt(CodeGen *parent_gen, OutType child_out_type, Stage2ProgressNode *progress_node) { Buf *full_path = buf_alloc(); os_path_join(parent_gen->zig_std_special_dir, buf_create_from_str("compiler_rt.zig"), full_path); - return build_a_raw(parent_gen, "compiler_rt", full_path, child_out_type); + return build_a_raw(parent_gen, "compiler_rt", full_path, child_out_type, progress_node); } -static Buf *build_c(CodeGen *parent_gen, OutType child_out_type) { +static Buf *build_c(CodeGen *parent_gen, OutType child_out_type, Stage2ProgressNode *progress_node) { Buf *full_path = buf_alloc(); os_path_join(parent_gen->zig_std_special_dir, buf_create_from_str("c.zig"), full_path); - return build_a_raw(parent_gen, "c", full_path, child_out_type); + return build_a_raw(parent_gen, "c", full_path, child_out_type, progress_node); } static const char *get_darwin_arch_string(const ZigTarget *t) { @@ -1616,7 +1614,7 @@ static void add_glibc_libs(LinkJob *lj) { Buf *artifact_dir; if ((err = glibc_build_dummies_and_maps(lj->codegen, glibc_abi, lj->codegen->zig_target, - &artifact_dir, true))) + &artifact_dir, true, lj->build_dep_prog_node))) { fprintf(stderr, "%s\n", err_str(err)); exit(1); @@ -1692,9 +1690,9 @@ static void construct_linker_job_elf(LinkJob *lj) { } else { crt1o = "Scrt1.o"; } - lj->args.append(get_libc_crt_file(g, crt1o)); + lj->args.append(get_libc_crt_file(g, crt1o, lj->build_dep_prog_node)); if (target_libc_needs_crti_crtn(g->zig_target)) { - lj->args.append(get_libc_crt_file(g, "crti.o")); + lj->args.append(get_libc_crt_file(g, "crti.o", lj->build_dep_prog_node)); } } @@ -1759,11 +1757,11 @@ static void construct_linker_job_elf(LinkJob *lj) { if (!g->is_dummy_so && (g->out_type == OutTypeExe || is_dyn_lib)) { if (g->libc_link_lib == nullptr) { - Buf *libc_a_path = build_c(g, OutTypeLib); + Buf *libc_a_path = build_c(g, OutTypeLib, lj->build_dep_prog_node); lj->args.append(buf_ptr(libc_a_path)); } - Buf *compiler_rt_o_path = build_compiler_rt(g, OutTypeLib); + Buf *compiler_rt_o_path = build_compiler_rt(g, OutTypeLib, lj->build_dep_prog_node); lj->args.append(buf_ptr(compiler_rt_o_path)); } @@ -1823,15 +1821,15 @@ static void construct_linker_job_elf(LinkJob *lj) { } } else if (target_is_glibc(g->zig_target)) { if (target_supports_libunwind(g->zig_target)) { - lj->args.append(build_libunwind(g)); + lj->args.append(build_libunwind(g, lj->build_dep_prog_node)); } add_glibc_libs(lj); - lj->args.append(get_libc_crt_file(g, "libc_nonshared.a")); + lj->args.append(get_libc_crt_file(g, "libc_nonshared.a", lj->build_dep_prog_node)); } else if (target_is_musl(g->zig_target)) { if (target_supports_libunwind(g->zig_target)) { - lj->args.append(build_libunwind(g)); + lj->args.append(build_libunwind(g, lj->build_dep_prog_node)); } - lj->args.append(build_musl(g)); + lj->args.append(build_musl(g, lj->build_dep_prog_node)); } else { zig_unreachable(); } @@ -1840,9 +1838,9 @@ static void construct_linker_job_elf(LinkJob *lj) { // crt end if (lj->link_in_crt) { if (target_is_android(g->zig_target)) { - lj->args.append(get_libc_crt_file(g, "crtend_android.o")); + lj->args.append(get_libc_crt_file(g, "crtend_android.o", lj->build_dep_prog_node)); } else if (target_libc_needs_crti_crtn(g->zig_target)) { - lj->args.append(get_libc_crt_file(g, "crtn.o")); + lj->args.append(get_libc_crt_file(g, "crtn.o", lj->build_dep_prog_node)); } } @@ -1887,10 +1885,10 @@ static void construct_linker_job_wasm(LinkJob *lj) { } if (g->out_type != OutTypeObj) { - Buf *libc_o_path = build_c(g, OutTypeObj); + Buf *libc_o_path = build_c(g, OutTypeObj, lj->build_dep_prog_node); lj->args.append(buf_ptr(libc_o_path)); - Buf *compiler_rt_o_path = build_compiler_rt(g, OutTypeObj); + Buf *compiler_rt_o_path = build_compiler_rt(g, OutTypeObj, lj->build_dep_prog_node); lj->args.append(buf_ptr(compiler_rt_o_path)); } } @@ -2170,14 +2168,14 @@ static void add_mingw_link_args(LinkJob *lj, bool is_library) { } if (is_dll) { - lj->args.append(get_libc_crt_file(g, "dllcrt2.o")); + lj->args.append(get_libc_crt_file(g, "dllcrt2.o", lj->build_dep_prog_node)); } else { - lj->args.append(get_libc_crt_file(g, "crt2.o")); + lj->args.append(get_libc_crt_file(g, "crt2.o", lj->build_dep_prog_node)); } - lj->args.append(get_libc_crt_file(g, "mingw32.lib")); - lj->args.append(get_libc_crt_file(g, "mingwex.lib")); - lj->args.append(get_libc_crt_file(g, "msvcrt-os.lib")); + lj->args.append(get_libc_crt_file(g, "mingw32.lib", lj->build_dep_prog_node)); + lj->args.append(get_libc_crt_file(g, "mingwex.lib", lj->build_dep_prog_node)); + lj->args.append(get_libc_crt_file(g, "msvcrt-os.lib", lj->build_dep_prog_node)); for (size_t def_i = 0; def_i < array_length(mingw_def_list); def_i += 1) { const char *name = mingw_def_list[def_i].name; @@ -2319,12 +2317,12 @@ static void construct_linker_job_coff(LinkJob *lj) { if (g->out_type == OutTypeExe || (g->out_type == OutTypeLib && g->is_dynamic)) { if (g->libc_link_lib == nullptr && !g->is_dummy_so) { - Buf *libc_a_path = build_c(g, OutTypeLib); + Buf *libc_a_path = build_c(g, OutTypeLib, lj->build_dep_prog_node); lj->args.append(buf_ptr(libc_a_path)); } // msvc compiler_rt is missing some stuff, so we still build it and rely on weak linkage - Buf *compiler_rt_o_path = build_compiler_rt(g, OutTypeLib); + Buf *compiler_rt_o_path = build_compiler_rt(g, OutTypeLib, lj->build_dep_prog_node); lj->args.append(buf_ptr(compiler_rt_o_path)); } @@ -2563,7 +2561,7 @@ static void construct_linker_job_macho(LinkJob *lj) { // compiler_rt on darwin is missing some stuff, so we still build it and rely on LinkOnce if (g->out_type == OutTypeExe || is_dyn_lib) { - Buf *compiler_rt_o_path = build_compiler_rt(g, OutTypeLib); + Buf *compiler_rt_o_path = build_compiler_rt(g, OutTypeLib, lj->build_dep_prog_node); lj->args.append(buf_ptr(compiler_rt_o_path)); } @@ -2621,16 +2619,22 @@ static void construct_linker_job(LinkJob *lj) { } } -void zig_link_add_compiler_rt(CodeGen *g) { - Buf *compiler_rt_o_path = build_compiler_rt(g, OutTypeObj); +void zig_link_add_compiler_rt(CodeGen *g, Stage2ProgressNode *progress_node) { + Buf *compiler_rt_o_path = build_compiler_rt(g, OutTypeObj, progress_node); g->link_objects.append(compiler_rt_o_path); } void codegen_link(CodeGen *g) { codegen_add_time_event(g, "Build Dependencies"); - LinkJob lj = {0}; + { + const char *progress_name = "Build Dependencies"; + lj.build_dep_prog_node = stage2_progress_start(g->progress_node, + progress_name, strlen(progress_name), 0); + } + + // even though we're calling LLD as a library it thinks the first // argument is its own exe name lj.args.append("lld"); @@ -2656,6 +2660,12 @@ void codegen_link(CodeGen *g) { } ZigLLVM_OSType os_type = get_llvm_os_type(g->zig_target->os); codegen_add_time_event(g, "LLVM Link"); + { + const char *progress_name = "linking"; + Stage2ProgressNode *child_progress_node = stage2_progress_start(g->progress_node, + progress_name, strlen(progress_name), 0); + (void)child_progress_node; + } if (g->verbose_link) { fprintf(stderr, "ar rcs %s", buf_ptr(&g->output_file_path)); for (size_t i = 0; i < file_names.length; i += 1) { diff --git a/src/main.cpp b/src/main.cpp index cd1f742181..13c93b269d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -506,6 +506,8 @@ int main(int argc, char **argv) { ZigList llvm_argv = {0}; llvm_argv.append("zig (LLVM option parsing)"); + Stage2ProgressNode *root_progress_node = stage2_progress_start_root(stage2_progress_create(), "", 0, 0); + if (argc >= 2 && strcmp(argv[1], "build") == 0) { Buf zig_exe_path_buf = BUF_INIT; if ((err = os_self_exe_path(&zig_exe_path_buf))) { @@ -589,7 +591,7 @@ int main(int argc, char **argv) { } CodeGen *g = codegen_create(main_pkg_path, build_runner_path, &target, OutTypeExe, - BuildModeDebug, override_lib_dir, nullptr, &full_cache_dir, false); + BuildModeDebug, override_lib_dir, nullptr, &full_cache_dir, false, root_progress_node); g->valgrind_support = valgrind_support; g->enable_time_report = timing_info; codegen_set_out_name(g, buf_create_from_str("build")); @@ -1034,17 +1036,19 @@ int main(int argc, char **argv) { ZigLibCInstallation libc; if ((err = zig_libc_parse(&libc, buf_create_from_str(in_file), &target, true))) return EXIT_FAILURE; + stage2_progress_end(root_progress_node); return EXIT_SUCCESS; } ZigLibCInstallation libc; if ((err = zig_libc_find_native(&libc, true))) return EXIT_FAILURE; zig_libc_render(&libc, stdout); + stage2_progress_end(root_progress_node); return EXIT_SUCCESS; } case CmdBuiltin: { CodeGen *g = codegen_create(main_pkg_path, nullptr, &target, - out_type, build_mode, override_lib_dir, nullptr, nullptr, false); + out_type, build_mode, override_lib_dir, nullptr, nullptr, false, root_progress_node); codegen_set_strip(g, strip); for (size_t i = 0; i < link_libs.length; i += 1) { 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) { fprintf(stderr, "unable to write to stdout: %s\n", strerror(ferror(stdout))); return EXIT_FAILURE; } + stage2_progress_end(root_progress_node); return EXIT_SUCCESS; } case CmdRun: @@ -1148,7 +1153,7 @@ int main(int argc, char **argv) { cache_dir_buf = buf_create_from_str(cache_dir); } CodeGen *g = codegen_create(main_pkg_path, zig_root_source_file, &target, out_type, build_mode, - override_lib_dir, libc, cache_dir_buf, cmd == CmdTest); + override_lib_dir, libc, cache_dir_buf, cmd == CmdTest, root_progress_node); if (llvm_argv.length >= 2) codegen_set_llvm_argv(g, llvm_argv.items + 1, llvm_argv.length - 2); g->valgrind_support = valgrind_support; g->want_pic = want_pic; @@ -1276,6 +1281,7 @@ int main(int argc, char **argv) { if (printf("%s\n", buf_ptr(&g->output_file_path)) < 0) return EXIT_FAILURE; } + stage2_progress_end(root_progress_node); return EXIT_SUCCESS; } else { zig_unreachable(); @@ -1284,6 +1290,7 @@ int main(int argc, char **argv) { codegen_translate_c(g, in_file_buf, stdout, cmd == CmdTranslateCUserland); if (timing_info) codegen_print_timing_report(g, stderr); + stage2_progress_end(root_progress_node); return EXIT_SUCCESS; } else if (cmd == CmdTest) { codegen_set_emit_file_type(g, emit_file_type); @@ -1338,6 +1345,7 @@ int main(int argc, char **argv) { fprintf(stderr, "\nTests failed. Use the following command to reproduce the failure:\n"); fprintf(stderr, "%s\n", buf_ptr(test_exe_path)); } + stage2_progress_end(root_progress_node); return (term.how == TerminationIdClean) ? term.code : -1; } else { zig_unreachable(); diff --git a/src/userland.cpp b/src/userland.cpp index d82f776cd6..9b5a2e9054 100644 --- a/src/userland.cpp +++ b/src/userland.cpp @@ -59,3 +59,31 @@ stage2_DepNextResult stage2_DepTokenizer_next(stage2_DepTokenizer *self) { const char *msg = "stage0 called stage2_DepTokenizer_next"; stage2_panic(msg, strlen(msg)); } + + +struct Stage2Progress { + int trash; +}; + +struct Stage2ProgressNode { + int trash; +}; + +Stage2Progress *stage2_progress_create(void) { + return nullptr; +} + +void stage2_progress_destroy(Stage2Progress *progress) {} + +Stage2ProgressNode *stage2_progress_start_root(Stage2Progress *progress, + const char *name_ptr, size_t name_len, size_t estimated_total_items) +{ + return nullptr; +} +Stage2ProgressNode *stage2_progress_start(Stage2ProgressNode *node, + const char *name_ptr, size_t name_len, size_t estimated_total_items) +{ + return nullptr; +} +void stage2_progress_end(Stage2ProgressNode *node) {} +void stage2_progress_complete_one(Stage2ProgressNode *node) {} diff --git a/src/userland.h b/src/userland.h index c92caf327e..e58f49200c 100644 --- a/src/userland.h +++ b/src/userland.h @@ -156,4 +156,23 @@ ZIG_EXTERN_C void stage2_DepTokenizer_deinit(stage2_DepTokenizer *self); // ABI warning ZIG_EXTERN_C stage2_DepNextResult stage2_DepTokenizer_next(stage2_DepTokenizer *self); +// ABI warning +struct Stage2Progress; +// ABI warning +struct Stage2ProgressNode; +// ABI warning +ZIG_EXTERN_C Stage2Progress *stage2_progress_create(void); +// ABI warning +ZIG_EXTERN_C void stage2_progress_destroy(Stage2Progress *progress); +// ABI warning +ZIG_EXTERN_C Stage2ProgressNode *stage2_progress_start_root(Stage2Progress *progress, + const char *name_ptr, size_t name_len, size_t estimated_total_items); +// ABI warning +ZIG_EXTERN_C Stage2ProgressNode *stage2_progress_start(Stage2ProgressNode *node, + const char *name_ptr, size_t name_len, size_t estimated_total_items); +// ABI warning +ZIG_EXTERN_C void stage2_progress_end(Stage2ProgressNode *node); +// ABI warning +ZIG_EXTERN_C void stage2_progress_complete_one(Stage2ProgressNode *node); + #endif