authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-07-18 00:34:42-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-07-18 17:43:36-04:00
logaa3b41247f297b4fd8b3bdb7920cb479f5aa004b
tree3e8bc66c275175cabe3f0a6fb6b8febd2c34c8bd
parent3e4a3fa5b7faadaae0a57088baa392e2bb52fe38

self-hosted: linking against libc

also introduce `zig libc` command to display paths `zig libc file.txt` will parse equivalent text and use that for libc paths.

8 files changed, 709 insertions(+), 172 deletions(-)

src-self-hosted/codegen.zig+1-1
...@@ -15,7 +15,7 @@ pub async fn renderToLlvm(comp: *Compilation, fn_val: *Value.Fn, code: *ir.Code)...@@ -15,7 +15,7 @@ pub async fn renderToLlvm(comp: *Compilation, fn_val: *Value.Fn, code: *ir.Code)
15 defer fn_val.base.deref(comp);15 defer fn_val.base.deref(comp);
16 defer code.destroy(comp.gpa());16 defer code.destroy(comp.gpa());
1717
18 var output_path = try await (async comp.createRandomOutputPath(comp.target.oFileExt()) catch unreachable);18 var output_path = try await (async comp.createRandomOutputPath(comp.target.objFileExt()) catch unreachable);
19 errdefer output_path.deinit();19 errdefer output_path.deinit();
2020
21 const llvm_handle = try comp.event_loop_local.getAnyLlvmContext();21 const llvm_handle = try comp.event_loop_local.getAnyLlvmContext();
src-self-hosted/compilation.zig+37-14
...@@ -120,7 +120,6 @@ pub const Compilation = struct {...@@ -120,7 +120,6 @@ pub const Compilation = struct {
120120
121 linker_script: ?[]const u8,121 linker_script: ?[]const u8,
122 cache_dir: []const u8,122 cache_dir: []const u8,
123 dynamic_linker: ?[]const u8,
124 out_h_path: ?[]const u8,123 out_h_path: ?[]const u8,
125124
126 is_test: bool,125 is_test: bool,
...@@ -201,6 +200,13 @@ pub const Compilation = struct {...@@ -201,6 +200,13 @@ pub const Compilation = struct {
201 root_package: *Package,200 root_package: *Package,
202 std_package: *Package,201 std_package: *Package,
203202
203 override_libc: ?*LibCInstallation,
204
205 /// need to wait on this group before deinitializing
206 deinit_group: event.Group(void),
207
208 destroy_handle: promise,
209
204 const CompileErrList = std.ArrayList(*errmsg.Msg);210 const CompileErrList = std.ArrayList(*errmsg.Msg);
205211
206 // TODO handle some of these earlier and report them in a way other than error codes212 // TODO handle some of these earlier and report them in a way other than error codes
...@@ -246,6 +252,8 @@ pub const Compilation = struct {...@@ -246,6 +252,8 @@ pub const Compilation = struct {
246 EnvironmentVariableNotFound,252 EnvironmentVariableNotFound,
247 AppDataDirUnavailable,253 AppDataDirUnavailable,
248 LinkFailed,254 LinkFailed,
255 LibCRequiredButNotProvidedOrFound,
256 LibCMissingDynamicLinker,
249 };257 };
250258
251 pub const Event = union(enum) {259 pub const Event = union(enum) {
...@@ -324,7 +332,6 @@ pub const Compilation = struct {...@@ -324,7 +332,6 @@ pub const Compilation = struct {
324 .verbose_link = false,332 .verbose_link = false,
325333
326 .linker_script = null,334 .linker_script = null,
327 .dynamic_linker = null,
328 .out_h_path = null,335 .out_h_path = null,
329 .is_test = false,336 .is_test = false,
330 .each_lib_rpath = false,337 .each_lib_rpath = false,
...@@ -351,6 +358,7 @@ pub const Compilation = struct {...@@ -351,6 +358,7 @@ pub const Compilation = struct {
351 .link_out_file = null,358 .link_out_file = null,
352 .exported_symbol_names = event.Locked(Decl.Table).init(loop, Decl.Table.init(loop.allocator)),359 .exported_symbol_names = event.Locked(Decl.Table).init(loop, Decl.Table.init(loop.allocator)),
353 .prelink_group = event.Group(BuildError!void).init(loop),360 .prelink_group = event.Group(BuildError!void).init(loop),
361 .deinit_group = event.Group(void).init(loop),
354 .compile_errors = event.Locked(CompileErrList).init(loop, CompileErrList.init(loop.allocator)),362 .compile_errors = event.Locked(CompileErrList).init(loop, CompileErrList.init(loop.allocator)),
355363
356 .meta_type = undefined,364 .meta_type = undefined,
...@@ -368,6 +376,9 @@ pub const Compilation = struct {...@@ -368,6 +376,9 @@ pub const Compilation = struct {
368376
369 .root_package = undefined,377 .root_package = undefined,
370 .std_package = undefined,378 .std_package = undefined,
379
380 .override_libc = null,
381 .destroy_handle = undefined,
371 });382 });
372 errdefer {383 errdefer {
373 comp.arena_allocator.deinit();384 comp.arena_allocator.deinit();
...@@ -431,6 +442,9 @@ pub const Compilation = struct {...@@ -431,6 +442,9 @@ pub const Compilation = struct {
431 }442 }
432443
433 try comp.initTypes();444 try comp.initTypes();
445 errdefer comp.derefTypes();
446
447 comp.destroy_handle = try async<loop.allocator> comp.internalDeinit();
434448
435 return comp;449 return comp;
436 }450 }
...@@ -526,11 +540,7 @@ pub const Compilation = struct {...@@ -526,11 +540,7 @@ pub const Compilation = struct {
526 errdefer comp.gpa().destroy(comp.noreturn_value);540 errdefer comp.gpa().destroy(comp.noreturn_value);
527 }541 }
528542
529 pub fn destroy(self: *Compilation) void {543 fn derefTypes(self: *Compilation) void {
530 if (self.tmp_dir.getOrNull()) |tmp_dir_result| if (tmp_dir_result.*) |tmp_dir| {
531 os.deleteTree(self.arena(), tmp_dir) catch {};
532 } else |_| {};
533
534 self.noreturn_value.base.deref(self);544 self.noreturn_value.base.deref(self);
535 self.void_value.base.deref(self);545 self.void_value.base.deref(self);
536 self.false_value.base.deref(self);546 self.false_value.base.deref(self);
...@@ -538,6 +548,17 @@ pub const Compilation = struct {...@@ -538,6 +548,17 @@ pub const Compilation = struct {
538 self.noreturn_type.base.base.deref(self);548 self.noreturn_type.base.base.deref(self);
539 self.void_type.base.base.deref(self);549 self.void_type.base.base.deref(self);
540 self.meta_type.base.base.deref(self);550 self.meta_type.base.base.deref(self);
551 }
552
553 async fn internalDeinit(self: *Compilation) void {
554 suspend;
555 await (async self.deinit_group.wait() catch unreachable);
556 if (self.tmp_dir.getOrNull()) |tmp_dir_result| if (tmp_dir_result.*) |tmp_dir| {
557 // TODO evented I/O?
558 os.deleteTree(self.arena(), tmp_dir) catch {};
559 } else |_| {};
560
561 self.derefTypes();
541562
542 self.events.destroy();563 self.events.destroy();
543564
...@@ -549,6 +570,10 @@ pub const Compilation = struct {...@@ -549,6 +570,10 @@ pub const Compilation = struct {
549 self.gpa().destroy(self);570 self.gpa().destroy(self);
550 }571 }
551572
573 pub fn destroy(self: *Compilation) void {
574 resume self.destroy_handle;
575 }
576
552 pub fn build(self: *Compilation) !void {577 pub fn build(self: *Compilation) !void {
553 if (self.llvm_argv.len != 0) {578 if (self.llvm_argv.len != 0) {
554 var c_compatible_args = try std.cstr.NullTerminated2DArray.fromSlices(self.arena(), [][]const []const u8{579 var c_compatible_args = try std.cstr.NullTerminated2DArray.fromSlices(self.arena(), [][]const []const u8{
...@@ -680,7 +705,7 @@ pub const Compilation = struct {...@@ -680,7 +705,7 @@ pub const Compilation = struct {
680 };705 };
681706
682 if (!any_prelink_errors) {707 if (!any_prelink_errors) {
683 try link(self);708 try await (async link(self) catch unreachable);
684 }709 }
685 }710 }
686711
...@@ -765,8 +790,8 @@ pub const Compilation = struct {...@@ -765,8 +790,8 @@ pub const Compilation = struct {
765 self.libc_link_lib = link_lib;790 self.libc_link_lib = link_lib;
766791
767 // get a head start on looking for the native libc792 // get a head start on looking for the native libc
768 if (self.target == Target.Native) {793 if (self.target == Target.Native and self.override_libc == null) {
769 try async<self.loop.allocator> self.startFindingNativeLibC();794 try self.deinit_group.call(startFindingNativeLibC, self);
770 }795 }
771 }796 }
772 return link_lib;797 return link_lib;
...@@ -774,11 +799,9 @@ pub const Compilation = struct {...@@ -774,11 +799,9 @@ pub const Compilation = struct {
774799
775 /// cancels itself so no need to await or cancel the promise.800 /// cancels itself so no need to await or cancel the promise.
776 async fn startFindingNativeLibC(self: *Compilation) void {801 async fn startFindingNativeLibC(self: *Compilation) void {
802 await (async self.loop.yield() catch unreachable);
777 // we don't care if it fails, we're just trying to kick off the future resolution803 // we don't care if it fails, we're just trying to kick off the future resolution
778 _ = (await (async self.loop.call(EventLoopLocal.getNativeLibC, self.event_loop_local) catch unreachable)) catch {};804 _ = (await (async self.event_loop_local.getNativeLibC() catch unreachable)) catch return;
779 suspend |p| {
780 cancel p;
781 }
782 }805 }
783806
784 /// General Purpose Allocator. Must free when done.807 /// General Purpose Allocator. Must free when done.
src-self-hosted/libc_installation.zig+187-35
...@@ -1,31 +1,18 @@...@@ -1,31 +1,18 @@
1const std = @import("std");1const std = @import("std");
2const builtin = @import("builtin");2const builtin = @import("builtin");
3const event = std.event;3const event = std.event;
4const Target = @import("target.zig").Target;
45
6/// See the render function implementation for documentation of the fields.
5pub const LibCInstallation = struct {7pub const LibCInstallation = struct {
6 /// The directory that contains `stdlib.h`.
7 /// On Linux, can be found with: `cc -E -Wp,-v -xc /dev/null`
8 include_dir: []const u8,8 include_dir: []const u8,
9
10 /// The directory that contains `crt1.o`.
11 /// On Linux, can be found with `cc -print-file-name=crt1.o`.
12 /// Not needed when targeting MacOS.
13 lib_dir: ?[]const u8,9 lib_dir: ?[]const u8,
14
15 /// The directory that contains `crtbegin.o`.
16 /// On Linux, can be found with `cc -print-file-name=crt1.o`.
17 /// Not needed when targeting MacOS or Windows.
18 static_lib_dir: ?[]const u8,10 static_lib_dir: ?[]const u8,
19
20 /// The directory that contains `vcruntime.lib`.
21 /// Only needed when targeting Windows.
22 msvc_lib_dir: ?[]const u8,11 msvc_lib_dir: ?[]const u8,
23
24 /// The directory that contains `kernel32.lib`.
25 /// Only needed when targeting Windows.
26 kernel32_lib_dir: ?[]const u8,12 kernel32_lib_dir: ?[]const u8,
13 dynamic_linker_path: ?[]const u8,
2714
28 pub const Error = error{15 pub const FindError = error{
29 OutOfMemory,16 OutOfMemory,
30 FileSystem,17 FileSystem,
31 UnableToSpawnCCompiler,18 UnableToSpawnCCompiler,
...@@ -36,16 +23,124 @@ pub const LibCInstallation = struct {...@@ -36,16 +23,124 @@ pub const LibCInstallation = struct {
36 LibCStdLibHeaderNotFound,23 LibCStdLibHeaderNotFound,
37 };24 };
3825
26 pub fn parse(
27 self: *LibCInstallation,
28 allocator: *std.mem.Allocator,
29 libc_file: []const u8,
30 stderr: *std.io.OutStream(std.io.FileOutStream.Error),
31 ) !void {
32 self.initEmpty();
33
34 const keys = []const []const u8{
35 "include_dir",
36 "lib_dir",
37 "static_lib_dir",
38 "msvc_lib_dir",
39 "kernel32_lib_dir",
40 "dynamic_linker_path",
41 };
42 const FoundKey = struct {
43 found: bool,
44 allocated: ?[]u8,
45 };
46 var found_keys = [1]FoundKey{FoundKey{ .found = false, .allocated = null }} ** keys.len;
47 errdefer {
48 self.initEmpty();
49 for (found_keys) |found_key| {
50 if (found_key.allocated) |s| allocator.free(s);
51 }
52 }
53
54 const contents = try std.io.readFileAlloc(allocator, libc_file);
55 defer allocator.free(contents);
56
57 var it = std.mem.split(contents, "\n");
58 while (it.next()) |line| {
59 if (line.len == 0 or line[0] == '#') continue;
60 var line_it = std.mem.split(line, "=");
61 const name = line_it.next() orelse {
62 try stderr.print("missing equal sign after field name\n");
63 return error.ParseError;
64 };
65 const value = line_it.rest();
66 inline for (keys) |key, i| {
67 if (std.mem.eql(u8, name, key)) {
68 found_keys[i].found = true;
69 switch (@typeInfo(@typeOf(@field(self, key)))) {
70 builtin.TypeId.Optional => {
71 if (value.len == 0) {
72 @field(self, key) = null;
73 } else {
74 found_keys[i].allocated = try std.mem.dupe(allocator, u8, value);
75 @field(self, key) = found_keys[i].allocated;
76 }
77 },
78 else => {
79 if (value.len == 0) {
80 try stderr.print("field cannot be empty: {}\n", key);
81 return error.ParseError;
82 }
83 const dupe = try std.mem.dupe(allocator, u8, value);
84 found_keys[i].allocated = dupe;
85 @field(self, key) = dupe;
86 },
87 }
88 break;
89 }
90 }
91 }
92 for (found_keys) |found_key, i| {
93 if (!found_key.found) {
94 try stderr.print("missing field: {}\n", keys[i]);
95 return error.ParseError;
96 }
97 }
98 }
99
100 pub fn render(self: *const LibCInstallation, out: *std.io.OutStream(std.io.FileOutStream.Error)) !void {
101 @setEvalBranchQuota(4000);
102 try out.print(
103 \\# The directory that contains `stdlib.h`.
104 \\# On Linux, can be found with: `cc -E -Wp,-v -xc /dev/null`
105 \\include_dir={}
106 \\
107 \\# The directory that contains `crt1.o`.
108 \\# On Linux, can be found with `cc -print-file-name=crt1.o`.
109 \\# Not needed when targeting MacOS.
110 \\lib_dir={}
111 \\
112 \\# The directory that contains `crtbegin.o`.
113 \\# On Linux, can be found with `cc -print-file-name=crt1.o`.
114 \\# Not needed when targeting MacOS or Windows.
115 \\static_lib_dir={}
116 \\
117 \\# The directory that contains `vcruntime.lib`.
118 \\# Only needed when targeting Windows.
119 \\msvc_lib_dir={}
120 \\
121 \\# The directory that contains `kernel32.lib`.
122 \\# Only needed when targeting Windows.
123 \\kernel32_lib_dir={}
124 \\
125 \\# The full path to the dynamic linker.
126 \\# Only needed when targeting Linux.
127 \\dynamic_linker_path={}
128 \\
129 ,
130 self.include_dir,
131 self.lib_dir orelse "",
132 self.static_lib_dir orelse "",
133 self.msvc_lib_dir orelse "",
134 self.kernel32_lib_dir orelse "",
135 self.dynamic_linker_path orelse Target(Target.Native).getDynamicLinkerPath(),
136 );
137 }
138
39 /// Finds the default, native libc.139 /// Finds the default, native libc.
40 pub async fn findNative(self: *LibCInstallation, loop: *event.Loop) !void {140 pub async fn findNative(self: *LibCInstallation, loop: *event.Loop) !void {
41 self.* = LibCInstallation{141 self.initEmpty();
42 .lib_dir = null,142 var group = event.Group(FindError!void).init(loop);
43 .include_dir = ([*]const u8)(undefined)[0..0],143 errdefer group.cancelAll();
44 .static_lib_dir = null,
45 .msvc_lib_dir = null,
46 .kernel32_lib_dir = null,
47 };
48 var group = event.Group(Error!void).init(loop);
49 switch (builtin.os) {144 switch (builtin.os) {
50 builtin.Os.windows => {145 builtin.Os.windows => {
51 try group.call(findNativeIncludeDirWindows, self, loop);146 try group.call(findNativeIncludeDirWindows, self, loop);
...@@ -57,6 +152,7 @@ pub const LibCInstallation = struct {...@@ -57,6 +152,7 @@ pub const LibCInstallation = struct {
57 try group.call(findNativeIncludeDirLinux, self, loop);152 try group.call(findNativeIncludeDirLinux, self, loop);
58 try group.call(findNativeLibDirLinux, self, loop);153 try group.call(findNativeLibDirLinux, self, loop);
59 try group.call(findNativeStaticLibDir, self, loop);154 try group.call(findNativeStaticLibDir, self, loop);
155 try group.call(findNativeDynamicLinker, self, loop);
60 },156 },
61 builtin.Os.macosx => {157 builtin.Os.macosx => {
62 try group.call(findNativeIncludeDirMacOS, self, loop);158 try group.call(findNativeIncludeDirMacOS, self, loop);
...@@ -147,7 +243,7 @@ pub const LibCInstallation = struct {...@@ -147,7 +243,7 @@ pub const LibCInstallation = struct {
147 self.include_dir = try std.mem.dupe(loop.allocator, u8, "/usr/include");243 self.include_dir = try std.mem.dupe(loop.allocator, u8, "/usr/include");
148 }244 }
149245
150 async fn findNativeLibDirWindows(self: *LibCInstallation, loop: *event.Loop) Error!void {246 async fn findNativeLibDirWindows(self: *LibCInstallation, loop: *event.Loop) FindError!void {
151 // TODO247 // TODO
152 //ZigWindowsSDK *sdk = get_windows_sdk(g);248 //ZigWindowsSDK *sdk = get_windows_sdk(g);
153249
...@@ -180,31 +276,83 @@ pub const LibCInstallation = struct {...@@ -180,31 +276,83 @@ pub const LibCInstallation = struct {
180 @panic("TODO");276 @panic("TODO");
181 }277 }
182278
183 async fn findNativeLibDirLinux(self: *LibCInstallation, loop: *event.Loop) Error!void {279 async fn findNativeLibDirLinux(self: *LibCInstallation, loop: *event.Loop) FindError!void {
184 self.lib_dir = try await (async ccPrintFileNameDir(loop, "crt1.o") catch unreachable);280 self.lib_dir = try await (async ccPrintFileName(loop, "crt1.o", true) catch unreachable);
281 }
282
283 async fn findNativeStaticLibDir(self: *LibCInstallation, loop: *event.Loop) FindError!void {
284 self.static_lib_dir = try await (async ccPrintFileName(loop, "crtbegin.o", true) catch unreachable);
285 }
286
287 async fn findNativeDynamicLinker(self: *LibCInstallation, loop: *event.Loop) FindError!void {
288 var dyn_tests = []DynTest{
289 DynTest{
290 .name = "ld-linux-x86-64.so.2",
291 .result = null,
292 },
293 DynTest{
294 .name = "ld-musl-x86_64.so.1",
295 .result = null,
296 },
297 };
298 var group = event.Group(FindError!void).init(loop);
299 errdefer group.cancelAll();
300 for (dyn_tests) |*dyn_test| {
301 try group.call(testNativeDynamicLinker, self, loop, dyn_test);
302 }
303 try await (async group.wait() catch unreachable);
304 for (dyn_tests) |*dyn_test| {
305 if (dyn_test.result) |result| {
306 self.dynamic_linker_path = result;
307 return;
308 }
309 }
185 }310 }
186311
187 async fn findNativeStaticLibDir(self: *LibCInstallation, loop: *event.Loop) Error!void {312 const DynTest = struct {
188 self.static_lib_dir = try await (async ccPrintFileNameDir(loop, "crtbegin.o") catch unreachable);313 name: []const u8,
314 result: ?[]const u8,
315 };
316
317 async fn testNativeDynamicLinker(self: *LibCInstallation, loop: *event.Loop, dyn_test: *DynTest) FindError!void {
318 if (await (async ccPrintFileName(loop, dyn_test.name, false) catch unreachable)) |result| {
319 dyn_test.result = result;
320 return;
321 } else |err| switch (err) {
322 error.CCompilerCannotFindCRuntime => return,
323 else => return err,
324 }
189 }325 }
190326
191 async fn findNativeMsvcLibDir(self: *LibCInstallation, loop: *event.Loop) Error!void {327 async fn findNativeMsvcLibDir(self: *LibCInstallation, loop: *event.Loop) FindError!void {
192 @panic("TODO");328 @panic("TODO");
193 }329 }
194330
195 async fn findNativeKernel32LibDir(self: *LibCInstallation, loop: *event.Loop) Error!void {331 async fn findNativeKernel32LibDir(self: *LibCInstallation, loop: *event.Loop) FindError!void {
196 @panic("TODO");332 @panic("TODO");
197 }333 }
334
335 fn initEmpty(self: *LibCInstallation) void {
336 self.* = LibCInstallation{
337 .include_dir = ([*]const u8)(undefined)[0..0],
338 .lib_dir = null,
339 .static_lib_dir = null,
340 .msvc_lib_dir = null,
341 .kernel32_lib_dir = null,
342 .dynamic_linker_path = null,
343 };
344 }
198};345};
199346
200/// caller owns returned memory347/// caller owns returned memory
201async fn ccPrintFileNameDir(loop: *event.Loop, o_file: []const u8) ![]u8 {348async fn ccPrintFileName(loop: *event.Loop, o_file: []const u8, want_dirname: bool) ![]u8 {
202 const cc_exe = std.os.getEnvPosix("CC") orelse "cc";349 const cc_exe = std.os.getEnvPosix("CC") orelse "cc";
203 const arg1 = try std.fmt.allocPrint(loop.allocator, "-print-file-name={}", o_file);350 const arg1 = try std.fmt.allocPrint(loop.allocator, "-print-file-name={}", o_file);
204 defer loop.allocator.free(arg1);351 defer loop.allocator.free(arg1);
205 const argv = []const []const u8{ cc_exe, arg1 };352 const argv = []const []const u8{ cc_exe, arg1 };
206353
207 // TODO evented I/O354 // TODO This simulates evented I/O for the child process exec
355 await (async loop.yield() catch unreachable);
208 const errorable_result = std.os.ChildProcess.exec(loop.allocator, argv, null, null, 1024 * 1024);356 const errorable_result = std.os.ChildProcess.exec(loop.allocator, argv, null, null, 1024 * 1024);
209 const exec_result = if (std.debug.runtime_safety) blk: {357 const exec_result = if (std.debug.runtime_safety) blk: {
210 break :blk errorable_result catch unreachable;358 break :blk errorable_result catch unreachable;
...@@ -230,5 +378,9 @@ async fn ccPrintFileNameDir(loop: *event.Loop, o_file: []const u8) ![]u8 {...@@ -230,5 +378,9 @@ async fn ccPrintFileNameDir(loop: *event.Loop, o_file: []const u8) ![]u8 {
230 const line = it.next() orelse return error.CCompilerCannotFindCRuntime;378 const line = it.next() orelse return error.CCompilerCannotFindCRuntime;
231 const dirname = std.os.path.dirname(line) orelse return error.CCompilerCannotFindCRuntime;379 const dirname = std.os.path.dirname(line) orelse return error.CCompilerCannotFindCRuntime;
232380
233 return std.mem.dupe(loop.allocator, u8, dirname);381 if (want_dirname) {
382 return std.mem.dupe(loop.allocator, u8, dirname);
383 } else {
384 return std.mem.dupe(loop.allocator, u8, line);
385 }
234}386}
src-self-hosted/link.zig+113-84
...@@ -3,6 +3,8 @@ const c = @import("c.zig");...@@ -3,6 +3,8 @@ const c = @import("c.zig");
3const builtin = @import("builtin");3const builtin = @import("builtin");
4const ObjectFormat = builtin.ObjectFormat;4const ObjectFormat = builtin.ObjectFormat;
5const Compilation = @import("compilation.zig").Compilation;5const Compilation = @import("compilation.zig").Compilation;
6const Target = @import("target.zig").Target;
7const LibCInstallation = @import("libc_installation.zig").LibCInstallation;
68
7const Context = struct {9const Context = struct {
8 comp: *Compilation,10 comp: *Compilation,
...@@ -12,9 +14,12 @@ const Context = struct {...@@ -12,9 +14,12 @@ const Context = struct {
1214
13 link_err: error{OutOfMemory}!void,15 link_err: error{OutOfMemory}!void,
14 link_msg: std.Buffer,16 link_msg: std.Buffer,
17
18 libc: *LibCInstallation,
19 out_file_path: std.Buffer,
15};20};
1621
17pub fn link(comp: *Compilation) !void {22pub async fn link(comp: *Compilation) !void {
18 var ctx = Context{23 var ctx = Context{
19 .comp = comp,24 .comp = comp,
20 .arena = std.heap.ArenaAllocator.init(comp.gpa()),25 .arena = std.heap.ArenaAllocator.init(comp.gpa()),
...@@ -22,15 +27,45 @@ pub fn link(comp: *Compilation) !void {...@@ -22,15 +27,45 @@ pub fn link(comp: *Compilation) !void {
22 .link_in_crt = comp.haveLibC() and comp.kind == Compilation.Kind.Exe,27 .link_in_crt = comp.haveLibC() and comp.kind == Compilation.Kind.Exe,
23 .link_err = {},28 .link_err = {},
24 .link_msg = undefined,29 .link_msg = undefined,
30 .libc = undefined,
31 .out_file_path = undefined,
25 };32 };
26 defer ctx.arena.deinit();33 defer ctx.arena.deinit();
27 ctx.args = std.ArrayList([*]const u8).init(&ctx.arena.allocator);34 ctx.args = std.ArrayList([*]const u8).init(&ctx.arena.allocator);
28 ctx.link_msg = std.Buffer.initNull(&ctx.arena.allocator);35 ctx.link_msg = std.Buffer.initNull(&ctx.arena.allocator);
2936
37 if (comp.link_out_file) |out_file| {
38 ctx.out_file_path = try std.Buffer.init(&ctx.arena.allocator, out_file);
39 } else {
40 ctx.out_file_path = try std.Buffer.init(&ctx.arena.allocator, comp.name.toSliceConst());
41 switch (comp.kind) {
42 Compilation.Kind.Exe => {
43 try ctx.out_file_path.append(comp.target.exeFileExt());
44 },
45 Compilation.Kind.Lib => {
46 try ctx.out_file_path.append(comp.target.libFileExt(comp.is_static));
47 },
48 Compilation.Kind.Obj => {
49 try ctx.out_file_path.append(comp.target.objFileExt());
50 },
51 }
52 }
53
30 // even though we're calling LLD as a library it thinks the first54 // even though we're calling LLD as a library it thinks the first
31 // argument is its own exe name55 // argument is its own exe name
32 try ctx.args.append(c"lld");56 try ctx.args.append(c"lld");
3357
58 if (comp.haveLibC()) {
59 ctx.libc = ctx.comp.override_libc orelse blk: {
60 switch (comp.target) {
61 Target.Native => {
62 break :blk (await (async comp.event_loop_local.getNativeLibC() catch unreachable)) catch return error.LibCRequiredButNotProvidedOrFound;
63 },
64 else => return error.LibCRequiredButNotProvidedOrFound,
65 }
66 };
67 }
68
34 try constructLinkerArgs(&ctx);69 try constructLinkerArgs(&ctx);
3570
36 if (comp.verbose_link) {71 if (comp.verbose_link) {
...@@ -43,6 +78,7 @@ pub fn link(comp: *Compilation) !void {...@@ -43,6 +78,7 @@ pub fn link(comp: *Compilation) !void {
4378
44 const extern_ofmt = toExternObjectFormatType(comp.target.getObjectFormat());79 const extern_ofmt = toExternObjectFormatType(comp.target.getObjectFormat());
45 const args_slice = ctx.args.toSlice();80 const args_slice = ctx.args.toSlice();
81 // Not evented I/O. LLD does its own multithreading internally.
46 if (!ZigLLDLink(extern_ofmt, args_slice.ptr, args_slice.len, linkDiagCallback, @ptrCast(*c_void, &ctx))) {82 if (!ZigLLDLink(extern_ofmt, args_slice.ptr, args_slice.len, linkDiagCallback, @ptrCast(*c_void, &ctx))) {
47 if (!ctx.link_msg.isNull()) {83 if (!ctx.link_msg.isNull()) {
48 // TODO capture these messages and pass them through the system, reporting them through the84 // TODO capture these messages and pass them through the system, reporting them through the
...@@ -95,10 +131,7 @@ fn constructLinkerArgs(ctx: *Context) !void {...@@ -95,10 +131,7 @@ fn constructLinkerArgs(ctx: *Context) !void {
95}131}
96132
97fn constructLinkerArgsElf(ctx: *Context) !void {133fn constructLinkerArgsElf(ctx: *Context) !void {
98 //if (g->libc_link_lib != nullptr) {134 // TODO commented out code in this function
99 // find_libc_lib_path(g);
100 //}
101
102 //if (g->linker_script) {135 //if (g->linker_script) {
103 // lj->args.append("-T");136 // lj->args.append("-T");
104 // lj->args.append(g->linker_script);137 // lj->args.append(g->linker_script);
...@@ -107,7 +140,7 @@ fn constructLinkerArgsElf(ctx: *Context) !void {...@@ -107,7 +140,7 @@ fn constructLinkerArgsElf(ctx: *Context) !void {
107 //if (g->no_rosegment_workaround) {140 //if (g->no_rosegment_workaround) {
108 // lj->args.append("--no-rosegment");141 // lj->args.append("--no-rosegment");
109 //}142 //}
110 //lj->args.append("--gc-sections");143 try ctx.args.append(c"--gc-sections");
111144
112 //lj->args.append("-m");145 //lj->args.append("-m");
113 //lj->args.append(getLDMOption(&g->zig_target));146 //lj->args.append(getLDMOption(&g->zig_target));
...@@ -115,14 +148,13 @@ fn constructLinkerArgsElf(ctx: *Context) !void {...@@ -115,14 +148,13 @@ fn constructLinkerArgsElf(ctx: *Context) !void {
115 //bool is_lib = g->out_type == OutTypeLib;148 //bool is_lib = g->out_type == OutTypeLib;
116 //bool shared = !g->is_static && is_lib;149 //bool shared = !g->is_static && is_lib;
117 //Buf *soname = nullptr;150 //Buf *soname = nullptr;
118 //if (g->is_static) {151 if (ctx.comp.is_static) {
119 // if (g->zig_target.arch.arch == ZigLLVM_arm || g->zig_target.arch.arch == ZigLLVM_armeb ||152 if (ctx.comp.target.isArmOrThumb()) {
120 // g->zig_target.arch.arch == ZigLLVM_thumb || g->zig_target.arch.arch == ZigLLVM_thumbeb)153 try ctx.args.append(c"-Bstatic");
121 // {154 } else {
122 // lj->args.append("-Bstatic");155 try ctx.args.append(c"-static");
123 // } else {156 }
124 // lj->args.append("-static");157 }
125 // }
126 //} else if (shared) {158 //} else if (shared) {
127 // lj->args.append("-shared");159 // lj->args.append("-shared");
128160
...@@ -133,23 +165,16 @@ fn constructLinkerArgsElf(ctx: *Context) !void {...@@ -133,23 +165,16 @@ fn constructLinkerArgsElf(ctx: *Context) !void {
133 // soname = buf_sprintf("lib%s.so.%" ZIG_PRI_usize "", buf_ptr(g->root_out_name), g->version_major);165 // soname = buf_sprintf("lib%s.so.%" ZIG_PRI_usize "", buf_ptr(g->root_out_name), g->version_major);
134 //}166 //}
135167
136 //lj->args.append("-o");168 try ctx.args.append(c"-o");
137 //lj->args.append(buf_ptr(&lj->out_file));169 try ctx.args.append(ctx.out_file_path.ptr());
138170
139 //if (lj->link_in_crt) {171 if (ctx.link_in_crt) {
140 // const char *crt1o;172 const crt1o = if (ctx.comp.is_static) "crt1.o" else "Scrt1.o";
141 // const char *crtbegino;173 const crtbegino = if (ctx.comp.is_static) "crtbeginT.o" else "crtbegin.o";
142 // if (g->is_static) {174 try addPathJoin(ctx, ctx.libc.lib_dir.?, crt1o);
143 // crt1o = "crt1.o";175 try addPathJoin(ctx, ctx.libc.lib_dir.?, "crti.o");
144 // crtbegino = "crtbeginT.o";176 try addPathJoin(ctx, ctx.libc.static_lib_dir.?, crtbegino);
145 // } else {177 }
146 // crt1o = "Scrt1.o";
147 // crtbegino = "crtbegin.o";
148 // }
149 // lj->args.append(get_libc_file(g, crt1o));
150 // lj->args.append(get_libc_file(g, "crti.o"));
151 // lj->args.append(get_libc_static_file(g, crtbegino));
152 //}
153178
154 //for (size_t i = 0; i < g->rpath_list.length; i += 1) {179 //for (size_t i = 0; i < g->rpath_list.length; i += 1) {
155 // Buf *rpath = g->rpath_list.at(i);180 // Buf *rpath = g->rpath_list.at(i);
...@@ -182,25 +207,23 @@ fn constructLinkerArgsElf(ctx: *Context) !void {...@@ -182,25 +207,23 @@ fn constructLinkerArgsElf(ctx: *Context) !void {
182 // lj->args.append(lib_dir);207 // lj->args.append(lib_dir);
183 //}208 //}
184209
185 //if (g->libc_link_lib != nullptr) {210 if (ctx.comp.haveLibC()) {
186 // lj->args.append("-L");211 try ctx.args.append(c"-L");
187 // lj->args.append(buf_ptr(g->libc_lib_dir));212 try ctx.args.append((try std.cstr.addNullByte(&ctx.arena.allocator, ctx.libc.lib_dir.?)).ptr);
188213
189 // lj->args.append("-L");214 try ctx.args.append(c"-L");
190 // lj->args.append(buf_ptr(g->libc_static_lib_dir));215 try ctx.args.append((try std.cstr.addNullByte(&ctx.arena.allocator, ctx.libc.static_lib_dir.?)).ptr);
191 //}216
192217 if (!ctx.comp.is_static) {
193 //if (!g->is_static) {218 const dl = blk: {
194 // if (g->dynamic_linker != nullptr) {219 if (ctx.libc.dynamic_linker_path) |dl| break :blk dl;
195 // assert(buf_len(g->dynamic_linker) != 0);220 if (ctx.comp.target.getDynamicLinkerPath()) |dl| break :blk dl;
196 // lj->args.append("-dynamic-linker");221 return error.LibCMissingDynamicLinker;
197 // lj->args.append(buf_ptr(g->dynamic_linker));222 };
198 // } else {223 try ctx.args.append(c"-dynamic-linker");
199 // Buf *resolved_dynamic_linker = get_dynamic_linker_path(g);224 try ctx.args.append((try std.cstr.addNullByte(&ctx.arena.allocator, dl)).ptr);
200 // lj->args.append("-dynamic-linker");225 }
201 // lj->args.append(buf_ptr(resolved_dynamic_linker));226 }
202 // }
203 //}
204227
205 //if (shared) {228 //if (shared) {
206 // lj->args.append("-soname");229 // lj->args.append("-soname");
...@@ -241,45 +264,51 @@ fn constructLinkerArgsElf(ctx: *Context) !void {...@@ -241,45 +264,51 @@ fn constructLinkerArgsElf(ctx: *Context) !void {
241 // lj->args.append(buf_ptr(arg));264 // lj->args.append(buf_ptr(arg));
242 //}265 //}
243266
244 //// libc dep267 // libc dep
245 //if (g->libc_link_lib != nullptr) {268 if (ctx.comp.haveLibC()) {
246 // if (g->is_static) {269 if (ctx.comp.is_static) {
247 // lj->args.append("--start-group");270 try ctx.args.append(c"--start-group");
248 // lj->args.append("-lgcc");271 try ctx.args.append(c"-lgcc");
249 // lj->args.append("-lgcc_eh");272 try ctx.args.append(c"-lgcc_eh");
250 // lj->args.append("-lc");273 try ctx.args.append(c"-lc");
251 // lj->args.append("-lm");274 try ctx.args.append(c"-lm");
252 // lj->args.append("--end-group");275 try ctx.args.append(c"--end-group");
253 // } else {276 } else {
254 // lj->args.append("-lgcc");277 try ctx.args.append(c"-lgcc");
255 // lj->args.append("--as-needed");278 try ctx.args.append(c"--as-needed");
256 // lj->args.append("-lgcc_s");279 try ctx.args.append(c"-lgcc_s");
257 // lj->args.append("--no-as-needed");280 try ctx.args.append(c"--no-as-needed");
258 // lj->args.append("-lc");281 try ctx.args.append(c"-lc");
259 // lj->args.append("-lm");282 try ctx.args.append(c"-lm");
260 // lj->args.append("-lgcc");283 try ctx.args.append(c"-lgcc");
261 // lj->args.append("--as-needed");284 try ctx.args.append(c"--as-needed");
262 // lj->args.append("-lgcc_s");285 try ctx.args.append(c"-lgcc_s");
263 // lj->args.append("--no-as-needed");286 try ctx.args.append(c"--no-as-needed");
264 // }287 }
265 //}288 }
266289
267 //// crt end290 // crt end
268 //if (lj->link_in_crt) {291 if (ctx.link_in_crt) {
269 // lj->args.append(get_libc_static_file(g, "crtend.o"));292 try addPathJoin(ctx, ctx.libc.static_lib_dir.?, "crtend.o");
270 // lj->args.append(get_libc_file(g, "crtn.o"));293 try addPathJoin(ctx, ctx.libc.lib_dir.?, "crtn.o");
271 //}294 }
272295
273 //if (!g->is_native_target) {296 if (ctx.comp.target != Target.Native) {
274 // lj->args.append("--allow-shlib-undefined");297 try ctx.args.append(c"--allow-shlib-undefined");
275 //}298 }
276299
277 //if (g->zig_target.os == OsZen) {300 if (ctx.comp.target.getOs() == builtin.Os.zen) {
278 // lj->args.append("-e");301 try ctx.args.append(c"-e");
279 // lj->args.append("_start");302 try ctx.args.append(c"_start");
280303
281 // lj->args.append("--image-base=0x10000000");304 try ctx.args.append(c"--image-base=0x10000000");
282 //}305 }
306}
307
308fn addPathJoin(ctx: *Context, dirname: []const u8, basename: []const u8) !void {
309 const full_path = try std.os.path.join(&ctx.arena.allocator, dirname, basename);
310 const full_path_with_null = try std.cstr.addNullByte(&ctx.arena.allocator, full_path);
311 try ctx.args.append(full_path_with_null.ptr);
283}312}
284313
285fn constructLinkerArgsCoff(ctx: *Context) void {314fn constructLinkerArgsCoff(ctx: *Context) void {
src-self-hosted/main.zig+53-34
...@@ -18,6 +18,7 @@ const EventLoopLocal = @import("compilation.zig").EventLoopLocal;...@@ -18,6 +18,7 @@ const EventLoopLocal = @import("compilation.zig").EventLoopLocal;
18const Compilation = @import("compilation.zig").Compilation;18const Compilation = @import("compilation.zig").Compilation;
19const Target = @import("target.zig").Target;19const Target = @import("target.zig").Target;
20const errmsg = @import("errmsg.zig");20const errmsg = @import("errmsg.zig");
21const LibCInstallation = @import("libc_installation.zig").LibCInstallation;
2122
22var stderr_file: os.File = undefined;23var stderr_file: os.File = undefined;
23var stderr: *io.OutStream(io.FileOutStream.Error) = undefined;24var stderr: *io.OutStream(io.FileOutStream.Error) = undefined;
...@@ -28,14 +29,14 @@ const usage =...@@ -28,14 +29,14 @@ const usage =
28 \\29 \\
29 \\Commands:30 \\Commands:
30 \\31 \\
31 \\ build-exe [source] Create executable from source or object files32 \\ build-exe [source] Create executable from source or object files
32 \\ build-lib [source] Create library from source or object files33 \\ build-lib [source] Create library from source or object files
33 \\ build-obj [source] Create object from source or assembly34 \\ build-obj [source] Create object from source or assembly
34 \\ find-libc Show native libc installation paths35 \\ fmt [source] Parse file and render in canonical zig format
35 \\ fmt [source] Parse file and render in canonical zig format36 \\ libc [paths_file] Display native libc paths file or validate one
36 \\ targets List available compilation targets37 \\ targets List available compilation targets
37 \\ version Print version number and exit38 \\ version Print version number and exit
38 \\ zen Print zen of zig and exit39 \\ zen Print zen of zig and exit
39 \\40 \\
40 \\41 \\
41;42;
...@@ -82,14 +83,14 @@ pub fn main() !void {...@@ -82,14 +83,14 @@ pub fn main() !void {
82 .name = "build-obj",83 .name = "build-obj",
83 .exec = cmdBuildObj,84 .exec = cmdBuildObj,
84 },85 },
85 Command{
86 .name = "find-libc",
87 .exec = cmdFindLibc,
88 },
89 Command{86 Command{
90 .name = "fmt",87 .name = "fmt",
91 .exec = cmdFmt,88 .exec = cmdFmt,
92 },89 },
90 Command{
91 .name = "libc",
92 .exec = cmdLibC,
93 },
93 Command{94 Command{
94 .name = "targets",95 .name = "targets",
95 .exec = cmdTargets,96 .exec = cmdTargets,
...@@ -135,6 +136,7 @@ const usage_build_generic =...@@ -135,6 +136,7 @@ const usage_build_generic =
135 \\ --color [auto|off|on] Enable or disable colored error messages136 \\ --color [auto|off|on] Enable or disable colored error messages
136 \\137 \\
137 \\Compile Options:138 \\Compile Options:
139 \\ --libc [file] Provide a file which specifies libc paths
138 \\ --assembly [source] Add assembly file to build140 \\ --assembly [source] Add assembly file to build
139 \\ --cache-dir [path] Override the cache directory141 \\ --cache-dir [path] Override the cache directory
140 \\ --emit [filetype] Emit a specific file format as compilation output142 \\ --emit [filetype] Emit a specific file format as compilation output
...@@ -167,7 +169,6 @@ const usage_build_generic =...@@ -167,7 +169,6 @@ const usage_build_generic =
167 \\169 \\
168 \\Link Options:170 \\Link Options:
169 \\ --ar-path [path] Set the path to ar171 \\ --ar-path [path] Set the path to ar
170 \\ --dynamic-linker [path] Set the path to ld.so
171 \\ --each-lib-rpath Add rpath for each used dynamic library172 \\ --each-lib-rpath Add rpath for each used dynamic library
172 \\ --library [lib] Link against lib173 \\ --library [lib] Link against lib
173 \\ --forbid-library [lib] Make it an error to link against lib174 \\ --forbid-library [lib] Make it an error to link against lib
...@@ -210,6 +211,7 @@ const args_build_generic = []Flag{...@@ -210,6 +211,7 @@ const args_build_generic = []Flag{
210 "llvm-ir",211 "llvm-ir",
211 }),212 }),
212 Flag.Bool("--enable-timing-info"),213 Flag.Bool("--enable-timing-info"),
214 Flag.Arg1("--libc"),
213 Flag.Arg1("--name"),215 Flag.Arg1("--name"),
214 Flag.Arg1("--output"),216 Flag.Arg1("--output"),
215 Flag.Arg1("--output-h"),217 Flag.Arg1("--output-h"),
...@@ -233,7 +235,6 @@ const args_build_generic = []Flag{...@@ -233,7 +235,6 @@ const args_build_generic = []Flag{
233 Flag.Arg1("-mllvm"),235 Flag.Arg1("-mllvm"),
234236
235 Flag.Arg1("--ar-path"),237 Flag.Arg1("--ar-path"),
236 Flag.Arg1("--dynamic-linker"),
237 Flag.Bool("--each-lib-rpath"),238 Flag.Bool("--each-lib-rpath"),
238 Flag.ArgMergeN("--library", 1),239 Flag.ArgMergeN("--library", 1),
239 Flag.ArgMergeN("--forbid-library", 1),240 Flag.ArgMergeN("--forbid-library", 1),
...@@ -382,6 +383,8 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co...@@ -382,6 +383,8 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co
382 const zig_lib_dir = introspect.resolveZigLibDir(allocator) catch os.exit(1);383 const zig_lib_dir = introspect.resolveZigLibDir(allocator) catch os.exit(1);
383 defer allocator.free(zig_lib_dir);384 defer allocator.free(zig_lib_dir);
384385
386 var override_libc: LibCInstallation = undefined;
387
385 var loop: event.Loop = undefined;388 var loop: event.Loop = undefined;
386 try loop.initMultiThreaded(allocator);389 try loop.initMultiThreaded(allocator);
387 defer loop.deinit();390 defer loop.deinit();
...@@ -402,6 +405,15 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co...@@ -402,6 +405,15 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co
402 );405 );
403 defer comp.destroy();406 defer comp.destroy();
404407
408 if (flags.single("libc")) |libc_path| {
409 parseLibcPaths(loop.allocator, &override_libc, libc_path);
410 comp.override_libc = &override_libc;
411 }
412
413 for (flags.many("library")) |lib| {
414 _ = try comp.addLinkLib(lib, true);
415 }
416
405 comp.version_major = try std.fmt.parseUnsigned(u32, flags.single("ver-major") orelse "0", 10);417 comp.version_major = try std.fmt.parseUnsigned(u32, flags.single("ver-major") orelse "0", 10);
406 comp.version_minor = try std.fmt.parseUnsigned(u32, flags.single("ver-minor") orelse "0", 10);418 comp.version_minor = try std.fmt.parseUnsigned(u32, flags.single("ver-minor") orelse "0", 10);
407 comp.version_patch = try std.fmt.parseUnsigned(u32, flags.single("ver-patch") orelse "0", 10);419 comp.version_patch = try std.fmt.parseUnsigned(u32, flags.single("ver-patch") orelse "0", 10);
...@@ -425,10 +437,6 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co...@@ -425,10 +437,6 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co
425437
426 comp.strip = flags.present("strip");438 comp.strip = flags.present("strip");
427439
428 if (flags.single("dynamic-linker")) |dynamic_linker| {
429 comp.dynamic_linker = dynamic_linker;
430 }
431
432 comp.verbose_tokenize = flags.present("verbose-tokenize");440 comp.verbose_tokenize = flags.present("verbose-tokenize");
433 comp.verbose_ast_tree = flags.present("verbose-ast-tree");441 comp.verbose_ast_tree = flags.present("verbose-ast-tree");
434 comp.verbose_ast_fmt = flags.present("verbose-ast-fmt");442 comp.verbose_ast_fmt = flags.present("verbose-ast-fmt");
...@@ -479,7 +487,6 @@ async fn processBuildEvents(comp: *Compilation, color: errmsg.Color) void {...@@ -479,7 +487,6 @@ async fn processBuildEvents(comp: *Compilation, color: errmsg.Color) void {
479487
480 switch (build_event) {488 switch (build_event) {
481 Compilation.Event.Ok => {489 Compilation.Event.Ok => {
482 std.debug.warn("Build succeeded\n");
483 return;490 return;
484 },491 },
485 Compilation.Event.Error => |err| {492 Compilation.Event.Error => |err| {
...@@ -559,7 +566,32 @@ const Fmt = struct {...@@ -559,7 +566,32 @@ const Fmt = struct {
559 }566 }
560};567};
561568
562fn cmdFindLibc(allocator: *Allocator, args: []const []const u8) !void {569fn parseLibcPaths(allocator: *Allocator, libc: *LibCInstallation, libc_paths_file: []const u8) void {
570 libc.parse(allocator, libc_paths_file, stderr) catch |err| {
571 stderr.print(
572 "Unable to parse libc path file '{}': {}.\n" ++
573 "Try running `zig libc` to see an example for the native target.\n",
574 libc_paths_file,
575 @errorName(err),
576 ) catch os.exit(1);
577 os.exit(1);
578 };
579}
580
581fn cmdLibC(allocator: *Allocator, args: []const []const u8) !void {
582 switch (args.len) {
583 0 => {},
584 1 => {
585 var libc_installation: LibCInstallation = undefined;
586 parseLibcPaths(allocator, &libc_installation, args[0]);
587 return;
588 },
589 else => {
590 try stderr.print("unexpected extra parameter: {}\n", args[1]);
591 os.exit(1);
592 },
593 }
594
563 var loop: event.Loop = undefined;595 var loop: event.Loop = undefined;
564 try loop.initMultiThreaded(allocator);596 try loop.initMultiThreaded(allocator);
565 defer loop.deinit();597 defer loop.deinit();
...@@ -578,20 +610,7 @@ async fn findLibCAsync(event_loop_local: *EventLoopLocal) void {...@@ -578,20 +610,7 @@ async fn findLibCAsync(event_loop_local: *EventLoopLocal) void {
578 stderr.print("unable to find libc: {}\n", @errorName(err)) catch os.exit(1);610 stderr.print("unable to find libc: {}\n", @errorName(err)) catch os.exit(1);
579 os.exit(1);611 os.exit(1);
580 };612 };
581 stderr.print(613 libc.render(stdout) catch os.exit(1);
582 \\include_dir={}
583 \\lib_dir={}
584 \\static_lib_dir={}
585 \\msvc_lib_dir={}
586 \\kernel32_lib_dir={}
587 \\
588 ,
589 libc.include_dir,
590 libc.lib_dir,
591 libc.static_lib_dir orelse "",
592 libc.msvc_lib_dir orelse "",
593 libc.kernel32_lib_dir orelse "",
594 ) catch os.exit(1);
595}614}
596615
597fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void {616fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void {
src-self-hosted/target.zig+315-1
...@@ -2,6 +2,12 @@ const std = @import("std");...@@ -2,6 +2,12 @@ const std = @import("std");
2const builtin = @import("builtin");2const builtin = @import("builtin");
3const llvm = @import("llvm.zig");3const llvm = @import("llvm.zig");
44
5pub const FloatAbi = enum {
6 Hard,
7 Soft,
8 SoftFp,
9};
10
5pub const Target = union(enum) {11pub const Target = union(enum) {
6 Native,12 Native,
7 Cross: Cross,13 Cross: Cross,
...@@ -13,7 +19,7 @@ pub const Target = union(enum) {...@@ -13,7 +19,7 @@ pub const Target = union(enum) {
13 object_format: builtin.ObjectFormat,19 object_format: builtin.ObjectFormat,
14 };20 };
1521
16 pub fn oFileExt(self: Target) []const u8 {22 pub fn objFileExt(self: Target) []const u8 {
17 return switch (self.getObjectFormat()) {23 return switch (self.getObjectFormat()) {
18 builtin.ObjectFormat.coff => ".obj",24 builtin.ObjectFormat.coff => ".obj",
19 else => ".o",25 else => ".o",
...@@ -27,6 +33,13 @@ pub const Target = union(enum) {...@@ -27,6 +33,13 @@ pub const Target = union(enum) {
27 };33 };
28 }34 }
2935
36 pub fn libFileExt(self: Target, is_static: bool) []const u8 {
37 return switch (self.getOs()) {
38 builtin.Os.windows => if (is_static) ".lib" else ".dll",
39 else => if (is_static) ".a" else ".so",
40 };
41 }
42
30 pub fn getOs(self: Target) builtin.Os {43 pub fn getOs(self: Target) builtin.Os {
31 return switch (self) {44 return switch (self) {
32 Target.Native => builtin.os,45 Target.Native => builtin.os,
...@@ -76,6 +89,56 @@ pub const Target = union(enum) {...@@ -76,6 +89,56 @@ pub const Target = union(enum) {
76 };89 };
77 }90 }
7891
92 /// TODO expose the arch and subarch separately
93 pub fn isArmOrThumb(self: Target) bool {
94 return switch (self.getArch()) {
95 builtin.Arch.armv8_3a,
96 builtin.Arch.armv8_2a,
97 builtin.Arch.armv8_1a,
98 builtin.Arch.armv8,
99 builtin.Arch.armv8r,
100 builtin.Arch.armv8m_baseline,
101 builtin.Arch.armv8m_mainline,
102 builtin.Arch.armv7,
103 builtin.Arch.armv7em,
104 builtin.Arch.armv7m,
105 builtin.Arch.armv7s,
106 builtin.Arch.armv7k,
107 builtin.Arch.armv7ve,
108 builtin.Arch.armv6,
109 builtin.Arch.armv6m,
110 builtin.Arch.armv6k,
111 builtin.Arch.armv6t2,
112 builtin.Arch.armv5,
113 builtin.Arch.armv5te,
114 builtin.Arch.armv4t,
115 builtin.Arch.armebv8_3a,
116 builtin.Arch.armebv8_2a,
117 builtin.Arch.armebv8_1a,
118 builtin.Arch.armebv8,
119 builtin.Arch.armebv8r,
120 builtin.Arch.armebv8m_baseline,
121 builtin.Arch.armebv8m_mainline,
122 builtin.Arch.armebv7,
123 builtin.Arch.armebv7em,
124 builtin.Arch.armebv7m,
125 builtin.Arch.armebv7s,
126 builtin.Arch.armebv7k,
127 builtin.Arch.armebv7ve,
128 builtin.Arch.armebv6,
129 builtin.Arch.armebv6m,
130 builtin.Arch.armebv6k,
131 builtin.Arch.armebv6t2,
132 builtin.Arch.armebv5,
133 builtin.Arch.armebv5te,
134 builtin.Arch.armebv4t,
135 builtin.Arch.thumb,
136 builtin.Arch.thumbeb,
137 => true,
138 else => false,
139 };
140 }
141
79 pub fn initializeAll() void {142 pub fn initializeAll() void {
80 llvm.InitializeAllTargets();143 llvm.InitializeAllTargets();
81 llvm.InitializeAllTargetInfos();144 llvm.InitializeAllTargetInfos();
...@@ -106,6 +169,257 @@ pub const Target = union(enum) {...@@ -106,6 +169,257 @@ pub const Target = union(enum) {
106 return result;169 return result;
107 }170 }
108171
172 pub fn is64bit(self: Target) bool {
173 return self.getArchPtrBitWidth() == 64;
174 }
175
176 pub fn getArchPtrBitWidth(self: Target) u8 {
177 switch (self.getArch()) {
178 builtin.Arch.avr,
179 builtin.Arch.msp430,
180 => return 16,
181
182 builtin.Arch.arc,
183 builtin.Arch.armv8_3a,
184 builtin.Arch.armv8_2a,
185 builtin.Arch.armv8_1a,
186 builtin.Arch.armv8,
187 builtin.Arch.armv8r,
188 builtin.Arch.armv8m_baseline,
189 builtin.Arch.armv8m_mainline,
190 builtin.Arch.armv7,
191 builtin.Arch.armv7em,
192 builtin.Arch.armv7m,
193 builtin.Arch.armv7s,
194 builtin.Arch.armv7k,
195 builtin.Arch.armv7ve,
196 builtin.Arch.armv6,
197 builtin.Arch.armv6m,
198 builtin.Arch.armv6k,
199 builtin.Arch.armv6t2,
200 builtin.Arch.armv5,
201 builtin.Arch.armv5te,
202 builtin.Arch.armv4t,
203 builtin.Arch.armebv8_3a,
204 builtin.Arch.armebv8_2a,
205 builtin.Arch.armebv8_1a,
206 builtin.Arch.armebv8,
207 builtin.Arch.armebv8r,
208 builtin.Arch.armebv8m_baseline,
209 builtin.Arch.armebv8m_mainline,
210 builtin.Arch.armebv7,
211 builtin.Arch.armebv7em,
212 builtin.Arch.armebv7m,
213 builtin.Arch.armebv7s,
214 builtin.Arch.armebv7k,
215 builtin.Arch.armebv7ve,
216 builtin.Arch.armebv6,
217 builtin.Arch.armebv6m,
218 builtin.Arch.armebv6k,
219 builtin.Arch.armebv6t2,
220 builtin.Arch.armebv5,
221 builtin.Arch.armebv5te,
222 builtin.Arch.armebv4t,
223 builtin.Arch.hexagon,
224 builtin.Arch.le32,
225 builtin.Arch.mips,
226 builtin.Arch.mipsel,
227 builtin.Arch.nios2,
228 builtin.Arch.powerpc,
229 builtin.Arch.r600,
230 builtin.Arch.riscv32,
231 builtin.Arch.sparc,
232 builtin.Arch.sparcel,
233 builtin.Arch.tce,
234 builtin.Arch.tcele,
235 builtin.Arch.thumb,
236 builtin.Arch.thumbeb,
237 builtin.Arch.i386,
238 builtin.Arch.xcore,
239 builtin.Arch.nvptx,
240 builtin.Arch.amdil,
241 builtin.Arch.hsail,
242 builtin.Arch.spir,
243 builtin.Arch.kalimbav3,
244 builtin.Arch.kalimbav4,
245 builtin.Arch.kalimbav5,
246 builtin.Arch.shave,
247 builtin.Arch.lanai,
248 builtin.Arch.wasm32,
249 builtin.Arch.renderscript32,
250 => return 32,
251
252 builtin.Arch.aarch64,
253 builtin.Arch.aarch64_be,
254 builtin.Arch.mips64,
255 builtin.Arch.mips64el,
256 builtin.Arch.powerpc64,
257 builtin.Arch.powerpc64le,
258 builtin.Arch.riscv64,
259 builtin.Arch.x86_64,
260 builtin.Arch.nvptx64,
261 builtin.Arch.le64,
262 builtin.Arch.amdil64,
263 builtin.Arch.hsail64,
264 builtin.Arch.spir64,
265 builtin.Arch.wasm64,
266 builtin.Arch.renderscript64,
267 builtin.Arch.amdgcn,
268 builtin.Arch.bpfel,
269 builtin.Arch.bpfeb,
270 builtin.Arch.sparcv9,
271 builtin.Arch.s390x,
272 => return 64,
273 }
274 }
275
276 pub fn getFloatAbi(self: Target) FloatAbi {
277 return switch (self.getEnviron()) {
278 builtin.Environ.gnueabihf,
279 builtin.Environ.eabihf,
280 builtin.Environ.musleabihf,
281 => FloatAbi.Hard,
282 else => FloatAbi.Soft,
283 };
284 }
285
286 pub fn getDynamicLinkerPath(self: Target) ?[]const u8 {
287 const env = self.getEnviron();
288 const arch = self.getArch();
289 switch (env) {
290 builtin.Environ.android => {
291 if (self.is64bit()) {
292 return "/system/bin/linker64";
293 } else {
294 return "/system/bin/linker";
295 }
296 },
297 builtin.Environ.gnux32 => {
298 if (arch == builtin.Arch.x86_64) {
299 return "/libx32/ld-linux-x32.so.2";
300 }
301 },
302 builtin.Environ.musl,
303 builtin.Environ.musleabi,
304 builtin.Environ.musleabihf,
305 => {
306 if (arch == builtin.Arch.x86_64) {
307 return "/lib/ld-musl-x86_64.so.1";
308 }
309 },
310 else => {},
311 }
312 switch (arch) {
313 builtin.Arch.i386,
314 builtin.Arch.sparc,
315 builtin.Arch.sparcel,
316 => return "/lib/ld-linux.so.2",
317
318 builtin.Arch.aarch64 => return "/lib/ld-linux-aarch64.so.1",
319 builtin.Arch.aarch64_be => return "/lib/ld-linux-aarch64_be.so.1",
320
321 builtin.Arch.armv8_3a,
322 builtin.Arch.armv8_2a,
323 builtin.Arch.armv8_1a,
324 builtin.Arch.armv8,
325 builtin.Arch.armv8r,
326 builtin.Arch.armv8m_baseline,
327 builtin.Arch.armv8m_mainline,
328 builtin.Arch.armv7,
329 builtin.Arch.armv7em,
330 builtin.Arch.armv7m,
331 builtin.Arch.armv7s,
332 builtin.Arch.armv7k,
333 builtin.Arch.armv7ve,
334 builtin.Arch.armv6,
335 builtin.Arch.armv6m,
336 builtin.Arch.armv6k,
337 builtin.Arch.armv6t2,
338 builtin.Arch.armv5,
339 builtin.Arch.armv5te,
340 builtin.Arch.armv4t,
341 builtin.Arch.thumb,
342 => return switch (self.getFloatAbi()) {
343 FloatAbi.Hard => return "/lib/ld-linux-armhf.so.3",
344 else => return "/lib/ld-linux.so.3",
345 },
346
347 builtin.Arch.armebv8_3a,
348 builtin.Arch.armebv8_2a,
349 builtin.Arch.armebv8_1a,
350 builtin.Arch.armebv8,
351 builtin.Arch.armebv8r,
352 builtin.Arch.armebv8m_baseline,
353 builtin.Arch.armebv8m_mainline,
354 builtin.Arch.armebv7,
355 builtin.Arch.armebv7em,
356 builtin.Arch.armebv7m,
357 builtin.Arch.armebv7s,
358 builtin.Arch.armebv7k,
359 builtin.Arch.armebv7ve,
360 builtin.Arch.armebv6,
361 builtin.Arch.armebv6m,
362 builtin.Arch.armebv6k,
363 builtin.Arch.armebv6t2,
364 builtin.Arch.armebv5,
365 builtin.Arch.armebv5te,
366 builtin.Arch.armebv4t,
367 builtin.Arch.thumbeb,
368 => return switch (self.getFloatAbi()) {
369 FloatAbi.Hard => return "/lib/ld-linux-armhf.so.3",
370 else => return "/lib/ld-linux.so.3",
371 },
372
373 builtin.Arch.mips,
374 builtin.Arch.mipsel,
375 builtin.Arch.mips64,
376 builtin.Arch.mips64el,
377 => return null,
378
379 builtin.Arch.powerpc => return "/lib/ld.so.1",
380 builtin.Arch.powerpc64 => return "/lib64/ld64.so.2",
381 builtin.Arch.powerpc64le => return "/lib64/ld64.so.2",
382 builtin.Arch.s390x => return "/lib64/ld64.so.1",
383 builtin.Arch.sparcv9 => return "/lib64/ld-linux.so.2",
384 builtin.Arch.x86_64 => return "/lib64/ld-linux-x86-64.so.2",
385
386 builtin.Arch.arc,
387 builtin.Arch.avr,
388 builtin.Arch.bpfel,
389 builtin.Arch.bpfeb,
390 builtin.Arch.hexagon,
391 builtin.Arch.msp430,
392 builtin.Arch.nios2,
393 builtin.Arch.r600,
394 builtin.Arch.amdgcn,
395 builtin.Arch.riscv32,
396 builtin.Arch.riscv64,
397 builtin.Arch.tce,
398 builtin.Arch.tcele,
399 builtin.Arch.xcore,
400 builtin.Arch.nvptx,
401 builtin.Arch.nvptx64,
402 builtin.Arch.le32,
403 builtin.Arch.le64,
404 builtin.Arch.amdil,
405 builtin.Arch.amdil64,
406 builtin.Arch.hsail,
407 builtin.Arch.hsail64,
408 builtin.Arch.spir,
409 builtin.Arch.spir64,
410 builtin.Arch.kalimbav3,
411 builtin.Arch.kalimbav4,
412 builtin.Arch.kalimbav5,
413 builtin.Arch.shave,
414 builtin.Arch.lanai,
415 builtin.Arch.wasm32,
416 builtin.Arch.wasm64,
417 builtin.Arch.renderscript32,
418 builtin.Arch.renderscript64,
419 => return null,
420 }
421 }
422
109 pub fn llvmTargetFromTriple(triple: std.Buffer) !llvm.TargetRef {423 pub fn llvmTargetFromTriple(triple: std.Buffer) !llvm.TargetRef {
110 var result: llvm.TargetRef = undefined;424 var result: llvm.TargetRef = undefined;
111 var err_msg: [*]u8 = undefined;425 var err_msg: [*]u8 = undefined;
std/event/group.zig+2-2
...@@ -6,7 +6,7 @@ const AtomicRmwOp = builtin.AtomicRmwOp;...@@ -6,7 +6,7 @@ const AtomicRmwOp = builtin.AtomicRmwOp;
6const AtomicOrder = builtin.AtomicOrder;6const AtomicOrder = builtin.AtomicOrder;
7const assert = std.debug.assert;7const assert = std.debug.assert;
88
9/// ReturnType should be `void` or `E!void`9/// ReturnType must be `void` or `E!void`
10pub fn Group(comptime ReturnType: type) type {10pub fn Group(comptime ReturnType: type) type {
11 return struct {11 return struct {
12 coro_stack: Stack,12 coro_stack: Stack,
...@@ -39,7 +39,7 @@ pub fn Group(comptime ReturnType: type) type {...@@ -39,7 +39,7 @@ pub fn Group(comptime ReturnType: type) type {
39 }39 }
4040
41 /// This is equivalent to an async call, but the async function is added to the group, instead41 /// This is equivalent to an async call, but the async function is added to the group, instead
42 /// of returning a promise. func must be async and have return type void.42 /// of returning a promise. func must be async and have return type ReturnType.
43 /// Thread-safe.43 /// Thread-safe.
44 pub fn call(self: *Self, comptime func: var, args: ...) (error{OutOfMemory}!void) {44 pub fn call(self: *Self, comptime func: var, args: ...) (error{OutOfMemory}!void) {
45 const S = struct {45 const S = struct {
std/event/loop.zig+1-1
...@@ -444,7 +444,7 @@ pub const Loop = struct {...@@ -444,7 +444,7 @@ pub const Loop = struct {
444 .next = undefined,444 .next = undefined,
445 .data = p,445 .data = p,
446 };446 };
447 loop.onNextTick(&my_tick_node);447 self.onNextTick(&my_tick_node);
448 }448 }
449 }449 }
450450