| author | |
| committer | |
| log | 78f26b970e1c5c288e45d0edd2ab2f229e6fe924 |
| tree | 8233f52a95ffba1b92661ea5d3bdf989c00950ff |
| parent | 535d5624e48e31752729d00c469aca504cf50091 |
| parent | f8dc6fc416d27bc6d93d79689823a4278aacd5b2 |
| signature |
stage2: Move `selfExePathWasi` to `introspect.zig`5 files changed, 52 insertions(+), 53 deletions(-)
lib/std/fs.zig-46| ... | @@ -2547,15 +2547,6 @@ pub const SelfExePathError = os.ReadLinkError || os.SysCtlError || os.RealPathEr | ... | @@ -2547,15 +2547,6 @@ pub const SelfExePathError = os.ReadLinkError || os.SysCtlError || os.RealPathEr |
| 2547 | /// `selfExePath` except allocates the result on the heap. | 2547 | /// `selfExePath` except allocates the result on the heap. |
| 2548 | /// Caller owns returned memory. | 2548 | /// Caller owns returned memory. |
| 2549 | pub fn selfExePathAlloc(allocator: Allocator) ![]u8 { | 2549 | pub fn selfExePathAlloc(allocator: Allocator) ![]u8 { |
| 2550 | if (builtin.os.tag == .wasi) { | ||
| 2551 | var args = try std.process.argsWithAllocator(allocator); | ||
| 2552 | defer args.deinit(); | ||
| 2553 | // On WASI, argv[0] is always just the basename of the current executable | ||
| 2554 | const exe_name = args.next() orelse return error.FileNotFound; | ||
| 2555 | |||
| 2556 | var buf: [MAX_PATH_BYTES]u8 = undefined; | ||
| 2557 | return allocator.dupe(u8, try selfExePathWasi(&buf, exe_name)); | ||
| 2558 | } | ||
| 2559 | // Use of MAX_PATH_BYTES here is justified as, at least on one tested Linux | 2550 | // Use of MAX_PATH_BYTES here is justified as, at least on one tested Linux |
| 2560 | // system, readlink will completely fail to return a result larger than | 2551 | // system, readlink will completely fail to return a result larger than |
| 2561 | // PATH_MAX even if given a sufficiently large buffer. This makes it | 2552 | // PATH_MAX even if given a sufficiently large buffer. This makes it |
| ... | @@ -2657,43 +2648,6 @@ pub fn selfExePath(out_buffer: []u8) SelfExePathError![]u8 { | ... | @@ -2657,43 +2648,6 @@ pub fn selfExePath(out_buffer: []u8) SelfExePathError![]u8 { |
| 2657 | } | 2648 | } |
| 2658 | } | 2649 | } |
| 2659 | 2650 | ||
| 2660 | /// WASI-specific implementation of selfExePath | ||
| 2661 | /// | ||
| 2662 | /// On WASI argv0 is always just the executable basename, so this function relies | ||
| 2663 | /// using a fixed executable directory path: "/zig" | ||
| 2664 | /// | ||
| 2665 | /// This path can be configured in wasmtime using `--mapdir=/zig::/path/to/zig/dir/` | ||
| 2666 | fn selfExePathWasi(out_buffer: []u8, argv0: []const u8) SelfExePathError![]const u8 { | ||
| 2667 | var allocator = std.heap.FixedBufferAllocator.init(out_buffer); | ||
| 2668 | var alloc = allocator.allocator(); | ||
| 2669 | |||
| 2670 | // Check these paths: | ||
| 2671 | // 1. "/zig/{exe_name}" | ||
| 2672 | // 2. "/zig/bin/{exe_name}" | ||
| 2673 | const base_paths_to_check = &[_][]const u8{ "/zig", "/zig/bin" }; | ||
| 2674 | const exe_names_to_check = &[_][]const u8{ path.basename(argv0), "zig.wasm" }; | ||
| 2675 | |||
| 2676 | for (base_paths_to_check) |base_path| { | ||
| 2677 | for (exe_names_to_check) |exe_name| { | ||
| 2678 | const test_path = path.join(alloc, &.{ base_path, exe_name }) catch continue; | ||
| 2679 | |||
| 2680 | // Make sure it's a file we're pointing to | ||
| 2681 | const file = os.fstatat(os.wasi.AT.FDCWD, test_path, 0) catch continue; | ||
| 2682 | if (file.filetype != .REGULAR_FILE) continue; | ||
| 2683 | |||
| 2684 | // Path seems to be valid, let's try to turn it into an absolute path | ||
| 2685 | var real_path_buf: [MAX_PATH_BYTES]u8 = undefined; | ||
| 2686 | if (os.realpath(test_path, &real_path_buf)) |real_path| { | ||
| 2687 | if (real_path.len > out_buffer.len) | ||
| 2688 | return error.NameTooLong; | ||
| 2689 | mem.copy(u8, out_buffer, real_path); | ||
| 2690 | return out_buffer[0..real_path.len]; | ||
| 2691 | } else |_| continue; | ||
| 2692 | } | ||
| 2693 | } | ||
| 2694 | return error.FileNotFound; | ||
| 2695 | } | ||
| 2696 | |||
| 2697 | /// The result is UTF16LE-encoded. | 2651 | /// The result is UTF16LE-encoded. |
| 2698 | pub fn selfExePathW() [:0]const u16 { | 2652 | pub fn selfExePathW() [:0]const u16 { |
| 2699 | const image_path_name = &os.windows.peb().ProcessParameters.ImagePathName; | 2653 | const image_path_name = &os.windows.peb().ProcessParameters.ImagePathName; |
src/Cache.zig+10-2| ... | @@ -762,7 +762,11 @@ pub const Manifest = struct { | ... | @@ -762,7 +762,11 @@ pub const Manifest = struct { |
| 762 | 762 | ||
| 763 | fn downgradeToSharedLock(self: *Manifest) !void { | 763 | fn downgradeToSharedLock(self: *Manifest) !void { |
| 764 | if (!self.have_exclusive_lock) return; | 764 | if (!self.have_exclusive_lock) return; |
| 765 | if (std.process.can_spawn or !builtin.single_threaded) { // Some targets (WASI) do not support flock | 765 | |
| 766 | // WASI does not currently support flock, so we bypass it here. | ||
| 767 | // TODO: If/when flock is supported on WASI, this check should be removed. | ||
| 768 | // See https://github.com/WebAssembly/wasi-filesystem/issues/2 | ||
| 769 | if (builtin.os.tag != .wasi or std.process.can_spawn or !builtin.single_threaded) { | ||
| 766 | const manifest_file = self.manifest_file.?; | 770 | const manifest_file = self.manifest_file.?; |
| 767 | try manifest_file.downgradeLock(); | 771 | try manifest_file.downgradeLock(); |
| 768 | } | 772 | } |
| ... | @@ -771,7 +775,11 @@ pub const Manifest = struct { | ... | @@ -771,7 +775,11 @@ pub const Manifest = struct { |
| 771 | 775 | ||
| 772 | fn upgradeToExclusiveLock(self: *Manifest) !void { | 776 | fn upgradeToExclusiveLock(self: *Manifest) !void { |
| 773 | if (self.have_exclusive_lock) return; | 777 | if (self.have_exclusive_lock) return; |
| 774 | if (std.process.can_spawn or !builtin.single_threaded) { // Some targets (WASI) do not support flock | 778 | |
| 779 | // WASI does not currently support flock, so we bypass it here. | ||
| 780 | // TODO: If/when flock is supported on WASI, this check should be removed. | ||
| 781 | // See https://github.com/WebAssembly/wasi-filesystem/issues/2 | ||
| 782 | if (builtin.os.tag != .wasi or std.process.can_spawn or !builtin.single_threaded) { | ||
| 775 | const manifest_file = self.manifest_file.?; | 783 | const manifest_file = self.manifest_file.?; |
| 776 | // Here we intentionally have a period where the lock is released, in case there are | 784 | // Here we intentionally have a period where the lock is released, in case there are |
| 777 | // other processes holding a shared lock. | 785 | // other processes holding a shared lock. |
src/introspect.zig+38-1| ... | @@ -33,9 +33,46 @@ fn testZigInstallPrefix(base_dir: fs.Dir) ?Compilation.Directory { | ... | @@ -33,9 +33,46 @@ fn testZigInstallPrefix(base_dir: fs.Dir) ?Compilation.Directory { |
| 33 | return Compilation.Directory{ .handle = test_zig_dir, .path = "lib" }; | 33 | return Compilation.Directory{ .handle = test_zig_dir, .path = "lib" }; |
| 34 | } | 34 | } |
| 35 | 35 | ||
| 36 | /// This is a small wrapper around selfExePathAlloc that adds support for WASI | ||
| 37 | /// based on a hard-coded Preopen directory ("/zig") | ||
| 38 | pub fn findZigExePath(allocator: mem.Allocator) ![]u8 { | ||
| 39 | if (builtin.os.tag == .wasi) { | ||
| 40 | var args = try std.process.argsWithAllocator(allocator); | ||
| 41 | defer args.deinit(); | ||
| 42 | // On WASI, argv[0] is always just the basename of the current executable | ||
| 43 | const argv0 = args.next() orelse return error.FileNotFound; | ||
| 44 | |||
| 45 | // Check these paths: | ||
| 46 | // 1. "/zig/{exe_name}" | ||
| 47 | // 2. "/zig/bin/{exe_name}" | ||
| 48 | const base_paths_to_check = &[_][]const u8{ "/zig", "/zig/bin" }; | ||
| 49 | const exe_names_to_check = &[_][]const u8{ fs.path.basename(argv0), "zig.wasm" }; | ||
| 50 | |||
| 51 | for (base_paths_to_check) |base_path| { | ||
| 52 | for (exe_names_to_check) |exe_name| { | ||
| 53 | const test_path = fs.path.join(allocator, &.{ base_path, exe_name }) catch continue; | ||
| 54 | defer allocator.free(test_path); | ||
| 55 | |||
| 56 | // Make sure it's a file we're pointing to | ||
| 57 | const file = os.fstatat(os.wasi.AT.FDCWD, test_path, 0) catch continue; | ||
| 58 | if (file.filetype != .REGULAR_FILE) continue; | ||
| 59 | |||
| 60 | // Path seems to be valid, let's try to turn it into an absolute path | ||
| 61 | var real_path_buf: [fs.MAX_PATH_BYTES]u8 = undefined; | ||
| 62 | if (os.realpath(test_path, &real_path_buf)) |real_path| { | ||
| 63 | return allocator.dupe(u8, real_path); // Success: return absolute path | ||
| 64 | } else |_| continue; | ||
| 65 | } | ||
| 66 | } | ||
| 67 | return error.FileNotFound; | ||
| 68 | } | ||
| 69 | |||
| 70 | return fs.selfExePathAlloc(allocator); | ||
| 71 | } | ||
| 72 | |||
| 36 | /// Both the directory handle and the path are newly allocated resources which the caller now owns. | 73 | /// Both the directory handle and the path are newly allocated resources which the caller now owns. |
| 37 | pub fn findZigLibDir(gpa: mem.Allocator) !Compilation.Directory { | 74 | pub fn findZigLibDir(gpa: mem.Allocator) !Compilation.Directory { |
| 38 | const self_exe_path = try fs.selfExePathAlloc(gpa); | 75 | const self_exe_path = try findZigExePath(gpa); |
| 39 | defer gpa.free(self_exe_path); | 76 | defer gpa.free(self_exe_path); |
| 40 | 77 | ||
| 41 | return findZigLibDirFromSelfExe(gpa, self_exe_path); | 78 | return findZigLibDirFromSelfExe(gpa, self_exe_path); |
src/main.zig+3-3| ... | @@ -2526,7 +2526,7 @@ fn buildOutputType( | ... | @@ -2526,7 +2526,7 @@ fn buildOutputType( |
| 2526 | pkg_tree_root.table = .{}; | 2526 | pkg_tree_root.table = .{}; |
| 2527 | } | 2527 | } |
| 2528 | 2528 | ||
| 2529 | const self_exe_path = try fs.selfExePathAlloc(arena); | 2529 | const self_exe_path = try introspect.findZigExePath(arena); |
| 2530 | var zig_lib_directory: Compilation.Directory = if (override_lib_dir) |lib_dir| .{ | 2530 | var zig_lib_directory: Compilation.Directory = if (override_lib_dir) |lib_dir| .{ |
| 2531 | .path = lib_dir, | 2531 | .path = lib_dir, |
| 2532 | .handle = fs.cwd().openDir(lib_dir, .{}) catch |err| { | 2532 | .handle = fs.cwd().openDir(lib_dir, .{}) catch |err| { |
| ... | @@ -3395,7 +3395,7 @@ pub fn cmdInit( | ... | @@ -3395,7 +3395,7 @@ pub fn cmdInit( |
| 3395 | } | 3395 | } |
| 3396 | } | 3396 | } |
| 3397 | } | 3397 | } |
| 3398 | const self_exe_path = try fs.selfExePathAlloc(arena); | 3398 | const self_exe_path = try introspect.findZigExePath(arena); |
| 3399 | var zig_lib_directory = introspect.findZigLibDirFromSelfExe(arena, self_exe_path) catch |err| { | 3399 | var zig_lib_directory = introspect.findZigLibDirFromSelfExe(arena, self_exe_path) catch |err| { |
| 3400 | fatal("unable to find zig installation directory: {s}\n", .{@errorName(err)}); | 3400 | fatal("unable to find zig installation directory: {s}\n", .{@errorName(err)}); |
| 3401 | }; | 3401 | }; |
| ... | @@ -3475,7 +3475,7 @@ pub fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi | ... | @@ -3475,7 +3475,7 @@ pub fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi |
| 3475 | // We want to release all the locks before executing the child process, so we make a nice | 3475 | // We want to release all the locks before executing the child process, so we make a nice |
| 3476 | // big block here to ensure the cleanup gets run when we extract out our argv. | 3476 | // big block here to ensure the cleanup gets run when we extract out our argv. |
| 3477 | const child_argv = argv: { | 3477 | const child_argv = argv: { |
| 3478 | const self_exe_path = try fs.selfExePathAlloc(arena); | 3478 | const self_exe_path = try introspect.findZigExePath(arena); |
| 3479 | 3479 | ||
| 3480 | var build_file: ?[]const u8 = null; | 3480 | var build_file: ?[]const u8 = null; |
| 3481 | var override_lib_dir: ?[]const u8 = null; | 3481 | var override_lib_dir: ?[]const u8 = null; |
src/print_env.zig+1-1| ... | @@ -6,7 +6,7 @@ const fatal = @import("main.zig").fatal; | ... | @@ -6,7 +6,7 @@ const fatal = @import("main.zig").fatal; |
| 6 | 6 | ||
| 7 | pub fn cmdEnv(gpa: Allocator, args: []const []const u8, stdout: std.fs.File.Writer) !void { | 7 | pub fn cmdEnv(gpa: Allocator, args: []const []const u8, stdout: std.fs.File.Writer) !void { |
| 8 | _ = args; | 8 | _ = args; |
| 9 | const self_exe_path = try std.fs.selfExePathAlloc(gpa); | 9 | const self_exe_path = try introspect.findZigExePath(gpa); |
| 10 | defer gpa.free(self_exe_path); | 10 | defer gpa.free(self_exe_path); |
| 11 | 11 | ||
| 12 | var zig_lib_directory = introspect.findZigLibDirFromSelfExe(gpa, self_exe_path) catch |err| { | 12 | var zig_lib_directory = introspect.findZigLibDirFromSelfExe(gpa, self_exe_path) catch |err| { |