Commit 0cd89e9176
Changed files (3)
lib
std
src-self-hosted
lib/std/os.zig
@@ -955,6 +955,7 @@ pub const Arg0Expand = enum {
/// Like `execvpeZ` except if `arg0_expand` is `.expand`, then `argv` is mutable,
/// and `argv[0]` is expanded to be the same absolute path that is passed to the execve syscall.
+/// If this function returns with an error, `argv[0]` will be restored to the value it was when it was passed in.
pub fn execvpeZ_expandArg0(
comptime arg0_expand: Arg0Expand,
file: [*:0]const u8,
@@ -972,6 +973,14 @@ pub fn execvpeZ_expandArg0(
var it = mem.tokenize(PATH, ":");
var seen_eacces = false;
var err: ExecveError = undefined;
+
+ // In case of expanding arg0 we must put it back if we return with an error.
+ const prev_arg0 = child_argv[0];
+ defer switch (arg0_expand) {
+ .expand => child_argv[0] = prev_arg0,
+ .no_expand => {},
+ };
+
while (it.next()) |search_path| {
if (path_buf.len < search_path.len + file_slice.len + 1) return error.NameTooLong;
mem.copy(u8, &path_buf, search_path);
src-self-hosted/libc_installation.zig
@@ -174,16 +174,23 @@ pub const LibCInstallation = struct {
});
}
+ pub const FindNativeOptions = struct {
+ allocator: *Allocator,
+
+ /// If enabled, will print human-friendly errors to stderr.
+ verbose: bool = false,
+ };
+
/// Finds the default, native libc.
- pub fn findNative(allocator: *Allocator) FindError!LibCInstallation {
+ pub fn findNative(args: FindNativeOptions) FindError!LibCInstallation {
var self: LibCInstallation = .{};
if (is_windows) {
if (is_gnu) {
var batch = Batch(FindError!void, 3, .auto_async).init();
- batch.add(&async self.findNativeIncludeDirPosix(allocator));
- batch.add(&async self.findNativeCrtDirPosix(allocator));
- batch.add(&async self.findNativeStaticCrtDirPosix(allocator));
+ batch.add(&async self.findNativeIncludeDirPosix(args));
+ batch.add(&async self.findNativeCrtDirPosix(args));
+ batch.add(&async self.findNativeStaticCrtDirPosix(args));
try batch.wait();
} else {
var sdk: *ZigWindowsSDK = undefined;
@@ -192,11 +199,11 @@ pub const LibCInstallation = struct {
defer zig_free_windows_sdk(sdk);
var batch = Batch(FindError!void, 5, .auto_async).init();
- batch.add(&async self.findNativeMsvcIncludeDir(allocator, sdk));
- batch.add(&async self.findNativeMsvcLibDir(allocator, sdk));
- batch.add(&async self.findNativeKernel32LibDir(allocator, sdk));
- batch.add(&async self.findNativeIncludeDirWindows(allocator, sdk));
- batch.add(&async self.findNativeCrtDirWindows(allocator, sdk));
+ batch.add(&async self.findNativeMsvcIncludeDir(args, sdk));
+ batch.add(&async self.findNativeMsvcLibDir(args, sdk));
+ batch.add(&async self.findNativeKernel32LibDir(args, sdk));
+ batch.add(&async self.findNativeIncludeDirWindows(args, sdk));
+ batch.add(&async self.findNativeCrtDirWindows(args, sdk));
try batch.wait();
},
.OutOfMemory => return error.OutOfMemory,
@@ -208,11 +215,11 @@ pub const LibCInstallation = struct {
try blk: {
var batch = Batch(FindError!void, 2, .auto_async).init();
errdefer batch.wait() catch {};
- batch.add(&async self.findNativeIncludeDirPosix(allocator));
+ batch.add(&async self.findNativeIncludeDirPosix(args));
if (is_freebsd or is_netbsd) {
- self.crt_dir = try std.mem.dupeZ(allocator, u8, "/usr/lib");
+ self.crt_dir = try std.mem.dupeZ(args.allocator, u8, "/usr/lib");
} else if (is_linux or is_dragonfly) {
- batch.add(&async self.findNativeCrtDirPosix(allocator));
+ batch.add(&async self.findNativeCrtDirPosix(args));
}
break :blk batch.wait();
};
@@ -231,7 +238,8 @@ pub const LibCInstallation = struct {
self.* = undefined;
}
- fn findNativeIncludeDirPosix(self: *LibCInstallation, allocator: *Allocator) FindError!void {
+ fn findNativeIncludeDirPosix(self: *LibCInstallation, args: FindNativeOptions) FindError!void {
+ const allocator = args.allocator;
const dev_null = if (is_windows) "nul" else "/dev/null";
const cc_exe = std.os.getenvZ("CC") orelse default_cc_exe;
const argv = [_][]const u8{
@@ -252,15 +260,24 @@ pub const LibCInstallation = struct {
.expand_arg0 = .expand,
}) catch |err| switch (err) {
error.OutOfMemory => return error.OutOfMemory,
- else => return error.UnableToSpawnCCompiler,
+ else => {
+ printVerboseInvocation(&argv, null, args.verbose, null);
+ return error.UnableToSpawnCCompiler;
+ },
};
defer {
allocator.free(exec_res.stdout);
allocator.free(exec_res.stderr);
}
switch (exec_res.term) {
- .Exited => |code| if (code != 0) return error.CCompilerExitCode,
- else => return error.CCompilerCrashed,
+ .Exited => |code| if (code != 0) {
+ printVerboseInvocation(&argv, null, args.verbose, exec_res.stderr);
+ return error.CCompilerExitCode;
+ },
+ else => {
+ printVerboseInvocation(&argv, null, args.verbose, exec_res.stderr);
+ return error.CCompilerCrashed;
+ },
}
var it = std.mem.tokenize(exec_res.stderr, "\n\r");
@@ -322,9 +339,11 @@ pub const LibCInstallation = struct {
fn findNativeIncludeDirWindows(
self: *LibCInstallation,
- allocator: *Allocator,
+ args: FindNativeOptions,
sdk: *ZigWindowsSDK,
) FindError!void {
+ const allocator = args.allocator;
+
var search_buf: [2]Search = undefined;
const searches = fillSearch(&search_buf, sdk);
@@ -358,7 +377,13 @@ pub const LibCInstallation = struct {
return error.LibCStdLibHeaderNotFound;
}
- fn findNativeCrtDirWindows(self: *LibCInstallation, allocator: *Allocator, sdk: *ZigWindowsSDK) FindError!void {
+ fn findNativeCrtDirWindows(
+ self: *LibCInstallation,
+ args: FindNativeOptions,
+ sdk: *ZigWindowsSDK,
+ ) FindError!void {
+ const allocator = args.allocator;
+
var search_buf: [2]Search = undefined;
const searches = fillSearch(&search_buf, sdk);
@@ -398,15 +423,31 @@ pub const LibCInstallation = struct {
return error.LibCRuntimeNotFound;
}
- fn findNativeCrtDirPosix(self: *LibCInstallation, allocator: *Allocator) FindError!void {
- self.crt_dir = try ccPrintFileName(allocator, "crt1.o", .only_dir);
+ fn findNativeCrtDirPosix(self: *LibCInstallation, args: FindNativeOptions) FindError!void {
+ self.crt_dir = try ccPrintFileName(.{
+ .allocator = args.allocator,
+ .search_basename = "crt1.o",
+ .want_dirname = .only_dir,
+ .verbose = args.verbose,
+ });
}
- fn findNativeStaticCrtDirPosix(self: *LibCInstallation, allocator: *Allocator) FindError!void {
- self.static_crt_dir = try ccPrintFileName(allocator, "crtbegin.o", .only_dir);
+ fn findNativeStaticCrtDirPosix(self: *LibCInstallation, args: FindNativeOptions) FindError!void {
+ self.static_crt_dir = try ccPrintFileName(.{
+ .allocator = args.allocator,
+ .search_basename = "crtbegin.o",
+ .want_dirname = .only_dir,
+ .verbose = args.verbose,
+ });
}
- fn findNativeKernel32LibDir(self: *LibCInstallation, allocator: *Allocator, sdk: *ZigWindowsSDK) FindError!void {
+ fn findNativeKernel32LibDir(
+ self: *LibCInstallation,
+ args: FindNativeOptions,
+ sdk: *ZigWindowsSDK,
+ ) FindError!void {
+ const allocator = args.allocator;
+
var search_buf: [2]Search = undefined;
const searches = fillSearch(&search_buf, sdk);
@@ -448,9 +489,11 @@ pub const LibCInstallation = struct {
fn findNativeMsvcIncludeDir(
self: *LibCInstallation,
- allocator: *Allocator,
+ args: FindNativeOptions,
sdk: *ZigWindowsSDK,
) FindError!void {
+ const allocator = args.allocator;
+
const msvc_lib_dir_ptr = sdk.msvc_lib_dir_ptr orelse return error.LibCStdLibHeaderNotFound;
const msvc_lib_dir = msvc_lib_dir_ptr[0..sdk.msvc_lib_dir_len];
const up1 = fs.path.dirname(msvc_lib_dir) orelse return error.LibCStdLibHeaderNotFound;
@@ -481,9 +524,10 @@ pub const LibCInstallation = struct {
fn findNativeMsvcLibDir(
self: *LibCInstallation,
- allocator: *Allocator,
+ args: FindNativeOptions,
sdk: *ZigWindowsSDK,
) FindError!void {
+ const allocator = args.allocator;
const msvc_lib_dir_ptr = sdk.msvc_lib_dir_ptr orelse return error.LibCRuntimeNotFound;
self.msvc_lib_dir = try std.mem.dupeZ(allocator, u8, msvc_lib_dir_ptr[0..sdk.msvc_lib_dir_len]);
}
@@ -491,14 +535,19 @@ pub const LibCInstallation = struct {
const default_cc_exe = if (is_windows) "cc.exe" else "cc";
-/// caller owns returned memory
-fn ccPrintFileName(
+pub const CCPrintFileNameOptions = struct {
allocator: *Allocator,
- o_file: []const u8,
+ search_basename: []const u8,
want_dirname: enum { full_path, only_dir },
-) ![:0]u8 {
+ verbose: bool = false,
+};
+
+/// caller owns returned memory
+fn ccPrintFileName(args: CCPrintFileNameOptions) ![:0]u8 {
+ const allocator = args.allocator;
+
const cc_exe = std.os.getenvZ("CC") orelse default_cc_exe;
- const arg1 = try std.fmt.allocPrint(allocator, "-print-file-name={}", .{o_file});
+ const arg1 = try std.fmt.allocPrint(allocator, "-print-file-name={}", .{args.search_basename});
defer allocator.free(arg1);
const argv = [_][]const u8{ cc_exe, arg1 };
@@ -520,16 +569,22 @@ fn ccPrintFileName(
allocator.free(exec_res.stderr);
}
switch (exec_res.term) {
- .Exited => |code| if (code != 0) return error.CCompilerExitCode,
- else => return error.CCompilerCrashed,
+ .Exited => |code| if (code != 0) {
+ printVerboseInvocation(&argv, args.search_basename, args.verbose, exec_res.stderr);
+ return error.CCompilerExitCode;
+ },
+ else => {
+ printVerboseInvocation(&argv, args.search_basename, args.verbose, exec_res.stderr);
+ return error.CCompilerCrashed;
+ },
}
var it = std.mem.tokenize(exec_res.stdout, "\n\r");
const line = it.next() orelse return error.LibCRuntimeNotFound;
// When this command fails, it returns exit code 0 and duplicates the input file name.
// So we detect failure by checking if the output matches exactly the input.
- if (std.mem.eql(u8, line, o_file)) return error.LibCRuntimeNotFound;
- switch (want_dirname) {
+ if (std.mem.eql(u8, line, args.search_basename)) return error.LibCRuntimeNotFound;
+ switch (args.want_dirname) {
.full_path => return std.mem.dupeZ(allocator, u8, line),
.only_dir => {
const dirname = fs.path.dirname(line) orelse return error.LibCRuntimeNotFound;
@@ -538,6 +593,29 @@ fn ccPrintFileName(
}
}
+fn printVerboseInvocation(
+ argv: []const []const u8,
+ search_basename: ?[]const u8,
+ verbose: bool,
+ stderr: ?[]const u8,
+) void {
+ if (!verbose) return;
+
+ if (search_basename) |s| {
+ std.debug.warn("Zig attempted to find the file '{}' by executing this command:\n", .{s});
+ } else {
+ std.debug.warn("Zig attempted to find the path to native system libc headers by executing this command:\n", .{});
+ }
+ for (argv) |arg, i| {
+ if (i != 0) std.debug.warn(" ", .{});
+ std.debug.warn("{}", .{arg});
+ }
+ std.debug.warn("\n", .{});
+ if (stderr) |s| {
+ std.debug.warn("Output:\n==========\n{}\n==========\n", .{s});
+ }
+}
+
/// Caller owns returned memory.
pub fn detectNativeDynamicLinker(allocator: *Allocator) error{
OutOfMemory,
@@ -617,7 +695,11 @@ pub fn detectNativeDynamicLinker(allocator: *Allocator) error{
for (ld_info_list.toSlice()) |ld_info| {
const standard_ld_basename = fs.path.basename(ld_info.ld_path);
- const full_ld_path = ccPrintFileName(allocator, standard_ld_basename, .full_path) catch |err| switch (err) {
+ const full_ld_path = ccPrintFileName(.{
+ .allocator = allocator,
+ .search_basename = standard_ld_basename,
+ .want_dirname = .full_path,
+ }) catch |err| switch (err) {
error.OutOfMemory => return error.OutOfMemory,
error.LibCRuntimeNotFound,
error.CCompilerExitCode,
src-self-hosted/stage2.zig
@@ -899,7 +899,10 @@ export fn stage2_libc_parse(stage1_libc: *Stage2LibCInstallation, libc_file_z: [
// ABI warning
export fn stage2_libc_find_native(stage1_libc: *Stage2LibCInstallation) Error {
- var libc = LibCInstallation.findNative(std.heap.c_allocator) catch |err| switch (err) {
+ var libc = LibCInstallation.findNative(.{
+ .allocator = std.heap.c_allocator,
+ .verbose = true,
+ }) catch |err| switch (err) {
error.OutOfMemory => return .OutOfMemory,
error.FileSystem => return .FileSystem,
error.UnableToSpawnCCompiler => return .UnableToSpawnCCompiler,