| ... | @@ -189,7 +189,9 @@ pub const NativeTargetInfo = struct { | ... | @@ -189,7 +189,9 @@ pub const NativeTargetInfo = struct { |
| 189 | | 189 | |
| 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 | } |
| 205 | | 207 | |
| 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 | } |
| 217 | | 213 | |
| ... | @@ -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, then | 225 | /// 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 zig | 236 | // 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 than | 239 | // 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 | } | | |
| 253 | | 245 | |
| | 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 and | 264 | // 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 | else | 274 | 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]; |
| 282 | | 282 | |
| 283 | // Best case scenario: the executable is dynamically linked, and we can iterate | 283 | // 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 | } |
| 361 | | 361 | |
| ... | @@ -502,7 +502,7 @@ pub const NativeTargetInfo = struct { | ... | @@ -502,7 +502,7 @@ pub const NativeTargetInfo = struct { |
| 502 | }; | 502 | }; |
| 503 | } | 503 | } |
| 504 | | 504 | |
| 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 | }; |