| 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 | 28 | const codegen = @import("codegen.zig"); |
| 29 | 29 | const Package = @import("package.zig").Package; |
| 30 | 30 | const link = @import("link.zig").link; |
| 31 | const LibCInstallation = @import("libc_installation.zig").LibCInstallation; | |
| 31 | 32 | |
| 32 | 33 | /// Data that is local to the event loop. |
| 33 | 34 | pub const EventLoopLocal = struct { |
| ... | ... | @@ -37,6 +38,8 @@ pub const EventLoopLocal = struct { |
| 37 | 38 | /// TODO pool these so that it doesn't have to lock |
| 38 | 39 | prng: event.Locked(std.rand.DefaultPrng), |
| 39 | 40 | |
| 41 | native_libc: event.Future(LibCInstallation), | |
| 42 | ||
| 40 | 43 | var lazy_init_targets = std.lazyInit(void); |
| 41 | 44 | |
| 42 | 45 | fn init(loop: *event.Loop) !EventLoopLocal { |
| ... | ... | @@ -52,6 +55,7 @@ pub const EventLoopLocal = struct { |
| 52 | 55 | .loop = loop, |
| 53 | 56 | .llvm_handle_pool = std.atomic.Stack(llvm.ContextRef).init(), |
| 54 | 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 | 82 | |
| 79 | 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 | 94 | pub const LlvmHandle = struct { |
| ... | ... | @@ -109,11 +120,6 @@ pub const Compilation = struct { |
| 109 | 120 | |
| 110 | 121 | linker_script: ?[]const u8, |
| 111 | 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 | 123 | dynamic_linker: ?[]const u8, |
| 118 | 124 | out_h_path: ?[]const u8, |
| 119 | 125 | |
| ... | ... | @@ -318,11 +324,6 @@ pub const Compilation = struct { |
| 318 | 324 | .verbose_link = false, |
| 319 | 325 | |
| 320 | 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 | 327 | .dynamic_linker = null, |
| 327 | 328 | .out_h_path = null, |
| 328 | 329 | .is_test = false, |
| ... | ... | @@ -762,10 +763,24 @@ pub const Compilation = struct { |
| 762 | 763 | try self.link_libs_list.append(link_lib); |
| 763 | 764 | if (is_libc) { |
| 764 | 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 | 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 | 784 | /// General Purpose Allocator. Must free when done. |
| 770 | 785 | fn gpa(self: Compilation) *mem.Allocator { |
| 771 | 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 | 31 | \\ build-exe [source] Create executable from source or object files |
| 32 | 32 | \\ build-lib [source] Create library from source or object files |
| 33 | 33 | \\ build-obj [source] Create object from source or assembly |
| 34 | \\ find-libc Show native libc installation paths | |
| 34 | 35 | \\ fmt [source] Parse file and render in canonical zig format |
| 35 | 36 | \\ targets List available compilation targets |
| 36 | 37 | \\ version Print version number and exit |
| ... | ... | @@ -81,6 +82,10 @@ pub fn main() !void { |
| 81 | 82 | .name = "build-obj", |
| 82 | 83 | .exec = cmdBuildObj, |
| 83 | 84 | }, |
| 85 | Command{ | |
| 86 | .name = "find-libc", | |
| 87 | .exec = cmdFindLibc, | |
| 88 | }, | |
| 84 | 89 | Command{ |
| 85 | 90 | .name = "fmt", |
| 86 | 91 | .exec = cmdFmt, |
| ... | ... | @@ -134,7 +139,6 @@ const usage_build_generic = |
| 134 | 139 | \\ --cache-dir [path] Override the cache directory |
| 135 | 140 | \\ --emit [filetype] Emit a specific file format as compilation output |
| 136 | 141 | \\ --enable-timing-info Print timing diagnostics |
| 137 | \\ --libc-include-dir [path] Directory where libc stdlib.h resides | |
| 138 | 142 | \\ --name [name] Override output name |
| 139 | 143 | \\ --output [file] Override destination path |
| 140 | 144 | \\ --output-h [file] Override generated header file path |
| ... | ... | @@ -165,10 +169,6 @@ const usage_build_generic = |
| 165 | 169 | \\ --ar-path [path] Set the path to ar |
| 166 | 170 | \\ --dynamic-linker [path] Set the path to ld.so |
| 167 | 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 | 172 | \\ --library [lib] Link against lib |
| 173 | 173 | \\ --forbid-library [lib] Make it an error to link against lib |
| 174 | 174 | \\ --library-path [dir] Add a directory to the library search path |
| ... | ... | @@ -210,7 +210,6 @@ const args_build_generic = []Flag{ |
| 210 | 210 | "llvm-ir", |
| 211 | 211 | }), |
| 212 | 212 | Flag.Bool("--enable-timing-info"), |
| 213 | Flag.Arg1("--libc-include-dir"), | |
| 214 | 213 | Flag.Arg1("--name"), |
| 215 | 214 | Flag.Arg1("--output"), |
| 216 | 215 | Flag.Arg1("--output-h"), |
| ... | ... | @@ -236,10 +235,6 @@ const args_build_generic = []Flag{ |
| 236 | 235 | Flag.Arg1("--ar-path"), |
| 237 | 236 | Flag.Arg1("--dynamic-linker"), |
| 238 | 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 | 238 | Flag.ArgMergeN("--library", 1), |
| 244 | 239 | Flag.ArgMergeN("--forbid-library", 1), |
| 245 | 240 | Flag.ArgMergeN("--library-path", 1), |
| ... | ... | @@ -430,21 +425,6 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co |
| 430 | 425 | |
| 431 | 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 | 428 | if (flags.single("dynamic-linker")) |dynamic_linker| { |
| 449 | 429 | comp.dynamic_linker = dynamic_linker; |
| 450 | 430 | } |
| ... | ... | @@ -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 | 597 | fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void { |
| 583 | 598 | var flags = try Args.parse(allocator, args_fmt_spec, args); |
| 584 | 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 | 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 | 791 | var size: usize = 0; |
| 790 | 792 | format(&size, error{}, countSize, fmt, args) catch |err| switch (err) {}; |
| 791 | 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 | 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 | 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 | 113 | const path_with_null = try std.cstr.addNullByte(allocator, path); |
| 114 | 114 | defer allocator.free(path_with_null); |
| 115 | 115 | |
| 116 | 116 | if (is_posix) { |
| 117 | // mode is ignored and is always F_OK for now | |
| 118 | 117 | const result = posix.access(path_with_null.ptr, posix.F_OK); |
| 119 | 118 | const err = posix.getErrno(result); |
| 120 | if (err > 0) { | |
| 121 | return switch (err) { | |
| 122 | posix.EACCES => error.PermissionDenied, | |
| 123 | posix.EROFS => error.PermissionDenied, | |
| 124 | posix.ELOOP => error.PermissionDenied, | |
| 125 | posix.ETXTBSY => error.PermissionDenied, | |
| 126 | posix.ENOTDIR => error.NotFound, | |
| 127 | posix.ENOENT => error.NotFound, | |
| 119 | switch (err) { | |
| 120 | 0 => return, | |
| 121 | posix.EACCES => return error.PermissionDenied, | |
| 122 | posix.EROFS => return error.PermissionDenied, | |
| 123 | posix.ELOOP => return error.PermissionDenied, | |
| 124 | posix.ETXTBSY => return error.PermissionDenied, | |
| 125 | posix.ENOTDIR => return error.NotFound, | |
| 126 | posix.ENOENT => return error.NotFound, | |
| 128 | 127 | |
| 129 | posix.ENAMETOOLONG => error.NameTooLong, | |
| 130 | posix.EINVAL => error.BadMode, | |
| 131 | posix.EFAULT => error.BadPathName, | |
| 132 | posix.EIO => error.Io, | |
| 133 | posix.ENOMEM => error.SystemResources, | |
| 134 | else => os.unexpectedErrorPosix(err), | |
| 135 | }; | |
| 128 | posix.ENAMETOOLONG => return error.NameTooLong, | |
| 129 | posix.EINVAL => unreachable, | |
| 130 | posix.EFAULT => return error.BadPathName, | |
| 131 | posix.EIO => return error.Io, | |
| 132 | posix.ENOMEM => return error.SystemResources, | |
| 133 | else => return os.unexpectedErrorPosix(err), | |
| 136 | 134 | } |
| 137 | return true; | |
| 138 | 135 | } else if (is_windows) { |
| 139 | 136 | if (os.windows.GetFileAttributesA(path_with_null.ptr) != os.windows.INVALID_FILE_ATTRIBUTES) { |
| 140 | return true; | |
| 137 | return; | |
| 141 | 138 | } |
| 142 | 139 | |
| 143 | 140 | const err = windows.GetLastError(); |
| 144 | return switch (err) { | |
| 145 | windows.ERROR.FILE_NOT_FOUND => error.NotFound, | |
| 146 | windows.ERROR.ACCESS_DENIED => error.PermissionDenied, | |
| 147 | else => os.unexpectedErrorWindows(err), | |
| 148 | }; | |
| 141 | switch (err) { | |
| 142 | windows.ERROR.FILE_NOT_FOUND => return error.NotFound, | |
| 143 | windows.ERROR.ACCESS_DENIED => return error.PermissionDenied, | |
| 144 | else => return os.unexpectedErrorWindows(err), | |
| 145 | } | |
| 149 | 146 | } else { |
| 150 | 147 | @compileError("TODO implement access for this OS"); |
| 151 | 148 | } |