authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-02-25 01:52:27-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-02-28 14:51:53-05:00
log4616af0ca459358ffa09ba27f9daa8527a38fd35
tree2705847ded931e30dc924bd44acf24847743855c
parentfba39ff331a84f1a32d076ccbb8b87cd02ea7121
signaturelock-open Commit is signed but in an unrecognized format.

introduce operating system version ranges as part of the target

* re-introduce `std.build.Target` which is distinct from `std.Target`. `std.build.Target` wraps `std.Target` so that it can be annotated as "the native target" or an explicitly specified target. * `std.Target.Os` is moved to `std.Target.Os.Tag`. The former is now a struct which has the tag as well as version range information. * `std.elf` gains some more ELF header constants. * `std.Target.parse` gains the ability to parse operating system version ranges as well as glibc version. * Added `std.Target.isGnuLibC()`. * self-hosted dynamic linker detection and glibc version detection. This also adds the improved logic using `/usr/bin/env` rather than invoking the system C compiler to find the dynamic linker when zig is statically linked. Related: #2084 Note: this `/usr/bin/env` code is work-in-progress. * `-target-glibc` CLI option is removed in favor of the new `-target` syntax. Example: `-target x86_64-linux-gnu.2.27` closes #1907

59 files changed, 1275 insertions(+), 933 deletions(-)

