| author | |
| committer | |
| log | 3e4a3fa5b7faadaae0a57088baa392e2bb52fe38 |
| tree | 1d48d805c26c3551a88b865582e76cf25bc8ef23 |
| parent | fd3a41dadc92e7b69b409af5f747004996465032 |
5 files changed, 326 insertions(+), 61 deletions(-)
src-self-hosted/compilation.zig+25-10| ... | @@ -28,6 +28,7 @@ const Span = errmsg.Span; | ... | @@ -28,6 +28,7 @@ const Span = errmsg.Span; |
| 28 | const codegen = @import("codegen.zig"); | 28 | const codegen = @import("codegen.zig"); |
| 29 | const Package = @import("package.zig").Package; | 29 | const Package = @import("package.zig").Package; |
| 30 | const link = @import("link.zig").link; | 30 | const link = @import("link.zig").link; |
| 31 | const LibCInstallation = @import("libc_installation.zig").LibCInstallation; | ||
| 31 | 32 | ||
| 32 | /// Data that is local to the event loop. | 33 | /// Data that is local to the event loop. |
| 33 | pub const EventLoopLocal = struct { | 34 | pub const EventLoopLocal = struct { |
| ... | @@ -37,6 +38,8 @@ pub const EventLoopLocal = struct { | ... | @@ -37,6 +38,8 @@ pub const EventLoopLocal = struct { |
| 37 | /// TODO pool these so that it doesn't have to lock | 38 | /// TODO pool these so that it doesn't have to lock |
| 38 | prng: event.Locked(std.rand.DefaultPrng), | 39 | prng: event.Locked(std.rand.DefaultPrng), |
| 39 | 40 | ||
| 41 | native_libc: event.Future(LibCInstallation), | ||
| 42 | |||
| 40 | var lazy_init_targets = std.lazyInit(void); | 43 | var lazy_init_targets = std.lazyInit(void); |
| 41 | 44 | ||
| 42 | fn init(loop: *event.Loop) !EventLoopLocal { | 45 | fn init(loop: *event.Loop) !EventLoopLocal { |
| ... | @@ -52,6 +55,7 @@ pub const EventLoopLocal = struct { | ... | @@ -52,6 +55,7 @@ pub const EventLoopLocal = struct { |
| 52 | .loop = loop, | 55 | .loop = loop, |
| 53 | .llvm_handle_pool = std.atomic.Stack(llvm.ContextRef).init(), | 56 | .llvm_handle_pool = std.atomic.Stack(llvm.ContextRef).init(), |
| 54 | .prng = event.Locked(std.rand.DefaultPrng).init(loop, std.rand.DefaultPrng.init(seed)), | 57 | .prng = event.Locked(std.rand.DefaultPrng).init(loop, std.rand.DefaultPrng.init(seed)), |
| 58 | .native_libc = event.Future(LibCInstallation).init(loop), | ||
| 55 | }; | 59 | }; |
| 56 | } | 60 | } |
| 57 | 61 | ||
| ... | @@ -78,6 +82,13 @@ pub const EventLoopLocal = struct { | ... | @@ -78,6 +82,13 @@ pub const EventLoopLocal = struct { |
| 78 | 82 | ||
| 79 | return LlvmHandle{ .node = node }; | 83 | return LlvmHandle{ .node = node }; |
| 80 | } | 84 | } |
| 85 | |||
| 86 | pub async fn getNativeLibC(self: *EventLoopLocal) !*LibCInstallation { | ||
| 87 | if (await (async self.native_libc.start() catch unreachable)) |ptr| return ptr; | ||
| 88 | try await (async self.native_libc.data.findNative(self.loop) catch unreachable); | ||
| 89 | self.native_libc.resolve(); | ||
| 90 | return &self.native_libc.data; | ||
| 91 | } | ||
| 81 | }; | 92 | }; |
| 82 | 93 | ||
| 83 | pub const LlvmHandle = struct { | 94 | pub const LlvmHandle = struct { |
| ... | @@ -109,11 +120,6 @@ pub const Compilation = struct { | ... | @@ -109,11 +120,6 @@ pub const Compilation = struct { |
| 109 | 120 | ||
| 110 | linker_script: ?[]const u8, | 121 | linker_script: ?[]const u8, |
| 111 | cache_dir: []const u8, | 122 | cache_dir: []const u8, |
| 112 | libc_lib_dir: ?[]const u8, | ||
| 113 | libc_static_lib_dir: ?[]const u8, | ||
| 114 | libc_include_dir: ?[]const u8, | ||
| 115 | msvc_lib_dir: ?[]const u8, | ||
| 116 | kernel32_lib_dir: ?[]const u8, | ||
| 117 | dynamic_linker: ?[]const u8, | 123 | dynamic_linker: ?[]const u8, |
| 118 | out_h_path: ?[]const u8, | 124 | out_h_path: ?[]const u8, |
| 119 | 125 | ||
| ... | @@ -318,11 +324,6 @@ pub const Compilation = struct { | ... | @@ -318,11 +324,6 @@ pub const Compilation = struct { |
| 318 | .verbose_link = false, | 324 | .verbose_link = false, |
| 319 | 325 | ||
| 320 | .linker_script = null, | 326 | .linker_script = null, |
| 321 | .libc_lib_dir = null, | ||
| 322 | .libc_static_lib_dir = null, | ||
| 323 | .libc_include_dir = null, | ||
| 324 | .msvc_lib_dir = null, | ||
| 325 | .kernel32_lib_dir = null, | ||
| 326 | .dynamic_linker = null, | 327 | .dynamic_linker = null, |
| 327 | .out_h_path = null, | 328 | .out_h_path = null, |
| 328 | .is_test = false, | 329 | .is_test = false, |
| ... | @@ -762,10 +763,24 @@ pub const Compilation = struct { | ... | @@ -762,10 +763,24 @@ pub const Compilation = struct { |
| 762 | try self.link_libs_list.append(link_lib); | 763 | try self.link_libs_list.append(link_lib); |
| 763 | if (is_libc) { | 764 | if (is_libc) { |
| 764 | self.libc_link_lib = link_lib; | 765 | self.libc_link_lib = link_lib; |
| 766 | |||
| 767 | // get a head start on looking for the native libc | ||
| 768 | if (self.target == Target.Native) { | ||
| 769 | try async<self.loop.allocator> self.startFindingNativeLibC(); | ||
| 770 | } | ||
| 765 | } | 771 | } |
| 766 | return link_lib; | 772 | return link_lib; |
| 767 | } | 773 | } |
| 768 | 774 | ||
| 775 | /// cancels itself so no need to await or cancel the promise. | ||
| 776 | async fn startFindingNativeLibC(self: *Compilation) void { | ||
| 777 | // 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 | } | ||
| 782 | } | ||
| 783 | |||
| 769 | /// General Purpose Allocator. Must free when done. | 784 | /// General Purpose Allocator. Must free when done. |
| 770 | fn gpa(self: Compilation) *mem.Allocator { | 785 | fn gpa(self: Compilation) *mem.Allocator { |
| 771 | return self.loop.allocator; | 786 | return self.loop.allocator; |
src-self-hosted/libc_installation.zig created+234| ... | @@ -0,0 +1,234 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const builtin = @import("builtin"); | ||
| 3 | const event = std.event; | ||
| 4 | |||
| 5 | 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, | ||
| 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, | ||
| 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, | ||
| 19 | |||
| 20 | /// The directory that contains `vcruntime.lib`. | ||
| 21 | /// Only needed when targeting Windows. | ||
| 22 | 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, | ||
| 27 | |||
| 28 | pub const Error = error{ | ||
| 29 | OutOfMemory, | ||
| 30 | FileSystem, | ||
| 31 | UnableToSpawnCCompiler, | ||
| 32 | CCompilerExitCode, | ||
| 33 | CCompilerCrashed, | ||
| 34 | CCompilerCannotFindHeaders, | ||
| 35 | CCompilerCannotFindCRuntime, | ||
| 36 | LibCStdLibHeaderNotFound, | ||
| 37 | }; | ||
| 38 | |||
| 39 | /// Finds the default, native libc. | ||
| 40 | 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); | ||
| 49 | switch (builtin.os) { | ||
| 50 | builtin.Os.windows => { | ||
| 51 | try group.call(findNativeIncludeDirWindows, self, loop); | ||
| 52 | try group.call(findNativeLibDirWindows, self, loop); | ||
| 53 | try group.call(findNativeMsvcLibDir, self, loop); | ||
| 54 | try group.call(findNativeKernel32LibDir, self, loop); | ||
| 55 | }, | ||
| 56 | builtin.Os.linux => { | ||
| 57 | try group.call(findNativeIncludeDirLinux, self, loop); | ||
| 58 | try group.call(findNativeLibDirLinux, self, loop); | ||
| 59 | try group.call(findNativeStaticLibDir, self, loop); | ||
| 60 | }, | ||
| 61 | builtin.Os.macosx => { | ||
| 62 | try group.call(findNativeIncludeDirMacOS, self, loop); | ||
| 63 | }, | ||
| 64 | else => @compileError("unimplemented: find libc for this OS"), | ||
| 65 | } | ||
| 66 | return await (async group.wait() catch unreachable); | ||
| 67 | } | ||
| 68 | |||
| 69 | async fn findNativeIncludeDirLinux(self: *LibCInstallation, loop: *event.Loop) !void { | ||
| 70 | const cc_exe = std.os.getEnvPosix("CC") orelse "cc"; | ||
| 71 | const argv = []const []const u8{ | ||
| 72 | cc_exe, | ||
| 73 | "-E", | ||
| 74 | "-Wp,-v", | ||
| 75 | "-xc", | ||
| 76 | "/dev/null", | ||
| 77 | }; | ||
| 78 | // TODO make this use event loop | ||
| 79 | const errorable_result = std.os.ChildProcess.exec(loop.allocator, argv, null, null, 1024 * 1024); | ||
| 80 | const exec_result = if (std.debug.runtime_safety) blk: { | ||
| 81 | break :blk errorable_result catch unreachable; | ||
| 82 | } else blk: { | ||
| 83 | break :blk errorable_result catch |err| switch (err) { | ||
| 84 | error.OutOfMemory => return error.OutOfMemory, | ||
| 85 | else => return error.UnableToSpawnCCompiler, | ||
| 86 | }; | ||
| 87 | }; | ||
| 88 | defer { | ||
| 89 | loop.allocator.free(exec_result.stdout); | ||
| 90 | loop.allocator.free(exec_result.stderr); | ||
| 91 | } | ||
| 92 | |||
| 93 | switch (exec_result.term) { | ||
| 94 | std.os.ChildProcess.Term.Exited => |code| { | ||
| 95 | if (code != 0) return error.CCompilerExitCode; | ||
| 96 | }, | ||
| 97 | else => { | ||
| 98 | return error.CCompilerCrashed; | ||
| 99 | }, | ||
| 100 | } | ||
| 101 | |||
| 102 | var it = std.mem.split(exec_result.stderr, "\n\r"); | ||
| 103 | var search_paths = std.ArrayList([]const u8).init(loop.allocator); | ||
| 104 | defer search_paths.deinit(); | ||
| 105 | while (it.next()) |line| { | ||
| 106 | if (line.len != 0 and line[0] == ' ') { | ||
| 107 | try search_paths.append(line); | ||
| 108 | } | ||
| 109 | } | ||
| 110 | if (search_paths.len == 0) { | ||
| 111 | return error.CCompilerCannotFindHeaders; | ||
| 112 | } | ||
| 113 | |||
| 114 | // search in reverse order | ||
| 115 | var path_i: usize = 0; | ||
| 116 | while (path_i < search_paths.len) : (path_i += 1) { | ||
| 117 | const search_path_untrimmed = search_paths.at(search_paths.len - path_i - 1); | ||
| 118 | const search_path = std.mem.trimLeft(u8, search_path_untrimmed, " "); | ||
| 119 | const stdlib_path = try std.os.path.join(loop.allocator, search_path, "stdlib.h"); | ||
| 120 | defer loop.allocator.free(stdlib_path); | ||
| 121 | |||
| 122 | if (std.os.File.access(loop.allocator, stdlib_path)) |_| { | ||
| 123 | self.include_dir = try std.mem.dupe(loop.allocator, u8, search_path); | ||
| 124 | return; | ||
| 125 | } else |err| switch (err) { | ||
| 126 | error.NotFound, error.PermissionDenied => continue, | ||
| 127 | error.OutOfMemory => return error.OutOfMemory, | ||
| 128 | else => return error.FileSystem, | ||
| 129 | } | ||
| 130 | } | ||
| 131 | |||
| 132 | return error.LibCStdLibHeaderNotFound; | ||
| 133 | } | ||
| 134 | |||
| 135 | async fn findNativeIncludeDirWindows(self: *LibCInstallation, loop: *event.Loop) !void { | ||
| 136 | // TODO | ||
| 137 | //ZigWindowsSDK *sdk = get_windows_sdk(g); | ||
| 138 | //g->libc_include_dir = buf_alloc(); | ||
| 139 | //if (os_get_win32_ucrt_include_path(sdk, g->libc_include_dir)) { | ||
| 140 | // fprintf(stderr, "Unable to determine libc include path. --libc-include-dir"); | ||
| 141 | // exit(1); | ||
| 142 | //} | ||
| 143 | @panic("TODO"); | ||
| 144 | } | ||
| 145 | |||
| 146 | async fn findNativeIncludeDirMacOS(self: *LibCInstallation, loop: *event.Loop) !void { | ||
| 147 | self.include_dir = try std.mem.dupe(loop.allocator, u8, "/usr/include"); | ||
| 148 | } | ||
| 149 | |||
| 150 | async fn findNativeLibDirWindows(self: *LibCInstallation, loop: *event.Loop) Error!void { | ||
| 151 | // TODO | ||
| 152 | //ZigWindowsSDK *sdk = get_windows_sdk(g); | ||
| 153 | |||
| 154 | //if (g->msvc_lib_dir == nullptr) { | ||
| 155 | // Buf* vc_lib_dir = buf_alloc(); | ||
| 156 | // if (os_get_win32_vcruntime_path(vc_lib_dir, g->zig_target.arch.arch)) { | ||
| 157 | // fprintf(stderr, "Unable to determine vcruntime path. --msvc-lib-dir"); | ||
| 158 | // exit(1); | ||
| 159 | // } | ||
| 160 | // g->msvc_lib_dir = vc_lib_dir; | ||
| 161 | //} | ||
| 162 | |||
| 163 | //if (g->libc_lib_dir == nullptr) { | ||
| 164 | // Buf* ucrt_lib_path = buf_alloc(); | ||
| 165 | // if (os_get_win32_ucrt_lib_path(sdk, ucrt_lib_path, g->zig_target.arch.arch)) { | ||
| 166 | // fprintf(stderr, "Unable to determine ucrt path. --libc-lib-dir"); | ||
| 167 | // exit(1); | ||
| 168 | // } | ||
| 169 | // g->libc_lib_dir = ucrt_lib_path; | ||
| 170 | //} | ||
| 171 | |||
| 172 | //if (g->kernel32_lib_dir == nullptr) { | ||
| 173 | // Buf* kern_lib_path = buf_alloc(); | ||
| 174 | // if (os_get_win32_kern32_path(sdk, kern_lib_path, g->zig_target.arch.arch)) { | ||
| 175 | // fprintf(stderr, "Unable to determine kernel32 path. --kernel32-lib-dir"); | ||
| 176 | // exit(1); | ||
| 177 | // } | ||
| 178 | // g->kernel32_lib_dir = kern_lib_path; | ||
| 179 | //} | ||
| 180 | @panic("TODO"); | ||
| 181 | } | ||
| 182 | |||
| 183 | async fn findNativeLibDirLinux(self: *LibCInstallation, loop: *event.Loop) Error!void { | ||
| 184 | self.lib_dir = try await (async ccPrintFileNameDir(loop, "crt1.o") catch unreachable); | ||
| 185 | } | ||
| 186 | |||
| 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); | ||
| 189 | } | ||
| 190 | |||
| 191 | async fn findNativeMsvcLibDir(self: *LibCInstallation, loop: *event.Loop) Error!void { | ||
| 192 | @panic("TODO"); | ||
| 193 | } | ||
| 194 | |||
| 195 | async fn findNativeKernel32LibDir(self: *LibCInstallation, loop: *event.Loop) Error!void { | ||
| 196 | @panic("TODO"); | ||
| 197 | } | ||
| 198 | }; | ||
| 199 | |||
| 200 | /// caller owns returned memory | ||
| 201 | async fn ccPrintFileNameDir(loop: *event.Loop, o_file: []const u8) ![]u8 { | ||
| 202 | const cc_exe = std.os.getEnvPosix("CC") orelse "cc"; | ||
| 203 | const arg1 = try std.fmt.allocPrint(loop.allocator, "-print-file-name={}", o_file); | ||
| 204 | defer loop.allocator.free(arg1); | ||
| 205 | const argv = []const []const u8{ cc_exe, arg1 }; | ||
| 206 | |||
| 207 | // TODO evented I/O | ||
| 208 | const errorable_result = std.os.ChildProcess.exec(loop.allocator, argv, null, null, 1024 * 1024); | ||
| 209 | const exec_result = if (std.debug.runtime_safety) blk: { | ||
| 210 | break :blk errorable_result catch unreachable; | ||
| 211 | } else blk: { | ||
| 212 | break :blk errorable_result catch |err| switch (err) { | ||
| 213 | error.OutOfMemory => return error.OutOfMemory, | ||
| 214 | else => return error.UnableToSpawnCCompiler, | ||
| 215 | }; | ||
| 216 | }; | ||
| 217 | defer { | ||
| 218 | loop.allocator.free(exec_result.stdout); | ||
| 219 | loop.allocator.free(exec_result.stderr); | ||
| 220 | } | ||
| 221 | switch (exec_result.term) { | ||
| 222 | std.os.ChildProcess.Term.Exited => |code| { | ||
| 223 | if (code != 0) return error.CCompilerExitCode; | ||
| 224 | }, | ||
| 225 | else => { | ||
| 226 | return error.CCompilerCrashed; | ||
| 227 | }, | ||
| 228 | } | ||
| 229 | var it = std.mem.split(exec_result.stdout, "\n\r"); | ||
| 230 | const line = it.next() orelse return error.CCompilerCannotFindCRuntime; | ||
| 231 | const dirname = std.os.path.dirname(line) orelse return error.CCompilerCannotFindCRuntime; | ||
| 232 | |||
| 233 | return std.mem.dupe(loop.allocator, u8, dirname); | ||
| 234 | } | ||
src-self-hosted/main.zig+40-25| ... | @@ -31,6 +31,7 @@ const usage = | ... | @@ -31,6 +31,7 @@ const usage = |
| 31 | \\ build-exe [source] Create executable from source or object files | 31 | \\ build-exe [source] Create executable from source or object files |
| 32 | \\ build-lib [source] Create library 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 | 33 | \\ build-obj [source] Create object from source or assembly |
| 34 | \\ find-libc Show native libc installation paths | ||
| 34 | \\ fmt [source] Parse file and render in canonical zig format | 35 | \\ fmt [source] Parse file and render in canonical zig format |
| 35 | \\ targets List available compilation targets | 36 | \\ targets List available compilation targets |
| 36 | \\ version Print version number and exit | 37 | \\ version Print version number and exit |
| ... | @@ -81,6 +82,10 @@ pub fn main() !void { | ... | @@ -81,6 +82,10 @@ pub fn main() !void { |
| 81 | .name = "build-obj", | 82 | .name = "build-obj", |
| 82 | .exec = cmdBuildObj, | 83 | .exec = cmdBuildObj, |
| 83 | }, | 84 | }, |
| 85 | Command{ | ||
| 86 | .name = "find-libc", | ||
| 87 | .exec = cmdFindLibc, | ||
| 88 | }, | ||
| 84 | Command{ | 89 | Command{ |
| 85 | .name = "fmt", | 90 | .name = "fmt", |
| 86 | .exec = cmdFmt, | 91 | .exec = cmdFmt, |
| ... | @@ -134,7 +139,6 @@ const usage_build_generic = | ... | @@ -134,7 +139,6 @@ const usage_build_generic = |
| 134 | \\ --cache-dir [path] Override the cache directory | 139 | \\ --cache-dir [path] Override the cache directory |
| 135 | \\ --emit [filetype] Emit a specific file format as compilation output | 140 | \\ --emit [filetype] Emit a specific file format as compilation output |
| 136 | \\ --enable-timing-info Print timing diagnostics | 141 | \\ --enable-timing-info Print timing diagnostics |
| 137 | \\ --libc-include-dir [path] Directory where libc stdlib.h resides | ||
| 138 | \\ --name [name] Override output name | 142 | \\ --name [name] Override output name |
| 139 | \\ --output [file] Override destination path | 143 | \\ --output [file] Override destination path |
| 140 | \\ --output-h [file] Override generated header file path | 144 | \\ --output-h [file] Override generated header file path |
| ... | @@ -165,10 +169,6 @@ const usage_build_generic = | ... | @@ -165,10 +169,6 @@ const usage_build_generic = |
| 165 | \\ --ar-path [path] Set the path to ar | 169 | \\ --ar-path [path] Set the path to ar |
| 166 | \\ --dynamic-linker [path] Set the path to ld.so | 170 | \\ --dynamic-linker [path] Set the path to ld.so |
| 167 | \\ --each-lib-rpath Add rpath for each used dynamic library | 171 | \\ --each-lib-rpath Add rpath for each used dynamic library |
| 168 | \\ --libc-lib-dir [path] Directory where libc crt1.o resides | ||
| 169 | \\ --libc-static-lib-dir [path] Directory where libc crtbegin.o resides | ||
| 170 | \\ --msvc-lib-dir [path] (windows) directory where vcruntime.lib resides | ||
| 171 | \\ --kernel32-lib-dir [path] (windows) directory where kernel32.lib resides | ||
| 172 | \\ --library [lib] Link against lib | 172 | \\ --library [lib] Link against lib |
| 173 | \\ --forbid-library [lib] Make it an error to link against lib | 173 | \\ --forbid-library [lib] Make it an error to link against lib |
| 174 | \\ --library-path [dir] Add a directory to the library search path | 174 | \\ --library-path [dir] Add a directory to the library search path |
| ... | @@ -210,7 +210,6 @@ const args_build_generic = []Flag{ | ... | @@ -210,7 +210,6 @@ const args_build_generic = []Flag{ |
| 210 | "llvm-ir", | 210 | "llvm-ir", |
| 211 | }), | 211 | }), |
| 212 | Flag.Bool("--enable-timing-info"), | 212 | Flag.Bool("--enable-timing-info"), |
| 213 | Flag.Arg1("--libc-include-dir"), | ||
| 214 | Flag.Arg1("--name"), | 213 | Flag.Arg1("--name"), |
| 215 | Flag.Arg1("--output"), | 214 | Flag.Arg1("--output"), |
| 216 | Flag.Arg1("--output-h"), | 215 | Flag.Arg1("--output-h"), |
| ... | @@ -236,10 +235,6 @@ const args_build_generic = []Flag{ | ... | @@ -236,10 +235,6 @@ const args_build_generic = []Flag{ |
| 236 | Flag.Arg1("--ar-path"), | 235 | Flag.Arg1("--ar-path"), |
| 237 | Flag.Arg1("--dynamic-linker"), | 236 | Flag.Arg1("--dynamic-linker"), |
| 238 | Flag.Bool("--each-lib-rpath"), | 237 | Flag.Bool("--each-lib-rpath"), |
| 239 | Flag.Arg1("--libc-lib-dir"), | ||
| 240 | Flag.Arg1("--libc-static-lib-dir"), | ||
| 241 | Flag.Arg1("--msvc-lib-dir"), | ||
| 242 | Flag.Arg1("--kernel32-lib-dir"), | ||
| 243 | Flag.ArgMergeN("--library", 1), | 238 | Flag.ArgMergeN("--library", 1), |
| 244 | Flag.ArgMergeN("--forbid-library", 1), | 239 | Flag.ArgMergeN("--forbid-library", 1), |
| 245 | Flag.ArgMergeN("--library-path", 1), | 240 | Flag.ArgMergeN("--library-path", 1), |
| ... | @@ -430,21 +425,6 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co | ... | @@ -430,21 +425,6 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co |
| 430 | 425 | ||
| 431 | comp.strip = flags.present("strip"); | 426 | comp.strip = flags.present("strip"); |
| 432 | 427 | ||
| 433 | if (flags.single("libc-lib-dir")) |libc_lib_dir| { | ||
| 434 | comp.libc_lib_dir = libc_lib_dir; | ||
| 435 | } | ||
| 436 | if (flags.single("libc-static-lib-dir")) |libc_static_lib_dir| { | ||
| 437 | comp.libc_static_lib_dir = libc_static_lib_dir; | ||
| 438 | } | ||
| 439 | if (flags.single("libc-include-dir")) |libc_include_dir| { | ||
| 440 | comp.libc_include_dir = libc_include_dir; | ||
| 441 | } | ||
| 442 | if (flags.single("msvc-lib-dir")) |msvc_lib_dir| { | ||
| 443 | comp.msvc_lib_dir = msvc_lib_dir; | ||
| 444 | } | ||
| 445 | if (flags.single("kernel32-lib-dir")) |kernel32_lib_dir| { | ||
| 446 | comp.kernel32_lib_dir = kernel32_lib_dir; | ||
| 447 | } | ||
| 448 | if (flags.single("dynamic-linker")) |dynamic_linker| { | 428 | if (flags.single("dynamic-linker")) |dynamic_linker| { |
| 449 | comp.dynamic_linker = dynamic_linker; | 429 | comp.dynamic_linker = dynamic_linker; |
| 450 | } | 430 | } |
| ... | @@ -579,6 +559,41 @@ const Fmt = struct { | ... | @@ -579,6 +559,41 @@ const Fmt = struct { |
| 579 | } | 559 | } |
| 580 | }; | 560 | }; |
| 581 | 561 | ||
| 562 | fn cmdFindLibc(allocator: *Allocator, args: []const []const u8) !void { | ||
| 563 | var loop: event.Loop = undefined; | ||
| 564 | try loop.initMultiThreaded(allocator); | ||
| 565 | defer loop.deinit(); | ||
| 566 | |||
| 567 | var event_loop_local = try EventLoopLocal.init(&loop); | ||
| 568 | defer event_loop_local.deinit(); | ||
| 569 | |||
| 570 | const handle = try async<loop.allocator> findLibCAsync(&event_loop_local); | ||
| 571 | defer cancel handle; | ||
| 572 | |||
| 573 | loop.run(); | ||
| 574 | } | ||
| 575 | |||
| 576 | async fn findLibCAsync(event_loop_local: *EventLoopLocal) void { | ||
| 577 | const libc = (await (async event_loop_local.getNativeLibC() catch unreachable)) catch |err| { | ||
| 578 | stderr.print("unable to find libc: {}\n", @errorName(err)) catch os.exit(1); | ||
| 579 | os.exit(1); | ||
| 580 | }; | ||
| 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); | ||
| 595 | } | ||
| 596 | |||
| 582 | fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void { | 597 | fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void { |
| 583 | var flags = try Args.parse(allocator, args_fmt_spec, args); | 598 | var flags = try Args.parse(allocator, args_fmt_spec, args); |
| 584 | defer flags.deinit(); | 599 | defer flags.deinit(); |
std/fmt/index.zig+6-2| ... | @@ -785,11 +785,15 @@ pub fn bufPrint(buf: []u8, comptime fmt: []const u8, args: ...) ![]u8 { | ... | @@ -785,11 +785,15 @@ pub fn bufPrint(buf: []u8, comptime fmt: []const u8, args: ...) ![]u8 { |
| 785 | return buf[0 .. buf.len - context.remaining.len]; | 785 | return buf[0 .. buf.len - context.remaining.len]; |
| 786 | } | 786 | } |
| 787 | 787 | ||
| 788 | pub fn allocPrint(allocator: *mem.Allocator, comptime fmt: []const u8, args: ...) ![]u8 { | 788 | pub const AllocPrintError = error{OutOfMemory}; |
| 789 | |||
| 790 | pub fn allocPrint(allocator: *mem.Allocator, comptime fmt: []const u8, args: ...) AllocPrintError![]u8 { | ||
| 789 | var size: usize = 0; | 791 | var size: usize = 0; |
| 790 | format(&size, error{}, countSize, fmt, args) catch |err| switch (err) {}; | 792 | format(&size, error{}, countSize, fmt, args) catch |err| switch (err) {}; |
| 791 | const buf = try allocator.alloc(u8, size); | 793 | const buf = try allocator.alloc(u8, size); |
| 792 | return bufPrint(buf, fmt, args); | 794 | return bufPrint(buf, fmt, args) catch |err| switch (err) { |
| 795 | error.BufferTooSmall => unreachable, // we just counted the size above | ||
| 796 | }; | ||
| 793 | } | 797 | } |
| 794 | 798 | ||
| 795 | fn countSize(size: *usize, bytes: []const u8) (error{}!void) { | 799 | fn countSize(size: *usize, bytes: []const u8) (error{}!void) { |
std/os/file.zig+21-24| ... | @@ -109,43 +109,40 @@ pub const File = struct { | ... | @@ -109,43 +109,40 @@ pub const File = struct { |
| 109 | Unexpected, | 109 | Unexpected, |
| 110 | }; | 110 | }; |
| 111 | 111 | ||
| 112 | pub fn access(allocator: *mem.Allocator, path: []const u8, file_mode: os.FileMode) AccessError!bool { | 112 | pub fn access(allocator: *mem.Allocator, path: []const u8) AccessError!void { |
| 113 | const path_with_null = try std.cstr.addNullByte(allocator, path); | 113 | const path_with_null = try std.cstr.addNullByte(allocator, path); |
| 114 | defer allocator.free(path_with_null); | 114 | defer allocator.free(path_with_null); |
| 115 | 115 | ||
| 116 | if (is_posix) { | 116 | if (is_posix) { |
| 117 | // mode is ignored and is always F_OK for now | ||
| 118 | const result = posix.access(path_with_null.ptr, posix.F_OK); | 117 | const result = posix.access(path_with_null.ptr, posix.F_OK); |
| 119 | const err = posix.getErrno(result); | 118 | const err = posix.getErrno(result); |
| 120 | if (err > 0) { | 119 | switch (err) { |
| 121 | return switch (err) { | 120 | 0 => return, |
| 122 | posix.EACCES => error.PermissionDenied, | 121 | posix.EACCES => return error.PermissionDenied, |
| 123 | posix.EROFS => error.PermissionDenied, | 122 | posix.EROFS => return error.PermissionDenied, |
| 124 | posix.ELOOP => error.PermissionDenied, | 123 | posix.ELOOP => return error.PermissionDenied, |
| 125 | posix.ETXTBSY => error.PermissionDenied, | 124 | posix.ETXTBSY => return error.PermissionDenied, |
| 126 | posix.ENOTDIR => error.NotFound, | 125 | posix.ENOTDIR => return error.NotFound, |
| 127 | posix.ENOENT => error.NotFound, | 126 | posix.ENOENT => return error.NotFound, |
| 128 | 127 | ||
| 129 | posix.ENAMETOOLONG => error.NameTooLong, | 128 | posix.ENAMETOOLONG => return error.NameTooLong, |
| 130 | posix.EINVAL => error.BadMode, | 129 | posix.EINVAL => unreachable, |
| 131 | posix.EFAULT => error.BadPathName, | 130 | posix.EFAULT => return error.BadPathName, |
| 132 | posix.EIO => error.Io, | 131 | posix.EIO => return error.Io, |
| 133 | posix.ENOMEM => error.SystemResources, | 132 | posix.ENOMEM => return error.SystemResources, |
| 134 | else => os.unexpectedErrorPosix(err), | 133 | else => return os.unexpectedErrorPosix(err), |
| 135 | }; | ||
| 136 | } | 134 | } |
| 137 | return true; | ||
| 138 | } else if (is_windows) { | 135 | } else if (is_windows) { |
| 139 | if (os.windows.GetFileAttributesA(path_with_null.ptr) != os.windows.INVALID_FILE_ATTRIBUTES) { | 136 | if (os.windows.GetFileAttributesA(path_with_null.ptr) != os.windows.INVALID_FILE_ATTRIBUTES) { |
| 140 | return true; | 137 | return; |
| 141 | } | 138 | } |
| 142 | 139 | ||
| 143 | const err = windows.GetLastError(); | 140 | const err = windows.GetLastError(); |
| 144 | return switch (err) { | 141 | switch (err) { |
| 145 | windows.ERROR.FILE_NOT_FOUND => error.NotFound, | 142 | windows.ERROR.FILE_NOT_FOUND => return error.NotFound, |
| 146 | windows.ERROR.ACCESS_DENIED => error.PermissionDenied, | 143 | windows.ERROR.ACCESS_DENIED => return error.PermissionDenied, |
| 147 | else => os.unexpectedErrorWindows(err), | 144 | else => return os.unexpectedErrorWindows(err), |
| 148 | }; | 145 | } |
| 149 | } else { | 146 | } else { |
| 150 | @compileError("TODO implement access for this OS"); | 147 | @compileError("TODO implement access for this OS"); |
| 151 | } | 148 | } |