| 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 | 15 | defer fn_val.base.deref(comp); |
| 16 | 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 | 19 | errdefer output_path.deinit(); |
| 20 | 20 | |
| 21 | 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 | 120 | |
| 121 | 121 | linker_script: ?[]const u8, |
| 122 | 122 | cache_dir: []const u8, |
| 123 | dynamic_linker: ?[]const u8, | |
| 124 | 123 | out_h_path: ?[]const u8, |
| 125 | 124 | |
| 126 | 125 | is_test: bool, |
| ... | ... | @@ -201,6 +200,13 @@ pub const Compilation = struct { |
| 201 | 200 | root_package: *Package, |
| 202 | 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 | 210 | const CompileErrList = std.ArrayList(*errmsg.Msg); |
| 205 | 211 | |
| 206 | 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 | 252 | EnvironmentVariableNotFound, |
| 247 | 253 | AppDataDirUnavailable, |
| 248 | 254 | LinkFailed, |
| 255 | LibCRequiredButNotProvidedOrFound, | |
| 256 | LibCMissingDynamicLinker, | |
| 249 | 257 | }; |
| 250 | 258 | |
| 251 | 259 | pub const Event = union(enum) { |
| ... | ... | @@ -324,7 +332,6 @@ pub const Compilation = struct { |
| 324 | 332 | .verbose_link = false, |
| 325 | 333 | |
| 326 | 334 | .linker_script = null, |
| 327 | .dynamic_linker = null, | |
| 328 | 335 | .out_h_path = null, |
| 329 | 336 | .is_test = false, |
| 330 | 337 | .each_lib_rpath = false, |
| ... | ... | @@ -351,6 +358,7 @@ pub const Compilation = struct { |
| 351 | 358 | .link_out_file = null, |
| 352 | 359 | .exported_symbol_names = event.Locked(Decl.Table).init(loop, Decl.Table.init(loop.allocator)), |
| 353 | 360 | .prelink_group = event.Group(BuildError!void).init(loop), |
| 361 | .deinit_group = event.Group(void).init(loop), | |
| 354 | 362 | .compile_errors = event.Locked(CompileErrList).init(loop, CompileErrList.init(loop.allocator)), |
| 355 | 363 | |
| 356 | 364 | .meta_type = undefined, |
| ... | ... | @@ -368,6 +376,9 @@ pub const Compilation = struct { |
| 368 | 376 | |
| 369 | 377 | .root_package = undefined, |
| 370 | 378 | .std_package = undefined, |
| 379 | ||
| 380 | .override_libc = null, | |
| 381 | .destroy_handle = undefined, | |
| 371 | 382 | }); |
| 372 | 383 | errdefer { |
| 373 | 384 | comp.arena_allocator.deinit(); |
| ... | ... | @@ -431,6 +442,9 @@ pub const Compilation = struct { |
| 431 | 442 | } |
| 432 | 443 | |
| 433 | 444 | try comp.initTypes(); |
| 445 | errdefer comp.derefTypes(); | |
| 446 | ||
| 447 | comp.destroy_handle = try async<loop.allocator> comp.internalDeinit(); | |
| 434 | 448 | |
| 435 | 449 | return comp; |
| 436 | 450 | } |
| ... | ... | @@ -526,11 +540,7 @@ pub const Compilation = struct { |
| 526 | 540 | errdefer comp.gpa().destroy(comp.noreturn_value); |
| 527 | 541 | } |
| 528 | 542 | |
| 529 | pub fn destroy(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 | ||
| 543 | fn derefTypes(self: *Compilation) void { | |
| 534 | 544 | self.noreturn_value.base.deref(self); |
| 535 | 545 | self.void_value.base.deref(self); |
| 536 | 546 | self.false_value.base.deref(self); |
| ... | ... | @@ -538,6 +548,17 @@ pub const Compilation = struct { |
| 538 | 548 | self.noreturn_type.base.base.deref(self); |
| 539 | 549 | self.void_type.base.base.deref(self); |
| 540 | 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 | 563 | self.events.destroy(); |
| 543 | 564 | |
| ... | ... | @@ -549,6 +570,10 @@ pub const Compilation = struct { |
| 549 | 570 | self.gpa().destroy(self); |
| 550 | 571 | } |
| 551 | 572 | |
| 573 | pub fn destroy(self: *Compilation) void { | |
| 574 | resume self.destroy_handle; | |
| 575 | } | |
| 576 | ||
| 552 | 577 | pub fn build(self: *Compilation) !void { |
| 553 | 578 | if (self.llvm_argv.len != 0) { |
| 554 | 579 | var c_compatible_args = try std.cstr.NullTerminated2DArray.fromSlices(self.arena(), [][]const []const u8{ |
| ... | ... | @@ -680,7 +705,7 @@ pub const Compilation = struct { |
| 680 | 705 | }; |
| 681 | 706 | |
| 682 | 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 | 790 | self.libc_link_lib = link_lib; |
| 766 | 791 | |
| 767 | 792 | // get a head start on looking for the native libc |
| 768 | if (self.target == Target.Native) { | |
| 769 | try async<self.loop.allocator> self.startFindingNativeLibC(); | |
| 793 | if (self.target == Target.Native and self.override_libc == null) { | |
| 794 | try self.deinit_group.call(startFindingNativeLibC, self); | |
| 770 | 795 | } |
| 771 | 796 | } |
| 772 | 797 | return link_lib; |
| ... | ... | @@ -774,11 +799,9 @@ pub const Compilation = struct { |
| 774 | 799 | |
| 775 | 800 | /// cancels itself so no need to await or cancel the promise. |
| 776 | 801 | async fn startFindingNativeLibC(self: *Compilation) void { |
| 802 | await (async self.loop.yield() catch unreachable); | |
| 777 | 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 {}; | |
| 779 | suspend |p| { | |
| 780 | cancel p; | |
| 781 | } | |
| 804 | _ = (await (async self.event_loop_local.getNativeLibC() catch unreachable)) catch return; | |
| 782 | 805 | } |
| 783 | 806 | |
| 784 | 807 | /// General Purpose Allocator. Must free when done. |
src-self-hosted/libc_installation.zig+187-35| ... | ... | @@ -1,31 +1,18 @@ |
| 1 | 1 | const std = @import("std"); |
| 2 | 2 | const builtin = @import("builtin"); |
| 3 | 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 | 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 | 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 | 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 | 10 | static_lib_dir: ?[]const u8, |
| 19 | ||
| 20 | /// The directory that contains `vcruntime.lib`. | |
| 21 | /// Only needed when targeting Windows. | |
| 22 | 11 | msvc_lib_dir: ?[]const u8, |
| 23 | ||
| 24 | /// The directory that contains `kernel32.lib`. | |
| 25 | /// Only needed when targeting Windows. | |
| 26 | 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 | 16 | OutOfMemory, |
| 30 | 17 | FileSystem, |
| 31 | 18 | UnableToSpawnCCompiler, |
| ... | ... | @@ -36,16 +23,124 @@ pub const LibCInstallation = struct { |
| 36 | 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 | 139 | /// Finds the default, native libc. |
| 40 | 140 | pub async fn findNative(self: *LibCInstallation, loop: *event.Loop) !void { |
| 41 | self.* = LibCInstallation{ | |
| 42 | .lib_dir = null, | |
| 43 | .include_dir = ([*]const u8)(undefined)[0..0], | |
| 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); | |
| 141 | self.initEmpty(); | |
| 142 | var group = event.Group(FindError!void).init(loop); | |
| 143 | errdefer group.cancelAll(); | |
| 49 | 144 | switch (builtin.os) { |
| 50 | 145 | builtin.Os.windows => { |
| 51 | 146 | try group.call(findNativeIncludeDirWindows, self, loop); |
| ... | ... | @@ -57,6 +152,7 @@ pub const LibCInstallation = struct { |
| 57 | 152 | try group.call(findNativeIncludeDirLinux, self, loop); |
| 58 | 153 | try group.call(findNativeLibDirLinux, self, loop); |
| 59 | 154 | try group.call(findNativeStaticLibDir, self, loop); |
| 155 | try group.call(findNativeDynamicLinker, self, loop); | |
| 60 | 156 | }, |
| 61 | 157 | builtin.Os.macosx => { |
| 62 | 158 | try group.call(findNativeIncludeDirMacOS, self, loop); |
| ... | ... | @@ -147,7 +243,7 @@ pub const LibCInstallation = struct { |
| 147 | 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 | 247 | // TODO |
| 152 | 248 | //ZigWindowsSDK *sdk = get_windows_sdk(g); |
| 153 | 249 | |
| ... | ... | @@ -180,31 +276,83 @@ pub const LibCInstallation = struct { |
| 180 | 276 | @panic("TODO"); |
| 181 | 277 | } |
| 182 | 278 | |
| 183 | async fn findNativeLibDirLinux(self: *LibCInstallation, loop: *event.Loop) Error!void { | |
| 184 | self.lib_dir = try await (async ccPrintFileNameDir(loop, "crt1.o") catch unreachable); | |
| 279 | async fn findNativeLibDirLinux(self: *LibCInstallation, loop: *event.Loop) FindError!void { | |
| 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 { | |
| 188 | self.static_lib_dir = try await (async ccPrintFileNameDir(loop, "crtbegin.o") catch unreachable); | |
| 312 | const DynTest = struct { | |
| 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 | 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 | 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 | 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 | 349 | const cc_exe = std.os.getEnvPosix("CC") orelse "cc"; |
| 203 | 350 | const arg1 = try std.fmt.allocPrint(loop.allocator, "-print-file-name={}", o_file); |
| 204 | 351 | defer loop.allocator.free(arg1); |
| 205 | 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 | 356 | const errorable_result = std.os.ChildProcess.exec(loop.allocator, argv, null, null, 1024 * 1024); |
| 209 | 357 | const exec_result = if (std.debug.runtime_safety) blk: { |
| 210 | 358 | break :blk errorable_result catch unreachable; |
| ... | ... | @@ -230,5 +378,9 @@ async fn ccPrintFileNameDir(loop: *event.Loop, o_file: []const u8) ![]u8 { |
| 230 | 378 | const line = it.next() orelse return error.CCompilerCannotFindCRuntime; |
| 231 | 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 | 3 | const builtin = @import("builtin"); |
| 4 | 4 | const ObjectFormat = builtin.ObjectFormat; |
| 5 | 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 | 9 | const Context = struct { |
| 8 | 10 | comp: *Compilation, |
| ... | ... | @@ -12,9 +14,12 @@ const Context = struct { |
| 12 | 14 | |
| 13 | 15 | link_err: error{OutOfMemory}!void, |
| 14 | 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 | 23 | var ctx = Context{ |
| 19 | 24 | .comp = comp, |
| 20 | 25 | .arena = std.heap.ArenaAllocator.init(comp.gpa()), |
| ... | ... | @@ -22,15 +27,45 @@ pub fn link(comp: *Compilation) !void { |
| 22 | 27 | .link_in_crt = comp.haveLibC() and comp.kind == Compilation.Kind.Exe, |
| 23 | 28 | .link_err = {}, |
| 24 | 29 | .link_msg = undefined, |
| 30 | .libc = undefined, | |
| 31 | .out_file_path = undefined, | |
| 25 | 32 | }; |
| 26 | 33 | defer ctx.arena.deinit(); |
| 27 | 34 | ctx.args = std.ArrayList([*]const u8).init(&ctx.arena.allocator); |
| 28 | 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 | 54 | // even though we're calling LLD as a library it thinks the first |
| 31 | 55 | // argument is its own exe name |
| 32 | 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 | 69 | try constructLinkerArgs(&ctx); |
| 35 | 70 | |
| 36 | 71 | if (comp.verbose_link) { |
| ... | ... | @@ -43,6 +78,7 @@ pub fn link(comp: *Compilation) !void { |
| 43 | 78 | |
| 44 | 79 | const extern_ofmt = toExternObjectFormatType(comp.target.getObjectFormat()); |
| 45 | 80 | const args_slice = ctx.args.toSlice(); |
| 81 | // Not evented I/O. LLD does its own multithreading internally. | |
| 46 | 82 | if (!ZigLLDLink(extern_ofmt, args_slice.ptr, args_slice.len, linkDiagCallback, @ptrCast(*c_void, &ctx))) { |
| 47 | 83 | if (!ctx.link_msg.isNull()) { |
| 48 | 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 | 131 | } |
| 96 | 132 | |
| 97 | 133 | fn constructLinkerArgsElf(ctx: *Context) !void { |
| 98 | //if (g->libc_link_lib != nullptr) { | |
| 99 | // find_libc_lib_path(g); | |
| 100 | //} | |
| 101 | ||
| 134 | // TODO commented out code in this function | |
| 102 | 135 | //if (g->linker_script) { |
| 103 | 136 | // lj->args.append("-T"); |
| 104 | 137 | // lj->args.append(g->linker_script); |
| ... | ... | @@ -107,7 +140,7 @@ fn constructLinkerArgsElf(ctx: *Context) !void { |
| 107 | 140 | //if (g->no_rosegment_workaround) { |
| 108 | 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 | 145 | //lj->args.append("-m"); |
| 113 | 146 | //lj->args.append(getLDMOption(&g->zig_target)); |
| ... | ... | @@ -115,14 +148,13 @@ fn constructLinkerArgsElf(ctx: *Context) !void { |
| 115 | 148 | //bool is_lib = g->out_type == OutTypeLib; |
| 116 | 149 | //bool shared = !g->is_static && is_lib; |
| 117 | 150 | //Buf *soname = nullptr; |
| 118 | //if (g->is_static) { | |
| 119 | // if (g->zig_target.arch.arch == ZigLLVM_arm || g->zig_target.arch.arch == ZigLLVM_armeb || | |
| 120 | // g->zig_target.arch.arch == ZigLLVM_thumb || g->zig_target.arch.arch == ZigLLVM_thumbeb) | |
| 121 | // { | |
| 122 | // lj->args.append("-Bstatic"); | |
| 123 | // } else { | |
| 124 | // lj->args.append("-static"); | |
| 125 | // } | |
| 151 | if (ctx.comp.is_static) { | |
| 152 | if (ctx.comp.target.isArmOrThumb()) { | |
| 153 | try ctx.args.append(c"-Bstatic"); | |
| 154 | } else { | |
| 155 | try ctx.args.append(c"-static"); | |
| 156 | } | |
| 157 | } | |
| 126 | 158 | //} else if (shared) { |
| 127 | 159 | // lj->args.append("-shared"); |
| 128 | 160 | |
| ... | ... | @@ -133,23 +165,16 @@ fn constructLinkerArgsElf(ctx: *Context) !void { |
| 133 | 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"); | |
| 137 | //lj->args.append(buf_ptr(&lj->out_file)); | |
| 168 | try ctx.args.append(c"-o"); | |
| 169 | try ctx.args.append(ctx.out_file_path.ptr()); | |
| 138 | 170 | |
| 139 | //if (lj->link_in_crt) { | |
| 140 | // const char *crt1o; | |
| 141 | // const char *crtbegino; | |
| 142 | // if (g->is_static) { | |
| 143 | // crt1o = "crt1.o"; | |
| 144 | // crtbegino = "crtbeginT.o"; | |
| 145 | // } else { | |
| 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 | //} | |
| 171 | if (ctx.link_in_crt) { | |
| 172 | const crt1o = if (ctx.comp.is_static) "crt1.o" else "Scrt1.o"; | |
| 173 | const crtbegino = if (ctx.comp.is_static) "crtbeginT.o" else "crtbegin.o"; | |
| 174 | try addPathJoin(ctx, ctx.libc.lib_dir.?, crt1o); | |
| 175 | try addPathJoin(ctx, ctx.libc.lib_dir.?, "crti.o"); | |
| 176 | try addPathJoin(ctx, ctx.libc.static_lib_dir.?, crtbegino); | |
| 177 | } | |
| 153 | 178 | |
| 154 | 179 | //for (size_t i = 0; i < g->rpath_list.length; i += 1) { |
| 155 | 180 | // Buf *rpath = g->rpath_list.at(i); |
| ... | ... | @@ -182,25 +207,23 @@ fn constructLinkerArgsElf(ctx: *Context) !void { |
| 182 | 207 | // lj->args.append(lib_dir); |
| 183 | 208 | //} |
| 184 | 209 | |
| 185 | //if (g->libc_link_lib != nullptr) { | |
| 186 | // lj->args.append("-L"); | |
| 187 | // lj->args.append(buf_ptr(g->libc_lib_dir)); | |
| 188 | ||
| 189 | // lj->args.append("-L"); | |
| 190 | // lj->args.append(buf_ptr(g->libc_static_lib_dir)); | |
| 191 | //} | |
| 192 | ||
| 193 | //if (!g->is_static) { | |
| 194 | // if (g->dynamic_linker != nullptr) { | |
| 195 | // assert(buf_len(g->dynamic_linker) != 0); | |
| 196 | // lj->args.append("-dynamic-linker"); | |
| 197 | // lj->args.append(buf_ptr(g->dynamic_linker)); | |
| 198 | // } else { | |
| 199 | // Buf *resolved_dynamic_linker = get_dynamic_linker_path(g); | |
| 200 | // lj->args.append("-dynamic-linker"); | |
| 201 | // lj->args.append(buf_ptr(resolved_dynamic_linker)); | |
| 202 | // } | |
| 203 | //} | |
| 210 | if (ctx.comp.haveLibC()) { | |
| 211 | try ctx.args.append(c"-L"); | |
| 212 | try ctx.args.append((try std.cstr.addNullByte(&ctx.arena.allocator, ctx.libc.lib_dir.?)).ptr); | |
| 213 | ||
| 214 | try ctx.args.append(c"-L"); | |
| 215 | try ctx.args.append((try std.cstr.addNullByte(&ctx.arena.allocator, ctx.libc.static_lib_dir.?)).ptr); | |
| 216 | ||
| 217 | if (!ctx.comp.is_static) { | |
| 218 | const dl = blk: { | |
| 219 | if (ctx.libc.dynamic_linker_path) |dl| break :blk dl; | |
| 220 | if (ctx.comp.target.getDynamicLinkerPath()) |dl| break :blk dl; | |
| 221 | return error.LibCMissingDynamicLinker; | |
| 222 | }; | |
| 223 | try ctx.args.append(c"-dynamic-linker"); | |
| 224 | try ctx.args.append((try std.cstr.addNullByte(&ctx.arena.allocator, dl)).ptr); | |
| 225 | } | |
| 226 | } | |
| 204 | 227 | |
| 205 | 228 | //if (shared) { |
| 206 | 229 | // lj->args.append("-soname"); |
| ... | ... | @@ -241,45 +264,51 @@ fn constructLinkerArgsElf(ctx: *Context) !void { |
| 241 | 264 | // lj->args.append(buf_ptr(arg)); |
| 242 | 265 | //} |
| 243 | 266 | |
| 244 | //// libc dep | |
| 245 | //if (g->libc_link_lib != nullptr) { | |
| 246 | // if (g->is_static) { | |
| 247 | // lj->args.append("--start-group"); | |
| 248 | // lj->args.append("-lgcc"); | |
| 249 | // lj->args.append("-lgcc_eh"); | |
| 250 | // lj->args.append("-lc"); | |
| 251 | // lj->args.append("-lm"); | |
| 252 | // lj->args.append("--end-group"); | |
| 253 | // } else { | |
| 254 | // lj->args.append("-lgcc"); | |
| 255 | // lj->args.append("--as-needed"); | |
| 256 | // lj->args.append("-lgcc_s"); | |
| 257 | // lj->args.append("--no-as-needed"); | |
| 258 | // lj->args.append("-lc"); | |
| 259 | // lj->args.append("-lm"); | |
| 260 | // lj->args.append("-lgcc"); | |
| 261 | // lj->args.append("--as-needed"); | |
| 262 | // lj->args.append("-lgcc_s"); | |
| 263 | // lj->args.append("--no-as-needed"); | |
| 264 | // } | |
| 265 | //} | |
| 267 | // libc dep | |
| 268 | if (ctx.comp.haveLibC()) { | |
| 269 | if (ctx.comp.is_static) { | |
| 270 | try ctx.args.append(c"--start-group"); | |
| 271 | try ctx.args.append(c"-lgcc"); | |
| 272 | try ctx.args.append(c"-lgcc_eh"); | |
| 273 | try ctx.args.append(c"-lc"); | |
| 274 | try ctx.args.append(c"-lm"); | |
| 275 | try ctx.args.append(c"--end-group"); | |
| 276 | } else { | |
| 277 | try ctx.args.append(c"-lgcc"); | |
| 278 | try ctx.args.append(c"--as-needed"); | |
| 279 | try ctx.args.append(c"-lgcc_s"); | |
| 280 | try ctx.args.append(c"--no-as-needed"); | |
| 281 | try ctx.args.append(c"-lc"); | |
| 282 | try ctx.args.append(c"-lm"); | |
| 283 | try ctx.args.append(c"-lgcc"); | |
| 284 | try ctx.args.append(c"--as-needed"); | |
| 285 | try ctx.args.append(c"-lgcc_s"); | |
| 286 | try ctx.args.append(c"--no-as-needed"); | |
| 287 | } | |
| 288 | } | |
| 266 | 289 | |
| 267 | //// crt end | |
| 268 | //if (lj->link_in_crt) { | |
| 269 | // lj->args.append(get_libc_static_file(g, "crtend.o")); | |
| 270 | // lj->args.append(get_libc_file(g, "crtn.o")); | |
| 271 | //} | |
| 290 | // crt end | |
| 291 | if (ctx.link_in_crt) { | |
| 292 | try addPathJoin(ctx, ctx.libc.static_lib_dir.?, "crtend.o"); | |
| 293 | try addPathJoin(ctx, ctx.libc.lib_dir.?, "crtn.o"); | |
| 294 | } | |
| 272 | 295 | |
| 273 | //if (!g->is_native_target) { | |
| 274 | // lj->args.append("--allow-shlib-undefined"); | |
| 275 | //} | |
| 296 | if (ctx.comp.target != Target.Native) { | |
| 297 | try ctx.args.append(c"--allow-shlib-undefined"); | |
| 298 | } | |
| 276 | 299 | |
| 277 | //if (g->zig_target.os == OsZen) { | |
| 278 | // lj->args.append("-e"); | |
| 279 | // lj->args.append("_start"); | |
| 300 | if (ctx.comp.target.getOs() == builtin.Os.zen) { | |
| 301 | try ctx.args.append(c"-e"); | |
| 302 | try ctx.args.append(c"_start"); | |
| 280 | 303 | |
| 281 | // lj->args.append("--image-base=0x10000000"); | |
| 282 | //} | |
| 304 | try ctx.args.append(c"--image-base=0x10000000"); | |
| 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 | 314 | fn constructLinkerArgsCoff(ctx: *Context) void { |
src-self-hosted/main.zig+53-34| ... | ... | @@ -18,6 +18,7 @@ const EventLoopLocal = @import("compilation.zig").EventLoopLocal; |
| 18 | 18 | const Compilation = @import("compilation.zig").Compilation; |
| 19 | 19 | const Target = @import("target.zig").Target; |
| 20 | 20 | const errmsg = @import("errmsg.zig"); |
| 21 | const LibCInstallation = @import("libc_installation.zig").LibCInstallation; | |
| 21 | 22 | |
| 22 | 23 | var stderr_file: os.File = undefined; |
| 23 | 24 | var stderr: *io.OutStream(io.FileOutStream.Error) = undefined; |
| ... | ... | @@ -28,14 +29,14 @@ const usage = |
| 28 | 29 | \\ |
| 29 | 30 | \\Commands: |
| 30 | 31 | \\ |
| 31 | \\ build-exe [source] Create executable from source or object files | |
| 32 | \\ build-lib [source] Create library from source or object files | |
| 33 | \\ 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 | |
| 36 | \\ targets List available compilation targets | |
| 37 | \\ version Print version number and exit | |
| 38 | \\ zen Print zen of zig and exit | |
| 32 | \\ build-exe [source] Create executable from source or object files | |
| 33 | \\ build-lib [source] Create library from source or object files | |
| 34 | \\ build-obj [source] Create object from source or assembly | |
| 35 | \\ fmt [source] Parse file and render in canonical zig format | |
| 36 | \\ libc [paths_file] Display native libc paths file or validate one | |
| 37 | \\ targets List available compilation targets | |
| 38 | \\ version Print version number 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 | 83 | .name = "build-obj", |
| 83 | 84 | .exec = cmdBuildObj, |
| 84 | 85 | }, |
| 85 | Command{ | |
| 86 | .name = "find-libc", | |
| 87 | .exec = cmdFindLibc, | |
| 88 | }, | |
| 89 | 86 | Command{ |
| 90 | 87 | .name = "fmt", |
| 91 | 88 | .exec = cmdFmt, |
| 92 | 89 | }, |
| 90 | Command{ | |
| 91 | .name = "libc", | |
| 92 | .exec = cmdLibC, | |
| 93 | }, | |
| 93 | 94 | Command{ |
| 94 | 95 | .name = "targets", |
| 95 | 96 | .exec = cmdTargets, |
| ... | ... | @@ -135,6 +136,7 @@ const usage_build_generic = |
| 135 | 136 | \\ --color [auto|off|on] Enable or disable colored error messages |
| 136 | 137 | \\ |
| 137 | 138 | \\Compile Options: |
| 139 | \\ --libc [file] Provide a file which specifies libc paths | |
| 138 | 140 | \\ --assembly [source] Add assembly file to build |
| 139 | 141 | \\ --cache-dir [path] Override the cache directory |
| 140 | 142 | \\ --emit [filetype] Emit a specific file format as compilation output |
| ... | ... | @@ -167,7 +169,6 @@ const usage_build_generic = |
| 167 | 169 | \\ |
| 168 | 170 | \\Link Options: |
| 169 | 171 | \\ --ar-path [path] Set the path to ar |
| 170 | \\ --dynamic-linker [path] Set the path to ld.so | |
| 171 | 172 | \\ --each-lib-rpath Add rpath for each used dynamic library |
| 172 | 173 | \\ --library [lib] Link against lib |
| 173 | 174 | \\ --forbid-library [lib] Make it an error to link against lib |
| ... | ... | @@ -210,6 +211,7 @@ const args_build_generic = []Flag{ |
| 210 | 211 | "llvm-ir", |
| 211 | 212 | }), |
| 212 | 213 | Flag.Bool("--enable-timing-info"), |
| 214 | Flag.Arg1("--libc"), | |
| 213 | 215 | Flag.Arg1("--name"), |
| 214 | 216 | Flag.Arg1("--output"), |
| 215 | 217 | Flag.Arg1("--output-h"), |
| ... | ... | @@ -233,7 +235,6 @@ const args_build_generic = []Flag{ |
| 233 | 235 | Flag.Arg1("-mllvm"), |
| 234 | 236 | |
| 235 | 237 | Flag.Arg1("--ar-path"), |
| 236 | Flag.Arg1("--dynamic-linker"), | |
| 237 | 238 | Flag.Bool("--each-lib-rpath"), |
| 238 | 239 | Flag.ArgMergeN("--library", 1), |
| 239 | 240 | Flag.ArgMergeN("--forbid-library", 1), |
| ... | ... | @@ -382,6 +383,8 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co |
| 382 | 383 | const zig_lib_dir = introspect.resolveZigLibDir(allocator) catch os.exit(1); |
| 383 | 384 | defer allocator.free(zig_lib_dir); |
| 384 | 385 | |
| 386 | var override_libc: LibCInstallation = undefined; | |
| 387 | ||
| 385 | 388 | var loop: event.Loop = undefined; |
| 386 | 389 | try loop.initMultiThreaded(allocator); |
| 387 | 390 | defer loop.deinit(); |
| ... | ... | @@ -402,6 +405,15 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co |
| 402 | 405 | ); |
| 403 | 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 | 417 | comp.version_major = try std.fmt.parseUnsigned(u32, flags.single("ver-major") orelse "0", 10); |
| 406 | 418 | comp.version_minor = try std.fmt.parseUnsigned(u32, flags.single("ver-minor") orelse "0", 10); |
| 407 | 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 | 437 | |
| 426 | 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 | 440 | comp.verbose_tokenize = flags.present("verbose-tokenize"); |
| 433 | 441 | comp.verbose_ast_tree = flags.present("verbose-ast-tree"); |
| 434 | 442 | comp.verbose_ast_fmt = flags.present("verbose-ast-fmt"); |
| ... | ... | @@ -479,7 +487,6 @@ async fn processBuildEvents(comp: *Compilation, color: errmsg.Color) void { |
| 479 | 487 | |
| 480 | 488 | switch (build_event) { |
| 481 | 489 | Compilation.Event.Ok => { |
| 482 | std.debug.warn("Build succeeded\n"); | |
| 483 | 490 | return; |
| 484 | 491 | }, |
| 485 | 492 | Compilation.Event.Error => |err| { |
| ... | ... | @@ -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 | 595 | var loop: event.Loop = undefined; |
| 564 | 596 | try loop.initMultiThreaded(allocator); |
| 565 | 597 | defer loop.deinit(); |
| ... | ... | @@ -578,20 +610,7 @@ async fn findLibCAsync(event_loop_local: *EventLoopLocal) void { |
| 578 | 610 | stderr.print("unable to find libc: {}\n", @errorName(err)) catch os.exit(1); |
| 579 | 611 | os.exit(1); |
| 580 | 612 | }; |
| 581 | stderr.print( | |
| 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); | |
| 613 | libc.render(stdout) catch os.exit(1); | |
| 595 | 614 | } |
| 596 | 615 | |
| 597 | 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 | 2 | const builtin = @import("builtin"); |
| 3 | 3 | const llvm = @import("llvm.zig"); |
| 4 | 4 | |
| 5 | pub const FloatAbi = enum { | |
| 6 | Hard, | |
| 7 | Soft, | |
| 8 | SoftFp, | |
| 9 | }; | |
| 10 | ||
| 5 | 11 | pub const Target = union(enum) { |
| 6 | 12 | Native, |
| 7 | 13 | Cross: Cross, |
| ... | ... | @@ -13,7 +19,7 @@ pub const Target = union(enum) { |
| 13 | 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 | 23 | return switch (self.getObjectFormat()) { |
| 18 | 24 | builtin.ObjectFormat.coff => ".obj", |
| 19 | 25 | else => ".o", |
| ... | ... | @@ -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 | 43 | pub fn getOs(self: Target) builtin.Os { |
| 31 | 44 | return switch (self) { |
| 32 | 45 | Target.Native => builtin.os, |
| ... | ... | @@ -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 | 142 | pub fn initializeAll() void { |
| 80 | 143 | llvm.InitializeAllTargets(); |
| 81 | 144 | llvm.InitializeAllTargetInfos(); |
| ... | ... | @@ -106,6 +169,257 @@ pub const Target = union(enum) { |
| 106 | 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 | 423 | pub fn llvmTargetFromTriple(triple: std.Buffer) !llvm.TargetRef { |
| 110 | 424 | var result: llvm.TargetRef = undefined; |
| 111 | 425 | var err_msg: [*]u8 = undefined; |
std/event/group.zig+2-2| ... | ... | @@ -6,7 +6,7 @@ const AtomicRmwOp = builtin.AtomicRmwOp; |
| 6 | 6 | const AtomicOrder = builtin.AtomicOrder; |
| 7 | 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 | 10 | pub fn Group(comptime ReturnType: type) type { |
| 11 | 11 | return struct { |
| 12 | 12 | coro_stack: Stack, |
| ... | ... | @@ -39,7 +39,7 @@ pub fn Group(comptime ReturnType: type) type { |
| 39 | 39 | } |
| 40 | 40 | |
| 41 | 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 | 43 | /// Thread-safe. |
| 44 | 44 | pub fn call(self: *Self, comptime func: var, args: ...) (error{OutOfMemory}!void) { |
| 45 | 45 | const S = struct { |
std/event/loop.zig+1-1| ... | ... | @@ -444,7 +444,7 @@ pub const Loop = struct { |
| 444 | 444 | .next = undefined, |
| 445 | 445 | .data = p, |
| 446 | 446 | }; |
| 447 | loop.onNextTick(&my_tick_node); | |
| 447 | self.onNextTick(&my_tick_node); | |
| 448 | 448 | } |
| 449 | 449 | } |
| 450 | 450 |