| author | |
| committer | |
| log | aa3b41247f297b4fd8b3bdb7920cb479f5aa004b |
| tree | 3e8bc66c275175cabe3f0a6fb6b8febd2c34c8bd |
| parent | 3e4a3fa5b7faadaae0a57088baa392e2bb52fe38 |
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()); |
| 17 | 17 | ||
| 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(); |
| 20 | 20 | ||
| 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 { |
| 120 | 120 | ||
| 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, |
| 125 | 124 | ||
| 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, |
| 203 | 202 | ||
| 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); |
| 205 | 211 | ||
| 206 | // TODO handle some of these earlier and report them in a way other than error codes | 212 | // 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 | }; |
| 250 | 258 | ||
| 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, |
| 325 | 333 | ||
| 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)), |
| 355 | 363 | ||
| 356 | .meta_type = undefined, | 364 | .meta_type = undefined, |
| ... | @@ -368,6 +376,9 @@ pub const Compilation = struct { | ... | @@ -368,6 +376,9 @@ pub const Compilation = struct { |
| 368 | 376 | ||
| 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 | } |
| 432 | 443 | ||
| 433 | try comp.initTypes(); | 444 | try comp.initTypes(); |
| 445 | errdefer comp.derefTypes(); | ||
| 446 | |||
| 447 | comp.destroy_handle = try async<loop.allocator> comp.internalDeinit(); | ||
| 434 | 448 | ||
| 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 | } |
| 528 | 542 | ||
| 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(); | ||
| 541 | 562 | ||
| 542 | self.events.destroy(); | 563 | self.events.destroy(); |
| 543 | 564 | ||
| ... | @@ -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 | } |
| 551 | 572 | ||
| 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 | }; |
| 681 | 706 | ||
| 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 | } |
| 686 | 711 | ||
| ... | @@ -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; |
| 766 | 791 | ||
| 767 | // get a head start on looking for the native libc | 792 | // 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 { |
| 774 | 799 | ||
| 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 resolution | 803 | // 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 | } |
| 783 | 806 | ||
| 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 @@ |
| 1 | const std = @import("std"); | 1 | const std = @import("std"); |
| 2 | const builtin = @import("builtin"); | 2 | const builtin = @import("builtin"); |
| 3 | const event = std.event; | 3 | const event = std.event; |
| 4 | const Target = @import("target.zig").Target; | ||
| 4 | 5 | ||
| 6 | /// See the render function implementation for documentation of the fields. | ||
| 5 | pub const LibCInstallation = struct { | 7 | pub 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, | ||
| 27 | 14 | ||
| 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 | }; |
| 38 | 25 | ||
| 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 | } |
| 149 | 245 | ||
| 150 | async fn findNativeLibDirWindows(self: *LibCInstallation, loop: *event.Loop) Error!void { | 246 | async fn findNativeLibDirWindows(self: *LibCInstallation, loop: *event.Loop) FindError!void { |
| 151 | // TODO | 247 | // TODO |
| 152 | //ZigWindowsSDK *sdk = get_windows_sdk(g); | 248 | //ZigWindowsSDK *sdk = get_windows_sdk(g); |
| 153 | 249 | ||
| ... | @@ -180,31 +276,83 @@ pub const LibCInstallation = struct { | ... | @@ -180,31 +276,83 @@ pub const LibCInstallation = struct { |
| 180 | @panic("TODO"); | 276 | @panic("TODO"); |
| 181 | } | 277 | } |
| 182 | 278 | ||
| 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 | } |
| 186 | 311 | ||
| 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 | } |
| 190 | 326 | ||
| 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 | } |
| 194 | 330 | ||
| 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 | }; |
| 199 | 346 | ||
| 200 | /// caller owns returned memory | 347 | /// caller owns returned memory |
| 201 | async fn ccPrintFileNameDir(loop: *event.Loop, o_file: []const u8) ![]u8 { | 348 | async 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 }; |
| 206 | 353 | ||
| 207 | // TODO evented I/O | 354 | // 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; |
| 232 | 380 | ||
| 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"); |
| 3 | const builtin = @import("builtin"); | 3 | const builtin = @import("builtin"); |
| 4 | const ObjectFormat = builtin.ObjectFormat; | 4 | const ObjectFormat = builtin.ObjectFormat; |
| 5 | const Compilation = @import("compilation.zig").Compilation; | 5 | const Compilation = @import("compilation.zig").Compilation; |
| 6 | const Target = @import("target.zig").Target; | ||
| 7 | const LibCInstallation = @import("libc_installation.zig").LibCInstallation; | ||
| 6 | 8 | ||
| 7 | const Context = struct { | 9 | const Context = struct { |
| 8 | comp: *Compilation, | 10 | comp: *Compilation, |
| ... | @@ -12,9 +14,12 @@ const Context = struct { | ... | @@ -12,9 +14,12 @@ const Context = struct { |
| 12 | 14 | ||
| 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 | }; |
| 16 | 21 | ||
| 17 | pub fn link(comp: *Compilation) !void { | 22 | pub 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); |
| 29 | 36 | ||
| 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 first | 54 | // even though we're calling LLD as a library it thinks the first |
| 31 | // argument is its own exe name | 55 | // argument is its own exe name |
| 32 | try ctx.args.append(c"lld"); | 56 | try ctx.args.append(c"lld"); |
| 33 | 57 | ||
| 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); |
| 35 | 70 | ||
| 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 { |
| 43 | 78 | ||
| 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 the | 84 | // 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 | } |
| 96 | 132 | ||
| 97 | fn constructLinkerArgsElf(ctx: *Context) !void { | 133 | fn 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"); |
| 111 | 144 | ||
| 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"); |
| 128 | 160 | ||
| ... | @@ -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 | //} |
| 135 | 167 | ||
| 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()); |
| 138 | 170 | ||
| 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 | //} | ||
| 153 | 178 | ||
| 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 | //} |
| 184 | 209 | ||
| 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); |
| 188 | 213 | ||
| 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 | |
| 192 | 217 | 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 | //} | ||
| 204 | 227 | ||
| 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 | //} |
| 243 | 266 | ||
| 244 | //// libc dep | 267 | // 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 | } |
| 266 | 289 | ||
| 267 | //// crt end | 290 | // 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 | } |
| 272 | 295 | ||
| 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 | } |
| 276 | 299 | ||
| 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"); |
| 280 | 303 | ||
| 281 | // lj->args.append("--image-base=0x10000000"); | 304 | try ctx.args.append(c"--image-base=0x10000000"); |
| 282 | //} | 305 | } |
| 306 | } | ||
| 307 | |||
| 308 | fn 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 | } |
| 284 | 313 | ||
| 285 | fn constructLinkerArgsCoff(ctx: *Context) void { | 314 | fn 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; |
| 18 | const Compilation = @import("compilation.zig").Compilation; | 18 | const Compilation = @import("compilation.zig").Compilation; |
| 19 | const Target = @import("target.zig").Target; | 19 | const Target = @import("target.zig").Target; |
| 20 | const errmsg = @import("errmsg.zig"); | 20 | const errmsg = @import("errmsg.zig"); |
| 21 | const LibCInstallation = @import("libc_installation.zig").LibCInstallation; | ||
| 21 | 22 | ||
| 22 | var stderr_file: os.File = undefined; | 23 | var stderr_file: os.File = undefined; |
| 23 | var stderr: *io.OutStream(io.FileOutStream.Error) = undefined; | 24 | var 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 files | 32 | \\ build-exe [source] Create executable from source or object files |
| 32 | \\ build-lib [source] Create library from source or object files | 33 | \\ build-lib [source] Create library from source or object files |
| 33 | \\ build-obj [source] Create object from source or assembly | 34 | \\ build-obj [source] Create object from source or assembly |
| 34 | \\ find-libc Show native libc installation paths | 35 | \\ fmt [source] Parse file and render in canonical zig format |
| 35 | \\ fmt [source] Parse file and render in canonical zig format | 36 | \\ libc [paths_file] Display native libc paths file or validate one |
| 36 | \\ targets List available compilation targets | 37 | \\ targets List available compilation targets |
| 37 | \\ version Print version number and exit | 38 | \\ version Print version number and exit |
| 38 | \\ zen Print zen of zig and exit | 39 | \\ 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 messages | 136 | \\ --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 build | 140 | \\ --assembly [source] Add assembly file to build |
| 139 | \\ --cache-dir [path] Override the cache directory | 141 | \\ --cache-dir [path] Override the cache directory |
| 140 | \\ --emit [filetype] Emit a specific file format as compilation output | 142 | \\ --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 ar | 171 | \\ --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 library | 172 | \\ --each-lib-rpath Add rpath for each used dynamic library |
| 172 | \\ --library [lib] Link against lib | 173 | \\ --library [lib] Link against lib |
| 173 | \\ --forbid-library [lib] Make it an error to link against lib | 174 | \\ --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"), |
| 234 | 236 | ||
| 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); |
| 384 | 385 | ||
| 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(); |
| 404 | 407 | ||
| 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 |
| 425 | 437 | ||
| 426 | comp.strip = flags.present("strip"); | 438 | comp.strip = flags.present("strip"); |
| 427 | 439 | ||
| 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 { |
| 479 | 487 | ||
| 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 | }; |
| 561 | 568 | ||
| 562 | fn cmdFindLibc(allocator: *Allocator, args: []const []const u8) !void { | 569 | fn 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 | |||
| 581 | fn 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 | } |
| 596 | 615 | ||
| 597 | fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void { | 616 | fn 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"); |
| 2 | const builtin = @import("builtin"); | 2 | const builtin = @import("builtin"); |
| 3 | const llvm = @import("llvm.zig"); | 3 | const llvm = @import("llvm.zig"); |
| 4 | 4 | ||
| 5 | pub const FloatAbi = enum { | ||
| 6 | Hard, | ||
| 7 | Soft, | ||
| 8 | SoftFp, | ||
| 9 | }; | ||
| 10 | |||
| 5 | pub const Target = union(enum) { | 11 | pub 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 | }; |
| 15 | 21 | ||
| 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 | } |
| 29 | 35 | ||
| 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 | } |
| 78 | 91 | ||
| 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 | } |
| 108 | 171 | ||
| 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; |
| 6 | const AtomicOrder = builtin.AtomicOrder; | 6 | const AtomicOrder = builtin.AtomicOrder; |
| 7 | const assert = std.debug.assert; | 7 | const assert = std.debug.assert; |
| 8 | 8 | ||
| 9 | /// ReturnType should be `void` or `E!void` | 9 | /// ReturnType must be `void` or `E!void` |
| 10 | pub fn Group(comptime ReturnType: type) type { | 10 | pub 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 | } |
| 40 | 40 | ||
| 41 | /// This is equivalent to an async call, but the async function is added to the group, instead | 41 | /// 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 | } |
| 450 | 450 |