Skip to content

Commit

Permalink
Toolchain: improve include directory search for Linux
Browse files Browse the repository at this point in the history
  • Loading branch information
ehaas committed Feb 24, 2024
1 parent eb837b0 commit 03cffdf
Show file tree
Hide file tree
Showing 6 changed files with 88 additions and 25 deletions.
26 changes: 7 additions & 19 deletions src/aro/Compilation.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1057,9 +1057,8 @@ pub fn getCharSignedness(comp: *const Compilation) std.builtin.Signedness {
return comp.langopts.char_signedness_override orelse comp.target.charSignedness();
}

pub fn defineSystemIncludes(comp: *Compilation, aro_dir: []const u8) !void {
var stack_fallback = std.heap.stackFallback(path_buf_stack_limit, comp.gpa);
const allocator = stack_fallback.get();
/// Add built-in aro headers directory to system include paths
pub fn addBuiltinIncludeDir(comp: *Compilation, aro_dir: []const u8) !void {
var search_path = aro_dir;
while (std.fs.path.dirname(search_path)) |dirname| : (search_path = dirname) {
var base_dir = std.fs.cwd().openDir(dirname, .{}) catch continue;
Expand All @@ -1071,23 +1070,12 @@ pub fn defineSystemIncludes(comp: *Compilation, aro_dir: []const u8) !void {
try comp.system_include_dirs.append(comp.gpa, path);
break;
} else return error.AroIncludeNotFound;
}

if (comp.target.os.tag == .linux) {
const triple_str = try comp.target.linuxTriple(allocator);
defer allocator.free(triple_str);

const multiarch_path = try std.fs.path.join(allocator, &.{ "/usr/include", triple_str });
defer allocator.free(multiarch_path);

if (!std.meta.isError(std.fs.accessAbsolute(multiarch_path, .{}))) {
const duped = try comp.gpa.dupe(u8, multiarch_path);
errdefer comp.gpa.free(duped);
try comp.system_include_dirs.append(comp.gpa, duped);
}
}
const usr_include = try comp.gpa.dupe(u8, "/usr/include");
errdefer comp.gpa.free(usr_include);
try comp.system_include_dirs.append(comp.gpa, usr_include);
pub fn addSystemIncludeDir(comp: *Compilation, path: []const u8) !void {
const duped = try comp.gpa.dupe(u8, path);
errdefer comp.gpa.free(duped);
try comp.system_include_dirs.append(comp.gpa, duped);
}

pub fn getSource(comp: *const Compilation, id: Source.Id) Source {
Expand Down
18 changes: 15 additions & 3 deletions src/aro/Driver.zig
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ verbose_pp: bool = false,
verbose_ir: bool = false,
verbose_linker_args: bool = false,
color: ?bool = null,
nobuiltininc: bool = false,
nostdinc: bool = false,
nostdlibinc: bool = false,

/// Full path to the aro executable
aro_name: []const u8 = "",
Expand Down Expand Up @@ -129,6 +132,10 @@ pub const usage =
\\ -isystem Add directory to SYSTEM include search path
\\ --emulate=[clang|gcc|msvc]
\\ Select which C compiler to emulate (default clang)
\\ -nobuiltininc Do not search the compiler's builtin directory for include files
\\ -nostdinc, --no-standard-includes
\\ Do not search the standard system directories or compiler builtin directories for include files.
\\ -nostdlibinc Do not search the standard system directories for include files, but do search compiler builtin include directories
\\ -o <file> Write output to <file>
\\ -P, --no-line-commands Disable linemarker output in -E mode
\\ -pedantic Warn on language extensions
Expand Down Expand Up @@ -428,6 +435,12 @@ pub fn parseArgs(
d.nodefaultlibs = true;
} else if (mem.eql(u8, arg, "-nolibc")) {
d.nolibc = true;
} else if (mem.eql(u8, arg, "-nobuiltininc")) {
d.nobuiltininc = true;
} else if (mem.eql(u8, arg, "-nostdinc") or mem.eql(u8, arg, "--no-standard-includes")) {
d.nostdinc = true;
} else if (mem.eql(u8, arg, "-nostdlibinc")) {
d.nostdlibinc = true;
} else if (mem.eql(u8, arg, "-nostdlib")) {
d.nostdlib = true;
} else if (mem.eql(u8, arg, "-nostartfiles")) {
Expand Down Expand Up @@ -569,7 +582,8 @@ pub fn main(d: *Driver, tc: *Toolchain, args: []const []const u8, comptime fast_
try d.comp.addDiagnostic(.{ .tag = .cli_unused_link_object, .extra = .{ .str = obj } }, &.{});
};

d.comp.defineSystemIncludes(d.aro_name) catch |er| switch (er) {
try tc.discover();
tc.defineSystemIncludes() catch |er| switch (er) {
error.OutOfMemory => return error.OutOfMemory,
error.AroIncludeNotFound => return d.fatal("unable to find Aro builtin headers", .{}),
};
Expand Down Expand Up @@ -774,8 +788,6 @@ fn dumpLinkerArgs(items: []const []const u8) !void {
/// The entry point of the Aro compiler.
/// **MAY call `exit` if `fast_exit` is set.**
pub fn invokeLinker(d: *Driver, tc: *Toolchain, comptime fast_exit: bool) !void {
try tc.discover();

var argv = std.ArrayList([]const u8).init(d.comp.gpa);
defer argv.deinit();

Expand Down
19 changes: 19 additions & 0 deletions src/aro/Toolchain.zig
Original file line number Diff line number Diff line change
Expand Up @@ -487,3 +487,22 @@ pub fn addRuntimeLibs(tc: *const Toolchain, argv: *std.ArrayList([]const u8)) !v
try argv.append("-ldl");
}
}

pub fn defineSystemIncludes(tc: *Toolchain) !void {
return switch (tc.inner) {
.uninitialized => unreachable,
.linux => |*linux| linux.defineSystemIncludes(tc),
.unknown => {
if (tc.driver.nostdinc) return;

const comp = tc.driver.comp;
if (!tc.driver.nobuiltininc) {
try comp.addBuiltinIncludeDir(tc.driver.aro_name);
}

if (!tc.driver.nostdlibinc) {
try comp.addSystemIncludeDir.append("/usr/include");
}
},
};
}
44 changes: 44 additions & 0 deletions src/aro/toolchains/Linux.zig
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,50 @@ fn getOSLibDir(target: std.Target) []const u8 {
return "lib64";
}

pub fn defineSystemIncludes(self: *const Linux, tc: *const Toolchain) !void {
if (tc.driver.nostdinc) return;

const comp = tc.driver.comp;
const target = tc.getTarget();

// musl prefers /usr/include before builtin includes, so musl targets will add builtins
// at the end of this function (unless disabled with nostdlibinc)
if (!tc.driver.nobuiltininc and (!target.isMusl() or tc.driver.nostdlibinc)) {
try comp.addBuiltinIncludeDir(tc.driver.aro_name);
}

if (tc.driver.nostdlibinc) return;

const sysroot = tc.getSysroot();
const local_include = try std.fmt.allocPrint(comp.gpa, "{s}{s}", .{ sysroot, "/usr/local/include" });
defer comp.gpa.free(local_include);
try comp.addSystemIncludeDir(local_include);

if (self.gcc_detector.is_valid) {
const gcc_include_path = try std.fs.path.join(comp.gpa, &.{ self.gcc_detector.parent_lib_path, "..", self.gcc_detector.gcc_triple, "include" });
defer comp.gpa.free(gcc_include_path);
try comp.addSystemIncludeDir(gcc_include_path);
}

if (getMultiarchTriple(target)) |triple| {
const joined = try std.fs.path.join(comp.gpa, &.{ sysroot, "usr", "include", triple });
errdefer comp.gpa.free(joined);
if (tc.filesystem.exists(joined)) {
try comp.addSystemIncludeDir(joined);
}
}

if (target.os.tag == .rtems) return;

try comp.addSystemIncludeDir("/include");
try comp.addSystemIncludeDir("/usr/include");

std.debug.assert(!tc.driver.nostdlibinc);
if (!tc.driver.nobuiltininc and target.isMusl()) {
try comp.addBuiltinIncludeDir(tc.driver.aro_name);
}
}

test Linux {
if (@import("builtin").os.tag == .windows) return error.SkipZigTest;

Expand Down
2 changes: 1 addition & 1 deletion test/record_runner.zig
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ fn singleRun(alloc: std.mem.Allocator, test_dir: []const u8, test_case: TestCase
defer comp.deinit();

try comp.addDefaultPragmaHandlers();
try comp.defineSystemIncludes(test_dir);
try comp.addBuiltinIncludeDir(test_dir);

const target = setTarget(&comp, test_case.target) catch |err| switch (err) {
error.UnknownCpuModel => unreachable,
Expand Down
4 changes: 2 additions & 2 deletions test/runner.zig
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ fn testOne(allocator: std.mem.Allocator, path: []const u8, test_dir: []const u8)
defer comp.deinit();

try comp.addDefaultPragmaHandlers();
try comp.defineSystemIncludes(test_dir);
try comp.addBuiltinIncludeDir(test_dir);

const file = try comp.addSourceFromPath(path);
var macro_buf = std.ArrayList(u8).init(comp.gpa);
Expand Down Expand Up @@ -173,7 +173,7 @@ pub fn main() !void {
try initial_comp.include_dirs.append(gpa, cases_next_include_dir);

try initial_comp.addDefaultPragmaHandlers();
try initial_comp.defineSystemIncludes(test_dir);
try initial_comp.addBuiltinIncludeDir(test_dir);

// apparently we can't use setAstCwd without libc on windows yet
const win = @import("builtin").os.tag == .windows;
Expand Down

0 comments on commit 03cffdf

Please sign in to comment.