mirror of
https://github.com/ziglang/zig.git
synced 2026-02-21 16:54:52 +00:00
Remove some unwanted changes
Leftovers after a long rebase.
This commit is contained in:
parent
608a73efb1
commit
5b981b1be7
189
build.zig
189
build.zig
@ -359,195 +359,6 @@ pub fn build(b: *Builder) !void {
|
||||
test_step.dependOn(docs_step);
|
||||
}
|
||||
|
||||
fn dependOnLib(b: *Builder, lib_exe_obj: anytype, dep: LibraryDep) void {
|
||||
for (dep.libdirs.items) |lib_dir| {
|
||||
lib_exe_obj.addLibPath(lib_dir);
|
||||
}
|
||||
const lib_dir = fs.path.join(
|
||||
b.allocator,
|
||||
&[_][]const u8{ dep.prefix, "lib" },
|
||||
) catch unreachable;
|
||||
for (dep.system_libs.items) |lib| {
|
||||
const static_bare_name = if (mem.eql(u8, lib, "curses"))
|
||||
@as([]const u8, "libncurses.a")
|
||||
else
|
||||
b.fmt("lib{s}.a", .{lib});
|
||||
const static_lib_name = fs.path.join(
|
||||
b.allocator,
|
||||
&[_][]const u8{ lib_dir, static_bare_name },
|
||||
) catch unreachable;
|
||||
const have_static = fileExists(static_lib_name) catch unreachable;
|
||||
if (have_static) {
|
||||
lib_exe_obj.addObjectFile(static_lib_name);
|
||||
} else {
|
||||
lib_exe_obj.linkSystemLibrary(lib);
|
||||
}
|
||||
}
|
||||
for (dep.libs.items) |lib| {
|
||||
lib_exe_obj.addObjectFile(lib);
|
||||
}
|
||||
for (dep.includes.items) |include_path| {
|
||||
lib_exe_obj.addIncludeDir(include_path);
|
||||
}
|
||||
}
|
||||
|
||||
fn fileExists(filename: []const u8) !bool {
|
||||
fs.cwd().access(filename, .{}) catch |err| switch (err) {
|
||||
error.FileNotFound => return false,
|
||||
else => return err,
|
||||
};
|
||||
return true;
|
||||
}
|
||||
|
||||
fn addCppLib(b: *Builder, lib_exe_obj: anytype, cmake_binary_dir: []const u8, lib_name: []const u8) void {
|
||||
lib_exe_obj.addObjectFile(fs.path.join(b.allocator, &[_][]const u8{
|
||||
cmake_binary_dir,
|
||||
"zigcpp",
|
||||
b.fmt("{s}{s}{s}", .{ lib_exe_obj.target.libPrefix(), lib_name, lib_exe_obj.target.staticLibSuffix() }),
|
||||
}) catch unreachable);
|
||||
}
|
||||
|
||||
const LibraryDep = struct {
|
||||
prefix: []const u8,
|
||||
libdirs: ArrayList([]const u8),
|
||||
libs: ArrayList([]const u8),
|
||||
system_libs: ArrayList([]const u8),
|
||||
includes: ArrayList([]const u8),
|
||||
};
|
||||
|
||||
fn findLLVM(b: *Builder, llvm_config_exe: []const u8) !LibraryDep {
|
||||
const shared_mode = try b.exec(&[_][]const u8{ llvm_config_exe, "--shared-mode" });
|
||||
const is_static = mem.startsWith(u8, shared_mode, "static");
|
||||
const libs_output = if (is_static)
|
||||
try b.exec(&[_][]const u8{
|
||||
llvm_config_exe,
|
||||
"--libfiles",
|
||||
"--system-libs",
|
||||
})
|
||||
else
|
||||
try b.exec(&[_][]const u8{
|
||||
llvm_config_exe,
|
||||
"--libs",
|
||||
});
|
||||
const includes_output = try b.exec(&[_][]const u8{ llvm_config_exe, "--includedir" });
|
||||
const libdir_output = try b.exec(&[_][]const u8{ llvm_config_exe, "--libdir" });
|
||||
const prefix_output = try b.exec(&[_][]const u8{ llvm_config_exe, "--prefix" });
|
||||
|
||||
var result = LibraryDep{
|
||||
.prefix = mem.tokenize(prefix_output, " \r\n").next().?,
|
||||
.libs = ArrayList([]const u8).init(b.allocator),
|
||||
.system_libs = ArrayList([]const u8).init(b.allocator),
|
||||
.includes = ArrayList([]const u8).init(b.allocator),
|
||||
.libdirs = ArrayList([]const u8).init(b.allocator),
|
||||
};
|
||||
{
|
||||
var it = mem.tokenize(libs_output, " \r\n");
|
||||
while (it.next()) |lib_arg| {
|
||||
if (mem.startsWith(u8, lib_arg, "-l")) {
|
||||
try result.system_libs.append(lib_arg[2..]);
|
||||
} else {
|
||||
if (fs.path.isAbsolute(lib_arg)) {
|
||||
try result.libs.append(lib_arg);
|
||||
} else {
|
||||
var lib_arg_copy = lib_arg;
|
||||
if (mem.endsWith(u8, lib_arg, ".lib")) {
|
||||
lib_arg_copy = lib_arg[0 .. lib_arg.len - 4];
|
||||
}
|
||||
try result.system_libs.append(lib_arg_copy);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
var it = mem.tokenize(includes_output, " \r\n");
|
||||
while (it.next()) |include_arg| {
|
||||
if (mem.startsWith(u8, include_arg, "-I")) {
|
||||
try result.includes.append(include_arg[2..]);
|
||||
} else {
|
||||
try result.includes.append(include_arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
var it = mem.tokenize(libdir_output, " \r\n");
|
||||
while (it.next()) |libdir| {
|
||||
if (mem.startsWith(u8, libdir, "-L")) {
|
||||
try result.libdirs.append(libdir[2..]);
|
||||
} else {
|
||||
try result.libdirs.append(libdir);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
fn configureStage2(b: *Builder, exe: anytype, ctx: Context, need_cpp_includes: bool) !void {
|
||||
exe.addIncludeDir("src");
|
||||
exe.addIncludeDir(ctx.cmake_binary_dir);
|
||||
addCppLib(b, exe, ctx.cmake_binary_dir, "zigcpp");
|
||||
assert(ctx.lld_include_dir.len != 0);
|
||||
exe.addIncludeDir(ctx.lld_include_dir);
|
||||
{
|
||||
var it = mem.tokenize(ctx.lld_libraries, ";");
|
||||
while (it.next()) |lib| {
|
||||
exe.addObjectFile(lib);
|
||||
}
|
||||
}
|
||||
{
|
||||
var it = mem.tokenize(ctx.clang_libraries, ";");
|
||||
while (it.next()) |lib| {
|
||||
exe.addObjectFile(lib);
|
||||
}
|
||||
}
|
||||
dependOnLib(b, exe, ctx.llvm);
|
||||
|
||||
// Boy, it sure would be nice to simply linkSystemLibrary("c++") and rely on zig's
|
||||
// ability to provide libc++ right? Well thanks to C++ not having a stable ABI this
|
||||
// will cause linker errors. It would work in the situation when `zig cc` is used to
|
||||
// build LLVM, Clang, and LLD, however when depending on them as system libraries, system
|
||||
// libc++ must be used.
|
||||
const cross_compile = false; // TODO
|
||||
if (cross_compile) {
|
||||
// In this case we assume that zig cc was used to build the LLVM, Clang, LLD dependencies.
|
||||
exe.linkSystemLibrary("c++");
|
||||
} else {
|
||||
if (exe.target.getOsTag() == .linux) {
|
||||
// First we try to static link against gcc libstdc++. If that doesn't work,
|
||||
// we fall back to -lc++ and cross our fingers.
|
||||
addCxxKnownPath(b, ctx, exe, "libstdc++.a", "", need_cpp_includes) catch |err| switch (err) {
|
||||
error.RequiredLibraryNotFound => {
|
||||
exe.linkSystemLibrary("c++");
|
||||
},
|
||||
else => |e| return e,
|
||||
};
|
||||
|
||||
exe.linkSystemLibrary("pthread");
|
||||
} else if (exe.target.isFreeBSD()) {
|
||||
try addCxxKnownPath(b, ctx, exe, "libc++.a", null, need_cpp_includes);
|
||||
exe.linkSystemLibrary("pthread");
|
||||
} else if (exe.target.isDarwin()) {
|
||||
if (addCxxKnownPath(b, ctx, exe, "libgcc_eh.a", "", need_cpp_includes)) {
|
||||
// Compiler is GCC.
|
||||
try addCxxKnownPath(b, ctx, exe, "libstdc++.a", null, need_cpp_includes);
|
||||
exe.linkSystemLibrary("pthread");
|
||||
// TODO LLD cannot perform this link.
|
||||
// Set ZIG_SYSTEM_LINKER_HACK env var to use system linker ld instead.
|
||||
// See https://github.com/ziglang/zig/issues/1535
|
||||
} else |err| switch (err) {
|
||||
error.RequiredLibraryNotFound => {
|
||||
// System compiler, not gcc.
|
||||
exe.linkSystemLibrary("c++");
|
||||
},
|
||||
else => |e| return e,
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx.dia_guids_lib.len != 0) {
|
||||
exe.addObjectFile(ctx.dia_guids_lib);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn addCxxKnownPath(
|
||||
b: *Builder,
|
||||
ctx: CMakeConfig,
|
||||
|
||||
@ -1,229 +0,0 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright (c) 2015-2020 Zig Contributors
|
||||
// This file is part of [zig](https://ziglang.org/), which is MIT licensed.
|
||||
// The MIT license requires this copyright notice to be included in all copies
|
||||
// and substantial portions of the software.
|
||||
const std = @import("std.zig");
|
||||
const debug = std.debug;
|
||||
const mem = std.mem;
|
||||
const Allocator = mem.Allocator;
|
||||
const assert = debug.assert;
|
||||
const testing = std.testing;
|
||||
const ArrayList = std.ArrayList;
|
||||
|
||||
/// A contiguous, growable list of items in memory, with a sentinel after them.
|
||||
/// The sentinel is maintained when appending, resizing, etc.
|
||||
/// If you do not need a sentinel, consider using `ArrayList` instead.
|
||||
pub fn ArrayListSentineled(comptime T: type, comptime sentinel: T) type {
|
||||
return struct {
|
||||
list: ArrayList(T),
|
||||
|
||||
const Self = @This();
|
||||
|
||||
/// Must deinitialize with deinit.
|
||||
pub fn init(allocator: *Allocator, m: []const T) !Self {
|
||||
var self = try initSize(allocator, m.len);
|
||||
mem.copy(T, self.list.items, m);
|
||||
return self;
|
||||
}
|
||||
|
||||
/// Initialize memory to size bytes of undefined values.
|
||||
/// Must deinitialize with deinit.
|
||||
pub fn initSize(allocator: *Allocator, size: usize) !Self {
|
||||
var self = initNull(allocator);
|
||||
try self.resize(size);
|
||||
return self;
|
||||
}
|
||||
|
||||
/// Initialize with capacity to hold at least num bytes.
|
||||
/// Must deinitialize with deinit.
|
||||
pub fn initCapacity(allocator: *Allocator, num: usize) !Self {
|
||||
var self = Self{ .list = try ArrayList(T).initCapacity(allocator, num + 1) };
|
||||
self.list.appendAssumeCapacity(sentinel);
|
||||
return self;
|
||||
}
|
||||
|
||||
/// Must deinitialize with deinit.
|
||||
/// None of the other operations are valid until you do one of these:
|
||||
/// * `replaceContents`
|
||||
/// * `resize`
|
||||
pub fn initNull(allocator: *Allocator) Self {
|
||||
return Self{ .list = ArrayList(T).init(allocator) };
|
||||
}
|
||||
|
||||
/// Must deinitialize with deinit.
|
||||
pub fn initFromBuffer(buffer: Self) !Self {
|
||||
return Self.init(buffer.list.allocator, buffer.span());
|
||||
}
|
||||
|
||||
/// Takes ownership of the passed in slice. The slice must have been
|
||||
/// allocated with `allocator`.
|
||||
/// Must deinitialize with deinit.
|
||||
pub fn fromOwnedSlice(allocator: *Allocator, slice: []T) !Self {
|
||||
var self = Self{ .list = ArrayList(T).fromOwnedSlice(allocator, slice) };
|
||||
try self.list.append(sentinel);
|
||||
return self;
|
||||
}
|
||||
|
||||
/// The caller owns the returned memory. The list becomes null and is safe to `deinit`.
|
||||
pub fn toOwnedSlice(self: *Self) [:sentinel]T {
|
||||
const allocator = self.list.allocator;
|
||||
const result = self.list.toOwnedSlice();
|
||||
self.* = initNull(allocator);
|
||||
return result[0 .. result.len - 1 :sentinel];
|
||||
}
|
||||
|
||||
/// Only works when `T` is `u8`.
|
||||
pub fn allocPrint(allocator: *Allocator, comptime format: []const u8, args: anytype) !Self {
|
||||
const size = std.math.cast(usize, std.fmt.count(format, args)) catch |err| switch (err) {
|
||||
error.Overflow => return error.OutOfMemory,
|
||||
};
|
||||
var self = try Self.initSize(allocator, size);
|
||||
assert((std.fmt.bufPrint(self.list.items, format, args) catch unreachable).len == size);
|
||||
return self;
|
||||
}
|
||||
|
||||
pub fn deinit(self: *Self) void {
|
||||
self.list.deinit();
|
||||
}
|
||||
|
||||
pub fn span(self: anytype) @TypeOf(self.list.items[0..:sentinel]) {
|
||||
return self.list.items[0..self.len() :sentinel];
|
||||
}
|
||||
|
||||
pub fn shrink(self: *Self, new_len: usize) void {
|
||||
assert(new_len <= self.len());
|
||||
self.list.shrink(new_len + 1);
|
||||
self.list.items[self.len()] = sentinel;
|
||||
}
|
||||
|
||||
pub fn resize(self: *Self, new_len: usize) !void {
|
||||
try self.list.resize(new_len + 1);
|
||||
self.list.items[self.len()] = sentinel;
|
||||
}
|
||||
|
||||
pub fn isNull(self: Self) bool {
|
||||
return self.list.items.len == 0;
|
||||
}
|
||||
|
||||
pub fn len(self: Self) usize {
|
||||
return self.list.items.len - 1;
|
||||
}
|
||||
|
||||
pub fn capacity(self: Self) usize {
|
||||
return if (self.list.capacity > 0)
|
||||
self.list.capacity - 1
|
||||
else
|
||||
0;
|
||||
}
|
||||
|
||||
pub fn appendSlice(self: *Self, m: []const T) !void {
|
||||
const old_len = self.len();
|
||||
try self.resize(old_len + m.len);
|
||||
mem.copy(T, self.list.items[old_len..], m);
|
||||
}
|
||||
|
||||
pub fn append(self: *Self, byte: T) !void {
|
||||
const old_len = self.len();
|
||||
try self.resize(old_len + 1);
|
||||
self.list.items[old_len] = byte;
|
||||
}
|
||||
|
||||
pub fn eql(self: Self, m: []const T) bool {
|
||||
return mem.eql(T, self.span(), m);
|
||||
}
|
||||
|
||||
pub fn startsWith(self: Self, m: []const T) bool {
|
||||
if (self.len() < m.len) return false;
|
||||
return mem.eql(T, self.list.items[0..m.len], m);
|
||||
}
|
||||
|
||||
pub fn endsWith(self: Self, m: []const T) bool {
|
||||
const l = self.len();
|
||||
if (l < m.len) return false;
|
||||
const start = l - m.len;
|
||||
return mem.eql(T, self.list.items[start..l], m);
|
||||
}
|
||||
|
||||
pub fn replaceContents(self: *Self, m: []const T) !void {
|
||||
try self.resize(m.len);
|
||||
mem.copy(T, self.list.items, m);
|
||||
}
|
||||
|
||||
/// Initializes an OutStream which will append to the list.
|
||||
/// This function may be called only when `T` is `u8`.
|
||||
pub fn outStream(self: *Self) std.io.OutStream(*Self, error{OutOfMemory}, appendWrite) {
|
||||
return .{ .context = self };
|
||||
}
|
||||
|
||||
/// Same as `append` except it returns the number of bytes written, which is always the same
|
||||
/// as `m.len`. The purpose of this function existing is to match `std.io.OutStream` API.
|
||||
/// This function may be called only when `T` is `u8`.
|
||||
pub fn appendWrite(self: *Self, m: []const u8) !usize {
|
||||
try self.appendSlice(m);
|
||||
return m.len;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
test "simple" {
|
||||
var buf = try ArrayListSentineled(u8, 0).init(testing.allocator, "");
|
||||
defer buf.deinit();
|
||||
|
||||
testing.expect(buf.len() == 0);
|
||||
try buf.appendSlice("hello");
|
||||
try buf.appendSlice(" ");
|
||||
try buf.appendSlice("world");
|
||||
testing.expect(buf.eql("hello world"));
|
||||
testing.expect(mem.eql(u8, mem.spanZ(buf.span().ptr), buf.span()));
|
||||
|
||||
var buf2 = try ArrayListSentineled(u8, 0).initFromBuffer(buf);
|
||||
defer buf2.deinit();
|
||||
testing.expect(buf.eql(buf2.span()));
|
||||
|
||||
testing.expect(buf.startsWith("hell"));
|
||||
testing.expect(buf.endsWith("orld"));
|
||||
|
||||
try buf2.resize(4);
|
||||
testing.expect(buf.startsWith(buf2.span()));
|
||||
}
|
||||
|
||||
test "initSize" {
|
||||
var buf = try ArrayListSentineled(u8, 0).initSize(testing.allocator, 3);
|
||||
defer buf.deinit();
|
||||
testing.expect(buf.len() == 3);
|
||||
try buf.appendSlice("hello");
|
||||
testing.expect(mem.eql(u8, buf.span()[3..], "hello"));
|
||||
}
|
||||
|
||||
test "initCapacity" {
|
||||
var buf = try ArrayListSentineled(u8, 0).initCapacity(testing.allocator, 10);
|
||||
defer buf.deinit();
|
||||
testing.expect(buf.len() == 0);
|
||||
testing.expect(buf.capacity() >= 10);
|
||||
const old_cap = buf.capacity();
|
||||
try buf.appendSlice("hello");
|
||||
testing.expect(buf.len() == 5);
|
||||
testing.expect(buf.capacity() == old_cap);
|
||||
testing.expect(mem.eql(u8, buf.span(), "hello"));
|
||||
}
|
||||
|
||||
test "print" {
|
||||
var buf = try ArrayListSentineled(u8, 0).init(testing.allocator, "");
|
||||
defer buf.deinit();
|
||||
|
||||
try buf.outStream().print("Hello {d} the {s}", .{ 2, "world" });
|
||||
testing.expect(buf.eql("Hello 2 the world"));
|
||||
}
|
||||
|
||||
test "outStream" {
|
||||
var buffer = try ArrayListSentineled(u8, 0).initSize(testing.allocator, 0);
|
||||
defer buffer.deinit();
|
||||
const buf_stream = buffer.outStream();
|
||||
|
||||
const x: i32 = 42;
|
||||
const y: i32 = 1234;
|
||||
try buf_stream.print("x: {}\ny: {}\n", .{ x, y });
|
||||
|
||||
testing.expect(mem.eql(u8, buffer.span(), "x: 42\ny: 1234\n"));
|
||||
}
|
||||
@ -1,310 +0,0 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright (c) 2015-2020 Zig Contributors
|
||||
// This file is part of [zig](https://ziglang.org/), which is MIT licensed.
|
||||
// The MIT license requires this copyright notice to be included in all copies
|
||||
// and substantial portions of the software.
|
||||
const std = @import("std");
|
||||
const windows = std.os.windows;
|
||||
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,
|
||||
|
||||
/// Whether the terminal supports ANSI escape codes.
|
||||
supports_ansi_escape_codes: bool = false,
|
||||
|
||||
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.ns_per_ms,
|
||||
|
||||
/// How many nanoseconds to keep the output hidden
|
||||
initial_delay_ns: u64 = 500 * std.time.ns_per_ms,
|
||||
|
||||
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 {
|
||||
const stderr = std.io.getStdErr();
|
||||
self.terminal = null;
|
||||
if (stderr.supportsAnsiEscapeCodes()) {
|
||||
self.terminal = stderr;
|
||||
self.supports_ansi_escape_codes = true;
|
||||
} else if (std.builtin.os.tag == .windows and stderr.isTty()) {
|
||||
self.terminal = stderr;
|
||||
}
|
||||
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 the cursor position by moving the cursor
|
||||
// `columns_written` cells to the left, then clear the rest of the
|
||||
// line
|
||||
if (self.supports_ansi_escape_codes) {
|
||||
end += (std.fmt.bufPrint(self.output_buffer[end..], "\x1b[{d}D", .{self.columns_written}) catch unreachable).len;
|
||||
end += (std.fmt.bufPrint(self.output_buffer[end..], "\x1b[0K", .{}) catch unreachable).len;
|
||||
} else if (std.builtin.os.tag == .windows) winapi: {
|
||||
var info: windows.CONSOLE_SCREEN_BUFFER_INFO = undefined;
|
||||
if (windows.kernel32.GetConsoleScreenBufferInfo(file.handle, &info) != windows.TRUE)
|
||||
unreachable;
|
||||
|
||||
var cursor_pos = windows.COORD{
|
||||
.X = info.dwCursorPosition.X - @intCast(windows.SHORT, self.columns_written),
|
||||
.Y = info.dwCursorPosition.Y,
|
||||
};
|
||||
|
||||
if (cursor_pos.X < 0)
|
||||
cursor_pos.X = 0;
|
||||
|
||||
const fill_chars = @intCast(windows.DWORD, info.dwSize.X - cursor_pos.X);
|
||||
|
||||
var written: windows.DWORD = undefined;
|
||||
if (windows.kernel32.FillConsoleOutputAttribute(
|
||||
file.handle,
|
||||
info.wAttributes,
|
||||
fill_chars,
|
||||
cursor_pos,
|
||||
&written,
|
||||
) != windows.TRUE) {
|
||||
// Stop trying to write to this file.
|
||||
self.terminal = null;
|
||||
break :winapi;
|
||||
}
|
||||
if (windows.kernel32.FillConsoleOutputCharacterA(
|
||||
file.handle,
|
||||
' ',
|
||||
fill_chars,
|
||||
cursor_pos,
|
||||
&written,
|
||||
) != windows.TRUE) unreachable;
|
||||
|
||||
if (windows.kernel32.SetConsoleCursorPosition(file.handle, cursor_pos) != windows.TRUE)
|
||||
unreachable;
|
||||
} else unreachable;
|
||||
|
||||
self.columns_written = 0;
|
||||
}
|
||||
|
||||
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, "{s}", .{node.name});
|
||||
need_ellipse = true;
|
||||
}
|
||||
if (node.estimated_total_items) |total| {
|
||||
if (need_ellipse) self.bufWrite(&end, " ", .{});
|
||||
self.bufWrite(&end, "[{d}/{d}] ", .{ node.completed_items + 1, total });
|
||||
need_ellipse = false;
|
||||
} else if (node.completed_items != 0) {
|
||||
if (need_ellipse) self.bufWrite(&end, " ", .{});
|
||||
self.bufWrite(&end, "[{d}] ", .{node.completed_items + 1});
|
||||
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: anytype) void {
|
||||
const file = self.terminal orelse return;
|
||||
self.refresh();
|
||||
file.outStream().print(format, args) catch {
|
||||
self.terminal = null;
|
||||
return;
|
||||
};
|
||||
self.columns_written = 0;
|
||||
}
|
||||
|
||||
fn bufWrite(self: *Progress, end: *usize, comptime format: []const u8, args: anytype) 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.NoSpaceLeft => {
|
||||
self.columns_written += self.output_buffer.len - end.*;
|
||||
end.* = self.output_buffer.len;
|
||||
},
|
||||
}
|
||||
const bytes_needed_for_esc_codes_at_end = if (std.builtin.os.tag == .windows) 0 else 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.ns_per_ms);
|
||||
node.completeOne();
|
||||
node.completeOne();
|
||||
std.time.sleep(5 * std.time.ns_per_ms);
|
||||
node.completeOne();
|
||||
node.completeOne();
|
||||
std.time.sleep(5 * std.time.ns_per_ms);
|
||||
|
||||
node.end();
|
||||
|
||||
std.time.sleep(5 * std.time.ns_per_ms);
|
||||
}
|
||||
{
|
||||
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.ns_per_ms);
|
||||
progress.refresh();
|
||||
std.time.sleep(10 * std.time.ns_per_ms);
|
||||
node.end();
|
||||
}
|
||||
}
|
||||
@ -481,9 +481,8 @@ fn genBinOp(ctx: *Context, file: *C, inst: *Inst.BinOp, operator: []const u8) !?
|
||||
const rhs = try ctx.resolveInst(inst.rhs);
|
||||
const writer = file.main.writer();
|
||||
const name = try ctx.name();
|
||||
try writer.writeAll(indentation ++ "const ");
|
||||
try renderType(ctx, writer, inst.base.ty);
|
||||
try writer.print(" {s} = {s} " ++ operator ++ " {s};\n", .{ name, lhs, rhs });
|
||||
try renderTypeAndName(ctx, writer, inst.base.ty, name, .Const);
|
||||
try writer.print(" = {s} {s} {s};\n", .{ lhs, operator, rhs });
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
@ -1,125 +0,0 @@
|
||||
const std = @import("std");
|
||||
const Allocator = std.mem.Allocator;
|
||||
|
||||
pub fn targetTriple(allocator: *Allocator, target: std.Target) ![]u8 {
|
||||
const llvm_arch = switch (target.cpu.arch) {
|
||||
.arm => "arm",
|
||||
.armeb => "armeb",
|
||||
.aarch64 => "aarch64",
|
||||
.aarch64_be => "aarch64_be",
|
||||
.aarch64_32 => "aarch64_32",
|
||||
.arc => "arc",
|
||||
.avr => "avr",
|
||||
.bpfel => "bpfel",
|
||||
.bpfeb => "bpfeb",
|
||||
.hexagon => "hexagon",
|
||||
.mips => "mips",
|
||||
.mipsel => "mipsel",
|
||||
.mips64 => "mips64",
|
||||
.mips64el => "mips64el",
|
||||
.msp430 => "msp430",
|
||||
.powerpc => "powerpc",
|
||||
.powerpc64 => "powerpc64",
|
||||
.powerpc64le => "powerpc64le",
|
||||
.r600 => "r600",
|
||||
.amdgcn => "amdgcn",
|
||||
.riscv32 => "riscv32",
|
||||
.riscv64 => "riscv64",
|
||||
.sparc => "sparc",
|
||||
.sparcv9 => "sparcv9",
|
||||
.sparcel => "sparcel",
|
||||
.s390x => "s390x",
|
||||
.tce => "tce",
|
||||
.tcele => "tcele",
|
||||
.thumb => "thumb",
|
||||
.thumbeb => "thumbeb",
|
||||
.i386 => "i386",
|
||||
.x86_64 => "x86_64",
|
||||
.xcore => "xcore",
|
||||
.nvptx => "nvptx",
|
||||
.nvptx64 => "nvptx64",
|
||||
.le32 => "le32",
|
||||
.le64 => "le64",
|
||||
.amdil => "amdil",
|
||||
.amdil64 => "amdil64",
|
||||
.hsail => "hsail",
|
||||
.hsail64 => "hsail64",
|
||||
.spir => "spir",
|
||||
.spir64 => "spir64",
|
||||
.kalimba => "kalimba",
|
||||
.shave => "shave",
|
||||
.lanai => "lanai",
|
||||
.wasm32 => "wasm32",
|
||||
.wasm64 => "wasm64",
|
||||
.renderscript32 => "renderscript32",
|
||||
.renderscript64 => "renderscript64",
|
||||
.ve => "ve",
|
||||
.spu_2 => return error.LLVMBackendDoesNotSupportSPUMarkII,
|
||||
};
|
||||
// TODO Add a sub-arch for some architectures depending on CPU features.
|
||||
|
||||
const llvm_os = switch (target.os.tag) {
|
||||
.freestanding => "unknown",
|
||||
.ananas => "ananas",
|
||||
.cloudabi => "cloudabi",
|
||||
.dragonfly => "dragonfly",
|
||||
.freebsd => "freebsd",
|
||||
.fuchsia => "fuchsia",
|
||||
.ios => "ios",
|
||||
.kfreebsd => "kfreebsd",
|
||||
.linux => "linux",
|
||||
.lv2 => "lv2",
|
||||
.macos => "macosx",
|
||||
.netbsd => "netbsd",
|
||||
.openbsd => "openbsd",
|
||||
.solaris => "solaris",
|
||||
.windows => "windows",
|
||||
.haiku => "haiku",
|
||||
.minix => "minix",
|
||||
.rtems => "rtems",
|
||||
.nacl => "nacl",
|
||||
.cnk => "cnk",
|
||||
.aix => "aix",
|
||||
.cuda => "cuda",
|
||||
.nvcl => "nvcl",
|
||||
.amdhsa => "amdhsa",
|
||||
.ps4 => "ps4",
|
||||
.elfiamcu => "elfiamcu",
|
||||
.tvos => "tvos",
|
||||
.watchos => "watchos",
|
||||
.mesa3d => "mesa3d",
|
||||
.contiki => "contiki",
|
||||
.amdpal => "amdpal",
|
||||
.hermit => "hermit",
|
||||
.hurd => "hurd",
|
||||
.wasi => "wasi",
|
||||
.emscripten => "emscripten",
|
||||
.uefi => "windows",
|
||||
.other => "unknown",
|
||||
};
|
||||
|
||||
const llvm_abi = switch (target.abi) {
|
||||
.none => "unknown",
|
||||
.gnu => "gnu",
|
||||
.gnuabin32 => "gnuabin32",
|
||||
.gnuabi64 => "gnuabi64",
|
||||
.gnueabi => "gnueabi",
|
||||
.gnueabihf => "gnueabihf",
|
||||
.gnux32 => "gnux32",
|
||||
.code16 => "code16",
|
||||
.eabi => "eabi",
|
||||
.eabihf => "eabihf",
|
||||
.android => "android",
|
||||
.musl => "musl",
|
||||
.musleabi => "musleabi",
|
||||
.musleabihf => "musleabihf",
|
||||
.msvc => "msvc",
|
||||
.itanium => "itanium",
|
||||
.cygnus => "cygnus",
|
||||
.coreclr => "coreclr",
|
||||
.simulator => "simulator",
|
||||
.macabi => "macabi",
|
||||
};
|
||||
|
||||
return std.fmt.allocPrint(allocator, "{s}-unknown-{s}-{s}", .{ llvm_arch, llvm_os, llvm_abi });
|
||||
}
|
||||
@ -111,9 +111,6 @@ pub fn flushModule(self: *C, comp: *Compilation) !void {
|
||||
if (self.header.buf.items.len > 0) {
|
||||
try writer.writeByte('\n');
|
||||
}
|
||||
if (self.header.items.len > 0) {
|
||||
try writer.print("{s}\n", .{self.header.items});
|
||||
}
|
||||
if (self.constants.items.len > 0) {
|
||||
try writer.print("{s}\n", .{self.constants.items});
|
||||
}
|
||||
|
||||
@ -132,7 +132,7 @@ pub fn targetTriple(allocator: *Allocator, target: std.Target) ![:0]u8 {
|
||||
.macabi => "macabi",
|
||||
};
|
||||
|
||||
return std.fmt.allocPrintZ(allocator, "{}-unknown-{}-{}", .{ llvm_arch, llvm_os, llvm_abi });
|
||||
return std.fmt.allocPrintZ(allocator, "{s}-unknown-{s}-{s}", .{ llvm_arch, llvm_os, llvm_abi });
|
||||
}
|
||||
|
||||
pub const LLVMIRModule = struct {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user