mirror of
https://github.com/ziglang/zig.git
synced 2025-02-04 12:01:18 +00:00
commit
e42d86b657
@ -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];
|
||||
}
|
||||
|
||||
|
258
lib/std/progress.zig
Normal file
258
lib/std/progress.zig
Normal file
@ -0,0 +1,258 @@
|
||||
const std = @import("std");
|
||||
const testing = std.testing;
|
||||
const assert = std.debug.assert;
|
||||
|
||||
/// 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,
|
||||
|
||||
root: Node = undefined,
|
||||
|
||||
/// 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,
|
||||
|
||||
/// When the previous refresh was written to the terminal.
|
||||
/// Used to compare with `refresh_rate_ms`.
|
||||
prev_refresh_timestamp: u64 = undefined,
|
||||
|
||||
/// This buffer represents the maximum number of bytes written to the terminal
|
||||
/// with each refresh.
|
||||
output_buffer: [100]u8 = undefined,
|
||||
|
||||
/// 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,
|
||||
|
||||
/// 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,
|
||||
|
||||
/// 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,
|
||||
};
|
||||
}
|
||||
|
||||
/// 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();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
/// 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| {
|
||||
self.terminal = if (stderr.supportsAnsiEscapeCodes()) 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.columns_written = 0;
|
||||
self.prev_refresh_timestamp = 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) {
|
||||
// restore cursor position
|
||||
end += (std.fmt.bufPrint(self.output_buffer[end..], "\x1b[{}D", self.columns_written) catch unreachable).len;
|
||||
self.columns_written = 0;
|
||||
|
||||
// clear rest of line
|
||||
end += (std.fmt.bufPrint(self.output_buffer[end..], "\x1b[0K") catch unreachable).len;
|
||||
}
|
||||
|
||||
if (!self.done) {
|
||||
var need_ellipse = false;
|
||||
var maybe_node: ?*Node = &self.root;
|
||||
while (maybe_node) |node| {
|
||||
if (need_ellipse) {
|
||||
self.bufWrite(&end, "...");
|
||||
}
|
||||
need_ellipse = false;
|
||||
if (node.name.len != 0 or node.estimated_total_items != null) {
|
||||
if (node.name.len != 0) {
|
||||
self.bufWrite(&end, "{}", node.name);
|
||||
need_ellipse = true;
|
||||
}
|
||||
if (node.estimated_total_items) |total| {
|
||||
if (need_ellipse) self.bufWrite(&end, " ");
|
||||
self.bufWrite(&end, "[{}/{}] ", node.completed_items, total);
|
||||
need_ellipse = false;
|
||||
} else if (node.completed_items != 0) {
|
||||
if (need_ellipse) self.bufWrite(&end, " ");
|
||||
self.bufWrite(&end, "[{}] ", node.completed_items);
|
||||
need_ellipse = false;
|
||||
}
|
||||
}
|
||||
maybe_node = node.recently_updated_child;
|
||||
}
|
||||
if (need_ellipse) {
|
||||
self.bufWrite(&end, "...");
|
||||
}
|
||||
}
|
||||
|
||||
_ = 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();
|
||||
}
|
||||
|
||||
pub fn log(self: *Progress, comptime format: []const u8, args: ...) void {
|
||||
const file = self.terminal orelse return;
|
||||
self.refresh();
|
||||
file.outStream().stream.print(format, args) catch {
|
||||
self.terminal = null;
|
||||
return;
|
||||
};
|
||||
self.columns_written = 0;
|
||||
}
|
||||
|
||||
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 disable = true;
|
||||
if (disable) {
|
||||
// This test is disabled because it uses time.sleep() and is therefore slow. It also
|
||||
// prints bogus progress data to stderr.
|
||||
return error.SkipZigTest;
|
||||
}
|
||||
var progress = Progress{};
|
||||
const root_node = try progress.start("", 100);
|
||||
defer root_node.end();
|
||||
|
||||
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 += 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.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.refresh();
|
||||
std.time.sleep(10 * std.time.millisecond);
|
||||
node.end();
|
||||
}
|
||||
}
|
@ -2,28 +2,33 @@ const std = @import("std");
|
||||
const io = std.io;
|
||||
const builtin = @import("builtin");
|
||||
const test_fn_list = builtin.test_functions;
|
||||
const warn = std.debug.warn;
|
||||
|
||||
pub fn main() !void {
|
||||
pub fn main() anyerror!void {
|
||||
var ok_count: usize = 0;
|
||||
var skip_count: usize = 0;
|
||||
for (test_fn_list) |test_fn, i| {
|
||||
warn("{}/{} {}...", i + 1, test_fn_list.len, test_fn.name);
|
||||
var progress = std.Progress{};
|
||||
const root_node = progress.start("Test", test_fn_list.len) catch |err| switch (err) {
|
||||
// TODO still run tests in this case
|
||||
error.TimerUnsupported => @panic("timer unsupported"),
|
||||
};
|
||||
|
||||
for (test_fn_list) |test_fn, i| {
|
||||
var test_node = root_node.start(test_fn.name, null);
|
||||
test_node.activate();
|
||||
if (test_fn.func()) |_| {
|
||||
ok_count += 1;
|
||||
warn("OK\n");
|
||||
test_node.end();
|
||||
} else |err| switch (err) {
|
||||
error.SkipZigTest => {
|
||||
skip_count += 1;
|
||||
warn("SKIP\n");
|
||||
test_node.end();
|
||||
progress.log("{}...SKIP\n", test_fn.name);
|
||||
},
|
||||
else => return err,
|
||||
}
|
||||
}
|
||||
if (ok_count == test_fn_list.len) {
|
||||
warn("All tests passed.\n");
|
||||
} else {
|
||||
warn("{} passed; {} skipped.\n", ok_count, skip_count);
|
||||
root_node.end();
|
||||
if (ok_count != test_fn_list.len) {
|
||||
progress.log("{} passed; {} skipped.\n", ok_count, skip_count);
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
@ -456,3 +456,62 @@ 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_disable_tty(progress: *std.Progress) void {
|
||||
progress.terminal = null;
|
||||
}
|
||||
|
||||
// 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();
|
||||
}
|
||||
|
@ -2010,6 +2010,8 @@ struct CodeGen {
|
||||
|
||||
ZigFn *largest_frame_fn;
|
||||
|
||||
Stage2ProgressNode *progress_node;
|
||||
|
||||
WantPIC want_pic;
|
||||
WantStackCheck want_stack_check;
|
||||
CacheHash cache_hash;
|
||||
|
@ -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 *parent_progress_node)
|
||||
{
|
||||
Stage2ProgressNode *child_progress_node = stage2_progress_start(
|
||||
parent_progress_node ? parent_progress_node : 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<CodeGen>(1);
|
||||
g->progress_node = progress_node;
|
||||
|
||||
codegen_add_time_event(g, "Initialize");
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
142
src/link.cpp
142
src/link.cpp
@ -594,11 +594,13 @@ struct LinkJob {
|
||||
ZigList<const char *> args;
|
||||
bool link_in_crt;
|
||||
HashMap<Buf *, bool, buf_hash, buf_eql_buf> 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<CFile *> 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/<arch>/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<CFile>(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<CFile>(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<CFile>(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<CFile>(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<CFile>(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<CFile>(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<CFile>(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<CFile>(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<CFile>(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) {
|
||||
|
17
src/main.cpp
17
src/main.cpp
@ -587,9 +587,10 @@ int main(int argc, char **argv) {
|
||||
Buf *cache_dir_buf = buf_create_from_str(cache_dir);
|
||||
full_cache_dir = os_path_resolve(&cache_dir_buf, 1);
|
||||
}
|
||||
Stage2ProgressNode *root_progress_node = stage2_progress_start_root(stage2_progress_create(), "", 0, 0);
|
||||
|
||||
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"));
|
||||
@ -963,6 +964,10 @@ int main(int argc, char **argv) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
Stage2Progress *progress = stage2_progress_create();
|
||||
Stage2ProgressNode *root_progress_node = stage2_progress_start_root(progress, "", 0, 0);
|
||||
if (color == ErrColorOff) stage2_progress_disable_tty(progress);
|
||||
|
||||
init_all_targets();
|
||||
|
||||
ZigTarget target;
|
||||
@ -1034,17 +1039,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 +1067,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 +1156,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 +1284,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 +1293,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 +1348,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();
|
||||
|
@ -59,3 +59,32 @@ 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) {}
|
||||
void stage2_progress_disable_tty(Stage2Progress *progress) {}
|
||||
|
@ -156,4 +156,25 @@ 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_disable_tty(Stage2Progress *progress);
|
||||
// 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
|
||||
|
@ -87,7 +87,7 @@ fn exec(cwd: []const u8, argv: []const []const u8) !ChildProcess.ExecResult {
|
||||
fn testZigInitLib(zig_exe: []const u8, dir_path: []const u8) !void {
|
||||
_ = try exec(dir_path, [_][]const u8{ zig_exe, "init-lib" });
|
||||
const test_result = try exec(dir_path, [_][]const u8{ zig_exe, "build", "test" });
|
||||
testing.expect(std.mem.endsWith(u8, test_result.stderr, "All tests passed.\n"));
|
||||
testing.expect(std.mem.eql(u8, test_result.stderr, ""));
|
||||
}
|
||||
|
||||
fn testZigInitExe(zig_exe: []const u8, dir_path: []const u8) !void {
|
||||
@ -136,6 +136,6 @@ fn testMissingOutputPath(zig_exe: []const u8, dir_path: []const u8) !void {
|
||||
const output_path = try fs.path.join(a, [_][]const u8{ "does", "not", "exist" });
|
||||
const source_path = try fs.path.join(a, [_][]const u8{ "src", "main.zig" });
|
||||
_ = try exec(dir_path, [_][]const u8{
|
||||
zig_exe, "build-exe", source_path, "--output-dir", output_path
|
||||
zig_exe, "build-exe", source_path, "--output-dir", output_path,
|
||||
});
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user