Skip to content

Commit 5349348

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 2ce3a34 commit 5349348

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

+1274
-932
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

+11-11
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ pub fn detectTTYConfig() TTY.Config {
8989
} else |_| {
9090
if (stderr_file.supportsAnsiEscapeCodes()) {
9191
return .escape_codes;
92-
} else if (builtin.os == .windows and stderr_file.isTty()) {
92+
} else if (builtin.os.tag == .windows and stderr_file.isTty()) {
9393
return .windows_api;
9494
} else {
9595
return .no_color;
@@ -143,7 +143,7 @@ pub fn dumpStackTraceFromBase(bp: usize, ip: usize) void {
143143
/// chopping off the irrelevant frames and shifting so that the returned addresses pointer
144144
/// equals the passed in addresses pointer.
145145
pub fn captureStackTrace(first_address: ?usize, stack_trace: *builtin.StackTrace) void {
146-
if (builtin.os == .windows) {
146+
if (builtin.os.tag == .windows) {
147147
const addrs = stack_trace.instruction_addresses;
148148
const u32_addrs_len = @intCast(u32, addrs.len);
149149
const first_addr = first_address orelse {
@@ -219,7 +219,7 @@ pub fn assert(ok: bool) void {
219219
pub fn panic(comptime format: []const u8, args: var) noreturn {
220220
@setCold(true);
221221
// TODO: remove conditional once wasi / LLVM defines __builtin_return_address
222-
const first_trace_addr = if (builtin.os == .wasi) null else @returnAddress();
222+
const first_trace_addr = if (builtin.os.tag == .wasi) null else @returnAddress();
223223
panicExtra(null, first_trace_addr, format, args);
224224
}
225225

@@ -349,7 +349,7 @@ pub fn writeCurrentStackTrace(
349349
tty_config: TTY.Config,
350350
start_addr: ?usize,
351351
) !void {
352-
if (builtin.os == .windows) {
352+
if (builtin.os.tag == .windows) {
353353
return writeCurrentStackTraceWindows(out_stream, debug_info, tty_config, start_addr);
354354
}
355355
var it = StackIterator.init(start_addr, null);
@@ -381,7 +381,7 @@ pub fn writeCurrentStackTraceWindows(
381381
/// TODO once https://github.com/ziglang/zig/issues/3157 is fully implemented,
382382
/// make this `noasync fn` and remove the individual noasync calls.
383383
pub fn printSourceAtAddress(debug_info: *DebugInfo, out_stream: var, address: usize, tty_config: TTY.Config) !void {
384-
if (builtin.os == .windows) {
384+
if (builtin.os.tag == .windows) {
385385
return noasync printSourceAtAddressWindows(debug_info, out_stream, address, tty_config);
386386
}
387387
if (comptime std.Target.current.isDarwin()) {
@@ -575,7 +575,7 @@ pub const TTY = struct {
575575
.Dim => noasync out_stream.write(DIM) catch return,
576576
.Reset => noasync out_stream.write(RESET) catch return,
577577
},
578-
.windows_api => if (builtin.os == .windows) {
578+
.windows_api => if (builtin.os.tag == .windows) {
579579
const S = struct {
580580
var attrs: windows.WORD = undefined;
581581
var init_attrs = false;
@@ -778,7 +778,7 @@ pub fn openSelfDebugInfo(allocator: *mem.Allocator) !DebugInfo {
778778
if (@hasDecl(root, "os") and @hasDecl(root.os, "debug") and @hasDecl(root.os.debug, "openSelfDebugInfo")) {
779779
return noasync root.os.debug.openSelfDebugInfo(allocator);
780780
}
781-
if (builtin.os == .windows) {
781+
if (builtin.os.tag == .windows) {
782782
return noasync openSelfDebugInfoWindows(allocator);
783783
}
784784
if (comptime std.Target.current.isDarwin()) {
@@ -1688,7 +1688,7 @@ pub const DwarfInfo = struct {
16881688
}
16891689
};
16901690

1691-
pub const DebugInfo = switch (builtin.os) {
1691+
pub const DebugInfo = switch (builtin.os.tag) {
16921692
.macosx, .ios, .watchos, .tvos => struct {
16931693
symbols: []const MachoSymbol,
16941694
strings: []const u8,
@@ -2225,7 +2225,7 @@ fn getDebugInfoAllocator() *mem.Allocator {
22252225
}
22262226

22272227
/// Whether or not the current target can print useful debug information when a segfault occurs.
2228-
pub const have_segfault_handling_support = builtin.os == .linux or builtin.os == .windows;
2228+
pub const have_segfault_handling_support = builtin.os.tag == .linux or builtin.os.tag == .windows;
22292229
pub const enable_segfault_handler: bool = if (@hasDecl(root, "enable_segfault_handler"))
22302230
root.enable_segfault_handler
22312231
else
@@ -2244,7 +2244,7 @@ pub fn attachSegfaultHandler() void {
22442244
if (!have_segfault_handling_support) {
22452245
@compileError("segfault handler not supported for this target");
22462246
}
2247-
if (builtin.os == .windows) {
2247+
if (builtin.os.tag == .windows) {
22482248
windows_segfault_handle = windows.kernel32.AddVectoredExceptionHandler(0, handleSegfaultWindows);
22492249
return;
22502250
}
@@ -2260,7 +2260,7 @@ pub fn attachSegfaultHandler() void {
22602260
}
22612261

22622262
fn resetSegfaultHandler() void {
2263-
if (builtin.os == .windows) {
2263+
if (builtin.os.tag == .windows) {
22642264
if (windows_segfault_handle) |handle| {
22652265
assert(windows.kernel32.RemoveVectoredExceptionHandler(handle) != 0);
22662266
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",

lib/std/elf.zig

+15-10
Original file line numberDiff line numberDiff line change
@@ -349,16 +349,6 @@ pub const Elf = struct {
349349
program_headers: []ProgramHeader,
350350
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-
362352
pub fn openStream(
363353
allocator: *mem.Allocator,
364354
seekable_stream: *io.SeekableStream(anyerror, anyerror),
@@ -554,6 +544,21 @@ pub const Elf = struct {
554544
};
555545

556546
pub const EI_NIDENT = 16;
547+
548+
pub const EI_CLASS = 4;
549+
pub const ELFCLASSNONE = 0;
550+
pub const ELFCLASS32 = 1;
551+
pub const ELFCLASS64 = 2;
552+
pub const ELFCLASSNUM = 3;
553+
554+
pub const EI_DATA = 5;
555+
pub const ELFDATANONE = 0;
556+
pub const ELFDATA2LSB = 1;
557+
pub const ELFDATA2MSB = 2;
558+
pub const ELFDATANUM = 3;
559+
560+
pub const EI_VERSION = 6;
561+
557562
pub const Elf32_Half = u16;
558563
pub const Elf64_Half = u16;
559564
pub const Elf32_Word = u32;

lib/std/event/channel.zig

+1-1
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,7 @@ test "std.event.Channel" {
273273
if (builtin.single_threaded) return error.SkipZigTest;
274274

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

278278
var channel: Channel(i32) = undefined;
279279
channel.init(&[0]i32{});

0 commit comments

Comments
 (0)