authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-02-28 17:23:16-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-02-28 17:23:16-05:00
log8691d3c50d65c3e9e399c83cf2fc1a1173acb6d2
tree3802ec6c7c817657e7850e90330c5ab8a2a8b3be
parent578dc16910c7fb6c9e3a059915b13fa6609e066f
signaturelock-open Commit is signed but in an unrecognized format.

improve std.zig.system.NativeTargetInfo.detect

It now takes a std.zig.CrossTarget parameter, and only resolves native things, leaving explicitly overridden things alone.

3 files changed, 140 insertions(+), 80 deletions(-)

lib/std/zig/cross_target.zig+11-7
...@@ -7,19 +7,17 @@ const mem = std.mem;...@@ -7,19 +7,17 @@ const mem = std.mem;
7/// The purpose of this abstraction is to provide meaningful and unsurprising defaults.7/// The purpose of this abstraction is to provide meaningful and unsurprising defaults.
8/// This struct does reference any resources and it is copyable.8/// This struct does reference any resources and it is copyable.
9pub const CrossTarget = struct {9pub const CrossTarget = struct {
10 /// `null` means native.10 /// `null` means native. If this is `null` then `cpu_model` must be `null`.
11 cpu_arch: ?Target.Cpu.Arch = null,11 cpu_arch: ?Target.Cpu.Arch = null,
1212
13 /// If `cpu_arch` is native, `null` means native. Otherwise it means baseline.13 /// `null` means native.
14 /// If this is non-null, `cpu_arch` must be specified.14 /// If this is non-null, `cpu_arch` must be specified.
15 cpu_model: ?*const Target.Cpu.Model = null,15 cpu_model: ?*const Target.Cpu.Model = null,
1616
17 /// Sparse set of CPU features to add to the set from `cpu_model`.17 /// Sparse set of CPU features to add to the set from `cpu_model`.
18 /// If this is non-empty, `cpu_arch` must be specified.
19 cpu_features_add: Target.Cpu.Feature.Set = Target.Cpu.Feature.Set.empty,18 cpu_features_add: Target.Cpu.Feature.Set = Target.Cpu.Feature.Set.empty,
2019
21 /// Sparse set of CPU features to remove from the set from `cpu_model`.20 /// Sparse set of CPU features to remove from the set from `cpu_model`.
22 /// If this is non-empty, `cpu_arch` must be specified.
23 cpu_features_sub: Target.Cpu.Feature.Set = Target.Cpu.Feature.Set.empty,21 cpu_features_sub: Target.Cpu.Feature.Set = Target.Cpu.Feature.Set.empty,
2422
25 /// `null` means native.23 /// `null` means native.
...@@ -33,13 +31,13 @@ pub const CrossTarget = struct {...@@ -33,13 +31,13 @@ pub const CrossTarget = struct {
33 /// When `os_tag` is native, `null` means equal to the native OS version.31 /// When `os_tag` is native, `null` means equal to the native OS version.
34 os_version_max: ?OsVersion = null,32 os_version_max: ?OsVersion = null,
3533
36 /// `null` means the native C ABI, if `os_tag` is native, otherwise it means the default C ABI.
37 abi: ?Target.Abi = null,
38
39 /// `null` means default when cross compiling, or native when os_tag is native.34 /// `null` means default when cross compiling, or native when os_tag is native.
40 /// If `isGnuLibC()` is `false`, this must be `null` and is ignored.35 /// If `isGnuLibC()` is `false`, this must be `null` and is ignored.
41 glibc_version: ?SemVer = null,36 glibc_version: ?SemVer = null,
4237
38 /// `null` means the native C ABI, if `os_tag` is native, otherwise it means the default C ABI.
39 abi: ?Target.Abi = null,
40
43 /// When `os_tag` is `null`, then `null` means native. Otherwise it means the standard path41 /// When `os_tag` is `null`, then `null` means native. Otherwise it means the standard path
44 /// based on the `os_tag`.42 /// based on the `os_tag`.
45 dynamic_linker: DynamicLinker = DynamicLinker{},43 dynamic_linker: DynamicLinker = DynamicLinker{},
...@@ -146,6 +144,7 @@ pub const CrossTarget = struct {...@@ -146,6 +144,7 @@ pub const CrossTarget = struct {
146 }144 }
147 }145 }
148146
147 /// TODO deprecated, use `std.zig.system.NativeTargetInfo.detect`.
149 pub fn toTarget(self: CrossTarget) Target {148 pub fn toTarget(self: CrossTarget) Target {
150 return .{149 return .{
151 .cpu = self.getCpu(),150 .cpu = self.getCpu(),
...@@ -307,6 +306,7 @@ pub const CrossTarget = struct {...@@ -307,6 +306,7 @@ pub const CrossTarget = struct {
307 return result;306 return result;
308 }307 }
309308
309 /// TODO deprecated, use `std.zig.system.NativeTargetInfo.detect`.
310 pub fn getCpu(self: CrossTarget) Target.Cpu {310 pub fn getCpu(self: CrossTarget) Target.Cpu {
311 if (self.cpu_arch) |arch| {311 if (self.cpu_arch) |arch| {
312 if (self.cpu_model) |model| {312 if (self.cpu_model) |model| {
...@@ -342,6 +342,7 @@ pub const CrossTarget = struct {...@@ -342,6 +342,7 @@ pub const CrossTarget = struct {
342 return self.getCpu().features;342 return self.getCpu().features;
343 }343 }
344344
345 /// TODO deprecated, use `std.zig.system.NativeTargetInfo.detect`.
345 pub fn getOs(self: CrossTarget) Target.Os {346 pub fn getOs(self: CrossTarget) Target.Os {
346 // `Target.current.os` works when doing `zig build` because Zig generates a build executable using347 // `Target.current.os` works when doing `zig build` because Zig generates a build executable using
347 // native OS version range. However this will not be accurate otherwise, and348 // native OS version range. However this will not be accurate otherwise, and
...@@ -378,6 +379,7 @@ pub const CrossTarget = struct {...@@ -378,6 +379,7 @@ pub const CrossTarget = struct {
378 return self.os_tag orelse Target.current.os.tag;379 return self.os_tag orelse Target.current.os.tag;
379 }380 }
380381
382 /// TODO deprecated, use `std.zig.system.NativeTargetInfo.detect`.
381 pub fn getOsVersionMin(self: CrossTarget) OsVersion {383 pub fn getOsVersionMin(self: CrossTarget) OsVersion {
382 if (self.os_version_min) |version_min| return version_min;384 if (self.os_version_min) |version_min| return version_min;
383 var tmp: CrossTarget = undefined;385 var tmp: CrossTarget = undefined;
...@@ -385,6 +387,7 @@ pub const CrossTarget = struct {...@@ -385,6 +387,7 @@ pub const CrossTarget = struct {
385 return tmp.os_version_min.?;387 return tmp.os_version_min.?;
386 }388 }
387389
390 /// TODO deprecated, use `std.zig.system.NativeTargetInfo.detect`.
388 pub fn getOsVersionMax(self: CrossTarget) OsVersion {391 pub fn getOsVersionMax(self: CrossTarget) OsVersion {
389 if (self.os_version_max) |version_max| return version_max;392 if (self.os_version_max) |version_max| return version_max;
390 var tmp: CrossTarget = undefined;393 var tmp: CrossTarget = undefined;
...@@ -392,6 +395,7 @@ pub const CrossTarget = struct {...@@ -392,6 +395,7 @@ pub const CrossTarget = struct {
392 return tmp.os_version_max.?;395 return tmp.os_version_max.?;
393 }396 }
394397
398 /// TODO deprecated, use `std.zig.system.NativeTargetInfo.detect`.
395 pub fn getAbi(self: CrossTarget) Target.Abi {399 pub fn getAbi(self: CrossTarget) Target.Abi {
396 if (self.abi) |abi| return abi;400 if (self.abi) |abi| return abi;
397401
lib/std/zig/system.zig+114-38
...@@ -7,6 +7,7 @@ const ArrayList = std.ArrayList;...@@ -7,6 +7,7 @@ const ArrayList = std.ArrayList;
7const assert = std.debug.assert;7const assert = std.debug.assert;
8const process = std.process;8const process = std.process;
9const Target = std.Target;9const Target = std.Target;
10const CrossTarget = std.zig.CrossTarget;
1011
11const is_windows = Target.current.os.tag == .windows;12const is_windows = Target.current.os.tag == .windows;
1213
...@@ -182,37 +183,87 @@ pub const NativeTargetInfo = struct {...@@ -182,37 +183,87 @@ pub const NativeTargetInfo = struct {
182 DeviceBusy,183 DeviceBusy,
183 };184 };
184185
185 /// Detects the native CPU model & features, operating system & version, and C ABI & dynamic linker.186 /// Given a `CrossTarget`, which specifies in detail which parts of the target should be detected
186 /// On Linux, this is additionally responsible for detecting the native glibc version when applicable.187 /// natively, which should be standard or default, and which are provided explicitly, this function
188 /// resolves the native components by detecting the native system, and then resolves standard/default parts
189 /// relative to that.
187 /// Any resources this function allocates are released before returning, and so there is no190 /// Any resources this function allocates are released before returning, and so there is no
188 /// deinitialization method.191 /// deinitialization method.
189 /// TODO Remove the Allocator requirement from this function.192 /// TODO Remove the Allocator requirement from this function.
190 pub fn detect(allocator: *Allocator) DetectError!NativeTargetInfo {193 pub fn detect(allocator: *Allocator, cross_target: CrossTarget) DetectError!NativeTargetInfo {
191 const arch = Target.current.cpu.arch;194 const cpu = blk: {
192 const os_tag = Target.current.os.tag;195 if (cross_target.cpu_arch) |arch| {
193196 if (cross_target.cpu_model) |model| {
194 // TODO Detect native CPU model & features. Until that is implemented we hard code baseline.197 var adjusted_model = model.toCpu(arch);
195 const cpu = Target.Cpu.baseline(arch);198 cross_target.updateCpuFeatures(&adjusted_model.features);
196199 break :blk adjusted_model;
197 // TODO Detect native operating system version. Until that is implemented we use the default range.200 } else {
198 var os = Target.Os.defaultVersionRange(os_tag);201 // TODO Detect native CPU model. Until that is implemented we use baseline.
199 switch (Target.current.os.tag) {202 var adjusted_baseline = Target.Cpu.baseline(arch);
200 .linux => {203 cross_target.updateCpuFeatures(&adjusted_baseline.features);
201 const uts = std.os.uname();204 break :blk adjusted_baseline;
202 const release = mem.toSliceConst(u8, @ptrCast([*:0]const u8, &uts.release));
203 if (std.builtin.Version.parse(release)) |ver| {
204 os.version_range.linux.range.min = ver;
205 os.version_range.linux.range.max = ver;
206 } else |err| switch (err) {
207 error.Overflow => {},
208 error.InvalidCharacter => {},
209 error.InvalidVersion => {},
210 }205 }
206 } else {
207 assert(cross_target.cpu_model == null);
208 // TODO Detect native CPU model & features. Until that is implemented we use baseline.
209 var adjusted_baseline = Target.Cpu.baseline(Target.current.cpu.arch);
210 cross_target.updateCpuFeatures(&adjusted_baseline.features);
211 break :blk adjusted_baseline;
212 }
213 };
214
215 var os = Target.Os.defaultVersionRange(cross_target.getOsTag());
216 if (cross_target.os_tag == null) {
217 switch (Target.current.os.tag) {
218 .linux => {
219 const uts = std.os.uname();
220 const release = mem.toSliceConst(u8, @ptrCast([*:0]const u8, &uts.release));
221 if (std.builtin.Version.parse(release)) |ver| {
222 os.version_range.linux.range.min = ver;
223 os.version_range.linux.range.max = ver;
224 } else |err| switch (err) {
225 error.Overflow => {},
226 error.InvalidCharacter => {},
227 error.InvalidVersion => {},
228 }
229 },
230 .windows => {
231 // TODO Detect native operating system version.
232 },
233 .macosx => {
234 // TODO Detect native operating system version.
235 },
236 .freebsd => {
237 // TODO Detect native operating system version.
238 },
239 else => {},
240 }
241 }
242
243 if (cross_target.os_version_min) |min| switch (min) {
244 .none => {},
245 .semver => |semver| switch (cross_target.getOsTag()) {
246 .linux => os.version_range.linux.range.min = semver,
247 else => os.version_range.semver.min = semver,
248 },
249 .windows => |win_ver| os.version_range.windows.min = win_ver,
250 };
251
252 if (cross_target.os_version_max) |max| switch (max) {
253 .none => {},
254 .semver => |semver| switch (cross_target.getOsTag()) {
255 .linux => os.version_range.linux.range.max = semver,
256 else => os.version_range.semver.max = semver,
211 },257 },
212 else => {},258 .windows => |win_ver| os.version_range.windows.max = win_ver,
259 };
260
261 if (cross_target.glibc_version) |glibc| {
262 assert(cross_target.isGnuLibC());
263 os.version_range.linux.glibc = glibc;
213 }264 }
214265
215 return detectAbiAndDynamicLinker(allocator, cpu, os);266 return detectAbiAndDynamicLinker(allocator, cpu, os, cross_target);
216 }267 }
217268
218 /// First we attempt to use the executable's own binary. If it is dynamically269 /// First we attempt to use the executable's own binary. If it is dynamically
...@@ -224,9 +275,14 @@ pub const NativeTargetInfo = struct {...@@ -224,9 +275,14 @@ pub const NativeTargetInfo = struct {
224 allocator: *Allocator,275 allocator: *Allocator,
225 cpu: Target.Cpu,276 cpu: Target.Cpu,
226 os: Target.Os,277 os: Target.Os,
278 cross_target: CrossTarget,
227 ) DetectError!NativeTargetInfo {279 ) DetectError!NativeTargetInfo {
228 if (!comptime Target.current.hasDynamicLinker()) {280 const native_target_has_ld = comptime Target.current.hasDynamicLinker();
229 return defaultAbiAndDynamicLinker(cpu, os);281 const is_linux = Target.current.os.tag == .linux;
282 const have_all_info = cross_target.dynamic_linker.get() != null and
283 cross_target.abi != null and (!is_linux or cross_target.abi.?.isGnu());
284 if (!native_target_has_ld or have_all_info) {
285 return defaultAbiAndDynamicLinker(cpu, os, cross_target);
230 }286 }
231 // The current target's ABI cannot be relied on for this. For example, we may build the zig287 // The current target's ABI cannot be relied on for this. For example, we may build the zig
232 // compiler for target riscv64-linux-musl and provide a tarball for users to download.288 // compiler for target riscv64-linux-musl and provide a tarball for users to download.
...@@ -264,6 +320,13 @@ pub const NativeTargetInfo = struct {...@@ -264,6 +320,13 @@ pub const NativeTargetInfo = struct {
264 }320 }
265 const ld_info_list = ld_info_list_buffer[0..ld_info_list_len];321 const ld_info_list = ld_info_list_buffer[0..ld_info_list_len];
266322
323 if (cross_target.dynamic_linker.get()) |explicit_ld| {
324 const explicit_ld_basename = fs.path.basename(explicit_ld);
325 for (ld_info_list) |ld_info| {
326 const standard_ld_basename = fs.path.basename(ld_info.ld.get().?);
327 }
328 }
329
267 // Best case scenario: the executable is dynamically linked, and we can iterate330 // Best case scenario: the executable is dynamically linked, and we can iterate
268 // over our own shared objects and find a dynamic linker.331 // over our own shared objects and find a dynamic linker.
269 self_exe: {332 self_exe: {
...@@ -288,7 +351,9 @@ pub const NativeTargetInfo = struct {...@@ -288,7 +351,9 @@ pub const NativeTargetInfo = struct {
288351
289 // Look for glibc version.352 // Look for glibc version.
290 var os_adjusted = os;353 var os_adjusted = os;
291 if (Target.current.os.tag == .linux and found_ld_info.abi.isGnu()) {354 if (Target.current.os.tag == .linux and found_ld_info.abi.isGnu() and
355 cross_target.glibc_version == null)
356 {
292 for (lib_paths) |lib_path| {357 for (lib_paths) |lib_path| {
293 if (std.mem.endsWith(u8, lib_path, glibc_so_basename)) {358 if (std.mem.endsWith(u8, lib_path, glibc_so_basename)) {
294 os_adjusted.version_range.linux.glibc = glibcVerFromSO(lib_path) catch |err| switch (err) {359 os_adjusted.version_range.linux.glibc = glibcVerFromSO(lib_path) catch |err| switch (err) {
...@@ -306,9 +371,12 @@ pub const NativeTargetInfo = struct {...@@ -306,9 +371,12 @@ pub const NativeTargetInfo = struct {
306 .target = .{371 .target = .{
307 .cpu = cpu,372 .cpu = cpu,
308 .os = os_adjusted,373 .os = os_adjusted,
309 .abi = found_ld_info.abi,374 .abi = cross_target.abi orelse found_ld_info.abi,
310 },375 },
311 .dynamic_linker = DynamicLinker.init(found_ld_path),376 .dynamic_linker = if (cross_target.dynamic_linker.get() == null)
377 DynamicLinker.init(found_ld_path)
378 else
379 cross_target.dynamic_linker,
312 };380 };
313 return result;381 return result;
314 }382 }
...@@ -317,7 +385,7 @@ pub const NativeTargetInfo = struct {...@@ -317,7 +385,7 @@ pub const NativeTargetInfo = struct {
317 // trick won't work. The next thing we fall back to is the same thing, but for /usr/bin/env.385 // trick won't work. The next thing we fall back to is the same thing, but for /usr/bin/env.
318 // Since that path is hard-coded into the shebang line of many portable scripts, it's a386 // Since that path is hard-coded into the shebang line of many portable scripts, it's a
319 // reasonably reliable path to check for.387 // reasonably reliable path to check for.
320 return abiAndDynamicLinkerFromUsrBinEnv(cpu, os, ld_info_list) catch |err| switch (err) {388 return abiAndDynamicLinkerFromUsrBinEnv(cpu, os, ld_info_list, cross_target) catch |err| switch (err) {
321 error.FileSystem,389 error.FileSystem,
322 error.SystemResources,390 error.SystemResources,
323 error.SymLinkLoop,391 error.SymLinkLoop,
...@@ -337,7 +405,7 @@ pub const NativeTargetInfo = struct {...@@ -337,7 +405,7 @@ pub const NativeTargetInfo = struct {
337 error.UnexpectedEndOfFile,405 error.UnexpectedEndOfFile,
338 error.NameTooLong,406 error.NameTooLong,
339 // Finally, we fall back on the standard path.407 // Finally, we fall back on the standard path.
340 => defaultAbiAndDynamicLinker(cpu, os),408 => defaultAbiAndDynamicLinker(cpu, os, cross_target),
341 };409 };
342 }410 }
343411
...@@ -379,6 +447,7 @@ pub const NativeTargetInfo = struct {...@@ -379,6 +447,7 @@ pub const NativeTargetInfo = struct {
379 cpu: Target.Cpu,447 cpu: Target.Cpu,
380 os: Target.Os,448 os: Target.Os,
381 ld_info_list: []const LdInfo,449 ld_info_list: []const LdInfo,
450 cross_target: CrossTarget,
382 ) !NativeTargetInfo {451 ) !NativeTargetInfo {
383 const env_file = std.fs.openFileAbsoluteC("/usr/bin/env", .{}) catch |err| switch (err) {452 const env_file = std.fs.openFileAbsoluteC("/usr/bin/env", .{}) catch |err| switch (err) {
384 error.NoSpaceLeft => unreachable,453 error.NoSpaceLeft => unreachable,
...@@ -424,10 +493,12 @@ pub const NativeTargetInfo = struct {...@@ -424,10 +493,12 @@ pub const NativeTargetInfo = struct {
424 .target = .{493 .target = .{
425 .cpu = cpu,494 .cpu = cpu,
426 .os = os,495 .os = os,
427 .abi = Target.Abi.default(cpu.arch, os),496 .abi = cross_target.abi orelse Target.Abi.default(cpu.arch, os),
428 },497 },
498 .dynamic_linker = cross_target.dynamic_linker,
429 };499 };
430 var rpath_offset: ?u64 = null; // Found inside PT_DYNAMIC500 var rpath_offset: ?u64 = null; // Found inside PT_DYNAMIC
501 const look_for_ld = cross_target.dynamic_linker.get() == null;
431502
432 var ph_buf: [16 * @sizeOf(elf.Elf64_Phdr)]u8 align(@alignOf(elf.Elf64_Phdr)) = undefined;503 var ph_buf: [16 * @sizeOf(elf.Elf64_Phdr)]u8 align(@alignOf(elf.Elf64_Phdr)) = undefined;
433 if (phentsize > @sizeOf(elf.Elf64_Phdr)) return error.InvalidElfFile;504 if (phentsize > @sizeOf(elf.Elf64_Phdr)) return error.InvalidElfFile;
...@@ -448,7 +519,7 @@ pub const NativeTargetInfo = struct {...@@ -448,7 +519,7 @@ pub const NativeTargetInfo = struct {
448 const ph64 = @ptrCast(*elf.Elf64_Phdr, @alignCast(@alignOf(elf.Elf64_Phdr), &ph_buf[ph_buf_i]));519 const ph64 = @ptrCast(*elf.Elf64_Phdr, @alignCast(@alignOf(elf.Elf64_Phdr), &ph_buf[ph_buf_i]));
449 const p_type = elfInt(is_64, need_bswap, ph32.p_type, ph64.p_type);520 const p_type = elfInt(is_64, need_bswap, ph32.p_type, ph64.p_type);
450 switch (p_type) {521 switch (p_type) {
451 elf.PT_INTERP => {522 elf.PT_INTERP => if (look_for_ld) {
452 const p_offset = elfInt(is_64, need_bswap, ph32.p_offset, ph64.p_offset);523 const p_offset = elfInt(is_64, need_bswap, ph32.p_offset, ph64.p_offset);
453 const p_filesz = elfInt(is_64, need_bswap, ph32.p_filesz, ph64.p_filesz);524 const p_filesz = elfInt(is_64, need_bswap, ph32.p_filesz, ph64.p_filesz);
454 if (p_filesz > result.dynamic_linker.buffer.len) return error.NameTooLong;525 if (p_filesz > result.dynamic_linker.buffer.len) return error.NameTooLong;
...@@ -470,7 +541,9 @@ pub const NativeTargetInfo = struct {...@@ -470,7 +541,9 @@ pub const NativeTargetInfo = struct {
470 }541 }
471 },542 },
472 // We only need this for detecting glibc version.543 // We only need this for detecting glibc version.
473 elf.PT_DYNAMIC => if (Target.current.os.tag == .linux and result.target.isGnuLibC()) {544 elf.PT_DYNAMIC => if (Target.current.os.tag == .linux and result.target.isGnuLibC() and
545 cross_target.glibc_version == null)
546 {
474 var dyn_off = elfInt(is_64, need_bswap, ph32.p_offset, ph64.p_offset);547 var dyn_off = elfInt(is_64, need_bswap, ph32.p_offset, ph64.p_offset);
475 const p_filesz = elfInt(is_64, need_bswap, ph32.p_filesz, ph64.p_filesz);548 const p_filesz = elfInt(is_64, need_bswap, ph32.p_filesz, ph64.p_filesz);
476 const dyn_size: u64 = if (is_64) @sizeOf(elf.Elf64_Dyn) else @sizeOf(elf.Elf32_Dyn);549 const dyn_size: u64 = if (is_64) @sizeOf(elf.Elf64_Dyn) else @sizeOf(elf.Elf32_Dyn);
...@@ -515,7 +588,7 @@ pub const NativeTargetInfo = struct {...@@ -515,7 +588,7 @@ pub const NativeTargetInfo = struct {
515 }588 }
516 }589 }
517590
518 if (Target.current.os.tag == .linux and result.target.isGnuLibC()) {591 if (Target.current.os.tag == .linux and result.target.isGnuLibC() and cross_target.glibc_version == null) {
519 if (rpath_offset) |rpoff| {592 if (rpath_offset) |rpoff| {
520 const shstrndx = elfInt(is_64, need_bswap, hdr32.e_shstrndx, hdr64.e_shstrndx);593 const shstrndx = elfInt(is_64, need_bswap, hdr32.e_shstrndx, hdr64.e_shstrndx);
521594
...@@ -657,15 +730,18 @@ pub const NativeTargetInfo = struct {...@@ -657,15 +730,18 @@ pub const NativeTargetInfo = struct {
657 return i;730 return i;
658 }731 }
659732
660 fn defaultAbiAndDynamicLinker(cpu: Target.Cpu, os: Target.Os) !NativeTargetInfo {733 fn defaultAbiAndDynamicLinker(cpu: Target.Cpu, os: Target.Os, cross_target: CrossTarget) !NativeTargetInfo {
661 const target: Target = .{734 const target: Target = .{
662 .cpu = cpu,735 .cpu = cpu,
663 .os = os,736 .os = os,
664 .abi = Target.Abi.default(cpu.arch, os),737 .abi = cross_target.abi orelse Target.Abi.default(cpu.arch, os),
665 };738 };
666 return NativeTargetInfo{739 return NativeTargetInfo{
667 .target = target,740 .target = target,
668 .dynamic_linker = target.standardDynamicLinkerPath(),741 .dynamic_linker = if (cross_target.dynamic_linker.get() == null)
742 target.standardDynamicLinkerPath()
743 else
744 cross_target.dynamic_linker,
669 };745 };
670 }746 }
671747
src-self-hosted/stage2.zig+15-35
...@@ -1152,44 +1152,24 @@ fn enumInt(comptime Enum: type, int: c_int) Enum {...@@ -1152,44 +1152,24 @@ fn enumInt(comptime Enum: type, int: c_int) Enum {
1152 return @intToEnum(Enum, @intCast(@TagType(Enum), int));1152 return @intToEnum(Enum, @intCast(@TagType(Enum), int));
1153}1153}
11541154
1155/// TODO move dynamic linker to be part of the target
1156/// TODO self-host this function
1157fn crossTargetToTarget(cross_target: CrossTarget, dynamic_linker_ptr: *?[*:0]u8) !Target {1155fn crossTargetToTarget(cross_target: CrossTarget, dynamic_linker_ptr: *?[*:0]u8) !Target {
1158 var adjusted_target = cross_target.toTarget();1156 var info = try std.zig.system.NativeTargetInfo.detect(std.heap.c_allocator, cross_target);
1159 var have_native_dl = false;1157 if (cross_target.cpu_arch == null or cross_target.cpu_model == null) {
1160 if (cross_target.cpu_arch == null or cross_target.os_tag == null) {1158 // TODO We want to just use detected_info.target but implementing
1161 const detected_info = try std.zig.system.NativeTargetInfo.detect(std.heap.c_allocator);1159 // CPU model & feature detection is todo so here we rely on LLVM.
1162 if (cross_target.cpu_arch == null) {1160 const llvm = @import("llvm.zig");
1163 adjusted_target.cpu = detected_info.target.cpu;1161 const llvm_cpu_name = llvm.GetHostCPUName();
11641162 const llvm_cpu_features = llvm.GetNativeFeatures();
1165 // TODO We want to just use detected_info.target but implementing1163 const arch = std.Target.current.cpu.arch;
1166 // CPU model & feature detection is todo so here we rely on LLVM.1164 info.target.cpu = try detectNativeCpuWithLLVM(arch, llvm_cpu_name, llvm_cpu_features);
1167 // There is another occurrence of this; search for detectNativeCpuWithLLVM.1165 cross_target.updateCpuFeatures(&info.target.cpu.features);
1168 const llvm = @import("llvm.zig");
1169 const llvm_cpu_name = llvm.GetHostCPUName();
1170 const llvm_cpu_features = llvm.GetNativeFeatures();
1171 const arch = std.Target.current.cpu.arch;
1172 adjusted_target.cpu = try detectNativeCpuWithLLVM(arch, llvm_cpu_name, llvm_cpu_features);
1173 }
1174 if (cross_target.os_tag == null) {
1175 adjusted_target.os = detected_info.target.os;
1176
1177 if (detected_info.dynamic_linker.get()) |dl| {
1178 have_native_dl = true;
1179 dynamic_linker_ptr.* = try mem.dupeZ(std.heap.c_allocator, u8, dl);
1180 }
1181 if (cross_target.abi == null) {
1182 adjusted_target.abi = detected_info.target.abi;
1183 }
1184 } else if (cross_target.abi == null) {
1185 adjusted_target.abi = Target.Abi.default(adjusted_target.cpu.arch, adjusted_target.os);
1186 }
1187 }1166 }
1188 if (!have_native_dl) {1167 if (info.dynamic_linker.get()) |dl| {
1189 const dl = adjusted_target.standardDynamicLinkerPath();1168 dynamic_linker_ptr.* = try mem.dupeZ(std.heap.c_allocator, u8, dl);
1190 dynamic_linker_ptr.* = if (dl.get()) |s| try mem.dupeZ(std.heap.c_allocator, u8, s) else null;1169 } else {
1170 dynamic_linker_ptr.* = null;
1191 }1171 }
1192 return adjusted_target;1172 return info.target;
1193}1173}
11941174
1195// ABI warning1175// ABI warning