feature. See also
. The project being documented here (as the example) is the Zig library itself.
LibCInstallation.findNativeIncludeDirPosix
fn findNativeIncludeDirPosix(self: *LibCInstallation, gpa: Allocator, io: Io, args: FindNativeOptions) FindError!void
File
Code
fn findNativeIncludeDirPosix(self: *LibCInstallation, gpa: Allocator, io: Io, args: FindNativeOptions) FindError!void {
var environ_map = try args.environ_map.clone(gpa);
defer environ_map.deinit();
const skip_cc_env_var = if (environ_map.get(inf_loop_env_key)) |phase| blk: {
if (std.mem.eql(u8, phase, "1")) {
try environ_map.put(inf_loop_env_key, "2");
break :blk true;
} else {
return error.ZigIsTheCCompiler;
}
} else blk: {
try environ_map.put(inf_loop_env_key, "1");
break :blk false;
};
const dev_null = if (is_windows) "nul" else "/dev/null";
var argv = std.array_list.Managed([]const u8).init(gpa);
defer argv.deinit();
try appendCcExe(&argv, skip_cc_env_var, &environ_map);
try argv.appendSlice(&.{
"-E",
"-Wp,-v",
"-xc",
dev_null,
});
const run_res = std.process.run(gpa, io, .{
.stdout_limit = .limited(1024 * 1024),
.stderr_limit = .limited(1024 * 1024),
.argv = argv.items,
.environ_map = &environ_map,
// to their own executable, without even bothering to resolve PATH. This results in the message:
// error: unable to execute command: Executable "" doesn't exist!
// So we use the expandArg0 variant of ChildProcess to give them a helping hand.
.expand_arg0 = .expand,
}) catch |err| switch (err) {
error.OutOfMemory => |e| return e,
else => {
printVerboseInvocation(argv.items, null, args.verbose, null);
return error.UnableToSpawnCCompiler;
},
};
defer {
gpa.free(run_res.stdout);
gpa.free(run_res.stderr);
}
switch (run_res.term) {
.exited => |code| if (code != 0) {
printVerboseInvocation(argv.items, null, args.verbose, run_res.stderr);
return error.CCompilerExitCode;
},
else => {
printVerboseInvocation(argv.items, null, args.verbose, run_res.stderr);
return error.CCompilerCrashed;
},
}
var it = std.mem.tokenizeAny(u8, run_res.stderr, "\n\r");
var search_paths = std.array_list.Managed([]const u8).init(gpa);
defer search_paths.deinit();
while (it.next()) |line| {
if (line.len != 0 and line[0] == ' ') {
try search_paths.append(line);
}
}
if (search_paths.items.len == 0) {
return error.CCompilerCannotFindHeaders;
}
const include_dir_example_file = if (is_haiku) "posix/stdlib.h" else "stdlib.h";
const sys_include_dir_example_file = if (is_windows)
"sys\\types.h"
else if (is_haiku or is_serenity)
"errno.h"
else
"sys/errno.h";
var path_i: usize = 0;
while (path_i < search_paths.items.len) : (path_i += 1) {
const search_path_untrimmed = search_paths.items[search_paths.items.len - path_i - 1];
const search_path = std.mem.trimStart(u8, search_path_untrimmed, " ");
var search_dir = Io.Dir.cwd().openDir(io, search_path, .{}) catch |err| switch (err) {
error.FileNotFound,
error.NotDir,
error.NoDevice,
=> continue,
else => return error.FileSystem,
};
defer search_dir.close(io);
if (self.include_dir == null) {
if (search_dir.access(io, include_dir_example_file, .{})) |_| {
self.include_dir = try gpa.dupe(u8, search_path);
} else |err| switch (err) {
error.FileNotFound => {},
else => return error.FileSystem,
}
}
if (self.sys_include_dir == null) {
if (search_dir.access(io, sys_include_dir_example_file, .{})) |_| {
self.sys_include_dir = try gpa.dupe(u8, search_path);
} else |err| switch (err) {
error.FileNotFound => {},
else => return error.FileSystem,
}
}
if (self.include_dir != null and self.sys_include_dir != null) {
return;
}
}
return error.LibCStdLibHeaderNotFound;
}