| author | |
| committer | |
| log | 0cd87102221233c2885faccfcaaac297b8d3b656 |
| tree | 398202b27b782976d0971b26e5627837d99788de |
| parent | b24cbecdb2abb4399d65553ebade318263cd57d3 |
Previously when using `zig run` or `zig test`, zig would try to guess
whether the host system was capable of running the target binaries. Now,
it will always try. If it fails, then Zig emits a helpful warning to
explain the probable cause.2 files changed, 90 insertions(+), 47 deletions(-)
lib/std/build.zig+43-28| ... | @@ -2527,45 +2527,56 @@ pub const LibExeObjStep = struct { | ... | @@ -2527,45 +2527,56 @@ pub const LibExeObjStep = struct { |
| 2527 | } | 2527 | } |
| 2528 | } | 2528 | } |
| 2529 | } else switch (self.target.getExternalExecutor()) { | 2529 | } else switch (self.target.getExternalExecutor()) { |
| 2530 | .native, .unavailable => {}, | 2530 | .native => {}, |
| 2531 | .unavailable => { | ||
| 2532 | try zig_args.append("--test-no-exec"); | ||
| 2533 | }, | ||
| 2531 | .rosetta => if (builder.enable_rosetta) { | 2534 | .rosetta => if (builder.enable_rosetta) { |
| 2532 | try zig_args.append("--test-cmd-bin"); | 2535 | try zig_args.append("--test-cmd-bin"); |
| 2536 | } else { | ||
| 2537 | try zig_args.append("--test-no-exec"); | ||
| 2533 | }, | 2538 | }, |
| 2534 | .qemu => |bin_name| if (builder.enable_qemu) qemu: { | 2539 | .qemu => |bin_name| ok: { |
| 2535 | const need_cross_glibc = self.target.isGnuLibC() and self.is_linking_libc; | 2540 | if (builder.enable_qemu) qemu: { |
| 2536 | const glibc_dir_arg = if (need_cross_glibc) | 2541 | const need_cross_glibc = self.target.isGnuLibC() and self.is_linking_libc; |
| 2537 | builder.glibc_runtimes_dir orelse break :qemu | 2542 | const glibc_dir_arg = if (need_cross_glibc) |
| 2538 | else | 2543 | builder.glibc_runtimes_dir orelse break :qemu |
| 2539 | null; | ||
| 2540 | try zig_args.append("--test-cmd"); | ||
| 2541 | try zig_args.append(bin_name); | ||
| 2542 | if (glibc_dir_arg) |dir| { | ||
| 2543 | // TODO look into making this a call to `linuxTriple`. This | ||
| 2544 | // needs the directory to be called "i686" rather than | ||
| 2545 | // "i386" which is why we do it manually here. | ||
| 2546 | const fmt_str = "{s}" ++ fs.path.sep_str ++ "{s}-{s}-{s}"; | ||
| 2547 | const cpu_arch = self.target.getCpuArch(); | ||
| 2548 | const os_tag = self.target.getOsTag(); | ||
| 2549 | const abi = self.target.getAbi(); | ||
| 2550 | const cpu_arch_name: []const u8 = if (cpu_arch == .i386) | ||
| 2551 | "i686" | ||
| 2552 | else | 2544 | else |
| 2553 | @tagName(cpu_arch); | 2545 | null; |
| 2554 | const full_dir = try std.fmt.allocPrint(builder.allocator, fmt_str, .{ | ||
| 2555 | dir, cpu_arch_name, @tagName(os_tag), @tagName(abi), | ||
| 2556 | }); | ||
| 2557 | |||
| 2558 | try zig_args.append("--test-cmd"); | 2546 | try zig_args.append("--test-cmd"); |
| 2559 | try zig_args.append("-L"); | 2547 | try zig_args.append(bin_name); |
| 2560 | try zig_args.append("--test-cmd"); | 2548 | if (glibc_dir_arg) |dir| { |
| 2561 | try zig_args.append(full_dir); | 2549 | // TODO look into making this a call to `linuxTriple`. This |
| 2550 | // needs the directory to be called "i686" rather than | ||
| 2551 | // "i386" which is why we do it manually here. | ||
| 2552 | const fmt_str = "{s}" ++ fs.path.sep_str ++ "{s}-{s}-{s}"; | ||
| 2553 | const cpu_arch = self.target.getCpuArch(); | ||
| 2554 | const os_tag = self.target.getOsTag(); | ||
| 2555 | const abi = self.target.getAbi(); | ||
| 2556 | const cpu_arch_name: []const u8 = if (cpu_arch == .i386) | ||
| 2557 | "i686" | ||
| 2558 | else | ||
| 2559 | @tagName(cpu_arch); | ||
| 2560 | const full_dir = try std.fmt.allocPrint(builder.allocator, fmt_str, .{ | ||
| 2561 | dir, cpu_arch_name, @tagName(os_tag), @tagName(abi), | ||
| 2562 | }); | ||
| 2563 | |||
| 2564 | try zig_args.append("--test-cmd"); | ||
| 2565 | try zig_args.append("-L"); | ||
| 2566 | try zig_args.append("--test-cmd"); | ||
| 2567 | try zig_args.append(full_dir); | ||
| 2568 | } | ||
| 2569 | try zig_args.append("--test-cmd-bin"); | ||
| 2570 | break :ok; | ||
| 2562 | } | 2571 | } |
| 2563 | try zig_args.append("--test-cmd-bin"); | 2572 | try zig_args.append("--test-no-exec"); |
| 2564 | }, | 2573 | }, |
| 2565 | .wine => |bin_name| if (builder.enable_wine) { | 2574 | .wine => |bin_name| if (builder.enable_wine) { |
| 2566 | try zig_args.append("--test-cmd"); | 2575 | try zig_args.append("--test-cmd"); |
| 2567 | try zig_args.append(bin_name); | 2576 | try zig_args.append(bin_name); |
| 2568 | try zig_args.append("--test-cmd-bin"); | 2577 | try zig_args.append("--test-cmd-bin"); |
| 2578 | } else { | ||
| 2579 | try zig_args.append("--test-no-exec"); | ||
| 2569 | }, | 2580 | }, |
| 2570 | .wasmtime => |bin_name| if (builder.enable_wasmtime) { | 2581 | .wasmtime => |bin_name| if (builder.enable_wasmtime) { |
| 2571 | try zig_args.append("--test-cmd"); | 2582 | try zig_args.append("--test-cmd"); |
| ... | @@ -2573,11 +2584,15 @@ pub const LibExeObjStep = struct { | ... | @@ -2573,11 +2584,15 @@ pub const LibExeObjStep = struct { |
| 2573 | try zig_args.append("--test-cmd"); | 2584 | try zig_args.append("--test-cmd"); |
| 2574 | try zig_args.append("--dir=."); | 2585 | try zig_args.append("--dir=."); |
| 2575 | try zig_args.append("--test-cmd-bin"); | 2586 | try zig_args.append("--test-cmd-bin"); |
| 2587 | } else { | ||
| 2588 | try zig_args.append("--test-no-exec"); | ||
| 2576 | }, | 2589 | }, |
| 2577 | .darling => |bin_name| if (builder.enable_darling) { | 2590 | .darling => |bin_name| if (builder.enable_darling) { |
| 2578 | try zig_args.append("--test-cmd"); | 2591 | try zig_args.append("--test-cmd"); |
| 2579 | try zig_args.append(bin_name); | 2592 | try zig_args.append(bin_name); |
| 2580 | try zig_args.append("--test-cmd-bin"); | 2593 | try zig_args.append("--test-cmd-bin"); |
| 2594 | } else { | ||
| 2595 | try zig_args.append("--test-no-exec"); | ||
| 2581 | }, | 2596 | }, |
| 2582 | } | 2597 | } |
| 2583 | 2598 |
src/main.zig+47-19| ... | @@ -2534,7 +2534,7 @@ fn buildOutputType( | ... | @@ -2534,7 +2534,7 @@ fn buildOutputType( |
| 2534 | test_exec_args.items, | 2534 | test_exec_args.items, |
| 2535 | self_exe_path, | 2535 | self_exe_path, |
| 2536 | arg_mode, | 2536 | arg_mode, |
| 2537 | target_info.target, | 2537 | target_info, |
| 2538 | watch, | 2538 | watch, |
| 2539 | &comp_destroyed, | 2539 | &comp_destroyed, |
| 2540 | all_args, | 2540 | all_args, |
| ... | @@ -2606,7 +2606,7 @@ fn buildOutputType( | ... | @@ -2606,7 +2606,7 @@ fn buildOutputType( |
| 2606 | test_exec_args.items, | 2606 | test_exec_args.items, |
| 2607 | self_exe_path, | 2607 | self_exe_path, |
| 2608 | arg_mode, | 2608 | arg_mode, |
| 2609 | target_info.target, | 2609 | target_info, |
| 2610 | watch, | 2610 | watch, |
| 2611 | &comp_destroyed, | 2611 | &comp_destroyed, |
| 2612 | all_args, | 2612 | all_args, |
| ... | @@ -2631,7 +2631,7 @@ fn buildOutputType( | ... | @@ -2631,7 +2631,7 @@ fn buildOutputType( |
| 2631 | test_exec_args.items, | 2631 | test_exec_args.items, |
| 2632 | self_exe_path, | 2632 | self_exe_path, |
| 2633 | arg_mode, | 2633 | arg_mode, |
| 2634 | target_info.target, | 2634 | target_info, |
| 2635 | watch, | 2635 | watch, |
| 2636 | &comp_destroyed, | 2636 | &comp_destroyed, |
| 2637 | all_args, | 2637 | all_args, |
| ... | @@ -2695,7 +2695,7 @@ fn runOrTest( | ... | @@ -2695,7 +2695,7 @@ fn runOrTest( |
| 2695 | test_exec_args: []const ?[]const u8, | 2695 | test_exec_args: []const ?[]const u8, |
| 2696 | self_exe_path: []const u8, | 2696 | self_exe_path: []const u8, |
| 2697 | arg_mode: ArgMode, | 2697 | arg_mode: ArgMode, |
| 2698 | target: std.Target, | 2698 | target_info: std.zig.system.NativeTargetInfo, |
| 2699 | watch: bool, | 2699 | watch: bool, |
| 2700 | comp_destroyed: *bool, | 2700 | comp_destroyed: *bool, |
| 2701 | all_args: []const []const u8, | 2701 | all_args: []const []const u8, |
| ... | @@ -2711,20 +2711,6 @@ fn runOrTest( | ... | @@ -2711,20 +2711,6 @@ fn runOrTest( |
| 2711 | defer argv.deinit(); | 2711 | defer argv.deinit(); |
| 2712 | 2712 | ||
| 2713 | if (test_exec_args.len == 0) { | 2713 | if (test_exec_args.len == 0) { |
| 2714 | if (!builtin.target.canExecBinariesOf(target)) { | ||
| 2715 | switch (arg_mode) { | ||
| 2716 | .zig_test => { | ||
| 2717 | warn("created {s} but skipping execution because it is non-native", .{exe_path}); | ||
| 2718 | if (!watch) return cleanExit(); | ||
| 2719 | return; | ||
| 2720 | }, | ||
| 2721 | else => { | ||
| 2722 | std.log.err("unable to execute {s}: non-native", .{exe_path}); | ||
| 2723 | if (!watch) process.exit(1); | ||
| 2724 | return; | ||
| 2725 | }, | ||
| 2726 | } | ||
| 2727 | } | ||
| 2728 | // when testing pass the zig_exe_path to argv | 2714 | // when testing pass the zig_exe_path to argv |
| 2729 | if (arg_mode == .zig_test) | 2715 | if (arg_mode == .zig_test) |
| 2730 | try argv.appendSlice(&[_][]const u8{ | 2716 | try argv.appendSlice(&[_][]const u8{ |
| ... | @@ -2754,6 +2740,7 @@ fn runOrTest( | ... | @@ -2754,6 +2740,7 @@ fn runOrTest( |
| 2754 | if (std.process.can_execv and arg_mode == .run and !watch) { | 2740 | if (std.process.can_execv and arg_mode == .run and !watch) { |
| 2755 | // execv releases the locks; no need to destroy the Compilation here. | 2741 | // execv releases the locks; no need to destroy the Compilation here. |
| 2756 | const err = std.process.execv(gpa, argv.items); | 2742 | const err = std.process.execv(gpa, argv.items); |
| 2743 | try warnAboutForeignBinaries(gpa, arena, arg_mode, target_info); | ||
| 2757 | const cmd = try argvCmd(arena, argv.items); | 2744 | const cmd = try argvCmd(arena, argv.items); |
| 2758 | fatal("the following command failed to execve with '{s}':\n{s}", .{ @errorName(err), cmd }); | 2745 | fatal("the following command failed to execve with '{s}':\n{s}", .{ @errorName(err), cmd }); |
| 2759 | } else { | 2746 | } else { |
| ... | @@ -2771,7 +2758,11 @@ fn runOrTest( | ... | @@ -2771,7 +2758,11 @@ fn runOrTest( |
| 2771 | comp_destroyed.* = true; | 2758 | comp_destroyed.* = true; |
| 2772 | } | 2759 | } |
| 2773 | 2760 | ||
| 2774 | const term = try child.spawnAndWait(); | 2761 | const term = child.spawnAndWait() catch |err| { |
| 2762 | try warnAboutForeignBinaries(gpa, arena, arg_mode, target_info); | ||
| 2763 | const cmd = try argvCmd(arena, argv.items); | ||
| 2764 | fatal("the following command failed with '{s}':\n{s}", .{ @errorName(err), cmd }); | ||
| 2765 | }; | ||
| 2775 | switch (arg_mode) { | 2766 | switch (arg_mode) { |
| 2776 | .run, .build => { | 2767 | .run, .build => { |
| 2777 | switch (term) { | 2768 | switch (term) { |
| ... | @@ -4665,3 +4656,40 @@ fn parseIntSuffix(arg: []const u8, prefix_len: usize) u64 { | ... | @@ -4665,3 +4656,40 @@ fn parseIntSuffix(arg: []const u8, prefix_len: usize) u64 { |
| 4665 | fatal("unable to parse '{s}': {s}", .{ arg, @errorName(err) }); | 4656 | fatal("unable to parse '{s}': {s}", .{ arg, @errorName(err) }); |
| 4666 | }; | 4657 | }; |
| 4667 | } | 4658 | } |
| 4659 | |||
| 4660 | fn warnAboutForeignBinaries( | ||
| 4661 | gpa: Allocator, | ||
| 4662 | arena: Allocator, | ||
| 4663 | arg_mode: ArgMode, | ||
| 4664 | target_info: std.zig.system.NativeTargetInfo, | ||
| 4665 | ) !void { | ||
| 4666 | const host_cross_target: std.zig.CrossTarget = .{}; | ||
| 4667 | const host_target_info = try detectNativeTargetInfo(gpa, host_cross_target); | ||
| 4668 | |||
| 4669 | if (!host_target_info.target.canExecBinariesOf(target_info.target)) { | ||
| 4670 | const host_name = try host_target_info.target.zigTriple(arena); | ||
| 4671 | const foreign_name = try target_info.target.zigTriple(arena); | ||
| 4672 | const tip_suffix = switch (arg_mode) { | ||
| 4673 | .zig_test => ". Consider using --test-no-exec or --test-cmd", | ||
| 4674 | else => "", | ||
| 4675 | }; | ||
| 4676 | warn("the host system ({s}) does not appear to be capable of executing binaries from the target ({s}){s}", .{ | ||
| 4677 | host_name, foreign_name, tip_suffix, | ||
| 4678 | }); | ||
| 4679 | return; | ||
| 4680 | } | ||
| 4681 | |||
| 4682 | if (target_info.dynamic_linker.get()) |foreign_dl| { | ||
| 4683 | std.fs.cwd().access(foreign_dl, .{}) catch { | ||
| 4684 | const host_dl = host_target_info.dynamic_linker.get() orelse "(none)"; | ||
| 4685 | const tip_suffix = switch (arg_mode) { | ||
| 4686 | .zig_test => ", --test-no-exec, or --test-cmd", | ||
| 4687 | else => "", | ||
| 4688 | }; | ||
| 4689 | warn("the host system does not appear to be capable of executing binaries from the target because the host dynamic linker is located at '{s}', while the target dynamic linker path is '{s}'. Consider using --dynamic-linker{s}", .{ | ||
| 4690 | host_dl, foreign_dl, tip_suffix, | ||
| 4691 | }); | ||
| 4692 | return; | ||
| 4693 | }; | ||
| 4694 | } | ||
| 4695 | } |