clean up some self-hosted bitrot + don't assume libstdc++

closes #4682

The self-hosted compiler is still bit rotted and still not compiling
successfully yet. I have a more serious rework of the code in a
different branch.
This commit is contained in:
Andrew Kelley 2020-03-17 23:03:45 -04:00
parent 7251eb1681
commit dbde5df568
No known key found for this signature in database
GPG Key ID: 7C5F548F728501A9
9 changed files with 158 additions and 139 deletions

View File

@ -298,10 +298,14 @@ fn configureStage2(b: *Builder, exe: var, ctx: Context) !void {
dependOnLib(b, exe, ctx.llvm); dependOnLib(b, exe, ctx.llvm);
if (exe.target.getOsTag() == .linux) { if (exe.target.getOsTag() == .linux) {
try addCxxKnownPath(b, ctx, exe, "libstdc++.a", // First we try to static link against gcc libstdc++. If that doesn't work,
\\Unable to determine path to libstdc++.a // we fall back to -lc++ and cross our fingers.
\\On Fedora, install libstdc++-static and try again. addCxxKnownPath(b, ctx, exe, "libstdc++.a", "") catch |err| switch (err) {
); error.RequiredLibraryNotFound => {
exe.linkSystemLibrary("c++");
},
else => |e| return e,
};
exe.linkSystemLibrary("pthread"); exe.linkSystemLibrary("pthread");
} else if (exe.target.isFreeBSD()) { } else if (exe.target.isFreeBSD()) {
@ -320,7 +324,7 @@ fn configureStage2(b: *Builder, exe: var, ctx: Context) !void {
// System compiler, not gcc. // System compiler, not gcc.
exe.linkSystemLibrary("c++"); exe.linkSystemLibrary("c++");
}, },
else => return err, else => |e| return e,
} }
} }

View File

@ -520,13 +520,13 @@ pub const Int = struct {
comptime fmt: []const u8, comptime fmt: []const u8,
options: std.fmt.FormatOptions, options: std.fmt.FormatOptions,
out_stream: var, out_stream: var,
) FmtError!void { ) !void {
self.assertWritable(); self.assertWritable();
// TODO look at fmt and support other bases // TODO look at fmt and support other bases
// TODO support read-only fixed integers // TODO support read-only fixed integers
const str = self.toString(self.allocator.?, 10) catch @panic("TODO make this non allocating"); const str = self.toString(self.allocator.?, 10) catch @panic("TODO make this non allocating");
defer self.allocator.?.free(str); defer self.allocator.?.free(str);
return out_stream.print(str); return out_stream.writeAll(str);
} }
/// Returns -1, 0, 1 if |a| < |b|, |a| == |b| or |a| > |b| respectively. /// Returns -1, 0, 1 if |a| < |b|, |a| == |b| or |a| > |b| respectively.

View File

