std.Build: implement --host-target, --host-cpu, --host-dynamic-linker

This also makes a long-overdue change of extracting common state from
Build into a shared Graph object.

Getting the semantics right for these flags turned out to be quite
tricky. In the end it works like this:
* The override only happens when the target is fully native, with no
  additional query parameters, such as versions or CPU features added.
* The override affects the resolved Target but leaves the original Query
  unmodified.
* The "is native?" detection logic operates on the original, unmodified
  query. This makes it possible to provide invalid host target
  information, causing confusing errors to occur. Don't do that.

There are some minor breaking changes to std.Build API such as the fact
that `b.zig_exe` is now moved to `b.graph.zig_exe`, as well as a handful
of other similar flags.
This commit is contained in:
Andrew Kelley 2024-02-01 15:44:44 -07:00
parent bd1d2b0ae2
commit 105db13536
15 changed files with 237 additions and 223 deletions

View file

@ -45,7 +45,7 @@ pub fn build(b: *std.Build) !void {
}); });
const docgen_cmd = b.addRunArtifact(docgen_exe); const docgen_cmd = b.addRunArtifact(docgen_exe);
docgen_cmd.addArgs(&.{ "--zig", b.zig_exe }); docgen_cmd.addArgs(&.{ "--zig", b.graph.zig_exe });
if (b.zig_lib_dir) |p| { if (b.zig_lib_dir) |p| {
docgen_cmd.addArg("--zig-lib-dir"); docgen_cmd.addArg("--zig-lib-dir");
docgen_cmd.addDirectoryArg(p); docgen_cmd.addDirectoryArg(p);
@ -410,14 +410,14 @@ pub fn build(b: *std.Build) !void {
test_cases_options.addOption(bool, "only_c", only_c); test_cases_options.addOption(bool, "only_c", only_c);
test_cases_options.addOption(bool, "only_core_functionality", true); test_cases_options.addOption(bool, "only_core_functionality", true);
test_cases_options.addOption(bool, "only_reduce", false); test_cases_options.addOption(bool, "only_reduce", false);
test_cases_options.addOption(bool, "enable_qemu", b.enable_qemu); test_cases_options.addOption(bool, "enable_qemu", b.graph.enable_qemu);
test_cases_options.addOption(bool, "enable_wine", b.enable_wine); test_cases_options.addOption(bool, "enable_wine", b.graph.enable_wine);
test_cases_options.addOption(bool, "enable_wasmtime", b.enable_wasmtime); test_cases_options.addOption(bool, "enable_wasmtime", b.graph.enable_wasmtime);
test_cases_options.addOption(bool, "enable_rosetta", b.enable_rosetta); test_cases_options.addOption(bool, "enable_rosetta", b.graph.enable_rosetta);
test_cases_options.addOption(bool, "enable_darling", b.enable_darling); test_cases_options.addOption(bool, "enable_darling", b.graph.enable_darling);
test_cases_options.addOption(u32, "mem_leak_frames", mem_leak_frames * 2); test_cases_options.addOption(u32, "mem_leak_frames", mem_leak_frames * 2);
test_cases_options.addOption(bool, "value_tracing", value_tracing); test_cases_options.addOption(bool, "value_tracing", value_tracing);
test_cases_options.addOption(?[]const u8, "glibc_runtimes_dir", b.glibc_runtimes_dir); test_cases_options.addOption(?[]const u8, "glibc_runtimes_dir", b.graph.glibc_runtimes_dir);
test_cases_options.addOption([:0]const u8, "version", version); test_cases_options.addOption([:0]const u8, "version", version);
test_cases_options.addOption(std.SemanticVersion, "semver", semver); test_cases_options.addOption(std.SemanticVersion, "semver", semver);
test_cases_options.addOption(?[]const u8, "test_filter", test_filter); test_cases_options.addOption(?[]const u8, "test_filter", test_filter);
@ -884,7 +884,7 @@ fn findConfigH(b: *std.Build, config_h_path_option: ?[]const u8) ?[]const u8 {
} }
} }
var check_dir = fs.path.dirname(b.zig_exe).?; var check_dir = fs.path.dirname(b.graph.zig_exe).?;
while (true) { while (true) {
var dir = fs.cwd().openDir(check_dir, .{}) catch unreachable; var dir = fs.cwd().openDir(check_dir, .{}) catch unreachable;
defer dir.close(); defer dir.close();

View file

@ -53,7 +53,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
const self = @fieldParentPtr(GenerateDef, "step", step); const self = @fieldParentPtr(GenerateDef, "step", step);
const arena = b.allocator; const arena = b.allocator;
var man = b.cache.obtain(); var man = b.graph.cache.obtain();
defer man.deinit(); defer man.deinit();
// Random bytes to make GenerateDef unique. Refresh this with new // Random bytes to make GenerateDef unique. Refresh this with new

View file

@ -46,11 +46,6 @@ pub fn main() !void {
return error.InvalidArgs; return error.InvalidArgs;
}; };
const host: std.Build.ResolvedTarget = .{
.query = .{},
.result = try std.zig.system.resolveTargetQuery(.{}),
};
const build_root_directory: std.Build.Cache.Directory = .{ const build_root_directory: std.Build.Cache.Directory = .{
.path = build_root, .path = build_root,
.handle = try std.fs.cwd().openDir(build_root, .{}), .handle = try std.fs.cwd().openDir(build_root, .{}),
@ -66,28 +61,28 @@ pub fn main() !void {
.handle = try std.fs.cwd().makeOpenPath(global_cache_root, .{}), .handle = try std.fs.cwd().makeOpenPath(global_cache_root, .{}),
}; };
var cache: std.Build.Cache = .{ var graph: std.Build.Graph = .{
.gpa = arena, .arena = arena,
.manifest_dir = try local_cache_directory.handle.makeOpenPath("h", .{}), .cache = .{
.gpa = arena,
.manifest_dir = try local_cache_directory.handle.makeOpenPath("h", .{}),
},
.zig_exe = zig_exe,
.env_map = try process.getEnvMap(arena),
.global_cache_root = global_cache_directory,
}; };
cache.addPrefix(.{ .path = null, .handle = std.fs.cwd() });
cache.addPrefix(build_root_directory);
cache.addPrefix(local_cache_directory);
cache.addPrefix(global_cache_directory);
cache.hash.addBytes(builtin.zig_version_string);
var system_library_options: std.StringArrayHashMapUnmanaged(std.Build.SystemLibraryMode) = .{}; graph.cache.addPrefix(.{ .path = null, .handle = std.fs.cwd() });
graph.cache.addPrefix(build_root_directory);
graph.cache.addPrefix(local_cache_directory);
graph.cache.addPrefix(global_cache_directory);
graph.cache.hash.addBytes(builtin.zig_version_string);
const builder = try std.Build.create( const builder = try std.Build.create(
arena, &graph,
zig_exe,
build_root_directory, build_root_directory,
local_cache_directory, local_cache_directory,
global_cache_directory,
host,
&cache,
dependencies.root_deps, dependencies.root_deps,
&system_library_options,
); );
var targets = ArrayList([]const u8).init(arena); var targets = ArrayList([]const u8).init(arena);
@ -132,10 +127,16 @@ pub fn main() !void {
steps_menu = true; steps_menu = true;
} else if (mem.eql(u8, arg, "--system-lib")) { } else if (mem.eql(u8, arg, "--system-lib")) {
const name = nextArgOrFatal(args, &arg_idx); const name = nextArgOrFatal(args, &arg_idx);
builder.system_library_options.put(arena, name, .user_enabled) catch @panic("OOM"); graph.system_library_options.put(arena, name, .user_enabled) catch @panic("OOM");
} else if (mem.eql(u8, arg, "--no-system-lib")) { } else if (mem.eql(u8, arg, "--no-system-lib")) {
const name = nextArgOrFatal(args, &arg_idx); const name = nextArgOrFatal(args, &arg_idx);
builder.system_library_options.put(arena, name, .user_disabled) catch @panic("OOM"); graph.system_library_options.put(arena, name, .user_disabled) catch @panic("OOM");
} else if (mem.eql(u8, arg, "--host-target")) {
graph.host_query_options.arch_os_abi = nextArgOrFatal(args, &arg_idx);
} else if (mem.eql(u8, arg, "--host-cpu")) {
graph.host_query_options.cpu_features = nextArgOrFatal(args, &arg_idx);
} else if (mem.eql(u8, arg, "--host-dynamic-linker")) {
graph.host_query_options.dynamic_linker = nextArgOrFatal(args, &arg_idx);
} else if (mem.eql(u8, arg, "--prefix-lib-dir")) { } else if (mem.eql(u8, arg, "--prefix-lib-dir")) {
dir_list.lib_dir = nextArgOrFatal(args, &arg_idx); dir_list.lib_dir = nextArgOrFatal(args, &arg_idx);
} else if (mem.eql(u8, arg, "--prefix-exe-dir")) { } else if (mem.eql(u8, arg, "--prefix-exe-dir")) {
@ -193,7 +194,7 @@ pub fn main() !void {
} else if (mem.eql(u8, arg, "--debug-compile-errors")) { } else if (mem.eql(u8, arg, "--debug-compile-errors")) {
builder.debug_compile_errors = true; builder.debug_compile_errors = true;
} else if (mem.eql(u8, arg, "--glibc-runtimes")) { } else if (mem.eql(u8, arg, "--glibc-runtimes")) {
builder.glibc_runtimes_dir = nextArgOrFatal(args, &arg_idx); graph.glibc_runtimes_dir = nextArgOrFatal(args, &arg_idx);
} else if (mem.eql(u8, arg, "--verbose-link")) { } else if (mem.eql(u8, arg, "--verbose-link")) {
builder.verbose_link = true; builder.verbose_link = true;
} else if (mem.eql(u8, arg, "--verbose-air")) { } else if (mem.eql(u8, arg, "--verbose-air")) {
@ -213,25 +214,25 @@ pub fn main() !void {
} else if (mem.eql(u8, arg, "--prominent-compile-errors")) { } else if (mem.eql(u8, arg, "--prominent-compile-errors")) {
prominent_compile_errors = true; prominent_compile_errors = true;
} else if (mem.eql(u8, arg, "-fwine")) { } else if (mem.eql(u8, arg, "-fwine")) {
builder.enable_wine = true; graph.enable_wine = true;
} else if (mem.eql(u8, arg, "-fno-wine")) { } else if (mem.eql(u8, arg, "-fno-wine")) {
builder.enable_wine = false; graph.enable_wine = false;
} else if (mem.eql(u8, arg, "-fqemu")) { } else if (mem.eql(u8, arg, "-fqemu")) {
builder.enable_qemu = true; graph.enable_qemu = true;
} else if (mem.eql(u8, arg, "-fno-qemu")) { } else if (mem.eql(u8, arg, "-fno-qemu")) {
builder.enable_qemu = false; graph.enable_qemu = false;
} else if (mem.eql(u8, arg, "-fwasmtime")) { } else if (mem.eql(u8, arg, "-fwasmtime")) {
builder.enable_wasmtime = true; graph.enable_wasmtime = true;
} else if (mem.eql(u8, arg, "-fno-wasmtime")) { } else if (mem.eql(u8, arg, "-fno-wasmtime")) {
builder.enable_wasmtime = false; graph.enable_wasmtime = false;
} else if (mem.eql(u8, arg, "-frosetta")) { } else if (mem.eql(u8, arg, "-frosetta")) {
builder.enable_rosetta = true; graph.enable_rosetta = true;
} else if (mem.eql(u8, arg, "-fno-rosetta")) { } else if (mem.eql(u8, arg, "-fno-rosetta")) {
builder.enable_rosetta = false; graph.enable_rosetta = false;
} else if (mem.eql(u8, arg, "-fdarling")) { } else if (mem.eql(u8, arg, "-fdarling")) {
builder.enable_darling = true; graph.enable_darling = true;
} else if (mem.eql(u8, arg, "-fno-darling")) { } else if (mem.eql(u8, arg, "-fno-darling")) {
builder.enable_darling = false; graph.enable_darling = false;
} else if (mem.eql(u8, arg, "-freference-trace")) { } else if (mem.eql(u8, arg, "-freference-trace")) {
builder.reference_trace = 256; builder.reference_trace = 256;
} else if (mem.startsWith(u8, arg, "-freference-trace=")) { } else if (mem.startsWith(u8, arg, "-freference-trace=")) {
@ -266,11 +267,19 @@ pub fn main() !void {
} }
} }
const host_query = std.Build.parseTargetQuery(graph.host_query_options) catch |err| switch (err) {
error.ParseFailed => process.exit(1),
};
builder.host = .{
.query = .{},
.result = try std.zig.system.resolveTargetQuery(host_query),
};
const stderr = std.io.getStdErr(); const stderr = std.io.getStdErr();
const ttyconf = get_tty_conf(color, stderr); const ttyconf = get_tty_conf(color, stderr);
switch (ttyconf) { switch (ttyconf) {
.no_color => try builder.env_map.put("NO_COLOR", "1"), .no_color => try graph.env_map.put("NO_COLOR", "1"),
.escape_codes => try builder.env_map.put("YES_COLOR", "1"), .escape_codes => try graph.env_map.put("YES_COLOR", "1"),
.windows_api => {}, .windows_api => {},
} }
@ -1029,7 +1038,7 @@ fn usage(b: *std.Build, out_stream: anytype) !void {
\\ \\
\\Steps: \\Steps:
\\ \\
, .{b.zig_exe}); , .{b.graph.zig_exe});
try steps(b, out_stream); try steps(b, out_stream);
try out_stream.writeAll( try out_stream.writeAll(
@ -1104,22 +1113,23 @@ fn usage(b: *std.Build, out_stream: anytype) !void {
\\ --system [dir] System Package Mode. Disable fetching; prefer system libs \\ --system [dir] System Package Mode. Disable fetching; prefer system libs
\\ --host-target [triple] Use the provided target as the host \\ --host-target [triple] Use the provided target as the host
\\ --host-cpu [cpu] Use the provided CPU as the host \\ --host-cpu [cpu] Use the provided CPU as the host
\\ --host-dynamic-linker [path] Use the provided dynamic linker as the host
\\ --system-lib [name] Use the system-provided library \\ --system-lib [name] Use the system-provided library
\\ --no-system-lib [name] Do not use the system-provided library \\ --no-system-lib [name] Do not use the system-provided library
\\ \\
\\ Available System Library Integrations: Enabled: \\ Available System Library Integrations: Enabled:
\\ \\
); );
if (b.system_library_options.entries.len == 0) { if (b.graph.system_library_options.entries.len == 0) {
try out_stream.writeAll(" (none) -\n"); try out_stream.writeAll(" (none) -\n");
} else { } else {
for (b.system_library_options.keys(), b.system_library_options.values()) |name, v| { for (b.graph.system_library_options.keys(), b.graph.system_library_options.values()) |k, v| {
const status = switch (v) { const status = switch (v) {
.declared_enabled => "yes", .declared_enabled => "yes",
.declared_disabled => "no", .declared_disabled => "no",
.user_enabled, .user_disabled => unreachable, // already emitted error .user_enabled, .user_disabled => unreachable, // already emitted error
}; };
try out_stream.print(" {s:<43} {s}\n", .{ name, status }); try out_stream.print(" {s:<43} {s}\n", .{ k, status });
} }
} }
@ -1203,7 +1213,7 @@ fn fatal(comptime f: []const u8, args: anytype) noreturn {
fn validateSystemLibraryOptions(b: *std.Build) void { fn validateSystemLibraryOptions(b: *std.Build) void {
var bad = false; var bad = false;
for (b.system_library_options.keys(), b.system_library_options.values()) |k, v| { for (b.graph.system_library_options.keys(), b.graph.system_library_options.values()) |k, v| {
switch (v) { switch (v) {
.user_disabled, .user_enabled => { .user_disabled, .user_enabled => {
// The user tried to enable or disable a system library integration, but // The user tried to enable or disable a system library integration, but

View file

@ -22,15 +22,14 @@ pub const Cache = @import("Build/Cache.zig");
pub const Step = @import("Build/Step.zig"); pub const Step = @import("Build/Step.zig");
pub const Module = @import("Build/Module.zig"); pub const Module = @import("Build/Module.zig");
/// Shared state among all Build instances.
graph: *Graph,
install_tls: TopLevelStep, install_tls: TopLevelStep,
uninstall_tls: TopLevelStep, uninstall_tls: TopLevelStep,
allocator: Allocator, allocator: Allocator,
user_input_options: UserInputOptionsMap, user_input_options: UserInputOptionsMap,
available_options_map: AvailableOptionsMap, available_options_map: AvailableOptionsMap,
available_options_list: ArrayList(AvailableOption), available_options_list: ArrayList(AvailableOption),
/// All Build instances share this hash map.
system_library_options: *std.StringArrayHashMapUnmanaged(SystemLibraryMode),
system_package_mode: bool,
verbose: bool, verbose: bool,
verbose_link: bool, verbose_link: bool,
verbose_cc: bool, verbose_cc: bool,
@ -41,9 +40,7 @@ verbose_cimport: bool,
verbose_llvm_cpu_features: bool, verbose_llvm_cpu_features: bool,
reference_trace: ?u32 = null, reference_trace: ?u32 = null,
invalid_user_input: bool, invalid_user_input: bool,
zig_exe: [:0]const u8,
default_step: *Step, default_step: *Step,
env_map: *EnvMap,
top_level_steps: std.StringArrayHashMapUnmanaged(*TopLevelStep), top_level_steps: std.StringArrayHashMapUnmanaged(*TopLevelStep),
install_prefix: []const u8, install_prefix: []const u8,
dest_dir: ?[]const u8, dest_dir: ?[]const u8,
@ -52,14 +49,12 @@ exe_dir: []const u8,
h_dir: []const u8, h_dir: []const u8,
install_path: []const u8, install_path: []const u8,
sysroot: ?[]const u8 = null, sysroot: ?[]const u8 = null,
search_prefixes: ArrayList([]const u8), search_prefixes: std.ArrayListUnmanaged([]const u8),
libc_file: ?[]const u8 = null, libc_file: ?[]const u8 = null,
installed_files: ArrayList(InstalledFile), installed_files: ArrayList(InstalledFile),
/// Path to the directory containing build.zig. /// Path to the directory containing build.zig.
build_root: Cache.Directory, build_root: Cache.Directory,
cache_root: Cache.Directory, cache_root: Cache.Directory,
global_cache_root: Cache.Directory,
cache: *Cache,
zig_lib_dir: ?LazyPath, zig_lib_dir: ?LazyPath,
pkg_config_pkg_list: ?(PkgConfigError![]const PkgConfigPkg) = null, pkg_config_pkg_list: ?(PkgConfigError![]const PkgConfigPkg) = null,
args: ?[][]const u8 = null, args: ?[][]const u8 = null,
@ -71,22 +66,6 @@ debug_pkg_config: bool = false,
/// Set to 0 to disable stack collection. /// Set to 0 to disable stack collection.
debug_stack_frames_count: u8 = 8, debug_stack_frames_count: u8 = 8,
/// Experimental. Use system Darling installation to run cross compiled macOS build artifacts.
enable_darling: bool = false,
/// Use system QEMU installation to run cross compiled foreign architecture build artifacts.
enable_qemu: bool = false,
/// Darwin. Use Rosetta to run x86_64 macOS build artifacts on arm64 macOS.
enable_rosetta: bool = false,
/// Use system Wasmtime installation to run cross compiled wasm/wasi build artifacts.
enable_wasmtime: bool = false,
/// Use system Wine installation to run cross compiled Windows build artifacts.
enable_wine: bool = false,
/// After following the steps in https://github.com/ziglang/zig/wiki/Updating-libc#glibc,
/// this will be the directory $glibc-build-dir/install/glibcs
/// Given the example of the aarch64 target, this is the directory
/// that contains the path `aarch64-linux-gnu/lib/ld-linux-aarch64.so.1`.
glibc_runtimes_dir: ?[]const u8 = null,
/// Information about the native target. Computed before build() is invoked. /// Information about the native target. Computed before build() is invoked.
host: ResolvedTarget, host: ResolvedTarget,
@ -101,9 +80,38 @@ initialized_deps: *InitializedDepMap,
/// A mapping from dependency names to package hashes. /// A mapping from dependency names to package hashes.
available_deps: AvailableDeps, available_deps: AvailableDeps,
/// Shared state among all Build instances.
/// Settings that are here rather than in Build are not configurable per-package.
pub const Graph = struct {
arena: Allocator,
system_library_options: std.StringArrayHashMapUnmanaged(SystemLibraryMode) = .{},
system_package_mode: bool = false,
cache: Cache,
zig_exe: [:0]const u8,
env_map: EnvMap,
global_cache_root: Cache.Directory,
host_query_options: std.Target.Query.ParseOptions = .{},
/// Experimental. Use system Darling installation to run cross compiled macOS build artifacts.
enable_darling: bool = false,
/// Use system QEMU installation to run cross compiled foreign architecture build artifacts.
enable_qemu: bool = false,
/// Darwin. Use Rosetta to run x86_64 macOS build artifacts on arm64 macOS.
enable_rosetta: bool = false,
/// Use system Wasmtime installation to run cross compiled wasm/wasi build artifacts.
enable_wasmtime: bool = false,
/// Use system Wine installation to run cross compiled Windows build artifacts.
enable_wine: bool = false,
/// After following the steps in https://github.com/ziglang/zig/wiki/Updating-libc#glibc,
/// this will be the directory $glibc-build-dir/install/glibcs
/// Given the example of the aarch64 target, this is the directory
/// that contains the path `aarch64-linux-gnu/lib/ld-linux-aarch64.so.1`.
glibc_runtimes_dir: ?[]const u8 = null,
};
const AvailableDeps = []const struct { []const u8, []const u8 }; const AvailableDeps = []const struct { []const u8, []const u8 };
pub const SystemLibraryMode = enum { const SystemLibraryMode = enum {
/// User asked for the library to be disabled. /// User asked for the library to be disabled.
/// The build runner has not confirmed whether the setting is recognized yet. /// The build runner has not confirmed whether the setting is recognized yet.
user_disabled, user_disabled,
@ -226,29 +234,20 @@ pub const DirList = struct {
}; };
pub fn create( pub fn create(
allocator: Allocator, graph: *Graph,
zig_exe: [:0]const u8,
build_root: Cache.Directory, build_root: Cache.Directory,
cache_root: Cache.Directory, cache_root: Cache.Directory,
global_cache_root: Cache.Directory,
host: ResolvedTarget,
cache: *Cache,
available_deps: AvailableDeps, available_deps: AvailableDeps,
system_library_options: *std.StringArrayHashMapUnmanaged(SystemLibraryMode),
) !*Build { ) !*Build {
const env_map = try allocator.create(EnvMap); const arena = graph.arena;
env_map.* = try process.getEnvMap(allocator); const initialized_deps = try arena.create(InitializedDepMap);
initialized_deps.* = InitializedDepMap.initContext(arena, .{ .allocator = arena });
const initialized_deps = try allocator.create(InitializedDepMap); const self = try arena.create(Build);
initialized_deps.* = InitializedDepMap.initContext(allocator, .{ .allocator = allocator });
const self = try allocator.create(Build);
self.* = .{ self.* = .{
.zig_exe = zig_exe, .graph = graph,
.build_root = build_root, .build_root = build_root,
.cache_root = cache_root, .cache_root = cache_root,
.global_cache_root = global_cache_root,
.cache = cache,
.verbose = false, .verbose = false,
.verbose_link = false, .verbose_link = false,
.verbose_cc = false, .verbose_cc = false,
@ -258,20 +257,19 @@ pub fn create(
.verbose_cimport = false, .verbose_cimport = false,
.verbose_llvm_cpu_features = false, .verbose_llvm_cpu_features = false,
.invalid_user_input = false, .invalid_user_input = false,
.allocator = allocator, .allocator = arena,
.user_input_options = UserInputOptionsMap.init(allocator), .user_input_options = UserInputOptionsMap.init(arena),
.available_options_map = AvailableOptionsMap.init(allocator), .available_options_map = AvailableOptionsMap.init(arena),
.available_options_list = ArrayList(AvailableOption).init(allocator), .available_options_list = ArrayList(AvailableOption).init(arena),
.top_level_steps = .{}, .top_level_steps = .{},
.default_step = undefined, .default_step = undefined,
.env_map = env_map, .search_prefixes = .{},
.search_prefixes = ArrayList([]const u8).init(allocator),
.install_prefix = undefined, .install_prefix = undefined,
.lib_dir = undefined, .lib_dir = undefined,
.exe_dir = undefined, .exe_dir = undefined,
.h_dir = undefined, .h_dir = undefined,
.dest_dir = env_map.get("DESTDIR"), .dest_dir = graph.env_map.get("DESTDIR"),
.installed_files = ArrayList(InstalledFile).init(allocator), .installed_files = ArrayList(InstalledFile).init(arena),
.install_tls = .{ .install_tls = .{
.step = Step.init(.{ .step = Step.init(.{
.id = .top_level, .id = .top_level,
@ -292,16 +290,14 @@ pub fn create(
.zig_lib_dir = null, .zig_lib_dir = null,
.install_path = undefined, .install_path = undefined,
.args = null, .args = null,
.host = host, .host = undefined,
.modules = std.StringArrayHashMap(*Module).init(allocator), .modules = std.StringArrayHashMap(*Module).init(arena),
.named_writefiles = std.StringArrayHashMap(*Step.WriteFile).init(allocator), .named_writefiles = std.StringArrayHashMap(*Step.WriteFile).init(arena),
.initialized_deps = initialized_deps, .initialized_deps = initialized_deps,
.available_deps = available_deps, .available_deps = available_deps,
.system_library_options = system_library_options,
.system_package_mode = false,
}; };
try self.top_level_steps.put(allocator, self.install_tls.step.name, &self.install_tls); try self.top_level_steps.put(arena, self.install_tls.step.name, &self.install_tls);
try self.top_level_steps.put(allocator, self.uninstall_tls.step.name, &self.uninstall_tls); try self.top_level_steps.put(arena, self.uninstall_tls.step.name, &self.uninstall_tls);
self.default_step = &self.install_tls.step; self.default_step = &self.install_tls.step;
return self; return self;
} }
@ -328,6 +324,7 @@ fn createChildOnly(
const allocator = parent.allocator; const allocator = parent.allocator;
const child = try allocator.create(Build); const child = try allocator.create(Build);
child.* = .{ child.* = .{
.graph = parent.graph,
.allocator = allocator, .allocator = allocator,
.install_tls = .{ .install_tls = .{
.step = Step.init(.{ .step = Step.init(.{
@ -359,9 +356,7 @@ fn createChildOnly(
.verbose_llvm_cpu_features = parent.verbose_llvm_cpu_features, .verbose_llvm_cpu_features = parent.verbose_llvm_cpu_features,
.reference_trace = parent.reference_trace, .reference_trace = parent.reference_trace,
.invalid_user_input = false, .invalid_user_input = false,
.zig_exe = parent.zig_exe,
.default_step = undefined, .default_step = undefined,
.env_map = parent.env_map,
.top_level_steps = .{}, .top_level_steps = .{},
.install_prefix = undefined, .install_prefix = undefined,
.dest_dir = parent.dest_dir, .dest_dir = parent.dest_dir,
@ -375,26 +370,16 @@ fn createChildOnly(
.installed_files = ArrayList(InstalledFile).init(allocator), .installed_files = ArrayList(InstalledFile).init(allocator),
.build_root = build_root, .build_root = build_root,
.cache_root = parent.cache_root, .cache_root = parent.cache_root,
.global_cache_root = parent.global_cache_root,
.cache = parent.cache,
.zig_lib_dir = parent.zig_lib_dir, .zig_lib_dir = parent.zig_lib_dir,
.debug_log_scopes = parent.debug_log_scopes, .debug_log_scopes = parent.debug_log_scopes,
.debug_compile_errors = parent.debug_compile_errors, .debug_compile_errors = parent.debug_compile_errors,
.debug_pkg_config = parent.debug_pkg_config, .debug_pkg_config = parent.debug_pkg_config,
.enable_darling = parent.enable_darling,
.enable_qemu = parent.enable_qemu,
.enable_rosetta = parent.enable_rosetta,
.enable_wasmtime = parent.enable_wasmtime,
.enable_wine = parent.enable_wine,
.glibc_runtimes_dir = parent.glibc_runtimes_dir,
.host = parent.host, .host = parent.host,
.dep_prefix = parent.fmt("{s}{s}.", .{ parent.dep_prefix, dep_name }), .dep_prefix = parent.fmt("{s}{s}.", .{ parent.dep_prefix, dep_name }),
.modules = std.StringArrayHashMap(*Module).init(allocator), .modules = std.StringArrayHashMap(*Module).init(allocator),
.named_writefiles = std.StringArrayHashMap(*Step.WriteFile).init(allocator), .named_writefiles = std.StringArrayHashMap(*Step.WriteFile).init(allocator),
.initialized_deps = parent.initialized_deps, .initialized_deps = parent.initialized_deps,
.available_deps = pkg_deps, .available_deps = pkg_deps,
.system_library_options = parent.system_library_options,
.system_package_mode = parent.system_package_mode,
}; };
try child.top_level_steps.put(allocator, child.install_tls.step.name, &child.install_tls); try child.top_level_steps.put(allocator, child.install_tls.step.name, &child.install_tls);
try child.top_level_steps.put(allocator, child.uninstall_tls.step.name, &child.uninstall_tls); try child.top_level_steps.put(allocator, child.uninstall_tls.step.name, &child.uninstall_tls);
@ -572,7 +557,7 @@ fn hashUserInputOptionsMap(allocator: Allocator, user_input_options: UserInputOp
fn determineAndApplyInstallPrefix(b: *Build) !void { fn determineAndApplyInstallPrefix(b: *Build) !void {
// Create an installation directory local to this package. This will be used when // Create an installation directory local to this package. This will be used when
// dependant packages require a standard prefix, such as include directories for C headers. // dependant packages require a standard prefix, such as include directories for C headers.
var hash = b.cache.hash; var hash = b.graph.cache.hash;
// Random bytes to make unique. Refresh this with new random bytes when // Random bytes to make unique. Refresh this with new random bytes when
// implementation is modified in a non-backwards-compatible way. // implementation is modified in a non-backwards-compatible way.
hash.add(@as(u32, 0xd8cb0055)); hash.add(@as(u32, 0xd8cb0055));
@ -587,12 +572,6 @@ fn determineAndApplyInstallPrefix(b: *Build) !void {
b.resolveInstallPrefix(install_prefix, .{}); b.resolveInstallPrefix(install_prefix, .{});
} }
pub fn destroy(b: *Build) void {
b.env_map.deinit();
b.top_level_steps.deinit(b.allocator);
b.allocator.destroy(b);
}
/// This function is intended to be called by lib/build_runner.zig, not a build.zig file. /// This function is intended to be called by lib/build_runner.zig, not a build.zig file.
pub fn resolveInstallPrefix(self: *Build, install_prefix: ?[]const u8, dir_list: DirList) void { pub fn resolveInstallPrefix(self: *Build, install_prefix: ?[]const u8, dir_list: DirList) void {
if (self.dest_dir) |dest_dir| { if (self.dest_dir) |dest_dir| {
@ -1273,6 +1252,54 @@ pub fn standardTargetOptions(b: *Build, args: StandardTargetOptionsArgs) Resolve
return b.resolveTargetQuery(query); return b.resolveTargetQuery(query);
} }
pub fn parseTargetQuery(options: std.Target.Query.ParseOptions) error{ParseFailed}!std.Target.Query {
var diags: Target.Query.ParseOptions.Diagnostics = .{};
var opts_copy = options;
opts_copy.diagnostics = &diags;
return std.Target.Query.parse(options) catch |err| switch (err) {
error.UnknownCpuModel => {
std.debug.print("unknown CPU: '{s}'\navailable CPUs for architecture '{s}':\n", .{
diags.cpu_name.?, @tagName(diags.arch.?),
});
for (diags.arch.?.allCpuModels()) |cpu| {
std.debug.print(" {s}\n", .{cpu.name});
}
return error.ParseFailed;
},
error.UnknownCpuFeature => {
std.debug.print(
\\unknown CPU feature: '{s}'
\\available CPU features for architecture '{s}':
\\
, .{
diags.unknown_feature_name.?,
@tagName(diags.arch.?),
});
for (diags.arch.?.allFeaturesList()) |feature| {
std.debug.print(" {s}: {s}\n", .{ feature.name, feature.description });
}
return error.ParseFailed;
},
error.UnknownOperatingSystem => {
std.debug.print(
\\unknown OS: '{s}'
\\available operating systems:
\\
, .{diags.os_name.?});
inline for (std.meta.fields(Target.Os.Tag)) |field| {
std.debug.print(" {s}\n", .{field.name});
}
return error.ParseFailed;
},
else => |e| {
std.debug.print("unable to parse target '{s}': {s}\n", .{
options.arch_os_abi, @errorName(e),
});
return error.ParseFailed;
},
};
}
/// Exposes standard `zig build` options for choosing a target. /// Exposes standard `zig build` options for choosing a target.
pub fn standardTargetOptionsQueryOnly(b: *Build, args: StandardTargetOptionsArgs) Target.Query { pub fn standardTargetOptionsQueryOnly(b: *Build, args: StandardTargetOptionsArgs) Target.Query {
const maybe_triple = b.option( const maybe_triple = b.option(
@ -1280,60 +1307,28 @@ pub fn standardTargetOptionsQueryOnly(b: *Build, args: StandardTargetOptionsArgs
"target", "target",
"The CPU architecture, OS, and ABI to build for", "The CPU architecture, OS, and ABI to build for",
); );
const mcpu = b.option([]const u8, "cpu", "Target CPU features to add or subtract"); const mcpu = b.option(
[]const u8,
"cpu",
"Target CPU features to add or subtract",
);
const dynamic_linker = b.option(
[]const u8,
"dynamic-linker",
"Path to interpreter on the target system",
);
if (maybe_triple == null and mcpu == null) { if (maybe_triple == null and mcpu == null and dynamic_linker == null)
return args.default_target; return args.default_target;
}
const triple = maybe_triple orelse "native"; const triple = maybe_triple orelse "native";
var diags: Target.Query.ParseOptions.Diagnostics = .{}; const selected_target = parseTargetQuery(.{
const selected_target = Target.Query.parse(.{
.arch_os_abi = triple, .arch_os_abi = triple,
.cpu_features = mcpu, .cpu_features = mcpu,
.diagnostics = &diags, .dynamic_linker = dynamic_linker,
}) catch |err| switch (err) { }) catch |err| switch (err) {
error.UnknownCpuModel => { error.ParseFailed => {
log.err("Unknown CPU: '{s}'\nAvailable CPUs for architecture '{s}':", .{
diags.cpu_name.?,
@tagName(diags.arch.?),
});
for (diags.arch.?.allCpuModels()) |cpu| {
log.err(" {s}", .{cpu.name});
}
b.markInvalidUserInput();
return args.default_target;
},
error.UnknownCpuFeature => {
log.err(
\\Unknown CPU feature: '{s}'
\\Available CPU features for architecture '{s}':
\\
, .{
diags.unknown_feature_name.?,
@tagName(diags.arch.?),
});
for (diags.arch.?.allFeaturesList()) |feature| {
log.err(" {s}: {s}", .{ feature.name, feature.description });
}
b.markInvalidUserInput();
return args.default_target;
},
error.UnknownOperatingSystem => {
log.err(
\\Unknown OS: '{s}'
\\Available operating systems:
\\
, .{diags.os_name.?});
inline for (std.meta.fields(Target.Os.Tag)) |field| {
log.err(" {s}", .{field.name});
}
b.markInvalidUserInput();
return args.default_target;
},
else => |e| {
log.err("Unable to parse target '{s}': {s}\n", .{ triple, @errorName(e) });
b.markInvalidUserInput(); b.markInvalidUserInput();
return args.default_target; return args.default_target;
}, },
@ -1622,7 +1617,7 @@ pub fn findProgram(self: *Build, names: []const []const u8, paths: []const []con
return fs.realpathAlloc(self.allocator, full_path) catch continue; return fs.realpathAlloc(self.allocator, full_path) catch continue;
} }
} }
if (self.env_map.get("PATH")) |PATH| { if (self.graph.env_map.get("PATH")) |PATH| {
for (names) |name| { for (names) |name| {
if (fs.path.isAbsolute(name)) { if (fs.path.isAbsolute(name)) {
return name; return name;
@ -1668,7 +1663,7 @@ pub fn runAllowFail(
child.stdin_behavior = .Ignore; child.stdin_behavior = .Ignore;
child.stdout_behavior = .Pipe; child.stdout_behavior = .Pipe;
child.stderr_behavior = stderr_behavior; child.stderr_behavior = stderr_behavior;
child.env_map = self.env_map; child.env_map = &self.graph.env_map;
try child.spawn(); try child.spawn();
@ -1714,8 +1709,8 @@ pub fn run(b: *Build, argv: []const []const u8) []u8 {
}; };
} }
pub fn addSearchPrefix(self: *Build, search_prefix: []const u8) void { pub fn addSearchPrefix(b: *Build, search_prefix: []const u8) void {
self.search_prefixes.append(self.dupePath(search_prefix)) catch @panic("OOM"); b.search_prefixes.append(b.allocator, b.dupePath(search_prefix)) catch @panic("OOM");
} }
pub fn getInstallPath(self: *Build, dir: InstallDir, dest_rel_path: []const u8) []const u8 { pub fn getInstallPath(self: *Build, dir: InstallDir, dest_rel_path: []const u8) []const u8 {
@ -2310,9 +2305,7 @@ pub const ResolvedTarget = struct {
/// Converts a target query into a fully resolved target that can be passed to /// Converts a target query into a fully resolved target that can be passed to
/// various parts of the API. /// various parts of the API.
pub fn resolveTargetQuery(b: *Build, query: Target.Query) ResolvedTarget { pub fn resolveTargetQuery(b: *Build, query: Target.Query) ResolvedTarget {
// This context will likely be required in the future when the target is if (query.isNative()) return b.host;
// resolved via a WASI API or via the build protocol.
_ = b;
return .{ return .{
.query = query, .query = query,
@ -2326,7 +2319,7 @@ pub fn wantSharedLibSymLinks(target: Target) bool {
} }
pub fn systemLibraryOption(b: *Build, name: []const u8) bool { pub fn systemLibraryOption(b: *Build, name: []const u8) bool {
const gop = b.system_library_options.getOrPut(b.allocator, name) catch @panic("OOM"); const gop = b.graph.system_library_options.getOrPut(b.allocator, name) catch @panic("OOM");
if (gop.found_existing) switch (gop.value_ptr.*) { if (gop.found_existing) switch (gop.value_ptr.*) {
.user_disabled => { .user_disabled => {
gop.value_ptr.* = .declared_disabled; gop.value_ptr.* = .declared_disabled;
@ -2340,7 +2333,7 @@ pub fn systemLibraryOption(b: *Build, name: []const u8) bool {
.declared_enabled => return true, .declared_enabled => return true,
} else { } else {
gop.key_ptr.* = b.dupe(name); gop.key_ptr.* = b.dupe(name);
if (b.system_package_mode) { if (b.graph.system_package_mode) {
gop.value_ptr.* = .declared_enabled; gop.value_ptr.* = .declared_enabled;
return true; return true;
} else { } else {

View file

@ -314,7 +314,7 @@ pub fn evalZigProcess(
try handleVerbose(s.owner, null, argv); try handleVerbose(s.owner, null, argv);
var child = std.ChildProcess.init(argv, arena); var child = std.ChildProcess.init(argv, arena);
child.env_map = b.env_map; child.env_map = &b.graph.env_map;
child.stdin_behavior = .Pipe; child.stdin_behavior = .Pipe;
child.stdout_behavior = .Pipe; child.stdout_behavior = .Pipe;
child.stderr_behavior = .Pipe; child.stderr_behavior = .Pipe;

View file

@ -923,7 +923,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
var zig_args = ArrayList([]const u8).init(arena); var zig_args = ArrayList([]const u8).init(arena);
defer zig_args.deinit(); defer zig_args.deinit();
try zig_args.append(b.zig_exe); try zig_args.append(b.graph.zig_exe);
const cmd = switch (self.kind) { const cmd = switch (self.kind) {
.lib => "build-lib", .lib => "build-lib",
@ -933,6 +933,16 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
}; };
try zig_args.append(cmd); try zig_args.append(cmd);
if (!mem.eql(u8, b.graph.host_query_options.arch_os_abi, "native")) {
try zig_args.appendSlice(&.{ "--host-target", b.graph.host_query_options.arch_os_abi });
}
if (b.graph.host_query_options.cpu_features) |cpu| {
try zig_args.appendSlice(&.{ "--host-cpu", cpu });
}
if (b.graph.host_query_options.dynamic_linker) |dl| {
try zig_args.appendSlice(&.{ "--host-dynamic-linker", dl });
}
if (b.reference_trace) |some| { if (b.reference_trace) |some| {
try zig_args.append(try std.fmt.allocPrint(arena, "-freference-trace={d}", .{some})); try zig_args.append(try std.fmt.allocPrint(arena, "-freference-trace={d}", .{some}));
} }
@ -1393,7 +1403,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
try zig_args.append(b.cache_root.path orelse "."); try zig_args.append(b.cache_root.path orelse ".");
try zig_args.append("--global-cache-dir"); try zig_args.append("--global-cache-dir");
try zig_args.append(b.global_cache_root.path orelse "."); try zig_args.append(b.graph.global_cache_root.path orelse ".");
try zig_args.append("--name"); try zig_args.append("--name");
try zig_args.append(self.name); try zig_args.append(self.name);

View file

@ -171,7 +171,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
const gpa = b.allocator; const gpa = b.allocator;
const arena = b.allocator; const arena = b.allocator;
var man = b.cache.obtain(); var man = b.graph.cache.obtain();
defer man.deinit(); defer man.deinit();
// Random bytes to make ConfigHeader unique. Refresh this with new // Random bytes to make ConfigHeader unique. Refresh this with new

View file

@ -52,7 +52,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
var argv: std.ArrayListUnmanaged([]const u8) = .{}; var argv: std.ArrayListUnmanaged([]const u8) = .{};
try argv.ensureUnusedCapacity(arena, 2 + 1 + self.paths.len + 2 * self.exclude_paths.len); try argv.ensureUnusedCapacity(arena, 2 + 1 + self.paths.len + 2 * self.exclude_paths.len);
argv.appendAssumeCapacity(b.zig_exe); argv.appendAssumeCapacity(b.graph.zig_exe);
argv.appendAssumeCapacity("fmt"); argv.appendAssumeCapacity("fmt");
if (self.check) { if (self.check) {

View file

@ -94,7 +94,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
const b = step.owner; const b = step.owner;
const self = @fieldParentPtr(ObjCopy, "step", step); const self = @fieldParentPtr(ObjCopy, "step", step);
var man = b.cache.obtain(); var man = b.graph.cache.obtain();
defer man.deinit(); defer man.deinit();
// Random bytes to make ObjCopy unique. Refresh this with new random // Random bytes to make ObjCopy unique. Refresh this with new random
@ -133,7 +133,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
}; };
var argv = std.ArrayList([]const u8).init(b.allocator); var argv = std.ArrayList([]const u8).init(b.allocator);
try argv.appendSlice(&.{ b.zig_exe, "objcopy" }); try argv.appendSlice(&.{ b.graph.zig_exe, "objcopy" });
if (self.only_section) |only_section| { if (self.only_section) |only_section| {
try argv.appendSlice(&.{ "-j", only_section }); try argv.appendSlice(&.{ "-j", only_section });

View file

@ -222,7 +222,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
const basename = "options.zig"; const basename = "options.zig";
// Hash contents to file name. // Hash contents to file name.
var hash = b.cache.hash; var hash = b.graph.cache.hash;
// Random bytes to make unique. Refresh this with new random bytes when // Random bytes to make unique. Refresh this with new random bytes when
// implementation is modified in a non-backwards-compatible way. // implementation is modified in a non-backwards-compatible way.
hash.add(@as(u32, 0xad95e922)); hash.add(@as(u32, 0xad95e922));
@ -301,27 +301,28 @@ test Options {
var arena = std.heap.ArenaAllocator.init(std.testing.allocator); var arena = std.heap.ArenaAllocator.init(std.testing.allocator);
defer arena.deinit(); defer arena.deinit();
const host: std.Build.ResolvedTarget = .{ var graph: std.Build.Graph = .{
.query = .{}, .arena = arena.allocator(),
.result = try std.zig.system.resolveTargetQuery(.{}), .cache = .{
}; .gpa = arena.allocator(),
.manifest_dir = std.fs.cwd(),
var cache: std.Build.Cache = .{ },
.gpa = arena.allocator(), .zig_exe = "test",
.manifest_dir = std.fs.cwd(), .env_map = std.process.EnvMap.init(arena.allocator()),
.global_cache_root = .{ .path = "test", .handle = std.fs.cwd() },
}; };
var builder = try std.Build.create( var builder = try std.Build.create(
arena.allocator(), &graph,
"test",
.{ .path = "test", .handle = std.fs.cwd() }, .{ .path = "test", .handle = std.fs.cwd() },
.{ .path = "test", .handle = std.fs.cwd() }, .{ .path = "test", .handle = std.fs.cwd() },
.{ .path = "test", .handle = std.fs.cwd() },
host,
&cache,
&.{}, &.{},
); );
defer builder.destroy();
builder.host = .{
.query = .{},
.result = try std.zig.system.resolveTargetQuery(.{}),
};
const options = builder.addOptions(); const options = builder.addOptions();

View file

@ -463,7 +463,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
var argv_list = ArrayList([]const u8).init(arena); var argv_list = ArrayList([]const u8).init(arena);
var output_placeholders = ArrayList(IndexedOutput).init(arena); var output_placeholders = ArrayList(IndexedOutput).init(arena);
var man = b.cache.obtain(); var man = b.graph.cache.obtain();
defer man.deinit(); defer man.deinit();
for (self.argv.items) |arg| { for (self.argv.items) |arg| {
@ -747,7 +747,7 @@ fn runCommand(
exe.is_linking_libc; exe.is_linking_libc;
const other_target = exe.root_module.resolved_target.?.result; const other_target = exe.root_module.resolved_target.?.result;
switch (std.zig.system.getExternalExecutor(b.host.result, &other_target, .{ switch (std.zig.system.getExternalExecutor(b.host.result, &other_target, .{
.qemu_fixes_dl = need_cross_glibc and b.glibc_runtimes_dir != null, .qemu_fixes_dl = need_cross_glibc and b.graph.glibc_runtimes_dir != null,
.link_libc = exe.is_linking_libc, .link_libc = exe.is_linking_libc,
})) { })) {
.native, .rosetta => { .native, .rosetta => {
@ -755,7 +755,7 @@ fn runCommand(
break :interpret; break :interpret;
}, },
.wine => |bin_name| { .wine => |bin_name| {
if (b.enable_wine) { if (b.graph.enable_wine) {
try interp_argv.append(bin_name); try interp_argv.append(bin_name);
try interp_argv.appendSlice(argv); try interp_argv.appendSlice(argv);
} else { } else {
@ -763,9 +763,9 @@ fn runCommand(
} }
}, },
.qemu => |bin_name| { .qemu => |bin_name| {
if (b.enable_qemu) { if (b.graph.enable_qemu) {
const glibc_dir_arg = if (need_cross_glibc) const glibc_dir_arg = if (need_cross_glibc)
b.glibc_runtimes_dir orelse b.graph.glibc_runtimes_dir orelse
return failForeign(self, "--glibc-runtimes", argv[0], exe) return failForeign(self, "--glibc-runtimes", argv[0], exe)
else else
null; null;
@ -798,7 +798,7 @@ fn runCommand(
} }
}, },
.darling => |bin_name| { .darling => |bin_name| {
if (b.enable_darling) { if (b.graph.enable_darling) {
try interp_argv.append(bin_name); try interp_argv.append(bin_name);
try interp_argv.appendSlice(argv); try interp_argv.appendSlice(argv);
} else { } else {
@ -806,7 +806,7 @@ fn runCommand(
} }
}, },
.wasmtime => |bin_name| { .wasmtime => |bin_name| {
if (b.enable_wasmtime) { if (b.graph.enable_wasmtime) {
try interp_argv.append(bin_name); try interp_argv.append(bin_name);
try interp_argv.append("--dir=."); try interp_argv.append("--dir=.");
try interp_argv.append(argv[0]); try interp_argv.append(argv[0]);
@ -1036,7 +1036,7 @@ fn spawnChildAndCollect(
child.cwd = b.build_root.path; child.cwd = b.build_root.path;
child.cwd_dir = b.build_root.handle; child.cwd_dir = b.build_root.handle;
} }
child.env_map = self.env_map orelse b.env_map; child.env_map = self.env_map orelse &b.graph.env_map;
child.request_resource_usage_statistics = true; child.request_resource_usage_statistics = true;
child.stdin_behavior = switch (self.stdio) { child.stdin_behavior = switch (self.stdio) {

View file

@ -121,7 +121,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
const self = @fieldParentPtr(TranslateC, "step", step); const self = @fieldParentPtr(TranslateC, "step", step);
var argv_list = std.ArrayList([]const u8).init(b.allocator); var argv_list = std.ArrayList([]const u8).init(b.allocator);
try argv_list.append(b.zig_exe); try argv_list.append(b.graph.zig_exe);
try argv_list.append("translate-c"); try argv_list.append("translate-c");
if (self.link_libc) { if (self.link_libc) {
try argv_list.append("-lc"); try argv_list.append("-lc");

View file

@ -190,7 +190,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
// If, for example, a hard-coded path was used as the location to put WriteFile // If, for example, a hard-coded path was used as the location to put WriteFile
// files, then two WriteFiles executing in parallel might clobber each other. // files, then two WriteFiles executing in parallel might clobber each other.
var man = b.cache.obtain(); var man = b.graph.cache.obtain();
defer man.deinit(); defer man.deinit();
// Random bytes to make WriteFile unique. Refresh this with // Random bytes to make WriteFile unique. Refresh this with

View file

@ -562,7 +562,7 @@ pub fn lowerToBuildSteps(
run.setName(incr_case.base_path); run.setName(incr_case.base_path);
run.addArgs(&.{ run.addArgs(&.{
case_base_path_with_dir, case_base_path_with_dir,
b.zig_exe, b.graph.zig_exe,
}); });
run.expectStdOutEqual(""); run.expectStdOutEqual("");
parent_step.dependOn(&run.step); parent_step.dependOn(&run.step);
@ -653,7 +653,7 @@ pub fn lowerToBuildSteps(
break :no_exec; break :no_exec;
} }
const run_c = b.addSystemCommand(&.{ const run_c = b.addSystemCommand(&.{
b.zig_exe, b.graph.zig_exe,
"run", "run",
"-cflags", "-cflags",
"-Ilib", "-Ilib",

View file

@ -796,7 +796,7 @@ pub fn addCliTests(b: *std.Build) *Step {
{ {
// Test `zig init`. // Test `zig init`.
const tmp_path = b.makeTempPath(); const tmp_path = b.makeTempPath();
const init_exe = b.addSystemCommand(&.{ b.zig_exe, "init" }); const init_exe = b.addSystemCommand(&.{ b.graph.zig_exe, "init" });
init_exe.setCwd(.{ .cwd_relative = tmp_path }); init_exe.setCwd(.{ .cwd_relative = tmp_path });
init_exe.setName("zig init"); init_exe.setName("zig init");
init_exe.expectStdOutEqual(""); init_exe.expectStdOutEqual("");
@ -810,20 +810,20 @@ pub fn addCliTests(b: *std.Build) *Step {
const bad_out_arg = "-femit-bin=does" ++ s ++ "not" ++ s ++ "exist" ++ s ++ "foo.exe"; const bad_out_arg = "-femit-bin=does" ++ s ++ "not" ++ s ++ "exist" ++ s ++ "foo.exe";
const ok_src_arg = "src" ++ s ++ "main.zig"; const ok_src_arg = "src" ++ s ++ "main.zig";
const expected = "error: unable to open output directory 'does" ++ s ++ "not" ++ s ++ "exist': FileNotFound\n"; const expected = "error: unable to open output directory 'does" ++ s ++ "not" ++ s ++ "exist': FileNotFound\n";
const run_bad = b.addSystemCommand(&.{ b.zig_exe, "build-exe", ok_src_arg, bad_out_arg }); const run_bad = b.addSystemCommand(&.{ b.graph.zig_exe, "build-exe", ok_src_arg, bad_out_arg });
run_bad.setName("zig build-exe error message for bad -femit-bin arg"); run_bad.setName("zig build-exe error message for bad -femit-bin arg");
run_bad.expectExitCode(1); run_bad.expectExitCode(1);
run_bad.expectStdErrEqual(expected); run_bad.expectStdErrEqual(expected);
run_bad.expectStdOutEqual(""); run_bad.expectStdOutEqual("");
run_bad.step.dependOn(&init_exe.step); run_bad.step.dependOn(&init_exe.step);
const run_test = b.addSystemCommand(&.{ b.zig_exe, "build", "test" }); const run_test = b.addSystemCommand(&.{ b.graph.zig_exe, "build", "test" });
run_test.setCwd(.{ .cwd_relative = tmp_path }); run_test.setCwd(.{ .cwd_relative = tmp_path });
run_test.setName("zig build test"); run_test.setName("zig build test");
run_test.expectStdOutEqual(""); run_test.expectStdOutEqual("");
run_test.step.dependOn(&init_exe.step); run_test.step.dependOn(&init_exe.step);
const run_run = b.addSystemCommand(&.{ b.zig_exe, "build", "run" }); const run_run = b.addSystemCommand(&.{ b.graph.zig_exe, "build", "run" });
run_run.setCwd(.{ .cwd_relative = tmp_path }); run_run.setCwd(.{ .cwd_relative = tmp_path });
run_run.setName("zig build run"); run_run.setName("zig build run");
run_run.expectStdOutEqual("Run `zig build test` to run the tests.\n"); run_run.expectStdOutEqual("Run `zig build test` to run the tests.\n");
@ -857,7 +857,7 @@ pub fn addCliTests(b: *std.Build) *Step {
// This is intended to be the exact CLI usage used by godbolt.org. // This is intended to be the exact CLI usage used by godbolt.org.
const run = b.addSystemCommand(&.{ const run = b.addSystemCommand(&.{
b.zig_exe, "build-obj", b.graph.zig_exe, "build-obj",
"--cache-dir", tmp_path, "--cache-dir", tmp_path,
"--name", "example", "--name", "example",
"-fno-emit-bin", "-fno-emit-h", "-fno-emit-bin", "-fno-emit-h",
@ -900,7 +900,7 @@ pub fn addCliTests(b: *std.Build) *Step {
subdir.writeFile("fmt3.zig", unformatted_code) catch @panic("unhandled"); subdir.writeFile("fmt3.zig", unformatted_code) catch @panic("unhandled");
// Test zig fmt affecting only the appropriate files. // Test zig fmt affecting only the appropriate files.
const run1 = b.addSystemCommand(&.{ b.zig_exe, "fmt", "fmt1.zig" }); const run1 = b.addSystemCommand(&.{ b.graph.zig_exe, "fmt", "fmt1.zig" });
run1.setName("run zig fmt one file"); run1.setName("run zig fmt one file");
run1.setCwd(.{ .cwd_relative = tmp_path }); run1.setCwd(.{ .cwd_relative = tmp_path });
run1.has_side_effects = true; run1.has_side_effects = true;
@ -908,7 +908,7 @@ pub fn addCliTests(b: *std.Build) *Step {
run1.expectStdOutEqual("fmt1.zig\n"); run1.expectStdOutEqual("fmt1.zig\n");
// Test excluding files and directories from a run // Test excluding files and directories from a run
const run2 = b.addSystemCommand(&.{ b.zig_exe, "fmt", "--exclude", "fmt2.zig", "--exclude", "subdir", "." }); const run2 = b.addSystemCommand(&.{ b.graph.zig_exe, "fmt", "--exclude", "fmt2.zig", "--exclude", "subdir", "." });
run2.setName("run zig fmt on directory with exclusions"); run2.setName("run zig fmt on directory with exclusions");
run2.setCwd(.{ .cwd_relative = tmp_path }); run2.setCwd(.{ .cwd_relative = tmp_path });
run2.has_side_effects = true; run2.has_side_effects = true;
@ -916,7 +916,7 @@ pub fn addCliTests(b: *std.Build) *Step {
run2.step.dependOn(&run1.step); run2.step.dependOn(&run1.step);
// Test excluding non-existent file // Test excluding non-existent file
const run3 = b.addSystemCommand(&.{ b.zig_exe, "fmt", "--exclude", "fmt2.zig", "--exclude", "nonexistent.zig", "." }); const run3 = b.addSystemCommand(&.{ b.graph.zig_exe, "fmt", "--exclude", "fmt2.zig", "--exclude", "nonexistent.zig", "." });
run3.setName("run zig fmt on directory with non-existent exclusion"); run3.setName("run zig fmt on directory with non-existent exclusion");
run3.setCwd(.{ .cwd_relative = tmp_path }); run3.setCwd(.{ .cwd_relative = tmp_path });
run3.has_side_effects = true; run3.has_side_effects = true;
@ -924,7 +924,7 @@ pub fn addCliTests(b: *std.Build) *Step {
run3.step.dependOn(&run2.step); run3.step.dependOn(&run2.step);
// running it on the dir, only the new file should be changed // running it on the dir, only the new file should be changed
const run4 = b.addSystemCommand(&.{ b.zig_exe, "fmt", "." }); const run4 = b.addSystemCommand(&.{ b.graph.zig_exe, "fmt", "." });
run4.setName("run zig fmt the directory"); run4.setName("run zig fmt the directory");
run4.setCwd(.{ .cwd_relative = tmp_path }); run4.setCwd(.{ .cwd_relative = tmp_path });
run4.has_side_effects = true; run4.has_side_effects = true;
@ -932,7 +932,7 @@ pub fn addCliTests(b: *std.Build) *Step {
run4.step.dependOn(&run3.step); run4.step.dependOn(&run3.step);
// both files have been formatted, nothing should change now // both files have been formatted, nothing should change now
const run5 = b.addSystemCommand(&.{ b.zig_exe, "fmt", "." }); const run5 = b.addSystemCommand(&.{ b.graph.zig_exe, "fmt", "." });
run5.setName("run zig fmt with nothing to do"); run5.setName("run zig fmt with nothing to do");
run5.setCwd(.{ .cwd_relative = tmp_path }); run5.setCwd(.{ .cwd_relative = tmp_path });
run5.has_side_effects = true; run5.has_side_effects = true;
@ -946,7 +946,7 @@ pub fn addCliTests(b: *std.Build) *Step {
write6.step.dependOn(&run5.step); write6.step.dependOn(&run5.step);
// Test `zig fmt` handling UTF-16 decoding. // Test `zig fmt` handling UTF-16 decoding.
const run6 = b.addSystemCommand(&.{ b.zig_exe, "fmt", "." }); const run6 = b.addSystemCommand(&.{ b.graph.zig_exe, "fmt", "." });
run6.setName("run zig fmt convert UTF-16 to UTF-8"); run6.setName("run zig fmt convert UTF-16 to UTF-8");
run6.setCwd(.{ .cwd_relative = tmp_path }); run6.setCwd(.{ .cwd_relative = tmp_path });
run6.has_side_effects = true; run6.has_side_effects = true;