lib/std/build.zig+33-7
...@@ -971,9 +971,9 @@ pub const Builder = struct {...@@ -971,9 +971,9 @@ pub const Builder = struct {
971};971};
972972
973test "builder.findProgram compiles" {973test "builder.findProgram compiles" {
974 // TODO: uncomment and fix the leak974 var buf: [1000]u8 = undefined;
975 // const builder = try Builder.create(std.testing.allocator, "zig", "zig-cache", "zig-cache");975 var fba = std.heap.FixedBufferAllocator.init(&buf);
976 const builder = try Builder.create(std.heap.page_allocator, "zig", "zig-cache", "zig-cache");976 const builder = try Builder.create(&fba.allocator, "zig", "zig-cache", "zig-cache");
977 defer builder.destroy();977 defer builder.destroy();
978 _ = builder.findProgram(&[_][]const u8{}, &[_][]const u8{}) catch null;978 _ = builder.findProgram(&[_][]const u8{}, &[_][]const u8{}) catch null;
979}979}
...@@ -981,11 +981,37 @@ test "builder.findProgram compiles" {...@@ -981,11 +981,37 @@ test "builder.findProgram compiles" {
981/// Deprecated. Use `builtin.Version`.981/// Deprecated. Use `builtin.Version`.
982pub const Version = builtin.Version;982pub const Version = builtin.Version;
983983
984/// Deprecated. Use `std.Target.Cross`.
985pub const CrossTarget = std.Target.Cross;
986
987/// Deprecated. Use `std.Target`.984/// Deprecated. Use `std.Target`.
988pub const Target = std.Target;985pub const CrossTarget = std.Target;
986
987/// Wraps `std.Target` so that it can be annotated as "the native target" or an explicitly specified target.
988pub const Target = union(enum) {
989 Native,
990 Cross: std.Target,
991
992 pub fn getTarget(self: Target) std.Target {
993 return switch (self) {
994 .Native => std.Target.current,
995 .Cross => |t| t,
996 };
997 }
998
999 pub fn getOs(self: Target) std.Target.Os.Tag {
1000 return self.getTarget().os.tag;
1001 }
1002
1003 pub fn getCpu(self: Target) std.Target.Cpu {
1004 return self.getTarget().cpu;
1005 }
1006
1007 pub fn getAbi(self: Target) std.Target.Abi {
1008 return self.getTarget().abi;
1009 }
1010
1011 pub fn getArch(self: Target) std.Target.Cpu.Arch {
1012 return self.getCpu().arch;
1013 }
1014};
9891015
990pub const Pkg = struct {1016pub const Pkg = struct {
991 name: []const u8,1017 name: []const u8,
lib/std/build/run.zig+1-1
...@@ -82,7 +82,7 @@ pub const RunStep = struct {...@@ -82,7 +82,7 @@ pub const RunStep = struct {
8282
83 var key: []const u8 = undefined;83 var key: []const u8 = undefined;
84 var prev_path: ?[]const u8 = undefined;84 var prev_path: ?[]const u8 = undefined;
85 if (builtin.os == .windows) {85 if (builtin.os.tag == .windows) {
86 key = "Path";86 key = "Path";
87 prev_path = env_map.get(key);87 prev_path = env_map.get(key);
88 if (prev_path == null) {88 if (prev_path == null) {
lib/std/builtin.zig+2-2
...@@ -411,7 +411,7 @@ pub const Version = struct {...@@ -411,7 +411,7 @@ pub const Version = struct {
411 }411 }
412 };412 };
413413
414 pub fn order(lhs: Version, rhs: version) std.math.Order {414 pub fn order(lhs: Version, rhs: Version) std.math.Order {
415 if (lhs.major < rhs.major) return .lt;415 if (lhs.major < rhs.major) return .lt;
416 if (lhs.major > rhs.major) return .gt;416 if (lhs.major > rhs.major) return .gt;
417 if (lhs.minor < rhs.minor) return .lt;417 if (lhs.minor < rhs.minor) return .lt;
...@@ -504,7 +504,7 @@ pub fn default_panic(msg: []const u8, error_return_trace: ?*StackTrace) noreturn...@@ -504,7 +504,7 @@ pub fn default_panic(msg: []const u8, error_return_trace: ?*StackTrace) noreturn
504 root.os.panic(msg, error_return_trace);504 root.os.panic(msg, error_return_trace);
505 unreachable;505 unreachable;
506 }506 }
507 switch (os) {507 switch (os.tag) {
508 .freestanding => {508 .freestanding => {
509 while (true) {509 while (true) {
510 @breakpoint();510 @breakpoint();
lib/std/c.zig+12-13
...@@ -1,5 +1,5 @@...@@ -1,5 +1,5 @@
1const builtin = @import("builtin");
2const std = @import("std");1const std = @import("std");
2const builtin = std.builtin;
3const page_size = std.mem.page_size;3const page_size = std.mem.page_size;
44
5pub const tokenizer = @import("c/tokenizer.zig");5pub const tokenizer = @import("c/tokenizer.zig");
...@@ -10,7 +10,7 @@ pub const ast = @import("c/ast.zig");...@@ -10,7 +10,7 @@ pub const ast = @import("c/ast.zig");
1010
11pub usingnamespace @import("os/bits.zig");11pub usingnamespace @import("os/bits.zig");
1212
13pub usingnamespace switch (builtin.os) {13pub usingnamespace switch (std.Target.current.os.tag) {
14 .linux => @import("c/linux.zig"),14 .linux => @import("c/linux.zig"),
15 .windows => @import("c/windows.zig"),15 .windows => @import("c/windows.zig"),
16 .macosx, .ios, .tvos, .watchos => @import("c/darwin.zig"),16 .macosx, .ios, .tvos, .watchos => @import("c/darwin.zig"),
...@@ -46,17 +46,16 @@ pub fn versionCheck(glibc_version: builtin.Version) type {...@@ -46,17 +46,16 @@ pub fn versionCheck(glibc_version: builtin.Version) type {
46 return struct {46 return struct {
47 pub const ok = blk: {47 pub const ok = blk: {
48 if (!builtin.link_libc) break :blk false;48 if (!builtin.link_libc) break :blk false;
49 switch (builtin.abi) {49 if (std.Target.current.abi.isMusl()) break :blk true;
50 .musl, .musleabi, .musleabihf => break :blk true,50 if (std.Target.current.isGnuLibC()) {
51 .gnu, .gnuabin32, .gnuabi64, .gnueabi, .gnueabihf, .gnux32 => {51 const ver = std.Target.current.os.version_range.linux.glibc;
52 const ver = builtin.glibc_version orelse break :blk false;52 const order = ver.order(glibc_version);
53 if (ver.major < glibc_version.major) break :blk false;53 break :blk switch (order) {
54 if (ver.major > glibc_version.major) break :blk true;54 .gt, .eq => true,
55 if (ver.minor < glibc_version.minor) break :blk false;55 .lt => false,
56 if (ver.minor > glibc_version.minor) break :blk true;56 };
57 break :blk ver.patch >= glibc_version.patch;57 } else {
58 },58 break :blk false;
59 else => break :blk false,
60 }59 }
61 };60 };
62 };61 };
lib/std/c/linux.zig+1-1
...@@ -94,7 +94,7 @@ pub const pthread_cond_t = extern struct {...@@ -94,7 +94,7 @@ pub const pthread_cond_t = extern struct {
94 size: [__SIZEOF_PTHREAD_COND_T]u8 align(@alignOf(usize)) = [_]u8{0} ** __SIZEOF_PTHREAD_COND_T,94 size: [__SIZEOF_PTHREAD_COND_T]u8 align(@alignOf(usize)) = [_]u8{0} ** __SIZEOF_PTHREAD_COND_T,
95};95};
96const __SIZEOF_PTHREAD_COND_T = 48;96const __SIZEOF_PTHREAD_COND_T = 48;
97const __SIZEOF_PTHREAD_MUTEX_T = if (builtin.os == .fuchsia) 40 else switch (builtin.abi) {97const __SIZEOF_PTHREAD_MUTEX_T = if (builtin.os.tag == .fuchsia) 40 else switch (builtin.abi) {
98 .musl, .musleabi, .musleabihf => if (@sizeOf(usize) == 8) 40 else 24,98 .musl, .musleabi, .musleabihf => if (@sizeOf(usize) == 8) 40 else 24,
99 .gnu, .gnuabin32, .gnuabi64, .gnueabi, .gnueabihf, .gnux32 => switch (builtin.arch) {99 .gnu, .gnuabin32, .gnuabi64, .gnueabi, .gnueabihf, .gnux32 => switch (builtin.arch) {
100 .aarch64 => 48,100 .aarch64 => 48,
lib/std/child_process.zig+13-13
...@@ -17,9 +17,9 @@ const TailQueue = std.TailQueue;...@@ -17,9 +17,9 @@ const TailQueue = std.TailQueue;
17const maxInt = std.math.maxInt;17const maxInt = std.math.maxInt;
1818
19pub const ChildProcess = struct {19pub const ChildProcess = struct {
20 pid: if (builtin.os == .windows) void else i32,20 pid: if (builtin.os.tag == .windows) void else i32,
21 handle: if (builtin.os == .windows) windows.HANDLE else void,21 handle: if (builtin.os.tag == .windows) windows.HANDLE else void,
22 thread_handle: if (builtin.os == .windows) windows.HANDLE else void,22 thread_handle: if (builtin.os.tag == .windows) windows.HANDLE else void,
2323
24 allocator: *mem.Allocator,24 allocator: *mem.Allocator,
2525
...@@ -39,15 +39,15 @@ pub const ChildProcess = struct {...@@ -39,15 +39,15 @@ pub const ChildProcess = struct {
39 stderr_behavior: StdIo,39 stderr_behavior: StdIo,
4040
41 /// Set to change the user id when spawning the child process.41 /// Set to change the user id when spawning the child process.
42 uid: if (builtin.os == .windows) void else ?u32,42 uid: if (builtin.os.tag == .windows) void else ?u32,
4343
44 /// Set to change the group id when spawning the child process.44 /// Set to change the group id when spawning the child process.
45 gid: if (builtin.os == .windows) void else ?u32,45 gid: if (builtin.os.tag == .windows) void else ?u32,
4646
47 /// Set to change the current working directory when spawning the child process.47 /// Set to change the current working directory when spawning the child process.
48 cwd: ?[]const u8,48 cwd: ?[]const u8,
4949
50 err_pipe: if (builtin.os == .windows) void else [2]os.fd_t,50 err_pipe: if (builtin.os.tag == .windows) void else [2]os.fd_t,
5151
52 expand_arg0: Arg0Expand,52 expand_arg0: Arg0Expand,
5353
...@@ -96,8 +96,8 @@ pub const ChildProcess = struct {...@@ -96,8 +96,8 @@ pub const ChildProcess = struct {
96 .term = null,96 .term = null,
97 .env_map = null,97 .env_map = null,
98 .cwd = null,98 .cwd = null,
99 .uid = if (builtin.os == .windows) {} else null,99 .uid = if (builtin.os.tag == .windows) {} else null,
100 .gid = if (builtin.os == .windows) {} else null,100 .gid = if (builtin.os.tag == .windows) {} else null,
101 .stdin = null,101 .stdin = null,
102 .stdout = null,102 .stdout = null,
103 .stderr = null,103 .stderr = null,
...@@ -118,7 +118,7 @@ pub const ChildProcess = struct {...@@ -118,7 +118,7 @@ pub const ChildProcess = struct {
118118
119 /// On success must call `kill` or `wait`.119 /// On success must call `kill` or `wait`.
120 pub fn spawn(self: *ChildProcess) SpawnError!void {120 pub fn spawn(self: *ChildProcess) SpawnError!void {
121 if (builtin.os == .windows) {121 if (builtin.os.tag == .windows) {
122 return self.spawnWindows();122 return self.spawnWindows();
123 } else {123 } else {
124 return self.spawnPosix();124 return self.spawnPosix();
...@@ -132,7 +132,7 @@ pub const ChildProcess = struct {...@@ -132,7 +132,7 @@ pub const ChildProcess = struct {
132132
133 /// Forcibly terminates child process and then cleans up all resources.133 /// Forcibly terminates child process and then cleans up all resources.
134 pub fn kill(self: *ChildProcess) !Term {134 pub fn kill(self: *ChildProcess) !Term {
135 if (builtin.os == .windows) {135 if (builtin.os.tag == .windows) {
136 return self.killWindows(1);136 return self.killWindows(1);
137 } else {137 } else {
138 return self.killPosix();138 return self.killPosix();
...@@ -162,7 +162,7 @@ pub const ChildProcess = struct {...@@ -162,7 +162,7 @@ pub const ChildProcess = struct {
162162
163 /// Blocks until child process terminates and then cleans up all resources.163 /// Blocks until child process terminates and then cleans up all resources.
164 pub fn wait(self: *ChildProcess) !Term {164 pub fn wait(self: *ChildProcess) !Term {
165 if (builtin.os == .windows) {165 if (builtin.os.tag == .windows) {
166 return self.waitWindows();166 return self.waitWindows();
167 } else {167 } else {
168 return self.waitPosix();168 return self.waitPosix();
...@@ -307,7 +307,7 @@ pub const ChildProcess = struct {...@@ -307,7 +307,7 @@ pub const ChildProcess = struct {
307 fn cleanupAfterWait(self: *ChildProcess, status: u32) !Term {307 fn cleanupAfterWait(self: *ChildProcess, status: u32) !Term {
308 defer destroyPipe(self.err_pipe);308 defer destroyPipe(self.err_pipe);
309309
310 if (builtin.os == .linux) {310 if (builtin.os.tag == .linux) {
311 var fd = [1]std.os.pollfd{std.os.pollfd{311 var fd = [1]std.os.pollfd{std.os.pollfd{
312 .fd = self.err_pipe[0],312 .fd = self.err_pipe[0],
313 .events = std.os.POLLIN,313 .events = std.os.POLLIN,
...@@ -402,7 +402,7 @@ pub const ChildProcess = struct {...@@ -402,7 +402,7 @@ pub const ChildProcess = struct {
402 // This pipe is used to communicate errors between the time of fork402 // This pipe is used to communicate errors between the time of fork
403 // and execve from the child process to the parent process.403 // and execve from the child process to the parent process.
404 const err_pipe = blk: {404 const err_pipe = blk: {
405 if (builtin.os == .linux) {405 if (builtin.os.tag == .linux) {
406 const fd = try os.eventfd(0, 0);406 const fd = try os.eventfd(0, 0);
407 // There's no distinction between the readable and the writeable407 // There's no distinction between the readable and the writeable
408 // end with eventfd408 // end with eventfd
lib/std/cstr.zig+2-2
...@@ -4,8 +4,8 @@ const debug = std.debug;...@@ -4,8 +4,8 @@ const debug = std.debug;
4const mem = std.mem;4const mem = std.mem;
5const testing = std.testing;5const testing = std.testing;
66
7pub const line_sep = switch (builtin.os) {7pub const line_sep = switch (builtin.os.tag) {
8 builtin.Os.windows => "\r\n",8 .windows => "\r\n",
9 else => "\n",9 else => "\n",
10};10};
1111
lib/std/debug.zig+12-12
...@@ -1,4 +1,5 @@...@@ -1,4 +1,5 @@
1const std = @import("std.zig");1const std = @import("std.zig");
2const builtin = std.builtin;
2const math = std.math;3const math = std.math;
3const mem = std.mem;4const mem = std.mem;
4const io = std.io;5const io = std.io;
...@@ -11,7 +12,6 @@ const macho = std.macho;...@@ -11,7 +12,6 @@ const macho = std.macho;
11const coff = std.coff;12const coff = std.coff;
12const pdb = std.pdb;13const pdb = std.pdb;
13const ArrayList = std.ArrayList;14const ArrayList = std.ArrayList;
14const builtin = @import("builtin");
15const root = @import("root");15const root = @import("root");
16const maxInt = std.math.maxInt;16const maxInt = std.math.maxInt;
17const File = std.fs.File;17const File = std.fs.File;
...@@ -101,7 +101,7 @@ pub fn detectTTYConfig() TTY.Config {...@@ -101,7 +101,7 @@ pub fn detectTTYConfig() TTY.Config {
101 } else |_| {101 } else |_| {
102 if (stderr_file.supportsAnsiEscapeCodes()) {102 if (stderr_file.supportsAnsiEscapeCodes()) {
103 return .escape_codes;103 return .escape_codes;
104 } else if (builtin.os == .windows and stderr_file.isTty()) {104 } else if (builtin.os.tag == .windows and stderr_file.isTty()) {
105 return .windows_api;105 return .windows_api;
106 } else {106 } else {
107 return .no_color;107 return .no_color;
...@@ -155,7 +155,7 @@ pub fn dumpStackTraceFromBase(bp: usize, ip: usize) void {...@@ -155,7 +155,7 @@ pub fn dumpStackTraceFromBase(bp: usize, ip: usize) void {
155/// chopping off the irrelevant frames and shifting so that the returned addresses pointer155/// chopping off the irrelevant frames and shifting so that the returned addresses pointer
156/// equals the passed in addresses pointer.156/// equals the passed in addresses pointer.
157pub fn captureStackTrace(first_address: ?usize, stack_trace: *builtin.StackTrace) void {157pub fn captureStackTrace(first_address: ?usize, stack_trace: *builtin.StackTrace) void {
158 if (builtin.os == .windows) {158 if (builtin.os.tag == .windows) {
159 const addrs = stack_trace.instruction_addresses;159 const addrs = stack_trace.instruction_addresses;
160 const u32_addrs_len = @intCast(u32, addrs.len);160 const u32_addrs_len = @intCast(u32, addrs.len);
161 const first_addr = first_address orelse {161 const first_addr = first_address orelse {
...@@ -231,7 +231,7 @@ pub fn assert(ok: bool) void {...@@ -231,7 +231,7 @@ pub fn assert(ok: bool) void {
231pub fn panic(comptime format: []const u8, args: var) noreturn {231pub fn panic(comptime format: []const u8, args: var) noreturn {
232 @setCold(true);232 @setCold(true);
233 // TODO: remove conditional once wasi / LLVM defines __builtin_return_address233 // TODO: remove conditional once wasi / LLVM defines __builtin_return_address
234 const first_trace_addr = if (builtin.os == .wasi) null else @returnAddress();234 const first_trace_addr = if (builtin.os.tag == .wasi) null else @returnAddress();
235 panicExtra(null, first_trace_addr, format, args);235 panicExtra(null, first_trace_addr, format, args);
236}236}
237237
...@@ -361,7 +361,7 @@ pub fn writeCurrentStackTrace(...@@ -361,7 +361,7 @@ pub fn writeCurrentStackTrace(
361 tty_config: TTY.Config,361 tty_config: TTY.Config,
362 start_addr: ?usize,362 start_addr: ?usize,
363) !void {363) !void {
364 if (builtin.os == .windows) {364 if (builtin.os.tag == .windows) {
365 return writeCurrentStackTraceWindows(out_stream, debug_info, tty_config, start_addr);365 return writeCurrentStackTraceWindows(out_stream, debug_info, tty_config, start_addr);
366 }366 }
367 var it = StackIterator.init(start_addr, null);367 var it = StackIterator.init(start_addr, null);
...@@ -418,7 +418,7 @@ pub const TTY = struct {...@@ -418,7 +418,7 @@ pub const TTY = struct {
418 .Dim => noasync out_stream.write(DIM) catch return,418 .Dim => noasync out_stream.write(DIM) catch return,
419 .Reset => noasync out_stream.write(RESET) catch return,419 .Reset => noasync out_stream.write(RESET) catch return,
420 },420 },
421 .windows_api => if (builtin.os == .windows) {421 .windows_api => if (builtin.os.tag == .windows) {
422 const S = struct {422 const S = struct {
423 var attrs: windows.WORD = undefined;423 var attrs: windows.WORD = undefined;
424 var init_attrs = false;424 var init_attrs = false;
...@@ -617,7 +617,7 @@ pub fn openSelfDebugInfo(allocator: *mem.Allocator) anyerror!DebugInfo {...@@ -617,7 +617,7 @@ pub fn openSelfDebugInfo(allocator: *mem.Allocator) anyerror!DebugInfo {
617 if (@hasDecl(root, "os") and @hasDecl(root.os, "debug") and @hasDecl(root.os.debug, "openSelfDebugInfo")) {617 if (@hasDecl(root, "os") and @hasDecl(root.os, "debug") and @hasDecl(root.os.debug, "openSelfDebugInfo")) {
618 return noasync root.os.debug.openSelfDebugInfo(allocator);618 return noasync root.os.debug.openSelfDebugInfo(allocator);
619 }619 }
620 switch (builtin.os) {620 switch (builtin.os.tag) {
621 .linux,621 .linux,
622 .freebsd,622 .freebsd,
623 .macosx,623 .macosx,
...@@ -1019,7 +1019,7 @@ pub const DebugInfo = struct {...@@ -1019,7 +1019,7 @@ pub const DebugInfo = struct {
1019 pub fn getModuleForAddress(self: *DebugInfo, address: usize) !*ModuleDebugInfo {1019 pub fn getModuleForAddress(self: *DebugInfo, address: usize) !*ModuleDebugInfo {
1020 if (comptime std.Target.current.isDarwin())1020 if (comptime std.Target.current.isDarwin())
1021 return self.lookupModuleDyld(address)1021 return self.lookupModuleDyld(address)
1022 else if (builtin.os == .windows)1022 else if (builtin.os.tag == .windows)
1023 return self.lookupModuleWin32(address)1023 return self.lookupModuleWin32(address)
1024 else1024 else
1025 return self.lookupModuleDl(address);1025 return self.lookupModuleDl(address);
...@@ -1242,7 +1242,7 @@ const SymbolInfo = struct {...@@ -1242,7 +1242,7 @@ const SymbolInfo = struct {
1242 }1242 }
1243};1243};
12441244
1245pub const ModuleDebugInfo = switch (builtin.os) {1245pub const ModuleDebugInfo = switch (builtin.os.tag) {
1246 .macosx, .ios, .watchos, .tvos => struct {1246 .macosx, .ios, .watchos, .tvos => struct {
1247 base_address: usize,1247 base_address: usize,
1248 mapped_memory: []const u8,1248 mapped_memory: []const u8,
...@@ -1602,7 +1602,7 @@ fn getDebugInfoAllocator() *mem.Allocator {...@@ -1602,7 +1602,7 @@ fn getDebugInfoAllocator() *mem.Allocator {
1602}1602}
16031603
1604/// Whether or not the current target can print useful debug information when a segfault occurs.1604/// Whether or not the current target can print useful debug information when a segfault occurs.
1605pub const have_segfault_handling_support = builtin.os == .linux or builtin.os == .windows;1605pub const have_segfault_handling_support = builtin.os.tag == .linux or builtin.os.tag == .windows;
1606pub const enable_segfault_handler: bool = if (@hasDecl(root, "enable_segfault_handler"))1606pub const enable_segfault_handler: bool = if (@hasDecl(root, "enable_segfault_handler"))
1607 root.enable_segfault_handler1607 root.enable_segfault_handler
1608else1608else
...@@ -1621,7 +1621,7 @@ pub fn attachSegfaultHandler() void {...@@ -1621,7 +1621,7 @@ pub fn attachSegfaultHandler() void {
1621 if (!have_segfault_handling_support) {1621 if (!have_segfault_handling_support) {
1622 @compileError("segfault handler not supported for this target");1622 @compileError("segfault handler not supported for this target");
1623 }1623 }
1624 if (builtin.os == .windows) {1624 if (builtin.os.tag == .windows) {
1625 windows_segfault_handle = windows.kernel32.AddVectoredExceptionHandler(0, handleSegfaultWindows);1625 windows_segfault_handle = windows.kernel32.AddVectoredExceptionHandler(0, handleSegfaultWindows);
1626 return;1626 return;
1627 }1627 }
...@@ -1637,7 +1637,7 @@ pub fn attachSegfaultHandler() void {...@@ -1637,7 +1637,7 @@ pub fn attachSegfaultHandler() void {
1637}1637}
16381638
1639fn resetSegfaultHandler() void {1639fn resetSegfaultHandler() void {
1640 if (builtin.os == .windows) {1640 if (builtin.os.tag == .windows) {
1641 if (windows_segfault_handle) |handle| {1641 if (windows_segfault_handle) |handle| {
1642 assert(windows.kernel32.RemoveVectoredExceptionHandler(handle) != 0);1642 assert(windows.kernel32.RemoveVectoredExceptionHandler(handle) != 0);
1643 windows_segfault_handle = null;1643 windows_segfault_handle = null;
lib/std/dynamic_library.zig+2-2
...@@ -11,7 +11,7 @@ const system = std.os.system;...@@ -11,7 +11,7 @@ const system = std.os.system;
11const maxInt = std.math.maxInt;11const maxInt = std.math.maxInt;
12const max = std.math.max;12const max = std.math.max;
1313
14pub const DynLib = switch (builtin.os) {14pub const DynLib = switch (builtin.os.tag) {
15 .linux => if (builtin.link_libc) DlDynlib else ElfDynLib,15 .linux => if (builtin.link_libc) DlDynlib else ElfDynLib,
16 .windows => WindowsDynLib,16 .windows => WindowsDynLib,
17 .macosx, .tvos, .watchos, .ios, .freebsd => DlDynlib,17 .macosx, .tvos, .watchos, .ios, .freebsd => DlDynlib,
...@@ -390,7 +390,7 @@ pub const DlDynlib = struct {...@@ -390,7 +390,7 @@ pub const DlDynlib = struct {
390};390};
391391
392test "dynamic_library" {392test "dynamic_library" {
393 const libname = switch (builtin.os) {393 const libname = switch (builtin.os.tag) {
394 .linux, .freebsd => "invalid_so.so",394 .linux, .freebsd => "invalid_so.so",
395 .windows => "invalid_dll.dll",395 .windows => "invalid_dll.dll",
396 .macosx, .tvos, .watchos, .ios => "invalid_dylib.dylib",396 .macosx, .tvos, .watchos, .ios => "invalid_dylib.dylib",
lib/std/elf.zig+15-10
...@@ -349,16 +349,6 @@ pub const Elf = struct {...@@ -349,16 +349,6 @@ pub const Elf = struct {
349 program_headers: []ProgramHeader,349 program_headers: []ProgramHeader,
350 allocator: *mem.Allocator,350 allocator: *mem.Allocator,
351351
352 /// Call close when done.
353 pub fn openPath(allocator: *mem.Allocator, path: []const u8) !Elf {
354 @compileError("TODO implement");
355 }
356
357 /// Call close when done.
358 pub fn openFile(allocator: *mem.Allocator, file: File) !Elf {
359 @compileError("TODO implement");
360 }
361
362 pub fn openStream(352 pub fn openStream(
363 allocator: *mem.Allocator,353 allocator: *mem.Allocator,
364 seekable_stream: *io.SeekableStream(anyerror, anyerror),354 seekable_stream: *io.SeekableStream(anyerror, anyerror),
...@@ -554,6 +544,21 @@ pub const Elf = struct {...@@ -554,6 +544,21 @@ pub const Elf = struct {
554};544};
555545
556pub const EI_NIDENT = 16;546pub const EI_NIDENT = 16;
547
548pub const EI_CLASS = 4;
549pub const ELFCLASSNONE = 0;
550pub const ELFCLASS32 = 1;
551pub const ELFCLASS64 = 2;
552pub const ELFCLASSNUM = 3;
553
554pub const EI_DATA = 5;
555pub const ELFDATANONE = 0;
556pub const ELFDATA2LSB = 1;
557pub const ELFDATA2MSB = 2;
558pub const ELFDATANUM = 3;
559
560pub const EI_VERSION = 6;
561
557pub const Elf32_Half = u16;562pub const Elf32_Half = u16;
558pub const Elf64_Half = u16;563pub const Elf64_Half = u16;
559pub const Elf32_Word = u32;564pub const Elf32_Word = u32;
lib/std/event/channel.zig+1-1
...@@ -273,7 +273,7 @@ test "std.event.Channel" {...@@ -273,7 +273,7 @@ test "std.event.Channel" {
273 if (builtin.single_threaded) return error.SkipZigTest;273 if (builtin.single_threaded) return error.SkipZigTest;
274274
275 // https://github.com/ziglang/zig/issues/3251275 // https://github.com/ziglang/zig/issues/3251
276 if (builtin.os == .freebsd) return error.SkipZigTest;276 if (builtin.os.tag == .freebsd) return error.SkipZigTest;
277277
278 var channel: Channel(i32) = undefined;278 var channel: Channel(i32) = undefined;
279 channel.init(&[0]i32{});279 channel.init(&[0]i32{});
lib/std/event/future.zig+1-1
...@@ -86,7 +86,7 @@ test "std.event.Future" {...@@ -86,7 +86,7 @@ test "std.event.Future" {
86 // https://github.com/ziglang/zig/issues/190886 // https://github.com/ziglang/zig/issues/1908
87 if (builtin.single_threaded) return error.SkipZigTest;87 if (builtin.single_threaded) return error.SkipZigTest;
88 // https://github.com/ziglang/zig/issues/325188 // https://github.com/ziglang/zig/issues/3251
89 if (builtin.os == .freebsd) return error.SkipZigTest;89 if (builtin.os.tag == .freebsd) return error.SkipZigTest;
90 // TODO provide a way to run tests in evented I/O mode90 // TODO provide a way to run tests in evented I/O mode
91 if (!std.io.is_async) return error.SkipZigTest;91 if (!std.io.is_async) return error.SkipZigTest;
9292
lib/std/event/lock.zig+1-1
...@@ -123,7 +123,7 @@ test "std.event.Lock" {...@@ -123,7 +123,7 @@ test "std.event.Lock" {
123 if (builtin.single_threaded) return error.SkipZigTest;123 if (builtin.single_threaded) return error.SkipZigTest;
124124
125 // TODO https://github.com/ziglang/zig/issues/3251125 // TODO https://github.com/ziglang/zig/issues/3251
126 if (builtin.os == .freebsd) return error.SkipZigTest;126 if (builtin.os.tag == .freebsd) return error.SkipZigTest;
127127
128 var lock = Lock.init();128 var lock = Lock.init();
129 defer lock.deinit();129 defer lock.deinit();
lib/std/event/loop.zig+13-13
...@@ -34,7 +34,7 @@ pub const Loop = struct {...@@ -34,7 +34,7 @@ pub const Loop = struct {
34 handle: anyframe,34 handle: anyframe,
35 overlapped: Overlapped,35 overlapped: Overlapped,
3636
37 pub const overlapped_init = switch (builtin.os) {37 pub const overlapped_init = switch (builtin.os.tag) {
38 .windows => windows.OVERLAPPED{38 .windows => windows.OVERLAPPED{
39 .Internal = 0,39 .Internal = 0,
40 .InternalHigh = 0,40 .InternalHigh = 0,
...@@ -52,7 +52,7 @@ pub const Loop = struct {...@@ -52,7 +52,7 @@ pub const Loop = struct {
52 EventFd,52 EventFd,
53 };53 };
5454
55 pub const EventFd = switch (builtin.os) {55 pub const EventFd = switch (builtin.os.tag) {
56 .macosx, .freebsd, .netbsd, .dragonfly => KEventFd,56 .macosx, .freebsd, .netbsd, .dragonfly => KEventFd,
57 .linux => struct {57 .linux => struct {
58 base: ResumeNode,58 base: ResumeNode,
...@@ -71,7 +71,7 @@ pub const Loop = struct {...@@ -71,7 +71,7 @@ pub const Loop = struct {
71 kevent: os.Kevent,71 kevent: os.Kevent,
72 };72 };
7373
74 pub const Basic = switch (builtin.os) {74 pub const Basic = switch (builtin.os.tag) {
75 .macosx, .freebsd, .netbsd, .dragonfly => KEventBasic,75 .macosx, .freebsd, .netbsd, .dragonfly => KEventBasic,
76 .linux => struct {76 .linux => struct {
77 base: ResumeNode,77 base: ResumeNode,
...@@ -173,7 +173,7 @@ pub const Loop = struct {...@@ -173,7 +173,7 @@ pub const Loop = struct {
173 const wakeup_bytes = [_]u8{0x1} ** 8;173 const wakeup_bytes = [_]u8{0x1} ** 8;
174174
175 fn initOsData(self: *Loop, extra_thread_count: usize) InitOsDataError!void {175 fn initOsData(self: *Loop, extra_thread_count: usize) InitOsDataError!void {
176 switch (builtin.os) {176 switch (builtin.os.tag) {
177 .linux => {177 .linux => {
178 self.os_data.fs_queue = std.atomic.Queue(Request).init();178 self.os_data.fs_queue = std.atomic.Queue(Request).init();
179 self.os_data.fs_queue_item = 0;179 self.os_data.fs_queue_item = 0;
...@@ -404,7 +404,7 @@ pub const Loop = struct {...@@ -404,7 +404,7 @@ pub const Loop = struct {
404 }404 }
405405
406 fn deinitOsData(self: *Loop) void {406 fn deinitOsData(self: *Loop) void {
407 switch (builtin.os) {407 switch (builtin.os.tag) {
408 .linux => {408 .linux => {
409 noasync os.close(self.os_data.final_eventfd);409 noasync os.close(self.os_data.final_eventfd);
410 while (self.available_eventfd_resume_nodes.pop()) |node| noasync os.close(node.data.eventfd);410 while (self.available_eventfd_resume_nodes.pop()) |node| noasync os.close(node.data.eventfd);
...@@ -568,7 +568,7 @@ pub const Loop = struct {...@@ -568,7 +568,7 @@ pub const Loop = struct {
568 };568 };
569 const eventfd_node = &resume_stack_node.data;569 const eventfd_node = &resume_stack_node.data;
570 eventfd_node.base.handle = next_tick_node.data;570 eventfd_node.base.handle = next_tick_node.data;
571 switch (builtin.os) {571 switch (builtin.os.tag) {
572 .macosx, .freebsd, .netbsd, .dragonfly => {572 .macosx, .freebsd, .netbsd, .dragonfly => {
573 const kevent_array = @as(*const [1]os.Kevent, &eventfd_node.kevent);573 const kevent_array = @as(*const [1]os.Kevent, &eventfd_node.kevent);
574 const empty_kevs = &[0]os.Kevent{};574 const empty_kevs = &[0]os.Kevent{};
...@@ -628,7 +628,7 @@ pub const Loop = struct {...@@ -628,7 +628,7 @@ pub const Loop = struct {
628628
629 self.workerRun();629 self.workerRun();
630630
631 switch (builtin.os) {631 switch (builtin.os.tag) {
632 .linux,632 .linux,
633 .macosx,633 .macosx,
634 .freebsd,634 .freebsd,
...@@ -678,7 +678,7 @@ pub const Loop = struct {...@@ -678,7 +678,7 @@ pub const Loop = struct {
678 const prev = @atomicRmw(usize, &self.pending_event_count, AtomicRmwOp.Sub, 1, AtomicOrder.SeqCst);678 const prev = @atomicRmw(usize, &self.pending_event_count, AtomicRmwOp.Sub, 1, AtomicOrder.SeqCst);
679 if (prev == 1) {679 if (prev == 1) {
680 // cause all the threads to stop680 // cause all the threads to stop
681 switch (builtin.os) {681 switch (builtin.os.tag) {
682 .linux => {682 .linux => {
683 self.posixFsRequest(&self.os_data.fs_end_request);683 self.posixFsRequest(&self.os_data.fs_end_request);
684 // writing 8 bytes to an eventfd cannot fail684 // writing 8 bytes to an eventfd cannot fail
...@@ -902,7 +902,7 @@ pub const Loop = struct {...@@ -902,7 +902,7 @@ pub const Loop = struct {
902 self.finishOneEvent();902 self.finishOneEvent();
903 }903 }
904904
905 switch (builtin.os) {905 switch (builtin.os.tag) {
906 .linux => {906 .linux => {
907 // only process 1 event so we don't steal from other threads907 // only process 1 event so we don't steal from other threads
908 var events: [1]os.linux.epoll_event = undefined;908 var events: [1]os.linux.epoll_event = undefined;
...@@ -989,7 +989,7 @@ pub const Loop = struct {...@@ -989,7 +989,7 @@ pub const Loop = struct {
989 fn posixFsRequest(self: *Loop, request_node: *Request.Node) void {989 fn posixFsRequest(self: *Loop, request_node: *Request.Node) void {
990 self.beginOneEvent(); // finished in posixFsRun after processing the msg990 self.beginOneEvent(); // finished in posixFsRun after processing the msg
991 self.os_data.fs_queue.put(request_node);991 self.os_data.fs_queue.put(request_node);
992 switch (builtin.os) {992 switch (builtin.os.tag) {
993 .macosx, .freebsd, .netbsd, .dragonfly => {993 .macosx, .freebsd, .netbsd, .dragonfly => {
994 const fs_kevs = @as(*const [1]os.Kevent, &self.os_data.fs_kevent_wake);994 const fs_kevs = @as(*const [1]os.Kevent, &self.os_data.fs_kevent_wake);
995 const empty_kevs = &[0]os.Kevent{};995 const empty_kevs = &[0]os.Kevent{};
...@@ -1018,7 +1018,7 @@ pub const Loop = struct {...@@ -1018,7 +1018,7 @@ pub const Loop = struct {
1018 // https://github.com/ziglang/zig/issues/31571018 // https://github.com/ziglang/zig/issues/3157
1019 fn posixFsRun(self: *Loop) void {1019 fn posixFsRun(self: *Loop) void {
1020 while (true) {1020 while (true) {
1021 if (builtin.os == .linux) {1021 if (builtin.os.tag == .linux) {
1022 @atomicStore(i32, &self.os_data.fs_queue_item, 0, .SeqCst);1022 @atomicStore(i32, &self.os_data.fs_queue_item, 0, .SeqCst);
1023 }1023 }
1024 while (self.os_data.fs_queue.get()) |node| {1024 while (self.os_data.fs_queue.get()) |node| {
...@@ -1053,7 +1053,7 @@ pub const Loop = struct {...@@ -1053,7 +1053,7 @@ pub const Loop = struct {
1053 }1053 }
1054 self.finishOneEvent();1054 self.finishOneEvent();
1055 }1055 }
1056 switch (builtin.os) {1056 switch (builtin.os.tag) {
1057 .linux => {1057 .linux => {
1058 const rc = os.linux.futex_wait(&self.os_data.fs_queue_item, os.linux.FUTEX_WAIT, 0, null);1058 const rc = os.linux.futex_wait(&self.os_data.fs_queue_item, os.linux.FUTEX_WAIT, 0, null);
1059 switch (os.linux.getErrno(rc)) {1059 switch (os.linux.getErrno(rc)) {
...@@ -1071,7 +1071,7 @@ pub const Loop = struct {...@@ -1071,7 +1071,7 @@ pub const Loop = struct {
1071 }1071 }
1072 }1072 }
10731073
1074 const OsData = switch (builtin.os) {1074 const OsData = switch (builtin.os.tag) {
1075 .linux => LinuxOsData,1075 .linux => LinuxOsData,
1076 .macosx, .freebsd, .netbsd, .dragonfly => KEventData,1076 .macosx, .freebsd, .netbsd, .dragonfly => KEventData,
1077 .windows => struct {1077 .windows => struct {
lib/std/fs.zig+23-23
...@@ -29,7 +29,7 @@ pub const Watch = @import("fs/watch.zig").Watch;...@@ -29,7 +29,7 @@ pub const Watch = @import("fs/watch.zig").Watch;
29/// All file system operations which return a path are guaranteed to29/// All file system operations which return a path are guaranteed to
30/// fit into a UTF-8 encoded array of this length.30/// fit into a UTF-8 encoded array of this length.
31/// The byte count includes room for a null sentinel byte.31/// The byte count includes room for a null sentinel byte.
32pub const MAX_PATH_BYTES = switch (builtin.os) {32pub const MAX_PATH_BYTES = switch (builtin.os.tag) {
33 .linux, .macosx, .ios, .freebsd, .netbsd, .dragonfly => os.PATH_MAX,33 .linux, .macosx, .ios, .freebsd, .netbsd, .dragonfly => os.PATH_MAX,
34 // Each UTF-16LE character may be expanded to 3 UTF-8 bytes.34 // Each UTF-16LE character may be expanded to 3 UTF-8 bytes.
35 // If it would require 4 UTF-8 bytes, then there would be a surrogate35 // If it would require 4 UTF-8 bytes, then there would be a surrogate
...@@ -47,7 +47,7 @@ pub const base64_encoder = base64.Base64Encoder.init(...@@ -47,7 +47,7 @@ pub const base64_encoder = base64.Base64Encoder.init(
4747
48/// Whether or not async file system syscalls need a dedicated thread because the operating48/// Whether or not async file system syscalls need a dedicated thread because the operating
49/// system does not support non-blocking I/O on the file system.49/// system does not support non-blocking I/O on the file system.
50pub const need_async_thread = std.io.is_async and switch (builtin.os) {50pub const need_async_thread = std.io.is_async and switch (builtin.os.tag) {
51 .windows, .other => false,51 .windows, .other => false,
52 else => true,52 else => true,
53};53};
...@@ -270,7 +270,7 @@ pub const AtomicFile = struct {...@@ -270,7 +270,7 @@ pub const AtomicFile = struct {
270 assert(!self.finished);270 assert(!self.finished);
271 self.file.close();271 self.file.close();
272 self.finished = true;272 self.finished = true;
273 if (builtin.os == .windows) {273 if (builtin.os.tag == .windows) {
274 const dest_path_w = try os.windows.sliceToPrefixedFileW(self.dest_path);274 const dest_path_w = try os.windows.sliceToPrefixedFileW(self.dest_path);
275 const tmp_path_w = try os.windows.cStrToPrefixedFileW(@ptrCast([*:0]u8, &self.tmp_path_buf));275 const tmp_path_w = try os.windows.cStrToPrefixedFileW(@ptrCast([*:0]u8, &self.tmp_path_buf));
276 return os.renameW(&tmp_path_w, &dest_path_w);276 return os.renameW(&tmp_path_w, &dest_path_w);
...@@ -394,7 +394,7 @@ pub const Dir = struct {...@@ -394,7 +394,7 @@ pub const Dir = struct {
394394
395 const IteratorError = error{AccessDenied} || os.UnexpectedError;395 const IteratorError = error{AccessDenied} || os.UnexpectedError;
396396
397 pub const Iterator = switch (builtin.os) {397 pub const Iterator = switch (builtin.os.tag) {
398 .macosx, .ios, .freebsd, .netbsd, .dragonfly => struct {398 .macosx, .ios, .freebsd, .netbsd, .dragonfly => struct {
399 dir: Dir,399 dir: Dir,
400 seek: i64,400 seek: i64,
...@@ -409,7 +409,7 @@ pub const Dir = struct {...@@ -409,7 +409,7 @@ pub const Dir = struct {
409 /// Memory such as file names referenced in this returned entry becomes invalid409 /// Memory such as file names referenced in this returned entry becomes invalid
410 /// with subsequent calls to `next`, as well as when this `Dir` is deinitialized.410 /// with subsequent calls to `next`, as well as when this `Dir` is deinitialized.
411 pub fn next(self: *Self) Error!?Entry {411 pub fn next(self: *Self) Error!?Entry {
412 switch (builtin.os) {412 switch (builtin.os.tag) {
413 .macosx, .ios => return self.nextDarwin(),413 .macosx, .ios => return self.nextDarwin(),
414 .freebsd, .netbsd, .dragonfly => return self.nextBsd(),414 .freebsd, .netbsd, .dragonfly => return self.nextBsd(),
415 else => @compileError("unimplemented"),415 else => @compileError("unimplemented"),
...@@ -644,7 +644,7 @@ pub const Dir = struct {...@@ -644,7 +644,7 @@ pub const Dir = struct {
644 };644 };
645645
646 pub fn iterate(self: Dir) Iterator {646 pub fn iterate(self: Dir) Iterator {
647 switch (builtin.os) {647 switch (builtin.os.tag) {
648 .macosx, .ios, .freebsd, .netbsd, .dragonfly => return Iterator{648 .macosx, .ios, .freebsd, .netbsd, .dragonfly => return Iterator{
649 .dir = self,649 .dir = self,
650 .seek = 0,650 .seek = 0,
...@@ -710,7 +710,7 @@ pub const Dir = struct {...@@ -710,7 +710,7 @@ pub const Dir = struct {
710 /// Asserts that the path parameter has no null bytes.710 /// Asserts that the path parameter has no null bytes.
711 pub fn openFile(self: Dir, sub_path: []const u8, flags: File.OpenFlags) File.OpenError!File {711 pub fn openFile(self: Dir, sub_path: []const u8, flags: File.OpenFlags) File.OpenError!File {
712 if (std.debug.runtime_safety) for (sub_path) |byte| assert(byte != 0);712 if (std.debug.runtime_safety) for (sub_path) |byte| assert(byte != 0);
713 if (builtin.os == .windows) {713 if (builtin.os.tag == .windows) {
714 const path_w = try os.windows.sliceToPrefixedFileW(sub_path);714 const path_w = try os.windows.sliceToPrefixedFileW(sub_path);
715 return self.openFileW(&path_w, flags);715 return self.openFileW(&path_w, flags);
716 }716 }
...@@ -720,7 +720,7 @@ pub const Dir = struct {...@@ -720,7 +720,7 @@ pub const Dir = struct {
720720
721 /// Same as `openFile` but the path parameter is null-terminated.721 /// Same as `openFile` but the path parameter is null-terminated.
722 pub fn openFileC(self: Dir, sub_path: [*:0]const u8, flags: File.OpenFlags) File.OpenError!File {722 pub fn openFileC(self: Dir, sub_path: [*:0]const u8, flags: File.OpenFlags) File.OpenError!File {
723 if (builtin.os == .windows) {723 if (builtin.os.tag == .windows) {
724 const path_w = try os.windows.cStrToPrefixedFileW(sub_path);724 const path_w = try os.windows.cStrToPrefixedFileW(sub_path);
725 return self.openFileW(&path_w, flags);725 return self.openFileW(&path_w, flags);
726 }726 }
...@@ -760,7 +760,7 @@ pub const Dir = struct {...@@ -760,7 +760,7 @@ pub const Dir = struct {
760 /// Asserts that the path parameter has no null bytes.760 /// Asserts that the path parameter has no null bytes.
761 pub fn createFile(self: Dir, sub_path: []const u8, flags: File.CreateFlags) File.OpenError!File {761 pub fn createFile(self: Dir, sub_path: []const u8, flags: File.CreateFlags) File.OpenError!File {
762 if (std.debug.runtime_safety) for (sub_path) |byte| assert(byte != 0);762 if (std.debug.runtime_safety) for (sub_path) |byte| assert(byte != 0);
763 if (builtin.os == .windows) {763 if (builtin.os.tag == .windows) {
764 const path_w = try os.windows.sliceToPrefixedFileW(sub_path);764 const path_w = try os.windows.sliceToPrefixedFileW(sub_path);
765 return self.createFileW(&path_w, flags);765 return self.createFileW(&path_w, flags);
766 }766 }
...@@ -770,7 +770,7 @@ pub const Dir = struct {...@@ -770,7 +770,7 @@ pub const Dir = struct {
770770
771 /// Same as `createFile` but the path parameter is null-terminated.771 /// Same as `createFile` but the path parameter is null-terminated.
772 pub fn createFileC(self: Dir, sub_path_c: [*:0]const u8, flags: File.CreateFlags) File.OpenError!File {772 pub fn createFileC(self: Dir, sub_path_c: [*:0]const u8, flags: File.CreateFlags) File.OpenError!File {
773 if (builtin.os == .windows) {773 if (builtin.os.tag == .windows) {
774 const path_w = try os.windows.cStrToPrefixedFileW(sub_path_c);774 const path_w = try os.windows.cStrToPrefixedFileW(sub_path_c);
775 return self.createFileW(&path_w, flags);775 return self.createFileW(&path_w, flags);
776 }776 }
...@@ -901,7 +901,7 @@ pub const Dir = struct {...@@ -901,7 +901,7 @@ pub const Dir = struct {
901 /// Asserts that the path parameter has no null bytes.901 /// Asserts that the path parameter has no null bytes.
902 pub fn openDirTraverse(self: Dir, sub_path: []const u8) OpenError!Dir {902 pub fn openDirTraverse(self: Dir, sub_path: []const u8) OpenError!Dir {
903 if (std.debug.runtime_safety) for (sub_path) |byte| assert(byte != 0);903 if (std.debug.runtime_safety) for (sub_path) |byte| assert(byte != 0);
904 if (builtin.os == .windows) {904 if (builtin.os.tag == .windows) {
905 const sub_path_w = try os.windows.sliceToPrefixedFileW(sub_path);905 const sub_path_w = try os.windows.sliceToPrefixedFileW(sub_path);
906 return self.openDirTraverseW(&sub_path_w);906 return self.openDirTraverseW(&sub_path_w);
907 }907 }
...@@ -919,7 +919,7 @@ pub const Dir = struct {...@@ -919,7 +919,7 @@ pub const Dir = struct {
919 /// Asserts that the path parameter has no null bytes.919 /// Asserts that the path parameter has no null bytes.
920 pub fn openDirList(self: Dir, sub_path: []const u8) OpenError!Dir {920 pub fn openDirList(self: Dir, sub_path: []const u8) OpenError!Dir {
921 if (std.debug.runtime_safety) for (sub_path) |byte| assert(byte != 0);921 if (std.debug.runtime_safety) for (sub_path) |byte| assert(byte != 0);
922 if (builtin.os == .windows) {922 if (builtin.os.tag == .windows) {
923 const sub_path_w = try os.windows.sliceToPrefixedFileW(sub_path);923 const sub_path_w = try os.windows.sliceToPrefixedFileW(sub_path);
924 return self.openDirListW(&sub_path_w);924 return self.openDirListW(&sub_path_w);
925 }925 }
...@@ -930,7 +930,7 @@ pub const Dir = struct {...@@ -930,7 +930,7 @@ pub const Dir = struct {
930930
931 /// Same as `openDirTraverse` except the parameter is null-terminated.931 /// Same as `openDirTraverse` except the parameter is null-terminated.
932 pub fn openDirTraverseC(self: Dir, sub_path_c: [*:0]const u8) OpenError!Dir {932 pub fn openDirTraverseC(self: Dir, sub_path_c: [*:0]const u8) OpenError!Dir {
933 if (builtin.os == .windows) {933 if (builtin.os.tag == .windows) {
934 const sub_path_w = try os.windows.cStrToPrefixedFileW(sub_path_c);934 const sub_path_w = try os.windows.cStrToPrefixedFileW(sub_path_c);
935 return self.openDirTraverseW(&sub_path_w);935 return self.openDirTraverseW(&sub_path_w);
936 } else {936 } else {
...@@ -941,7 +941,7 @@ pub const Dir = struct {...@@ -941,7 +941,7 @@ pub const Dir = struct {
941941
942 /// Same as `openDirList` except the parameter is null-terminated.942 /// Same as `openDirList` except the parameter is null-terminated.
943 pub fn openDirListC(self: Dir, sub_path_c: [*:0]const u8) OpenError!Dir {943 pub fn openDirListC(self: Dir, sub_path_c: [*:0]const u8) OpenError!Dir {
944 if (builtin.os == .windows) {944 if (builtin.os.tag == .windows) {
945 const sub_path_w = try os.windows.cStrToPrefixedFileW(sub_path_c);945 const sub_path_w = try os.windows.cStrToPrefixedFileW(sub_path_c);
946 return self.openDirListW(&sub_path_w);946 return self.openDirListW(&sub_path_w);
947 } else {947 } else {
...@@ -1083,7 +1083,7 @@ pub const Dir = struct {...@@ -1083,7 +1083,7 @@ pub const Dir = struct {
1083 /// Asserts that the path parameter has no null bytes.1083 /// Asserts that the path parameter has no null bytes.
1084 pub fn deleteDir(self: Dir, sub_path: []const u8) DeleteDirError!void {1084 pub fn deleteDir(self: Dir, sub_path: []const u8) DeleteDirError!void {
1085 if (std.debug.runtime_safety) for (sub_path) |byte| assert(byte != 0);1085 if (std.debug.runtime_safety) for (sub_path) |byte| assert(byte != 0);
1086 if (builtin.os == .windows) {1086 if (builtin.os.tag == .windows) {
1087 const sub_path_w = try os.windows.sliceToPrefixedFileW(sub_path);1087 const sub_path_w = try os.windows.sliceToPrefixedFileW(sub_path);
1088 return self.deleteDirW(&sub_path_w);1088 return self.deleteDirW(&sub_path_w);
1089 }1089 }
...@@ -1340,7 +1340,7 @@ pub const Dir = struct {...@@ -1340,7 +1340,7 @@ pub const Dir = struct {
1340 /// For example, instead of testing if a file exists and then opening it, just1340 /// For example, instead of testing if a file exists and then opening it, just
1341 /// open it and handle the error for file not found.1341 /// open it and handle the error for file not found.
1342 pub fn access(self: Dir, sub_path: []const u8, flags: File.OpenFlags) AccessError!void {1342 pub fn access(self: Dir, sub_path: []const u8, flags: File.OpenFlags) AccessError!void {
1343 if (builtin.os == .windows) {1343 if (builtin.os.tag == .windows) {
1344 const sub_path_w = try os.windows.sliceToPrefixedFileW(sub_path);1344 const sub_path_w = try os.windows.sliceToPrefixedFileW(sub_path);
1345 return self.accessW(&sub_path_w, flags);1345 return self.accessW(&sub_path_w, flags);
1346 }1346 }
...@@ -1350,7 +1350,7 @@ pub const Dir = struct {...@@ -1350,7 +1350,7 @@ pub const Dir = struct {
13501350
1351 /// Same as `access` except the path parameter is null-terminated.1351 /// Same as `access` except the path parameter is null-terminated.
1352 pub fn accessZ(self: Dir, sub_path: [*:0]const u8, flags: File.OpenFlags) AccessError!void {1352 pub fn accessZ(self: Dir, sub_path: [*:0]const u8, flags: File.OpenFlags) AccessError!void {
1353 if (builtin.os == .windows) {1353 if (builtin.os.tag == .windows) {
1354 const sub_path_w = try os.windows.cStrToPrefixedFileW(sub_path);1354 const sub_path_w = try os.windows.cStrToPrefixedFileW(sub_path);
1355 return self.accessW(&sub_path_w, flags);1355 return self.accessW(&sub_path_w, flags);
1356 }1356 }
...@@ -1381,7 +1381,7 @@ pub const Dir = struct {...@@ -1381,7 +1381,7 @@ pub const Dir = struct {
1381/// Closing the returned `Dir` is checked illegal behavior. Iterating over the result is illegal behavior.1381/// Closing the returned `Dir` is checked illegal behavior. Iterating over the result is illegal behavior.
1382/// On POSIX targets, this function is comptime-callable.1382/// On POSIX targets, this function is comptime-callable.
1383pub fn cwd() Dir {1383pub fn cwd() Dir {
1384 if (builtin.os == .windows) {1384 if (builtin.os.tag == .windows) {
1385 return Dir{ .fd = os.windows.peb().ProcessParameters.CurrentDirectory.Handle };1385 return Dir{ .fd = os.windows.peb().ProcessParameters.CurrentDirectory.Handle };
1386 } else {1386 } else {
1387 return Dir{ .fd = os.AT_FDCWD };1387 return Dir{ .fd = os.AT_FDCWD };
...@@ -1560,10 +1560,10 @@ pub fn readLinkC(pathname_c: [*]const u8, buffer: *[MAX_PATH_BYTES]u8) ![]u8 {...@@ -1560,10 +1560,10 @@ pub fn readLinkC(pathname_c: [*]const u8, buffer: *[MAX_PATH_BYTES]u8) ![]u8 {
1560pub const OpenSelfExeError = os.OpenError || os.windows.CreateFileError || SelfExePathError;1560pub const OpenSelfExeError = os.OpenError || os.windows.CreateFileError || SelfExePathError;
15611561
1562pub fn openSelfExe() OpenSelfExeError!File {1562pub fn openSelfExe() OpenSelfExeError!File {
1563 if (builtin.os == .linux) {1563 if (builtin.os.tag == .linux) {
1564 return openFileAbsoluteC("/proc/self/exe", .{});1564 return openFileAbsoluteC("/proc/self/exe", .{});
1565 }1565 }
1566 if (builtin.os == .windows) {1566 if (builtin.os.tag == .windows) {
1567 const wide_slice = selfExePathW();1567 const wide_slice = selfExePathW();
1568 const prefixed_path_w = try os.windows.wToPrefixedFileW(wide_slice);1568 const prefixed_path_w = try os.windows.wToPrefixedFileW(wide_slice);
1569 return cwd().openReadW(&prefixed_path_w);1569 return cwd().openReadW(&prefixed_path_w);
...@@ -1575,7 +1575,7 @@ pub fn openSelfExe() OpenSelfExeError!File {...@@ -1575,7 +1575,7 @@ pub fn openSelfExe() OpenSelfExeError!File {
1575}1575}
15761576
1577test "openSelfExe" {1577test "openSelfExe" {
1578 switch (builtin.os) {1578 switch (builtin.os.tag) {
1579 .linux, .macosx, .ios, .windows, .freebsd, .dragonfly => (try openSelfExe()).close(),1579 .linux, .macosx, .ios, .windows, .freebsd, .dragonfly => (try openSelfExe()).close(),
1580 else => return error.SkipZigTest, // Unsupported OS.1580 else => return error.SkipZigTest, // Unsupported OS.
1581 }1581 }
...@@ -1600,7 +1600,7 @@ pub fn selfExePath(out_buffer: *[MAX_PATH_BYTES]u8) SelfExePathError![]u8 {...@@ -1600,7 +1600,7 @@ pub fn selfExePath(out_buffer: *[MAX_PATH_BYTES]u8) SelfExePathError![]u8 {
1600 if (rc != 0) return error.NameTooLong;1600 if (rc != 0) return error.NameTooLong;
1601 return mem.toSlice(u8, @ptrCast([*:0]u8, out_buffer));1601 return mem.toSlice(u8, @ptrCast([*:0]u8, out_buffer));
1602 }1602 }
1603 switch (builtin.os) {1603 switch (builtin.os.tag) {
1604 .linux => return os.readlinkC("/proc/self/exe", out_buffer),1604 .linux => return os.readlinkC("/proc/self/exe", out_buffer),
1605 .freebsd, .dragonfly => {1605 .freebsd, .dragonfly => {
1606 var mib = [4]c_int{ os.CTL_KERN, os.KERN_PROC, os.KERN_PROC_PATHNAME, -1 };1606 var mib = [4]c_int{ os.CTL_KERN, os.KERN_PROC, os.KERN_PROC_PATHNAME, -1 };
...@@ -1642,7 +1642,7 @@ pub fn selfExeDirPathAlloc(allocator: *Allocator) ![]u8 {...@@ -1642,7 +1642,7 @@ pub fn selfExeDirPathAlloc(allocator: *Allocator) ![]u8 {
1642/// Get the directory path that contains the current executable.1642/// Get the directory path that contains the current executable.
1643/// Returned value is a slice of out_buffer.1643/// Returned value is a slice of out_buffer.
1644pub fn selfExeDirPath(out_buffer: *[MAX_PATH_BYTES]u8) SelfExePathError![]const u8 {1644pub fn selfExeDirPath(out_buffer: *[MAX_PATH_BYTES]u8) SelfExePathError![]const u8 {
1645 if (builtin.os == .linux) {1645 if (builtin.os.tag == .linux) {
1646 // If the currently executing binary has been deleted,1646 // If the currently executing binary has been deleted,
1647 // the file path looks something like `/a/b/c/exe (deleted)`1647 // the file path looks something like `/a/b/c/exe (deleted)`
1648 // This path cannot be opened, but it's valid for determining the directory1648 // This path cannot be opened, but it's valid for determining the directory
lib/std/fs/file.zig+6-6
...@@ -29,7 +29,7 @@ pub const File = struct {...@@ -29,7 +29,7 @@ pub const File = struct {
2929
30 pub const Mode = os.mode_t;30 pub const Mode = os.mode_t;
3131
32 pub const default_mode = switch (builtin.os) {32 pub const default_mode = switch (builtin.os.tag) {
33 .windows => 0,33 .windows => 0,
34 else => 0o666,34 else => 0o666,
35 };35 };
...@@ -83,7 +83,7 @@ pub const File = struct {...@@ -83,7 +83,7 @@ pub const File = struct {
8383
84 /// Test whether ANSI escape codes will be treated as such.84 /// Test whether ANSI escape codes will be treated as such.
85 pub fn supportsAnsiEscapeCodes(self: File) bool {85 pub fn supportsAnsiEscapeCodes(self: File) bool {
86 if (builtin.os == .windows) {86 if (builtin.os.tag == .windows) {
87 return os.isCygwinPty(self.handle);87 return os.isCygwinPty(self.handle);
88 }88 }
89 if (self.isTty()) {89 if (self.isTty()) {
...@@ -128,7 +128,7 @@ pub const File = struct {...@@ -128,7 +128,7 @@ pub const File = struct {
128128
129 /// TODO: integrate with async I/O129 /// TODO: integrate with async I/O
130 pub fn getEndPos(self: File) GetPosError!u64 {130 pub fn getEndPos(self: File) GetPosError!u64 {
131 if (builtin.os == .windows) {131 if (builtin.os.tag == .windows) {
132 return windows.GetFileSizeEx(self.handle);132 return windows.GetFileSizeEx(self.handle);
133 }133 }
134 return (try self.stat()).size;134 return (try self.stat()).size;
...@@ -138,7 +138,7 @@ pub const File = struct {...@@ -138,7 +138,7 @@ pub const File = struct {
138138
139 /// TODO: integrate with async I/O139 /// TODO: integrate with async I/O
140 pub fn mode(self: File) ModeError!Mode {140 pub fn mode(self: File) ModeError!Mode {
141 if (builtin.os == .windows) {141 if (builtin.os.tag == .windows) {
142 return {};142 return {};
143 }143 }
144 return (try self.stat()).mode;144 return (try self.stat()).mode;
...@@ -162,7 +162,7 @@ pub const File = struct {...@@ -162,7 +162,7 @@ pub const File = struct {
162162
163 /// TODO: integrate with async I/O163 /// TODO: integrate with async I/O
164 pub fn stat(self: File) StatError!Stat {164 pub fn stat(self: File) StatError!Stat {
165 if (builtin.os == .windows) {165 if (builtin.os.tag == .windows) {
166 var io_status_block: windows.IO_STATUS_BLOCK = undefined;166 var io_status_block: windows.IO_STATUS_BLOCK = undefined;
167 var info: windows.FILE_ALL_INFORMATION = undefined;167 var info: windows.FILE_ALL_INFORMATION = undefined;
168 const rc = windows.ntdll.NtQueryInformationFile(self.handle, &io_status_block, &info, @sizeOf(windows.FILE_ALL_INFORMATION), .FileAllInformation);168 const rc = windows.ntdll.NtQueryInformationFile(self.handle, &io_status_block, &info, @sizeOf(windows.FILE_ALL_INFORMATION), .FileAllInformation);
...@@ -209,7 +209,7 @@ pub const File = struct {...@@ -209,7 +209,7 @@ pub const File = struct {
209 /// last modification timestamp in nanoseconds209 /// last modification timestamp in nanoseconds
210 mtime: i64,210 mtime: i64,
211 ) UpdateTimesError!void {211 ) UpdateTimesError!void {
212 if (builtin.os == .windows) {212 if (builtin.os.tag == .windows) {
213 const atime_ft = windows.nanoSecondsToFileTime(atime);213 const atime_ft = windows.nanoSecondsToFileTime(atime);
214 const mtime_ft = windows.nanoSecondsToFileTime(mtime);214 const mtime_ft = windows.nanoSecondsToFileTime(mtime);
215 return windows.SetFileTime(self.handle, null, &atime_ft, &mtime_ft);215 return windows.SetFileTime(self.handle, null, &atime_ft, &mtime_ft);
lib/std/fs/get_app_data_dir.zig+1-1
...@@ -13,7 +13,7 @@ pub const GetAppDataDirError = error{...@@ -13,7 +13,7 @@ pub const GetAppDataDirError = error{
13/// Caller owns returned memory.13/// Caller owns returned memory.
14/// TODO determine if we can remove the allocator requirement14/// TODO determine if we can remove the allocator requirement
15pub fn getAppDataDir(allocator: *mem.Allocator, appname: []const u8) GetAppDataDirError![]u8 {15pub fn getAppDataDir(allocator: *mem.Allocator, appname: []const u8) GetAppDataDirError![]u8 {
16 switch (builtin.os) {16 switch (builtin.os.tag) {
17 .windows => {17 .windows => {
18 var dir_path_ptr: [*:0]u16 = undefined;18 var dir_path_ptr: [*:0]u16 = undefined;
19 switch (os.windows.shell32.SHGetKnownFolderPath(19 switch (os.windows.shell32.SHGetKnownFolderPath(
lib/std/fs/path.zig+19-19
...@@ -13,18 +13,18 @@ const process = std.process;...@@ -13,18 +13,18 @@ const process = std.process;
1313
14pub const sep_windows = '\\';14pub const sep_windows = '\\';
15pub const sep_posix = '/';15pub const sep_posix = '/';
16pub const sep = if (builtin.os == .windows) sep_windows else sep_posix;16pub const sep = if (builtin.os.tag == .windows) sep_windows else sep_posix;
1717
18pub const sep_str_windows = "\\";18pub const sep_str_windows = "\\";
19pub const sep_str_posix = "/";19pub const sep_str_posix = "/";
20pub const sep_str = if (builtin.os == .windows) sep_str_windows else sep_str_posix;20pub const sep_str = if (builtin.os.tag == .windows) sep_str_windows else sep_str_posix;
2121
22pub const delimiter_windows = ';';22pub const delimiter_windows = ';';
23pub const delimiter_posix = ':';23pub const delimiter_posix = ':';
24pub const delimiter = if (builtin.os == .windows) delimiter_windows else delimiter_posix;24pub const delimiter = if (builtin.os.tag == .windows) delimiter_windows else delimiter_posix;
2525
26pub fn isSep(byte: u8) bool {26pub fn isSep(byte: u8) bool {
27 if (builtin.os == .windows) {27 if (builtin.os.tag == .windows) {
28 return byte == '/' or byte == '\\';28 return byte == '/' or byte == '\\';
29 } else {29 } else {
30 return byte == '/';30 return byte == '/';
...@@ -74,7 +74,7 @@ fn joinSep(allocator: *Allocator, separator: u8, paths: []const []const u8) ![]u...@@ -74,7 +74,7 @@ fn joinSep(allocator: *Allocator, separator: u8, paths: []const []const u8) ![]u
74 return buf;74 return buf;
75}75}
7676
77pub const join = if (builtin.os == .windows) joinWindows else joinPosix;77pub const join = if (builtin.os.tag == .windows) joinWindows else joinPosix;
7878
79/// Naively combines a series of paths with the native path seperator.79/// Naively combines a series of paths with the native path seperator.
80/// Allocates memory for the result, which must be freed by the caller.80/// Allocates memory for the result, which must be freed by the caller.
...@@ -129,7 +129,7 @@ test "join" {...@@ -129,7 +129,7 @@ test "join" {
129}129}
130130
131pub fn isAbsoluteC(path_c: [*:0]const u8) bool {131pub fn isAbsoluteC(path_c: [*:0]const u8) bool {
132 if (builtin.os == .windows) {132 if (builtin.os.tag == .windows) {
133 return isAbsoluteWindowsC(path_c);133 return isAbsoluteWindowsC(path_c);
134 } else {134 } else {
135 return isAbsolutePosixC(path_c);135 return isAbsolutePosixC(path_c);
...@@ -137,7 +137,7 @@ pub fn isAbsoluteC(path_c: [*:0]const u8) bool {...@@ -137,7 +137,7 @@ pub fn isAbsoluteC(path_c: [*:0]const u8) bool {
137}137}
138138
139pub fn isAbsolute(path: []const u8) bool {139pub fn isAbsolute(path: []const u8) bool {
140 if (builtin.os == .windows) {140 if (builtin.os.tag == .windows) {
141 return isAbsoluteWindows(path);141 return isAbsoluteWindows(path);
142 } else {142 } else {
143 return isAbsolutePosix(path);143 return isAbsolutePosix(path);
...@@ -318,7 +318,7 @@ test "windowsParsePath" {...@@ -318,7 +318,7 @@ test "windowsParsePath" {
318}318}
319319
320pub fn diskDesignator(path: []const u8) []const u8 {320pub fn diskDesignator(path: []const u8) []const u8 {
321 if (builtin.os == .windows) {321 if (builtin.os.tag == .windows) {
322 return diskDesignatorWindows(path);322 return diskDesignatorWindows(path);
323 } else {323 } else {
324 return "";324 return "";
...@@ -383,7 +383,7 @@ fn asciiEqlIgnoreCase(s1: []const u8, s2: []const u8) bool {...@@ -383,7 +383,7 @@ fn asciiEqlIgnoreCase(s1: []const u8, s2: []const u8) bool {
383383
384/// On Windows, this calls `resolveWindows` and on POSIX it calls `resolvePosix`.384/// On Windows, this calls `resolveWindows` and on POSIX it calls `resolvePosix`.
385pub fn resolve(allocator: *Allocator, paths: []const []const u8) ![]u8 {385pub fn resolve(allocator: *Allocator, paths: []const []const u8) ![]u8 {
386 if (builtin.os == .windows) {386 if (builtin.os.tag == .windows) {
387 return resolveWindows(allocator, paths);387 return resolveWindows(allocator, paths);
388 } else {388 } else {
389 return resolvePosix(allocator, paths);389 return resolvePosix(allocator, paths);
...@@ -400,7 +400,7 @@ pub fn resolve(allocator: *Allocator, paths: []const []const u8) ![]u8 {...@@ -400,7 +400,7 @@ pub fn resolve(allocator: *Allocator, paths: []const []const u8) ![]u8 {
400/// Without performing actual syscalls, resolving `..` could be incorrect.400/// Without performing actual syscalls, resolving `..` could be incorrect.
401pub fn resolveWindows(allocator: *Allocator, paths: []const []const u8) ![]u8 {401pub fn resolveWindows(allocator: *Allocator, paths: []const []const u8) ![]u8 {
402 if (paths.len == 0) {402 if (paths.len == 0) {
403 assert(builtin.os == .windows); // resolveWindows called on non windows can't use getCwd403 assert(builtin.os.tag == .windows); // resolveWindows called on non windows can't use getCwd
404 return process.getCwdAlloc(allocator);404 return process.getCwdAlloc(allocator);
405 }405 }
406406
...@@ -495,7 +495,7 @@ pub fn resolveWindows(allocator: *Allocator, paths: []const []const u8) ![]u8 {...@@ -495,7 +495,7 @@ pub fn resolveWindows(allocator: *Allocator, paths: []const []const u8) ![]u8 {
495 result_disk_designator = result[0..result_index];495 result_disk_designator = result[0..result_index];
496 },496 },
497 WindowsPath.Kind.None => {497 WindowsPath.Kind.None => {
498 assert(builtin.os == .windows); // resolveWindows called on non windows can't use getCwd498 assert(builtin.os.tag == .windows); // resolveWindows called on non windows can't use getCwd
499 const cwd = try process.getCwdAlloc(allocator);499 const cwd = try process.getCwdAlloc(allocator);
500 defer allocator.free(cwd);500 defer allocator.free(cwd);
501 const parsed_cwd = windowsParsePath(cwd);501 const parsed_cwd = windowsParsePath(cwd);
...@@ -510,7 +510,7 @@ pub fn resolveWindows(allocator: *Allocator, paths: []const []const u8) ![]u8 {...@@ -510,7 +510,7 @@ pub fn resolveWindows(allocator: *Allocator, paths: []const []const u8) ![]u8 {
510 },510 },
511 }511 }
512 } else {512 } else {
513 assert(builtin.os == .windows); // resolveWindows called on non windows can't use getCwd513 assert(builtin.os.tag == .windows); // resolveWindows called on non windows can't use getCwd
514 // TODO call get cwd for the result_disk_designator instead of the global one514 // TODO call get cwd for the result_disk_designator instead of the global one
515 const cwd = try process.getCwdAlloc(allocator);515 const cwd = try process.getCwdAlloc(allocator);
516 defer allocator.free(cwd);516 defer allocator.free(cwd);
...@@ -581,7 +581,7 @@ pub fn resolveWindows(allocator: *Allocator, paths: []const []const u8) ![]u8 {...@@ -581,7 +581,7 @@ pub fn resolveWindows(allocator: *Allocator, paths: []const []const u8) ![]u8 {
581/// Without performing actual syscalls, resolving `..` could be incorrect.581/// Without performing actual syscalls, resolving `..` could be incorrect.
582pub fn resolvePosix(allocator: *Allocator, paths: []const []const u8) ![]u8 {582pub fn resolvePosix(allocator: *Allocator, paths: []const []const u8) ![]u8 {
583 if (paths.len == 0) {583 if (paths.len == 0) {
584 assert(builtin.os != .windows); // resolvePosix called on windows can't use getCwd584 assert(builtin.os.tag != .windows); // resolvePosix called on windows can't use getCwd
585 return process.getCwdAlloc(allocator);585 return process.getCwdAlloc(allocator);
586 }586 }
587587
...@@ -603,7 +603,7 @@ pub fn resolvePosix(allocator: *Allocator, paths: []const []const u8) ![]u8 {...@@ -603,7 +603,7 @@ pub fn resolvePosix(allocator: *Allocator, paths: []const []const u8) ![]u8 {
603 if (have_abs) {603 if (have_abs) {
604 result = try allocator.alloc(u8, max_size);604 result = try allocator.alloc(u8, max_size);
605 } else {605 } else {
606 assert(builtin.os != .windows); // resolvePosix called on windows can't use getCwd606 assert(builtin.os.tag != .windows); // resolvePosix called on windows can't use getCwd
607 const cwd = try process.getCwdAlloc(allocator);607 const cwd = try process.getCwdAlloc(allocator);
608 defer allocator.free(cwd);608 defer allocator.free(cwd);
609 result = try allocator.alloc(u8, max_size + cwd.len + 1);609 result = try allocator.alloc(u8, max_size + cwd.len + 1);
...@@ -645,7 +645,7 @@ pub fn resolvePosix(allocator: *Allocator, paths: []const []const u8) ![]u8 {...@@ -645,7 +645,7 @@ pub fn resolvePosix(allocator: *Allocator, paths: []const []const u8) ![]u8 {
645test "resolve" {645test "resolve" {
646 const cwd = try process.getCwdAlloc(testing.allocator);646 const cwd = try process.getCwdAlloc(testing.allocator);
647 defer testing.allocator.free(cwd);647 defer testing.allocator.free(cwd);
648 if (builtin.os == .windows) {648 if (builtin.os.tag == .windows) {
649 if (windowsParsePath(cwd).kind == WindowsPath.Kind.Drive) {649 if (windowsParsePath(cwd).kind == WindowsPath.Kind.Drive) {
650 cwd[0] = asciiUpper(cwd[0]);650 cwd[0] = asciiUpper(cwd[0]);
651 }651 }
...@@ -661,7 +661,7 @@ test "resolveWindows" {...@@ -661,7 +661,7 @@ test "resolveWindows" {
661 // TODO https://github.com/ziglang/zig/issues/3288661 // TODO https://github.com/ziglang/zig/issues/3288
662 return error.SkipZigTest;662 return error.SkipZigTest;
663 }663 }
664 if (builtin.os == .windows) {664 if (builtin.os.tag == .windows) {
665 const cwd = try process.getCwdAlloc(testing.allocator);665 const cwd = try process.getCwdAlloc(testing.allocator);
666 defer testing.allocator.free(cwd);666 defer testing.allocator.free(cwd);
667 const parsed_cwd = windowsParsePath(cwd);667 const parsed_cwd = windowsParsePath(cwd);
...@@ -732,7 +732,7 @@ fn testResolvePosix(paths: []const []const u8, expected: []const u8) !void {...@@ -732,7 +732,7 @@ fn testResolvePosix(paths: []const []const u8, expected: []const u8) !void {
732/// If the path is a file in the current directory (no directory component)732/// If the path is a file in the current directory (no directory component)
733/// then returns null733/// then returns null
734pub fn dirname(path: []const u8) ?[]const u8 {734pub fn dirname(path: []const u8) ?[]const u8 {
735 if (builtin.os == .windows) {735 if (builtin.os.tag == .windows) {
736 return dirnameWindows(path);736 return dirnameWindows(path);
737 } else {737 } else {
738 return dirnamePosix(path);738 return dirnamePosix(path);
...@@ -864,7 +864,7 @@ fn testDirnameWindows(input: []const u8, expected_output: ?[]const u8) void {...@@ -864,7 +864,7 @@ fn testDirnameWindows(input: []const u8, expected_output: ?[]const u8) void {
864}864}
865865
866pub fn basename(path: []const u8) []const u8 {866pub fn basename(path: []const u8) []const u8 {
867 if (builtin.os == .windows) {867 if (builtin.os.tag == .windows) {
868 return basenameWindows(path);868 return basenameWindows(path);
869 } else {869 } else {
870 return basenamePosix(path);870 return basenamePosix(path);
...@@ -980,7 +980,7 @@ fn testBasenameWindows(input: []const u8, expected_output: []const u8) void {...@@ -980,7 +980,7 @@ fn testBasenameWindows(input: []const u8, expected_output: []const u8) void {
980/// string is returned.980/// string is returned.
981/// On Windows this canonicalizes the drive to a capital letter and paths to `\\`.981/// On Windows this canonicalizes the drive to a capital letter and paths to `\\`.
982pub fn relative(allocator: *Allocator, from: []const u8, to: []const u8) ![]u8 {982pub fn relative(allocator: *Allocator, from: []const u8, to: []const u8) ![]u8 {
983 if (builtin.os == .windows) {983 if (builtin.os.tag == .windows) {
984 return relativeWindows(allocator, from, to);984 return relativeWindows(allocator, from, to);
985 } else {985 } else {
986 return relativePosix(allocator, from, to);986 return relativePosix(allocator, from, to);
lib/std/fs/watch.zig+4-4
...@@ -42,7 +42,7 @@ pub fn Watch(comptime V: type) type {...@@ -42,7 +42,7 @@ pub fn Watch(comptime V: type) type {
42 os_data: OsData,42 os_data: OsData,
43 allocator: *Allocator,43 allocator: *Allocator,
4444
45 const OsData = switch (builtin.os) {45 const OsData = switch (builtin.os.tag) {
46 // TODO https://github.com/ziglang/zig/issues/377846 // TODO https://github.com/ziglang/zig/issues/3778
47 .macosx, .freebsd, .netbsd, .dragonfly => KqOsData,47 .macosx, .freebsd, .netbsd, .dragonfly => KqOsData,
48 .linux => LinuxOsData,48 .linux => LinuxOsData,
...@@ -121,7 +121,7 @@ pub fn Watch(comptime V: type) type {...@@ -121,7 +121,7 @@ pub fn Watch(comptime V: type) type {
121 const self = try allocator.create(Self);121 const self = try allocator.create(Self);
122 errdefer allocator.destroy(self);122 errdefer allocator.destroy(self);
123123
124 switch (builtin.os) {124 switch (builtin.os.tag) {
125 .linux => {125 .linux => {
126 const inotify_fd = try os.inotify_init1(os.linux.IN_NONBLOCK | os.linux.IN_CLOEXEC);126 const inotify_fd = try os.inotify_init1(os.linux.IN_NONBLOCK | os.linux.IN_CLOEXEC);
127 errdefer os.close(inotify_fd);127 errdefer os.close(inotify_fd);
...@@ -172,7 +172,7 @@ pub fn Watch(comptime V: type) type {...@@ -172,7 +172,7 @@ pub fn Watch(comptime V: type) type {
172172
173 /// All addFile calls and removeFile calls must have completed.173 /// All addFile calls and removeFile calls must have completed.
174 pub fn deinit(self: *Self) void {174 pub fn deinit(self: *Self) void {
175 switch (builtin.os) {175 switch (builtin.os.tag) {
176 .macosx, .freebsd, .netbsd, .dragonfly => {176 .macosx, .freebsd, .netbsd, .dragonfly => {
177 // TODO we need to cancel the frames before destroying the lock177 // TODO we need to cancel the frames before destroying the lock
178 self.os_data.table_lock.deinit();178 self.os_data.table_lock.deinit();
...@@ -223,7 +223,7 @@ pub fn Watch(comptime V: type) type {...@@ -223,7 +223,7 @@ pub fn Watch(comptime V: type) type {
223 }223 }
224224
225 pub fn addFile(self: *Self, file_path: []const u8, value: V) !?V {225 pub fn addFile(self: *Self, file_path: []const u8, value: V) !?V {
226 switch (builtin.os) {226 switch (builtin.os.tag) {
227 .macosx, .freebsd, .netbsd, .dragonfly => return addFileKEvent(self, file_path, value),227 .macosx, .freebsd, .netbsd, .dragonfly => return addFileKEvent(self, file_path, value),
228 .linux => return addFileLinux(self, file_path, value),228 .linux => return addFileLinux(self, file_path, value),
229 .windows => return addFileWindows(self, file_path, value),229 .windows => return addFileWindows(self, file_path, value),
lib/std/heap.zig+7-7
...@@ -36,7 +36,7 @@ fn cShrink(self: *Allocator, old_mem: []u8, old_align: u29, new_size: usize, new...@@ -36,7 +36,7 @@ fn cShrink(self: *Allocator, old_mem: []u8, old_align: u29, new_size: usize, new
36/// Thread-safe and lock-free.36/// Thread-safe and lock-free.
37pub const page_allocator = if (std.Target.current.isWasm())37pub const page_allocator = if (std.Target.current.isWasm())
38 &wasm_page_allocator_state38 &wasm_page_allocator_state
39else if (std.Target.current.getOs() == .freestanding)39else if (std.Target.current.os.tag == .freestanding)
40 root.os.heap.page_allocator40 root.os.heap.page_allocator
41else41else
42 &page_allocator_state;42 &page_allocator_state;
...@@ -57,7 +57,7 @@ const PageAllocator = struct {...@@ -57,7 +57,7 @@ const PageAllocator = struct {
57 fn alloc(allocator: *Allocator, n: usize, alignment: u29) error{OutOfMemory}![]u8 {57 fn alloc(allocator: *Allocator, n: usize, alignment: u29) error{OutOfMemory}![]u8 {
58 if (n == 0) return &[0]u8{};58 if (n == 0) return &[0]u8{};
5959
60 if (builtin.os == .windows) {60 if (builtin.os.tag == .windows) {
61 const w = os.windows;61 const w = os.windows;
6262
63 // Although officially it's at least aligned to page boundary,63 // Although officially it's at least aligned to page boundary,
...@@ -143,7 +143,7 @@ const PageAllocator = struct {...@@ -143,7 +143,7 @@ const PageAllocator = struct {
143143
144 fn shrink(allocator: *Allocator, old_mem_unaligned: []u8, old_align: u29, new_size: usize, new_align: u29) []u8 {144 fn shrink(allocator: *Allocator, old_mem_unaligned: []u8, old_align: u29, new_size: usize, new_align: u29) []u8 {
145 const old_mem = @alignCast(mem.page_size, old_mem_unaligned);145 const old_mem = @alignCast(mem.page_size, old_mem_unaligned);
146 if (builtin.os == .windows) {146 if (builtin.os.tag == .windows) {
147 const w = os.windows;147 const w = os.windows;
148 if (new_size == 0) {148 if (new_size == 0) {
149 // From the docs:149 // From the docs:
...@@ -183,7 +183,7 @@ const PageAllocator = struct {...@@ -183,7 +183,7 @@ const PageAllocator = struct {
183183
184 fn realloc(allocator: *Allocator, old_mem_unaligned: []u8, old_align: u29, new_size: usize, new_align: u29) ![]u8 {184 fn realloc(allocator: *Allocator, old_mem_unaligned: []u8, old_align: u29, new_size: usize, new_align: u29) ![]u8 {
185 const old_mem = @alignCast(mem.page_size, old_mem_unaligned);185 const old_mem = @alignCast(mem.page_size, old_mem_unaligned);
186 if (builtin.os == .windows) {186 if (builtin.os.tag == .windows) {
187 if (old_mem.len == 0) {187 if (old_mem.len == 0) {
188 return alloc(allocator, new_size, new_align);188 return alloc(allocator, new_size, new_align);
189 }189 }
...@@ -412,7 +412,7 @@ const WasmPageAllocator = struct {...@@ -412,7 +412,7 @@ const WasmPageAllocator = struct {
412 }412 }
413};413};
414414
415pub const HeapAllocator = switch (builtin.os) {415pub const HeapAllocator = switch (builtin.os.tag) {
416 .windows => struct {416 .windows => struct {
417 allocator: Allocator,417 allocator: Allocator,
418 heap_handle: ?HeapHandle,418 heap_handle: ?HeapHandle,
...@@ -855,7 +855,7 @@ test "PageAllocator" {...@@ -855,7 +855,7 @@ test "PageAllocator" {
855 try testAllocatorAlignedShrink(allocator);855 try testAllocatorAlignedShrink(allocator);
856 }856 }
857857
858 if (builtin.os == .windows) {858 if (builtin.os.tag == .windows) {
859 // Trying really large alignment. As mentionned in the implementation,859 // Trying really large alignment. As mentionned in the implementation,
860 // VirtualAlloc returns 64K aligned addresses. We want to make sure860 // VirtualAlloc returns 64K aligned addresses. We want to make sure
861 // PageAllocator works beyond that, as it's not tested by861 // PageAllocator works beyond that, as it's not tested by
...@@ -868,7 +868,7 @@ test "PageAllocator" {...@@ -868,7 +868,7 @@ test "PageAllocator" {
868}868}
869869
870test "HeapAllocator" {870test "HeapAllocator" {
871 if (builtin.os == .windows) {871 if (builtin.os.tag == .windows) {
872 var heap_allocator = HeapAllocator.init();872 var heap_allocator = HeapAllocator.init();
873 defer heap_allocator.deinit();873 defer heap_allocator.deinit();
874874
lib/std/io.zig+3-3
...@@ -35,7 +35,7 @@ else...@@ -35,7 +35,7 @@ else
35pub const is_async = mode != .blocking;35pub const is_async = mode != .blocking;
3636
37fn getStdOutHandle() os.fd_t {37fn getStdOutHandle() os.fd_t {
38 if (builtin.os == .windows) {38 if (builtin.os.tag == .windows) {
39 return os.windows.peb().ProcessParameters.hStdOutput;39 return os.windows.peb().ProcessParameters.hStdOutput;
40 }40 }
4141
...@@ -54,7 +54,7 @@ pub fn getStdOut() File {...@@ -54,7 +54,7 @@ pub fn getStdOut() File {
54}54}
5555
56fn getStdErrHandle() os.fd_t {56fn getStdErrHandle() os.fd_t {
57 if (builtin.os == .windows) {57 if (builtin.os.tag == .windows) {
58 return os.windows.peb().ProcessParameters.hStdError;58 return os.windows.peb().ProcessParameters.hStdError;
59 }59 }
6060
...@@ -74,7 +74,7 @@ pub fn getStdErr() File {...@@ -74,7 +74,7 @@ pub fn getStdErr() File {
74}74}
7575
76fn getStdInHandle() os.fd_t {76fn getStdInHandle() os.fd_t {
77 if (builtin.os == .windows) {77 if (builtin.os.tag == .windows) {
78 return os.windows.peb().ProcessParameters.hStdInput;78 return os.windows.peb().ProcessParameters.hStdInput;
79 }79 }
8080
lib/std/mutex.zig+2-2
...@@ -73,7 +73,7 @@ pub const Mutex = if (builtin.single_threaded)...@@ -73,7 +73,7 @@ pub const Mutex = if (builtin.single_threaded)
73 return self.tryAcquire() orelse @panic("deadlock detected");73 return self.tryAcquire() orelse @panic("deadlock detected");
74 }74 }
75 }75 }
76else if (builtin.os == .windows)76else if (builtin.os.tag == .windows)
77// https://locklessinc.com/articles/keyed_events/77// https://locklessinc.com/articles/keyed_events/
78 extern union {78 extern union {
79 locked: u8,79 locked: u8,
...@@ -161,7 +161,7 @@ else if (builtin.os == .windows)...@@ -161,7 +161,7 @@ else if (builtin.os == .windows)
161 }161 }
162 };162 };
163 }163 }
164else if (builtin.link_libc or builtin.os == .linux)164else if (builtin.link_libc or builtin.os.tag == .linux)
165// stack-based version of https://github.com/Amanieu/parking_lot/blob/master/core/src/word_lock.rs165// stack-based version of https://github.com/Amanieu/parking_lot/blob/master/core/src/word_lock.rs
166 struct {166 struct {
167 state: usize,167 state: usize,
lib/std/net.zig+1-1
...@@ -501,7 +501,7 @@ pub fn getAddressList(allocator: *mem.Allocator, name: []const u8, port: u16) !*...@@ -501,7 +501,7 @@ pub fn getAddressList(allocator: *mem.Allocator, name: []const u8, port: u16) !*
501501
502 return result;502 return result;
503 }503 }
504 if (builtin.os == .linux) {504 if (builtin.os.tag == .linux) {
505 const flags = std.c.AI_NUMERICSERV;505 const flags = std.c.AI_NUMERICSERV;
506 const family = os.AF_UNSPEC;506 const family = os.AF_UNSPEC;
507 var lookup_addrs = std.ArrayList(LookupAddr).init(allocator);507 var lookup_addrs = std.ArrayList(LookupAddr).init(allocator);
lib/std/net/test.zig+2-2
...@@ -63,7 +63,7 @@ test "parse and render IPv4 addresses" {...@@ -63,7 +63,7 @@ test "parse and render IPv4 addresses" {
63}63}
6464
65test "resolve DNS" {65test "resolve DNS" {
66 if (std.builtin.os == .windows) {66 if (std.builtin.os.tag == .windows) {
67 // DNS resolution not implemented on Windows yet.67 // DNS resolution not implemented on Windows yet.
68 return error.SkipZigTest;68 return error.SkipZigTest;
69 }69 }
...@@ -81,7 +81,7 @@ test "resolve DNS" {...@@ -81,7 +81,7 @@ test "resolve DNS" {
81test "listen on a port, send bytes, receive bytes" {81test "listen on a port, send bytes, receive bytes" {
82 if (!std.io.is_async) return error.SkipZigTest;82 if (!std.io.is_async) return error.SkipZigTest;
8383
84 if (std.builtin.os != .linux) {84 if (std.builtin.os.tag != .linux) {
85 // TODO build abstractions for other operating systems85 // TODO build abstractions for other operating systems
86 return error.SkipZigTest;86 return error.SkipZigTest;
87 }87 }
lib/std/os.zig+68-68
...@@ -56,7 +56,7 @@ pub const system = if (@hasDecl(root, "os") and root.os != @This())...@@ -56,7 +56,7 @@ pub const system = if (@hasDecl(root, "os") and root.os != @This())
56 root.os.system56 root.os.system
57else if (builtin.link_libc)57else if (builtin.link_libc)
58 std.c58 std.c
59else switch (builtin.os) {59else switch (builtin.os.tag) {
60 .macosx, .ios, .watchos, .tvos => darwin,60 .macosx, .ios, .watchos, .tvos => darwin,
61 .freebsd => freebsd,61 .freebsd => freebsd,
62 .linux => linux,62 .linux => linux,
...@@ -93,10 +93,10 @@ pub const errno = system.getErrno;...@@ -93,10 +93,10 @@ pub const errno = system.getErrno;
93/// must call `fsync` before `close`.93/// must call `fsync` before `close`.
94/// Note: The Zig standard library does not support POSIX thread cancellation.94/// Note: The Zig standard library does not support POSIX thread cancellation.
95pub fn close(fd: fd_t) void {95pub fn close(fd: fd_t) void {
96 if (builtin.os == .windows) {96 if (builtin.os.tag == .windows) {
97 return windows.CloseHandle(fd);97 return windows.CloseHandle(fd);
98 }98 }
99 if (builtin.os == .wasi) {99 if (builtin.os.tag == .wasi) {
100 _ = wasi.fd_close(fd);100 _ = wasi.fd_close(fd);
101 }101 }
102 if (comptime std.Target.current.isDarwin()) {102 if (comptime std.Target.current.isDarwin()) {
...@@ -121,12 +121,12 @@ pub const GetRandomError = OpenError;...@@ -121,12 +121,12 @@ pub const GetRandomError = OpenError;
121/// appropriate OS-specific library call. Otherwise it uses the zig standard121/// appropriate OS-specific library call. Otherwise it uses the zig standard
122/// library implementation.122/// library implementation.
123pub fn getrandom(buffer: []u8) GetRandomError!void {123pub fn getrandom(buffer: []u8) GetRandomError!void {
124 if (builtin.os == .windows) {124 if (builtin.os.tag == .windows) {
125 return windows.RtlGenRandom(buffer);125 return windows.RtlGenRandom(buffer);
126 }126 }
127 if (builtin.os == .linux or builtin.os == .freebsd) {127 if (builtin.os.tag == .linux or builtin.os.tag == .freebsd) {
128 var buf = buffer;128 var buf = buffer;
129 const use_c = builtin.os != .linux or129 const use_c = builtin.os.tag != .linux or
130 std.c.versionCheck(builtin.Version{ .major = 2, .minor = 25, .patch = 0 }).ok;130 std.c.versionCheck(builtin.Version{ .major = 2, .minor = 25, .patch = 0 }).ok;
131131
132 while (buf.len != 0) {132 while (buf.len != 0) {
...@@ -153,7 +153,7 @@ pub fn getrandom(buffer: []u8) GetRandomError!void {...@@ -153,7 +153,7 @@ pub fn getrandom(buffer: []u8) GetRandomError!void {
153 }153 }
154 return;154 return;
155 }155 }
156 if (builtin.os == .wasi) {156 if (builtin.os.tag == .wasi) {
157 switch (wasi.random_get(buffer.ptr, buffer.len)) {157 switch (wasi.random_get(buffer.ptr, buffer.len)) {
158 0 => return,158 0 => return,
159 else => |err| return unexpectedErrno(err),159 else => |err| return unexpectedErrno(err),
...@@ -188,13 +188,13 @@ pub fn abort() noreturn {...@@ -188,13 +188,13 @@ pub fn abort() noreturn {
188 // MSVCRT abort() sometimes opens a popup window which is undesirable, so188 // MSVCRT abort() sometimes opens a popup window which is undesirable, so
189 // even when linking libc on Windows we use our own abort implementation.189 // even when linking libc on Windows we use our own abort implementation.
190 // See https://github.com/ziglang/zig/issues/2071 for more details.190 // See https://github.com/ziglang/zig/issues/2071 for more details.
191 if (builtin.os == .windows) {191 if (builtin.os.tag == .windows) {
192 if (builtin.mode == .Debug) {192 if (builtin.mode == .Debug) {
193 @breakpoint();193 @breakpoint();
194 }194 }
195 windows.kernel32.ExitProcess(3);195 windows.kernel32.ExitProcess(3);
196 }196 }
197 if (!builtin.link_libc and builtin.os == .linux) {197 if (!builtin.link_libc and builtin.os.tag == .linux) {
198 raise(SIGABRT) catch {};198 raise(SIGABRT) catch {};
199199
200 // TODO the rest of the implementation of abort() from musl libc here200 // TODO the rest of the implementation of abort() from musl libc here
...@@ -202,10 +202,10 @@ pub fn abort() noreturn {...@@ -202,10 +202,10 @@ pub fn abort() noreturn {
202 raise(SIGKILL) catch {};202 raise(SIGKILL) catch {};
203 exit(127);203 exit(127);
204 }204 }
205 if (builtin.os == .uefi) {205 if (builtin.os.tag == .uefi) {
206 exit(0); // TODO choose appropriate exit code206 exit(0); // TODO choose appropriate exit code
207 }207 }
208 if (builtin.os == .wasi) {208 if (builtin.os.tag == .wasi) {
209 @breakpoint();209 @breakpoint();
210 exit(1);210 exit(1);
211 }211 }
...@@ -223,7 +223,7 @@ pub fn raise(sig: u8) RaiseError!void {...@@ -223,7 +223,7 @@ pub fn raise(sig: u8) RaiseError!void {
223 }223 }
224 }224 }
225225
226 if (builtin.os == .linux) {226 if (builtin.os.tag == .linux) {
227 var set: linux.sigset_t = undefined;227 var set: linux.sigset_t = undefined;
228 // block application signals228 // block application signals
229 _ = linux.sigprocmask(SIG_BLOCK, &linux.app_mask, &set);229 _ = linux.sigprocmask(SIG_BLOCK, &linux.app_mask, &set);
...@@ -260,16 +260,16 @@ pub fn exit(status: u8) noreturn {...@@ -260,16 +260,16 @@ pub fn exit(status: u8) noreturn {
260 if (builtin.link_libc) {260 if (builtin.link_libc) {
261 system.exit(status);261 system.exit(status);
262 }262 }
263 if (builtin.os == .windows) {263 if (builtin.os.tag == .windows) {
264 windows.kernel32.ExitProcess(status);264 windows.kernel32.ExitProcess(status);
265 }265 }
266 if (builtin.os == .wasi) {266 if (builtin.os.tag == .wasi) {
267 wasi.proc_exit(status);267 wasi.proc_exit(status);
268 }268 }
269 if (builtin.os == .linux and !builtin.single_threaded) {269 if (builtin.os.tag == .linux and !builtin.single_threaded) {
270 linux.exit_group(status);270 linux.exit_group(status);
271 }271 }
272 if (builtin.os == .uefi) {272 if (builtin.os.tag == .uefi) {
273 // exit() is only avaliable if exitBootServices() has not been called yet.273 // exit() is only avaliable if exitBootServices() has not been called yet.
274 // This call to exit should not fail, so we don't care about its return value.274 // This call to exit should not fail, so we don't care about its return value.
275 if (uefi.system_table.boot_services) |bs| {275 if (uefi.system_table.boot_services) |bs| {
...@@ -299,11 +299,11 @@ pub const ReadError = error{...@@ -299,11 +299,11 @@ pub const ReadError = error{
299/// If the application has a global event loop enabled, EAGAIN is handled299/// If the application has a global event loop enabled, EAGAIN is handled
300/// via the event loop. Otherwise EAGAIN results in error.WouldBlock.300/// via the event loop. Otherwise EAGAIN results in error.WouldBlock.
301pub fn read(fd: fd_t, buf: []u8) ReadError!usize {301pub fn read(fd: fd_t, buf: []u8) ReadError!usize {
302 if (builtin.os == .windows) {302 if (builtin.os.tag == .windows) {
303 return windows.ReadFile(fd, buf, null);303 return windows.ReadFile(fd, buf, null);
304 }304 }
305305
306 if (builtin.os == .wasi and !builtin.link_libc) {306 if (builtin.os.tag == .wasi and !builtin.link_libc) {
307 const iovs = [1]iovec{iovec{307 const iovs = [1]iovec{iovec{
308 .iov_base = buf.ptr,308 .iov_base = buf.ptr,
309 .iov_len = buf.len,309 .iov_len = buf.len,
...@@ -352,7 +352,7 @@ pub fn read(fd: fd_t, buf: []u8) ReadError!usize {...@@ -352,7 +352,7 @@ pub fn read(fd: fd_t, buf: []u8) ReadError!usize {
352/// * Windows352/// * Windows
353/// On these systems, the read races with concurrent writes to the same file descriptor.353/// On these systems, the read races with concurrent writes to the same file descriptor.
354pub fn readv(fd: fd_t, iov: []const iovec) ReadError!usize {354pub fn readv(fd: fd_t, iov: []const iovec) ReadError!usize {
355 if (builtin.os == .windows) {355 if (builtin.os.tag == .windows) {
356 // TODO batch these into parallel requests356 // TODO batch these into parallel requests
357 var off: usize = 0;357 var off: usize = 0;
358 var iov_i: usize = 0;358 var iov_i: usize = 0;
...@@ -406,7 +406,7 @@ pub fn readv(fd: fd_t, iov: []const iovec) ReadError!usize {...@@ -406,7 +406,7 @@ pub fn readv(fd: fd_t, iov: []const iovec) ReadError!usize {
406/// On Windows, if the application has a global event loop enabled, I/O Completion Ports are406/// On Windows, if the application has a global event loop enabled, I/O Completion Ports are
407/// used to perform the I/O. `error.WouldBlock` is not possible on Windows.407/// used to perform the I/O. `error.WouldBlock` is not possible on Windows.
408pub fn pread(fd: fd_t, buf: []u8, offset: u64) ReadError!usize {408pub fn pread(fd: fd_t, buf: []u8, offset: u64) ReadError!usize {
409 if (builtin.os == .windows) {409 if (builtin.os.tag == .windows) {
410 return windows.ReadFile(fd, buf, offset);410 return windows.ReadFile(fd, buf, offset);
411 }411 }
412412
...@@ -493,7 +493,7 @@ pub fn preadv(fd: fd_t, iov: []const iovec, offset: u64) ReadError!usize {...@@ -493,7 +493,7 @@ pub fn preadv(fd: fd_t, iov: []const iovec, offset: u64) ReadError!usize {
493 }493 }
494 }494 }
495495
496 if (builtin.os == .windows) {496 if (builtin.os.tag == .windows) {
497 // TODO batch these into parallel requests497 // TODO batch these into parallel requests
498 var off: usize = 0;498 var off: usize = 0;
499 var iov_i: usize = 0;499 var iov_i: usize = 0;
...@@ -557,11 +557,11 @@ pub const WriteError = error{...@@ -557,11 +557,11 @@ pub const WriteError = error{
557/// If the application has a global event loop enabled, EAGAIN is handled557/// If the application has a global event loop enabled, EAGAIN is handled
558/// via the event loop. Otherwise EAGAIN results in error.WouldBlock.558/// via the event loop. Otherwise EAGAIN results in error.WouldBlock.
559pub fn write(fd: fd_t, bytes: []const u8) WriteError!void {559pub fn write(fd: fd_t, bytes: []const u8) WriteError!void {
560 if (builtin.os == .windows) {560 if (builtin.os.tag == .windows) {
561 return windows.WriteFile(fd, bytes, null);561 return windows.WriteFile(fd, bytes, null);
562 }562 }
563563
564 if (builtin.os == .wasi and !builtin.link_libc) {564 if (builtin.os.tag == .wasi and !builtin.link_libc) {
565 const ciovs = [1]iovec_const{iovec_const{565 const ciovs = [1]iovec_const{iovec_const{
566 .iov_base = bytes.ptr,566 .iov_base = bytes.ptr,
567 .iov_len = bytes.len,567 .iov_len = bytes.len,
...@@ -1129,7 +1129,7 @@ pub fn getenv(key: []const u8) ?[]const u8 {...@@ -1129,7 +1129,7 @@ pub fn getenv(key: []const u8) ?[]const u8 {
1129 }1129 }
1130 return null;1130 return null;
1131 }1131 }
1132 if (builtin.os == .windows) {1132 if (builtin.os.tag == .windows) {
1133 @compileError("std.os.getenv is unavailable for Windows because environment string is in WTF-16 format. See std.process.getEnvVarOwned for cross-platform API or std.os.getenvW for Windows-specific API.");1133 @compileError("std.os.getenv is unavailable for Windows because environment string is in WTF-16 format. See std.process.getEnvVarOwned for cross-platform API or std.os.getenvW for Windows-specific API.");
1134 }1134 }
1135 // TODO see https://github.com/ziglang/zig/issues/45241135 // TODO see https://github.com/ziglang/zig/issues/4524
...@@ -1158,7 +1158,7 @@ pub fn getenvZ(key: [*:0]const u8) ?[]const u8 {...@@ -1158,7 +1158,7 @@ pub fn getenvZ(key: [*:0]const u8) ?[]const u8 {
1158 const value = system.getenv(key) orelse return null;1158 const value = system.getenv(key) orelse return null;
1159 return mem.toSliceConst(u8, value);1159 return mem.toSliceConst(u8, value);
1160 }1160 }
1161 if (builtin.os == .windows) {1161 if (builtin.os.tag == .windows) {
1162 @compileError("std.os.getenvZ is unavailable for Windows because environment string is in WTF-16 format. See std.process.getEnvVarOwned for cross-platform API or std.os.getenvW for Windows-specific API.");1162 @compileError("std.os.getenvZ is unavailable for Windows because environment string is in WTF-16 format. See std.process.getEnvVarOwned for cross-platform API or std.os.getenvW for Windows-specific API.");
1163 }1163 }
1164 return getenv(mem.toSliceConst(u8, key));1164 return getenv(mem.toSliceConst(u8, key));
...@@ -1167,7 +1167,7 @@ pub fn getenvZ(key: [*:0]const u8) ?[]const u8 {...@@ -1167,7 +1167,7 @@ pub fn getenvZ(key: [*:0]const u8) ?[]const u8 {
1167/// Windows-only. Get an environment variable with a null-terminated, WTF-16 encoded name.1167/// Windows-only. Get an environment variable with a null-terminated, WTF-16 encoded name.
1168/// See also `getenv`.1168/// See also `getenv`.
1169pub fn getenvW(key: [*:0]const u16) ?[:0]const u16 {1169pub fn getenvW(key: [*:0]const u16) ?[:0]const u16 {
1170 if (builtin.os != .windows) {1170 if (builtin.os.tag != .windows) {
1171 @compileError("std.os.getenvW is a Windows-only API");1171 @compileError("std.os.getenvW is a Windows-only API");
1172 }1172 }
1173 const key_slice = mem.toSliceConst(u16, key);1173 const key_slice = mem.toSliceConst(u16, key);
...@@ -1199,7 +1199,7 @@ pub const GetCwdError = error{...@@ -1199,7 +1199,7 @@ pub const GetCwdError = error{
11991199
1200/// The result is a slice of out_buffer, indexed from 0.1200/// The result is a slice of out_buffer, indexed from 0.
1201pub fn getcwd(out_buffer: []u8) GetCwdError![]u8 {1201pub fn getcwd(out_buffer: []u8) GetCwdError![]u8 {
1202 if (builtin.os == .windows) {1202 if (builtin.os.tag == .windows) {
1203 return windows.GetCurrentDirectory(out_buffer);1203 return windows.GetCurrentDirectory(out_buffer);
1204 }1204 }
12051205
...@@ -1240,7 +1240,7 @@ pub const SymLinkError = error{...@@ -1240,7 +1240,7 @@ pub const SymLinkError = error{
1240/// If `sym_link_path` exists, it will not be overwritten.1240/// If `sym_link_path` exists, it will not be overwritten.
1241/// See also `symlinkC` and `symlinkW`.1241/// See also `symlinkC` and `symlinkW`.
1242pub fn symlink(target_path: []const u8, sym_link_path: []const u8) SymLinkError!void {1242pub fn symlink(target_path: []const u8, sym_link_path: []const u8) SymLinkError!void {
1243 if (builtin.os == .windows) {1243 if (builtin.os.tag == .windows) {
1244 const target_path_w = try windows.sliceToPrefixedFileW(target_path);1244 const target_path_w = try windows.sliceToPrefixedFileW(target_path);
1245 const sym_link_path_w = try windows.sliceToPrefixedFileW(sym_link_path);1245 const sym_link_path_w = try windows.sliceToPrefixedFileW(sym_link_path);
1246 return windows.CreateSymbolicLinkW(&sym_link_path_w, &target_path_w, 0);1246 return windows.CreateSymbolicLinkW(&sym_link_path_w, &target_path_w, 0);
...@@ -1254,7 +1254,7 @@ pub fn symlink(target_path: []const u8, sym_link_path: []const u8) SymLinkError!...@@ -1254,7 +1254,7 @@ pub fn symlink(target_path: []const u8, sym_link_path: []const u8) SymLinkError!
1254/// This is the same as `symlink` except the parameters are null-terminated pointers.1254/// This is the same as `symlink` except the parameters are null-terminated pointers.
1255/// See also `symlink`.1255/// See also `symlink`.
1256pub fn symlinkC(target_path: [*:0]const u8, sym_link_path: [*:0]const u8) SymLinkError!void {1256pub fn symlinkC(target_path: [*:0]const u8, sym_link_path: [*:0]const u8) SymLinkError!void {
1257 if (builtin.os == .windows) {1257 if (builtin.os.tag == .windows) {
1258 const target_path_w = try windows.cStrToPrefixedFileW(target_path);1258 const target_path_w = try windows.cStrToPrefixedFileW(target_path);
1259 const sym_link_path_w = try windows.cStrToPrefixedFileW(sym_link_path);1259 const sym_link_path_w = try windows.cStrToPrefixedFileW(sym_link_path);
1260 return windows.CreateSymbolicLinkW(&sym_link_path_w, &target_path_w, 0);1260 return windows.CreateSymbolicLinkW(&sym_link_path_w, &target_path_w, 0);
...@@ -1329,7 +1329,7 @@ pub const UnlinkError = error{...@@ -1329,7 +1329,7 @@ pub const UnlinkError = error{
1329/// Delete a name and possibly the file it refers to.1329/// Delete a name and possibly the file it refers to.
1330/// See also `unlinkC`.1330/// See also `unlinkC`.
1331pub fn unlink(file_path: []const u8) UnlinkError!void {1331pub fn unlink(file_path: []const u8) UnlinkError!void {
1332 if (builtin.os == .windows) {1332 if (builtin.os.tag == .windows) {
1333 const file_path_w = try windows.sliceToPrefixedFileW(file_path);1333 const file_path_w = try windows.sliceToPrefixedFileW(file_path);
1334 return windows.DeleteFileW(&file_path_w);1334 return windows.DeleteFileW(&file_path_w);
1335 } else {1335 } else {
...@@ -1340,7 +1340,7 @@ pub fn unlink(file_path: []const u8) UnlinkError!void {...@@ -1340,7 +1340,7 @@ pub fn unlink(file_path: []const u8) UnlinkError!void {
13401340
1341/// Same as `unlink` except the parameter is a null terminated UTF8-encoded string.1341/// Same as `unlink` except the parameter is a null terminated UTF8-encoded string.
1342pub fn unlinkC(file_path: [*:0]const u8) UnlinkError!void {1342pub fn unlinkC(file_path: [*:0]const u8) UnlinkError!void {
1343 if (builtin.os == .windows) {1343 if (builtin.os.tag == .windows) {
1344 const file_path_w = try windows.cStrToPrefixedFileW(file_path);1344 const file_path_w = try windows.cStrToPrefixedFileW(file_path);
1345 return windows.DeleteFileW(&file_path_w);1345 return windows.DeleteFileW(&file_path_w);
1346 }1346 }
...@@ -1372,7 +1372,7 @@ pub const UnlinkatError = UnlinkError || error{...@@ -1372,7 +1372,7 @@ pub const UnlinkatError = UnlinkError || error{
1372/// Asserts that the path parameter has no null bytes.1372/// Asserts that the path parameter has no null bytes.
1373pub fn unlinkat(dirfd: fd_t, file_path: []const u8, flags: u32) UnlinkatError!void {1373pub fn unlinkat(dirfd: fd_t, file_path: []const u8, flags: u32) UnlinkatError!void {
1374 if (std.debug.runtime_safety) for (file_path) |byte| assert(byte != 0);1374 if (std.debug.runtime_safety) for (file_path) |byte| assert(byte != 0);
1375 if (builtin.os == .windows) {1375 if (builtin.os.tag == .windows) {
1376 const file_path_w = try windows.sliceToPrefixedFileW(file_path);1376 const file_path_w = try windows.sliceToPrefixedFileW(file_path);
1377 return unlinkatW(dirfd, &file_path_w, flags);1377 return unlinkatW(dirfd, &file_path_w, flags);
1378 }1378 }
...@@ -1382,7 +1382,7 @@ pub fn unlinkat(dirfd: fd_t, file_path: []const u8, flags: u32) UnlinkatError!vo...@@ -1382,7 +1382,7 @@ pub fn unlinkat(dirfd: fd_t, file_path: []const u8, flags: u32) UnlinkatError!vo
13821382
1383/// Same as `unlinkat` but `file_path` is a null-terminated string.1383/// Same as `unlinkat` but `file_path` is a null-terminated string.
1384pub fn unlinkatC(dirfd: fd_t, file_path_c: [*:0]const u8, flags: u32) UnlinkatError!void {1384pub fn unlinkatC(dirfd: fd_t, file_path_c: [*:0]const u8, flags: u32) UnlinkatError!void {
1385 if (builtin.os == .windows) {1385 if (builtin.os.tag == .windows) {
1386 const file_path_w = try windows.cStrToPrefixedFileW(file_path_c);1386 const file_path_w = try windows.cStrToPrefixedFileW(file_path_c);
1387 return unlinkatW(dirfd, &file_path_w, flags);1387 return unlinkatW(dirfd, &file_path_w, flags);
1388 }1388 }
...@@ -1493,7 +1493,7 @@ const RenameError = error{...@@ -1493,7 +1493,7 @@ const RenameError = error{
14931493
1494/// Change the name or location of a file.1494/// Change the name or location of a file.
1495pub fn rename(old_path: []const u8, new_path: []const u8) RenameError!void {1495pub fn rename(old_path: []const u8, new_path: []const u8) RenameError!void {
1496 if (builtin.os == .windows) {1496 if (builtin.os.tag == .windows) {
1497 const old_path_w = try windows.sliceToPrefixedFileW(old_path);1497 const old_path_w = try windows.sliceToPrefixedFileW(old_path);
1498 const new_path_w = try windows.sliceToPrefixedFileW(new_path);1498 const new_path_w = try windows.sliceToPrefixedFileW(new_path);
1499 return renameW(&old_path_w, &new_path_w);1499 return renameW(&old_path_w, &new_path_w);
...@@ -1506,7 +1506,7 @@ pub fn rename(old_path: []const u8, new_path: []const u8) RenameError!void {...@@ -1506,7 +1506,7 @@ pub fn rename(old_path: []const u8, new_path: []const u8) RenameError!void {
15061506
1507/// Same as `rename` except the parameters are null-terminated byte arrays.1507/// Same as `rename` except the parameters are null-terminated byte arrays.
1508pub fn renameC(old_path: [*:0]const u8, new_path: [*:0]const u8) RenameError!void {1508pub fn renameC(old_path: [*:0]const u8, new_path: [*:0]const u8) RenameError!void {
1509 if (builtin.os == .windows) {1509 if (builtin.os.tag == .windows) {
1510 const old_path_w = try windows.cStrToPrefixedFileW(old_path);1510 const old_path_w = try windows.cStrToPrefixedFileW(old_path);
1511 const new_path_w = try windows.cStrToPrefixedFileW(new_path);1511 const new_path_w = try windows.cStrToPrefixedFileW(new_path);
1512 return renameW(&old_path_w, &new_path_w);1512 return renameW(&old_path_w, &new_path_w);
...@@ -1561,7 +1561,7 @@ pub const MakeDirError = error{...@@ -1561,7 +1561,7 @@ pub const MakeDirError = error{
1561/// Create a directory.1561/// Create a directory.
1562/// `mode` is ignored on Windows.1562/// `mode` is ignored on Windows.
1563pub fn mkdir(dir_path: []const u8, mode: u32) MakeDirError!void {1563pub fn mkdir(dir_path: []const u8, mode: u32) MakeDirError!void {
1564 if (builtin.os == .windows) {1564 if (builtin.os.tag == .windows) {
1565 const dir_path_w = try windows.sliceToPrefixedFileW(dir_path);1565 const dir_path_w = try windows.sliceToPrefixedFileW(dir_path);
1566 return windows.CreateDirectoryW(&dir_path_w, null);1566 return windows.CreateDirectoryW(&dir_path_w, null);
1567 } else {1567 } else {
...@@ -1572,7 +1572,7 @@ pub fn mkdir(dir_path: []const u8, mode: u32) MakeDirError!void {...@@ -1572,7 +1572,7 @@ pub fn mkdir(dir_path: []const u8, mode: u32) MakeDirError!void {
15721572
1573/// Same as `mkdir` but the parameter is a null-terminated UTF8-encoded string.1573/// Same as `mkdir` but the parameter is a null-terminated UTF8-encoded string.
1574pub fn mkdirC(dir_path: [*:0]const u8, mode: u32) MakeDirError!void {1574pub fn mkdirC(dir_path: [*:0]const u8, mode: u32) MakeDirError!void {
1575 if (builtin.os == .windows) {1575 if (builtin.os.tag == .windows) {
1576 const dir_path_w = try windows.cStrToPrefixedFileW(dir_path);1576 const dir_path_w = try windows.cStrToPrefixedFileW(dir_path);
1577 return windows.CreateDirectoryW(&dir_path_w, null);1577 return windows.CreateDirectoryW(&dir_path_w, null);
1578 }1578 }
...@@ -1611,7 +1611,7 @@ pub const DeleteDirError = error{...@@ -1611,7 +1611,7 @@ pub const DeleteDirError = error{
16111611
1612/// Deletes an empty directory.1612/// Deletes an empty directory.
1613pub fn rmdir(dir_path: []const u8) DeleteDirError!void {1613pub fn rmdir(dir_path: []const u8) DeleteDirError!void {
1614 if (builtin.os == .windows) {1614 if (builtin.os.tag == .windows) {
1615 const dir_path_w = try windows.sliceToPrefixedFileW(dir_path);1615 const dir_path_w = try windows.sliceToPrefixedFileW(dir_path);
1616 return windows.RemoveDirectoryW(&dir_path_w);1616 return windows.RemoveDirectoryW(&dir_path_w);
1617 } else {1617 } else {
...@@ -1622,7 +1622,7 @@ pub fn rmdir(dir_path: []const u8) DeleteDirError!void {...@@ -1622,7 +1622,7 @@ pub fn rmdir(dir_path: []const u8) DeleteDirError!void {
16221622
1623/// Same as `rmdir` except the parameter is null-terminated.1623/// Same as `rmdir` except the parameter is null-terminated.
1624pub fn rmdirC(dir_path: [*:0]const u8) DeleteDirError!void {1624pub fn rmdirC(dir_path: [*:0]const u8) DeleteDirError!void {
1625 if (builtin.os == .windows) {1625 if (builtin.os.tag == .windows) {
1626 const dir_path_w = try windows.cStrToPrefixedFileW(dir_path);1626 const dir_path_w = try windows.cStrToPrefixedFileW(dir_path);
1627 return windows.RemoveDirectoryW(&dir_path_w);1627 return windows.RemoveDirectoryW(&dir_path_w);
1628 }1628 }
...@@ -1658,7 +1658,7 @@ pub const ChangeCurDirError = error{...@@ -1658,7 +1658,7 @@ pub const ChangeCurDirError = error{
1658/// Changes the current working directory of the calling process.1658/// Changes the current working directory of the calling process.
1659/// `dir_path` is recommended to be a UTF-8 encoded string.1659/// `dir_path` is recommended to be a UTF-8 encoded string.
1660pub fn chdir(dir_path: []const u8) ChangeCurDirError!void {1660pub fn chdir(dir_path: []const u8) ChangeCurDirError!void {
1661 if (builtin.os == .windows) {1661 if (builtin.os.tag == .windows) {
1662 const dir_path_w = try windows.sliceToPrefixedFileW(dir_path);1662 const dir_path_w = try windows.sliceToPrefixedFileW(dir_path);
1663 @compileError("TODO implement chdir for Windows");1663 @compileError("TODO implement chdir for Windows");
1664 } else {1664 } else {
...@@ -1669,7 +1669,7 @@ pub fn chdir(dir_path: []const u8) ChangeCurDirError!void {...@@ -1669,7 +1669,7 @@ pub fn chdir(dir_path: []const u8) ChangeCurDirError!void {
16691669
1670/// Same as `chdir` except the parameter is null-terminated.1670/// Same as `chdir` except the parameter is null-terminated.
1671pub fn chdirC(dir_path: [*:0]const u8) ChangeCurDirError!void {1671pub fn chdirC(dir_path: [*:0]const u8) ChangeCurDirError!void {
1672 if (builtin.os == .windows) {1672 if (builtin.os.tag == .windows) {
1673 const dir_path_w = try windows.cStrToPrefixedFileW(dir_path);1673 const dir_path_w = try windows.cStrToPrefixedFileW(dir_path);
1674 @compileError("TODO implement chdir for Windows");1674 @compileError("TODO implement chdir for Windows");
1675 }1675 }
...@@ -1700,7 +1700,7 @@ pub const ReadLinkError = error{...@@ -1700,7 +1700,7 @@ pub const ReadLinkError = error{
1700/// Read value of a symbolic link.1700/// Read value of a symbolic link.
1701/// The return value is a slice of `out_buffer` from index 0.1701/// The return value is a slice of `out_buffer` from index 0.
1702pub fn readlink(file_path: []const u8, out_buffer: []u8) ReadLinkError![]u8 {1702pub fn readlink(file_path: []const u8, out_buffer: []u8) ReadLinkError![]u8 {
1703 if (builtin.os == .windows) {1703 if (builtin.os.tag == .windows) {
1704 const file_path_w = try windows.sliceToPrefixedFileW(file_path);1704 const file_path_w = try windows.sliceToPrefixedFileW(file_path);
1705 @compileError("TODO implement readlink for Windows");1705 @compileError("TODO implement readlink for Windows");
1706 } else {1706 } else {
...@@ -1711,7 +1711,7 @@ pub fn readlink(file_path: []const u8, out_buffer: []u8) ReadLinkError![]u8 {...@@ -1711,7 +1711,7 @@ pub fn readlink(file_path: []const u8, out_buffer: []u8) ReadLinkError![]u8 {
17111711
1712/// Same as `readlink` except `file_path` is null-terminated.1712/// Same as `readlink` except `file_path` is null-terminated.
1713pub fn readlinkC(file_path: [*:0]const u8, out_buffer: []u8) ReadLinkError![]u8 {1713pub fn readlinkC(file_path: [*:0]const u8, out_buffer: []u8) ReadLinkError![]u8 {
1714 if (builtin.os == .windows) {1714 if (builtin.os.tag == .windows) {
1715 const file_path_w = try windows.cStrToPrefixedFileW(file_path);1715 const file_path_w = try windows.cStrToPrefixedFileW(file_path);
1716 @compileError("TODO implement readlink for Windows");1716 @compileError("TODO implement readlink for Windows");
1717 }1717 }
...@@ -1732,7 +1732,7 @@ pub fn readlinkC(file_path: [*:0]const u8, out_buffer: []u8) ReadLinkError![]u8...@@ -1732,7 +1732,7 @@ pub fn readlinkC(file_path: [*:0]const u8, out_buffer: []u8) ReadLinkError![]u8
1732}1732}
17331733
1734pub fn readlinkatC(dirfd: fd_t, file_path: [*:0]const u8, out_buffer: []u8) ReadLinkError![]u8 {1734pub fn readlinkatC(dirfd: fd_t, file_path: [*:0]const u8, out_buffer: []u8) ReadLinkError![]u8 {
1735 if (builtin.os == .windows) {1735 if (builtin.os.tag == .windows) {
1736 const file_path_w = try windows.cStrToPrefixedFileW(file_path);1736 const file_path_w = try windows.cStrToPrefixedFileW(file_path);
1737 @compileError("TODO implement readlink for Windows");1737 @compileError("TODO implement readlink for Windows");
1738 }1738 }
...@@ -1800,7 +1800,7 @@ pub fn setregid(rgid: u32, egid: u32) SetIdError!void {...@@ -1800,7 +1800,7 @@ pub fn setregid(rgid: u32, egid: u32) SetIdError!void {
18001800
1801/// Test whether a file descriptor refers to a terminal.1801/// Test whether a file descriptor refers to a terminal.
1802pub fn isatty(handle: fd_t) bool {1802pub fn isatty(handle: fd_t) bool {
1803 if (builtin.os == .windows) {1803 if (builtin.os.tag == .windows) {
1804 if (isCygwinPty(handle))1804 if (isCygwinPty(handle))
1805 return true;1805 return true;
18061806
...@@ -1810,7 +1810,7 @@ pub fn isatty(handle: fd_t) bool {...@@ -1810,7 +1810,7 @@ pub fn isatty(handle: fd_t) bool {
1810 if (builtin.link_libc) {1810 if (builtin.link_libc) {
1811 return system.isatty(handle) != 0;1811 return system.isatty(handle) != 0;
1812 }1812 }
1813 if (builtin.os == .wasi) {1813 if (builtin.os.tag == .wasi) {
1814 var statbuf: fdstat_t = undefined;1814 var statbuf: fdstat_t = undefined;
1815 const err = system.fd_fdstat_get(handle, &statbuf);1815 const err = system.fd_fdstat_get(handle, &statbuf);
1816 if (err != 0) {1816 if (err != 0) {
...@@ -1828,7 +1828,7 @@ pub fn isatty(handle: fd_t) bool {...@@ -1828,7 +1828,7 @@ pub fn isatty(handle: fd_t) bool {
18281828
1829 return true;1829 return true;
1830 }1830 }
1831 if (builtin.os == .linux) {1831 if (builtin.os.tag == .linux) {
1832 var wsz: linux.winsize = undefined;1832 var wsz: linux.winsize = undefined;
1833 return linux.syscall3(linux.SYS_ioctl, @bitCast(usize, @as(isize, handle)), linux.TIOCGWINSZ, @ptrToInt(&wsz)) == 0;1833 return linux.syscall3(linux.SYS_ioctl, @bitCast(usize, @as(isize, handle)), linux.TIOCGWINSZ, @ptrToInt(&wsz)) == 0;
1834 }1834 }
...@@ -1836,7 +1836,7 @@ pub fn isatty(handle: fd_t) bool {...@@ -1836,7 +1836,7 @@ pub fn isatty(handle: fd_t) bool {
1836}1836}
18371837
1838pub fn isCygwinPty(handle: fd_t) bool {1838pub fn isCygwinPty(handle: fd_t) bool {
1839 if (builtin.os != .windows) return false;1839 if (builtin.os.tag != .windows) return false;
18401840
1841 const size = @sizeOf(windows.FILE_NAME_INFO);1841 const size = @sizeOf(windows.FILE_NAME_INFO);
1842 var name_info_bytes align(@alignOf(windows.FILE_NAME_INFO)) = [_]u8{0} ** (size + windows.MAX_PATH);1842 var name_info_bytes align(@alignOf(windows.FILE_NAME_INFO)) = [_]u8{0} ** (size + windows.MAX_PATH);
...@@ -2589,7 +2589,7 @@ pub const AccessError = error{...@@ -2589,7 +2589,7 @@ pub const AccessError = error{
2589/// check user's permissions for a file2589/// check user's permissions for a file
2590/// TODO currently this assumes `mode` is `F_OK` on Windows.2590/// TODO currently this assumes `mode` is `F_OK` on Windows.
2591pub fn access(path: []const u8, mode: u32) AccessError!void {2591pub fn access(path: []const u8, mode: u32) AccessError!void {
2592 if (builtin.os == .windows) {2592 if (builtin.os.tag == .windows) {
2593 const path_w = try windows.sliceToPrefixedFileW(path);2593 const path_w = try windows.sliceToPrefixedFileW(path);
2594 _ = try windows.GetFileAttributesW(&path_w);2594 _ = try windows.GetFileAttributesW(&path_w);
2595 return;2595 return;
...@@ -2603,7 +2603,7 @@ pub const accessC = accessZ;...@@ -2603,7 +2603,7 @@ pub const accessC = accessZ;
26032603
2604/// Same as `access` except `path` is null-terminated.2604/// Same as `access` except `path` is null-terminated.
2605pub fn accessZ(path: [*:0]const u8, mode: u32) AccessError!void {2605pub fn accessZ(path: [*:0]const u8, mode: u32) AccessError!void {
2606 if (builtin.os == .windows) {2606 if (builtin.os.tag == .windows) {
2607 const path_w = try windows.cStrToPrefixedFileW(path);2607 const path_w = try windows.cStrToPrefixedFileW(path);
2608 _ = try windows.GetFileAttributesW(&path_w);2608 _ = try windows.GetFileAttributesW(&path_w);
2609 return;2609 return;
...@@ -2644,7 +2644,7 @@ pub fn accessW(path: [*:0]const u16, mode: u32) windows.GetFileAttributesError!v...@@ -2644,7 +2644,7 @@ pub fn accessW(path: [*:0]const u16, mode: u32) windows.GetFileAttributesError!v
2644/// Check user's permissions for a file, based on an open directory handle.2644/// Check user's permissions for a file, based on an open directory handle.
2645/// TODO currently this ignores `mode` and `flags` on Windows.2645/// TODO currently this ignores `mode` and `flags` on Windows.
2646pub fn faccessat(dirfd: fd_t, path: []const u8, mode: u32, flags: u32) AccessError!void {2646pub fn faccessat(dirfd: fd_t, path: []const u8, mode: u32, flags: u32) AccessError!void {
2647 if (builtin.os == .windows) {2647 if (builtin.os.tag == .windows) {
2648 const path_w = try windows.sliceToPrefixedFileW(path);2648 const path_w = try windows.sliceToPrefixedFileW(path);
2649 return faccessatW(dirfd, &path_w, mode, flags);2649 return faccessatW(dirfd, &path_w, mode, flags);
2650 }2650 }
...@@ -2654,7 +2654,7 @@ pub fn faccessat(dirfd: fd_t, path: []const u8, mode: u32, flags: u32) AccessErr...@@ -2654,7 +2654,7 @@ pub fn faccessat(dirfd: fd_t, path: []const u8, mode: u32, flags: u32) AccessErr
26542654
2655/// Same as `faccessat` except the path parameter is null-terminated.2655/// Same as `faccessat` except the path parameter is null-terminated.
2656pub fn faccessatZ(dirfd: fd_t, path: [*:0]const u8, mode: u32, flags: u32) AccessError!void {2656pub fn faccessatZ(dirfd: fd_t, path: [*:0]const u8, mode: u32, flags: u32) AccessError!void {
2657 if (builtin.os == .windows) {2657 if (builtin.os.tag == .windows) {
2658 const path_w = try windows.cStrToPrefixedFileW(path);2658 const path_w = try windows.cStrToPrefixedFileW(path);
2659 return faccessatW(dirfd, &path_w, mode, flags);2659 return faccessatW(dirfd, &path_w, mode, flags);
2660 }2660 }
...@@ -2811,7 +2811,7 @@ pub const SeekError = error{Unseekable} || UnexpectedError;...@@ -2811,7 +2811,7 @@ pub const SeekError = error{Unseekable} || UnexpectedError;
28112811
2812/// Repositions read/write file offset relative to the beginning.2812/// Repositions read/write file offset relative to the beginning.
2813pub fn lseek_SET(fd: fd_t, offset: u64) SeekError!void {2813pub fn lseek_SET(fd: fd_t, offset: u64) SeekError!void {
2814 if (builtin.os == .linux and !builtin.link_libc and @sizeOf(usize) == 4) {2814 if (builtin.os.tag == .linux and !builtin.link_libc and @sizeOf(usize) == 4) {
2815 var result: u64 = undefined;2815 var result: u64 = undefined;
2816 switch (errno(system.llseek(fd, offset, &result, SEEK_SET))) {2816 switch (errno(system.llseek(fd, offset, &result, SEEK_SET))) {
2817 0 => return,2817 0 => return,
...@@ -2823,7 +2823,7 @@ pub fn lseek_SET(fd: fd_t, offset: u64) SeekError!void {...@@ -2823,7 +2823,7 @@ pub fn lseek_SET(fd: fd_t, offset: u64) SeekError!void {
2823 else => |err| return unexpectedErrno(err),2823 else => |err| return unexpectedErrno(err),
2824 }2824 }
2825 }2825 }
2826 if (builtin.os == .windows) {2826 if (builtin.os.tag == .windows) {
2827 return windows.SetFilePointerEx_BEGIN(fd, offset);2827 return windows.SetFilePointerEx_BEGIN(fd, offset);
2828 }2828 }
2829 const ipos = @bitCast(i64, offset); // the OS treats this as unsigned2829 const ipos = @bitCast(i64, offset); // the OS treats this as unsigned
...@@ -2840,7 +2840,7 @@ pub fn lseek_SET(fd: fd_t, offset: u64) SeekError!void {...@@ -2840,7 +2840,7 @@ pub fn lseek_SET(fd: fd_t, offset: u64) SeekError!void {
28402840
2841/// Repositions read/write file offset relative to the current offset.2841/// Repositions read/write file offset relative to the current offset.
2842pub fn lseek_CUR(fd: fd_t, offset: i64) SeekError!void {2842pub fn lseek_CUR(fd: fd_t, offset: i64) SeekError!void {
2843 if (builtin.os == .linux and !builtin.link_libc and @sizeOf(usize) == 4) {2843 if (builtin.os.tag == .linux and !builtin.link_libc and @sizeOf(usize) == 4) {
2844 var result: u64 = undefined;2844 var result: u64 = undefined;
2845 switch (errno(system.llseek(fd, @bitCast(u64, offset), &result, SEEK_CUR))) {2845 switch (errno(system.llseek(fd, @bitCast(u64, offset), &result, SEEK_CUR))) {
2846 0 => return,2846 0 => return,
...@@ -2852,7 +2852,7 @@ pub fn lseek_CUR(fd: fd_t, offset: i64) SeekError!void {...@@ -2852,7 +2852,7 @@ pub fn lseek_CUR(fd: fd_t, offset: i64) SeekError!void {
2852 else => |err| return unexpectedErrno(err),2852 else => |err| return unexpectedErrno(err),
2853 }2853 }
2854 }2854 }
2855 if (builtin.os == .windows) {2855 if (builtin.os.tag == .windows) {
2856 return windows.SetFilePointerEx_CURRENT(fd, offset);2856 return windows.SetFilePointerEx_CURRENT(fd, offset);
2857 }2857 }
2858 switch (errno(system.lseek(fd, offset, SEEK_CUR))) {2858 switch (errno(system.lseek(fd, offset, SEEK_CUR))) {
...@@ -2868,7 +2868,7 @@ pub fn lseek_CUR(fd: fd_t, offset: i64) SeekError!void {...@@ -2868,7 +2868,7 @@ pub fn lseek_CUR(fd: fd_t, offset: i64) SeekError!void {
28682868
2869/// Repositions read/write file offset relative to the end.2869/// Repositions read/write file offset relative to the end.
2870pub fn lseek_END(fd: fd_t, offset: i64) SeekError!void {2870pub fn lseek_END(fd: fd_t, offset: i64) SeekError!void {
2871 if (builtin.os == .linux and !builtin.link_libc and @sizeOf(usize) == 4) {2871 if (builtin.os.tag == .linux and !builtin.link_libc and @sizeOf(usize) == 4) {
2872 var result: u64 = undefined;2872 var result: u64 = undefined;
2873 switch (errno(system.llseek(fd, @bitCast(u64, offset), &result, SEEK_END))) {2873 switch (errno(system.llseek(fd, @bitCast(u64, offset), &result, SEEK_END))) {
2874 0 => return,2874 0 => return,
...@@ -2880,7 +2880,7 @@ pub fn lseek_END(fd: fd_t, offset: i64) SeekError!void {...@@ -2880,7 +2880,7 @@ pub fn lseek_END(fd: fd_t, offset: i64) SeekError!void {
2880 else => |err| return unexpectedErrno(err),2880 else => |err| return unexpectedErrno(err),
2881 }2881 }
2882 }2882 }
2883 if (builtin.os == .windows) {2883 if (builtin.os.tag == .windows) {
2884 return windows.SetFilePointerEx_END(fd, offset);2884 return windows.SetFilePointerEx_END(fd, offset);
2885 }2885 }
2886 switch (errno(system.lseek(fd, offset, SEEK_END))) {2886 switch (errno(system.lseek(fd, offset, SEEK_END))) {
...@@ -2896,7 +2896,7 @@ pub fn lseek_END(fd: fd_t, offset: i64) SeekError!void {...@@ -2896,7 +2896,7 @@ pub fn lseek_END(fd: fd_t, offset: i64) SeekError!void {
28962896
2897/// Returns the read/write file offset relative to the beginning.2897/// Returns the read/write file offset relative to the beginning.
2898pub fn lseek_CUR_get(fd: fd_t) SeekError!u64 {2898pub fn lseek_CUR_get(fd: fd_t) SeekError!u64 {
2899 if (builtin.os == .linux and !builtin.link_libc and @sizeOf(usize) == 4) {2899 if (builtin.os.tag == .linux and !builtin.link_libc and @sizeOf(usize) == 4) {
2900 var result: u64 = undefined;2900 var result: u64 = undefined;
2901 switch (errno(system.llseek(fd, 0, &result, SEEK_CUR))) {2901 switch (errno(system.llseek(fd, 0, &result, SEEK_CUR))) {
2902 0 => return result,2902 0 => return result,
...@@ -2908,7 +2908,7 @@ pub fn lseek_CUR_get(fd: fd_t) SeekError!u64 {...@@ -2908,7 +2908,7 @@ pub fn lseek_CUR_get(fd: fd_t) SeekError!u64 {
2908 else => |err| return unexpectedErrno(err),2908 else => |err| return unexpectedErrno(err),
2909 }2909 }
2910 }2910 }
2911 if (builtin.os == .windows) {2911 if (builtin.os.tag == .windows) {
2912 return windows.SetFilePointerEx_CURRENT_get(fd);2912 return windows.SetFilePointerEx_CURRENT_get(fd);
2913 }2913 }
2914 const rc = system.lseek(fd, 0, SEEK_CUR);2914 const rc = system.lseek(fd, 0, SEEK_CUR);
...@@ -2957,7 +2957,7 @@ pub const RealPathError = error{...@@ -2957,7 +2957,7 @@ pub const RealPathError = error{
2957/// The return value is a slice of `out_buffer`, but not necessarily from the beginning.2957/// The return value is a slice of `out_buffer`, but not necessarily from the beginning.
2958/// See also `realpathC` and `realpathW`.2958/// See also `realpathC` and `realpathW`.
2959pub fn realpath(pathname: []const u8, out_buffer: *[MAX_PATH_BYTES]u8) RealPathError![]u8 {2959pub fn realpath(pathname: []const u8, out_buffer: *[MAX_PATH_BYTES]u8) RealPathError![]u8 {
2960 if (builtin.os == .windows) {2960 if (builtin.os.tag == .windows) {
2961 const pathname_w = try windows.sliceToPrefixedFileW(pathname);2961 const pathname_w = try windows.sliceToPrefixedFileW(pathname);
2962 return realpathW(&pathname_w, out_buffer);2962 return realpathW(&pathname_w, out_buffer);
2963 }2963 }
...@@ -2967,11 +2967,11 @@ pub fn realpath(pathname: []const u8, out_buffer: *[MAX_PATH_BYTES]u8) RealPathE...@@ -2967,11 +2967,11 @@ pub fn realpath(pathname: []const u8, out_buffer: *[MAX_PATH_BYTES]u8) RealPathE
29672967
2968/// Same as `realpath` except `pathname` is null-terminated.2968/// Same as `realpath` except `pathname` is null-terminated.
2969pub fn realpathC(pathname: [*:0]const u8, out_buffer: *[MAX_PATH_BYTES]u8) RealPathError![]u8 {2969pub fn realpathC(pathname: [*:0]const u8, out_buffer: *[MAX_PATH_BYTES]u8) RealPathError![]u8 {
2970 if (builtin.os == .windows) {2970 if (builtin.os.tag == .windows) {
2971 const pathname_w = try windows.cStrToPrefixedFileW(pathname);2971 const pathname_w = try windows.cStrToPrefixedFileW(pathname);
2972 return realpathW(&pathname_w, out_buffer);2972 return realpathW(&pathname_w, out_buffer);
2973 }2973 }
2974 if (builtin.os == .linux and !builtin.link_libc) {2974 if (builtin.os.tag == .linux and !builtin.link_libc) {
2975 const fd = try openC(pathname, linux.O_PATH | linux.O_NONBLOCK | linux.O_CLOEXEC, 0);2975 const fd = try openC(pathname, linux.O_PATH | linux.O_NONBLOCK | linux.O_CLOEXEC, 0);
2976 defer close(fd);2976 defer close(fd);
29772977
...@@ -3121,7 +3121,7 @@ pub fn dl_iterate_phdr(...@@ -3121,7 +3121,7 @@ pub fn dl_iterate_phdr(
3121pub const ClockGetTimeError = error{UnsupportedClock} || UnexpectedError;3121pub const ClockGetTimeError = error{UnsupportedClock} || UnexpectedError;
31223122
3123pub fn clock_gettime(clk_id: i32, tp: *timespec) ClockGetTimeError!void {3123pub fn clock_gettime(clk_id: i32, tp: *timespec) ClockGetTimeError!void {
3124 if (comptime std.Target.current.getOs() == .wasi) {3124 if (std.Target.current.os.tag == .wasi) {
3125 var ts: timestamp_t = undefined;3125 var ts: timestamp_t = undefined;
3126 switch (system.clock_time_get(@bitCast(u32, clk_id), 1, &ts)) {3126 switch (system.clock_time_get(@bitCast(u32, clk_id), 1, &ts)) {
3127 0 => {3127 0 => {
...@@ -3144,7 +3144,7 @@ pub fn clock_gettime(clk_id: i32, tp: *timespec) ClockGetTimeError!void {...@@ -3144,7 +3144,7 @@ pub fn clock_gettime(clk_id: i32, tp: *timespec) ClockGetTimeError!void {
3144}3144}
31453145
3146pub fn clock_getres(clk_id: i32, res: *timespec) ClockGetTimeError!void {3146pub fn clock_getres(clk_id: i32, res: *timespec) ClockGetTimeError!void {
3147 if (comptime std.Target.current.getOs() == .wasi) {3147 if (std.Target.current.os.tag == .wasi) {
3148 var ts: timestamp_t = undefined;3148 var ts: timestamp_t = undefined;
3149 switch (system.clock_res_get(@bitCast(u32, clk_id), &ts)) {3149 switch (system.clock_res_get(@bitCast(u32, clk_id), &ts)) {
3150 0 => res.* = .{3150 0 => res.* = .{
...@@ -3222,7 +3222,7 @@ pub const SigaltstackError = error{...@@ -3222,7 +3222,7 @@ pub const SigaltstackError = error{
3222} || UnexpectedError;3222} || UnexpectedError;
32233223
3224pub fn sigaltstack(ss: ?*stack_t, old_ss: ?*stack_t) SigaltstackError!void {3224pub fn sigaltstack(ss: ?*stack_t, old_ss: ?*stack_t) SigaltstackError!void {
3225 if (builtin.os == .windows or builtin.os == .uefi or builtin.os == .wasi)3225 if (builtin.os.tag == .windows or builtin.os.tag == .uefi or builtin.os.tag == .wasi)
3226 @compileError("std.os.sigaltstack not available for this target");3226 @compileError("std.os.sigaltstack not available for this target");
32273227
3228 switch (errno(system.sigaltstack(ss, old_ss))) {3228 switch (errno(system.sigaltstack(ss, old_ss))) {
...@@ -3294,7 +3294,7 @@ pub fn gethostname(name_buffer: *[HOST_NAME_MAX]u8) GetHostNameError![]u8 {...@@ -3294,7 +3294,7 @@ pub fn gethostname(name_buffer: *[HOST_NAME_MAX]u8) GetHostNameError![]u8 {
3294 else => |err| return unexpectedErrno(err),3294 else => |err| return unexpectedErrno(err),
3295 }3295 }
3296 }3296 }
3297 if (builtin.os == .linux) {3297 if (builtin.os.tag == .linux) {
3298 var uts: utsname = undefined;3298 var uts: utsname = undefined;
3299 switch (errno(system.uname(&uts))) {3299 switch (errno(system.uname(&uts))) {
3300 0 => {3300 0 => {
...@@ -3611,7 +3611,7 @@ pub const SchedYieldError = error{...@@ -3611,7 +3611,7 @@ pub const SchedYieldError = error{
3611};3611};
36123612
3613pub fn sched_yield() SchedYieldError!void {3613pub fn sched_yield() SchedYieldError!void {
3614 if (builtin.os == .windows) {3614 if (builtin.os.tag == .windows) {
3615 // The return value has to do with how many other threads there are; it is not3615 // The return value has to do with how many other threads there are; it is not
3616 // an error condition on Windows.3616 // an error condition on Windows.
3617 _ = windows.kernel32.SwitchToThread();3617 _ = windows.kernel32.SwitchToThread();
lib/std/os/bits.zig+2-2
...@@ -3,10 +3,10 @@...@@ -3,10 +3,10 @@
3//! Root source files can define `os.bits` and these will additionally be added3//! Root source files can define `os.bits` and these will additionally be added
4//! to the namespace.4//! to the namespace.
55
6const builtin = @import("builtin");6const std = @import("std");
7const root = @import("root");7const root = @import("root");
88
9pub usingnamespace switch (builtin.os) {9pub usingnamespace switch (std.Target.current.os.tag) {
10 .macosx, .ios, .tvos, .watchos => @import("bits/darwin.zig"),10 .macosx, .ios, .tvos, .watchos => @import("bits/darwin.zig"),
11 .dragonfly => @import("bits/dragonfly.zig"),11 .dragonfly => @import("bits/dragonfly.zig"),
12 .freebsd => @import("bits/freebsd.zig"),12 .freebsd => @import("bits/freebsd.zig"),
lib/std/os/linux.zig+1-1
...@@ -1070,7 +1070,7 @@ pub fn tcsetattr(fd: fd_t, optional_action: TCSA, termios_p: *const termios) usi...@@ -1070,7 +1070,7 @@ pub fn tcsetattr(fd: fd_t, optional_action: TCSA, termios_p: *const termios) usi
1070}1070}
10711071
1072test "" {1072test "" {
1073 if (builtin.os == .linux) {1073 if (builtin.os.tag == .linux) {
1074 _ = @import("linux/test.zig");1074 _ = @import("linux/test.zig");
1075 }1075 }
1076}1076}
lib/std/os/test.zig+8-8
...@@ -53,7 +53,7 @@ test "std.Thread.getCurrentId" {...@@ -53,7 +53,7 @@ test "std.Thread.getCurrentId" {
53 thread.wait();53 thread.wait();
54 if (Thread.use_pthreads) {54 if (Thread.use_pthreads) {
55 expect(thread_current_id == thread_id);55 expect(thread_current_id == thread_id);
56 } else if (builtin.os == .windows) {56 } else if (builtin.os.tag == .windows) {
57 expect(Thread.getCurrentId() != thread_current_id);57 expect(Thread.getCurrentId() != thread_current_id);
58 } else {58 } else {
59 // If the thread completes very quickly, then thread_id can be 0. See the59 // If the thread completes very quickly, then thread_id can be 0. See the
...@@ -151,7 +151,7 @@ test "realpath" {...@@ -151,7 +151,7 @@ test "realpath" {
151}151}
152152
153test "sigaltstack" {153test "sigaltstack" {
154 if (builtin.os == .windows or builtin.os == .wasi) return error.SkipZigTest;154 if (builtin.os.tag == .windows or builtin.os.tag == .wasi) return error.SkipZigTest;
155155
156 var st: os.stack_t = undefined;156 var st: os.stack_t = undefined;
157 try os.sigaltstack(null, &st);157 try os.sigaltstack(null, &st);
...@@ -204,7 +204,7 @@ fn iter_fn(info: *dl_phdr_info, size: usize, counter: *usize) IterFnError!void {...@@ -204,7 +204,7 @@ fn iter_fn(info: *dl_phdr_info, size: usize, counter: *usize) IterFnError!void {
204}204}
205205
206test "dl_iterate_phdr" {206test "dl_iterate_phdr" {
207 if (builtin.os == .windows or builtin.os == .wasi or builtin.os == .macosx)207 if (builtin.os.tag == .windows or builtin.os.tag == .wasi or builtin.os.tag == .macosx)
208 return error.SkipZigTest;208 return error.SkipZigTest;
209209
210 var counter: usize = 0;210 var counter: usize = 0;
...@@ -213,7 +213,7 @@ test "dl_iterate_phdr" {...@@ -213,7 +213,7 @@ test "dl_iterate_phdr" {
213}213}
214214
215test "gethostname" {215test "gethostname" {
216 if (builtin.os == .windows)216 if (builtin.os.tag == .windows)
217 return error.SkipZigTest;217 return error.SkipZigTest;
218218
219 var buf: [os.HOST_NAME_MAX]u8 = undefined;219 var buf: [os.HOST_NAME_MAX]u8 = undefined;
...@@ -222,7 +222,7 @@ test "gethostname" {...@@ -222,7 +222,7 @@ test "gethostname" {
222}222}
223223
224test "pipe" {224test "pipe" {
225 if (builtin.os == .windows)225 if (builtin.os.tag == .windows)
226 return error.SkipZigTest;226 return error.SkipZigTest;
227227
228 var fds = try os.pipe();228 var fds = try os.pipe();
...@@ -241,7 +241,7 @@ test "argsAlloc" {...@@ -241,7 +241,7 @@ test "argsAlloc" {
241241
242test "memfd_create" {242test "memfd_create" {
243 // memfd_create is linux specific.243 // memfd_create is linux specific.
244 if (builtin.os != .linux) return error.SkipZigTest;244 if (builtin.os.tag != .linux) return error.SkipZigTest;
245 const fd = std.os.memfd_create("test", 0) catch |err| switch (err) {245 const fd = std.os.memfd_create("test", 0) catch |err| switch (err) {
246 // Related: https://github.com/ziglang/zig/issues/4019246 // Related: https://github.com/ziglang/zig/issues/4019
247 error.SystemOutdated => return error.SkipZigTest,247 error.SystemOutdated => return error.SkipZigTest,
...@@ -258,7 +258,7 @@ test "memfd_create" {...@@ -258,7 +258,7 @@ test "memfd_create" {
258}258}
259259
260test "mmap" {260test "mmap" {
261 if (builtin.os == .windows)261 if (builtin.os.tag == .windows)
262 return error.SkipZigTest;262 return error.SkipZigTest;
263263
264 // Simple mmap() call with non page-aligned size264 // Simple mmap() call with non page-aligned size
...@@ -353,7 +353,7 @@ test "mmap" {...@@ -353,7 +353,7 @@ test "mmap" {
353}353}
354354
355test "getenv" {355test "getenv" {
356 if (builtin.os == .windows) {356 if (builtin.os.tag == .windows) {
357 expect(os.getenvW(&[_:0]u16{ 'B', 'O', 'G', 'U', 'S', 0x11, 0x22, 0x33, 0x44, 0x55 }) == null);357 expect(os.getenvW(&[_:0]u16{ 'B', 'O', 'G', 'U', 'S', 0x11, 0x22, 0x33, 0x44, 0x55 }) == null);
358 } else {358 } else {
359 expect(os.getenvZ("BOGUSDOESNOTEXISTENVVAR") == null);359 expect(os.getenvZ("BOGUSDOESNOTEXISTENVVAR") == null);
lib/std/packed_int_array.zig+2-2
...@@ -593,7 +593,7 @@ test "PackedInt(Array/Slice)Endian" {...@@ -593,7 +593,7 @@ test "PackedInt(Array/Slice)Endian" {
593// after this one is not mapped and will cause a segfault if we593// after this one is not mapped and will cause a segfault if we
594// don't account for the bounds.594// don't account for the bounds.
595test "PackedIntArray at end of available memory" {595test "PackedIntArray at end of available memory" {
596 switch (builtin.os) {596 switch (builtin.os.tag) {
597 .linux, .macosx, .ios, .freebsd, .netbsd, .windows => {},597 .linux, .macosx, .ios, .freebsd, .netbsd, .windows => {},
598 else => return,598 else => return,
599 }599 }
...@@ -612,7 +612,7 @@ test "PackedIntArray at end of available memory" {...@@ -612,7 +612,7 @@ test "PackedIntArray at end of available memory" {
612}612}
613613
614test "PackedIntSlice at end of available memory" {614test "PackedIntSlice at end of available memory" {
615 switch (builtin.os) {615 switch (builtin.os.tag) {
616 .linux, .macosx, .ios, .freebsd, .netbsd, .windows => {},616 .linux, .macosx, .ios, .freebsd, .netbsd, .windows => {},
617 else => return,617 else => return,
618 }618 }
lib/std/process.zig+11-11
...@@ -36,7 +36,7 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap {...@@ -36,7 +36,7 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap {
36 var result = BufMap.init(allocator);36 var result = BufMap.init(allocator);
37 errdefer result.deinit();37 errdefer result.deinit();
3838
39 if (builtin.os == .windows) {39 if (builtin.os.tag == .windows) {
40 const ptr = os.windows.peb().ProcessParameters.Environment;40 const ptr = os.windows.peb().ProcessParameters.Environment;
4141
42 var i: usize = 0;42 var i: usize = 0;
...@@ -61,7 +61,7 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap {...@@ -61,7 +61,7 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap {
61 try result.setMove(key, value);61 try result.setMove(key, value);
62 }62 }
63 return result;63 return result;
64 } else if (builtin.os == .wasi) {64 } else if (builtin.os.tag == .wasi) {
65 var environ_count: usize = undefined;65 var environ_count: usize = undefined;
66 var environ_buf_size: usize = undefined;66 var environ_buf_size: usize = undefined;
6767
...@@ -137,7 +137,7 @@ pub const GetEnvVarOwnedError = error{...@@ -137,7 +137,7 @@ pub const GetEnvVarOwnedError = error{
137137
138/// Caller must free returned memory.138/// Caller must free returned memory.
139pub fn getEnvVarOwned(allocator: *mem.Allocator, key: []const u8) GetEnvVarOwnedError![]u8 {139pub fn getEnvVarOwned(allocator: *mem.Allocator, key: []const u8) GetEnvVarOwnedError![]u8 {
140 if (builtin.os == .windows) {140 if (builtin.os.tag == .windows) {
141 const result_w = blk: {141 const result_w = blk: {
142 const key_w = try std.unicode.utf8ToUtf16LeWithNull(allocator, key);142 const key_w = try std.unicode.utf8ToUtf16LeWithNull(allocator, key);
143 defer allocator.free(key_w);143 defer allocator.free(key_w);
...@@ -338,12 +338,12 @@ pub const ArgIteratorWindows = struct {...@@ -338,12 +338,12 @@ pub const ArgIteratorWindows = struct {
338};338};
339339
340pub const ArgIterator = struct {340pub const ArgIterator = struct {
341 const InnerType = if (builtin.os == .windows) ArgIteratorWindows else ArgIteratorPosix;341 const InnerType = if (builtin.os.tag == .windows) ArgIteratorWindows else ArgIteratorPosix;
342342
343 inner: InnerType,343 inner: InnerType,
344344
345 pub fn init() ArgIterator {345 pub fn init() ArgIterator {
346 if (builtin.os == .wasi) {346 if (builtin.os.tag == .wasi) {
347 // TODO: Figure out a compatible interface accomodating WASI347 // TODO: Figure out a compatible interface accomodating WASI
348 @compileError("ArgIterator is not yet supported in WASI. Use argsAlloc and argsFree instead.");348 @compileError("ArgIterator is not yet supported in WASI. Use argsAlloc and argsFree instead.");
349 }349 }
...@@ -355,7 +355,7 @@ pub const ArgIterator = struct {...@@ -355,7 +355,7 @@ pub const ArgIterator = struct {
355355
356 /// You must free the returned memory when done.356 /// You must free the returned memory when done.
357 pub fn next(self: *ArgIterator, allocator: *Allocator) ?(NextError![]u8) {357 pub fn next(self: *ArgIterator, allocator: *Allocator) ?(NextError![]u8) {
358 if (builtin.os == .windows) {358 if (builtin.os.tag == .windows) {
359 return self.inner.next(allocator);359 return self.inner.next(allocator);
360 } else {360 } else {
361 return mem.dupe(allocator, u8, self.inner.next() orelse return null);361 return mem.dupe(allocator, u8, self.inner.next() orelse return null);
...@@ -380,7 +380,7 @@ pub fn args() ArgIterator {...@@ -380,7 +380,7 @@ pub fn args() ArgIterator {
380380
381/// Caller must call argsFree on result.381/// Caller must call argsFree on result.
382pub fn argsAlloc(allocator: *mem.Allocator) ![][]u8 {382pub fn argsAlloc(allocator: *mem.Allocator) ![][]u8 {
383 if (builtin.os == .wasi) {383 if (builtin.os.tag == .wasi) {
384 var count: usize = undefined;384 var count: usize = undefined;
385 var buf_size: usize = undefined;385 var buf_size: usize = undefined;
386386
...@@ -445,7 +445,7 @@ pub fn argsAlloc(allocator: *mem.Allocator) ![][]u8 {...@@ -445,7 +445,7 @@ pub fn argsAlloc(allocator: *mem.Allocator) ![][]u8 {
445}445}
446446
447pub fn argsFree(allocator: *mem.Allocator, args_alloc: []const []u8) void {447pub fn argsFree(allocator: *mem.Allocator, args_alloc: []const []u8) void {
448 if (builtin.os == .wasi) {448 if (builtin.os.tag == .wasi) {
449 const last_item = args_alloc[args_alloc.len - 1];449 const last_item = args_alloc[args_alloc.len - 1];
450 const last_byte_addr = @ptrToInt(last_item.ptr) + last_item.len + 1; // null terminated450 const last_byte_addr = @ptrToInt(last_item.ptr) + last_item.len + 1; // null terminated
451 const first_item_ptr = args_alloc[0].ptr;451 const first_item_ptr = args_alloc[0].ptr;
...@@ -498,7 +498,7 @@ pub const UserInfo = struct {...@@ -498,7 +498,7 @@ pub const UserInfo = struct {
498498
499/// POSIX function which gets a uid from username.499/// POSIX function which gets a uid from username.
500pub fn getUserInfo(name: []const u8) !UserInfo {500pub fn getUserInfo(name: []const u8) !UserInfo {
501 return switch (builtin.os) {501 return switch (builtin.os.tag) {
502 .linux, .macosx, .watchos, .tvos, .ios, .freebsd, .netbsd => posixGetUserInfo(name),502 .linux, .macosx, .watchos, .tvos, .ios, .freebsd, .netbsd => posixGetUserInfo(name),
503 else => @compileError("Unsupported OS"),503 else => @compileError("Unsupported OS"),
504 };504 };
...@@ -591,7 +591,7 @@ pub fn posixGetUserInfo(name: []const u8) !UserInfo {...@@ -591,7 +591,7 @@ pub fn posixGetUserInfo(name: []const u8) !UserInfo {
591}591}
592592
593pub fn getBaseAddress() usize {593pub fn getBaseAddress() usize {
594 switch (builtin.os) {594 switch (builtin.os.tag) {
595 .linux => {595 .linux => {
596 const base = os.system.getauxval(std.elf.AT_BASE);596 const base = os.system.getauxval(std.elf.AT_BASE);
597 if (base != 0) {597 if (base != 0) {
...@@ -615,7 +615,7 @@ pub fn getSelfExeSharedLibPaths(allocator: *Allocator) error{OutOfMemory}![][:0]...@@ -615,7 +615,7 @@ pub fn getSelfExeSharedLibPaths(allocator: *Allocator) error{OutOfMemory}![][:0]
615 .Dynamic => {},615 .Dynamic => {},
616 }616 }
617 const List = std.ArrayList([:0]u8);617 const List = std.ArrayList([:0]u8);
618 switch (builtin.os) {618 switch (builtin.os.tag) {
619 .linux,619 .linux,
620 .freebsd,620 .freebsd,
621 .netbsd,621 .netbsd,
lib/std/reset_event.zig+3-3
...@@ -16,7 +16,7 @@ pub const ResetEvent = struct {...@@ -16,7 +16,7 @@ pub const ResetEvent = struct {
1616
17 pub const OsEvent = if (builtin.single_threaded)17 pub const OsEvent = if (builtin.single_threaded)
18 DebugEvent18 DebugEvent
19 else if (builtin.link_libc and builtin.os != .windows and builtin.os != .linux)19 else if (builtin.link_libc and builtin.os.tag != .windows and builtin.os.tag != .linux)
20 PosixEvent20 PosixEvent
21 else21 else
22 AtomicEvent;22 AtomicEvent;
...@@ -106,7 +106,7 @@ const PosixEvent = struct {...@@ -106,7 +106,7 @@ const PosixEvent = struct {
106 fn deinit(self: *PosixEvent) void {106 fn deinit(self: *PosixEvent) void {
107 // on dragonfly, *destroy() functions can return EINVAL107 // on dragonfly, *destroy() functions can return EINVAL
108 // for statically initialized pthread structures108 // for statically initialized pthread structures
109 const err = if (builtin.os == .dragonfly) os.EINVAL else 0;109 const err = if (builtin.os.tag == .dragonfly) os.EINVAL else 0;
110110
111 const retm = c.pthread_mutex_destroy(&self.mutex);111 const retm = c.pthread_mutex_destroy(&self.mutex);
112 assert(retm == 0 or retm == err);112 assert(retm == 0 or retm == err);
...@@ -215,7 +215,7 @@ const AtomicEvent = struct {...@@ -215,7 +215,7 @@ const AtomicEvent = struct {
215 }215 }
216 }216 }
217217
218 pub const Futex = switch (builtin.os) {218 pub const Futex = switch (builtin.os.tag) {
219 .windows => WindowsFutex,219 .windows => WindowsFutex,
220 .linux => LinuxFutex,220 .linux => LinuxFutex,
221 else => SpinFutex,221 else => SpinFutex,
lib/std/special/c.zig+4-4
...@@ -17,7 +17,7 @@ const is_msvc = switch (builtin.abi) {...@@ -17,7 +17,7 @@ const is_msvc = switch (builtin.abi) {
17 .msvc => true,17 .msvc => true,
18 else => false,18 else => false,
19};19};
20const is_freestanding = switch (builtin.os) {20const is_freestanding = switch (builtin.os.tag) {
21 .freestanding => true,21 .freestanding => true,
22 else => false,22 else => false,
23};23};
...@@ -81,7 +81,7 @@ pub fn panic(msg: []const u8, error_return_trace: ?*builtin.StackTrace) noreturn...@@ -81,7 +81,7 @@ pub fn panic(msg: []const u8, error_return_trace: ?*builtin.StackTrace) noreturn
81 @setCold(true);81 @setCold(true);
82 std.debug.panic("{}", .{msg});82 std.debug.panic("{}", .{msg});
83 }83 }
84 if (builtin.os != .freestanding and builtin.os != .other) {84 if (builtin.os.tag != .freestanding and builtin.os.tag != .other) {
85 std.os.abort();85 std.os.abort();
86 }86 }
87 while (true) {}87 while (true) {}
...@@ -178,11 +178,11 @@ test "test_bcmp" {...@@ -178,11 +178,11 @@ test "test_bcmp" {
178comptime {178comptime {
179 if (builtin.mode != builtin.Mode.ReleaseFast and179 if (builtin.mode != builtin.Mode.ReleaseFast and
180 builtin.mode != builtin.Mode.ReleaseSmall and180 builtin.mode != builtin.Mode.ReleaseSmall and
181 builtin.os != builtin.Os.windows)181 builtin.os.tag != .windows)
182 {182 {
183 @export(__stack_chk_fail, .{ .name = "__stack_chk_fail" });183 @export(__stack_chk_fail, .{ .name = "__stack_chk_fail" });
184 }184 }
185 if (builtin.os == builtin.Os.linux) {185 if (builtin.os.tag == .linux) {
186 @export(clone, .{ .name = "clone" });186 @export(clone, .{ .name = "clone" });
187 }187 }
188}188}
lib/std/special/compiler_rt.zig+7-6
...@@ -1,11 +1,12 @@...@@ -1,11 +1,12 @@
1const builtin = @import("builtin");1const std = @import("std");
2const builtin = std.builtin;
2const is_test = builtin.is_test;3const is_test = builtin.is_test;
34
4const is_gnu = switch (builtin.abi) {5const is_gnu = switch (builtin.abi) {
5 .gnu, .gnuabin32, .gnuabi64, .gnueabi, .gnueabihf, .gnux32 => true,6 .gnu, .gnuabin32, .gnuabi64, .gnueabi, .gnueabihf, .gnux32 => true,
6 else => false,7 else => false,
7};8};
8const is_mingw = builtin.os == .windows and is_gnu;9const is_mingw = builtin.os.tag == .windows and is_gnu;
910
10comptime {11comptime {
11 const linkage = if (is_test) builtin.GlobalLinkage.Internal else builtin.GlobalLinkage.Weak;12 const linkage = if (is_test) builtin.GlobalLinkage.Internal else builtin.GlobalLinkage.Weak;
...@@ -180,7 +181,7 @@ comptime {...@@ -180,7 +181,7 @@ comptime {
180 @export(@import("compiler_rt/arm.zig").__aeabi_memclr, .{ .name = "__aeabi_memclr4", .linkage = linkage });181 @export(@import("compiler_rt/arm.zig").__aeabi_memclr, .{ .name = "__aeabi_memclr4", .linkage = linkage });
181 @export(@import("compiler_rt/arm.zig").__aeabi_memclr, .{ .name = "__aeabi_memclr8", .linkage = linkage });182 @export(@import("compiler_rt/arm.zig").__aeabi_memclr, .{ .name = "__aeabi_memclr8", .linkage = linkage });
182183
183 if (builtin.os == .linux) {184 if (builtin.os.tag == .linux) {
184 @export(@import("compiler_rt/arm.zig").__aeabi_read_tp, .{ .name = "__aeabi_read_tp", .linkage = linkage });185 @export(@import("compiler_rt/arm.zig").__aeabi_read_tp, .{ .name = "__aeabi_read_tp", .linkage = linkage });
185 }186 }
186187
...@@ -250,7 +251,7 @@ comptime {...@@ -250,7 +251,7 @@ comptime {
250 @export(@import("compiler_rt/aullrem.zig")._aullrem, .{ .name = "\x01__aullrem", .linkage = strong_linkage });251 @export(@import("compiler_rt/aullrem.zig")._aullrem, .{ .name = "\x01__aullrem", .linkage = strong_linkage });
251 }252 }
252253
253 if (builtin.os == .windows) {254 if (builtin.os.tag == .windows) {
254 // Default stack-probe functions emitted by LLVM255 // Default stack-probe functions emitted by LLVM
255 if (is_mingw) {256 if (is_mingw) {
256 @export(@import("compiler_rt/stack_probe.zig")._chkstk, .{ .name = "_alloca", .linkage = strong_linkage });257 @export(@import("compiler_rt/stack_probe.zig")._chkstk, .{ .name = "_alloca", .linkage = strong_linkage });
...@@ -288,7 +289,7 @@ comptime {...@@ -288,7 +289,7 @@ comptime {
288 else => {},289 else => {},
289 }290 }
290 } else {291 } else {
291 if (builtin.glibc_version != null) {292 if (std.Target.current.isGnuLibC()) {
292 @export(__stack_chk_guard, .{ .name = "__stack_chk_guard", .linkage = linkage });293 @export(__stack_chk_guard, .{ .name = "__stack_chk_guard", .linkage = linkage });
293 }294 }
294 @export(@import("compiler_rt/divti3.zig").__divti3, .{ .name = "__divti3", .linkage = linkage });295 @export(@import("compiler_rt/divti3.zig").__divti3, .{ .name = "__divti3", .linkage = linkage });
...@@ -307,7 +308,7 @@ comptime {...@@ -307,7 +308,7 @@ comptime {
307pub fn panic(msg: []const u8, error_return_trace: ?*builtin.StackTrace) noreturn {308pub fn panic(msg: []const u8, error_return_trace: ?*builtin.StackTrace) noreturn {
308 @setCold(true);309 @setCold(true);
309 if (is_test) {310 if (is_test) {
310 @import("std").debug.panic("{}", .{msg});311 std.debug.panic("{}", .{msg});
311 } else {312 } else {
312 unreachable;313 unreachable;
313 }314 }
lib/std/special/compiler_rt/extendXfYf2_test.zig+1-1
...@@ -90,7 +90,7 @@ test "extendhfsf2" {...@@ -90,7 +90,7 @@ test "extendhfsf2" {
90 test__extendhfsf2(0x7f00, 0x7fe00000); // sNaN90 test__extendhfsf2(0x7f00, 0x7fe00000); // sNaN
91 // On x86 the NaN becomes quiet because the return is pushed on the x8791 // On x86 the NaN becomes quiet because the return is pushed on the x87
92 // stack due to ABI requirements92 // stack due to ABI requirements
93 if (builtin.arch != .i386 and builtin.os == .windows)93 if (builtin.arch != .i386 and builtin.os.tag == .windows)
94 test__extendhfsf2(0x7c01, 0x7f802000); // sNaN94 test__extendhfsf2(0x7c01, 0x7f802000); // sNaN
9595
96 test__extendhfsf2(0, 0); // 096 test__extendhfsf2(0, 0); // 0
lib/std/spinlock.zig+1-1
...@@ -46,7 +46,7 @@ pub const SpinLock = struct {...@@ -46,7 +46,7 @@ pub const SpinLock = struct {
46 // and yielding for 380-410 iterations was found to be46 // and yielding for 380-410 iterations was found to be
47 // a nice sweet spot. Posix systems on the other hand,47 // a nice sweet spot. Posix systems on the other hand,
48 // especially linux, perform better by yielding the thread.48 // especially linux, perform better by yielding the thread.
49 switch (builtin.os) {49 switch (builtin.os.tag) {
50 .windows => loopHint(400),50 .windows => loopHint(400),
51 else => std.os.sched_yield() catch loopHint(1),51 else => std.os.sched_yield() catch loopHint(1),
52 }52 }
lib/std/start.zig+8-8
...@@ -12,7 +12,7 @@ const start_sym_name = if (builtin.arch.isMIPS()) "__start" else "_start";...@@ -12,7 +12,7 @@ const start_sym_name = if (builtin.arch.isMIPS()) "__start" else "_start";
1212
13comptime {13comptime {
14 if (builtin.output_mode == .Lib and builtin.link_mode == .Dynamic) {14 if (builtin.output_mode == .Lib and builtin.link_mode == .Dynamic) {
15 if (builtin.os == .windows and !@hasDecl(root, "_DllMainCRTStartup")) {15 if (builtin.os.tag == .windows and !@hasDecl(root, "_DllMainCRTStartup")) {
16 @export(_DllMainCRTStartup, .{ .name = "_DllMainCRTStartup" });16 @export(_DllMainCRTStartup, .{ .name = "_DllMainCRTStartup" });
17 }17 }
18 } else if (builtin.output_mode == .Exe or @hasDecl(root, "main")) {18 } else if (builtin.output_mode == .Exe or @hasDecl(root, "main")) {
...@@ -20,17 +20,17 @@ comptime {...@@ -20,17 +20,17 @@ comptime {
20 if (@typeInfo(@TypeOf(root.main)).Fn.calling_convention != .C) {20 if (@typeInfo(@TypeOf(root.main)).Fn.calling_convention != .C) {
21 @export(main, .{ .name = "main", .linkage = .Weak });21 @export(main, .{ .name = "main", .linkage = .Weak });
22 }22 }
23 } else if (builtin.os == .windows) {23 } else if (builtin.os.tag == .windows) {
24 if (!@hasDecl(root, "WinMain") and !@hasDecl(root, "WinMainCRTStartup") and24 if (!@hasDecl(root, "WinMain") and !@hasDecl(root, "WinMainCRTStartup") and
25 !@hasDecl(root, "wWinMain") and !@hasDecl(root, "wWinMainCRTStartup"))25 !@hasDecl(root, "wWinMain") and !@hasDecl(root, "wWinMainCRTStartup"))
26 {26 {
27 @export(WinMainCRTStartup, .{ .name = "WinMainCRTStartup" });27 @export(WinMainCRTStartup, .{ .name = "WinMainCRTStartup" });
28 }28 }
29 } else if (builtin.os == .uefi) {29 } else if (builtin.os.tag == .uefi) {
30 if (!@hasDecl(root, "EfiMain")) @export(EfiMain, .{ .name = "EfiMain" });30 if (!@hasDecl(root, "EfiMain")) @export(EfiMain, .{ .name = "EfiMain" });
31 } else if (builtin.arch.isWasm() and builtin.os == .freestanding) {31 } else if (builtin.arch.isWasm() and builtin.os.tag == .freestanding) {
32 if (!@hasDecl(root, start_sym_name)) @export(wasm_freestanding_start, .{ .name = start_sym_name });32 if (!@hasDecl(root, start_sym_name)) @export(wasm_freestanding_start, .{ .name = start_sym_name });
33 } else if (builtin.os != .other and builtin.os != .freestanding) {33 } else if (builtin.os.tag != .other and builtin.os.tag != .freestanding) {
34 if (!@hasDecl(root, start_sym_name)) @export(_start, .{ .name = start_sym_name });34 if (!@hasDecl(root, start_sym_name)) @export(_start, .{ .name = start_sym_name });
35 }35 }
36 }36 }
...@@ -78,7 +78,7 @@ fn EfiMain(handle: uefi.Handle, system_table: *uefi.tables.SystemTable) callconv...@@ -78,7 +78,7 @@ fn EfiMain(handle: uefi.Handle, system_table: *uefi.tables.SystemTable) callconv
78}78}
7979
80fn _start() callconv(.Naked) noreturn {80fn _start() callconv(.Naked) noreturn {
81 if (builtin.os == builtin.Os.wasi) {81 if (builtin.os.tag == .wasi) {
82 // This is marked inline because for some reason LLVM in release mode fails to inline it,82 // This is marked inline because for some reason LLVM in release mode fails to inline it,
83 // and we want fewer call frames in stack traces.83 // and we want fewer call frames in stack traces.
84 std.os.wasi.proc_exit(@call(.{ .modifier = .always_inline }, callMain, .{}));84 std.os.wasi.proc_exit(@call(.{ .modifier = .always_inline }, callMain, .{}));
...@@ -133,7 +133,7 @@ fn WinMainCRTStartup() callconv(.Stdcall) noreturn {...@@ -133,7 +133,7 @@ fn WinMainCRTStartup() callconv(.Stdcall) noreturn {
133133
134// TODO https://github.com/ziglang/zig/issues/265134// TODO https://github.com/ziglang/zig/issues/265
135fn posixCallMainAndExit() noreturn {135fn posixCallMainAndExit() noreturn {
136 if (builtin.os == builtin.Os.freebsd) {136 if (builtin.os.tag == .freebsd) {
137 @setAlignStack(16);137 @setAlignStack(16);
138 }138 }
139 const argc = starting_stack_ptr[0];139 const argc = starting_stack_ptr[0];
...@@ -144,7 +144,7 @@ fn posixCallMainAndExit() noreturn {...@@ -144,7 +144,7 @@ fn posixCallMainAndExit() noreturn {
144 while (envp_optional[envp_count]) |_| : (envp_count += 1) {}144 while (envp_optional[envp_count]) |_| : (envp_count += 1) {}
145 const envp = @ptrCast([*][*:0]u8, envp_optional)[0..envp_count];145 const envp = @ptrCast([*][*:0]u8, envp_optional)[0..envp_count];
146146
147 if (builtin.os == .linux) {147 if (builtin.os.tag == .linux) {
148 // Find the beginning of the auxiliary vector148 // Find the beginning of the auxiliary vector
149 const auxv = @ptrCast([*]std.elf.Auxv, @alignCast(@alignOf(usize), envp.ptr + envp_count + 1));149 const auxv = @ptrCast([*]std.elf.Auxv, @alignCast(@alignOf(usize), envp.ptr + envp_count + 1));
150 std.os.linux.elf_aux_maybe = auxv;150 std.os.linux.elf_aux_maybe = auxv;
lib/std/target.zig+308-291
...@@ -11,143 +11,48 @@ pub const Target = struct {...@@ -11,143 +11,48 @@ pub const Target = struct {
11 os: Os,11 os: Os,
12 abi: Abi,12 abi: Abi,
1313
14 /// The version ranges here represent the minimum OS version to be supported14 pub const Os = struct {
15 /// and the maximum OS version to be supported. The default values represent15 tag: Tag,
16 /// the range that the Zig Standard Library bases its abstractions on.16 version_range: VersionRange,
17 ///17
18 /// The minimum version of the range is the main setting to tweak for a target.18 pub const Tag = enum {
19 /// Usually, the maximum target OS version will remain the default, which is19 freestanding,
20 /// the latest released version of the OS.20 ananas,
21 ///21 cloudabi,
22 /// To test at compile time if the target is guaranteed to support a given OS feature,22 dragonfly,
23 /// one should check that the minimum version of the range is greater than or equal to23 freebsd,
24 /// the version the feature was introduced in.24 fuchsia,
25 ///25 ios,
26 /// To test at compile time if the target certainly will not support a given OS feature,26 kfreebsd,
27 /// one should check that the maximum version of the range is less than the version the27 linux,
28 /// feature was introduced in.28 lv2,
29 ///29 macosx,
30 /// If neither of these cases apply, a runtime check should be used to determine if the30 netbsd,
31 /// target supports a given OS feature.31 openbsd,
32 ///32 solaris,
33 /// Binaries built with a given maximum version will continue to function on newer operating system33 windows,
34 /// versions. However, such a binary may not take full advantage of the newer operating system APIs.34 haiku,
35 pub const Os = union(enum) {35 minix,
36 freestanding,36 rtems,
37 ananas,37 nacl,
38 cloudabi,38 cnk,
39 dragonfly,39 aix,
40 freebsd: Version.Range,40 cuda,
41 fuchsia,41 nvcl,
42 ios,42 amdhsa,
43 kfreebsd,43 ps4,
44 linux: LinuxVersionRange,44 elfiamcu,
45 lv2,45 tvos,
46 macosx: Version.Range,46 watchos,
47 netbsd: Version.Range,47 mesa3d,
48 openbsd: Version.Range,48 contiki,
49 solaris,49 amdpal,
50 windows: WindowsVersion.Range,50 hermit,
51 haiku,51 hurd,
52 minix,52 wasi,
53 rtems,53 emscripten,
54 nacl,54 uefi,
55 cnk,55 other,
56 aix,
57 cuda,
58 nvcl,
59 amdhsa,
60 ps4,
61 elfiamcu,
62 tvos,
63 watchos,
64 mesa3d,
65 contiki,
66 amdpal,
67 hermit,
68 hurd,
69 wasi,
70 emscripten,
71 uefi,
72 other,
73
74 /// See the documentation for `Os` for an explanation of the default version range.
75 pub fn defaultVersionRange(tag: @TagType(Os)) Os {
76 switch (tag) {
77 .freestanding => return .freestanding,
78 .ananas => return .ananas,
79 .cloudabi => return .cloudabi,
80 .dragonfly => return .dragonfly,
81 .freebsd => return .{
82 .freebsd = Version.Range{
83 .min = .{ .major = 12, .minor = 0 },
84 .max = .{ .major = 12, .minor = 1 },
85 },
86 },
87 .fuchsia => return .fuchsia,
88 .ios => return .ios,
89 .kfreebsd => return .kfreebsd,
90 .linux => return .{
91 .linux = .{
92 .range = .{
93 .min = .{ .major = 3, .minor = 16 },
94 .max = .{ .major = 5, .minor = 5, .patch = 5 },
95 },
96 .glibc = .{ .major = 2, .minor = 17 },
97 },
98 },
99 .lv2 => return .lv2,
100 .macosx => return .{
101 .min = .{ .major = 10, .minor = 13 },
102 .max = .{ .major = 10, .minor = 15, .patch = 3 },
103 },
104 .netbsd => return .{
105 .min = .{ .major = 8, .minor = 0 },
106 .max = .{ .major = 9, .minor = 0 },
107 },
108 .openbsd => return .{
109 .min = .{ .major = 6, .minor = 6 },
110 .max = .{ .major = 6, .minor = 6 },
111 },
112 solaris => return .solaris,
113 windows => return .{
114 .windows = .{
115 .min = .win8_1,
116 .max = .win10_19h1,
117 },
118 },
119 haiku => return .haiku,
120 minix => return .minix,
121 rtems => return .rtems,
122 nacl => return .nacl,
123 cnk => return .cnk,
124 aix => return .aix,
125 cuda => return .cuda,
126 nvcl => return .nvcl,
127 amdhsa => return .amdhsa,
128 ps4 => return .ps4,
129 elfiamcu => return .elfiamcu,
130 tvos => return .tvos,
131 watchos => return .watchos,
132 mesa3d => return .mesa3d,
133 contiki => return .contiki,
134 amdpal => return .amdpal,
135 hermit => return .hermit,
136 hurd => return .hurd,
137 wasi => return .wasi,
138 emscripten => return .emscripten,
139 uefi => return .uefi,
140 other => return .other,
141 }
142 }
143
144 pub const LinuxVersionRange = struct {
145 range: Version.Range,
146 glibc: Version,
147
148 pub fn includesVersion(self: LinuxVersionRange, ver: Version) bool {
149 return self.range.includesVersion(ver);
150 }
151 };56 };
15257
153 /// Based on NTDDI version constants from58 /// Based on NTDDI version constants from
...@@ -178,29 +83,137 @@ pub const Target = struct {...@@ -178,29 +83,137 @@ pub const Target = struct {
178 return @enumToInt(ver) >= @enumToInt(self.min) and @enumToInt(ver) <= @enumToInt(self.max);83 return @enumToInt(ver) >= @enumToInt(self.min) and @enumToInt(ver) <= @enumToInt(self.max);
179 }84 }
180 };85 };
86 };
18187
182 pub fn nameToTag(name: []const u8) ?WindowsVersion {88 pub const LinuxVersionRange = struct {
183 const info = @typeInfo(WindowsVersion);89 range: Version.Range,
184 inline for (info.Enum.fields) |field| {90 glibc: Version,
185 if (mem.eql(u8, name, field.name)) {91
186 return @field(WindowsVersion, field.name);92 pub fn includesVersion(self: LinuxVersionRange, ver: Version) bool {
187 }93 return self.range.includesVersion(ver);
94 }
95 };
96
97 /// The version ranges here represent the minimum OS version to be supported
98 /// and the maximum OS version to be supported. The default values represent
99 /// the range that the Zig Standard Library bases its abstractions on.
100 ///
101 /// The minimum version of the range is the main setting to tweak for a target.
102 /// Usually, the maximum target OS version will remain the default, which is
103 /// the latest released version of the OS.
104 ///
105 /// To test at compile time if the target is guaranteed to support a given OS feature,
106 /// one should check that the minimum version of the range is greater than or equal to
107 /// the version the feature was introduced in.
108 ///
109 /// To test at compile time if the target certainly will not support a given OS feature,
110 /// one should check that the maximum version of the range is less than the version the
111 /// feature was introduced in.
112 ///
113 /// If neither of these cases apply, a runtime check should be used to determine if the
114 /// target supports a given OS feature.
115 ///
116 /// Binaries built with a given maximum version will continue to function on newer operating system
117 /// versions. However, such a binary may not take full advantage of the newer operating system APIs.
118 pub const VersionRange = union {
119 none: void,
120 semver: Version.Range,
121 linux: LinuxVersionRange,
122 windows: WindowsVersion.Range,
123
124 /// The default `VersionRange` represents the range that the Zig Standard Library
125 /// bases its abstractions on.
126 pub fn default(tag: Tag) VersionRange {
127 switch (tag) {
128 .freestanding,
129 .ananas,
130 .cloudabi,
131 .dragonfly,
132 .fuchsia,
133 .ios,
134 .kfreebsd,
135 .lv2,
136 .solaris,
137 .haiku,
138 .minix,
139 .rtems,
140 .nacl,
141 .cnk,
142 .aix,
143 .cuda,
144 .nvcl,
145 .amdhsa,
146 .ps4,
147 .elfiamcu,
148 .tvos,
149 .watchos,
150 .mesa3d,
151 .contiki,
152 .amdpal,
153 .hermit,
154 .hurd,
155 .wasi,
156 .emscripten,
157 .uefi,
158 .other,
159 => return .{ .none = {} },
160
161 .freebsd => return .{
162 .semver = Version.Range{
163 .min = .{ .major = 12, .minor = 0 },
164 .max = .{ .major = 12, .minor = 1 },
165 },
166 },
167 .macosx => return .{
168 .semver = .{
169 .min = .{ .major = 10, .minor = 13 },
170 .max = .{ .major = 10, .minor = 15, .patch = 3 },
171 },
172 },
173 .netbsd => return .{
174 .semver = .{
175 .min = .{ .major = 8, .minor = 0 },
176 .max = .{ .major = 9, .minor = 0 },
177 },
178 },
179 .openbsd => return .{
180 .semver = .{
181 .min = .{ .major = 6, .minor = 6 },
182 .max = .{ .major = 6, .minor = 6 },
183 },
184 },
185
186 .linux => return .{
187 .linux = .{
188 .range = .{
189 .min = .{ .major = 3, .minor = 16 },
190 .max = .{ .major = 5, .minor = 5, .patch = 5 },
191 },
192 .glibc = .{ .major = 2, .minor = 17 },
193 },
194 },
195
196 .windows => return .{
197 .windows = .{
198 .min = .win8_1,
199 .max = .win10_19h1,
200 },
201 },
188 }202 }
189 return null;
190 }203 }
191 };204 };
192205
193 pub fn parse(text: []const u8) !Os {206 pub fn parse(text: []const u8) !Os {
194 var it = mem.separate(text, ".");207 var it = mem.separate(text, ".");
195 const os_name = it.next().?;208 const os_name = it.next().?;
196 const tag = nameToTag(os_name) orelse return error.UnknownOperatingSystem;209 const tag = std.meta.stringToEnum(Tag, os_name) orelse return error.UnknownOperatingSystem;
197 const version_text = it.rest();210 const version_text = it.rest();
198 const S = struct {211 const S = struct {
199 fn parseNone(s: []const u8) !void {212 fn parseNone(s: []const u8) !void {
200 if (s.len != 0) return error.InvalidOperatingSystemVersion;213 if (s.len != 0) return error.InvalidOperatingSystemVersion;
201 }214 }
202 fn parseSemVer(s: []const u8, default: Version.Range) !Version.Range {215 fn parseSemVer(s: []const u8, d_range: Version.Range) !Version.Range {
203 if (s.len == 0) return default;216 if (s.len == 0) return d_range;
204 var range_it = mem.separate(s, "...");217 var range_it = mem.separate(s, "...");
205218
206 const min_text = range_it.next().?;219 const min_text = range_it.next().?;
...@@ -212,7 +225,7 @@ pub const Target = struct {...@@ -212,7 +225,7 @@ pub const Target = struct {
212225
213 const max_text = range_it.next() orelse return Version.Range{226 const max_text = range_it.next() orelse return Version.Range{
214 .min = min_ver,227 .min = min_ver,
215 .max = default.max,228 .max = d_range.max,
216 };229 };
217 const max_ver = Version.parse(max_text) catch |err| switch (err) {230 const max_ver = Version.parse(max_text) catch |err| switch (err) {
218 error.Overflow => return error.InvalidOperatingSystemVersion,231 error.Overflow => return error.InvalidOperatingSystemVersion,
...@@ -222,79 +235,93 @@ pub const Target = struct {...@@ -222,79 +235,93 @@ pub const Target = struct {
222235
223 return Version.Range{ .min = min_ver, .max = max_ver };236 return Version.Range{ .min = min_ver, .max = max_ver };
224 }237 }
225 fn parseWindows(s: []const u8, default: WindowsVersion.Range) !WindowsVersion.Range {238 fn parseWindows(s: []const u8, d_range: WindowsVersion.Range) !WindowsVersion.Range {
226 if (s.len == 0) return default;239 if (s.len == 0) return d_range;
227 var range_it = mem.separate(s, "...");240 var range_it = mem.separate(s, "...");
228241
229 const min_text = range_it.next().?;242 const min_text = range_it.next().?;
230 const min_ver = WindowsVersion.nameToTag(min_text) orelse243 const min_ver = std.meta.stringToEnum(WindowsVersion, min_text) orelse
231 return error.InvalidOperatingSystemVersion;244 return error.InvalidOperatingSystemVersion;
232245
233 const max_text = range_it.next() orelse return WindowsVersion.Range{246 const max_text = range_it.next() orelse return WindowsVersion.Range{
234 .min = min_ver,247 .min = min_ver,
235 .max = default.max,248 .max = d_range.max,
236 };249 };
237 const max_ver = WindowsVersion.nameToTag(max_text) orelse250 const max_ver = std.meta.stringToEnum(WindowsVersion, max_text) orelse
238 return error.InvalidOperatingSystemVersion;251 return error.InvalidOperatingSystemVersion;
239252
240 return WindowsVersion.Range{ .min = min_ver, .max = max_ver };253 return WindowsVersion.Range{ .min = min_ver, .max = max_ver };
241 }254 }
242 };255 };
243 const default = defaultVersionRange(tag);256 const d_range = VersionRange.default(tag);
244 switch (tag) {257 switch (tag) {
245 .freestanding => return Os{ .freestanding = try S.parseNone(version_text) },258 .freestanding,
246 .ananas => return Os{ .ananas = try S.parseNone(version_text) },259 .ananas,
247 .cloudabi => return Os{ .cloudabi = try S.parseNone(version_text) },260 .cloudabi,
248 .dragonfly => return Os{ .dragonfly = try S.parseNone(version_text) },261 .dragonfly,
249 .freebsd => return Os{ .freebsd = try S.parseSemVer(version_text, default.freebsd) },262 .fuchsia,
250 .fuchsia => return Os{ .fuchsia = try S.parseNone(version_text) },263 .ios,
251 .ios => return Os{ .ios = try S.parseNone(version_text) },264 .kfreebsd,
252 .kfreebsd => return Os{ .kfreebsd = try S.parseNone(version_text) },265 .lv2,
266 .solaris,
267 .haiku,
268 .minix,
269 .rtems,
270 .nacl,
271 .cnk,
272 .aix,
273 .cuda,
274 .nvcl,
275 .amdhsa,
276 .ps4,
277 .elfiamcu,
278 .tvos,
279 .watchos,
280 .mesa3d,
281 .contiki,
282 .amdpal,
283 .hermit,
284 .hurd,
285 .wasi,
286 .emscripten,
287 .uefi,
288 .other,
289 => return Os{
290 .tag = tag,
291 .version_range = .{ .none = try S.parseNone(version_text) },
292 },
293
294 .freebsd,
295 .macosx,
296 .netbsd,
297 .openbsd,
298 => return Os{
299 .tag = tag,
300 .version_range = .{ .semver = try S.parseSemVer(version_text, d_range.semver) },
301 },
302
253 .linux => return Os{303 .linux => return Os{
254 .linux = .{304 .tag = tag,
255 .range = try S.parseSemVer(version_text, default.linux.range),305 .version_range = .{
256 .glibc = default.linux.glibc,306 .linux = .{
307 .range = try S.parseSemVer(version_text, d_range.linux.range),
308 .glibc = d_range.linux.glibc,
309 },
257 },310 },
258 },311 },
259 .lv2 => return Os{ .lv2 = try S.parseNone(version_text) },312
260 .macosx => return Os{ .macosx = try S.parseSemVer(version_text, default.macosx) },313 .windows => return Os{
261 .netbsd => return Os{ .netbsd = try S.parseSemVer(version_text, default.netbsd) },314 .tag = tag,
262 .openbsd => return Os{ .openbsd = try S.parseSemVer(version_text, default.openbsd) },315 .version_range = .{ .windows = try S.parseWindows(version_text, d_range.windows) },
263 .solaris => return Os{ .solaris = try S.parseNone(version_text) },316 },
264 .windows => return Os{ .windows = try S.parseWindows(version_text, default.windows) },
265 .haiku => return Os{ .haiku = try S.parseNone(version_text) },
266 .minix => return Os{ .minix = try S.parseNone(version_text) },
267 .rtems => return Os{ .rtems = try S.parseNone(version_text) },
268 .nacl => return Os{ .nacl = try S.parseNone(version_text) },
269 .cnk => return Os{ .cnk = try S.parseNone(version_text) },
270 .aix => return Os{ .aix = try S.parseNone(version_text) },
271 .cuda => return Os{ .cuda = try S.parseNone(version_text) },
272 .nvcl => return Os{ .nvcl = try S.parseNone(version_text) },
273 .amdhsa => return Os{ .amdhsa = try S.parseNone(version_text) },
274 .ps4 => return Os{ .ps4 = try S.parseNone(version_text) },
275 .elfiamcu => return Os{ .elfiamcu = try S.parseNone(version_text) },
276 .tvos => return Os{ .tvos = try S.parseNone(version_text) },
277 .watchos => return Os{ .watchos = try S.parseNone(version_text) },
278 .mesa3d => return Os{ .mesa3d = try S.parseNone(version_text) },
279 .contiki => return Os{ .contiki = try S.parseNone(version_text) },
280 .amdpal => return Os{ .amdpal = try S.parseNone(version_text) },
281 .hermit => return Os{ .hermit = try S.parseNone(version_text) },
282 .hurd => return Os{ .hurd = try S.parseNone(version_text) },
283 .wasi => return Os{ .wasi = try S.parseNone(version_text) },
284 .emscripten => return Os{ .emscripten = try S.parseNone(version_text) },
285 .uefi => return Os{ .uefi = try S.parseNone(version_text) },
286 .other => return Os{ .other = try S.parseNone(version_text) },
287 }317 }
288 }318 }
289319
290 pub fn nameToTag(name: []const u8) ?@TagType(Os) {320 pub fn defaultVersionRange(tag: Tag) Os {
291 const info = @typeInfo(Os);321 return .{
292 inline for (info.Union.fields) |field| {322 .tag = tag,
293 if (mem.eql(u8, name, field.name)) {323 .version_range = VersionRange.default(tag),
294 return @field(Os, field.name);324 };
295 }
296 }
297 return null;
298 }325 }
299 };326 };
300327
...@@ -339,11 +366,10 @@ pub const Target = struct {...@@ -339,11 +366,10 @@ pub const Target = struct {
339 macabi,366 macabi,
340367
341 pub fn default(arch: Cpu.Arch, target_os: Os) Abi {368 pub fn default(arch: Cpu.Arch, target_os: Os) Abi {
342 switch (arch) {369 if (arch.isWasm()) {
343 .wasm32, .wasm64 => return .musl,370 return .musl;
344 else => {},
345 }371 }
346 switch (target_os) {372 switch (target_os.tag) {
347 .freestanding,373 .freestanding,
348 .ananas,374 .ananas,
349 .cloudabi,375 .cloudabi,
...@@ -388,40 +414,19 @@ pub const Target = struct {...@@ -388,40 +414,19 @@ pub const Target = struct {
388 }414 }
389 }415 }
390416
391 pub fn nameToTag(text: []const u8) ?Abi {
392 const info = @typeInfo(Abi);
393 inline for (info.Enum.fields) |field| {
394 if (mem.eql(u8, text, field.name)) {
395 return @field(Abi, field.name);
396 }
397 }
398 return null;
399 }
400
401 pub fn parse(text: []const u8, os: *Os) !Abi {
402 var it = mem.separate(text, ".");
403 const tag = nameToTag(it.next().?) orelse return error.UnknownApplicationBinaryInterface;
404 const version_text = it.rest();
405 if (version_text.len != 0) {
406 if (@as(@TagType(Os), os.*) == .linux and tag.isGnu()) {
407 os.linux.glibc = Version.parse(version_text) catch |err| switch (err) {
408 error.Overflow => return error.InvalidGlibcVersion,
409 error.InvalidCharacter => return error.InvalidGlibcVersion,
410 error.InvalidVersion => return error.InvalidGlibcVersion,
411 };
412 } else {
413 return error.InvalidAbiVersion;
414 }
415 }
416 return tag;
417 }
418
419 pub fn isGnu(abi: Abi) bool {417 pub fn isGnu(abi: Abi) bool {
420 return switch (abi) {418 return switch (abi) {
421 .gnu, .gnuabin32, .gnuabi64, .gnueabi, .gnueabihf, .gnux32 => true,419 .gnu, .gnuabin32, .gnuabi64, .gnueabi, .gnueabihf, .gnux32 => true,
422 else => false,420 else => false,
423 };421 };
424 }422 }
423
424 pub fn isMusl(abi: Abi) bool {
425 return switch (abi) {
426 .musl, .musleabi, .musleabihf => true,
427 else => false,
428 };
429 }
425 };430 };
426431
427 pub const ObjectFormat = enum {432 pub const ObjectFormat = enum {
...@@ -909,15 +914,15 @@ pub const Target = struct {...@@ -909,15 +914,15 @@ pub const Target = struct {
909 /// TODO add OS version ranges and glibc version914 /// TODO add OS version ranges and glibc version
910 pub fn zigTriple(self: Target, allocator: *mem.Allocator) ![]u8 {915 pub fn zigTriple(self: Target, allocator: *mem.Allocator) ![]u8 {
911 return std.fmt.allocPrint(allocator, "{}-{}-{}", .{916 return std.fmt.allocPrint(allocator, "{}-{}-{}", .{
912 @tagName(self.getArch()),917 @tagName(self.cpu.arch),
913 @tagName(self.os),918 @tagName(self.os.tag),
914 @tagName(self.abi),919 @tagName(self.abi),
915 });920 });
916 }921 }
917922
918 /// Returned slice must be freed by the caller.923 /// Returned slice must be freed by the caller.
919 pub fn vcpkgTriplet(allocator: *mem.Allocator, target: Target, linkage: std.build.VcpkgLinkage) ![]const u8 {924 pub fn vcpkgTriplet(allocator: *mem.Allocator, target: Target, linkage: std.build.VcpkgLinkage) ![]const u8 {
920 const arch = switch (target.getArch()) {925 const arch = switch (target.cpu.arch) {
921 .i386 => "x86",926 .i386 => "x86",
922 .x86_64 => "x64",927 .x86_64 => "x64",
923928
...@@ -957,16 +962,16 @@ pub const Target = struct {...@@ -957,16 +962,16 @@ pub const Target = struct {
957962
958 pub fn zigTripleNoSubArch(self: Target, allocator: *mem.Allocator) ![]u8 {963 pub fn zigTripleNoSubArch(self: Target, allocator: *mem.Allocator) ![]u8 {
959 return std.fmt.allocPrint(allocator, "{}-{}-{}", .{964 return std.fmt.allocPrint(allocator, "{}-{}-{}", .{
960 @tagName(self.getArch()),965 @tagName(self.cpu.arch),
961 @tagName(self.os),966 @tagName(self.os.tag),
962 @tagName(self.abi),967 @tagName(self.abi),
963 });968 });
964 }969 }
965970
966 pub fn linuxTriple(self: Target, allocator: *mem.Allocator) ![]u8 {971 pub fn linuxTriple(self: Target, allocator: *mem.Allocator) ![]u8 {
967 return std.fmt.allocPrint(allocator, "{}-{}-{}", .{972 return std.fmt.allocPrint(allocator, "{}-{}-{}", .{
968 @tagName(self.getArch()),973 @tagName(self.cpu.arch),
969 @tagName(self.os),974 @tagName(self.os.tag),
970 @tagName(self.abi),975 @tagName(self.abi),
971 });976 });
972 }977 }
...@@ -1017,11 +1022,28 @@ pub const Target = struct {...@@ -1017,11 +1022,28 @@ pub const Target = struct {
1017 diags.arch = arch;1022 diags.arch = arch;
10181023
1019 const os_name = it.next() orelse return error.MissingOperatingSystem;1024 const os_name = it.next() orelse return error.MissingOperatingSystem;
1020 var os = try Os.parse(os_name); // var because Abi.parse can update linux.glibc version1025 var os = try Os.parse(os_name);
1021 diags.os = os;1026 diags.os = os;
10221027
1023 const abi_name = it.next();1028 const opt_abi_text = it.next();
1024 const abi = if (abi_name) |n| try Abi.parse(n, &os) else Abi.default(arch, os);1029 const abi = if (opt_abi_text) |abi_text| blk: {
1030 var abi_it = mem.separate(abi_text, ".");
1031 const abi = std.meta.stringToEnum(Abi, abi_it.next().?) orelse
1032 return error.UnknownApplicationBinaryInterface;
1033 const abi_ver_text = abi_it.rest();
1034 if (abi_ver_text.len != 0) {
1035 if (os.tag == .linux and abi.isGnu()) {
1036 os.version_range.linux.glibc = Version.parse(abi_ver_text) catch |err| switch (err) {
1037 error.Overflow => return error.InvalidAbiVersion,
1038 error.InvalidCharacter => return error.InvalidAbiVersion,
1039 error.InvalidVersion => return error.InvalidAbiVersion,
1040 };
1041 } else {
1042 return error.InvalidAbiVersion;
1043 }
1044 }
1045 break :blk abi;
1046 } else Abi.default(arch, os);
1025 diags.abi = abi;1047 diags.abi = abi;
10261048
1027 if (it.next() != null) return error.UnexpectedExtraField;1049 if (it.next() != null) return error.UnexpectedExtraField;
...@@ -1130,25 +1152,6 @@ pub const Target = struct {...@@ -1130,25 +1152,6 @@ pub const Target = struct {
1130 }1152 }
1131 }1153 }
11321154
1133 /// Deprecated; access the `os` field directly.
1134 pub fn getOs(self: Target) @TagType(Os) {
1135 return self.os;
1136 }
1137
1138 /// Deprecated; access the `cpu` field directly.
1139 pub fn getCpu(self: Target) Cpu {
1140 return self.cpu;
1141 }
1142
1143 /// Deprecated; access the `abi` field directly.
1144 pub fn getAbi(self: Target) Abi {
1145 return self.abi;
1146 }
1147
1148 pub fn getArch(self: Target) Cpu.Arch {
1149 return self.cpu.arch;
1150 }
1151
1152 pub fn getObjectFormat(self: Target) ObjectFormat {1155 pub fn getObjectFormat(self: Target) ObjectFormat {
1153 if (self.isWindows() or self.isUefi()) {1156 if (self.isWindows() or self.isUefi()) {
1154 return .coff;1157 return .coff;
...@@ -1170,28 +1173,25 @@ pub const Target = struct {...@@ -1170,28 +1173,25 @@ pub const Target = struct {
1170 }1173 }
11711174
1172 pub fn isMusl(self: Target) bool {1175 pub fn isMusl(self: Target) bool {
1173 return switch (self.abi) {1176 return self.abi.isMusl();
1174 .musl, .musleabi, .musleabihf => true,
1175 else => false,
1176 };
1177 }1177 }
11781178
1179 pub fn isDarwin(self: Target) bool {1179 pub fn isDarwin(self: Target) bool {
1180 return switch (self.os) {1180 return switch (self.os.tag) {
1181 .ios, .macosx, .watchos, .tvos => true,1181 .ios, .macosx, .watchos, .tvos => true,
1182 else => false,1182 else => false,
1183 };1183 };
1184 }1184 }
11851185
1186 pub fn isWindows(self: Target) bool {1186 pub fn isWindows(self: Target) bool {
1187 return switch (self.os) {1187 return switch (self.os.tag) {
1188 .windows => true,1188 .windows => true,
1189 else => false,1189 else => false,
1190 };1190 };
1191 }1191 }
11921192
1193 pub fn isLinux(self: Target) bool {1193 pub fn isLinux(self: Target) bool {
1194 return switch (self.os) {1194 return switch (self.os.tag) {
1195 .linux => true,1195 .linux => true,
1196 else => false,1196 else => false,
1197 };1197 };
...@@ -1205,40 +1205,41 @@ pub const Target = struct {...@@ -1205,40 +1205,41 @@ pub const Target = struct {
1205 }1205 }
12061206
1207 pub fn isDragonFlyBSD(self: Target) bool {1207 pub fn isDragonFlyBSD(self: Target) bool {
1208 return switch (self.os) {1208 return switch (self.os.tag) {
1209 .dragonfly => true,1209 .dragonfly => true,
1210 else => false,1210 else => false,
1211 };1211 };
1212 }1212 }
12131213
1214 pub fn isUefi(self: Target) bool {1214 pub fn isUefi(self: Target) bool {
1215 return switch (self.os) {1215 return switch (self.os.tag) {
1216 .uefi => true,1216 .uefi => true,
1217 else => false,1217 else => false,
1218 };1218 };
1219 }1219 }
12201220
1221 pub fn isWasm(self: Target) bool {1221 pub fn isWasm(self: Target) bool {
1222 return switch (self.getArch()) {1222 return self.cpu.arch.isWasm();
1223 .wasm32, .wasm64 => true,
1224 else => false,
1225 };
1226 }1223 }
12271224
1228 pub fn isFreeBSD(self: Target) bool {1225 pub fn isFreeBSD(self: Target) bool {
1229 return switch (self.os) {1226 return switch (self.os.tag) {
1230 .freebsd => true,1227 .freebsd => true,
1231 else => false,1228 else => false,
1232 };1229 };
1233 }1230 }
12341231
1235 pub fn isNetBSD(self: Target) bool {1232 pub fn isNetBSD(self: Target) bool {
1236 return switch (self.os) {1233 return switch (self.os.tag) {
1237 .netbsd => true,1234 .netbsd => true,
1238 else => false,1235 else => false,
1239 };1236 };
1240 }1237 }
12411238
1239 pub fn isGnuLibC(self: Target) bool {
1240 return self.os.tag == .linux and self.abi.isGnu();
1241 }
1242
1242 pub fn wantSharedLibSymLinks(self: Target) bool {1243 pub fn wantSharedLibSymLinks(self: Target) bool {
1243 return !self.isWindows();1244 return !self.isWindows();
1244 }1245 }
...@@ -1248,7 +1249,7 @@ pub const Target = struct {...@@ -1248,7 +1249,7 @@ pub const Target = struct {
1248 }1249 }
12491250
1250 pub fn getArchPtrBitWidth(self: Target) u32 {1251 pub fn getArchPtrBitWidth(self: Target) u32 {
1251 switch (self.getArch()) {1252 switch (self.cpu.arch) {
1252 .avr,1253 .avr,
1253 .msp430,1254 .msp430,
1254 => return 16,1255 => return 16,
...@@ -1323,8 +1324,8 @@ pub const Target = struct {...@@ -1323,8 +1324,8 @@ pub const Target = struct {
1323 if (@as(@TagType(Target), self) == .Native) return .native;1324 if (@as(@TagType(Target), self) == .Native) return .native;
13241325
1325 // If the target OS matches the host OS, we can use QEMU to emulate a foreign architecture.1326 // If the target OS matches the host OS, we can use QEMU to emulate a foreign architecture.
1326 if (self.os == builtin.os) {1327 if (self.os.tag == builtin.os.tag) {
1327 return switch (self.getArch()) {1328 return switch (self.cpu.arch) {
1328 .aarch64 => Executor{ .qemu = "qemu-aarch64" },1329 .aarch64 => Executor{ .qemu = "qemu-aarch64" },
1329 .aarch64_be => Executor{ .qemu = "qemu-aarch64_be" },1330 .aarch64_be => Executor{ .qemu = "qemu-aarch64_be" },
1330 .arm => Executor{ .qemu = "qemu-arm" },1331 .arm => Executor{ .qemu = "qemu-arm" },
...@@ -1381,13 +1382,10 @@ pub const Target = struct {...@@ -1381,13 +1382,10 @@ pub const Target = struct {
1381 }1382 }
13821383
1383 pub fn hasDynamicLinker(self: Target) bool {1384 pub fn hasDynamicLinker(self: Target) bool {
1384 switch (self.getArch()) {1385 if (self.cpu.arch.isWasm()) {
1385 .wasm32,1386 return false;
1386 .wasm64,
1387 => return false,
1388 else => {},
1389 }1387 }
1390 switch (self.os) {1388 switch (self.os.tag) {
1391 .freestanding,1389 .freestanding,
1392 .ios,1390 .ios,
1393 .tvos,1391 .tvos,
...@@ -1424,7 +1422,7 @@ pub const Target = struct {...@@ -1424,7 +1422,7 @@ pub const Target = struct {
1424 defer result.deinit();1422 defer result.deinit();
14251423
1426 var is_arm = false;1424 var is_arm = false;
1427 switch (self.getArch()) {1425 switch (self.cpu.arch) {
1428 .arm, .thumb => {1426 .arm, .thumb => {
1429 try result.append("arm");1427 try result.append("arm");
1430 is_arm = true;1428 is_arm = true;
...@@ -1442,11 +1440,11 @@ pub const Target = struct {...@@ -1442,11 +1440,11 @@ pub const Target = struct {
1442 return result.toOwnedSlice();1440 return result.toOwnedSlice();
1443 }1441 }
14441442
1445 switch (self.os) {1443 switch (self.os.tag) {
1446 .freebsd => return mem.dupeZ(a, u8, "/libexec/ld-elf.so.1"),1444 .freebsd => return mem.dupeZ(a, u8, "/libexec/ld-elf.so.1"),
1447 .netbsd => return mem.dupeZ(a, u8, "/libexec/ld.elf_so"),1445 .netbsd => return mem.dupeZ(a, u8, "/libexec/ld.elf_so"),
1448 .dragonfly => return mem.dupeZ(a, u8, "/libexec/ld-elf.so.2"),1446 .dragonfly => return mem.dupeZ(a, u8, "/libexec/ld-elf.so.2"),
1449 .linux => switch (self.getArch()) {1447 .linux => switch (self.cpu.arch) {
1450 .i386,1448 .i386,
1451 .sparc,1449 .sparc,
1452 .sparcel,1450 .sparcel,
...@@ -1539,7 +1537,7 @@ test "Target.parse" {...@@ -1539,7 +1537,7 @@ test "Target.parse" {
1539 .cpu_features = "x86_64-sse-sse2-avx-cx8",1537 .cpu_features = "x86_64-sse-sse2-avx-cx8",
1540 });1538 });
15411539
1542 std.testing.expect(target.os == .linux);1540 std.testing.expect(target.os.tag == .linux);
1543 std.testing.expect(target.abi == .gnu);1541 std.testing.expect(target.abi == .gnu);
1544 std.testing.expect(target.cpu.arch == .x86_64);1542 std.testing.expect(target.cpu.arch == .x86_64);
1545 std.testing.expect(!Target.x86.featureSetHas(target.cpu.features, .sse));1543 std.testing.expect(!Target.x86.featureSetHas(target.cpu.features, .sse));
...@@ -1554,10 +1552,29 @@ test "Target.parse" {...@@ -1554,10 +1552,29 @@ test "Target.parse" {
1554 .cpu_features = "generic+v8a",1552 .cpu_features = "generic+v8a",
1555 });1553 });
15561554
1557 std.testing.expect(target.os == .linux);1555 std.testing.expect(target.os.tag == .linux);
1558 std.testing.expect(target.abi == .musleabihf);1556 std.testing.expect(target.abi == .musleabihf);
1559 std.testing.expect(target.cpu.arch == .arm);1557 std.testing.expect(target.cpu.arch == .arm);
1560 std.testing.expect(target.cpu.model == &Target.arm.cpu.generic);1558 std.testing.expect(target.cpu.model == &Target.arm.cpu.generic);
1561 std.testing.expect(Target.arm.featureSetHas(target.cpu.features, .v8a));1559 std.testing.expect(Target.arm.featureSetHas(target.cpu.features, .v8a));
1562 }1560 }
1561 {
1562 const target = try Target.parse(.{
1563 .arch_os_abi = "aarch64-linux.3.10...4.4.1-gnu.2.27",
1564 .cpu_features = "generic+v8a",
1565 });
1566
1567 std.testing.expect(target.cpu.arch == .aarch64);
1568 std.testing.expect(target.os.tag == .linux);
1569 std.testing.expect(target.os.version_range.linux.min.major == 3);
1570 std.testing.expect(target.os.version_range.linux.min.minor == 10);
1571 std.testing.expect(target.os.version_range.linux.min.patch == 0);
1572 std.testing.expect(target.os.version_range.linux.max.major == 4);
1573 std.testing.expect(target.os.version_range.linux.max.minor == 4);
1574 std.testing.expect(target.os.version_range.linux.max.patch == 1);
1575 std.testing.expect(target.os.version_range.linux.glibc.major == 2);
1576 std.testing.expect(target.os.version_range.linux.glibc.minor == 27);
1577 std.testing.expect(target.os.version_range.linux.glibc.patch == 0);
1578 std.testing.expect(target.abi == .gnu);
1579 }
1563}1580}
lib/std/thread.zig+10-10
...@@ -9,14 +9,14 @@ const assert = std.debug.assert;...@@ -9,14 +9,14 @@ const assert = std.debug.assert;
9pub const Thread = struct {9pub const Thread = struct {
10 data: Data,10 data: Data,
1111
12 pub const use_pthreads = builtin.os != .windows and builtin.link_libc;12 pub const use_pthreads = builtin.os.tag != .windows and builtin.link_libc;
1313
14 /// Represents a kernel thread handle.14 /// Represents a kernel thread handle.
15 /// May be an integer or a pointer depending on the platform.15 /// May be an integer or a pointer depending on the platform.
16 /// On Linux and POSIX, this is the same as Id.16 /// On Linux and POSIX, this is the same as Id.
17 pub const Handle = if (use_pthreads)17 pub const Handle = if (use_pthreads)
18 c.pthread_t18 c.pthread_t
19 else switch (builtin.os) {19 else switch (builtin.os.tag) {
20 .linux => i32,20 .linux => i32,
21 .windows => windows.HANDLE,21 .windows => windows.HANDLE,
22 else => void,22 else => void,
...@@ -25,7 +25,7 @@ pub const Thread = struct {...@@ -25,7 +25,7 @@ pub const Thread = struct {
25 /// Represents a unique ID per thread.25 /// Represents a unique ID per thread.
26 /// May be an integer or pointer depending on the platform.26 /// May be an integer or pointer depending on the platform.
27 /// On Linux and POSIX, this is the same as Handle.27 /// On Linux and POSIX, this is the same as Handle.
28 pub const Id = switch (builtin.os) {28 pub const Id = switch (builtin.os.tag) {
29 .windows => windows.DWORD,29 .windows => windows.DWORD,
30 else => Handle,30 else => Handle,
31 };31 };
...@@ -35,7 +35,7 @@ pub const Thread = struct {...@@ -35,7 +35,7 @@ pub const Thread = struct {
35 handle: Thread.Handle,35 handle: Thread.Handle,
36 memory: []align(mem.page_size) u8,36 memory: []align(mem.page_size) u8,
37 }37 }
38 else switch (builtin.os) {38 else switch (builtin.os.tag) {
39 .linux => struct {39 .linux => struct {
40 handle: Thread.Handle,40 handle: Thread.Handle,
41 memory: []align(mem.page_size) u8,41 memory: []align(mem.page_size) u8,
...@@ -55,7 +55,7 @@ pub const Thread = struct {...@@ -55,7 +55,7 @@ pub const Thread = struct {
55 if (use_pthreads) {55 if (use_pthreads) {
56 return c.pthread_self();56 return c.pthread_self();
57 } else57 } else
58 return switch (builtin.os) {58 return switch (builtin.os.tag) {
59 .linux => os.linux.gettid(),59 .linux => os.linux.gettid(),
60 .windows => windows.kernel32.GetCurrentThreadId(),60 .windows => windows.kernel32.GetCurrentThreadId(),
61 else => @compileError("Unsupported OS"),61 else => @compileError("Unsupported OS"),
...@@ -83,7 +83,7 @@ pub const Thread = struct {...@@ -83,7 +83,7 @@ pub const Thread = struct {
83 else => unreachable,83 else => unreachable,
84 }84 }
85 os.munmap(self.data.memory);85 os.munmap(self.data.memory);
86 } else switch (builtin.os) {86 } else switch (builtin.os.tag) {
87 .linux => {87 .linux => {
88 while (true) {88 while (true) {
89 const pid_value = @atomicLoad(i32, &self.data.handle, .SeqCst);89 const pid_value = @atomicLoad(i32, &self.data.handle, .SeqCst);
...@@ -150,7 +150,7 @@ pub const Thread = struct {...@@ -150,7 +150,7 @@ pub const Thread = struct {
150 const Context = @TypeOf(context);150 const Context = @TypeOf(context);
151 comptime assert(@typeInfo(@TypeOf(startFn)).Fn.args[0].arg_type.? == Context);151 comptime assert(@typeInfo(@TypeOf(startFn)).Fn.args[0].arg_type.? == Context);
152152
153 if (builtin.os == builtin.Os.windows) {153 if (builtin.os.tag == .windows) {
154 const WinThread = struct {154 const WinThread = struct {
155 const OuterContext = struct {155 const OuterContext = struct {
156 thread: Thread,156 thread: Thread,
...@@ -309,7 +309,7 @@ pub const Thread = struct {...@@ -309,7 +309,7 @@ pub const Thread = struct {
309 os.EINVAL => unreachable,309 os.EINVAL => unreachable,
310 else => return os.unexpectedErrno(@intCast(usize, err)),310 else => return os.unexpectedErrno(@intCast(usize, err)),
311 }311 }
312 } else if (builtin.os == .linux) {312 } else if (builtin.os.tag == .linux) {
313 var flags: u32 = os.CLONE_VM | os.CLONE_FS | os.CLONE_FILES | os.CLONE_SIGHAND |313 var flags: u32 = os.CLONE_VM | os.CLONE_FS | os.CLONE_FILES | os.CLONE_SIGHAND |
314 os.CLONE_THREAD | os.CLONE_SYSVSEM | os.CLONE_PARENT_SETTID | os.CLONE_CHILD_CLEARTID |314 os.CLONE_THREAD | os.CLONE_SYSVSEM | os.CLONE_PARENT_SETTID | os.CLONE_CHILD_CLEARTID |
315 os.CLONE_DETACHED;315 os.CLONE_DETACHED;
...@@ -369,11 +369,11 @@ pub const Thread = struct {...@@ -369,11 +369,11 @@ pub const Thread = struct {
369 };369 };
370370
371 pub fn cpuCount() CpuCountError!usize {371 pub fn cpuCount() CpuCountError!usize {
372 if (builtin.os == .linux) {372 if (builtin.os.tag == .linux) {
373 const cpu_set = try os.sched_getaffinity(0);373 const cpu_set = try os.sched_getaffinity(0);
374 return @as(usize, os.CPU_COUNT(cpu_set)); // TODO should not need this usize cast374 return @as(usize, os.CPU_COUNT(cpu_set)); // TODO should not need this usize cast
375 }375 }
376 if (builtin.os == .windows) {376 if (builtin.os.tag == .windows) {
377 var system_info: windows.SYSTEM_INFO = undefined;377 var system_info: windows.SYSTEM_INFO = undefined;
378 windows.kernel32.GetSystemInfo(&system_info);378 windows.kernel32.GetSystemInfo(&system_info);
379 return @intCast(usize, system_info.dwNumberOfProcessors);379 return @intCast(usize, system_info.dwNumberOfProcessors);
lib/std/time.zig+10-8
...@@ -1,5 +1,5 @@...@@ -1,5 +1,5 @@
1const builtin = @import("builtin");
2const std = @import("std.zig");1const std = @import("std.zig");
2const builtin = std.builtin;
3const assert = std.debug.assert;3const assert = std.debug.assert;
4const testing = std.testing;4const testing = std.testing;
5const os = std.os;5const os = std.os;
...@@ -7,10 +7,12 @@ const math = std.math;...@@ -7,10 +7,12 @@ const math = std.math;
77
8pub const epoch = @import("time/epoch.zig");8pub const epoch = @import("time/epoch.zig");
99
10const is_windows = std.Target.current.os.tag == .windows;
11
10/// Spurious wakeups are possible and no precision of timing is guaranteed.12/// Spurious wakeups are possible and no precision of timing is guaranteed.
11/// TODO integrate with evented I/O13/// TODO integrate with evented I/O
12pub fn sleep(nanoseconds: u64) void {14pub fn sleep(nanoseconds: u64) void {
13 if (builtin.os == .windows) {15 if (is_windows) {
14 const ns_per_ms = ns_per_s / ms_per_s;16 const ns_per_ms = ns_per_s / ms_per_s;
15 const big_ms_from_ns = nanoseconds / ns_per_ms;17 const big_ms_from_ns = nanoseconds / ns_per_ms;
16 const ms = math.cast(os.windows.DWORD, big_ms_from_ns) catch math.maxInt(os.windows.DWORD);18 const ms = math.cast(os.windows.DWORD, big_ms_from_ns) catch math.maxInt(os.windows.DWORD);
...@@ -31,7 +33,7 @@ pub fn timestamp() u64 {...@@ -31,7 +33,7 @@ pub fn timestamp() u64 {
31/// Get the posix timestamp, UTC, in milliseconds33/// Get the posix timestamp, UTC, in milliseconds
32/// TODO audit this function. is it possible to return an error?34/// TODO audit this function. is it possible to return an error?
33pub fn milliTimestamp() u64 {35pub fn milliTimestamp() u64 {
34 if (builtin.os == .windows) {36 if (is_windows) {
35 //FileTime has a granularity of 100 nanoseconds37 //FileTime has a granularity of 100 nanoseconds
36 // and uses the NTFS/Windows epoch38 // and uses the NTFS/Windows epoch
37 var ft: os.windows.FILETIME = undefined;39 var ft: os.windows.FILETIME = undefined;
...@@ -42,7 +44,7 @@ pub fn milliTimestamp() u64 {...@@ -42,7 +44,7 @@ pub fn milliTimestamp() u64 {
42 const ft64 = (@as(u64, ft.dwHighDateTime) << 32) | ft.dwLowDateTime;44 const ft64 = (@as(u64, ft.dwHighDateTime) << 32) | ft.dwLowDateTime;
43 return @divFloor(ft64, hns_per_ms) - -epoch_adj;45 return @divFloor(ft64, hns_per_ms) - -epoch_adj;
44 }46 }
45 if (builtin.os == .wasi and !builtin.link_libc) {47 if (builtin.os.tag == .wasi and !builtin.link_libc) {
46 var ns: os.wasi.timestamp_t = undefined;48 var ns: os.wasi.timestamp_t = undefined;
4749
48 // TODO: Verify that precision is ignored50 // TODO: Verify that precision is ignored
...@@ -102,7 +104,7 @@ pub const Timer = struct {...@@ -102,7 +104,7 @@ pub const Timer = struct {
102 ///if we used resolution's value when performing the104 ///if we used resolution's value when performing the
103 /// performance counter calc on windows/darwin, it would105 /// performance counter calc on windows/darwin, it would
104 /// be less precise106 /// be less precise
105 frequency: switch (builtin.os) {107 frequency: switch (builtin.os.tag) {
106 .windows => u64,108 .windows => u64,
107 .macosx, .ios, .tvos, .watchos => os.darwin.mach_timebase_info_data,109 .macosx, .ios, .tvos, .watchos => os.darwin.mach_timebase_info_data,
108 else => void,110 else => void,
...@@ -127,7 +129,7 @@ pub const Timer = struct {...@@ -127,7 +129,7 @@ pub const Timer = struct {
127 pub fn start() Error!Timer {129 pub fn start() Error!Timer {
128 var self: Timer = undefined;130 var self: Timer = undefined;
129131
130 if (builtin.os == .windows) {132 if (is_windows) {
131 self.frequency = os.windows.QueryPerformanceFrequency();133 self.frequency = os.windows.QueryPerformanceFrequency();
132 self.resolution = @divFloor(ns_per_s, self.frequency);134 self.resolution = @divFloor(ns_per_s, self.frequency);
133 self.start_time = os.windows.QueryPerformanceCounter();135 self.start_time = os.windows.QueryPerformanceCounter();
...@@ -172,7 +174,7 @@ pub const Timer = struct {...@@ -172,7 +174,7 @@ pub const Timer = struct {
172 }174 }
173175
174 fn clockNative() u64 {176 fn clockNative() u64 {
175 if (builtin.os == .windows) {177 if (is_windows) {
176 return os.windows.QueryPerformanceCounter();178 return os.windows.QueryPerformanceCounter();
177 }179 }
178 if (comptime std.Target.current.isDarwin()) {180 if (comptime std.Target.current.isDarwin()) {
...@@ -184,7 +186,7 @@ pub const Timer = struct {...@@ -184,7 +186,7 @@ pub const Timer = struct {
184 }186 }
185187
186 fn nativeDurationToNanos(self: Timer, duration: u64) u64 {188 fn nativeDurationToNanos(self: Timer, duration: u64) u64 {
187 if (builtin.os == .windows) {189 if (is_windows) {
188 return @divFloor(duration * ns_per_s, self.frequency);190 return @divFloor(duration * ns_per_s, self.frequency);
189 }191 }
190 if (comptime std.Target.current.isDarwin()) {192 if (comptime std.Target.current.isDarwin()) {
lib/std/zig/system.zig+328-2
...@@ -1,11 +1,14 @@...@@ -1,11 +1,14 @@
1const std = @import("../std.zig");1const std = @import("../std.zig");
2const elf = std.elf;
2const mem = std.mem;3const mem = std.mem;
4const fs = std.fs;
3const Allocator = std.mem.Allocator;5const Allocator = std.mem.Allocator;
4const ArrayList = std.ArrayList;6const ArrayList = std.ArrayList;
5const assert = std.debug.assert;7const assert = std.debug.assert;
6const process = std.process;8const process = std.process;
9const Target = std.Target;
710
8const is_windows = std.Target.current.isWindows();11const is_windows = Target.current.os.tag == .windows;
912
10pub const NativePaths = struct {13pub const NativePaths = struct {
11 include_dirs: ArrayList([:0]u8),14 include_dirs: ArrayList([:0]u8),
...@@ -77,7 +80,7 @@ pub const NativePaths = struct {...@@ -77,7 +80,7 @@ pub const NativePaths = struct {
77 }80 }
7881
79 if (!is_windows) {82 if (!is_windows) {
80 const triple = try std.Target.current.linuxTriple(allocator);83 const triple = try Target.current.linuxTriple(allocator);
8184
82 // TODO: $ ld --verbose | grep SEARCH_DIR85 // TODO: $ ld --verbose | grep SEARCH_DIR
83 // the output contains some paths that end with lib64, maybe include them too?86 // the output contains some paths that end with lib64, maybe include them too?
...@@ -161,3 +164,326 @@ pub const NativePaths = struct {...@@ -161,3 +164,326 @@ pub const NativePaths = struct {
161 try array.append(item);164 try array.append(item);
162 }165 }
163};166};
167
168pub const NativeTargetInfo = struct {
169 target: Target,
170 dynamic_linker: ?[:0]u8,
171
172 pub const DetectError = error{
173 OutOfMemory,
174 FileSystem,
175 SystemResources,
176 SymLinkLoop,
177 ProcessFdQuotaExceeded,
178 SystemFdQuotaExceeded,
179 DeviceBusy,
180 };
181
182 /// Detects the native CPU model & features, operating system & version, and C ABI & dynamic linker.
183 /// On Linux, this is additionally responsible for detecting the native glibc version when applicable.
184 pub fn detect(allocator: *Allocator) DetectError!NativeTargetInfo {
185 const arch = Target.current.cpu.arch;
186 const os_tag = Target.current.os.tag;
187
188 // TODO Detect native CPU model & features. Until that is implemented we hard code baseline.
189 const cpu = Target.Cpu.baseline(arch);
190
191 // TODO Detect native operating system version. Until that is implemented we use the minimum version
192 // of the default range.
193 const os = Target.Os.defaultVersionRange(os_tag);
194
195 return detectAbiAndDynamicLinker(allocator, cpu, os);
196 }
197
198 /// Must be the same `Allocator` passed to `detect`.
199 pub fn deinit(self: *NativeTargetInfo, allocator: *Allocator) void {
200 if (self.dynamic_linker) |dl| allocator.free(dl);
201 self.* = undefined;
202 }
203
204 /// First we attempt to use the executable's own binary. If it is dynamically
205 /// linked, then it should answer both the C ABI question and the dynamic linker question.
206 /// If it is statically linked, then we try /usr/bin/env. If that does not provide the answer, then
207 /// we fall back to the defaults.
208 fn detectAbiAndDynamicLinker(
209 allocator: *Allocator,
210 cpu: Target.Cpu,
211 os: Target.Os,
212 ) DetectError!NativeTargetInfo {
213 if (!comptime Target.current.hasDynamicLinker()) {
214 return defaultAbiAndDynamicLinker(allocator, cpu, os);
215 }
216 // The current target's ABI cannot be relied on for this. For example, we may build the zig
217 // compiler for target riscv64-linux-musl and provide a tarball for users to download.
218 // A user could then run that zig compiler on riscv64-linux-gnu. This use case is well-defined
219 // and supported by Zig. But that means that we must detect the system ABI here rather than
220 // relying on `Target.current`.
221 const LdInfo = struct {
222 ld_path: []u8,
223 abi: Target.Abi,
224 };
225 var ld_info_list = std.ArrayList(LdInfo).init(allocator);
226 defer {
227 for (ld_info_list.toSlice()) |ld_info| allocator.free(ld_info.ld_path);
228 ld_info_list.deinit();
229 }
230
231 const all_abis = comptime blk: {
232 assert(@enumToInt(Target.Abi.none) == 0);
233 const fields = std.meta.fields(Target.Abi)[1..];
234 var array: [fields.len]Target.Abi = undefined;
235 inline for (fields) |field, i| {
236 array[i] = @field(Target.Abi, field.name);
237 }
238 break :blk array;
239 };
240 for (all_abis) |abi| {
241 // This may be a nonsensical parameter. We detect this with error.UnknownDynamicLinkerPath and
242 // skip adding it to `ld_info_list`.
243 const target: Target = .{
244 .cpu = cpu,
245 .os = os,
246 .abi = abi,
247 };
248 const standard_ld_path = target.getStandardDynamicLinkerPath(allocator) catch |err| switch (err) {
249 error.OutOfMemory => return error.OutOfMemory,
250 error.UnknownDynamicLinkerPath, error.TargetHasNoDynamicLinker => continue,
251 };
252 errdefer allocator.free(standard_ld_path);
253 try ld_info_list.append(.{
254 .ld_path = standard_ld_path,
255 .abi = abi,
256 });
257 }
258
259 // Best case scenario: the executable is dynamically linked, and we can iterate
260 // over our own shared objects and find a dynamic linker.
261 self_exe: {
262 const lib_paths = try std.process.getSelfExeSharedLibPaths(allocator);
263 defer allocator.free(lib_paths);
264
265 var found_ld_info: LdInfo = undefined;
266 var found_ld_path: [:0]const u8 = undefined;
267
268 // Look for dynamic linker.
269 // This is O(N^M) but typical case here is N=2 and M=10.
270 find_ld: for (lib_paths) |lib_path| {
271 for (ld_info_list.toSlice()) |ld_info| {
272 const standard_ld_basename = fs.path.basename(ld_info.ld_path);
273 if (std.mem.endsWith(u8, lib_path, standard_ld_basename)) {
274 found_ld_info = ld_info;
275 found_ld_path = lib_path;
276 break :find_ld;
277 }
278 }
279 } else break :self_exe;
280
281 // Look for glibc version.
282 var os_adjusted = os;
283 if (Target.current.os.tag == .linux and found_ld_info.abi.isGnu()) {
284 for (lib_paths) |lib_path| {
285 if (std.mem.endsWith(u8, lib_path, glibc_so_basename)) {
286 os_adjusted.version_range.linux.glibc = glibcVerFromSO(lib_path) catch |err| switch (err) {
287 error.UnrecognizedGnuLibCFileName => continue,
288 error.InvalidGnuLibCVersion => continue,
289 error.GnuLibCVersionUnavailable => continue,
290 else => |e| return e,
291 };
292 break;
293 }
294 }
295 }
296
297 return NativeTargetInfo{
298 .target = .{
299 .cpu = cpu,
300 .os = os_adjusted,
301 .abi = found_ld_info.abi,
302 },
303 .dynamic_linker = try mem.dupeZ(allocator, u8, found_ld_path),
304 };
305 }
306
307 // If Zig is statically linked, such as via distributed binary static builds, the above
308 // trick won't work. The next thing we fall back to is the same thing, but for /usr/bin/env.
309 // Since that path is hard-coded into the shebang line of many portable scripts, it's a
310 // reasonably reliable path to check for.
311 return abiAndDynamicLinkerFromUsrBinEnv(allocator, cpu, os) catch |err| switch (err) {
312 error.OutOfMemory => return error.OutOfMemory,
313 error.FileSystem => return error.FileSystem,
314 error.SystemResources => return error.SystemResources,
315 error.SymLinkLoop => return error.SymLinkLoop,
316 error.ProcessFdQuotaExceeded => return error.ProcessFdQuotaExceeded,
317 error.SystemFdQuotaExceeded => return error.SystemFdQuotaExceeded,
318 error.DeviceBusy => return error.DeviceBusy,
319
320 error.UnableToReadElfFile,
321 error.ElfNotADynamicExecutable,
322 error.InvalidElfProgramHeaders,
323 error.InvalidElfClass,
324 error.InvalidElfVersion,
325 error.InvalidElfEndian,
326 error.InvalidElfFile,
327 error.InvalidElfMagic,
328 error.UsrBinEnvNotAvailable,
329 error.Unexpected,
330 // Finally, we fall back on the standard path.
331 => defaultAbiAndDynamicLinker(allocator, cpu, os),
332 };
333 }
334
335 const glibc_so_basename = "libc.so.6";
336
337 fn glibcVerFromSO(so_path: [:0]const u8) !std.builtin.Version {
338 var link_buf: [std.os.PATH_MAX]u8 = undefined;
339 const link_name = std.os.readlinkC(so_path.ptr, &link_buf) catch |err| switch (err) {
340 error.AccessDenied => return error.GnuLibCVersionUnavailable,
341 error.FileSystem => return error.FileSystem,
342 error.SymLinkLoop => return error.SymLinkLoop,
343 error.NameTooLong => unreachable,
344 error.FileNotFound => return error.GnuLibCVersionUnavailable,
345 error.SystemResources => return error.SystemResources,
346 error.NotDir => return error.GnuLibCVersionUnavailable,
347 error.Unexpected => return error.GnuLibCVersionUnavailable,
348 };
349 // example: "libc-2.3.4.so"
350 // example: "libc-2.27.so"
351 const prefix = "libc-";
352 const suffix = ".so";
353 if (!mem.startsWith(u8, link_name, prefix) or !mem.endsWith(u8, link_name, suffix)) {
354 return error.UnrecognizedGnuLibCFileName;
355 }
356 // chop off "libc-" and ".so"
357 const link_name_chopped = link_name[prefix.len .. link_name.len - suffix.len];
358 return std.builtin.Version.parse(link_name_chopped) catch |err| switch (err) {
359 error.Overflow => return error.InvalidGnuLibCVersion,
360 error.InvalidCharacter => return error.InvalidGnuLibCVersion,
361 error.InvalidVersion => return error.InvalidGnuLibCVersion,
362 };
363 }
364
365 fn abiAndDynamicLinkerFromUsrBinEnv(
366 allocator: *Allocator,
367 cpu: Target.Cpu,
368 os: Target.Os,
369 ) !NativeTargetInfo {
370 const env_file = std.fs.openFileAbsoluteC("/usr/bin/env", .{}) catch |err| switch (err) {
371 error.NoSpaceLeft => unreachable,
372 error.NameTooLong => unreachable,
373 error.PathAlreadyExists => unreachable,
374 error.SharingViolation => unreachable,
375 error.InvalidUtf8 => unreachable,
376 error.BadPathName => unreachable,
377 error.PipeBusy => unreachable,
378
379 error.IsDir => return error.UsrBinEnvNotAvailable,
380 error.NotDir => return error.UsrBinEnvNotAvailable,
381 error.AccessDenied => return error.UsrBinEnvNotAvailable,
382 error.NoDevice => return error.UsrBinEnvNotAvailable,
383 error.FileNotFound => return error.UsrBinEnvNotAvailable,
384 error.FileTooBig => return error.UsrBinEnvNotAvailable,
385
386 else => |e| return e,
387 };
388 var hdr_buf: [@sizeOf(elf.Elf64_Ehdr)]u8 align(@alignOf(elf.Elf64_Ehdr)) = undefined;
389 const hdr_bytes_len = try wrapRead(env_file.pread(&hdr_buf, 0));
390 if (hdr_bytes_len < @sizeOf(elf.Elf32_Ehdr)) return error.InvalidElfFile;
391 const hdr32 = @ptrCast(*elf.Elf32_Ehdr, &hdr_buf);
392 const hdr64 = @ptrCast(*elf.Elf64_Ehdr, &hdr_buf);
393 if (!mem.eql(u8, hdr32.e_ident[0..4], "\x7fELF")) return error.InvalidElfMagic;
394 const elf_endian: std.builtin.Endian = switch (hdr32.e_ident[elf.EI_DATA]) {
395 elf.ELFDATA2LSB => .Little,
396 elf.ELFDATA2MSB => .Big,
397 else => return error.InvalidElfEndian,
398 };
399 const need_bswap = elf_endian != std.builtin.endian;
400 if (hdr32.e_ident[elf.EI_VERSION] != 1) return error.InvalidElfVersion;
401
402 const is_64 = switch (hdr32.e_ident[elf.EI_CLASS]) {
403 elf.ELFCLASS32 => false,
404 elf.ELFCLASS64 => true,
405 else => return error.InvalidElfClass,
406 };
407 var phoff = elfInt(is_64, need_bswap, hdr32.e_phoff, hdr64.e_phoff);
408 const phentsize = elfInt(is_64, need_bswap, hdr32.e_phentsize, hdr64.e_phentsize);
409 const phnum = elfInt(is_64, need_bswap, hdr32.e_phnum, hdr64.e_phnum);
410 const shstrndx = elfInt(is_64, need_bswap, hdr32.e_shstrndx, hdr64.e_shstrndx);
411
412 const ph_total_size = std.math.mul(u32, phentsize, phnum) catch |err| switch (err) {
413 error.Overflow => return error.InvalidElfProgramHeaders,
414 };
415 var ph_buf: [16 * @sizeOf(elf.Elf64_Phdr)]u8 align(@alignOf(elf.Elf64_Phdr)) = undefined;
416 var ph_i: u16 = 0;
417 while (ph_i < phnum) {
418 // Reserve some bytes so that we can deref the 64-bit struct fields even when the ELF file is 32-bits.
419 const reserve = @sizeOf(elf.Elf64_Phdr) - @sizeOf(elf.Elf32_Phdr);
420 const read_byte_len = try wrapRead(env_file.pread(ph_buf[0 .. ph_buf.len - reserve], phoff));
421 if (read_byte_len < phentsize) return error.ElfNotADynamicExecutable;
422 var buf_i: usize = 0;
423 while (buf_i < read_byte_len and ph_i < phnum) : ({
424 ph_i += 1;
425 phoff += phentsize;
426 buf_i += phentsize;
427 }) {
428 const ph32 = @ptrCast(*elf.Elf32_Phdr, @alignCast(@alignOf(elf.Elf32_Phdr), &ph_buf[buf_i]));
429 const ph64 = @ptrCast(*elf.Elf64_Phdr, @alignCast(@alignOf(elf.Elf64_Phdr), &ph_buf[buf_i]));
430 const p_type = elfInt(is_64, need_bswap, ph32.p_type, ph64.p_type);
431 switch (p_type) {
432 elf.PT_INTERP => {
433 std.debug.warn("found PT_INTERP\n", .{});
434 },
435 elf.PT_DYNAMIC => {
436 std.debug.warn("found PT_DYNAMIC\n", .{});
437 },
438 else => continue,
439 }
440 }
441 }
442
443 return error.OutOfMemory; // TODO
444 }
445
446 fn wrapRead(res: std.os.ReadError!usize) !usize {
447 return res catch |err| switch (err) {
448 error.OperationAborted => unreachable, // Windows-only
449 error.WouldBlock => unreachable, // Did not request blocking mode
450 error.SystemResources => return error.SystemResources,
451 error.IsDir => return error.UnableToReadElfFile,
452 error.BrokenPipe => return error.UnableToReadElfFile,
453 error.ConnectionResetByPeer => return error.UnableToReadElfFile,
454 error.Unexpected => return error.Unexpected,
455 error.InputOutput => return error.FileSystem,
456 };
457 }
458
459 fn defaultAbiAndDynamicLinker(allocator: *Allocator, cpu: Target.Cpu, os: Target.Os) !NativeTargetInfo {
460 const target: Target = .{
461 .cpu = cpu,
462 .os = os,
463 .abi = Target.Abi.default(cpu.arch, os),
464 };
465 return @as(NativeTargetInfo, .{
466 .target = target,
467 .dynamic_linker = target.getStandardDynamicLinkerPath(allocator) catch |err| switch (err) {
468 error.OutOfMemory => return error.OutOfMemory,
469 error.UnknownDynamicLinkerPath, error.TargetHasNoDynamicLinker => null,
470 },
471 });
472 }
473};
474
475fn elfInt(is_64: bool, need_bswap: bool, int_32: var, int_64: var) @TypeOf(int_64) {
476 if (is_64) {
477 if (need_bswap) {
478 return @byteSwap(@TypeOf(int_64), int_64);
479 } else {
480 return int_64;
481 }
482 } else {
483 if (need_bswap) {
484 return @byteSwap(@TypeOf(int_32), int_32);
485 } else {
486 return int_32;
487 }
488 }
489}
src-self-hosted/c_int.zig+1-1
...@@ -70,7 +70,7 @@ pub const CInt = struct {...@@ -70,7 +70,7 @@ pub const CInt = struct {
7070
71 pub fn sizeInBits(cint: CInt, self: Target) u32 {71 pub fn sizeInBits(cint: CInt, self: Target) u32 {
72 const arch = self.getArch();72 const arch = self.getArch();
73 switch (self.getOs()) {73 switch (self.os.tag) {
74 .freestanding, .other => switch (self.getArch()) {74 .freestanding, .other => switch (self.getArch()) {
75 .msp430 => switch (cint.id) {75 .msp430 => switch (cint.id) {
76 .Short,76 .Short,
src-self-hosted/clang.zig+1-1
...@@ -1050,7 +1050,7 @@ pub const struct_ZigClangExprEvalResult = extern struct {...@@ -1050,7 +1050,7 @@ pub const struct_ZigClangExprEvalResult = extern struct {
10501050
1051pub const struct_ZigClangAPValue = extern struct {1051pub const struct_ZigClangAPValue = extern struct {
1052 Kind: ZigClangAPValueKind,1052 Kind: ZigClangAPValueKind,
1053 Data: if (builtin.os == .windows and builtin.abi == .msvc) [52]u8 else [68]u8,1053 Data: if (builtin.os.tag == .windows and builtin.abi == .msvc) [52]u8 else [68]u8,
1054};1054};
1055pub extern fn ZigClangVarDecl_getTypeSourceInfo_getType(self: *const struct_ZigClangVarDecl) struct_ZigClangQualType;1055pub extern fn ZigClangVarDecl_getTypeSourceInfo_getType(self: *const struct_ZigClangVarDecl) struct_ZigClangQualType;
10561056
src-self-hosted/introspect.zig+1-9
...@@ -1,4 +1,4 @@...@@ -1,4 +1,4 @@
1// Introspection and determination of system libraries needed by zig.1//! Introspection and determination of system libraries needed by zig.
22
3const std = @import("std");3const std = @import("std");
4const mem = std.mem;4const mem = std.mem;
...@@ -6,14 +6,6 @@ const fs = std.fs;...@@ -6,14 +6,6 @@ const fs = std.fs;
66
7const warn = std.debug.warn;7const warn = std.debug.warn;
88
9pub fn detectDynamicLinker(allocator: *mem.Allocator, target: std.Target) ![:0]u8 {
10 if (target == .Native) {
11 return @import("libc_installation.zig").detectNativeDynamicLinker(allocator);
12 } else {
13 return target.getStandardDynamicLinkerPath(allocator);
14 }
15}
16
17/// Caller must free result9/// Caller must free result
18pub fn testZigInstallPrefix(allocator: *mem.Allocator, test_path: []const u8) ![]u8 {10pub fn testZigInstallPrefix(allocator: *mem.Allocator, test_path: []const u8) ![]u8 {
19 const test_zig_dir = try fs.path.join(allocator, &[_][]const u8{ test_path, "lib", "zig" });11 const test_zig_dir = try fs.path.join(allocator, &[_][]const u8{ test_path, "lib", "zig" });
src-self-hosted/libc_installation.zig+7-105
...@@ -99,27 +99,27 @@ pub const LibCInstallation = struct {...@@ -99,27 +99,27 @@ pub const LibCInstallation = struct {
99 return error.ParseError;99 return error.ParseError;
100 }100 }
101 if (self.crt_dir == null and !is_darwin) {101 if (self.crt_dir == null and !is_darwin) {
102 try stderr.print("crt_dir may not be empty for {}\n", .{@tagName(Target.current.getOs())});102 try stderr.print("crt_dir may not be empty for {}\n", .{@tagName(Target.current.os.tag)});
103 return error.ParseError;103 return error.ParseError;
104 }104 }
105 if (self.static_crt_dir == null and is_windows and is_gnu) {105 if (self.static_crt_dir == null and is_windows and is_gnu) {
106 try stderr.print("static_crt_dir may not be empty for {}-{}\n", .{106 try stderr.print("static_crt_dir may not be empty for {}-{}\n", .{
107 @tagName(Target.current.getOs()),107 @tagName(Target.current.os.tag),
108 @tagName(Target.current.getAbi()),108 @tagName(Target.current.abi),
109 });109 });
110 return error.ParseError;110 return error.ParseError;
111 }111 }
112 if (self.msvc_lib_dir == null and is_windows and !is_gnu) {112 if (self.msvc_lib_dir == null and is_windows and !is_gnu) {
113 try stderr.print("msvc_lib_dir may not be empty for {}-{}\n", .{113 try stderr.print("msvc_lib_dir may not be empty for {}-{}\n", .{
114 @tagName(Target.current.getOs()),114 @tagName(Target.current.os.tag),
115 @tagName(Target.current.getAbi()),115 @tagName(Target.current.abi),
116 });116 });
117 return error.ParseError;117 return error.ParseError;
118 }118 }
119 if (self.kernel32_lib_dir == null and is_windows and !is_gnu) {119 if (self.kernel32_lib_dir == null and is_windows and !is_gnu) {
120 try stderr.print("kernel32_lib_dir may not be empty for {}-{}\n", .{120 try stderr.print("kernel32_lib_dir may not be empty for {}-{}\n", .{
121 @tagName(Target.current.getOs()),121 @tagName(Target.current.os.tag),
122 @tagName(Target.current.getAbi()),122 @tagName(Target.current.abi),
123 });123 });
124 return error.ParseError;124 return error.ParseError;
125 }125 }
...@@ -616,104 +616,6 @@ fn printVerboseInvocation(...@@ -616,104 +616,6 @@ fn printVerboseInvocation(
616 }616 }
617}617}
618618
619/// Caller owns returned memory.
620pub fn detectNativeDynamicLinker(allocator: *Allocator) error{
621 OutOfMemory,
622 TargetHasNoDynamicLinker,
623 UnknownDynamicLinkerPath,
624}![:0]u8 {
625 if (!comptime Target.current.hasDynamicLinker()) {
626 return error.TargetHasNoDynamicLinker;
627 }
628
629 // The current target's ABI cannot be relied on for this. For example, we may build the zig
630 // compiler for target riscv64-linux-musl and provide a tarball for users to download.
631 // A user could then run that zig compiler on riscv64-linux-gnu. This use case is well-defined
632 // and supported by Zig. But that means that we must detect the system ABI here rather than
633 // relying on `std.Target.current`.
634
635 const LdInfo = struct {
636 ld_path: []u8,
637 abi: Target.Abi,
638 };
639 var ld_info_list = std.ArrayList(LdInfo).init(allocator);
640 defer {
641 for (ld_info_list.toSlice()) |ld_info| allocator.free(ld_info.ld_path);
642 ld_info_list.deinit();
643 }
644
645 const all_abis = comptime blk: {
646 const fields = std.meta.fields(Target.Abi);
647 var array: [fields.len]Target.Abi = undefined;
648 inline for (fields) |field, i| {
649 array[i] = @field(Target.Abi, field.name);
650 }
651 break :blk array;
652 };
653 for (all_abis) |abi| {
654 // This may be a nonsensical parameter. We detect this with error.UnknownDynamicLinkerPath and
655 // skip adding it to `ld_info_list`.
656 const target: Target = .{
657 .Cross = .{
658 .cpu = Target.Cpu.baseline(Target.current.getArch()),
659 .os = Target.current.getOs(),
660 .abi = abi,
661 },
662 };
663 const standard_ld_path = target.getStandardDynamicLinkerPath(allocator) catch |err| switch (err) {
664 error.OutOfMemory => return error.OutOfMemory,
665 error.UnknownDynamicLinkerPath, error.TargetHasNoDynamicLinker => continue,
666 };
667 errdefer allocator.free(standard_ld_path);
668 try ld_info_list.append(.{
669 .ld_path = standard_ld_path,
670 .abi = abi,
671 });
672 }
673
674 // Best case scenario: the zig compiler is dynamically linked, and we can iterate
675 // over our own shared objects and find a dynamic linker.
676 {
677 const lib_paths = try std.process.getSelfExeSharedLibPaths(allocator);
678 defer allocator.free(lib_paths);
679
680 // This is O(N^M) but typical case here is N=2 and M=10.
681 for (lib_paths) |lib_path| {
682 for (ld_info_list.toSlice()) |ld_info| {
683 const standard_ld_basename = fs.path.basename(ld_info.ld_path);
684 if (std.mem.endsWith(u8, lib_path, standard_ld_basename)) {
685 return std.mem.dupeZ(allocator, u8, lib_path);
686 }
687 }
688 }
689 }
690
691 // If Zig is statically linked, such as via distributed binary static builds, the above
692 // trick won't work. What are we left with? Try to run the system C compiler and get
693 // it to tell us the dynamic linker path.
694 // TODO: instead of this, look at the shared libs of /usr/bin/env.
695 for (ld_info_list.toSlice()) |ld_info| {
696 const standard_ld_basename = fs.path.basename(ld_info.ld_path);
697
698 const full_ld_path = ccPrintFileName(.{
699 .allocator = allocator,
700 .search_basename = standard_ld_basename,
701 .want_dirname = .full_path,
702 }) catch |err| switch (err) {
703 error.OutOfMemory => return error.OutOfMemory,
704 error.LibCRuntimeNotFound,
705 error.CCompilerExitCode,
706 error.CCompilerCrashed,
707 error.UnableToSpawnCCompiler,
708 => continue,
709 };
710 return full_ld_path;
711 }
712
713 // Finally, we fall back on the standard path.
714 return Target.current.getStandardDynamicLinkerPath(allocator);
715}
716
717const Search = struct {619const Search = struct {
718 path: []const u8,620 path: []const u8,
719 version: []const u8,621 version: []const u8,
src-self-hosted/link.zig+2-2
...@@ -515,7 +515,7 @@ const DarwinPlatform = struct {...@@ -515,7 +515,7 @@ const DarwinPlatform = struct {
515 break :blk ver;515 break :blk ver;
516 },516 },
517 .None => blk: {517 .None => blk: {
518 assert(comp.target.getOs() == .macosx);518 assert(comp.target.os.tag == .macosx);
519 result.kind = .MacOS;519 result.kind = .MacOS;
520 break :blk "10.14";520 break :blk "10.14";
521 },521 },
...@@ -534,7 +534,7 @@ const DarwinPlatform = struct {...@@ -534,7 +534,7 @@ const DarwinPlatform = struct {
534 }534 }
535535
536 if (result.kind == .IPhoneOS) {536 if (result.kind == .IPhoneOS) {
537 switch (comp.target.getArch()) {537 switch (comp.target.cpu.arch) {
538 .i386,538 .i386,
539 .x86_64,539 .x86_64,
540 => result.kind = .IPhoneOSSimulator,540 => result.kind = .IPhoneOSSimulator,
src-self-hosted/main.zig+3-3
...@@ -79,9 +79,9 @@ pub fn main() !void {...@@ -79,9 +79,9 @@ pub fn main() !void {
79 } else if (mem.eql(u8, cmd, "libc")) {79 } else if (mem.eql(u8, cmd, "libc")) {
80 return cmdLibC(allocator, cmd_args);80 return cmdLibC(allocator, cmd_args);
81 } else if (mem.eql(u8, cmd, "targets")) {81 } else if (mem.eql(u8, cmd, "targets")) {
82 // TODO figure out the current target rather than using the target that was specified when82 const info = try std.zig.system.NativeTargetInfo.detect(allocator);
83 // compiling the compiler83 defer info.deinit(allocator);
84 return @import("print_targets.zig").cmdTargets(allocator, cmd_args, stdout, Target.current);84 return @import("print_targets.zig").cmdTargets(allocator, cmd_args, stdout, info.target);
85 } else if (mem.eql(u8, cmd, "version")) {85 } else if (mem.eql(u8, cmd, "version")) {
86 return cmdVersion(allocator, cmd_args);86 return cmdVersion(allocator, cmd_args);
87 } else if (mem.eql(u8, cmd, "zen")) {87 } else if (mem.eql(u8, cmd, "zen")) {
src-self-hosted/print_targets.zig+6-6
...@@ -124,7 +124,7 @@ pub fn cmdTargets(...@@ -124,7 +124,7 @@ pub fn cmdTargets(
124124
125 try jws.objectField("os");125 try jws.objectField("os");
126 try jws.beginArray();126 try jws.beginArray();
127 inline for (@typeInfo(Target.Os).Enum.fields) |field| {127 inline for (@typeInfo(Target.Os.Tag).Enum.fields) |field| {
128 try jws.arrayElem();128 try jws.arrayElem();
129 try jws.emitString(field.name);129 try jws.emitString(field.name);
130 }130 }
...@@ -201,16 +201,16 @@ pub fn cmdTargets(...@@ -201,16 +201,16 @@ pub fn cmdTargets(
201 try jws.objectField("cpu");201 try jws.objectField("cpu");
202 try jws.beginObject();202 try jws.beginObject();
203 try jws.objectField("arch");203 try jws.objectField("arch");
204 try jws.emitString(@tagName(native_target.getArch()));204 try jws.emitString(@tagName(native_target.cpu.arch));
205205
206 try jws.objectField("name");206 try jws.objectField("name");
207 const cpu = native_target.getCpu();207 const cpu = native_target.cpu;
208 try jws.emitString(cpu.model.name);208 try jws.emitString(cpu.model.name);
209209
210 {210 {
211 try jws.objectField("features");211 try jws.objectField("features");
212 try jws.beginArray();212 try jws.beginArray();
213 for (native_target.getArch().allFeaturesList()) |feature, i_usize| {213 for (native_target.cpu.arch.allFeaturesList()) |feature, i_usize| {
214 const index = @intCast(Target.Cpu.Feature.Set.Index, i_usize);214 const index = @intCast(Target.Cpu.Feature.Set.Index, i_usize);
215 if (cpu.features.isEnabled(index)) {215 if (cpu.features.isEnabled(index)) {
216 try jws.arrayElem();216 try jws.arrayElem();
...@@ -222,9 +222,9 @@ pub fn cmdTargets(...@@ -222,9 +222,9 @@ pub fn cmdTargets(
222 try jws.endObject();222 try jws.endObject();
223 }223 }
224 try jws.objectField("os");224 try jws.objectField("os");
225 try jws.emitString(@tagName(native_target.getOs()));225 try jws.emitString(@tagName(native_target.os.tag));
226 try jws.objectField("abi");226 try jws.objectField("abi");
227 try jws.emitString(@tagName(native_target.getAbi()));227 try jws.emitString(@tagName(native_target.abi));
228 // TODO implement native glibc version detection in self-hosted228 // TODO implement native glibc version detection in self-hosted
229 try jws.endObject();229 try jws.endObject();
230230
src-self-hosted/stage2.zig+271-133
...@@ -110,6 +110,8 @@ const Error = extern enum {...@@ -110,6 +110,8 @@ const Error = extern enum {
110 WindowsSdkNotFound,110 WindowsSdkNotFound,
111 UnknownDynamicLinkerPath,111 UnknownDynamicLinkerPath,
112 TargetHasNoDynamicLinker,112 TargetHasNoDynamicLinker,
113 InvalidAbiVersion,
114 InvalidOperatingSystemVersion,
113};115};
114116
115const FILE = std.c.FILE;117const FILE = std.c.FILE;
...@@ -633,11 +635,11 @@ export fn stage2_cmd_targets(zig_triple: [*:0]const u8) c_int {...@@ -633,11 +635,11 @@ export fn stage2_cmd_targets(zig_triple: [*:0]const u8) c_int {
633635
634fn cmdTargets(zig_triple: [*:0]const u8) !void {636fn cmdTargets(zig_triple: [*:0]const u8) !void {
635 var target = try Target.parse(.{ .arch_os_abi = mem.toSliceConst(u8, zig_triple) });637 var target = try Target.parse(.{ .arch_os_abi = mem.toSliceConst(u8, zig_triple) });
636 target.Cross.cpu = blk: {638 target.cpu = blk: {
637 const llvm = @import("llvm.zig");639 const llvm = @import("llvm.zig");
638 const llvm_cpu_name = llvm.GetHostCPUName();640 const llvm_cpu_name = llvm.GetHostCPUName();
639 const llvm_cpu_features = llvm.GetNativeFeatures();641 const llvm_cpu_features = llvm.GetNativeFeatures();
640 break :blk try detectNativeCpuWithLLVM(target.getArch(), llvm_cpu_name, llvm_cpu_features);642 break :blk try detectNativeCpuWithLLVM(target.cpu.arch, llvm_cpu_name, llvm_cpu_features);
641 };643 };
642 return @import("print_targets.zig").cmdTargets(644 return @import("print_targets.zig").cmdTargets(
643 std.heap.c_allocator,645 std.heap.c_allocator,
...@@ -662,6 +664,14 @@ export fn stage2_target_parse(...@@ -662,6 +664,14 @@ export fn stage2_target_parse(
662 error.MissingArchitecture => return .MissingArchitecture,664 error.MissingArchitecture => return .MissingArchitecture,
663 error.InvalidLlvmCpuFeaturesFormat => return .InvalidLlvmCpuFeaturesFormat,665 error.InvalidLlvmCpuFeaturesFormat => return .InvalidLlvmCpuFeaturesFormat,
664 error.UnexpectedExtraField => return .SemanticAnalyzeFail,666 error.UnexpectedExtraField => return .SemanticAnalyzeFail,
667 error.InvalidAbiVersion => return .InvalidAbiVersion,
668 error.InvalidOperatingSystemVersion => return .InvalidOperatingSystemVersion,
669 error.FileSystem => return .FileSystem,
670 error.SymLinkLoop => return .SymLinkLoop,
671 error.SystemResources => return .SystemResources,
672 error.ProcessFdQuotaExceeded => return .ProcessFdQuotaExceeded,
673 error.SystemFdQuotaExceeded => return .SystemFdQuotaExceeded,
674 error.DeviceBusy => return .DeviceBusy,
665 };675 };
666 return .None;676 return .None;
667}677}
...@@ -671,108 +681,48 @@ fn stage2TargetParse(...@@ -671,108 +681,48 @@ fn stage2TargetParse(
671 zig_triple_oz: ?[*:0]const u8,681 zig_triple_oz: ?[*:0]const u8,
672 mcpu_oz: ?[*:0]const u8,682 mcpu_oz: ?[*:0]const u8,
673) !void {683) !void {
674 const target: Target = if (zig_triple_oz) |zig_triple_z| blk: {684 const target: std.build.Target = if (zig_triple_oz) |zig_triple_z| blk: {
675 const zig_triple = mem.toSliceConst(u8, zig_triple_z);685 const zig_triple = mem.toSliceConst(u8, zig_triple_z);
676 const mcpu = if (mcpu_oz) |mcpu_z| mem.toSliceConst(u8, mcpu_z) else "baseline";686 const mcpu = if (mcpu_oz) |mcpu_z| mem.toSliceConst(u8, mcpu_z) else "baseline";
677 var diags: std.Target.ParseOptions.Diagnostics = .{};687 var diags: std.Target.ParseOptions.Diagnostics = .{};
678 break :blk Target.parse(.{688 break :blk std.build.Target{
679 .arch_os_abi = zig_triple,689 .Cross = Target.parse(.{
680 .cpu_features = mcpu,690 .arch_os_abi = zig_triple,
681 .diagnostics = &diags,691 .cpu_features = mcpu,
682 }) catch |err| switch (err) {692 .diagnostics = &diags,
683 error.UnknownCpu => {693 }) catch |err| switch (err) {
684 std.debug.warn("Unknown CPU: '{}'\nAvailable CPUs for architecture '{}':\n", .{694 error.UnknownCpu => {
685 diags.cpu_name.?,695 std.debug.warn("Unknown CPU: '{}'\nAvailable CPUs for architecture '{}':\n", .{
686 @tagName(diags.arch.?),696 diags.cpu_name.?,
687 });697 @tagName(diags.arch.?),
688 for (diags.arch.?.allCpuModels()) |cpu| {698 });
689 std.debug.warn(" {}\n", .{cpu.name});699 for (diags.arch.?.allCpuModels()) |cpu| {
690 }700 std.debug.warn(" {}\n", .{cpu.name});
691 process.exit(1);701 }
692 },702 process.exit(1);
693 error.UnknownCpuFeature => {703 },
694 std.debug.warn(704 error.UnknownCpuFeature => {
695 \\Unknown CPU feature: '{}'705 std.debug.warn(
696 \\Available CPU features for architecture '{}':706 \\Unknown CPU feature: '{}'
697 \\707 \\Available CPU features for architecture '{}':
698 , .{708 \\
699 diags.unknown_feature_name,709 , .{
700 @tagName(diags.arch.?),710 diags.unknown_feature_name,
701 });711 @tagName(diags.arch.?),
702 for (diags.arch.?.allFeaturesList()) |feature| {712 });
703 std.debug.warn(" {}: {}\n", .{ feature.name, feature.description });713 for (diags.arch.?.allFeaturesList()) |feature| {
704 }714 std.debug.warn(" {}: {}\n", .{ feature.name, feature.description });
705 process.exit(1);715 }
716 process.exit(1);
717 },
718 else => |e| return e,
706 },719 },
707 else => |e| return e,
708 };720 };
709 } else Target.Native;721 } else std.build.Target.Native;
710722
711 try stage1_target.fromTarget(target);723 try stage1_target.fromTarget(target);
712}724}
713725
714fn initStage1TargetCpuFeatures(stage1_target: *Stage2Target, cpu: Target.Cpu) !void {
715 const allocator = std.heap.c_allocator;
716 const cache_hash = try std.fmt.allocPrint0(allocator, "{}\n{}", .{
717 cpu.model.name,
718 cpu.features.asBytes(),
719 });
720 errdefer allocator.free(cache_hash);
721
722 const generic_arch_name = cpu.arch.genericName();
723 var builtin_str_buffer = try std.Buffer.allocPrint(allocator,
724 \\Cpu{{
725 \\ .arch = .{},
726 \\ .model = &Target.{}.cpu.{},
727 \\ .features = Target.{}.featureSet(&[_]Target.{}.Feature{{
728 \\
729 , .{
730 @tagName(cpu.arch),
731 generic_arch_name,
732 cpu.model.name,
733 generic_arch_name,
734 generic_arch_name,
735 });
736 defer builtin_str_buffer.deinit();
737
738 var llvm_features_buffer = try std.Buffer.initSize(allocator, 0);
739 defer llvm_features_buffer.deinit();
740
741 for (cpu.arch.allFeaturesList()) |feature, index_usize| {
742 const index = @intCast(Target.Cpu.Feature.Set.Index, index_usize);
743 const is_enabled = cpu.features.isEnabled(index);
744
745 if (feature.llvm_name) |llvm_name| {
746 const plus_or_minus = "-+"[@boolToInt(is_enabled)];
747 try llvm_features_buffer.appendByte(plus_or_minus);
748 try llvm_features_buffer.append(llvm_name);
749 try llvm_features_buffer.append(",");
750 }
751
752 if (is_enabled) {
753 // TODO some kind of "zig identifier escape" function rather than
754 // unconditionally using @"" syntax
755 try builtin_str_buffer.append(" .@\"");
756 try builtin_str_buffer.append(feature.name);
757 try builtin_str_buffer.append("\",\n");
758 }
759 }
760
761 try builtin_str_buffer.append(
762 \\ }),
763 \\};
764 \\
765 );
766
767 assert(mem.endsWith(u8, llvm_features_buffer.toSliceConst(), ","));
768 llvm_features_buffer.shrink(llvm_features_buffer.len() - 1);
769
770 stage1_target.llvm_cpu_name = if (cpu.model.llvm_name) |s| s.ptr else null;
771 stage1_target.llvm_cpu_features = llvm_features_buffer.toOwnedSlice().ptr;
772 stage1_target.builtin_str = builtin_str_buffer.toOwnedSlice().ptr;
773 stage1_target.cache_hash = cache_hash.ptr;
774}
775
776// ABI warning726// ABI warning
777const Stage2LibCInstallation = extern struct {727const Stage2LibCInstallation = extern struct {
778 include_dir: [*:0]const u8,728 include_dir: [*:0]const u8,
...@@ -952,10 +902,13 @@ const Stage2Target = extern struct {...@@ -952,10 +902,13 @@ const Stage2Target = extern struct {
952902
953 llvm_cpu_name: ?[*:0]const u8,903 llvm_cpu_name: ?[*:0]const u8,
954 llvm_cpu_features: ?[*:0]const u8,904 llvm_cpu_features: ?[*:0]const u8,
955 builtin_str: ?[*:0]const u8,905 cpu_builtin_str: ?[*:0]const u8,
956 cache_hash: ?[*:0]const u8,906 cache_hash: ?[*:0]const u8,
907 os_builtin_str: ?[*:0]const u8,
908
909 dynamic_linker: ?[*:0]const u8,
957910
958 fn toTarget(in_target: Stage2Target) Target {911 fn toTarget(in_target: Stage2Target) std.build.Target {
959 if (in_target.is_native) return .Native;912 if (in_target.is_native) return .Native;
960913
961 const in_arch = in_target.arch - 1; // skip over ZigLLVM_UnknownArch914 const in_arch = in_target.arch - 1; // skip over ZigLLVM_UnknownArch
...@@ -965,39 +918,244 @@ const Stage2Target = extern struct {...@@ -965,39 +918,244 @@ const Stage2Target = extern struct {
965 return .{918 return .{
966 .Cross = .{919 .Cross = .{
967 .cpu = Target.Cpu.baseline(enumInt(Target.Cpu.Arch, in_arch)),920 .cpu = Target.Cpu.baseline(enumInt(Target.Cpu.Arch, in_arch)),
968 .os = enumInt(Target.Os, in_os),921 .os = Target.Os.defaultVersionRange(enumInt(Target.Os.Tag, in_os)),
969 .abi = enumInt(Target.Abi, in_abi),922 .abi = enumInt(Target.Abi, in_abi),
970 },923 },
971 };924 };
972 }925 }
973926
974 fn fromTarget(self: *Stage2Target, target: Target) !void {927 fn fromTarget(self: *Stage2Target, build_target: std.build.Target) !void {
975 const cpu = switch (target) {928 const allocator = std.heap.c_allocator;
929 var dynamic_linker: ?[*:0]u8 = null;
930 const target = switch (build_target) {
976 .Native => blk: {931 .Native => blk: {
977 // TODO self-host CPU model and feature detection instead of relying on LLVM932 const info = try std.zig.system.NativeTargetInfo.detect(std.heap.c_allocator);
933 if (info.dynamic_linker) |dl| {
934 dynamic_linker = dl.ptr;
935 }
936
937 // TODO we want to just use info.target but implementing CPU model & feature detection is todo
938 // so here we rely on LLVM
978 const llvm = @import("llvm.zig");939 const llvm = @import("llvm.zig");
979 const llvm_cpu_name = llvm.GetHostCPUName();940 const llvm_cpu_name = llvm.GetHostCPUName();
980 const llvm_cpu_features = llvm.GetNativeFeatures();941 const llvm_cpu_features = llvm.GetNativeFeatures();
981 break :blk try detectNativeCpuWithLLVM(target.getArch(), llvm_cpu_name, llvm_cpu_features);942 const arch = std.Target.current.cpu.arch;
943 var t = info.target;
944 t.cpu = try detectNativeCpuWithLLVM(arch, llvm_cpu_name, llvm_cpu_features);
945 break :blk t;
982 },946 },
983 .Cross => target.getCpu(),947 .Cross => |t| t,
984 };948 };
949
950 var cache_hash = try std.Buffer.allocPrint(allocator, "{}\n{}\n", .{
951 target.cpu.model.name,
952 target.cpu.features.asBytes(),
953 });
954 defer cache_hash.deinit();
955
956 const generic_arch_name = target.cpu.arch.genericName();
957 var cpu_builtin_str_buffer = try std.Buffer.allocPrint(allocator,
958 \\Cpu{{
959 \\ .arch = .{},
960 \\ .model = &Target.{}.cpu.{},
961 \\ .features = Target.{}.featureSet(&[_]Target.{}.Feature{{
962 \\
963 , .{
964 @tagName(target.cpu.arch),
965 generic_arch_name,
966 target.cpu.model.name,
967 generic_arch_name,
968 generic_arch_name,
969 });
970 defer cpu_builtin_str_buffer.deinit();
971
972 var llvm_features_buffer = try std.Buffer.initSize(allocator, 0);
973 defer llvm_features_buffer.deinit();
974
975 for (target.cpu.arch.allFeaturesList()) |feature, index_usize| {
976 const index = @intCast(Target.Cpu.Feature.Set.Index, index_usize);
977 const is_enabled = target.cpu.features.isEnabled(index);
978
979 if (feature.llvm_name) |llvm_name| {
980 const plus_or_minus = "-+"[@boolToInt(is_enabled)];
981 try llvm_features_buffer.appendByte(plus_or_minus);
982 try llvm_features_buffer.append(llvm_name);
983 try llvm_features_buffer.append(",");
984 }
985
986 if (is_enabled) {
987 // TODO some kind of "zig identifier escape" function rather than
988 // unconditionally using @"" syntax
989 try cpu_builtin_str_buffer.append(" .@\"");
990 try cpu_builtin_str_buffer.append(feature.name);
991 try cpu_builtin_str_buffer.append("\",\n");
992 }
993 }
994
995 try cpu_builtin_str_buffer.append(
996 \\ }),
997 \\};
998 \\
999 );
1000
1001 assert(mem.endsWith(u8, llvm_features_buffer.toSliceConst(), ","));
1002 llvm_features_buffer.shrink(llvm_features_buffer.len() - 1);
1003
1004 var os_builtin_str_buffer = try std.Buffer.allocPrint(allocator,
1005 \\Os{{
1006 \\ .tag = .{},
1007 \\ .version_range = .{{
1008 , .{@tagName(target.os.tag)});
1009 defer os_builtin_str_buffer.deinit();
1010
1011 // We'll re-use the OS version range builtin string for the cache hash.
1012 const os_builtin_str_ver_start_index = os_builtin_str_buffer.len();
1013
1014 @setEvalBranchQuota(2000);
1015 switch (target.os.tag) {
1016 .freestanding,
1017 .ananas,
1018 .cloudabi,
1019 .dragonfly,
1020 .fuchsia,
1021 .ios,
1022 .kfreebsd,
1023 .lv2,
1024 .solaris,
1025 .haiku,
1026 .minix,
1027 .rtems,
1028 .nacl,
1029 .cnk,
1030 .aix,
1031 .cuda,
1032 .nvcl,
1033 .amdhsa,
1034 .ps4,
1035 .elfiamcu,
1036 .tvos,
1037 .watchos,
1038 .mesa3d,
1039 .contiki,
1040 .amdpal,
1041 .hermit,
1042 .hurd,
1043 .wasi,
1044 .emscripten,
1045 .uefi,
1046 .other,
1047 => try os_builtin_str_buffer.append(" .none = {} }\n"),
1048
1049 .freebsd,
1050 .macosx,
1051 .netbsd,
1052 .openbsd,
1053 => try os_builtin_str_buffer.print(
1054 \\.semver = .{{
1055 \\ .min = .{{
1056 \\ .major = {},
1057 \\ .minor = {},
1058 \\ .patch = {},
1059 \\ }},
1060 \\ .max = .{{
1061 \\ .major = {},
1062 \\ .minor = {},
1063 \\ .patch = {},
1064 \\ }},
1065 \\ }}}},
1066 , .{
1067 target.os.version_range.semver.min.major,
1068 target.os.version_range.semver.min.minor,
1069 target.os.version_range.semver.min.patch,
1070
1071 target.os.version_range.semver.max.major,
1072 target.os.version_range.semver.max.minor,
1073 target.os.version_range.semver.max.patch,
1074 }),
1075
1076 .linux => try os_builtin_str_buffer.print(
1077 \\.linux = .{{
1078 \\ .range = .{{
1079 \\ .min = .{{
1080 \\ .major = {},
1081 \\ .minor = {},
1082 \\ .patch = {},
1083 \\ }},
1084 \\ .max = .{{
1085 \\ .major = {},
1086 \\ .minor = {},
1087 \\ .patch = {},
1088 \\ }},
1089 \\ }},
1090 \\ .glibc = .{{
1091 \\ .major = {},
1092 \\ .minor = {},
1093 \\ .patch = {},
1094 \\ }},
1095 \\ }}}},
1096 \\
1097 , .{
1098 target.os.version_range.linux.range.min.major,
1099 target.os.version_range.linux.range.min.minor,
1100 target.os.version_range.linux.range.min.patch,
1101
1102 target.os.version_range.linux.range.max.major,
1103 target.os.version_range.linux.range.max.minor,
1104 target.os.version_range.linux.range.max.patch,
1105
1106 target.os.version_range.linux.glibc.major,
1107 target.os.version_range.linux.glibc.minor,
1108 target.os.version_range.linux.glibc.patch,
1109 }),
1110
1111 .windows => try os_builtin_str_buffer.print(
1112 \\.semver = .{{
1113 \\ .min = .{},
1114 \\ .max = .{},
1115 \\ }}}},
1116 , .{
1117 @tagName(target.os.version_range.windows.min),
1118 @tagName(target.os.version_range.windows.max),
1119 }),
1120 }
1121 try os_builtin_str_buffer.append("};\n");
1122
1123 try cache_hash.append(
1124 os_builtin_str_buffer.toSlice()[os_builtin_str_ver_start_index..os_builtin_str_buffer.len()],
1125 );
1126
1127 const glibc_version = if (target.isGnuLibC()) blk: {
1128 const stage1_glibc = try std.heap.c_allocator.create(Stage2GLibCVersion);
1129 const stage2_glibc = target.os.version_range.linux.glibc;
1130 stage1_glibc.* = .{
1131 .major = stage2_glibc.major,
1132 .minor = stage2_glibc.minor,
1133 .patch = stage2_glibc.patch,
1134 };
1135 break :blk stage1_glibc;
1136 } else null;
1137
985 self.* = .{1138 self.* = .{
986 .arch = @enumToInt(target.getArch()) + 1, // skip over ZigLLVM_UnknownArch1139 .arch = @enumToInt(target.cpu.arch) + 1, // skip over ZigLLVM_UnknownArch
987 .vendor = 0,1140 .vendor = 0,
988 .os = @enumToInt(target.getOs()),1141 .os = @enumToInt(target.os.tag),
989 .abi = @enumToInt(target.getAbi()),1142 .abi = @enumToInt(target.abi),
990 .llvm_cpu_name = null,1143 .llvm_cpu_name = if (target.cpu.model.llvm_name) |s| s.ptr else null,
991 .llvm_cpu_features = null,1144 .llvm_cpu_features = llvm_features_buffer.toOwnedSlice().ptr,
992 .builtin_str = null,1145 .cpu_builtin_str = cpu_builtin_str_buffer.toOwnedSlice().ptr,
993 .cache_hash = null,1146 .os_builtin_str = os_builtin_str_buffer.toOwnedSlice().ptr,
994 .is_native = target == .Native,1147 .cache_hash = cache_hash.toOwnedSlice().ptr,
995 .glibc_version = null,1148 .is_native = build_target == .Native,
1149 .glibc_version = glibc_version,
1150 .dynamic_linker = dynamic_linker,
996 };1151 };
997 try initStage1TargetCpuFeatures(self, cpu);
998 }1152 }
999};1153};
10001154
1155fn enumInt(comptime Enum: type, int: c_int) Enum {
1156 return @intToEnum(Enum, @intCast(@TagType(Enum), int));
1157}
1158
1001// ABI warning1159// ABI warning
1002const Stage2GLibCVersion = extern struct {1160const Stage2GLibCVersion = extern struct {
1003 major: u32,1161 major: u32,
...@@ -1005,26 +1163,6 @@ const Stage2GLibCVersion = extern struct {...@@ -1005,26 +1163,6 @@ const Stage2GLibCVersion = extern struct {
1005 patch: u32,1163 patch: u32,
1006};1164};
10071165
1008// ABI warning
1009export fn stage2_detect_dynamic_linker(in_target: *const Stage2Target, out_ptr: *[*:0]u8, out_len: *usize) Error {
1010 const target = in_target.toTarget();
1011 const result = @import("introspect.zig").detectDynamicLinker(
1012 std.heap.c_allocator,
1013 target,
1014 ) catch |err| switch (err) {
1015 error.OutOfMemory => return .OutOfMemory,
1016 error.UnknownDynamicLinkerPath => return .UnknownDynamicLinkerPath,
1017 error.TargetHasNoDynamicLinker => return .TargetHasNoDynamicLinker,
1018 };
1019 out_ptr.* = result.ptr;
1020 out_len.* = result.len;
1021 return .None;
1022}
1023
1024fn enumInt(comptime Enum: type, int: c_int) Enum {
1025 return @intToEnum(Enum, @intCast(@TagType(Enum), int));
1026}
1027
1028// ABI warning1166// ABI warning
1029const Stage2NativePaths = extern struct {1167const Stage2NativePaths = extern struct {
1030 include_dirs_ptr: [*][*:0]u8,1168 include_dirs_ptr: [*][*:0]u8,
src-self-hosted/util.zig-22
...@@ -34,25 +34,3 @@ pub fn initializeAllTargets() void {...@@ -34,25 +34,3 @@ pub fn initializeAllTargets() void {
34 llvm.InitializeAllAsmPrinters();34 llvm.InitializeAllAsmPrinters();
35 llvm.InitializeAllAsmParsers();35 llvm.InitializeAllAsmParsers();
36}36}
37
38pub fn getTriple(allocator: *std.mem.Allocator, self: std.Target) !std.Buffer {
39 var result = try std.Buffer.initSize(allocator, 0);
40 errdefer result.deinit();
41
42 // LLVM WebAssembly output support requires the target to be activated at
43 // build type with -DCMAKE_LLVM_EXPIERMENTAL_TARGETS_TO_BUILD=WebAssembly.
44 //
45 // LLVM determines the output format based on the abi suffix,
46 // defaulting to an object based on the architecture. The default format in
47 // LLVM 6 sets the wasm arch output incorrectly to ELF. We need to
48 // explicitly set this ourself in order for it to work.
49 //
50 // This is fixed in LLVM 7 and you will be able to get wasm output by
51 // using the target triple `wasm32-unknown-unknown-unknown`.
52 const env_name = if (self.isWasm()) "wasm" else @tagName(self.getAbi());
53
54 var out = &std.io.BufferOutStream.init(&result).stream;
55 try out.print("{}-unknown-{}-{}", .{ @tagName(self.getArch()), @tagName(self.getOs()), env_name });
56
57 return result;
58}
src/codegen.cpp+14-24
...@@ -4483,7 +4483,7 @@ static LLVMValueRef ir_render_union_field_ptr(CodeGen *g, IrExecutableGen *execu...@@ -4483,7 +4483,7 @@ static LLVMValueRef ir_render_union_field_ptr(CodeGen *g, IrExecutableGen *execu
44834483
4484 if (!type_has_bits(field->type_entry)) {4484 if (!type_has_bits(field->type_entry)) {
4485 ZigType *tag_type = union_type->data.unionation.tag_type;4485 ZigType *tag_type = union_type->data.unionation.tag_type;
4486 if (!instruction->initializing || !type_has_bits(tag_type))4486 if (!instruction->initializing || tag_type == nullptr || !type_has_bits(tag_type))
4487 return nullptr;4487 return nullptr;
44884488
4489 // The field has no bits but we still have to change the discriminant4489 // The field has no bits but we still have to change the discriminant
...@@ -8543,25 +8543,24 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {...@@ -8543,25 +8543,24 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
8543 buf_appendf(contents, "pub const link_mode = LinkMode.%s;\n", link_type);8543 buf_appendf(contents, "pub const link_mode = LinkMode.%s;\n", link_type);
8544 buf_appendf(contents, "pub const is_test = %s;\n", bool_to_str(g->is_test_build));8544 buf_appendf(contents, "pub const is_test = %s;\n", bool_to_str(g->is_test_build));
8545 buf_appendf(contents, "pub const single_threaded = %s;\n", bool_to_str(g->is_single_threaded));8545 buf_appendf(contents, "pub const single_threaded = %s;\n", bool_to_str(g->is_single_threaded));
8546 buf_appendf(contents, "pub const os = Os.%s;\n", cur_os);8546 buf_append_str(contents, "/// Deprecated: use `std.Target.cpu.arch`\n");
8547 buf_appendf(contents, "pub const arch = Arch.%s;\n", cur_arch);8547 buf_appendf(contents, "pub const arch = Arch.%s;\n", cur_arch);
8548 buf_appendf(contents, "pub const abi = Abi.%s;\n", cur_abi);8548 buf_appendf(contents, "pub const abi = Abi.%s;\n", cur_abi);
8549 {8549 {
8550 buf_append_str(contents, "pub const cpu: Cpu = ");8550 buf_append_str(contents, "pub const cpu: Cpu = ");
8551 if (g->zig_target->builtin_str != nullptr) {8551 if (g->zig_target->cpu_builtin_str != nullptr) {
8552 buf_append_str(contents, g->zig_target->builtin_str);8552 buf_append_str(contents, g->zig_target->cpu_builtin_str);
8553 } else {8553 } else {
8554 buf_append_str(contents, "Target.Cpu.baseline(arch);\n");8554 buf_appendf(contents, "Target.Cpu.baseline(.%s);\n", cur_arch);
8555 }8555 }
8556 }8556 }
8557 if (g->libc_link_lib != nullptr && g->zig_target->glibc_version != nullptr) {8557 {
8558 buf_appendf(contents,8558 buf_append_str(contents, "pub const os = ");
8559 "pub const glibc_version: ?Version = Version{.major = %d, .minor = %d, .patch = %d};\n",8559 if (g->zig_target->os_builtin_str != nullptr) {
8560 g->zig_target->glibc_version->major,8560 buf_append_str(contents, g->zig_target->os_builtin_str);
8561 g->zig_target->glibc_version->minor,8561 } else {
8562 g->zig_target->glibc_version->patch);8562 buf_appendf(contents, "Target.Os.defaultVersionRange(.%s);\n", cur_os);
8563 } else {8563 }
8564 buf_appendf(contents, "pub const glibc_version: ?Version = null;\n");
8565 }8564 }
8566 buf_appendf(contents, "pub const object_format = ObjectFormat.%s;\n", cur_obj_fmt);8565 buf_appendf(contents, "pub const object_format = ObjectFormat.%s;\n", cur_obj_fmt);
8567 buf_appendf(contents, "pub const mode = %s;\n", build_mode_to_str(g->build_mode));8566 buf_appendf(contents, "pub const mode = %s;\n", build_mode_to_str(g->build_mode));
...@@ -8867,8 +8866,6 @@ static void init(CodeGen *g) {...@@ -8867,8 +8866,6 @@ static void init(CodeGen *g) {
8867}8866}
88688867
8869static void detect_dynamic_linker(CodeGen *g) {8868static void detect_dynamic_linker(CodeGen *g) {
8870 Error err;
8871
8872 if (g->dynamic_linker_path != nullptr)8869 if (g->dynamic_linker_path != nullptr)
8873 return;8870 return;
8874 if (!g->have_dynamic_link)8871 if (!g->have_dynamic_link)
...@@ -8876,16 +8873,9 @@ static void detect_dynamic_linker(CodeGen *g) {...@@ -8876,16 +8873,9 @@ static void detect_dynamic_linker(CodeGen *g) {
8876 if (g->out_type == OutTypeObj || (g->out_type == OutTypeLib && !g->is_dynamic))8873 if (g->out_type == OutTypeObj || (g->out_type == OutTypeLib && !g->is_dynamic))
8877 return;8874 return;
88788875
8879 char *dynamic_linker_ptr;8876 if (g->zig_target->dynamic_linker != nullptr) {
8880 size_t dynamic_linker_len;8877 g->dynamic_linker_path = buf_create_from_str(g->zig_target->dynamic_linker);
8881 if ((err = stage2_detect_dynamic_linker(g->zig_target, &dynamic_linker_ptr, &dynamic_linker_len))) {
8882 if (err == ErrorTargetHasNoDynamicLinker) return;
8883 fprintf(stderr, "Unable to detect dynamic linker: %s\n", err_str(err));
8884 exit(1);
8885 }8878 }
8886 g->dynamic_linker_path = buf_create_from_mem(dynamic_linker_ptr, dynamic_linker_len);
8887 // Skips heap::c_allocator because the memory is allocated by stage2 library.
8888 free(dynamic_linker_ptr);
8889}8879}
88908880
8891static void detect_libc(CodeGen *g) {8881static void detect_libc(CodeGen *g) {
src/error.cpp+2
...@@ -81,6 +81,8 @@ const char *err_str(Error err) {...@@ -81,6 +81,8 @@ const char *err_str(Error err) {
81 case ErrorWindowsSdkNotFound: return "Windows SDK not found";81 case ErrorWindowsSdkNotFound: return "Windows SDK not found";
82 case ErrorUnknownDynamicLinkerPath: return "unknown dynamic linker path";82 case ErrorUnknownDynamicLinkerPath: return "unknown dynamic linker path";
83 case ErrorTargetHasNoDynamicLinker: return "target has no dynamic linker";83 case ErrorTargetHasNoDynamicLinker: return "target has no dynamic linker";
84 case ErrorInvalidAbiVersion: return "invalid C ABI version";
85 case ErrorInvalidOperatingSystemVersion: return "invalid operating system version";
84 }86 }
85 return "(invalid error)";87 return "(invalid error)";
86}88}
src/main.cpp+1-28
...@@ -89,8 +89,7 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) {...@@ -89,8 +89,7 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) {
89 " --single-threaded source may assume it is only used single-threaded\n"89 " --single-threaded source may assume it is only used single-threaded\n"
90 " -dynamic create a shared library (.so; .dll; .dylib)\n"90 " -dynamic create a shared library (.so; .dll; .dylib)\n"
91 " --strip exclude debug symbols\n"91 " --strip exclude debug symbols\n"
92 " -target [name] <arch><sub>-<os>-<abi> see the targets command\n"92 " -target [name] <arch>-<os>-<abi> see the targets command\n"
93 " -target-glibc [version] target a specific glibc version (default: 2.17)\n"
94 " --verbose-tokenize enable compiler debug output for tokenization\n"93 " --verbose-tokenize enable compiler debug output for tokenization\n"
95 " --verbose-ast enable compiler debug output for AST parsing\n"94 " --verbose-ast enable compiler debug output for AST parsing\n"
96 " --verbose-link enable compiler debug output for linking\n"95 " --verbose-link enable compiler debug output for linking\n"
...@@ -419,7 +418,6 @@ static int main0(int argc, char **argv) {...@@ -419,7 +418,6 @@ static int main0(int argc, char **argv) {
419 const char *mios_version_min = nullptr;418 const char *mios_version_min = nullptr;
420 const char *linker_script = nullptr;419 const char *linker_script = nullptr;
421 Buf *version_script = nullptr;420 Buf *version_script = nullptr;
422 const char *target_glibc = nullptr;
423 ZigList<const char *> rpath_list = {0};421 ZigList<const char *> rpath_list = {0};
424 bool each_lib_rpath = false;422 bool each_lib_rpath = false;
425 ZigList<const char *> objects = {0};423 ZigList<const char *> objects = {0};
...@@ -853,8 +851,6 @@ static int main0(int argc, char **argv) {...@@ -853,8 +851,6 @@ static int main0(int argc, char **argv) {
853 linker_script = argv[i];851 linker_script = argv[i];
854 } else if (strcmp(arg, "--version-script") == 0) {852 } else if (strcmp(arg, "--version-script") == 0) {
855 version_script = buf_create_from_str(argv[i]); 853 version_script = buf_create_from_str(argv[i]);
856 } else if (strcmp(arg, "-target-glibc") == 0) {
857 target_glibc = argv[i];
858 } else if (strcmp(arg, "-rpath") == 0) {854 } else if (strcmp(arg, "-rpath") == 0) {
859 rpath_list.append(argv[i]);855 rpath_list.append(argv[i]);
860 } else if (strcmp(arg, "--test-filter") == 0) {856 } else if (strcmp(arg, "--test-filter") == 0) {
...@@ -982,29 +978,6 @@ static int main0(int argc, char **argv) {...@@ -982,29 +978,6 @@ static int main0(int argc, char **argv) {
982 "See `%s targets` to display valid targets.\n", err_str(err), arg0);978 "See `%s targets` to display valid targets.\n", err_str(err), arg0);
983 return print_error_usage(arg0);979 return print_error_usage(arg0);
984 }980 }
985 if (target_is_glibc(&target)) {
986 target.glibc_version = heap::c_allocator.create<ZigGLibCVersion>();
987
988 if (target_glibc != nullptr) {
989 if ((err = target_parse_glibc_version(target.glibc_version, target_glibc))) {
990 fprintf(stderr, "invalid glibc version '%s': %s\n", target_glibc, err_str(err));
991 return print_error_usage(arg0);
992 }
993 } else {
994 target_init_default_glibc_version(&target);
995#if defined(ZIG_OS_LINUX)
996 if (target.is_native) {
997 // TODO self-host glibc version detection, and then this logic can go away
998 if ((err = glibc_detect_native_version(target.glibc_version))) {
999 // Fall back to the default version.
1000 }
1001 }
1002#endif
1003 }
1004 } else if (target_glibc != nullptr) {
1005 fprintf(stderr, "'%s' is not a glibc-compatible target", target_string);
1006 return print_error_usage(arg0);
1007 }
1008981
1009 Buf zig_triple_buf = BUF_INIT;982 Buf zig_triple_buf = BUF_INIT;
1010 target_triple_zig(&zig_triple_buf, &target);983 target_triple_zig(&zig_triple_buf, &target);
src/stage2.cpp-8
...@@ -100,13 +100,11 @@ Error stage2_target_parse(struct ZigTarget *target, const char *zig_triple, cons...@@ -100,13 +100,11 @@ Error stage2_target_parse(struct ZigTarget *target, const char *zig_triple, cons
100 if (mcpu == nullptr) {100 if (mcpu == nullptr) {
101 target->llvm_cpu_name = ZigLLVMGetHostCPUName();101 target->llvm_cpu_name = ZigLLVMGetHostCPUName();
102 target->llvm_cpu_features = ZigLLVMGetNativeFeatures();102 target->llvm_cpu_features = ZigLLVMGetNativeFeatures();
103 target->builtin_str = "Target.Cpu.baseline(arch);\n";
104 target->cache_hash = "native\n\n";103 target->cache_hash = "native\n\n";
105 } else if (strcmp(mcpu, "baseline") == 0) {104 } else if (strcmp(mcpu, "baseline") == 0) {
106 target->is_native = false;105 target->is_native = false;
107 target->llvm_cpu_name = "";106 target->llvm_cpu_name = "";
108 target->llvm_cpu_features = "";107 target->llvm_cpu_features = "";
109 target->builtin_str = "Target.Cpu.baseline(arch);\n";
110 target->cache_hash = "baseline\n\n";108 target->cache_hash = "baseline\n\n";
111 } else {109 } else {
112 const char *msg = "stage0 can't handle CPU/features in the target";110 const char *msg = "stage0 can't handle CPU/features in the target";
...@@ -148,7 +146,6 @@ Error stage2_target_parse(struct ZigTarget *target, const char *zig_triple, cons...@@ -148,7 +146,6 @@ Error stage2_target_parse(struct ZigTarget *target, const char *zig_triple, cons
148 const char *msg = "stage0 can't handle CPU/features in the target";146 const char *msg = "stage0 can't handle CPU/features in the target";
149 stage2_panic(msg, strlen(msg));147 stage2_panic(msg, strlen(msg));
150 }148 }
151 target->builtin_str = "Target.Cpu.baseline(arch);\n";
152 target->cache_hash = "\n\n";149 target->cache_hash = "\n\n";
153 }150 }
154151
...@@ -186,11 +183,6 @@ enum Error stage2_libc_find_native(struct Stage2LibCInstallation *libc) {...@@ -186,11 +183,6 @@ enum Error stage2_libc_find_native(struct Stage2LibCInstallation *libc) {
186 stage2_panic(msg, strlen(msg));183 stage2_panic(msg, strlen(msg));
187}184}
188185
189enum Error stage2_detect_dynamic_linker(const struct ZigTarget *target, char **out_ptr, size_t *out_len) {
190 const char *msg = "stage0 called stage2_detect_dynamic_linker";
191 stage2_panic(msg, strlen(msg));
192}
193
194enum Error stage2_detect_native_paths(struct Stage2NativePaths *native_paths) {186enum Error stage2_detect_native_paths(struct Stage2NativePaths *native_paths) {
195 native_paths->include_dirs_ptr = nullptr;187 native_paths->include_dirs_ptr = nullptr;
196 native_paths->include_dirs_len = 0;188 native_paths->include_dirs_len = 0;
src/stage2.h+5-5
...@@ -103,6 +103,8 @@ enum Error {...@@ -103,6 +103,8 @@ enum Error {
103 ErrorWindowsSdkNotFound,103 ErrorWindowsSdkNotFound,
104 ErrorUnknownDynamicLinkerPath,104 ErrorUnknownDynamicLinkerPath,
105 ErrorTargetHasNoDynamicLinker,105 ErrorTargetHasNoDynamicLinker,
106 ErrorInvalidAbiVersion,
107 ErrorInvalidOperatingSystemVersion,
106};108};
107109
108// ABI warning110// ABI warning
...@@ -290,14 +292,12 @@ struct ZigTarget {...@@ -290,14 +292,12 @@ struct ZigTarget {
290292
291 const char *llvm_cpu_name;293 const char *llvm_cpu_name;
292 const char *llvm_cpu_features;294 const char *llvm_cpu_features;
293 const char *builtin_str;295 const char *cpu_builtin_str;
294 const char *cache_hash;296 const char *cache_hash;
297 const char *os_builtin_str;
298 const char *dynamic_linker;
295};299};
296300
297// ABI warning
298ZIG_EXTERN_C enum Error stage2_detect_dynamic_linker(const struct ZigTarget *target,
299 char **out_ptr, size_t *out_len);
300
301// ABI warning301// ABI warning
302ZIG_EXTERN_C enum Error stage2_target_parse(struct ZigTarget *target, const char *zig_triple, const char *mcpu);302ZIG_EXTERN_C enum Error stage2_target_parse(struct ZigTarget *target, const char *zig_triple, const char *mcpu);
303303
test/stage1/behavior/asm.zig+4-3
...@@ -1,9 +1,10 @@...@@ -1,9 +1,10 @@
1const std = @import("std");1const std = @import("std");
2const config = @import("builtin");
3const expect = std.testing.expect;2const expect = std.testing.expect;
43
4const is_x86_64_linux = std.Target.current.cpu.arch == .x86_64 and std.Target.current.os.tag == .linux;
5
5comptime {6comptime {
6 if (config.arch == config.Arch.x86_64 and config.os == config.Os.linux) {7 if (is_x86_64_linux) {
7 asm (8 asm (
8 \\.globl this_is_my_alias;9 \\.globl this_is_my_alias;
9 \\.type this_is_my_alias, @function;10 \\.type this_is_my_alias, @function;
...@@ -13,7 +14,7 @@ comptime {...@@ -13,7 +14,7 @@ comptime {
13}14}
1415
15test "module level assembly" {16test "module level assembly" {
16 if (config.arch == config.Arch.x86_64 and config.os == config.Os.linux) {17 if (is_x86_64_linux) {
17 expect(this_is_my_alias() == 1234);18 expect(this_is_my_alias() == 1234);
18 }19 }
19}20}
test/stage1/behavior/byteswap.zig+2-3
...@@ -1,6 +1,5 @@...@@ -1,6 +1,5 @@
1const std = @import("std");1const std = @import("std");
2const expect = std.testing.expect;2const expect = std.testing.expect;
3const builtin = @import("builtin");
43
5test "@byteSwap integers" {4test "@byteSwap integers" {
6 const ByteSwapIntTest = struct {5 const ByteSwapIntTest = struct {
...@@ -41,10 +40,10 @@ test "@byteSwap integers" {...@@ -41,10 +40,10 @@ test "@byteSwap integers" {
4140
42test "@byteSwap vectors" {41test "@byteSwap vectors" {
43 // https://github.com/ziglang/zig/issues/356342 // https://github.com/ziglang/zig/issues/3563
44 if (builtin.os == .dragonfly) return error.SkipZigTest;43 if (std.Target.current.os.tag == .dragonfly) return error.SkipZigTest;
4544
46 // https://github.com/ziglang/zig/issues/331745 // https://github.com/ziglang/zig/issues/3317
47 if (builtin.arch == .mipsel) return error.SkipZigTest;46 if (std.Target.current.cpu.arch == .mipsel) return error.SkipZigTest;
4847
49 const ByteSwapVectorTest = struct {48 const ByteSwapVectorTest = struct {
50 fn run() void {49 fn run() void {
test/stage1/behavior/namespace_depends_on_compile_var.zig+4-4
...@@ -1,5 +1,5 @@...@@ -1,5 +1,5 @@
1const builtin = @import("builtin");1const std = @import("std");
2const expect = @import("std").testing.expect;2const expect = std.testing.expect;
33
4test "namespace depends on compile var" {4test "namespace depends on compile var" {
5 if (some_namespace.a_bool) {5 if (some_namespace.a_bool) {
...@@ -8,7 +8,7 @@ test "namespace depends on compile var" {...@@ -8,7 +8,7 @@ test "namespace depends on compile var" {
8 expect(!some_namespace.a_bool);8 expect(!some_namespace.a_bool);
9 }9 }
10}10}
11const some_namespace = switch (builtin.os) {11const some_namespace = switch (std.builtin.os.tag) {
12 builtin.Os.linux => @import("namespace_depends_on_compile_var/a.zig"),12 .linux => @import("namespace_depends_on_compile_var/a.zig"),
13 else => @import("namespace_depends_on_compile_var/b.zig"),13 else => @import("namespace_depends_on_compile_var/b.zig"),
14};14};
test/stage1/behavior/vector.zig+1-2
...@@ -2,7 +2,6 @@ const std = @import("std");...@@ -2,7 +2,6 @@ const std = @import("std");
2const mem = std.mem;2const mem = std.mem;
3const expect = std.testing.expect;3const expect = std.testing.expect;
4const expectEqual = std.testing.expectEqual;4const expectEqual = std.testing.expectEqual;
5const builtin = @import("builtin");
65
7test "implicit cast vector to array - bool" {6test "implicit cast vector to array - bool" {
8 const S = struct {7 const S = struct {
...@@ -114,7 +113,7 @@ test "array to vector" {...@@ -114,7 +113,7 @@ test "array to vector" {
114113
115test "vector casts of sizes not divisable by 8" {114test "vector casts of sizes not divisable by 8" {
116 // https://github.com/ziglang/zig/issues/3563115 // https://github.com/ziglang/zig/issues/3563
117 if (builtin.os == .dragonfly) return error.SkipZigTest;116 if (std.Target.current.os.tag == .dragonfly) return error.SkipZigTest;
118117
119 const S = struct {118 const S = struct {
120 fn doTheTest() void {119 fn doTheTest() void {
test/tests.zig+1-1
...@@ -31,7 +31,7 @@ pub const RunTranslatedCContext = @import("src/run_translated_c.zig").RunTransla...@@ -31,7 +31,7 @@ pub const RunTranslatedCContext = @import("src/run_translated_c.zig").RunTransla
31pub const CompareOutputContext = @import("src/compare_output.zig").CompareOutputContext;31pub const CompareOutputContext = @import("src/compare_output.zig").CompareOutputContext;
3232
33const TestTarget = struct {33const TestTarget = struct {
34 target: Target = .Native,34 target: build.Target = .Native,
35 mode: builtin.Mode = .Debug,35 mode: builtin.Mode = .Debug,
36 link_libc: bool = false,36 link_libc: bool = false,
37 single_threaded: bool = false,37 single_threaded: bool = false,