authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-02-27 17:20:40-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-02-28 14:51:55-05:00
logfd006c1c74a43827a6f1c32e289ba57cafa874be
tree0568223856214389c035304f0352fcc914d83414
parent60f2f3457dd73772e7cd60bf5d90358079361d11
signaturelock-open Commit is signed but in an unrecognized format.

std.zig.system.NativeTargetInfo.detect: almost no Allocator


4 files changed, 42 insertions(+), 40 deletions(-)

lib/std/process.zig+4
...@@ -609,6 +609,10 @@ pub fn getBaseAddress() usize {...@@ -609,6 +609,10 @@ pub fn getBaseAddress() usize {
609}609}
610610
611/// Caller owns the result value and each inner slice.611/// Caller owns the result value and each inner slice.
612/// TODO Remove the `Allocator` requirement from this API, which will remove the `Allocator`
613/// requirement from `std.zig.system.NativeTargetInfo.detect`. Most likely this will require
614/// introducing a new, lower-level function which takes a callback function, and then this
615/// function which takes an allocator can exist on top of it.
612pub fn getSelfExeSharedLibPaths(allocator: *Allocator) error{OutOfMemory}![][:0]u8 {616pub fn getSelfExeSharedLibPaths(allocator: *Allocator) error{OutOfMemory}![][:0]u8 {
613 switch (builtin.link_mode) {617 switch (builtin.link_mode) {
614 .Static => return &[_][:0]u8{},618 .Static => return &[_][:0]u8{},
lib/std/target.zig+6-6
...@@ -1084,16 +1084,16 @@ pub const Target = struct {...@@ -1084,16 +1084,16 @@ pub const Target = struct {
1084 }1084 }
1085 }1085 }
10861086
1087 /// The result will be a slice of `buffer`, pointing at position 0.1087 /// The result will be a byte index *pointing at the final byte*. In other words, length minus one.
1088 /// A return value of `null` means the concept of a dynamic linker is not meaningful for that target.1088 /// A return value of `null` means the concept of a dynamic linker is not meaningful for that target.
1089 pub fn standardDynamicLinkerPath(self: Target, buffer: *[255]u8) ?[]u8 {1089 pub fn standardDynamicLinkerPath(self: Target, buffer: *[255]u8) ?u8 {
1090 const S = struct {1090 const S = struct {
1091 fn print(b: *[255]u8, comptime fmt: []const u8, args: var) []u8 {1091 fn print(b: *[255]u8, comptime fmt: []const u8, args: var) u8 {
1092 return std.fmt.bufPrint(b, fmt, args) catch unreachable;1092 return @intCast(u8, (std.fmt.bufPrint(b, fmt, args) catch unreachable).len - 1);
1093 }1093 }
1094 fn copy(b: *[255]u8, s: []const u8) []u8 {1094 fn copy(b: *[255]u8, s: []const u8) u8 {
1095 mem.copy(u8, b, s);1095 mem.copy(u8, b, s);
1096 return b[0..s.len];1096 return @intCast(u8, s.len - 1);
1097 }1097 }
1098 };1098 };
1099 const print = S.print;1099 const print = S.print;
lib/std/zig/system.zig+30-32
...@@ -189,7 +189,9 @@ pub const NativeTargetInfo = struct {...@@ -189,7 +189,9 @@ pub const NativeTargetInfo = struct {
189189
190 /// Detects the native CPU model & features, operating system & version, and C ABI & dynamic linker.190 /// Detects the native CPU model & features, operating system & version, and C ABI & dynamic linker.
191 /// On Linux, this is additionally responsible for detecting the native glibc version when applicable.191 /// On Linux, this is additionally responsible for detecting the native glibc version when applicable.
192 /// TODO Remove the allocator requirement from this.192 /// Any resources this function allocates are released before returning, and so there is no
193 /// deinitialization method.
194 /// TODO Remove the Allocator requirement from this function.
193 pub fn detect(allocator: *Allocator) DetectError!NativeTargetInfo {195 pub fn detect(allocator: *Allocator) DetectError!NativeTargetInfo {
194 const arch = Target.current.cpu.arch;196 const arch = Target.current.cpu.arch;
195 const os_tag = Target.current.os.tag;197 const os_tag = Target.current.os.tag;
...@@ -203,15 +205,9 @@ pub const NativeTargetInfo = struct {...@@ -203,15 +205,9 @@ pub const NativeTargetInfo = struct {
203 return detectAbiAndDynamicLinker(allocator, cpu, os);205 return detectAbiAndDynamicLinker(allocator, cpu, os);
204 }206 }
205207
206 /// Must be the same `Allocator` passed to `detect`.
207 pub fn deinit(self: *NativeTargetInfo, allocator: *Allocator) void {
208 if (self.dynamic_linker) |dl| allocator.free(dl);
209 self.* = undefined;
210 }
211
212 /// The returned memory has the same lifetime as the `NativeTargetInfo`.208 /// The returned memory has the same lifetime as the `NativeTargetInfo`.
213 pub fn dynamicLinker(self: *const NativeTargetInfo) ?[]const u8 {209 pub fn dynamicLinker(self: *const NativeTargetInfo) ?[]const u8 {
214 const m = self.dynamic_linker_max orelse return null;210 const m: usize = self.dynamic_linker_max orelse return null;
215 return self.dynamic_linker_buffer[0 .. m + 1];211 return self.dynamic_linker_buffer[0 .. m + 1];
216 }212 }
217213
...@@ -228,13 +224,14 @@ pub const NativeTargetInfo = struct {...@@ -228,13 +224,14 @@ pub const NativeTargetInfo = struct {
228 /// linked, then it should answer both the C ABI question and the dynamic linker question.224 /// linked, then it should answer both the C ABI question and the dynamic linker question.
229 /// If it is statically linked, then we try /usr/bin/env. If that does not provide the answer, then225 /// If it is statically linked, then we try /usr/bin/env. If that does not provide the answer, then
230 /// we fall back to the defaults.226 /// we fall back to the defaults.
227 /// TODO Remove the Allocator requirement from this function.
231 fn detectAbiAndDynamicLinker(228 fn detectAbiAndDynamicLinker(
232 allocator: *Allocator,229 allocator: *Allocator,
233 cpu: Target.Cpu,230 cpu: Target.Cpu,
234 os: Target.Os,231 os: Target.Os,
235 ) DetectError!NativeTargetInfo {232 ) DetectError!NativeTargetInfo {
236 if (!comptime Target.current.hasDynamicLinker()) {233 if (!comptime Target.current.hasDynamicLinker()) {
237 return defaultAbiAndDynamicLinker(allocator, cpu, os);234 return defaultAbiAndDynamicLinker(cpu, os);
238 }235 }
239 // The current target's ABI cannot be relied on for this. For example, we may build the zig236 // The current target's ABI cannot be relied on for this. For example, we may build the zig
240 // compiler for target riscv64-linux-musl and provide a tarball for users to download.237 // compiler for target riscv64-linux-musl and provide a tarball for users to download.
...@@ -242,15 +239,15 @@ pub const NativeTargetInfo = struct {...@@ -242,15 +239,15 @@ pub const NativeTargetInfo = struct {
242 // and supported by Zig. But that means that we must detect the system ABI here rather than239 // and supported by Zig. But that means that we must detect the system ABI here rather than
243 // relying on `Target.current`.240 // relying on `Target.current`.
244 const LdInfo = struct {241 const LdInfo = struct {
245 ld_path: []u8,242 ld_path_buffer: [255]u8,
243 ld_path_max: u8,
246 abi: Target.Abi,244 abi: Target.Abi,
247 };
248 var ld_info_list = std.ArrayList(LdInfo).init(allocator);
249 defer {
250 for (ld_info_list.toSlice()) |ld_info| allocator.free(ld_info.ld_path);
251 ld_info_list.deinit();
252 }
253245
246 pub fn ldPath(self: *const @This()) []const u8 {
247 const m: usize = self.ld_path_max;
248 return self.ld_path_buffer[0 .. m + 1];
249 }
250 };
254 const all_abis = comptime blk: {251 const all_abis = comptime blk: {
255 assert(@enumToInt(Target.Abi.none) == 0);252 assert(@enumToInt(Target.Abi.none) == 0);
256 const fields = std.meta.fields(Target.Abi)[1..];253 const fields = std.meta.fields(Target.Abi)[1..];
...@@ -260,6 +257,9 @@ pub const NativeTargetInfo = struct {...@@ -260,6 +257,9 @@ pub const NativeTargetInfo = struct {
260 }257 }
261 break :blk array;258 break :blk array;
262 };259 };
260 var ld_info_list_buffer: [all_abis.len]LdInfo = undefined;
261 var ld_info_list_len: usize = 0;
262
263 for (all_abis) |abi| {263 for (all_abis) |abi| {
264 // This may be a nonsensical parameter. We detect this with error.UnknownDynamicLinkerPath and264 // This may be a nonsensical parameter. We detect this with error.UnknownDynamicLinkerPath and
265 // skip adding it to `ld_info_list`.265 // skip adding it to `ld_info_list`.
...@@ -268,17 +268,17 @@ pub const NativeTargetInfo = struct {...@@ -268,17 +268,17 @@ pub const NativeTargetInfo = struct {
268 .os = os,268 .os = os,
269 .abi = abi,269 .abi = abi,
270 };270 };
271 var buf: [255]u8 = undefined;271 const ld_info = &ld_info_list_buffer[ld_info_list_len];
272 const standard_ld_path = if (target.standardDynamicLinkerPath(&buf)) |s|272 ld_info_list_len += 1;
273 try mem.dupe(allocator, u8, s)273
274 else274 ld_info.* = .{
275 continue;275 .ld_path_buffer = undefined,
276 errdefer allocator.free(standard_ld_path);276 .ld_path_max = undefined,
277 try ld_info_list.append(.{
278 .ld_path = standard_ld_path,
279 .abi = abi,277 .abi = abi,
280 });278 };
279 ld_info.ld_path_max = target.standardDynamicLinkerPath(&ld_info.ld_path_buffer) orelse continue;
281 }280 }
281 const ld_info_list = ld_info_list_buffer[0..ld_info_list_len];
282282
283 // Best case scenario: the executable is dynamically linked, and we can iterate283 // Best case scenario: the executable is dynamically linked, and we can iterate
284 // over our own shared objects and find a dynamic linker.284 // over our own shared objects and find a dynamic linker.
...@@ -292,8 +292,8 @@ pub const NativeTargetInfo = struct {...@@ -292,8 +292,8 @@ pub const NativeTargetInfo = struct {
292 // Look for dynamic linker.292 // Look for dynamic linker.
293 // This is O(N^M) but typical case here is N=2 and M=10.293 // This is O(N^M) but typical case here is N=2 and M=10.
294 find_ld: for (lib_paths) |lib_path| {294 find_ld: for (lib_paths) |lib_path| {
295 for (ld_info_list.toSlice()) |ld_info| {295 for (ld_info_list) |ld_info| {
296 const standard_ld_basename = fs.path.basename(ld_info.ld_path);296 const standard_ld_basename = fs.path.basename(ld_info.ldPath());
297 if (std.mem.endsWith(u8, lib_path, standard_ld_basename)) {297 if (std.mem.endsWith(u8, lib_path, standard_ld_basename)) {
298 found_ld_info = ld_info;298 found_ld_info = ld_info;
299 found_ld_path = lib_path;299 found_ld_path = lib_path;
...@@ -355,7 +355,7 @@ pub const NativeTargetInfo = struct {...@@ -355,7 +355,7 @@ pub const NativeTargetInfo = struct {
355 error.UnexpectedEndOfFile,355 error.UnexpectedEndOfFile,
356 error.NameTooLong,356 error.NameTooLong,
357 // Finally, we fall back on the standard path.357 // Finally, we fall back on the standard path.
358 => defaultAbiAndDynamicLinker(allocator, cpu, os),358 => defaultAbiAndDynamicLinker(cpu, os),
359 };359 };
360 }360 }
361361
...@@ -502,7 +502,7 @@ pub const NativeTargetInfo = struct {...@@ -502,7 +502,7 @@ pub const NativeTargetInfo = struct {
502 };502 };
503 }503 }
504504
505 fn defaultAbiAndDynamicLinker(allocator: *Allocator, cpu: Target.Cpu, os: Target.Os) !NativeTargetInfo {505 fn defaultAbiAndDynamicLinker(cpu: Target.Cpu, os: Target.Os) !NativeTargetInfo {
506 var result: NativeTargetInfo = .{506 var result: NativeTargetInfo = .{
507 .target = .{507 .target = .{
508 .cpu = cpu,508 .cpu = cpu,
...@@ -510,9 +510,7 @@ pub const NativeTargetInfo = struct {...@@ -510,9 +510,7 @@ pub const NativeTargetInfo = struct {
510 .abi = Target.Abi.default(cpu.arch, os),510 .abi = Target.Abi.default(cpu.arch, os),
511 },511 },
512 };512 };
513 if (result.target.standardDynamicLinkerPath(&result.dynamic_linker_buffer)) |s| {513 result.dynamic_linker_max = result.target.standardDynamicLinkerPath(&result.dynamic_linker_buffer);
514 result.dynamic_linker_max = @intCast(u8, s.len - 1);
515 }
516 return result;514 return result;
517 }515 }
518};516};
src-self-hosted/stage2.zig+2-2
...@@ -1170,8 +1170,8 @@ fn crossTargetToTarget(cross_target: CrossTarget, dynamic_linker_ptr: *?[*:0]u8)...@@ -1170,8 +1170,8 @@ fn crossTargetToTarget(cross_target: CrossTarget, dynamic_linker_ptr: *?[*:0]u8)
1170 }1170 }
1171 if (!have_native_dl) {1171 if (!have_native_dl) {
1172 var buf: [255]u8 = undefined;1172 var buf: [255]u8 = undefined;
1173 dynamic_linker_ptr.* = if (adjusted_target.standardDynamicLinkerPath(&buf)) |s|1173 dynamic_linker_ptr.* = if (adjusted_target.standardDynamicLinkerPath(&buf)) |m|
1174 try mem.dupeZ(std.heap.c_allocator, u8, s)1174 try mem.dupeZ(std.heap.c_allocator, u8, buf[0 .. @as(usize, m) + 1])
1175 else1175 else
1176 null;1176 null;
1177 }1177 }