mirror of
https://codeberg.org/ziglang/zig.git
synced 2026-04-26 13:01:34 +03:00
Merge pull request 'Debug I/O color detection fixes/improvements for Windows/POSIX/WASI/Emscripten + tests' (#31108) from castholm/zig:wasm-env-vars into master
Reviewed-on: https://codeberg.org/ziglang/zig/pulls/31108 Reviewed-by: Andrew Kelley <andrew@ziglang.org>
This commit is contained in:
+17
-14
@@ -1671,20 +1671,23 @@ pub fn init(
|
||||
/// When initialized this way:
|
||||
/// * cancel requests have no effect.
|
||||
/// * `deinit` is safe, but unnecessary to call.
|
||||
pub const init_single_threaded: Threaded = .{
|
||||
.allocator = .failing,
|
||||
.stack_size = std.Thread.SpawnConfig.default_stack_size,
|
||||
.async_limit = .nothing,
|
||||
.cpu_count_error = null,
|
||||
.concurrent_limit = .nothing,
|
||||
.old_sig_io = undefined,
|
||||
.old_sig_pipe = undefined,
|
||||
.have_signal_handler = false,
|
||||
.argv0 = .empty,
|
||||
.environ_initialized = true,
|
||||
.environ = .empty,
|
||||
.worker_threads = .init(null),
|
||||
.disable_memory_mapping = false,
|
||||
pub const init_single_threaded: Threaded = init: {
|
||||
const env_block: process.Environ.Block = if (is_windows) .global else .empty;
|
||||
break :init .{
|
||||
.allocator = .failing,
|
||||
.stack_size = std.Thread.SpawnConfig.default_stack_size,
|
||||
.async_limit = .nothing,
|
||||
.cpu_count_error = null,
|
||||
.concurrent_limit = .nothing,
|
||||
.old_sig_io = undefined,
|
||||
.old_sig_pipe = undefined,
|
||||
.have_signal_handler = false,
|
||||
.argv0 = .empty,
|
||||
.environ_initialized = env_block.isEmpty(),
|
||||
.environ = .{ .process_environ = .{ .block = env_block } },
|
||||
.worker_threads = .init(null),
|
||||
.disable_memory_mapping = false,
|
||||
};
|
||||
};
|
||||
|
||||
var global_single_threaded_instance: Threaded = .init_single_threaded;
|
||||
|
||||
@@ -631,6 +631,7 @@ inline fn callMainWithArgs(argc: usize, argv: [*][*:0]u8, envp: [:null]?[*:0]u8)
|
||||
if (std.Options.debug_threaded_io) |t| {
|
||||
if (@sizeOf(std.Io.Threaded.Argv0) != 0) t.argv0.value = argv[0];
|
||||
t.environ = .{ .process_environ = .{ .block = env_block } };
|
||||
t.environ_initialized = env_block.isEmpty();
|
||||
}
|
||||
std.Thread.maybeAttachSignalStack();
|
||||
std.debug.maybeEnableSegfaultHandler();
|
||||
|
||||
@@ -199,6 +199,9 @@
|
||||
.posix = .{
|
||||
.path = "posix",
|
||||
},
|
||||
.debug_io_color = .{
|
||||
.path = "debug_io_color",
|
||||
},
|
||||
},
|
||||
.paths = .{
|
||||
"build.zig",
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
const std = @import("std");
|
||||
|
||||
pub fn build(b: *std.Build) void {
|
||||
const test_step = b.step("test", "Test");
|
||||
b.default_step = test_step;
|
||||
|
||||
// Most targets handle color the same way, regardless of whether libc is linked.
|
||||
const native_target = b.graph.host;
|
||||
addTestCases(test_step, native_target, false);
|
||||
addTestCases(test_step, native_target, true);
|
||||
|
||||
// WASI behaves differently depending on whether libc is linked.
|
||||
if (b.enable_wasmtime) {
|
||||
const wasi_target = b.resolveTargetQuery(.{ .cpu_arch = .wasm32, .os_tag = .wasi });
|
||||
addTestCases(test_step, wasi_target, false);
|
||||
addTestCases(test_step, wasi_target, true);
|
||||
}
|
||||
}
|
||||
|
||||
fn addTestCases(
|
||||
test_step: *std.Build.Step,
|
||||
target: std.Build.ResolvedTarget,
|
||||
link_libc: bool,
|
||||
) void {
|
||||
const b = test_step.owner;
|
||||
const exe = b.addExecutable(.{
|
||||
.name = b.fmt("{s}{s}", .{ @tagName(target.result.os.tag), if (link_libc) "-libc" else "" }),
|
||||
.root_module = b.createModule(.{
|
||||
.root_source_file = b.path("main.zig"),
|
||||
.target = target,
|
||||
.link_libc = link_libc,
|
||||
}),
|
||||
});
|
||||
|
||||
// Should reflect 'std.process.Environ.Block' and 'std.Io.Threaded.init_single_threaded'.
|
||||
const debug_io_can_read_environ = switch (target.result.os.tag) {
|
||||
.windows => true,
|
||||
.wasi, .emscripten => link_libc,
|
||||
.freestanding, .other => false,
|
||||
else => true,
|
||||
};
|
||||
|
||||
// Don't forget to account for whether the build process's stderr supports color.
|
||||
const parent_stderr_color_enabled = (std.Io.Terminal.Mode.detect(b.graph.io, .stderr(), false, false) catch unreachable) != .no_color;
|
||||
|
||||
_ = addTestCase(test_step, exe, "neither", .inherit, .manual, parent_stderr_color_enabled);
|
||||
_ = addTestCase(test_step, exe, "neither", .redirect, .manual, false);
|
||||
_ = addTestCase(test_step, exe, "no_color", .inherit, .disable, if (debug_io_can_read_environ) false else parent_stderr_color_enabled);
|
||||
_ = addTestCase(test_step, exe, "no_color", .redirect, .disable, false);
|
||||
_ = addTestCase(test_step, exe, "clicolor_force", .inherit, .enable, if (debug_io_can_read_environ) true else parent_stderr_color_enabled);
|
||||
_ = addTestCase(test_step, exe, "clicolor_force", .redirect, .enable, debug_io_can_read_environ);
|
||||
|
||||
const both = addTestCase(test_step, exe, "both", .inherit, .manual, if (debug_io_can_read_environ) false else parent_stderr_color_enabled);
|
||||
both.setEnvironmentVariable("NO_COLOR", "1");
|
||||
both.setEnvironmentVariable("CLICOLOR_FORCE", "1");
|
||||
|
||||
const both_redirected = addTestCase(test_step, exe, "both", .redirect, .manual, false);
|
||||
both_redirected.setEnvironmentVariable("NO_COLOR", "1");
|
||||
both_redirected.setEnvironmentVariable("CLICOLOR_FORCE", "1");
|
||||
}
|
||||
|
||||
fn addTestCase(
|
||||
test_step: *std.Build.Step,
|
||||
exe: *std.Build.Step.Compile,
|
||||
test_case_name: []const u8,
|
||||
stderr: enum { inherit, redirect },
|
||||
run_step_color: std.Build.Step.Run.Color,
|
||||
expected_color_enabled: bool,
|
||||
) *std.Build.Step.Run {
|
||||
const b = test_step.owner;
|
||||
const step_name = b.fmt("{s} {s}{s}", .{
|
||||
exe.name,
|
||||
test_case_name,
|
||||
if (stderr == .redirect) "-redirect" else "",
|
||||
});
|
||||
const run_exe = b.addRunArtifact(exe);
|
||||
run_exe.setName(b.fmt("run {s}", .{step_name}));
|
||||
|
||||
run_exe.failing_to_execute_foreign_is_an_error = false;
|
||||
if (stderr == .redirect) run_exe.expectStdErrMatch("");
|
||||
|
||||
run_exe.clearEnvironment();
|
||||
run_exe.color = run_step_color;
|
||||
|
||||
// Build system quirk: Currently, Run step stdout checks will also redirect stderr, so as a
|
||||
// workaround we use a CheckFile step instead. We must also mark the Run step as having side
|
||||
// effects, to ensure the parent stderr is inherited when not explicitly redirected.
|
||||
run_exe.has_side_effects = true;
|
||||
const stdout = run_exe.captureStdOut(.{});
|
||||
const check_file = b.addCheckFile(stdout, .{ .expected_exact = if (expected_color_enabled) "true" else "false" });
|
||||
check_file.setName(b.fmt("check {s}", .{step_name}));
|
||||
test_step.dependOn(&check_file.step);
|
||||
|
||||
return run_exe;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
const std = @import("std");
|
||||
|
||||
pub fn main() !void {
|
||||
const stderr = std.debug.lockStderr(&.{});
|
||||
defer std.debug.unlockStderr();
|
||||
try std.Io.File.stdout().writeStreamingAll(std.Options.debug_io, if (stderr.terminal_mode != .no_color) "true" else "false");
|
||||
}
|
||||
Reference in New Issue
Block a user