Skip to content

Commit 4616af0

Browse files
committed
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
1 parent fba39ff commit 4616af0

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

59 files changed

+1275
-933
lines changed

lib/std/build.zig

+33-7
Original file line numberDiff line numberDiff line change
@@ -971,21 +971,47 @@ pub const Builder = struct {
971971
};
972972

973973
test "builder.findProgram compiles" {
974-
// TODO: uncomment and fix the leak
975-
// const builder = try Builder.create(std.testing.allocator, "zig", "zig-cache", "zig-cache");
976-
const builder = try Builder.create(std.heap.page_allocator, "zig", "zig-cache", "zig-cache");
974+
var buf: [1000]u8 = undefined;
975+
var fba = std.heap.FixedBufferAllocator.init(&buf);
976+
const builder = try Builder.create(&fba.allocator, "zig", "zig-cache", "zig-cache");
977977
defer builder.destroy();
978978
_ = builder.findProgram(&[_][]const u8{}, &[_][]const u8{}) catch null;
979979
}
980980

981981
/// Deprecated. Use `builtin.Version`.
982982
pub const Version = builtin.Version;
983983

984-
/// Deprecated. Use `std.Target.Cross`.
985-
pub const CrossTarget = std.Target.Cross;
986-
987984
/// Deprecated. Use `std.Target`.
988-
pub const Target = std.Target;
985+
pub const CrossTarget = std.Target;
986+
987+
/// Wraps `std.Target` so that it can be annotated as "the native target" or an explicitly specified target.
988+
pub 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