@ -69,9 +69,9 @@ pub const CInt = struct {
}; };
pub fn sizeInBits(cint: CInt, self: Target) u32 { pub fn sizeInBits(cint: CInt, self: Target) u32 {
const arch = self.getArch(); const arch = self.cpu.arch;
switch (self.os.tag) { switch (self.os.tag) {
.freestanding, .other => switch (self.getArch()) { .freestanding, .other => switch (self.cpu.arch) {
.msp430 => switch (cint.id) { .msp430 => switch (cint.id) {
.Short, .Short,
.UShort, .UShort,
@ -94,7 +94,7 @@ pub const CInt = struct {
=> return 32, => return 32,
.Long, .Long,
.ULong, .ULong,
=> return self.getArchPtrBitWidth(), => return self.cpu.arch.ptrBitWidth(),
.LongLong, .LongLong,
.ULongLong, .ULongLong,
=> return 64, => return 64,
@ -114,7 +114,7 @@ pub const CInt = struct {
=> return 32, => return 32,
.Long, .Long,
.ULong, .ULong,
=> return self.getArchPtrBitWidth(), => return self.cpu.arch.ptrBitWidth(),
.LongLong, .LongLong,
.ULongLong, .ULongLong,
=> return 64, => return 64,

View File

@ -95,7 +95,7 @@ pub const ZigCompiler = struct {
pub fn getNativeLibC(self: *ZigCompiler) !*LibCInstallation { pub fn getNativeLibC(self: *ZigCompiler) !*LibCInstallation {
if (self.native_libc.start()) |ptr| return ptr; if (self.native_libc.start()) |ptr| return ptr;
try self.native_libc.data.findNative(self.allocator); self.native_libc.data = try LibCInstallation.findNative(.{ .allocator = self.allocator });
self.native_libc.resolve(); self.native_libc.resolve();
return &self.native_libc.data; return &self.native_libc.data;
} }
@ -126,7 +126,7 @@ pub const Compilation = struct {
name: Buffer, name: Buffer,
llvm_triple: Buffer, llvm_triple: Buffer,
root_src_path: ?[]const u8, root_src_path: ?[]const u8,
target: Target, target: std.Target,
llvm_target: *llvm.Target, llvm_target: *llvm.Target,
build_mode: builtin.Mode, build_mode: builtin.Mode,
zig_lib_dir: []const u8, zig_lib_dir: []const u8,
@ -338,7 +338,7 @@ pub const Compilation = struct {
zig_compiler: *ZigCompiler, zig_compiler: *ZigCompiler,
name: []const u8, name: []const u8,
root_src_path: ?[]const u8, root_src_path: ?[]const u8,
target: Target, target: std.zig.CrossTarget,
kind: Kind, kind: Kind,
build_mode: builtin.Mode, build_mode: builtin.Mode,
is_static: bool, is_static: bool,
@ -370,13 +370,18 @@ pub const Compilation = struct {
zig_compiler: *ZigCompiler, zig_compiler: *ZigCompiler,
name: []const u8, name: []const u8,
root_src_path: ?[]const u8, root_src_path: ?[]const u8,
target: Target, cross_target: std.zig.CrossTarget,
kind: Kind, kind: Kind,
build_mode: builtin.Mode, build_mode: builtin.Mode,
is_static: bool, is_static: bool,
zig_lib_dir: []const u8, zig_lib_dir: []const u8,
) !void { ) !void {
const allocator = zig_compiler.allocator; const allocator = zig_compiler.allocator;
// TODO merge this line with stage2.zig crossTargetToTarget
const target_info = try std.zig.system.NativeTargetInfo.detect(std.heap.c_allocator, cross_target);
const target = target_info.target;
var comp = Compilation{ var comp = Compilation{
.arena_allocator = std.heap.ArenaAllocator.init(allocator), .arena_allocator = std.heap.ArenaAllocator.init(allocator),
.zig_compiler = zig_compiler, .zig_compiler = zig_compiler,
@ -419,7 +424,7 @@ pub const Compilation = struct {
.target_machine = undefined, .target_machine = undefined,
.target_data_ref = undefined, .target_data_ref = undefined,
.target_layout_str = undefined, .target_layout_str = undefined,
.target_ptr_bits = target.getArchPtrBitWidth(), .target_ptr_bits = target.cpu.arch.ptrBitWidth(),
.root_package = undefined, .root_package = undefined,
.std_package = undefined, .std_package = undefined,
@ -440,7 +445,7 @@ pub const Compilation = struct {
} }
comp.name = try Buffer.init(comp.arena(), name); comp.name = try Buffer.init(comp.arena(), name);
comp.llvm_triple = try util.getTriple(comp.arena(), target); comp.llvm_triple = try util.getLLVMTriple(comp.arena(), target);
comp.llvm_target = try util.llvmTargetFromTriple(comp.llvm_triple); comp.llvm_target = try util.llvmTargetFromTriple(comp.llvm_triple);
comp.zig_std_dir = try fs.path.join(comp.arena(), &[_][]const u8{ zig_lib_dir, "std" }); comp.zig_std_dir = try fs.path.join(comp.arena(), &[_][]const u8{ zig_lib_dir, "std" });
@ -451,17 +456,12 @@ pub const Compilation = struct {
const reloc_mode = if (is_static) llvm.RelocStatic else llvm.RelocPIC; const reloc_mode = if (is_static) llvm.RelocStatic else llvm.RelocPIC;
// LLVM creates invalid binaries on Windows sometimes.
// See https://github.com/ziglang/zig/issues/508
// As a workaround we do not use target native features on Windows.
var target_specific_cpu_args: ?[*:0]u8 = null; var target_specific_cpu_args: ?[*:0]u8 = null;
var target_specific_cpu_features: ?[*:0]u8 = null; var target_specific_cpu_features: ?[*:0]u8 = null;
defer llvm.DisposeMessage(target_specific_cpu_args); defer llvm.DisposeMessage(target_specific_cpu_args);
defer llvm.DisposeMessage(target_specific_cpu_features); defer llvm.DisposeMessage(target_specific_cpu_features);
if (target == Target.Native and !target.isWindows()) {
target_specific_cpu_args = llvm.GetHostCPUName() orelse return error.OutOfMemory; // TODO detect native CPU & features here
target_specific_cpu_features = llvm.GetNativeFeatures() orelse return error.OutOfMemory;
}
comp.target_machine = llvm.CreateTargetMachine( comp.target_machine = llvm.CreateTargetMachine(
comp.llvm_target, comp.llvm_target,
@ -1125,7 +1125,9 @@ pub const Compilation = struct {
self.libc_link_lib = link_lib; self.libc_link_lib = link_lib;
// get a head start on looking for the native libc // get a head start on looking for the native libc
if (self.target == Target.Native and self.override_libc == null) { // TODO this is missing a bunch of logic related to whether the target is native
// and whether we can build libc
if (self.override_libc == null) {
try self.deinit_group.call(startFindingNativeLibC, .{self}); try self.deinit_group.call(startFindingNativeLibC, .{self});
} }
} }

View File

@ -164,8 +164,7 @@ pub const Msg = struct {
const realpath_copy = try mem.dupe(comp.gpa(), u8, tree_scope.root().realpath); const realpath_copy = try mem.dupe(comp.gpa(), u8, tree_scope.root().realpath);
errdefer comp.gpa().free(realpath_copy); errdefer comp.gpa().free(realpath_copy);
var out_stream = &std.io.BufferOutStream.init(&text_buf).stream; try parse_error.render(&tree_scope.tree.tokens, text_buf.outStream());
try parse_error.render(&tree_scope.tree.tokens, out_stream);
const msg = try comp.gpa().create(Msg); const msg = try comp.gpa().create(Msg);
msg.* = Msg{ msg.* = Msg{
@ -204,8 +203,7 @@ pub const Msg = struct {
const realpath_copy = try mem.dupe(allocator, u8, realpath); const realpath_copy = try mem.dupe(allocator, u8, realpath);
errdefer allocator.free(realpath_copy); errdefer allocator.free(realpath_copy);
var out_stream = &std.io.BufferOutStream.init(&text_buf).stream; try parse_error.render(&tree.tokens, text_buf.outStream());
try parse_error.render(&tree.tokens, out_stream);
const msg = try allocator.create(Msg); const msg = try allocator.create(Msg);
msg.* = Msg{ msg.* = Msg{
@ -272,7 +270,7 @@ pub const Msg = struct {
}); });
try stream.writeByteNTimes(' ', start_loc.column); try stream.writeByteNTimes(' ', start_loc.column);
try stream.writeByteNTimes('~', last_token.end - first_token.start); try stream.writeByteNTimes('~', last_token.end - first_token.start);
try stream.write("\n"); try stream.writeAll("\n");
} }
pub fn printToFile(msg: *const Msg, file: fs.File, color: Color) !void { pub fn printToFile(msg: *const Msg, file: fs.File, color: Color) !void {
@ -281,7 +279,6 @@ pub const Msg = struct {
.On => true, .On => true,
.Off => false, .Off => false,
}; };
var stream = &file.outStream().stream; return msg.printToStream(file.outStream(), color_on);
return msg.printToStream(stream, color_on);
} }
}; };

View File

@ -1099,7 +1099,6 @@ pub const Builder = struct {
.Await => return error.Unimplemented, .Await => return error.Unimplemented,
.BitNot => return error.Unimplemented, .BitNot => return error.Unimplemented,
.BoolNot => return error.Unimplemented, .BoolNot => return error.Unimplemented,
.Cancel => return error.Unimplemented,
.OptionalType => return error.Unimplemented, .OptionalType => return error.Unimplemented,
.Negation => return error.Unimplemented, .Negation => return error.Unimplemented,
.NegationWrap => return error.Unimplemented, .NegationWrap => return error.Unimplemented,
@ -1188,6 +1187,7 @@ pub const Builder = struct {
.ParamDecl => return error.Unimplemented, .ParamDecl => return error.Unimplemented,
.FieldInitializer => return error.Unimplemented, .FieldInitializer => return error.Unimplemented,
.EnumLiteral => return error.Unimplemented, .EnumLiteral => return error.Unimplemented,
.Noasync => return error.Unimplemented,
} }
} }

View File

@ -56,12 +56,13 @@ pub fn link(comp: *Compilation) !void {
if (comp.haveLibC()) { if (comp.haveLibC()) {
// TODO https://github.com/ziglang/zig/issues/3190 // TODO https://github.com/ziglang/zig/issues/3190
var libc = ctx.comp.override_libc orelse blk: { var libc = ctx.comp.override_libc orelse blk: {
switch (comp.target) { @panic("this code has bitrotted");
Target.Native => { //switch (comp.target) {
break :blk comp.zig_compiler.getNativeLibC() catch return error.LibCRequiredButNotProvidedOrFound; // Target.Native => {
}, // break :blk comp.zig_compiler.getNativeLibC() catch return error.LibCRequiredButNotProvidedOrFound;
else => return error.LibCRequiredButNotProvidedOrFound, // },
} // else => return error.LibCRequiredButNotProvidedOrFound,
//}
}; };
ctx.libc = libc; ctx.libc = libc;
} }
@ -155,11 +156,11 @@ fn constructLinkerArgsElf(ctx: *Context) !void {
//bool shared = !g->is_static && is_lib; //bool shared = !g->is_static && is_lib;
//Buf *soname = nullptr; //Buf *soname = nullptr;
if (ctx.comp.is_static) { if (ctx.comp.is_static) {
if (util.isArmOrThumb(ctx.comp.target)) { //if (util.isArmOrThumb(ctx.comp.target)) {
try ctx.args.append("-Bstatic"); // try ctx.args.append("-Bstatic");
} else { //} else {
try ctx.args.append("-static"); // try ctx.args.append("-static");
} //}
} }
//} else if (shared) { //} else if (shared) {
// lj->args.append("-shared"); // lj->args.append("-shared");
@ -176,29 +177,24 @@ fn constructLinkerArgsElf(ctx: *Context) !void {
if (ctx.link_in_crt) { if (ctx.link_in_crt) {
const crt1o = if (ctx.comp.is_static) "crt1.o" else "Scrt1.o"; const crt1o = if (ctx.comp.is_static) "crt1.o" else "Scrt1.o";
const crtbegino = if (ctx.comp.is_static) "crtbeginT.o" else "crtbegin.o"; try addPathJoin(ctx, ctx.libc.crt_dir.?, crt1o);
try addPathJoin(ctx, ctx.libc.lib_dir.?, crt1o); try addPathJoin(ctx, ctx.libc.crt_dir.?, "crti.o");
try addPathJoin(ctx, ctx.libc.lib_dir.?, "crti.o");
try addPathJoin(ctx, ctx.libc.static_lib_dir.?, crtbegino);
} }
if (ctx.comp.haveLibC()) { if (ctx.comp.haveLibC()) {
try ctx.args.append("-L"); try ctx.args.append("-L");
// TODO addNullByte should probably return [:0]u8 // TODO addNullByte should probably return [:0]u8
try ctx.args.append(@ptrCast([*:0]const u8, (try std.cstr.addNullByte(&ctx.arena.allocator, ctx.libc.lib_dir.?)).ptr)); try ctx.args.append(@ptrCast([*:0]const u8, (try std.cstr.addNullByte(&ctx.arena.allocator, ctx.libc.crt_dir.?)).ptr));
try ctx.args.append("-L"); //if (!ctx.comp.is_static) {
try ctx.args.append(@ptrCast([*:0]const u8, (try std.cstr.addNullByte(&ctx.arena.allocator, ctx.libc.static_lib_dir.?)).ptr)); // const dl = blk: {
// //if (ctx.libc.dynamic_linker_path) |dl| break :blk dl;
if (!ctx.comp.is_static) { // //if (util.getDynamicLinkerPath(ctx.comp.target)) |dl| break :blk dl;
const dl = blk: { // return error.LibCMissingDynamicLinker;
if (ctx.libc.dynamic_linker_path) |dl| break :blk dl; // };
if (util.getDynamicLinkerPath(ctx.comp.target)) |dl| break :blk dl; // try ctx.args.append("-dynamic-linker");
return error.LibCMissingDynamicLinker; // try ctx.args.append(@ptrCast([*:0]const u8, (try std.cstr.addNullByte(&ctx.arena.allocator, dl)).ptr));
}; //}
try ctx.args.append("-dynamic-linker");
try ctx.args.append(@ptrCast([*:0]const u8, (try std.cstr.addNullByte(&ctx.arena.allocator, dl)).ptr));
}
} }
//if (shared) { //if (shared) {
@ -265,13 +261,12 @@ fn constructLinkerArgsElf(ctx: *Context) !void {
// crt end // crt end
if (ctx.link_in_crt) { if (ctx.link_in_crt) {
try addPathJoin(ctx, ctx.libc.static_lib_dir.?, "crtend.o"); try addPathJoin(ctx, ctx.libc.crt_dir.?, "crtn.o");
try addPathJoin(ctx, ctx.libc.lib_dir.?, "crtn.o");
} }
if (ctx.comp.target != Target.Native) { //if (ctx.comp.target != Target.Native) {
try ctx.args.append("--allow-shlib-undefined"); // try ctx.args.append("--allow-shlib-undefined");
} //}
} }
fn addPathJoin(ctx: *Context, dirname: []const u8, basename: []const u8) !void { fn addPathJoin(ctx: *Context, dirname: []const u8, basename: []const u8) !void {
@ -287,7 +282,7 @@ fn constructLinkerArgsCoff(ctx: *Context) !void {
try ctx.args.append("-DEBUG"); try ctx.args.append("-DEBUG");
} }
switch (ctx.comp.target.getArch()) { switch (ctx.comp.target.cpu.arch) {
.i386 => try ctx.args.append("-MACHINE:X86"), .i386 => try ctx.args.append("-MACHINE:X86"),
.x86_64 => try ctx.args.append("-MACHINE:X64"), .x86_64 => try ctx.args.append("-MACHINE:X64"),
.aarch64 => try ctx.args.append("-MACHINE:ARM"), .aarch64 => try ctx.args.append("-MACHINE:ARM"),
@ -302,7 +297,7 @@ fn constructLinkerArgsCoff(ctx: *Context) !void {
if (ctx.comp.haveLibC()) { if (ctx.comp.haveLibC()) {
try ctx.args.append(@ptrCast([*:0]const u8, (try std.fmt.allocPrint(&ctx.arena.allocator, "-LIBPATH:{}\x00", .{ctx.libc.msvc_lib_dir.?})).ptr)); try ctx.args.append(@ptrCast([*:0]const u8, (try std.fmt.allocPrint(&ctx.arena.allocator, "-LIBPATH:{}\x00", .{ctx.libc.msvc_lib_dir.?})).ptr));
try ctx.args.append(@ptrCast([*:0]const u8, (try std.fmt.allocPrint(&ctx.arena.allocator, "-LIBPATH:{}\x00", .{ctx.libc.kernel32_lib_dir.?})).ptr)); try ctx.args.append(@ptrCast([*:0]const u8, (try std.fmt.allocPrint(&ctx.arena.allocator, "-LIBPATH:{}\x00", .{ctx.libc.kernel32_lib_dir.?})).ptr));
try ctx.args.append(@ptrCast([*:0]const u8, (try std.fmt.allocPrint(&ctx.arena.allocator, "-LIBPATH:{}\x00", .{ctx.libc.lib_dir.?})).ptr)); try ctx.args.append(@ptrCast([*:0]const u8, (try std.fmt.allocPrint(&ctx.arena.allocator, "-LIBPATH:{}\x00", .{ctx.libc.crt_dir.?})).ptr));
} }
if (ctx.link_in_crt) { if (ctx.link_in_crt) {
@ -417,7 +412,7 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {
} }
}, },
.IPhoneOS => { .IPhoneOS => {
if (ctx.comp.target.getArch() == .aarch64) { if (ctx.comp.target.cpu.arch == .aarch64) {
// iOS does not need any crt1 files for arm64 // iOS does not need any crt1 files for arm64
} else if (platform.versionLessThan(3, 1)) { } else if (platform.versionLessThan(3, 1)) {
try ctx.args.append("-lcrt1.o"); try ctx.args.append("-lcrt1.o");
@ -435,28 +430,29 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {
} }
try addFnObjects(ctx); try addFnObjects(ctx);
if (ctx.comp.target == Target.Native) { // TODO
for (ctx.comp.link_libs_list.toSliceConst()) |lib| { //if (ctx.comp.target == Target.Native) {
if (mem.eql(u8, lib.name, "c")) { // for (ctx.comp.link_libs_list.toSliceConst()) |lib| {
// on Darwin, libSystem has libc in it, but also you have to use it // if (mem.eql(u8, lib.name, "c")) {
// to make syscalls because the syscall numbers are not documented // // on Darwin, libSystem has libc in it, but also you have to use it
// and change between versions. // // to make syscalls because the syscall numbers are not documented
// so we always link against libSystem // // and change between versions.
try ctx.args.append("-lSystem"); // // so we always link against libSystem
} else { // try ctx.args.append("-lSystem");
if (mem.indexOfScalar(u8, lib.name, '/') == null) { // } else {
const arg = try std.fmt.allocPrint(&ctx.arena.allocator, "-l{}\x00", .{lib.name}); // if (mem.indexOfScalar(u8, lib.name, '/') == null) {
try ctx.args.append(@ptrCast([*:0]const u8, arg.ptr)); // const arg = try std.fmt.allocPrint(&ctx.arena.allocator, "-l{}\x00", .{lib.name});
} else { // try ctx.args.append(@ptrCast([*:0]const u8, arg.ptr));
const arg = try std.cstr.addNullByte(&ctx.arena.allocator, lib.name); // } else {
try ctx.args.append(@ptrCast([*:0]const u8, arg.ptr)); // const arg = try std.cstr.addNullByte(&ctx.arena.allocator, lib.name);
} // try ctx.args.append(@ptrCast([*:0]const u8, arg.ptr));
} // }
} // }
} else { // }
try ctx.args.append("-undefined"); //} else {
try ctx.args.append("dynamic_lookup"); // try ctx.args.append("-undefined");
} // try ctx.args.append("dynamic_lookup");
//}
if (platform.kind == .MacOS) { if (platform.kind == .MacOS) {
if (platform.versionLessThan(10, 5)) { if (platform.versionLessThan(10, 5)) {

View File

@ -18,10 +18,6 @@ const Target = std.Target;
const errmsg = @import("errmsg.zig"); const errmsg = @import("errmsg.zig");
const LibCInstallation = @import("libc_installation.zig").LibCInstallation; const LibCInstallation = @import("libc_installation.zig").LibCInstallation;
var stderr_file: fs.File = undefined;
var stderr: *io.OutStream(fs.File.WriteError) = undefined;
var stdout: *io.OutStream(fs.File.WriteError) = undefined;
pub const io_mode = .evented; pub const io_mode = .evented;
pub const max_src_size = 2 * 1024 * 1024 * 1024; // 2 GiB pub const max_src_size = 2 * 1024 * 1024 * 1024; // 2 GiB
@ -51,17 +47,14 @@ const Command = struct {
pub fn main() !void { pub fn main() !void {
const allocator = std.heap.c_allocator; const allocator = std.heap.c_allocator;
stdout = &std.io.getStdOut().outStream().stream; const stderr = io.getStdErr().outStream();
stderr_file = std.io.getStdErr();
stderr = &stderr_file.outStream().stream;
const args = try process.argsAlloc(allocator); const args = try process.argsAlloc(allocator);
defer process.argsFree(allocator, args); defer process.argsFree(allocator, args);
if (args.len <= 1) { if (args.len <= 1) {
try stderr.write("expected command argument\n\n"); try stderr.writeAll("expected command argument\n\n");
try stderr.write(usage); try stderr.writeAll(usage);
process.exit(1); process.exit(1);
} }
@ -78,8 +71,8 @@ pub fn main() !void {
} else if (mem.eql(u8, cmd, "libc")) { } else if (mem.eql(u8, cmd, "libc")) {
return cmdLibC(allocator, cmd_args); return cmdLibC(allocator, cmd_args);
} else if (mem.eql(u8, cmd, "targets")) { } else if (mem.eql(u8, cmd, "targets")) {
const info = try std.zig.system.NativeTargetInfo.detect(allocator); const info = try std.zig.system.NativeTargetInfo.detect(allocator, .{});
defer info.deinit(allocator); const stdout = io.getStdOut().outStream();
return @import("print_targets.zig").cmdTargets(allocator, cmd_args, stdout, info.target); return @import("print_targets.zig").cmdTargets(allocator, cmd_args, stdout, info.target);
} else if (mem.eql(u8, cmd, "version")) { } else if (mem.eql(u8, cmd, "version")) {
return cmdVersion(allocator, cmd_args); return cmdVersion(allocator, cmd_args);
@ -91,7 +84,7 @@ pub fn main() !void {
return cmdInternal(allocator, cmd_args); return cmdInternal(allocator, cmd_args);
} else { } else {
try stderr.print("unknown command: {}\n\n", .{args[1]}); try stderr.print("unknown command: {}\n\n", .{args[1]});
try stderr.write(usage); try stderr.writeAll(usage);
process.exit(1); process.exit(1);
} }
} }
@ -156,6 +149,8 @@ const usage_build_generic =
; ;
fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Compilation.Kind) !void { fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Compilation.Kind) !void {
const stderr = io.getStdErr().outStream();
var color: errmsg.Color = .Auto; var color: errmsg.Color = .Auto;
var build_mode: std.builtin.Mode = .Debug; var build_mode: std.builtin.Mode = .Debug;
var emit_bin = true; var emit_bin = true;
@ -208,11 +203,11 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co
const arg = args[i]; const arg = args[i];
if (mem.startsWith(u8, arg, "-")) { if (mem.startsWith(u8, arg, "-")) {
if (mem.eql(u8, arg, "--help")) { if (mem.eql(u8, arg, "--help")) {
try stdout.write(usage_build_generic); try io.getStdOut().writeAll(usage_build_generic);
process.exit(0); process.exit(0);
} else if (mem.eql(u8, arg, "--color")) { } else if (mem.eql(u8, arg, "--color")) {
if (i + 1 >= args.len) { if (i + 1 >= args.len) {
try stderr.write("expected [auto|on|off] after --color\n"); try stderr.writeAll("expected [auto|on|off] after --color\n");
process.exit(1); process.exit(1);
} }
i += 1; i += 1;
@ -229,7 +224,7 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co
} }
} else if (mem.eql(u8, arg, "--mode")) { } else if (mem.eql(u8, arg, "--mode")) {
if (i + 1 >= args.len) { if (i + 1 >= args.len) {
try stderr.write("expected [Debug|ReleaseSafe|ReleaseFast|ReleaseSmall] after --mode\n"); try stderr.writeAll("expected [Debug|ReleaseSafe|ReleaseFast|ReleaseSmall] after --mode\n");
process.exit(1); process.exit(1);
} }
i += 1; i += 1;
@ -248,49 +243,49 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co
} }
} else if (mem.eql(u8, arg, "--name")) { } else if (mem.eql(u8, arg, "--name")) {
if (i + 1 >= args.len) { if (i + 1 >= args.len) {
try stderr.write("expected parameter after --name\n"); try stderr.writeAll("expected parameter after --name\n");
process.exit(1); process.exit(1);
} }
i += 1; i += 1;
provided_name = args[i]; provided_name = args[i];
} else if (mem.eql(u8, arg, "--ver-major")) { } else if (mem.eql(u8, arg, "--ver-major")) {
if (i + 1 >= args.len) { if (i + 1 >= args.len) {
try stderr.write("expected parameter after --ver-major\n"); try stderr.writeAll("expected parameter after --ver-major\n");
process.exit(1); process.exit(1);
} }
i += 1; i += 1;
version.major = try std.fmt.parseInt(u32, args[i], 10); version.major = try std.fmt.parseInt(u32, args[i], 10);
} else if (mem.eql(u8, arg, "--ver-minor")) { } else if (mem.eql(u8, arg, "--ver-minor")) {
if (i + 1 >= args.len) { if (i + 1 >= args.len) {
try stderr.write("expected parameter after --ver-minor\n"); try stderr.writeAll("expected parameter after --ver-minor\n");
process.exit(1); process.exit(1);
} }
i += 1; i += 1;
version.minor = try std.fmt.parseInt(u32, args[i], 10); version.minor = try std.fmt.parseInt(u32, args[i], 10);
} else if (mem.eql(u8, arg, "--ver-patch")) { } else if (mem.eql(u8, arg, "--ver-patch")) {
if (i + 1 >= args.len) { if (i + 1 >= args.len) {
try stderr.write("expected parameter after --ver-patch\n"); try stderr.writeAll("expected parameter after --ver-patch\n");
process.exit(1); process.exit(1);
} }
i += 1; i += 1;
version.patch = try std.fmt.parseInt(u32, args[i], 10); version.patch = try std.fmt.parseInt(u32, args[i], 10);
} else if (mem.eql(u8, arg, "--linker-script")) { } else if (mem.eql(u8, arg, "--linker-script")) {
if (i + 1 >= args.len) { if (i + 1 >= args.len) {
try stderr.write("expected parameter after --linker-script\n"); try stderr.writeAll("expected parameter after --linker-script\n");
process.exit(1); process.exit(1);
} }
i += 1; i += 1;
linker_script = args[i]; linker_script = args[i];
} else if (mem.eql(u8, arg, "--libc")) { } else if (mem.eql(u8, arg, "--libc")) {
if (i + 1 >= args.len) { if (i + 1 >= args.len) {
try stderr.write("expected parameter after --libc\n"); try stderr.writeAll("expected parameter after --libc\n");
process.exit(1); process.exit(1);
} }
i += 1; i += 1;
libc_arg = args[i]; libc_arg = args[i];
} else if (mem.eql(u8, arg, "-mllvm")) { } else if (mem.eql(u8, arg, "-mllvm")) {
if (i + 1 >= args.len) { if (i + 1 >= args.len) {
try stderr.write("expected parameter after -mllvm\n"); try stderr.writeAll("expected parameter after -mllvm\n");
process.exit(1); process.exit(1);
} }
i += 1; i += 1;
@ -300,14 +295,14 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co
try mllvm_flags.append(args[i]); try mllvm_flags.append(args[i]);
} else if (mem.eql(u8, arg, "-mmacosx-version-min")) { } else if (mem.eql(u8, arg, "-mmacosx-version-min")) {
if (i + 1 >= args.len) { if (i + 1 >= args.len) {
try stderr.write("expected parameter after -mmacosx-version-min\n"); try stderr.writeAll("expected parameter after -mmacosx-version-min\n");
process.exit(1); process.exit(1);
} }
i += 1; i += 1;
macosx_version_min = args[i]; macosx_version_min = args[i];
} else if (mem.eql(u8, arg, "-mios-version-min")) { } else if (mem.eql(u8, arg, "-mios-version-min")) {
if (i + 1 >= args.len) { if (i + 1 >= args.len) {
try stderr.write("expected parameter after -mios-version-min\n"); try stderr.writeAll("expected parameter after -mios-version-min\n");
process.exit(1); process.exit(1);
} }
i += 1; i += 1;
@ -348,7 +343,7 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co
linker_rdynamic = true; linker_rdynamic = true;
} else if (mem.eql(u8, arg, "--pkg-begin")) { } else if (mem.eql(u8, arg, "--pkg-begin")) {
if (i + 2 >= args.len) { if (i + 2 >= args.len) {
try stderr.write("expected [name] [path] after --pkg-begin\n"); try stderr.writeAll("expected [name] [path] after --pkg-begin\n");
process.exit(1); process.exit(1);
} }
i += 1; i += 1;
@ -363,7 +358,7 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co
if (cur_pkg.parent) |parent| { if (cur_pkg.parent) |parent| {
cur_pkg = parent; cur_pkg = parent;
} else { } else {
try stderr.write("encountered --pkg-end with no matching --pkg-begin\n"); try stderr.writeAll("encountered --pkg-end with no matching --pkg-begin\n");
process.exit(1); process.exit(1);
} }
} else if (mem.startsWith(u8, arg, "-l")) { } else if (mem.startsWith(u8, arg, "-l")) {
@ -411,18 +406,18 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co
var it = mem.separate(basename, "."); var it = mem.separate(basename, ".");
break :blk it.next() orelse basename; break :blk it.next() orelse basename;
} else { } else {
try stderr.write("--name [name] not provided and unable to infer\n"); try stderr.writeAll("--name [name] not provided and unable to infer\n");
process.exit(1); process.exit(1);
} }
}; };
if (root_src_file == null and link_objects.len == 0 and assembly_files.len == 0) { if (root_src_file == null and link_objects.len == 0 and assembly_files.len == 0) {
try stderr.write("Expected source file argument or at least one --object or --assembly argument\n"); try stderr.writeAll("Expected source file argument or at least one --object or --assembly argument\n");
process.exit(1); process.exit(1);
} }
if (out_type == Compilation.Kind.Obj and link_objects.len != 0) { if (out_type == Compilation.Kind.Obj and link_objects.len != 0) {
try stderr.write("When building an object file, --object arguments are invalid\n"); try stderr.writeAll("When building an object file, --object arguments are invalid\n");
process.exit(1); process.exit(1);
} }
@ -440,7 +435,7 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co
&zig_compiler, &zig_compiler,
root_name, root_name,
root_src_file, root_src_file,
Target.Native, .{},
out_type, out_type,
build_mode, build_mode,
!is_dynamic, !is_dynamic,
@ -478,7 +473,7 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co
comp.linker_rdynamic = linker_rdynamic; comp.linker_rdynamic = linker_rdynamic;
if (macosx_version_min != null and ios_version_min != null) { if (macosx_version_min != null and ios_version_min != null) {
try stderr.write("-mmacosx-version-min and -mios-version-min options not allowed together\n"); try stderr.writeAll("-mmacosx-version-min and -mios-version-min options not allowed together\n");
process.exit(1); process.exit(1);
} }
@ -501,6 +496,8 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co
} }
fn processBuildEvents(comp: *Compilation, color: errmsg.Color) void { fn processBuildEvents(comp: *Compilation, color: errmsg.Color) void {
const stderr_file = io.getStdErr();
const stderr = stderr_file.outStream();
var count: usize = 0; var count: usize = 0;
while (!comp.cancelled) { while (!comp.cancelled) {
const build_event = comp.events.get(); const build_event = comp.events.get();
@ -551,7 +548,8 @@ const Fmt = struct {
}; };
fn parseLibcPaths(allocator: *Allocator, libc: *LibCInstallation, libc_paths_file: []const u8) void { fn parseLibcPaths(allocator: *Allocator, libc: *LibCInstallation, libc_paths_file: []const u8) void {
libc.parse(allocator, libc_paths_file, stderr) catch |err| { const stderr = io.getStdErr().outStream();
libc.* = LibCInstallation.parse(allocator, libc_paths_file, stderr) catch |err| {
stderr.print("Unable to parse libc path file '{}': {}.\n" ++ stderr.print("Unable to parse libc path file '{}': {}.\n" ++
"Try running `zig libc` to see an example for the native target.\n", .{ "Try running `zig libc` to see an example for the native target.\n", .{
libc_paths_file, libc_paths_file,
@ -562,6 +560,7 @@ fn parseLibcPaths(allocator: *Allocator, libc: *LibCInstallation, libc_paths_fil
} }
fn cmdLibC(allocator: *Allocator, args: []const []const u8) !void { fn cmdLibC(allocator: *Allocator, args: []const []const u8) !void {
const stderr = io.getStdErr().outStream();
switch (args.len) { switch (args.len) {
0 => {}, 0 => {},
1 => { 1 => {
@ -582,10 +581,12 @@ fn cmdLibC(allocator: *Allocator, args: []const []const u8) !void {
stderr.print("unable to find libc: {}\n", .{@errorName(err)}) catch {}; stderr.print("unable to find libc: {}\n", .{@errorName(err)}) catch {};
process.exit(1); process.exit(1);
}; };
libc.render(stdout) catch process.exit(1); libc.render(io.getStdOut().outStream()) catch process.exit(1);
} }
fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void { fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void {
const stderr_file = io.getStdErr();
const stderr = stderr_file.outStream();
var color: errmsg.Color = .Auto; var color: errmsg.Color = .Auto;
var stdin_flag: bool = false; var stdin_flag: bool = false;
var check_flag: bool = false; var check_flag: bool = false;
@ -597,11 +598,12 @@ fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void {
const arg = args[i]; const arg = args[i];
if (mem.startsWith(u8, arg, "-")) { if (mem.startsWith(u8, arg, "-")) {
if (mem.eql(u8, arg, "--help")) { if (mem.eql(u8, arg, "--help")) {
try stdout.write(usage_fmt); const stdout = io.getStdOut().outStream();
try stdout.writeAll(usage_fmt);
process.exit(0); process.exit(0);
} else if (mem.eql(u8, arg, "--color")) { } else if (mem.eql(u8, arg, "--color")) {
if (i + 1 >= args.len) { if (i + 1 >= args.len) {
try stderr.write("expected [auto|on|off] after --color\n"); try stderr.writeAll("expected [auto|on|off] after --color\n");
process.exit(1); process.exit(1);
} }
i += 1; i += 1;
@ -632,14 +634,13 @@ fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void {
if (stdin_flag) { if (stdin_flag) {
if (input_files.len != 0) { if (input_files.len != 0) {
try stderr.write("cannot use --stdin with positional arguments\n"); try stderr.writeAll("cannot use --stdin with positional arguments\n");
process.exit(1); process.exit(1);
} }
var stdin_file = io.getStdIn(); const stdin = io.getStdIn().inStream();
var stdin = stdin_file.inStream();
const source_code = try stdin.stream.readAllAlloc(allocator, max_src_size); const source_code = try stdin.readAllAlloc(allocator, max_src_size);
defer allocator.free(source_code); defer allocator.free(source_code);
const tree = std.zig.parse(allocator, source_code) catch |err| { const tree = std.zig.parse(allocator, source_code) catch |err| {
@ -653,7 +654,7 @@ fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void {
const msg = try errmsg.Msg.createFromParseError(allocator, parse_error, tree, "<stdin>"); const msg = try errmsg.Msg.createFromParseError(allocator, parse_error, tree, "<stdin>");
defer msg.destroy(); defer msg.destroy();
try msg.printToFile(stderr_file, color); try msg.printToFile(io.getStdErr(), color);
} }
if (tree.errors.len != 0) { if (tree.errors.len != 0) {
process.exit(1); process.exit(1);
@ -664,12 +665,13 @@ fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void {
process.exit(code); process.exit(code);
} }
const stdout = io.getStdOut().outStream();
_ = try std.zig.render(allocator, stdout, tree); _ = try std.zig.render(allocator, stdout, tree);
return; return;
} }
if (input_files.len == 0) { if (input_files.len == 0) {
try stderr.write("expected at least one source file argument\n"); try stderr.writeAll("expected at least one source file argument\n");
process.exit(1); process.exit(1);
} }
@ -713,6 +715,9 @@ const FmtError = error{
} || fs.File.OpenError; } || fs.File.OpenError;
async fn fmtPath(fmt: *Fmt, file_path_ref: []const u8, check_mode: bool) FmtError!void { async fn fmtPath(fmt: *Fmt, file_path_ref: []const u8, check_mode: bool) FmtError!void {
const stderr_file = io.getStdErr();
const stderr = stderr_file.outStream();
const file_path = try std.mem.dupe(fmt.allocator, u8, file_path_ref); const file_path = try std.mem.dupe(fmt.allocator, u8, file_path_ref);
defer fmt.allocator.free(file_path); defer fmt.allocator.free(file_path);
@ -791,11 +796,13 @@ async fn fmtPath(fmt: *Fmt, file_path_ref: []const u8, check_mode: bool) FmtErro
} }
fn cmdVersion(allocator: *Allocator, args: []const []const u8) !void { fn cmdVersion(allocator: *Allocator, args: []const []const u8) !void {
const stdout = io.getStdOut().outStream();
try stdout.print("{}\n", .{c.ZIG_VERSION_STRING}); try stdout.print("{}\n", .{c.ZIG_VERSION_STRING});
} }
fn cmdHelp(allocator: *Allocator, args: []const []const u8) !void { fn cmdHelp(allocator: *Allocator, args: []const []const u8) !void {
try stdout.write(usage); const stdout = io.getStdOut();
try stdout.writeAll(usage);
} }
pub const info_zen = pub const info_zen =
@ -816,7 +823,7 @@ pub const info_zen =
; ;
fn cmdZen(allocator: *Allocator, args: []const []const u8) !void { fn cmdZen(allocator: *Allocator, args: []const []const u8) !void {
try stdout.write(info_zen); try io.getStdOut().writeAll(info_zen);
} }
const usage_internal = const usage_internal =
@ -829,8 +836,9 @@ const usage_internal =
; ;
fn cmdInternal(allocator: *Allocator, args: []const []const u8) !void { fn cmdInternal(allocator: *Allocator, args: []const []const u8) !void {
const stderr = io.getStdErr().outStream();
if (args.len == 0) { if (args.len == 0) {
try stderr.write(usage_internal); try stderr.writeAll(usage_internal);
process.exit(1); process.exit(1);
} }
@ -849,10 +857,11 @@ fn cmdInternal(allocator: *Allocator, args: []const []const u8) !void {
} }
try stderr.print("unknown sub command: {}\n\n", .{args[0]}); try stderr.print("unknown sub command: {}\n\n", .{args[0]});
try stderr.write(usage_internal); try stderr.writeAll(usage_internal);
} }
fn cmdInternalBuildInfo(allocator: *Allocator, args: []const []const u8) !void { fn cmdInternalBuildInfo(allocator: *Allocator, args: []const []const u8) !void {
const stdout = io.getStdOut().outStream();
try stdout.print( try stdout.print(
\\ZIG_CMAKE_BINARY_DIR {} \\ZIG_CMAKE_BINARY_DIR {}
\\ZIG_CXX_COMPILER {} \\ZIG_CXX_COMPILER {}

View File

@ -3,8 +3,7 @@ const Target = std.Target;
const llvm = @import("llvm.zig"); const llvm = @import("llvm.zig");
pub fn getDarwinArchString(self: Target) [:0]const u8 { pub fn getDarwinArchString(self: Target) [:0]const u8 {
const arch = self.getArch(); switch (self.cpu.arch) {
switch (arch) {
.aarch64 => return "arm64", .aarch64 => return "arm64",
.thumb, .thumb,
.arm, .arm,
@ -34,3 +33,15 @@ pub fn initializeAllTargets() void {
llvm.InitializeAllAsmPrinters(); llvm.InitializeAllAsmPrinters();
llvm.InitializeAllAsmParsers(); llvm.InitializeAllAsmParsers();
} }
pub fn getLLVMTriple(allocator: *std.mem.Allocator, target: std.Target) !std.Buffer {
var result = try std.Buffer.initSize(allocator, 0);
errdefer result.deinit();
try result.outStream().print(
"{}-unknown-{}-{}",
.{ @tagName(target.cpu.arch), @tagName(target.os.tag), @tagName(target.abi) },
);
return result;
}