authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-02-19 01:24:34-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-02-19 01:24:34-05:00
logc664692bdd62765ab444a79a8704d2161c1809f1
tree54117a52a1407898728a3155451fc14665221076
parent63383a8af8bf45b2de78967a2fe8773a5639d36b
signaturelock-open Commit is signed but in an unrecognized format.

make the CLI support depending on system headers and libraries

(include and lib search paths) The detection of native system paths is self-hosted. closes #2041

7 files changed, 250 insertions(+), 124 deletions(-)

lib/std/build.zig-123
...@@ -27,9 +27,6 @@ pub const Builder = struct {...@@ -27,9 +27,6 @@ pub const Builder = struct {
27 install_tls: TopLevelStep,27 install_tls: TopLevelStep,
28 uninstall_tls: TopLevelStep,28 uninstall_tls: TopLevelStep,
29 allocator: *Allocator,29 allocator: *Allocator,
30 native_system_lib_paths: ArrayList([]const u8),
31 native_system_include_dirs: ArrayList([]const u8),
32 native_system_rpaths: ArrayList([]const u8),
33 user_input_options: UserInputOptionsMap,30 user_input_options: UserInputOptionsMap,
34 available_options_map: AvailableOptionsMap,31 available_options_map: AvailableOptionsMap,
35 available_options_list: ArrayList(AvailableOption),32 available_options_list: ArrayList(AvailableOption),
...@@ -139,9 +136,6 @@ pub const Builder = struct {...@@ -139,9 +136,6 @@ pub const Builder = struct {
139 .verbose_cimport = false,136 .verbose_cimport = false,
140 .invalid_user_input = false,137 .invalid_user_input = false,
141 .allocator = allocator,138 .allocator = allocator,
142 .native_system_lib_paths = ArrayList([]const u8).init(allocator),
143 .native_system_include_dirs = ArrayList([]const u8).init(allocator),
144 .native_system_rpaths = ArrayList([]const u8).init(allocator),
145 .user_input_options = UserInputOptionsMap.init(allocator),139 .user_input_options = UserInputOptionsMap.init(allocator),
146 .available_options_map = AvailableOptionsMap.init(allocator),140 .available_options_map = AvailableOptionsMap.init(allocator),
147 .available_options_list = ArrayList(AvailableOption).init(allocator),141 .available_options_list = ArrayList(AvailableOption).init(allocator),
...@@ -172,15 +166,11 @@ pub const Builder = struct {...@@ -172,15 +166,11 @@ pub const Builder = struct {
172 };166 };
173 try self.top_level_steps.append(&self.install_tls);167 try self.top_level_steps.append(&self.install_tls);
174 try self.top_level_steps.append(&self.uninstall_tls);168 try self.top_level_steps.append(&self.uninstall_tls);
175 self.detectNativeSystemPaths();
176 self.default_step = &self.install_tls.step;169 self.default_step = &self.install_tls.step;
177 return self;170 return self;
178 }171 }
179172
180 pub fn destroy(self: *Builder) void {173 pub fn destroy(self: *Builder) void {
181 self.native_system_lib_paths.deinit();
182 self.native_system_include_dirs.deinit();
183 self.native_system_rpaths.deinit();
184 self.env_map.deinit();174 self.env_map.deinit();
185 self.top_level_steps.deinit();175 self.top_level_steps.deinit();
186 self.allocator.destroy(self);176 self.allocator.destroy(self);
...@@ -347,18 +337,6 @@ pub const Builder = struct {...@@ -347,18 +337,6 @@ pub const Builder = struct {
347 };337 };
348 }338 }
349339
350 pub fn addNativeSystemIncludeDir(self: *Builder, path: []const u8) void {
351 self.native_system_include_dirs.append(path) catch unreachable;
352 }
353
354 pub fn addNativeSystemRPath(self: *Builder, path: []const u8) void {
355 self.native_system_rpaths.append(path) catch unreachable;
356 }
357
358 pub fn addNativeSystemLibPath(self: *Builder, path: []const u8) void {
359 self.native_system_lib_paths.append(path) catch unreachable;
360 }
361
362 pub fn make(self: *Builder, step_names: []const []const u8) !void {340 pub fn make(self: *Builder, step_names: []const []const u8) !void {
363 try self.makePath(self.cache_root);341 try self.makePath(self.cache_root);
364342
...@@ -433,87 +411,6 @@ pub const Builder = struct {...@@ -433,87 +411,6 @@ pub const Builder = struct {
433 return error.InvalidStepName;411 return error.InvalidStepName;
434 }412 }
435413
436 fn detectNativeSystemPaths(self: *Builder) void {
437 var is_nixos = false;
438 if (process.getEnvVarOwned(self.allocator, "NIX_CFLAGS_COMPILE")) |nix_cflags_compile| {
439 is_nixos = true;
440 var it = mem.tokenize(nix_cflags_compile, " ");
441 while (true) {
442 const word = it.next() orelse break;
443 if (mem.eql(u8, word, "-isystem")) {
444 const include_path = it.next() orelse {
445 warn("Expected argument after -isystem in NIX_CFLAGS_COMPILE\n", .{});
446 break;
447 };
448 self.addNativeSystemIncludeDir(include_path);
449 } else {
450 warn("Unrecognized C flag from NIX_CFLAGS_COMPILE: {}\n", .{word});
451 break;
452 }
453 }
454 } else |err| {
455 assert(err == error.EnvironmentVariableNotFound);
456 }
457 if (process.getEnvVarOwned(self.allocator, "NIX_LDFLAGS")) |nix_ldflags| {
458 is_nixos = true;
459 var it = mem.tokenize(nix_ldflags, " ");
460 while (true) {
461 const word = it.next() orelse break;
462 if (mem.eql(u8, word, "-rpath")) {
463 const rpath = it.next() orelse {
464 warn("Expected argument after -rpath in NIX_LDFLAGS\n", .{});
465 break;
466 };
467 self.addNativeSystemRPath(rpath);
468 } else if (word.len > 2 and word[0] == '-' and word[1] == 'L') {
469 const lib_path = word[2..];
470 self.addNativeSystemLibPath(lib_path);
471 } else {
472 warn("Unrecognized C flag from NIX_LDFLAGS: {}\n", .{word});
473 break;
474 }
475 }
476 } else |err| {
477 assert(err == error.EnvironmentVariableNotFound);
478 }
479 if (is_nixos) return;
480 switch (builtin.os) {
481 .windows => {},
482 else => {
483 const triple = (Target{
484 .Cross = CrossTarget{
485 .arch = builtin.arch,
486 .os = builtin.os,
487 .abi = builtin.abi,
488 .cpu_features = builtin.cpu_features,
489 },
490 }).linuxTriple(self.allocator);
491
492 // TODO: $ ld --verbose | grep SEARCH_DIR
493 // the output contains some paths that end with lib64, maybe include them too?
494 // also, what is the best possible order of things?
495
496 self.addNativeSystemIncludeDir("/usr/local/include");
497 self.addNativeSystemLibPath("/usr/local/lib");
498 self.addNativeSystemLibPath("/usr/local/lib64");
499
500 self.addNativeSystemIncludeDir(self.fmt("/usr/include/{}", .{triple}));
501 self.addNativeSystemLibPath(self.fmt("/usr/lib/{}", .{triple}));
502
503 self.addNativeSystemIncludeDir("/usr/include");
504 self.addNativeSystemLibPath("/lib");
505 self.addNativeSystemLibPath("/lib64");
506 self.addNativeSystemLibPath("/usr/lib");
507 self.addNativeSystemLibPath("/usr/lib64");
508
509 // example: on a 64-bit debian-based linux distro, with zlib installed from apt:
510 // zlib.h is in /usr/include (added above)
511 // libz.so.1 is in /lib/x86_64-linux-gnu (added here)
512 self.addNativeSystemLibPath(self.fmt("/lib/{}", .{triple}));
513 },
514 }
515 }
516
517 pub fn option(self: *Builder, comptime T: type, name: []const u8, description: []const u8) ?T {414 pub fn option(self: *Builder, comptime T: type, name: []const u8, description: []const u8) ?T {
518 const type_id = comptime typeToEnum(T);415 const type_id = comptime typeToEnum(T);
519 const available_option = AvailableOption{416 const available_option = AvailableOption{
...@@ -1185,7 +1082,6 @@ pub const LibExeObjStep = struct {...@@ -1185,7 +1082,6 @@ pub const LibExeObjStep = struct {
1185 include_dirs: ArrayList(IncludeDir),1082 include_dirs: ArrayList(IncludeDir),
1186 c_macros: ArrayList([]const u8),1083 c_macros: ArrayList([]const u8),
1187 output_dir: ?[]const u8,1084 output_dir: ?[]const u8,
1188 need_system_paths: bool,
1189 is_linking_libc: bool = false,1085 is_linking_libc: bool = false,
1190 vcpkg_bin_path: ?[]const u8 = null,1086 vcpkg_bin_path: ?[]const u8 = null,
11911087
...@@ -1323,7 +1219,6 @@ pub const LibExeObjStep = struct {...@@ -1323,7 +1219,6 @@ pub const LibExeObjStep = struct {
1323 .disable_stack_probing = false,1219 .disable_stack_probing = false,
1324 .disable_sanitize_c = false,1220 .disable_sanitize_c = false,
1325 .output_dir = null,1221 .output_dir = null,
1326 .need_system_paths = false,
1327 .single_threaded = false,1222 .single_threaded = false,
1328 .installed_path = null,1223 .installed_path = null,
1329 .install_step = null,1224 .install_step = null,
...@@ -1499,7 +1394,6 @@ pub const LibExeObjStep = struct {...@@ -1499,7 +1394,6 @@ pub const LibExeObjStep = struct {
1499 /// Prefer to use `linkSystemLibrary` instead.1394 /// Prefer to use `linkSystemLibrary` instead.
1500 pub fn linkSystemLibraryName(self: *LibExeObjStep, name: []const u8) void {1395 pub fn linkSystemLibraryName(self: *LibExeObjStep, name: []const u8) void {
1501 self.link_objects.append(LinkObject{ .SystemLib = self.builder.dupe(name) }) catch unreachable;1396 self.link_objects.append(LinkObject{ .SystemLib = self.builder.dupe(name) }) catch unreachable;
1502 self.need_system_paths = true;
1503 }1397 }
15041398
1505 /// This links against a system library, exclusively using pkg-config to find the library.1399 /// This links against a system library, exclusively using pkg-config to find the library.
...@@ -2159,23 +2053,6 @@ pub const LibExeObjStep = struct {...@@ -2159,23 +2053,6 @@ pub const LibExeObjStep = struct {
2159 try zig_args.append(lib_path);2053 try zig_args.append(lib_path);
2160 }2054 }
21612055
2162 if (self.need_system_paths and self.target == Target.Native) {
2163 for (builder.native_system_include_dirs.toSliceConst()) |include_path| {
2164 zig_args.append("-isystem") catch unreachable;
2165 zig_args.append(builder.pathFromRoot(include_path)) catch unreachable;
2166 }
2167
2168 for (builder.native_system_rpaths.toSliceConst()) |rpath| {
2169 zig_args.append("-rpath") catch unreachable;
2170 zig_args.append(rpath) catch unreachable;
2171 }
2172
2173 for (builder.native_system_lib_paths.toSliceConst()) |lib_path| {
2174 zig_args.append("--library-path") catch unreachable;
2175 zig_args.append(lib_path) catch unreachable;
2176 }
2177 }
2178
2179 for (self.c_macros.toSliceConst()) |c_macro| {2056 for (self.c_macros.toSliceConst()) |c_macro| {
2180 try zig_args.append("-D");2057 try zig_args.append("-D");
2181 try zig_args.append(c_macro);2058 try zig_args.append(c_macro);
lib/std/zig.zig+1
...@@ -5,6 +5,7 @@ pub const parse = @import("zig/parse.zig").parse;...@@ -5,6 +5,7 @@ pub const parse = @import("zig/parse.zig").parse;
5pub const parseStringLiteral = @import("zig/parse_string_literal.zig").parseStringLiteral;5pub const parseStringLiteral = @import("zig/parse_string_literal.zig").parseStringLiteral;
6pub const render = @import("zig/render.zig").render;6pub const render = @import("zig/render.zig").render;
7pub const ast = @import("zig/ast.zig");7pub const ast = @import("zig/ast.zig");
8pub const system = @import("zig/system.zig");
89
9test "std.zig tests" {10test "std.zig tests" {
10 _ = @import("zig/ast.zig");11 _ = @import("zig/ast.zig");
lib/std/zig/system.zig created+152
...@@ -0,0 +1,152 @@
1const std = @import("../std.zig");
2const mem = std.mem;
3const Allocator = std.mem.Allocator;
4const ArrayList = std.ArrayList;
5const assert = std.debug.assert;
6const process = std.process;
7
8pub const NativePaths = struct {
9 include_dirs: ArrayList([:0]u8),
10 lib_dirs: ArrayList([:0]u8),
11 rpaths: ArrayList([:0]u8),
12 warnings: ArrayList([:0]u8),
13
14 pub fn detect(allocator: *Allocator) !NativePaths {
15 var self: NativePaths = .{
16 .include_dirs = ArrayList([:0]u8).init(allocator),
17 .lib_dirs = ArrayList([:0]u8).init(allocator),
18 .rpaths = ArrayList([:0]u8).init(allocator),
19 .warnings = ArrayList([:0]u8).init(allocator),
20 };
21 errdefer self.deinit();
22
23 var is_nix = false;
24 if (std.os.getenvZ("NIX_CFLAGS_COMPILE")) |nix_cflags_compile| {
25 is_nix = true;
26 var it = mem.tokenize(nix_cflags_compile, " ");
27 while (true) {
28 const word = it.next() orelse break;
29 if (mem.eql(u8, word, "-isystem")) {
30 const include_path = it.next() orelse {
31 try self.addWarning("Expected argument after -isystem in NIX_CFLAGS_COMPILE");
32 break;
33 };
34 try self.addIncludeDir(include_path);
35 } else {
36 try self.addWarningFmt("Unrecognized C flag from NIX_CFLAGS_COMPILE: {}", .{word});
37 break;
38 }
39 }
40 }
41 if (std.os.getenvZ("NIX_LDFLAGS")) |nix_ldflags| {
42 is_nix = true;
43 var it = mem.tokenize(nix_ldflags, " ");
44 while (true) {
45 const word = it.next() orelse break;
46 if (mem.eql(u8, word, "-rpath")) {
47 const rpath = it.next() orelse {
48 try self.addWarning("Expected argument after -rpath in NIX_LDFLAGS");
49 break;
50 };
51 try self.addRPath(rpath);
52 } else if (word.len > 2 and word[0] == '-' and word[1] == 'L') {
53 const lib_path = word[2..];
54 try self.addLibDir(lib_path);
55 } else {
56 try self.addWarningFmt("Unrecognized C flag from NIX_LDFLAGS: {}", .{word});
57 break;
58 }
59 }
60 }
61 if (is_nix) {
62 return self;
63 }
64
65 switch (std.builtin.os) {
66 .windows => {},
67 else => {
68 const triple = try std.Target.current.linuxTriple(allocator);
69
70 // TODO: $ ld --verbose | grep SEARCH_DIR
71 // the output contains some paths that end with lib64, maybe include them too?
72 // TODO: what is the best possible order of things?
73 // TODO: some of these are suspect and should only be added on some systems. audit needed.
74
75 try self.addIncludeDir("/usr/local/include");
76 try self.addLibDir("/usr/local/lib");
77 try self.addLibDir("/usr/local/lib64");
78
79 try self.addIncludeDirFmt("/usr/include/{}", .{triple});
80 try self.addLibDirFmt("/usr/lib/{}", .{triple});
81
82 try self.addIncludeDir("/usr/include");
83 try self.addLibDir("/lib");
84 try self.addLibDir("/lib64");
85 try self.addLibDir("/usr/lib");
86 try self.addLibDir("/usr/lib64");
87
88 // example: on a 64-bit debian-based linux distro, with zlib installed from apt:
89 // zlib.h is in /usr/include (added above)
90 // libz.so.1 is in /lib/x86_64-linux-gnu (added here)
91 try self.addLibDirFmt("/lib/{}", .{triple});
92 },
93 }
94
95 return self;
96 }
97
98 pub fn deinit(self: *NativePaths) void {
99 deinitArray(&self.include_dirs);
100 deinitArray(&self.lib_dirs);
101 deinitArray(&self.rpaths);
102 deinitArray(&self.warnings);
103 self.* = undefined;
104 }
105
106 fn deinitArray(array: *ArrayList([:0]u8)) void {
107 for (array.toSlice()) |item| {
108 array.allocator.free(item);
109 }
110 array.deinit();
111 }
112
113 pub fn addIncludeDir(self: *NativePaths, s: []const u8) !void {
114 return self.appendArray(&self.include_dirs, s);
115 }
116
117 pub fn addIncludeDirFmt(self: *NativePaths, comptime fmt: []const u8, args: var) !void {
118 const item = try std.fmt.allocPrint0(self.include_dirs.allocator, fmt, args);
119 errdefer self.include_dirs.allocator.free(item);
120 try self.include_dirs.append(item);
121 }
122
123 pub fn addLibDir(self: *NativePaths, s: []const u8) !void {
124 return self.appendArray(&self.lib_dirs, s);
125 }
126
127 pub fn addLibDirFmt(self: *NativePaths, comptime fmt: []const u8, args: var) !void {
128 const item = try std.fmt.allocPrint0(self.lib_dirs.allocator, fmt, args);
129 errdefer self.lib_dirs.allocator.free(item);
130 try self.lib_dirs.append(item);
131 }
132
133 pub fn addWarning(self: *NativePaths, s: []const u8) !void {
134 return self.appendArray(&self.warnings, s);
135 }
136
137 pub fn addWarningFmt(self: *NativePaths, comptime fmt: []const u8, args: var) !void {
138 const item = try std.fmt.allocPrint0(self.warnings.allocator, fmt, args);
139 errdefer self.warnings.allocator.free(item);
140 try self.warnings.append(item);
141 }
142
143 pub fn addRPath(self: *NativePaths, s: []const u8) !void {
144 return self.appendArray(&self.rpaths, s);
145 }
146
147 fn appendArray(self: *NativePaths, array: *ArrayList([:0]u8), s: []const u8) !void {
148 const item = try std.mem.dupeZ(array.allocator, u8, s);
149 errdefer array.allocator.free(item);
150 try array.append(item);
151 }
152};
src-self-hosted/stage2.zig+38
...@@ -1116,3 +1116,41 @@ export fn stage2_detect_dynamic_linker(in_target: *const Stage2Target, out_ptr:...@@ -1116,3 +1116,41 @@ export fn stage2_detect_dynamic_linker(in_target: *const Stage2Target, out_ptr:
1116fn enumInt(comptime Enum: type, int: c_int) Enum {1116fn enumInt(comptime Enum: type, int: c_int) Enum {
1117 return @intToEnum(Enum, @intCast(@TagType(Enum), int));1117 return @intToEnum(Enum, @intCast(@TagType(Enum), int));
1118}1118}
1119
1120// ABI warning
1121const Stage2NativePaths = extern struct {
1122 include_dirs_ptr: [*][*:0]u8,
1123 include_dirs_len: usize,
1124 lib_dirs_ptr: [*][*:0]u8,
1125 lib_dirs_len: usize,
1126 rpaths_ptr: [*][*:0]u8,
1127 rpaths_len: usize,
1128 warnings_ptr: [*][*:0]u8,
1129 warnings_len: usize,
1130};
1131// ABI warning
1132export fn stage2_detect_native_paths(stage1_paths: *Stage2NativePaths) Error {
1133 stage2DetectNativePaths(stage1_paths) catch |err| switch (err) {
1134 error.OutOfMemory => return .OutOfMemory,
1135 };
1136 return .None;
1137}
1138
1139fn stage2DetectNativePaths(stage1_paths: *Stage2NativePaths) !void {
1140 var paths = try std.zig.system.NativePaths.detect(std.heap.c_allocator);
1141 errdefer paths.deinit();
1142
1143 try convertSlice(paths.include_dirs.toSlice(), &stage1_paths.include_dirs_ptr, &stage1_paths.include_dirs_len);
1144 try convertSlice(paths.lib_dirs.toSlice(), &stage1_paths.lib_dirs_ptr, &stage1_paths.lib_dirs_len);
1145 try convertSlice(paths.rpaths.toSlice(), &stage1_paths.rpaths_ptr, &stage1_paths.rpaths_len);
1146 try convertSlice(paths.warnings.toSlice(), &stage1_paths.warnings_ptr, &stage1_paths.warnings_len);
1147}
1148
1149fn convertSlice(slice: [][:0]u8, ptr: *[*][*:0]u8, len: *usize) !void {
1150 len.* = slice.len;
1151 const new_slice = try std.heap.c_allocator.alloc([*:0]u8, slice.len);
1152 for (slice) |item, i| {
1153 new_slice[i] = item.ptr;
1154 }
1155 ptr.* = new_slice.ptr;
1156}
src/main.cpp+27-1
...@@ -1120,6 +1120,33 @@ static int main0(int argc, char **argv) {...@@ -1120,6 +1120,33 @@ static int main0(int argc, char **argv) {
1120 return print_error_usage(arg0);1120 return print_error_usage(arg0);
1121 }1121 }
11221122
1123 if (target.is_native && link_libs.length != 0) {
1124 Error err;
1125 Stage2NativePaths paths;
1126 if ((err = stage2_detect_native_paths(&paths))) {
1127 fprintf(stderr, "unable to detect native system paths: %s\n", err_str(err));
1128 exit(1);
1129 }
1130 for (size_t i = 0; i < paths.warnings_len; i += 1) {
1131 const char *warning = paths.warnings_ptr[i];
1132 fprintf(stderr, "warning: %s\n", warning);
1133 }
1134 for (size_t i = 0; i < paths.include_dirs_len; i += 1) {
1135 const char *include_dir = paths.include_dirs_ptr[i];
1136 clang_argv.append("-I");
1137 clang_argv.append(include_dir);
1138 }
1139 for (size_t i = 0; i < paths.lib_dirs_len; i += 1) {
1140 const char *lib_dir = paths.lib_dirs_ptr[i];
1141 lib_dirs.append(lib_dir);
1142 }
1143 for (size_t i = 0; i < paths.rpaths_len; i += 1) {
1144 const char *rpath = paths.rpaths_ptr[i];
1145 rpath_list.append(rpath);
1146 }
1147 }
1148
1149
1123 assert(cmd != CmdBuild || out_type != OutTypeUnknown);1150 assert(cmd != CmdBuild || out_type != OutTypeUnknown);
11241151
1125 bool need_name = (cmd == CmdBuild || cmd == CmdTranslateC);1152 bool need_name = (cmd == CmdBuild || cmd == CmdTranslateC);
...@@ -1226,7 +1253,6 @@ static int main0(int argc, char **argv) {...@@ -1226,7 +1253,6 @@ static int main0(int argc, char **argv) {
1226 g->function_sections = function_sections;1253 g->function_sections = function_sections;
1227 g->code_model = code_model;1254 g->code_model = code_model;
12281255
1229
1230 for (size_t i = 0; i < lib_dirs.length; i += 1) {1256 for (size_t i = 0; i < lib_dirs.length; i += 1) {
1231 codegen_add_lib_dir(g, lib_dirs.at(i));1257 codegen_add_lib_dir(g, lib_dirs.at(i));
1232 }1258 }
src/stage2.cpp+16
...@@ -175,3 +175,19 @@ enum Error stage2_detect_dynamic_linker(const struct ZigTarget *target, char **o...@@ -175,3 +175,19 @@ enum Error stage2_detect_dynamic_linker(const struct ZigTarget *target, char **o
175 const char *msg = "stage0 called stage2_detect_dynamic_linker";175 const char *msg = "stage0 called stage2_detect_dynamic_linker";
176 stage2_panic(msg, strlen(msg));176 stage2_panic(msg, strlen(msg));
177}177}
178
179enum Error stage2_detect_native_paths(struct Stage2NativePaths *native_paths) {
180 native_paths->include_dirs_ptr = nullptr;
181 native_paths->include_dirs_len = 0;
182
183 native_paths->lib_dirs_ptr = nullptr;
184 native_paths->lib_dirs_len = 0;
185
186 native_paths->rpaths_ptr = nullptr;
187 native_paths->rpaths_len = 0;
188
189 native_paths->warnings_ptr = nullptr;
190 native_paths->warnings_len = 0;
191
192 return ErrorNone;
193}
src/stage2.h+16
...@@ -312,4 +312,20 @@ struct ZigTarget {...@@ -312,4 +312,20 @@ struct ZigTarget {
312ZIG_EXTERN_C enum Error stage2_detect_dynamic_linker(const struct ZigTarget *target,312ZIG_EXTERN_C enum Error stage2_detect_dynamic_linker(const struct ZigTarget *target,
313 char **out_ptr, size_t *out_len);313 char **out_ptr, size_t *out_len);
314314
315
316
317// ABI warning
318struct Stage2NativePaths {
319 const char **include_dirs_ptr;
320 size_t include_dirs_len;
321 const char **lib_dirs_ptr;
322 size_t lib_dirs_len;
323 const char **rpaths_ptr;
324 size_t rpaths_len;
325 const char **warnings_ptr;
326 size_t warnings_len;
327};
328// ABI warning
329ZIG_EXTERN_C enum Error stage2_detect_native_paths(struct Stage2NativePaths *native_paths);
330
315#endif331#endif