9901016
pub const Pkg = struct {
9911017
name: []const u8,

lib/std/build/run.zig

+1-1
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ pub const RunStep = struct {
8282

8383
var key: []const u8 = undefined;
8484
var prev_path: ?[]const u8 = undefined;
85-
if (builtin.os == .windows) {
85+
if (builtin.os.tag == .windows) {
8686
key = "Path";
8787
prev_path = env_map.get(key);
8888
if (prev_path == null) {

lib/std/builtin.zig

+2-2
Original file line numberDiff line numberDiff line change
@@ -411,7 +411,7 @@ pub const Version = struct {
411411
}
412412
};
413413

414-
pub fn order(lhs: Version, rhs: version) std.math.Order {
414+
pub fn order(lhs: Version, rhs: Version) std.math.Order {
415415
if (lhs.major < rhs.major) return .lt;
416416
if (lhs.major > rhs.major) return .gt;
417417
if (lhs.minor < rhs.minor) return .lt;
@@ -504,7 +504,7 @@ pub fn default_panic(msg: []const u8, error_return_trace: ?*StackTrace) noreturn
504504
root.os.panic(msg, error_return_trace);
505505
unreachable;
506506
}
507-
switch (os) {
507+
switch (os.tag) {
508508
.freestanding => {
509509
while (true) {
510510
@breakpoint();

lib/std/c.zig

+12-13
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
const builtin = @import("builtin");
21
const std = @import("std");
2+
const builtin = std.builtin;
33
const page_size = std.mem.page_size;
44

55
pub const tokenizer = @import("c/tokenizer.zig");
@@ -10,7 +10,7 @@ pub const ast = @import("c/ast.zig");
1010

1111
pub usingnamespace @import("os/bits.zig");
1212

13-
pub usingnamespace switch (builtin.os) {
13+
pub usingnamespace switch (std.Target.current.os.tag) {
1414
.linux => @import("c/linux.zig"),
1515
.windows => @import("c/windows.zig"),
1616
.macosx, .ios, .tvos, .watchos => @import("c/darwin.zig"),
@@ -46,17 +46,16 @@ pub fn versionCheck(glibc_version: builtin.Version) type {
4646
return struct {
4747
pub const ok = blk: {
4848
if (!builtin.link_libc) break :blk false;
49-
switch (builtin.abi) {
50-
.musl, .musleabi, .musleabihf => break :blk true,
51-
.gnu, .gnuabin32, .gnuabi64, .gnueabi, .gnueabihf, .gnux32 => {
52-
const ver = builtin.glibc_version orelse break :blk false;
53-
if (ver.major < glibc_version.major) break :blk false;
54-
if (ver.major > glibc_version.major) break :blk true;
55-
if (ver.minor < glibc_version.minor) break :blk false;
56-
if (ver.minor > glibc_version.minor) break :blk true;
57-
break :blk ver.patch >= glibc_version.patch;
58-
},
59-
else => break :blk false,
49+
if (std.Target.current.abi.isMusl()) break :blk true;
50+
if (std.Target.current.isGnuLibC()) {
51+
const ver = std.Target.current.os.version_range.linux.glibc;
52+
const order = ver.order(glibc_version);
53+
break :blk switch (order) {
54+
.gt, .eq => true,
55+
.lt => false,
56+
};
57+
} else {
58+
break :blk false;
6059
}
6160
};
6261
};

lib/std/c/linux.zig

+1-1
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ pub const pthread_cond_t = extern struct {
9494
size: [__SIZEOF_PTHREAD_COND_T]u8 align(@alignOf(usize)) = [_]u8{0} ** __SIZEOF_PTHREAD_COND_T,
9595
};
9696
const __SIZEOF_PTHREAD_COND_T = 48;
97-
const __SIZEOF_PTHREAD_MUTEX_T = if (builtin.os == .fuchsia) 40 else switch (builtin.abi) {
97+
const __SIZEOF_PTHREAD_MUTEX_T = if (builtin.os.tag == .fuchsia) 40 else switch (builtin.abi) {
9898
.musl, .musleabi, .musleabihf => if (@sizeOf(usize) == 8) 40 else 24,
9999
.gnu, .gnuabin32, .gnuabi64, .gnueabi, .gnueabihf, .gnux32 => switch (builtin.arch) {
100100
.aarch64 => 48,

lib/std/child_process.zig

+13-13
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@ const TailQueue = std.TailQueue;
1717
const maxInt = std.math.maxInt;
1818

1919
pub const ChildProcess = struct {
20-
pid: if (builtin.os == .windows) void else i32,
21-
handle: if (builtin.os == .windows) windows.HANDLE else void,
22-
thread_handle: if (builtin.os == .windows) windows.HANDLE else void,
20+
pid: if (builtin.os.tag == .windows) void else i32,
21+
handle: if (builtin.os.tag == .windows) windows.HANDLE else void,
22+
thread_handle: if (builtin.os.tag == .windows) windows.HANDLE else void,
2323

2424
allocator: *mem.Allocator,
2525

@@ -39,15 +39,15 @@ pub const ChildProcess = struct {
3939
stderr_behavior: StdIo,
4040

4141
/// 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

4444
/// 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

4747
/// Set to change the current working directory when spawning the child process.
4848
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

5252
expand_arg0: Arg0Expand,
5353

@@ -96,8 +96,8 @@ pub const ChildProcess = struct {
9696
.term = null,
9797
.env_map = null,
9898
.cwd = null,
99-
.uid = if (builtin.os == .windows) {} else null,
100-
.gid = if (builtin.os == .windows) {} else null,
99+
.uid = if (builtin.os.tag == .windows) {} else null,
100+
.gid = if (builtin.os.tag == .windows) {} else null,
101101
.stdin = null,
102102
.stdout = null,
103103
.stderr = null,
@@ -118,7 +118,7 @@ pub const ChildProcess = struct {
118118

119119
/// On success must call `kill` or `wait`.
120120
pub fn spawn(self: *ChildProcess) SpawnError!void {
121-
if (builtin.os == .windows) {
121+
if (builtin.os.tag == .windows) {
122122
return self.spawnWindows();
123123
} else {
124124
return self.spawnPosix();
@@ -132,7 +132,7 @@ pub const ChildProcess = struct {
132132

133133
/// Forcibly terminates child process and then cleans up all resources.
134134
pub fn kill(self: *ChildProcess) !Term {
135-
if (builtin.os == .windows) {
135+
if (builtin.os.tag == .windows) {
136136
return self.killWindows(1);
137137
} else {
138138
return self.killPosix();
@@ -162,7 +162,7 @@ pub const ChildProcess = struct {
162162

163163
/// Blocks until child process terminates and then cleans up all resources.
164164
pub fn wait(self: *ChildProcess) !Term {
165-
if (builtin.os == .windows) {
165+
if (builtin.os.tag == .windows) {
166166
return self.waitWindows();
167167
} else {
168168
return self.waitPosix();
@@ -307,7 +307,7 @@ pub const ChildProcess = struct {
307307
fn cleanupAfterWait(self: *ChildProcess, status: u32) !Term {
308308
defer destroyPipe(self.err_pipe);
309309

310-
if (builtin.os == .linux) {
310+
if (builtin.os.tag == .linux) {
311311
var fd = [1]std.os.pollfd{std.os.pollfd{
312312
.fd = self.err_pipe[0],
313313
.events = std.os.POLLIN,
@@ -402,7 +402,7 @@ pub const ChildProcess = struct {
402402
// This pipe is used to communicate errors between the time of fork
403403
// and execve from the child process to the parent process.
404404
const err_pipe = blk: {
405-
if (builtin.os == .linux) {
405+
if (builtin.os.tag == .linux) {
406406
const fd = try os.eventfd(0, 0);
407407
// There's no distinction between the readable and the writeable
408408
// end with eventfd

lib/std/cstr.zig

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ const debug = std.debug;
44
const mem = std.mem;
55
const testing = std.testing;
66

7-
pub const line_sep = switch (builtin.os) {
8-
builtin.Os.windows => "\r\n",
7+
pub const line_sep = switch (builtin.os.tag) {
8+
.windows => "\r\n",
99
else => "\n",
1010
};
1111

lib/std/debug.zig

+12-12
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
const std = @import("std.zig");
2+
const builtin = std.builtin;
23
const math = std.math;
34
const mem = std.mem;
45
const io = std.io;
@@ -11,7 +12,6 @@ const macho = std.macho;
1112
const coff = std.coff;
1213
const pdb = std.pdb;
1314
const ArrayList = std.ArrayList;
14-
const builtin = @import("builtin");
1515
const root = @import("root");
1616
const maxInt = std.math.maxInt;
1717
const File = std.fs.File;
@@ -101,7 +101,7 @@ pub fn detectTTYConfig() TTY.Config {
101101
} else |_| {
102102
if (stderr_file.supportsAnsiEscapeCodes()) {
103103
return .escape_codes;
104-
} else if (builtin.os == .windows and stderr_file.isTty()) {
104+
} else if (builtin.os.tag == .windows and stderr_file.isTty()) {
105105
return .windows_api;
106106
} else {
107107
return .no_color;
@@ -155,7 +155,7 @@ pub fn dumpStackTraceFromBase(bp: usize, ip: usize) void {
155155
/// chopping off the irrelevant frames and shifting so that the returned addresses pointer
156156
/// equals the passed in addresses pointer.
157157
pub fn captureStackTrace(first_address: ?usize, stack_trace: *builtin.StackTrace) void {
158-
if (builtin.os == .windows) {
158+
if (builtin.os.tag == .windows) {
159159
const addrs = stack_trace.instruction_addresses;
160160
const u32_addrs_len = @intCast(u32, addrs.len);
161161
const first_addr = first_address orelse {
@@ -231,7 +231,7 @@ pub fn assert(ok: bool) void {
231231
pub fn panic(comptime format: []const u8, args: var) noreturn {
232232
@setCold(true);
233233
// 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();
235235
panicExtra(null, first_trace_addr, format, args);
236236
}
237237

@@ -361,7 +361,7 @@ pub fn writeCurrentStackTrace(
361361
tty_config: TTY.Config,
362362
start_addr: ?usize,
363363
) !void {
364-
if (builtin.os == .windows) {
364+
if (builtin.os.tag == .windows) {
365365
return writeCurrentStackTraceWindows(out_stream, debug_info, tty_config, start_addr);
366366
}
367367
var it = StackIterator.init(start_addr, null);
@@ -418,7 +418,7 @@ pub const TTY = struct {
418418
.Dim => noasync out_stream.write(DIM) catch return,
419419
.Reset => noasync out_stream.write(RESET) catch return,
420420
},
421-
.windows_api => if (builtin.os == .windows) {
421+
.windows_api => if (builtin.os.tag == .windows) {
422422
const S = struct {
423423
var attrs: windows.WORD = undefined;
424424
var init_attrs = false;
@@ -617,7 +617,7 @@ pub fn openSelfDebugInfo(allocator: *mem.Allocator) anyerror!DebugInfo {
617617
if (@hasDecl(root, "os") and @hasDecl(root.os, "debug") and @hasDecl(root.os.debug, "openSelfDebugInfo")) {
618618
return noasync root.os.debug.openSelfDebugInfo(allocator);
619619
}
620-
switch (builtin.os) {
620+
switch (builtin.os.tag) {
621621
.linux,
622622
.freebsd,
623623
.macosx,
@@ -1019,7 +1019,7 @@ pub const DebugInfo = struct {
10191019
pub fn getModuleForAddress(self: *DebugInfo, address: usize) !*ModuleDebugInfo {
10201020
if (comptime std.Target.current.isDarwin())
10211021
return self.lookupModuleDyld(address)
1022-
else if (builtin.os == .windows)
1022+
else if (builtin.os.tag == .windows)
10231023
return self.lookupModuleWin32(address)
10241024
else
10251025
return self.lookupModuleDl(address);
@@ -1242,7 +1242,7 @@ const SymbolInfo = struct {
12421242
}
12431243
};
12441244

1245-
pub const ModuleDebugInfo = switch (builtin.os) {
1245+
pub const ModuleDebugInfo = switch (builtin.os.tag) {
12461246
.macosx, .ios, .watchos, .tvos => struct {
12471247
base_address: usize,
12481248
mapped_memory: []const u8,
@@ -1602,7 +1602,7 @@ fn getDebugInfoAllocator() *mem.Allocator {
16021602
}
16031603

16041604
/// Whether or not the current target can print useful debug information when a segfault occurs.
1605-
pub const have_segfault_handling_support = builtin.os == .linux or builtin.os == .windows;
1605+
pub const have_segfault_handling_support = builtin.os.tag == .linux or builtin.os.tag == .windows;
16061606
pub const enable_segfault_handler: bool = if (@hasDecl(root, "enable_segfault_handler"))
16071607
root.enable_segfault_handler
16081608
else
@@ -1621,7 +1621,7 @@ pub fn attachSegfaultHandler() void {
16211621
if (!have_segfault_handling_support) {
16221622
@compileError("segfault handler not supported for this target");
16231623
}
1624-
if (builtin.os == .windows) {
1624+
if (builtin.os.tag == .windows) {
16251625
windows_segfault_handle = windows.kernel32.AddVectoredExceptionHandler(0, handleSegfaultWindows);
16261626
return;
16271627
}
@@ -1637,7 +1637,7 @@ pub fn attachSegfaultHandler() void {
16371637
}
16381638

16391639
fn resetSegfaultHandler() void {
1640-
if (builtin.os == .windows) {
1640+
if (builtin.os.tag == .windows) {
16411641
if (windows_segfault_handle) |handle| {
16421642
assert(windows.kernel32.RemoveVectoredExceptionHandler(handle) != 0);
16431643
windows_segfault_handle = null;

lib/std/dynamic_library.zig

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ const system = std.os.system;
1111
const maxInt = std.math.maxInt;
1212
const max = std.math.max;
1313

14-
pub const DynLib = switch (builtin.os) {
14+
pub const DynLib = switch (builtin.os.tag) {
1515
.linux => if (builtin.link_libc) DlDynlib else ElfDynLib,
1616
.windows => WindowsDynLib,
1717
.macosx, .tvos, .watchos, .ios, .freebsd => DlDynlib,
@@ -390,7 +390,7 @@ pub const DlDynlib = struct {
390390
};
391391

392392
test "dynamic_library" {
393-
const libname = switch (builtin.os) {
393+
const libname = switch (builtin.os.tag) {
394394
.linux, .freebsd => "invalid_so.so",
395395
.windows => "invalid_dll.dll",
396396
.macosx, .tvos, .watchos, .ios => "invalid_dylib.dylib",

0 commit comments

Comments
 (0)