commit 71ac3f15b3740974e1bac091f32fc56933134ca2 (tree)
parent eaffd5551349be6132ab33827e307f28ca8ac051
Author: Andrew Kelley <andrew@ziglang.org>
Date: Mon, 9 Mar 2026 22:09:12 -0700
build system: implement LazyPath
Number of generated files is recorded in serialized Configuration. Maker
preallocates array of generated files so that loads and stores can be
synchronization-free (protected by the dependency tree ordering).
More progress on Compile Step Zig CLI lowering.
Diffstat:
15 files changed, 726 insertions(+), 458 deletions(-)
diff --git a/BRANCH_TODO b/BRANCH_TODO
@@ -0,0 +1,12 @@
+* rename std.zig.Configuration to std.Build.Configuration
+* replace union(@This().Tag)
+* replace b.dupe() with string internment
+* don't forget to add -listen arg back
+* get zig init template working
+* finish migrating the rest of the build steps
+* make zig-pkg path root configurable in maker (make sure --system still works)
+* eliminate calls to getPath, getPath2, getPath3
+* solve the TODOs added in this branch
+* get zig tests passing
+* test a bunch of third party projects / help people migrate
+* refactor with DefaultingEnum
diff --git a/lib/compiler/Maker.zig b/lib/compiler/Maker.zig
@@ -33,6 +33,7 @@ graph: *Graph,
install_paths: InstallPaths,
scanned_config: *const ScannedConfig,
steps: []Step,
+generated_files: []Path,
available_rss: usize,
max_rss_is_default: bool,
@@ -115,7 +116,13 @@ pub fn main(init: process.Init.Minimal) !void {
.zig_exe = zig_exe,
.environ_map = try init.environ.createMap(arena),
.global_cache_root = global_cache_directory,
+ .local_cache_root = local_cache_directory,
.zig_lib_directory = zig_lib_directory,
+ .build_root_directory = build_root_directory,
+ .pkg_root = .{
+ .root_dir = build_root_directory,
+ .sub_path = "zig-pkg",
+ },
};
graph.cache.addPrefix(.{ .path = null, .handle = cwd });
@@ -525,6 +532,7 @@ pub fn main(init: process.Init.Minimal) !void {
.include = install_include_path,
},
.steps = try arena.alloc(Step, scanned_config.configuration.steps.len),
+ .generated_files = try arena.alloc(Path, scanned_config.configuration.generated_files_len),
.available_rss = max_rss,
.max_rss_is_default = false,
@@ -1679,3 +1687,99 @@ fn initStdoutWriter(io: Io) *Writer {
stdout_writer_allocation = Io.File.stdout().writerStreaming(io, &stdio_buffer_allocation);
return &stdout_writer_allocation.interface;
}
+
+/// `asking_step` is only used for debugging purposes; it's the step being run
+/// that is asking for the path.
+pub fn resolveLazyPath(
+ maker: *const Maker,
+ arena: Allocator,
+ lazy_path: Configuration.LazyPath,
+ asking_step_index: Configuration.Step.Index,
+) Allocator.Error!Path {
+ _ = asking_step_index; // TODO use this to enhance debugability when this function fails
+ const c = &maker.scanned_config.configuration;
+ const graph = maker.graph;
+ return switch (lazy_path) {
+ .source_path => |sp| try packagePath(maker, arena, sp.owner, sp.sub_path.slice(c)),
+ .relative => |relative| switch (relative.flags.base) {
+ .cwd => .{
+ .root_dir = .cwd(),
+ .sub_path = relative.sub_path.slice(c),
+ },
+ .local_cache => .{
+ .root_dir = graph.local_cache_root,
+ },
+ .global_cache => .{
+ .root_dir = graph.global_cache_root,
+ },
+ .build_root => .{
+ .root_dir = graph.build_root_directory,
+ },
+ },
+ .generated => |gen| {
+ const base = maker.generated_files[@intFromEnum(gen.index)];
+ var file_path = base;
+ for (0..gen.flags.up) |_| {
+ file_path.sub_path = Io.Dir.path.dirname(file_path.sub_path) orelse
+ fatal("invalid LazyPath traversal: up {d} times from {f}", .{ gen.flags.up, base });
+ }
+ return file_path.join(arena, gen.sub_path.slice(c));
+ },
+ };
+}
+
+pub fn resolveLazyPathIndex(
+ maker: *const Maker,
+ arena: Allocator,
+ lazy_path_index: Configuration.LazyPath.Index,
+ asking_step_index: Configuration.Step.Index,
+) Allocator.Error!Path {
+ const c = &maker.scanned_config.configuration;
+ return resolveLazyPath(maker, arena, lazy_path_index.get(c), asking_step_index);
+}
+
+/// `resolveLazyPath` is preferred, but this can be necessary when passing Path
+/// objects to child processes.
+pub fn resolveLazyPathAbs(
+ maker: *const Maker,
+ arena: Allocator,
+ lazy_path: Configuration.LazyPath,
+ asking_step_index: Configuration.Step.Index,
+) Allocator.Error![]const u8 {
+ const p = try resolveLazyPath(maker, arena, lazy_path, asking_step_index);
+ const root_dir_path = p.root_dir.path orelse return p.subPathOrDot();
+ if (p.sub_path.len == 0) return root_dir_path;
+ return Io.Dir.path.join(arena, &.{ root_dir_path, p.sub_path });
+}
+
+/// `resolveLazyPath` is preferred, but this can be necessary when passing Path
+/// objects to child processes.
+pub fn resolveLazyPathIndexAbs(
+ maker: *const Maker,
+ arena: Allocator,
+ lazy_path_index: Configuration.LazyPath.Index,
+ asking_step_index: Configuration.Step.Index,
+) Allocator.Error![]const u8 {
+ const c = &maker.scanned_config.configuration;
+ return resolveLazyPathAbs(maker, arena, lazy_path_index.get(c), asking_step_index);
+}
+
+fn packagePath(
+ maker: *const Maker,
+ arena: Allocator,
+ package_index: Configuration.Package.Index,
+ sub_path: []const u8,
+) Allocator.Error!Path {
+ const c = &maker.scanned_config.configuration;
+ const graph = maker.graph;
+ const package = package_index.get(c) orelse return .{
+ .root_dir = graph.build_root_directory,
+ .sub_path = sub_path,
+ };
+ const hash = package.hash.slice(c);
+ const pkg_root = graph.pkg_root;
+ return .{
+ .root_dir = pkg_root.root_dir,
+ .sub_path = try Io.Dir.path.join(arena, &.{ pkg_root.sub_path, hash, sub_path }),
+ };
+}
diff --git a/lib/compiler/Maker/Graph.zig b/lib/compiler/Maker/Graph.zig
@@ -13,7 +13,10 @@ cache: std.Build.Cache,
zig_exe: []const u8,
environ_map: std.process.Environ.Map,
global_cache_root: std.Build.Cache.Directory,
+local_cache_root: std.Build.Cache.Directory,
zig_lib_directory: std.Build.Cache.Directory,
+build_root_directory: std.Build.Cache.Directory,
+pkg_root: std.Build.Cache.Path,
debug_compiler_runtime_libs: ?std.builtin.OptimizeMode = null,
incremental: ?bool = null,
diff --git a/lib/compiler/Maker/Step/Compile.zig b/lib/compiler/Maker/Step/Compile.zig
@@ -129,6 +129,7 @@ fn lowerZigArgs(
const conf = &maker.scanned_config.configuration;
const conf_step = compile_index.ptr(conf);
const conf_comp = conf_step.extended.get(conf.extra).compile;
+ const root_module_target = conf_comp.rootModuleTarget(conf);
try zig_args.append(gpa, graph.zig_exe);
@@ -232,17 +233,17 @@ fn lowerZigArgs(
}
}
- if (true) @panic("TODO");
-
// Inherit dependencies on system libraries and static libraries.
for (0..mod.link_objects.len) |lo_i| switch (mod.link_objects.get(conf.extra, lo_i)) {
.static_path => |static_path| {
if (my_responsibility) {
- try zig_args.append(gpa, static_path.getPath2(step));
+ try zig_args.append(gpa, try maker.resolveLazyPathIndexAbs(arena, static_path, compile_index));
total_linker_objects += 1;
}
},
- .system_lib => |system_lib| {
+ .system_lib => |system_lib_index| {
+ const system_lib = system_lib_index.get(conf);
+ const system_lib_name = system_lib.name.slice(conf);
const system_lib_gop = try seen_system_libs.getOrPut(arena, system_lib.name);
if (system_lib_gop.found_existing) {
try zig_args.appendSlice(gpa, system_lib_gop.value_ptr.*);
@@ -254,37 +255,39 @@ fn lowerZigArgs(
if (already_linked)
continue;
- if ((system_lib.search_strategy != prev_search_strategy or
- system_lib.preferred_link_mode != prev_preferred_link_mode) and
- compile.linkage != .static)
+ if ((system_lib.flags.search_strategy != prev_search_strategy or
+ system_lib.flags.preferred_link_mode != prev_preferred_link_mode) and
+ conf_comp.flags2.linkage != .static)
{
- switch (system_lib.search_strategy) {
- .no_fallback => switch (system_lib.preferred_link_mode) {
+ switch (system_lib.flags.search_strategy) {
+ .no_fallback => switch (system_lib.flags.preferred_link_mode) {
.dynamic => try zig_args.append(gpa, "-search_dylibs_only"),
.static => try zig_args.append(gpa, "-search_static_only"),
},
- .paths_first => switch (system_lib.preferred_link_mode) {
+ .paths_first => switch (system_lib.flags.preferred_link_mode) {
.dynamic => try zig_args.append(gpa, "-search_paths_first"),
.static => try zig_args.append(gpa, "-search_paths_first_static"),
},
- .mode_first => switch (system_lib.preferred_link_mode) {
+ .mode_first => switch (system_lib.flags.preferred_link_mode) {
.dynamic => try zig_args.append(gpa, "-search_dylibs_first"),
.static => try zig_args.append(gpa, "-search_static_first"),
},
}
- prev_search_strategy = system_lib.search_strategy;
- prev_preferred_link_mode = system_lib.preferred_link_mode;
+ prev_search_strategy = system_lib.flags.search_strategy;
+ prev_preferred_link_mode = system_lib.flags.preferred_link_mode;
}
const prefix: []const u8 = prefix: {
- if (system_lib.needed) break :prefix "-needed-l";
- if (system_lib.weak) break :prefix "-weak-l";
+ if (system_lib.flags.needed) break :prefix "-needed-l";
+ if (system_lib.flags.weak) break :prefix "-weak-l";
break :prefix "-l";
};
- switch (system_lib.use_pkg_config) {
- .no => try zig_args.append(gpa, try allocPrint(arena, "{s}{s}", .{ prefix, system_lib.name })),
+ switch (system_lib.flags.use_pkg_config) {
+ .no => try zig_args.append(gpa, try allocPrint(arena, "{s}{s}", .{
+ prefix, system_lib_name,
+ })),
.yes, .force => {
- if (compile.runPkgConfig(maker, system_lib.name)) |result| {
+ if (compile.runPkgConfig(maker, system_lib_name)) |result| {
try zig_args.appendSlice(gpa, result.cflags);
try zig_args.appendSlice(gpa, result.libs);
try seen_system_libs.put(arena, system_lib.name, result.cflags);
@@ -294,17 +297,18 @@ fn lowerZigArgs(
error.PkgConfigFailed,
error.PkgConfigNotInstalled,
error.PackageNotFound,
- => switch (system_lib.use_pkg_config) {
+ => switch (system_lib.flags.use_pkg_config) {
.yes => {
// pkg-config failed, so fall back to linking the library
// by name directly.
try zig_args.append(gpa, try allocPrint(arena, "{s}{s}", .{
- prefix,
- system_lib.name,
+ prefix, system_lib_name,
}));
},
.force => {
- return step.fail(maker, "pkg-config failed for library {s}", .{system_lib.name});
+ return step.fail(maker, "pkg-config failed for library {s}", .{
+ system_lib_name,
+ });
},
.no => unreachable,
},
@@ -314,23 +318,31 @@ fn lowerZigArgs(
},
}
},
- .other_step => |other| {
- switch (other.kind) {
+ .other_step => |other_step_index| {
+ const other = other_step_index.ptr(conf);
+ const other_compile = other.extended.get(conf.extra).compile;
+ switch (other_compile.flags3.kind) {
.exe => return step.fail(maker, "cannot link with an executable build artifact", .{}),
.@"test" => return step.fail(maker, "cannot link with a test", .{}),
.obj, .test_obj => {
- const included_in_lib_or_obj = !my_responsibility and
- (dep_compile.kind == .lib or dep_compile.kind == .obj or dep_compile.kind == .test_obj);
+ const included_in_lib_or_obj = switch (dep_compile.flags3.kind) {
+ .lib, .obj, .test_obj => !my_responsibility,
+ else => false,
+ };
if (!already_linked and !included_in_lib_or_obj) {
- try zig_args.append(gpa, other.getEmittedBin().getPath2(step));
+ try zig_args.append(gpa, try maker.resolveLazyPathAbs(
+ arena,
+ .{ .generated = .{ .index = other_compile.generated_bin.value.? } },
+ compile_index,
+ ));
total_linker_objects += 1;
}
},
.lib => l: {
- const other_produces_implib = other.producesImplib();
- const other_is_static = other_produces_implib or other.isStaticLibrary();
+ const other_produces_implib = other_compile.producesImplib(conf);
+ const other_is_static = other_produces_implib or other_compile.isStaticLibrary();
- if (compile.isStaticLibrary() and other_is_static) {
+ if (conf_comp.isStaticLibrary() and other_is_static) {
// Avoid putting a static library inside a static library.
break :l;
}
@@ -338,20 +350,25 @@ fn lowerZigArgs(
// For DLLs, we must link against the implib.
// For everything else, we directly link
// against the library file.
- const full_path_lib = if (other_produces_implib)
- try other.getGeneratedFilePath("generated_implib", &compile.step)
- else
- try other.getGeneratedFilePath("generated_bin", &compile.step);
+ const full_path_lib = try maker.resolveLazyPathAbs(
+ arena,
+ .{ .generated = .{
+ .index = if (other_produces_implib)
+ other_compile.generated_implib.value.?
+ else
+ other_compile.generated_bin.value.?,
+ } },
+ compile_index,
+ );
try zig_args.append(gpa, full_path_lib);
total_linker_objects += 1;
- if (other.linkage == .dynamic and
- compile.rootModuleTarget().os.tag != .windows)
+ if (other_compile.flags2.linkage == .dynamic and
+ root_module_target.flags.os_tag != .windows)
{
if (Dir.path.dirname(full_path_lib)) |dirname| {
- try zig_args.append(gpa, "-rpath");
- try zig_args.append(gpa, dirname);
+ try zig_args.appendSlice(gpa, &.{ "-rpath", dirname });
}
}
},
@@ -361,92 +378,96 @@ fn lowerZigArgs(
if (!my_responsibility) break :l;
if (prev_has_cflags) {
- try zig_args.append(gpa, "-cflags");
- try zig_args.append(gpa, "--");
+ try zig_args.appendSlice(gpa, &.{ "-cflags", "--" });
prev_has_cflags = false;
}
- try zig_args.append(gpa, asm_file.getPath2(mod.owner, step));
+ try zig_args.append(gpa, try maker.resolveLazyPathIndexAbs(arena, asm_file, compile_index));
total_linker_objects += 1;
},
- .c_source_file => |c_source_file| l: {
+ .c_source_file => |c_source_file_index| l: {
if (!my_responsibility) break :l;
- if (prev_has_cflags or c_source_file.flags.len != 0) {
- try zig_args.append(gpa, "-cflags");
- for (c_source_file.flags) |arg| {
- try zig_args.append(gpa, arg);
+ const c_source_file = c_source_file_index.get(conf);
+
+ if (prev_has_cflags or c_source_file.args.slice.len != 0) {
+ try zig_args.ensureUnusedCapacity(gpa, 2 + c_source_file.args.slice.len);
+ zig_args.appendAssumeCapacity("-cflags");
+ for (c_source_file.args.slice) |arg| {
+ zig_args.appendAssumeCapacity(arg.slice(conf));
}
- try zig_args.append(gpa, "--");
+ zig_args.appendAssumeCapacity("--");
}
- prev_has_cflags = (c_source_file.flags.len != 0);
+ prev_has_cflags = (c_source_file.args.slice.len != 0);
- if (c_source_file.language) |lang| {
- try zig_args.append(gpa, "-x");
- try zig_args.append(gpa, lang.internalIdentifier());
- }
+ if (c_source_file.flags.lang.get()) |lang|
+ (try zig_args.addManyAsArray(gpa, 2)).* = .{ "-x", lang.clangIdentifier() };
- try zig_args.append(gpa, c_source_file.file.getPath2(mod.owner, step));
+ try zig_args.append(gpa, try maker.resolveLazyPathIndexAbs(arena, c_source_file.file, compile_index));
+
+ if (c_source_file.flags.lang != .default)
+ (try zig_args.addManyAsArray(gpa, 2)).* = .{ "-x", "none" };
- if (c_source_file.language != null) {
- try zig_args.append(gpa, "-x");
- try zig_args.append(gpa, "none");
- }
total_linker_objects += 1;
},
- .c_source_files => |c_source_files| l: {
+ .c_source_files => |c_source_files_index| l: {
if (!my_responsibility) break :l;
- if (prev_has_cflags or c_source_files.flags.len != 0) {
- try zig_args.append(gpa, "-cflags");
- for (c_source_files.flags) |arg| {
- try zig_args.append(gpa, arg);
+ const c_source_files = c_source_files_index.get(conf);
+
+ if (prev_has_cflags or c_source_files.args.slice.len != 0) {
+ try zig_args.ensureUnusedCapacity(gpa, 2 + c_source_files.args.slice.len);
+ zig_args.appendAssumeCapacity("-cflags");
+ for (c_source_files.args.slice) |arg| {
+ zig_args.appendAssumeCapacity(arg.slice(conf));
}
- try zig_args.append(gpa, "--");
+ zig_args.appendAssumeCapacity("--");
}
- prev_has_cflags = (c_source_files.flags.len != 0);
+ prev_has_cflags = (c_source_files.args.slice.len != 0);
- if (c_source_files.language) |lang| {
- try zig_args.append(gpa, "-x");
- try zig_args.append(gpa, lang.internalIdentifier());
- }
+ if (c_source_files.flags.lang.get()) |lang|
+ (try zig_args.addManyAsArray(gpa, 2)).* = .{ "-x", lang.clangIdentifier() };
- const root_path = c_source_files.root.getPath2(mod.owner, step);
- for (c_source_files.files) |file| {
- try zig_args.append(gpa, try Dir.path.join(arena, &.{ root_path, file }));
+ const root_path = try maker.resolveLazyPathIndexAbs(arena, c_source_files.root, compile_index);
+ try zig_args.ensureUnusedCapacity(gpa, c_source_files.sub_paths.slice.len);
+ for (c_source_files.sub_paths.slice) |sub_path| {
+ zig_args.appendAssumeCapacity(try Dir.path.join(arena, &.{
+ root_path, sub_path.slice(conf),
+ }));
}
- if (c_source_files.language != null) {
- try zig_args.append(gpa, "-x");
- try zig_args.append(gpa, "none");
- }
+ if (c_source_files.flags.lang != .default)
+ (try zig_args.addManyAsArray(gpa, 2)).* = .{ "-x", "none" };
- total_linker_objects += c_source_files.files.len;
+ total_linker_objects += c_source_files.sub_paths.slice.len;
},
- .win32_resource_file => |rc_source_file| l: {
+ .win32_resource_file => |rc_source_file_index| l: {
if (!my_responsibility) break :l;
- if (rc_source_file.flags.len == 0 and rc_source_file.include_paths.len == 0) {
+ const rc_source_file = rc_source_file_index.get(conf);
+
+ if (rc_source_file.args.slice.len == 0 and rc_source_file.include_paths.slice.len == 0) {
if (prev_has_rcflags) {
- try zig_args.append(gpa, "-rcflags");
- try zig_args.append(gpa, "--");
+ (try zig_args.addManyAsArray(gpa, 2)).* = .{ "-rcflags", "--" };
prev_has_rcflags = false;
}
} else {
- try zig_args.append(gpa, "-rcflags");
- for (rc_source_file.flags) |arg| {
- try zig_args.append(gpa, arg);
+ try zig_args.ensureUnusedCapacity(gpa, 1 + rc_source_file.args.slice.len);
+ zig_args.appendAssumeCapacity("-rcflags");
+ for (rc_source_file.args.slice) |arg| {
+ zig_args.appendAssumeCapacity(arg.slice(conf));
}
- for (rc_source_file.include_paths) |include_path| {
- try zig_args.append(gpa, "/I");
- try zig_args.append(gpa, include_path.getPath2(mod.owner, step));
+ try zig_args.ensureUnusedCapacity(gpa, 1 + 2 * rc_source_file.include_paths.slice.len);
+ for (rc_source_file.include_paths.slice) |include_path| {
+ zig_args.appendAssumeCapacity("/I");
+ zig_args.appendAssumeCapacity(try maker.resolveLazyPathIndexAbs(arena, include_path, compile_index));
}
- try zig_args.append(gpa, "--");
+ zig_args.appendAssumeCapacity("--");
prev_has_rcflags = true;
}
- try zig_args.append(gpa, rc_source_file.file.getPath2(mod.owner, step));
+ try zig_args.append(gpa, try maker.resolveLazyPathIndexAbs(arena, rc_source_file.file, compile_index));
total_linker_objects += 1;
},
};
@@ -455,9 +476,10 @@ fn lowerZigArgs(
// have the correct parent module, but only if the module is part of
// this compilation.
if (!my_responsibility) continue;
- if (cli_named_modules.modules.getIndex(mod)) |module_cli_index| {
+ if (cli_named_modules.modules.getIndex(mod_index)) |module_cli_index| {
const module_cli_name = cli_named_modules.names.keys()[module_cli_index];
- try mod.appendZigProcessFlags(zig_args, step);
+ if (true) @panic("TODO");
+ try appendModuleFlags(zig_args, step);
// --dep arguments
try zig_args.ensureUnusedCapacity(mod.import_table.count() * 2);
@@ -510,12 +532,12 @@ fn lowerZigArgs(
if (is_linking_libc) zig_args.appendAssumeCapacity("-lc");
}
- if (true) @panic("TODO");
-
- if (conf_comp.win32_manifest) |manifest_file| {
- try zig_args.append(gpa, manifest_file.getPath2(step));
+ if (conf_comp.win32_manifest.value) |manifest_file| {
+ try zig_args.append(gpa, try maker.resolveLazyPathIndexAbs(arena, manifest_file, compile_index));
}
+ if (true) @panic("TODO");
+
if (conf_comp.win32_module_definition) |module_file| {
try zig_args.append(gpa, module_file.getPath2(step));
}
@@ -623,27 +645,26 @@ fn lowerZigArgs(
"--version", try allocPrint(arena, "{f}", .{version}),
});
- if (compile.rootModuleTarget().os.tag.isDarwin()) {
+ if (root_module_target.flags.os_tag.isDarwin()) {
const install_name = compile.install_name orelse try allocPrint(arena, "@rpath/{s}{s}{s}", .{
- compile.rootModuleTarget().libPrefix(),
+ root_module_target.libPrefix(),
compile.name,
- compile.rootModuleTarget().dynamicLibSuffix(),
+ root_module_target.dynamicLibSuffix(),
});
- try zig_args.append(gpa, "-install_name");
- try zig_args.append(gpa, install_name);
+ try zig_args.appendSlice(gpa, &.{ "-install_name", install_name });
}
}
if (compile.entitlements) |entitlements| {
- try zig_args.appendSlice(gpa, &[_][]const u8{ "--entitlements", entitlements });
+ try zig_args.appendSlice(gpa, &.{ "--entitlements", entitlements });
}
if (compile.pagezero_size) |pagezero_size| {
const size = try allocPrint(arena, "{x}", .{pagezero_size});
- try zig_args.appendSlice(gpa, &[_][]const u8{ "-pagezero_size", size });
+ try zig_args.appendSlice(gpa, &.{ "-pagezero_size", size });
}
if (compile.headerpad_size) |headerpad_size| {
const size = try allocPrint(arena, "{x}", .{headerpad_size});
- try zig_args.appendSlice(gpa, &[_][]const u8{ "-headerpad", size });
+ try zig_args.appendSlice(gpa, &.{ "-headerpad", size });
}
if (compile.headerpad_max_install_names) {
try zig_args.append(gpa, "-headerpad_max_install_names");
@@ -1019,7 +1040,8 @@ const PkgConfigResult = struct {
/// Run pkg-config for the given library name and parse the output, returning the arguments
/// that should be passed to zig to link the given library.
-fn runPkgConfig(compile: *Compile, maker: *Maker, lib_name: []const u8) !PkgConfigResult {
+fn runPkgConfig(compile: *const Compile, maker: *const Maker, lib_name: []const u8) !PkgConfigResult {
+ if (true) @panic("TODO");
const graph = maker.graph;
const wl_rpath_prefix = "-Wl,-rpath,";
@@ -1365,3 +1387,131 @@ fn getModuleList(
return modules;
}
+
+fn appendModuleFlags(
+ m: *Module,
+ zig_args: *std.array_list.Managed([]const u8),
+ asking_step: ?*Step,
+) !void {
+ const b = m.owner;
+
+ try addFlag(zig_args, m.strip, "-fstrip", "-fno-strip");
+ try addFlag(zig_args, m.single_threaded, "-fsingle-threaded", "-fno-single-threaded");
+ try addFlag(zig_args, m.stack_check, "-fstack-check", "-fno-stack-check");
+ try addFlag(zig_args, m.stack_protector, "-fstack-protector", "-fno-stack-protector");
+ try addFlag(zig_args, m.omit_frame_pointer, "-fomit-frame-pointer", "-fno-omit-frame-pointer");
+ try addFlag(zig_args, m.error_tracing, "-ferror-tracing", "-fno-error-tracing");
+ try addFlag(zig_args, m.sanitize_thread, "-fsanitize-thread", "-fno-sanitize-thread");
+ try addFlag(zig_args, m.fuzz, "-ffuzz", "-fno-fuzz");
+ try addFlag(zig_args, m.valgrind, "-fvalgrind", "-fno-valgrind");
+ try addFlag(zig_args, m.pic, "-fPIC", "-fno-PIC");
+ try addFlag(zig_args, m.red_zone, "-mred-zone", "-mno-red-zone");
+ try addFlag(zig_args, m.no_builtin, "-fno-builtin", "-fbuiltin");
+
+ if (m.sanitize_c) |sc| switch (sc) {
+ .off => try zig_args.append("-fno-sanitize-c"),
+ .trap => try zig_args.append("-fsanitize-c=trap"),
+ .full => try zig_args.append("-fsanitize-c=full"),
+ };
+
+ if (m.dwarf_format) |dwarf_format| {
+ try zig_args.append(switch (dwarf_format) {
+ .@"32" => "-gdwarf32",
+ .@"64" => "-gdwarf64",
+ });
+ }
+
+ if (m.unwind_tables) |unwind_tables| {
+ try zig_args.append(switch (unwind_tables) {
+ .none => "-fno-unwind-tables",
+ .sync => "-funwind-tables",
+ .async => "-fasync-unwind-tables",
+ });
+ }
+
+ try zig_args.ensureUnusedCapacity(1);
+ if (m.optimize) |optimize| switch (optimize) {
+ .Debug => zig_args.appendAssumeCapacity("-ODebug"),
+ .ReleaseSmall => zig_args.appendAssumeCapacity("-OReleaseSmall"),
+ .ReleaseFast => zig_args.appendAssumeCapacity("-OReleaseFast"),
+ .ReleaseSafe => zig_args.appendAssumeCapacity("-OReleaseSafe"),
+ };
+
+ if (m.code_model != .default) {
+ try zig_args.append("-mcmodel");
+ try zig_args.append(@tagName(m.code_model));
+ }
+
+ if (m.resolved_target) |*target| {
+ // Communicate the query via CLI since it's more compact.
+ if (!target.query.isNative()) {
+ try zig_args.appendSlice(&.{
+ "-target", try target.query.zigTriple(b.allocator),
+ "-mcpu", try target.query.serializeCpuAlloc(b.allocator),
+ });
+ if (target.query.dynamic_linker) |*dynamic_linker| {
+ if (dynamic_linker.get()) |dynamic_linker_path| {
+ try zig_args.append("--dynamic-linker");
+ try zig_args.append(dynamic_linker_path);
+ } else {
+ try zig_args.append("--no-dynamic-linker");
+ }
+ }
+ }
+ }
+
+ for (m.export_symbol_names) |symbol_name| {
+ try zig_args.append(b.fmt("--export={s}", .{symbol_name}));
+ }
+
+ for (m.include_dirs.items) |include_dir| {
+ try appendIncludeDirFlags(include_dir, b, zig_args, asking_step);
+ }
+
+ try zig_args.appendSlice(m.c_macros.items);
+
+ try zig_args.ensureUnusedCapacity(2 * m.lib_paths.items.len);
+ for (m.lib_paths.items) |lib_path| {
+ zig_args.appendAssumeCapacity("-L");
+ zig_args.appendAssumeCapacity(lib_path.getPath2(b, asking_step));
+ }
+
+ try zig_args.ensureUnusedCapacity(2 * m.rpaths.items.len);
+ for (m.rpaths.items) |rpath| switch (rpath) {
+ .lazy_path => |lp| {
+ zig_args.appendAssumeCapacity("-rpath");
+ zig_args.appendAssumeCapacity(lp.getPath2(b, asking_step));
+ },
+ .special => |bytes| {
+ zig_args.appendAssumeCapacity("-rpath");
+ zig_args.appendAssumeCapacity(bytes);
+ },
+ };
+}
+
+fn appendIncludeDirFlags(
+ include_dir: Configuration.Module.IncludeDir,
+ b: *std.Build,
+ zig_args: *std.array_list.Managed([]const u8),
+ asking_step: ?*Step,
+) !void {
+ const flag: []const u8, const lazy_path: Configuration.LazyPath = switch (include_dir) {
+ // zig fmt: off
+ .path => |lp| .{ "-I", lp },
+ .path_system => |lp| .{ "-isystem", lp },
+ .path_after => |lp| .{ "-idirafter", lp },
+ .framework_path => |lp| .{ "-F", lp },
+ .framework_path_system => |lp| .{ "-iframework", lp },
+ .config_header_step => |ch| .{ "-I", ch.getOutputDir() },
+ .other_step => |comp| .{ "-I", comp.installed_headers_include_tree.?.getDirectory() },
+ // zig fmt: on
+ .embed_path => |lazy_path| {
+ // Special case: this is a single arg.
+ const resolved = lazy_path.getPath3(b, asking_step);
+ const arg = b.fmt("--embed-dir={f}", .{resolved});
+ return zig_args.append(arg);
+ },
+ };
+ const resolved_str = try lazy_path.getPath3(b, asking_step).toString(b.graph.arena);
+ return zig_args.appendSlice(&.{ flag, resolved_str });
+}
diff --git a/lib/compiler/configurer.zig b/lib/compiler/configurer.zig
@@ -96,6 +96,7 @@ pub fn main(init: process.Init.Minimal) !void {
.query = .{},
.result = try std.zig.system.resolveTargetQuery(io, .{}),
},
+ .generated_files = .empty,
};
graph.cache.addPrefix(.{ .path = null, .handle = cwd });
@@ -242,7 +243,7 @@ const Serialize = struct {
return gop.value_ptr.*;
}
- fn addOptionalLazyPathEnum(s: *Serialize, lp: ?std.Build.LazyPath) !Configuration.OptionalLazyPath {
+ fn addOptionalLazyPathEnum(s: *Serialize, lp: ?std.Build.LazyPath) !Configuration.LazyPath.OptionalIndex {
const wc = s.wc;
return @enumFromInt(switch (lp orelse return .none) {
.src_path => |src_path| i: {
@@ -257,6 +258,7 @@ const Serialize = struct {
const sub_path = try wc.addString(generated.sub_path);
break :i try wc.addExtra(@as(Configuration.LazyPath.Generated, .{
.flags = .{ .up = @intCast(generated.up) },
+ .index = generated.index,
.sub_path = sub_path,
}));
},
@@ -278,11 +280,11 @@ const Serialize = struct {
});
}
- fn addOptionalLazyPath(s: *Serialize, lp: ?std.Build.LazyPath) !?Configuration.LazyPath {
+ fn addOptionalLazyPath(s: *Serialize, lp: ?std.Build.LazyPath) !?Configuration.LazyPath.Index {
return (try addOptionalLazyPathEnum(s, lp)).unwrap();
}
- fn addLazyPath(s: *Serialize, lp: std.Build.LazyPath) !Configuration.LazyPath {
+ fn addLazyPath(s: *Serialize, lp: std.Build.LazyPath) !Configuration.LazyPath.Index {
return @enumFromInt(@intFromEnum(try addOptionalLazyPathEnum(s, lp)));
}
@@ -351,8 +353,8 @@ const Serialize = struct {
})));
}
- fn initLazyPathList(s: *Serialize, list: []const std.Build.LazyPath) ![]const Configuration.LazyPath {
- const result = try s.arena.alloc(Configuration.LazyPath, list.len);
+ fn initLazyPathList(s: *Serialize, list: []const std.Build.LazyPath) ![]const Configuration.LazyPath.Index {
+ const result = try s.arena.alloc(Configuration.LazyPath.Index, list.len);
for (result, list) |*dest, src| dest.* = try addLazyPath(s, src);
return result;
}
@@ -665,6 +667,15 @@ fn serialize(b: *std.Build, wc: *Configuration.Wip, writer: *Io.Writer) !void {
} else .none,
.linker_script = c.linker_script != null,
.version_script = c.version_script != null,
+ .emit_directory = c.emit_directory != .none,
+ .generated_docs = c.generated_docs != .none,
+ .generated_asm = c.generated_asm != .none,
+ .generated_bin = c.generated_bin != .none,
+ .generated_pdb = c.generated_pdb != .none,
+ .generated_implib = c.generated_implib != .none,
+ .generated_llvm_bc = c.generated_llvm_bc != .none,
+ .generated_llvm_ir = c.generated_llvm_ir != .none,
+ .generated_h = c.generated_h != .none,
},
.root_module = try s.addModule(c.root_module),
.root_name = try wc.addString(c.name),
@@ -709,6 +720,16 @@ fn serialize(b: *std.Build, wc: *Configuration.Wip, writer: *Io.Writer) !void {
.simple => .{ .simple = try s.addLazyPath(tr.path) },
.server => .{ .server = try s.addLazyPath(tr.path) },
} else .default },
+
+ .emit_directory = .{ .value = c.emit_directory.unwrap() },
+ .generated_docs = .{ .value = c.generated_docs.unwrap() },
+ .generated_asm = .{ .value = c.generated_asm.unwrap() },
+ .generated_bin = .{ .value = c.generated_bin.unwrap() },
+ .generated_pdb = .{ .value = c.generated_pdb.unwrap() },
+ .generated_implib = .{ .value = c.generated_implib.unwrap() },
+ .generated_llvm_bc = .{ .value = c.generated_llvm_bc.unwrap() },
+ .generated_llvm_ir = .{ .value = c.generated_llvm_ir.unwrap() },
+ .generated_h = .{ .value = c.generated_h.unwrap() },
}));
break :e @enumFromInt(extra_index);
@@ -804,6 +825,7 @@ fn serialize(b: *std.Build, wc: *Configuration.Wip, writer: *Io.Writer) !void {
try wc.write(writer, .{
.default_step = s.stepIndex(b.default_step),
+ .generated_files_len = @intCast(graph.generated_files.items.len),
});
}
diff --git a/lib/std/Build.zig b/lib/std/Build.zig
@@ -1,4 +1,5 @@
const Build = @This();
+
const builtin = @import("builtin");
const std = @import("std.zig");
@@ -111,6 +112,14 @@ pub const Graph = struct {
/// process via `Step.Run` API but cannot be observed in the configure
/// phase.
have_run_args: bool = false,
+
+ /// Indexes correspond to `Configuration.GeneratedFileIndex`.
+ generated_files: std.ArrayList(*Step),
+
+ pub fn addGeneratedFile(graph: *Graph, owner: *Step) Configuration.GeneratedFileIndex {
+ graph.generated_files.append(graph.arena, owner) catch @panic("OOM");
+ return @enumFromInt(graph.generated_files.items.len - 1);
+ }
};
const AvailableDeps = []const struct { []const u8, []const u8 };
@@ -865,7 +874,7 @@ pub fn dupe(b: *Build, bytes: []const u8) []u8 {
return dupeInner(b.allocator, bytes);
}
-pub fn dupeInner(allocator: std.mem.Allocator, bytes: []const u8) []u8 {
+pub fn dupeInner(allocator: Allocator, bytes: []const u8) []u8 {
return allocator.dupe(u8, bytes) catch @panic("OOM");
}
@@ -881,7 +890,7 @@ pub fn dupePath(b: *Build, bytes: []const u8) []u8 {
return dupePathInner(b.allocator, bytes);
}
-fn dupePathInner(allocator: std.mem.Allocator, bytes: []const u8) []u8 {
+fn dupePathInner(allocator: Allocator, bytes: []const u8) []u8 {
const the_copy = dupeInner(allocator, bytes);
for (the_copy) |*byte| {
switch (byte.*) {
@@ -2068,13 +2077,6 @@ pub fn runBuild(b: *Build, build_zig: anytype) anyerror!void {
}
}
-/// A file that is generated by a build step.
-/// This struct is an interface that is meant to be used with `@fieldParentPtr` to implement the actual path logic.
-pub const GeneratedFile = struct {
- /// The step that generates the file.
- step: *Step,
-};
-
// dirnameAllowEmpty is a variant of fs.path.dirname
// that allows "" to refer to the root for relative paths.
//
@@ -2114,7 +2116,7 @@ pub const LazyPath = union(enum) {
},
generated: struct {
- file: *const GeneratedFile,
+ index: Configuration.GeneratedFileIndex,
/// The number of parent directories to go up.
/// 0 means the generated file itself.
@@ -2242,7 +2244,11 @@ pub const LazyPath = union(enum) {
pub fn addStepDependencies(lazy_path: LazyPath, other_step: *Step) void {
switch (lazy_path) {
.src_path, .cwd_relative, .dependency => {},
- .generated => |gen| other_step.dependOn(gen.file.step),
+ .generated => |gen| {
+ const graph = other_step.owner.graph;
+ const generated_owner_step = graph.generated_files.items[@intFromEnum(gen.index)];
+ other_step.dependOn(generated_owner_step);
+ },
}
}
@@ -2266,7 +2272,7 @@ pub const LazyPath = union(enum) {
return lazy_path.dupeInner(b.allocator);
}
- fn dupeInner(lazy_path: LazyPath, allocator: std.mem.Allocator) LazyPath {
+ fn dupeInner(lazy_path: LazyPath, allocator: Allocator) LazyPath {
return switch (lazy_path) {
.src_path => |sp| .{ .src_path = .{
.owner = sp.owner,
@@ -2274,7 +2280,7 @@ pub const LazyPath = union(enum) {
} },
.cwd_relative => |p| .{ .cwd_relative = dupePathInner(allocator, p) },
.generated => |gen| .{ .generated = .{
- .file = gen.file,
+ .index = gen.index,
.up = gen.up,
.sub_path = dupePathInner(allocator, gen.sub_path),
} },
diff --git a/lib/std/Build/Module.zig b/lib/std/Build/Module.zig
@@ -89,7 +89,8 @@ pub const CSourceLanguage = enum {
/// Assembly with the C preprocessor
assembly_with_preprocessor,
- pub fn internalIdentifier(self: CSourceLanguage) []const u8 {
+ /// The value passed to "-x" CLI flag of Clang.
+ pub fn clangIdentifier(self: CSourceLanguage) [:0]const u8 {
return switch (self) {
.c => "c",
.cpp => "c++",
@@ -164,33 +165,6 @@ pub const IncludeDir = union(enum) {
other_step: *Step.Compile,
config_header_step: *Step.ConfigHeader,
embed_path: LazyPath,
-
- pub fn appendZigProcessFlags(
- include_dir: IncludeDir,
- b: *std.Build,
- zig_args: *std.array_list.Managed([]const u8),
- asking_step: ?*Step,
- ) !void {
- const flag: []const u8, const lazy_path: LazyPath = switch (include_dir) {
- // zig fmt: off
- .path => |lp| .{ "-I", lp },
- .path_system => |lp| .{ "-isystem", lp },
- .path_after => |lp| .{ "-idirafter", lp },
- .framework_path => |lp| .{ "-F", lp },
- .framework_path_system => |lp| .{ "-iframework", lp },
- .config_header_step => |ch| .{ "-I", ch.getOutputDir() },
- .other_step => |comp| .{ "-I", comp.installed_headers_include_tree.?.getDirectory() },
- // zig fmt: on
- .embed_path => |lazy_path| {
- // Special case: this is a single arg.
- const resolved = lazy_path.getPath3(b, asking_step);
- const arg = b.fmt("--embed-dir={f}", .{resolved});
- return zig_args.append(arg);
- },
- };
- const resolved_str = try lazy_path.getPath3(b, asking_step).toString(b.graph.arena);
- return zig_args.appendSlice(&.{ flag, resolved_str });
- }
};
pub const LinkFrameworkOptions = struct {
@@ -533,117 +507,6 @@ pub fn addCMacro(m: *Module, name: []const u8, value: []const u8) void {
m.c_macros.append(b.allocator, b.fmt("-D{s}={s}", .{ name, value })) catch @panic("OOM");
}
-pub fn appendZigProcessFlags(
- m: *Module,
- zig_args: *std.array_list.Managed([]const u8),
- asking_step: ?*Step,
-) !void {
- const b = m.owner;
-
- try addFlag(zig_args, m.strip, "-fstrip", "-fno-strip");
- try addFlag(zig_args, m.single_threaded, "-fsingle-threaded", "-fno-single-threaded");
- try addFlag(zig_args, m.stack_check, "-fstack-check", "-fno-stack-check");
- try addFlag(zig_args, m.stack_protector, "-fstack-protector", "-fno-stack-protector");
- try addFlag(zig_args, m.omit_frame_pointer, "-fomit-frame-pointer", "-fno-omit-frame-pointer");
- try addFlag(zig_args, m.error_tracing, "-ferror-tracing", "-fno-error-tracing");
- try addFlag(zig_args, m.sanitize_thread, "-fsanitize-thread", "-fno-sanitize-thread");
- try addFlag(zig_args, m.fuzz, "-ffuzz", "-fno-fuzz");
- try addFlag(zig_args, m.valgrind, "-fvalgrind", "-fno-valgrind");
- try addFlag(zig_args, m.pic, "-fPIC", "-fno-PIC");
- try addFlag(zig_args, m.red_zone, "-mred-zone", "-mno-red-zone");
- try addFlag(zig_args, m.no_builtin, "-fno-builtin", "-fbuiltin");
-
- if (m.sanitize_c) |sc| switch (sc) {
- .off => try zig_args.append("-fno-sanitize-c"),
- .trap => try zig_args.append("-fsanitize-c=trap"),
- .full => try zig_args.append("-fsanitize-c=full"),
- };
-
- if (m.dwarf_format) |dwarf_format| {
- try zig_args.append(switch (dwarf_format) {
- .@"32" => "-gdwarf32",
- .@"64" => "-gdwarf64",
- });
- }
-
- if (m.unwind_tables) |unwind_tables| {
- try zig_args.append(switch (unwind_tables) {
- .none => "-fno-unwind-tables",
- .sync => "-funwind-tables",
- .async => "-fasync-unwind-tables",
- });
- }
-
- try zig_args.ensureUnusedCapacity(1);
- if (m.optimize) |optimize| switch (optimize) {
- .Debug => zig_args.appendAssumeCapacity("-ODebug"),
- .ReleaseSmall => zig_args.appendAssumeCapacity("-OReleaseSmall"),
- .ReleaseFast => zig_args.appendAssumeCapacity("-OReleaseFast"),
- .ReleaseSafe => zig_args.appendAssumeCapacity("-OReleaseSafe"),
- };
-
- if (m.code_model != .default) {
- try zig_args.append("-mcmodel");
- try zig_args.append(@tagName(m.code_model));
- }
-
- if (m.resolved_target) |*target| {
- // Communicate the query via CLI since it's more compact.
- if (!target.query.isNative()) {
- try zig_args.appendSlice(&.{
- "-target", try target.query.zigTriple(b.allocator),
- "-mcpu", try target.query.serializeCpuAlloc(b.allocator),
- });
- if (target.query.dynamic_linker) |*dynamic_linker| {
- if (dynamic_linker.get()) |dynamic_linker_path| {
- try zig_args.append("--dynamic-linker");
- try zig_args.append(dynamic_linker_path);
- } else {
- try zig_args.append("--no-dynamic-linker");
- }
- }
- }
- }
-
- for (m.export_symbol_names) |symbol_name| {
- try zig_args.append(b.fmt("--export={s}", .{symbol_name}));
- }
-
- for (m.include_dirs.items) |include_dir| {
- try include_dir.appendZigProcessFlags(b, zig_args, asking_step);
- }
-
- try zig_args.appendSlice(m.c_macros.items);
-
- try zig_args.ensureUnusedCapacity(2 * m.lib_paths.items.len);
- for (m.lib_paths.items) |lib_path| {
- zig_args.appendAssumeCapacity("-L");
- zig_args.appendAssumeCapacity(lib_path.getPath2(b, asking_step));
- }
-
- try zig_args.ensureUnusedCapacity(2 * m.rpaths.items.len);
- for (m.rpaths.items) |rpath| switch (rpath) {
- .lazy_path => |lp| {
- zig_args.appendAssumeCapacity("-rpath");
- zig_args.appendAssumeCapacity(lp.getPath2(b, asking_step));
- },
- .special => |bytes| {
- zig_args.appendAssumeCapacity("-rpath");
- zig_args.appendAssumeCapacity(bytes);
- },
- };
-}
-
-fn addFlag(
- args: *std.array_list.Managed([]const u8),
- opt: ?bool,
- then_name: []const u8,
- else_name: []const u8,
-) !void {
- const cond = opt orelse return;
- return args.append(if (cond) then_name else else_name);
-}
-
fn linkLibraryOrObject(m: *Module, other: *Step.Compile) void {
const allocator = m.owner.allocator;
_ = other.getEmittedBin(); // Indicate there is a dependency on the outputted binary.
diff --git a/lib/std/Build/Step/Compile.zig b/lib/std/Build/Step/Compile.zig
@@ -1,4 +1,5 @@
const Compile = @This();
+
const builtin = @import("builtin");
const std = @import("std");
@@ -13,8 +14,8 @@ const Step = std.Build.Step;
const LazyPath = std.Build.LazyPath;
const Module = std.Build.Module;
const InstallDir = std.Build.InstallDir;
-const GeneratedFile = std.Build.GeneratedFile;
const Path = std.Build.Cache.Path;
+const Configuration = std.Build.Configuration;
pub const base_tag: Step.Tag = .compile;
@@ -212,19 +213,6 @@ allow_so_scripts: ?bool = null,
/// otherwise.
expect_errors: ?ExpectedCompileErrors = null,
-emit_directory: ?*GeneratedFile,
-
-generated_docs: ?*GeneratedFile,
-generated_asm: ?*GeneratedFile,
-generated_bin: ?*GeneratedFile,
-generated_pdb: ?*GeneratedFile,
-// hack for stage2_x86_64 + coff
-generated_compiler_rt_dyn_lib: ?*GeneratedFile,
-generated_implib: ?*GeneratedFile,
-generated_llvm_bc: ?*GeneratedFile,
-generated_llvm_ir: ?*GeneratedFile,
-generated_h: ?*GeneratedFile,
-
/// The maximum number of distinct errors within a compilation step Defaults to
/// `std.math.maxInt(u16)`. Overrides the argument passed to `zig build`.
error_limit: ?u32 = null,
@@ -248,6 +236,16 @@ is_linking_libcpp: bool = false,
/// builtin fuzzer, see the `fuzz` flag in `Module`.
sanitize_coverage_trace_pc_guard: ?bool = null,
+emit_directory: Configuration.OptionalGeneratedFileIndex = .none,
+generated_docs: Configuration.OptionalGeneratedFileIndex = .none,
+generated_asm: Configuration.OptionalGeneratedFileIndex = .none,
+generated_bin: Configuration.OptionalGeneratedFileIndex = .none,
+generated_pdb: Configuration.OptionalGeneratedFileIndex = .none,
+generated_implib: Configuration.OptionalGeneratedFileIndex = .none,
+generated_llvm_bc: Configuration.OptionalGeneratedFileIndex = .none,
+generated_llvm_ir: Configuration.OptionalGeneratedFileIndex = .none,
+generated_h: Configuration.OptionalGeneratedFileIndex = .none,
+
pub const ExpectedCompileErrors = union(enum) {
contains: []const u8,
exact: []const []const u8,
@@ -291,7 +289,7 @@ pub const Options = struct {
entitlements: ?LazyPath = null,
};
-pub const Kind = std.Build.Configuration.Step.Compile.Kind;
+pub const Kind = Configuration.Step.Compile.Kind;
pub const HeaderInstallation = union(enum) {
file: File,
@@ -362,6 +360,9 @@ pub const TestRunner = struct {
};
pub fn create(owner: *std.Build, options: Options) *Compile {
+ const graph = owner.graph;
+ const arena = graph.arena;
+
const name = owner.dupe(options.name);
if (mem.find(u8, name, "/") != null or mem.find(u8, name, "\\") != null) {
panic("invalid name: '{s}'. It looks like a file path, but it is supposed to be the library or application name.", .{name});
@@ -376,12 +377,12 @@ pub fn create(owner: *std.Build, options: Options) *Compile {
if (options.kind.isTest() and mem.eql(u8, name, "test"))
@tagName(options.kind)
else
- owner.fmt("{s} {s}", .{ @tagName(options.kind), name }),
+ owner.fmt("{t} {s}", .{ options.kind, name }),
@tagName(options.root_module.optimize orelse .Debug),
- resolved_target.query.zigTriple(owner.allocator) catch @panic("OOM"),
+ resolved_target.query.zigTriple(arena) catch @panic("OOM"),
});
- const out_filename = std.zig.binNameAlloc(owner.allocator, .{
+ const out_filename = std.zig.binNameAlloc(arena, .{
.root_name = name,
.target = target,
.output_mode = switch (options.kind) {
@@ -393,7 +394,7 @@ pub fn create(owner: *std.Build, options: Options) *Compile {
.version = options.version,
}) catch @panic("OOM");
- const compile = owner.allocator.create(Compile) catch @panic("OOM");
+ const compile = arena.create(Compile) catch @panic("OOM");
compile.* = .{
.root_module = options.root_module,
.verbose_link = false,
@@ -420,17 +421,6 @@ pub fn create(owner: *std.Build, options: Options) *Compile {
.rdynamic = false,
.force_undefined_symbols = .empty,
- .emit_directory = null,
- .generated_docs = null,
- .generated_asm = null,
- .generated_bin = null,
- .generated_pdb = null,
- .generated_compiler_rt_dyn_lib = null,
- .generated_implib = null,
- .generated_llvm_bc = null,
- .generated_llvm_ir = null,
- .generated_h = null,
-
.use_llvm = options.use_llvm,
.use_lld = options.use_lld,
.use_new_linker = null,
@@ -706,13 +696,12 @@ pub fn setLibCFile(compile: *Compile, libc_file: ?LazyPath) void {
}
}
-fn getEmittedFileGeneric(compile: *Compile, output_file: *?*GeneratedFile) LazyPath {
- if (output_file.*) |file| return .{ .generated = .{ .file = file } };
- const arena = compile.step.owner.allocator;
- const generated_file = arena.create(GeneratedFile) catch @panic("OOM");
- generated_file.* = .{ .step = &compile.step };
- output_file.* = generated_file;
- return .{ .generated = .{ .file = generated_file } };
+fn getEmittedFileGeneric(compile: *Compile, output_file: *Configuration.OptionalGeneratedFileIndex) LazyPath {
+ if (output_file.unwrap()) |index| return .{ .generated = .{ .index = index } };
+ const graph = compile.step.owner.graph;
+ const index = graph.addGeneratedFile(&compile.step);
+ output_file.* = .init(index);
+ return .{ .generated = .{ .index = index } };
}
/// Returns the path to the directory that contains the emitted binary file.
@@ -785,46 +774,6 @@ pub fn setExecCmd(compile: *Compile, args: []const ?[]const u8) void {
compile.exec_cmd_args = duped_args;
}
-fn getGeneratedFilePath(compile: *Compile, comptime tag_name: []const u8, asking_step: ?*Step) ![]const u8 {
- const step = &compile.step;
- const b = step.owner;
- const graph = b.graph;
- const io = graph.io;
- const maybe_path: ?*GeneratedFile = @field(compile, tag_name);
-
- const generated_file = maybe_path orelse {
- const stderr = try io.lockStderr(&.{}, graph.stderr_mode);
- std.Build.dumpBadGetPathHelp(&compile.step, stderr.terminal(), compile.step.owner, asking_step) catch {};
- io.unlockStderr();
- @panic("missing emit option for " ++ tag_name);
- };
-
- const path = generated_file.path orelse {
- const stderr = try io.lockStderr(&.{}, graph.stderr_mode);
- std.Build.dumpBadGetPathHelp(&compile.step, stderr.terminal(), compile.step.owner, asking_step) catch {};
- io.unlockStderr();
- @panic(tag_name ++ " is null. Is there a missing step dependency?");
- };
-
- return path;
-}
-
-fn outputPath(c: *Compile, out_dir: std.Build.Cache.Path, ea: std.zig.EmitArtifact) []const u8 {
- const arena = c.step.owner.graph.arena;
- const name = ea.cacheName(arena, .{
- .root_name = c.name,
- .target = &c.root_module.resolved_target.?.result,
- .output_mode = switch (c.kind) {
- .lib => .Lib,
- .obj, .test_obj => .Obj,
- .exe, .@"test" => .Exe,
- },
- .link_mode = c.linkage,
- .version = c.version,
- }) catch @panic("OOM");
- return out_dir.joinString(arena, name) catch @panic("OOM");
-}
-
pub fn rootModuleTarget(c: *Compile) std.Target {
// The root module is always given a target, so we know this to be non-null.
return c.root_module.resolved_target.?.result;
diff --git a/lib/std/Build/Step/ConfigHeader.zig b/lib/std/Build/Step/ConfigHeader.zig
@@ -5,6 +5,7 @@ const Io = std.Io;
const Step = std.Build.Step;
const Allocator = std.mem.Allocator;
const Writer = std.Io.Writer;
+const Configuration = std.Build.Configuration;
pub const Style = union(enum) {
/// A configure format supported by autotools that uses `#undef foo` to
@@ -40,7 +41,7 @@ pub const Value = union(enum) {
step: Step,
values: std.array_hash_map.String(Value),
/// This directory contains the generated file under the name `include_path`.
-generated_dir: std.Build.GeneratedFile,
+generated_dir: Configuration.GeneratedFileIndex,
style: Style,
max_bytes: usize,
@@ -58,7 +59,9 @@ pub const Options = struct {
};
pub fn create(owner: *std.Build, options: Options) *ConfigHeader {
- const config_header = owner.allocator.create(ConfigHeader) catch @panic("OOM");
+ const graph = owner.graph;
+ const arena = graph.arena;
+ const config_header = arena.create(ConfigHeader) catch @panic("OOM");
var include_path: []const u8 = "config.h";
@@ -80,11 +83,9 @@ pub fn create(owner: *std.Build, options: Options) *ConfigHeader {
}
const name = if (options.style.getPath()) |s|
- owner.fmt("configure {s} header {s} to {s}", .{
- @tagName(options.style), s.getDisplayName(), include_path,
- })
+ owner.fmt("configure {t} header {s} to {s}", .{ options.style, s.getDisplayName(), include_path })
else
- owner.fmt("configure {s} header to {s}", .{ @tagName(options.style), include_path });
+ owner.fmt("configure {t} header to {s}", .{ options.style, include_path });
config_header.* = .{
.step = .init(.{
@@ -100,7 +101,7 @@ pub fn create(owner: *std.Build, options: Options) *ConfigHeader {
.max_bytes = options.max_bytes,
.include_path = include_path,
.include_guard_override = options.include_guard_override,
- .generated_dir = .{ .step = &config_header.step },
+ .generated_dir = graph.addGeneratedFile(&config_header.step),
};
if (options.style.getPath()) |s| {
@@ -125,7 +126,7 @@ pub fn addValues(config_header: *ConfigHeader, values: anytype) void {
}
pub fn getOutputDir(ch: *ConfigHeader) std.Build.LazyPath {
- return .{ .generated = .{ .file = &ch.generated_dir } };
+ return .{ .generated = .{ .index = &ch.generated_dir } };
}
pub fn getOutputFile(ch: *ConfigHeader) std.Build.LazyPath {
return ch.getOutputDir().path(ch.step.owner, ch.include_path);
diff --git a/lib/std/Build/Step/ObjCopy.zig b/lib/std/Build/Step/ObjCopy.zig
@@ -9,6 +9,7 @@ const Step = std.Build.Step;
const elf = std.elf;
const fs = std.fs;
const sort = std.sort;
+const Configuration = std.Build.Configuration;
pub const base_tag: Step.Tag = .objcopy;
@@ -71,8 +72,8 @@ pub const SetSectionFlags = struct {
step: Step,
input_file: std.Build.LazyPath,
basename: []const u8,
-output_file: std.Build.GeneratedFile,
-output_file_debug: ?std.Build.GeneratedFile,
+output_file: Configuration.GeneratedFileIndex,
+output_file_debug: Configuration.OptionalGeneratedFileIndex,
format: ?RawFormat,
only_section: ?[]const u8,
@@ -108,7 +109,10 @@ pub fn create(
input_file: std.Build.LazyPath,
options: Options,
) *ObjCopy {
- const objcopy = owner.allocator.create(ObjCopy) catch @panic("OOM");
+ const graph = owner.graph;
+ const arena = graph.arena;
+
+ const objcopy = arena.create(ObjCopy) catch @panic("OOM");
objcopy.* = ObjCopy{
.step = Step.init(.{
.tag = base_tag,
@@ -118,8 +122,11 @@ pub fn create(
}),
.input_file = input_file,
.basename = options.basename orelse input_file.getDisplayName(),
- .output_file = std.Build.GeneratedFile{ .step = &objcopy.step },
- .output_file_debug = if (options.strip != .none and options.extract_to_separate_file) std.Build.GeneratedFile{ .step = &objcopy.step } else null,
+ .output_file = graph.addGeneratedFile(&objcopy.step),
+ .output_file_debug = if (options.strip != .none and options.extract_to_separate_file)
+ .init(graph.addGeneratedFile(&objcopy.step))
+ else
+ .none,
.format = options.format,
.only_section = options.only_section,
.pad_to = options.pad_to,
@@ -134,10 +141,10 @@ pub fn create(
}
pub fn getOutput(objcopy: *const ObjCopy) std.Build.LazyPath {
- return .{ .generated = .{ .file = &objcopy.output_file } };
+ return .{ .generated = .{ .index = objcopy.output_file } };
}
pub fn getOutputSeparatedDebug(objcopy: *const ObjCopy) ?std.Build.LazyPath {
- return if (objcopy.output_file_debug) |*file| .{ .generated = .{ .file = file } } else null;
+ return if (objcopy.output_file_debug.unwrap()) |index| .{ .generated = .{ .index = index } } else null;
}
fn make(step: *Step, options: Step.MakeOptions) !void {
diff --git a/lib/std/Build/Step/Options.zig b/lib/std/Build/Step/Options.zig
@@ -1,24 +1,28 @@
const Options = @This();
+
const builtin = @import("builtin");
const std = @import("std");
const Io = std.Io;
const fs = std.fs;
const Step = std.Build.Step;
-const GeneratedFile = std.Build.GeneratedFile;
const LazyPath = std.Build.LazyPath;
+const Configuration = std.Build.Configuration;
pub const base_tag: Step.Tag = .options;
step: Step,
-generated_file: GeneratedFile,
+generated_file: Configuration.GeneratedFileIndex,
contents: std.ArrayList(u8),
args: std.ArrayList(Arg),
encountered_types: std.StringHashMapUnmanaged(void),
pub fn create(owner: *std.Build) *Options {
- const options = owner.allocator.create(Options) catch @panic("OOM");
+ const graph = owner.graph;
+ const arena = graph.arena;
+
+ const options = arena.create(Options) catch @panic("OOM");
options.* = .{
.step = .init(.{
.tag = base_tag,
@@ -26,12 +30,11 @@ pub fn create(owner: *std.Build) *Options {
.owner = owner,
.makeFn = make,
}),
- .generated_file = undefined,
+ .generated_file = graph.addGeneratedFile(&options.step),
.contents = .empty,
.args = .empty,
.encountered_types = .empty,
};
- options.generated_file = .{ .step = &options.step };
return options;
}
@@ -434,7 +437,7 @@ pub fn createModule(options: *Options) *std.Build.Module {
/// Returns the main artifact of this Build Step which is a Zig source file
/// generated from the key-value pairs of the Options.
pub fn getOutput(options: *Options) LazyPath {
- return .{ .generated = .{ .file = &options.generated_file } };
+ return .{ .generated = .{ .index = options.generated_file } };
}
fn make(step: *Step, make_options: Step.MakeOptions) !void {
diff --git a/lib/std/Build/Step/Run.zig b/lib/std/Build/Step/Run.zig
@@ -11,6 +11,7 @@ const process = std.process;
const EnvMap = std.process.Environ.Map;
const assert = std.debug.assert;
const Path = std.Build.Cache.Path;
+const Configuration = std.Build.Configuration;
pub const base_tag: Step.Tag = .run;
@@ -162,7 +163,7 @@ pub const DecoratedLazyPath = struct {
};
pub const Output = struct {
- generated_file: std.Build.GeneratedFile,
+ generated_file: Configuration.GeneratedFileIndex,
prefix: []const u8,
basename: []const u8,
};
@@ -272,21 +273,23 @@ pub fn addPrefixedOutputFileArg(
basename: []const u8,
) std.Build.LazyPath {
const b = run.step.owner;
+ const graph = b.graph;
+ const arena = graph.arena;
if (basename.len == 0) @panic("basename must not be empty");
- const output = b.allocator.create(Output) catch @panic("OOM");
+ const output = arena.create(Output) catch @panic("OOM");
output.* = .{
.prefix = b.dupe(prefix),
.basename = b.dupe(basename),
- .generated_file = .{ .step = &run.step },
+ .generated_file = graph.addGeneratedFile(&run.step),
};
- run.argv.append(b.allocator, .{ .output_file = output }) catch @panic("OOM");
+ run.argv.append(arena, .{ .output_file = output }) catch @panic("OOM");
if (run.rename_step_with_output_arg) {
run.setName(b.fmt("{s} ({s})", .{ run.step.name, basename }));
}
- return .{ .generated = .{ .file = &output.generated_file } };
+ return .{ .generated = .{ .index = output.generated_file } };
}
/// Appends an input file to the command line arguments.
@@ -470,20 +473,22 @@ pub fn addDepFileOutputArg(run: *Run, basename: []const u8) std.Build.LazyPath {
/// Only one dep file argument is allowed by instance.
pub fn addPrefixedDepFileOutputArg(run: *Run, prefix: []const u8, basename: []const u8) std.Build.LazyPath {
const b = run.step.owner;
+ const graph = b.graph;
+ const arena = graph.arena;
assert(run.dep_output_file == null);
- const dep_file = b.allocator.create(Output) catch @panic("OOM");
+ const dep_file = arena.create(Output) catch @panic("OOM");
dep_file.* = .{
.prefix = b.dupe(prefix),
.basename = b.dupe(basename),
- .generated_file = .{ .step = &run.step },
+ .generated_file = graph.addGeneratedFile(&run.step),
};
run.dep_output_file = dep_file;
- run.argv.append(b.allocator, .{ .output_file = dep_file }) catch @panic("OOM");
+ run.argv.append(arena, .{ .output_file = dep_file }) catch @panic("OOM");
- return .{ .generated = .{ .file = &dep_file.generated_file } };
+ return .{ .generated = .{ .index = dep_file.generated_file } };
}
pub fn addArg(run: *Run, arg: []const u8) void {
@@ -627,20 +632,22 @@ pub fn captureStdErr(run: *Run, options: CapturedStdIo.Options) std.Build.LazyPa
assert(run.stdio != .zig_test);
const b = run.step.owner;
+ const graph = b.graph;
+ const arena = graph.arena;
- if (run.captured_stderr) |captured| return .{ .generated = .{ .file = &captured.output.generated_file } };
+ if (run.captured_stderr) |captured| return .{ .generated = .{ .index = captured.output.generated_file } };
- const captured = b.allocator.create(CapturedStdIo) catch @panic("OOM");
+ const captured = arena.create(CapturedStdIo) catch @panic("OOM");
captured.* = .{
.output = .{
.prefix = "",
.basename = if (options.basename) |basename| b.dupe(basename) else "stderr",
- .generated_file = .{ .step = &run.step },
+ .generated_file = graph.addGeneratedFile(&run.step),
},
.trim_whitespace = options.trim_whitespace,
};
run.captured_stderr = captured;
- return .{ .generated = .{ .file = &captured.output.generated_file } };
+ return .{ .generated = .{ .index = captured.output.generated_file } };
}
pub fn captureStdOut(run: *Run, options: CapturedStdIo.Options) std.Build.LazyPath {
@@ -648,20 +655,22 @@ pub fn captureStdOut(run: *Run, options: CapturedStdIo.Options) std.Build.LazyPa
assert(run.stdio != .zig_test);
const b = run.step.owner;
+ const graph = b.graph;
+ const arena = graph.arena;
- if (run.captured_stdout) |captured| return .{ .generated = .{ .file = &captured.output.generated_file } };
+ if (run.captured_stdout) |captured| return .{ .generated = .{ .index = captured.output.generated_file } };
- const captured = b.allocator.create(CapturedStdIo) catch @panic("OOM");
+ const captured = arena.create(CapturedStdIo) catch @panic("OOM");
captured.* = .{
.output = .{
.prefix = "",
.basename = if (options.basename) |basename| b.dupe(basename) else "stdout",
- .generated_file = .{ .step = &run.step },
+ .generated_file = graph.addGeneratedFile(&run.step),
},
.trim_whitespace = options.trim_whitespace,
};
run.captured_stdout = captured;
- return .{ .generated = .{ .file = &captured.output.generated_file } };
+ return .{ .generated = .{ .index = captured.output.generated_file } };
}
/// Adds an additional input files that, when modified, indicates that this Run
diff --git a/lib/std/Build/Step/TranslateC.zig b/lib/std/Build/Step/TranslateC.zig
@@ -1,10 +1,11 @@
+const TranslateC = @This();
+
const std = @import("std");
const Step = std.Build.Step;
const LazyPath = std.Build.LazyPath;
const fs = std.fs;
const mem = std.mem;
-
-const TranslateC = @This();
+const Configuration = std.Build.Configuration;
pub const base_tag: Step.Tag = .translate_c;
@@ -16,7 +17,7 @@ c_macros: std.array_list.Managed([]const u8),
out_basename: []const u8,
target: std.Build.ResolvedTarget,
optimize: std.builtin.OptimizeMode,
-output_file: std.Build.GeneratedFile,
+output_file: Configuration.GeneratedFileIndex,
link_libc: bool,
pub const Options = struct {
@@ -27,7 +28,9 @@ pub const Options = struct {
};
pub fn create(owner: *std.Build, options: Options) *TranslateC {
- const translate_c = owner.allocator.create(TranslateC) catch @panic("OOM");
+ const graph = owner.graph;
+ const arena = graph.arena;
+ const translate_c = arena.create(TranslateC) catch @panic("OOM");
const source = options.root_source_file.dupe(owner);
translate_c.* = .{
.step = Step.init(.{
@@ -37,12 +40,12 @@ pub fn create(owner: *std.Build, options: Options) *TranslateC {
.makeFn = make,
}),
.source = source,
- .include_dirs = std.array_list.Managed(std.Build.Module.IncludeDir).init(owner.allocator),
- .c_macros = std.array_list.Managed([]const u8).init(owner.allocator),
+ .include_dirs = std.array_list.Managed(std.Build.Module.IncludeDir).init(arena),
+ .c_macros = std.array_list.Managed([]const u8).init(arena),
.out_basename = undefined,
.target = options.target,
.optimize = options.optimize,
- .output_file = .{ .step = &translate_c.step },
+ .output_file = graph.addGeneratedFile(&translate_c.step),
.link_libc = options.link_libc,
.system_libs = .empty,
};
@@ -59,7 +62,7 @@ pub const AddExecutableOptions = struct {
};
pub fn getOutput(translate_c: *TranslateC) std.Build.LazyPath {
- return .{ .generated = .{ .file = &translate_c.output_file } };
+ return .{ .generated = .{ .index = translate_c.output_file } };
}
/// Creates a module from the translated source and adds it to the package's
diff --git a/lib/std/Build/Step/WriteFile.zig b/lib/std/Build/Step/WriteFile.zig
@@ -9,13 +9,13 @@ const Dir = std.Io.Dir;
const Step = std.Build.Step;
const ArrayList = std.ArrayList;
const assert = std.debug.assert;
+const Configuration = std.Build.Configuration;
step: Step,
-/// The elements here are pointers because we need stable pointers for the GeneratedFile field.
files: std.ArrayList(File),
directories: std.ArrayList(Directory),
-generated_directory: std.Build.GeneratedFile,
+generated_directory: Configuration.GeneratedFileIndex,
mode: Mode = .whole_cached,
pub const base_tag: Step.Tag = .write_file;
@@ -86,7 +86,9 @@ pub const Contents = union(enum) {
};
pub fn create(owner: *std.Build) *WriteFile {
- const write_file = owner.allocator.create(WriteFile) catch @panic("OOM");
+ const graph = owner.graph;
+ const arena = graph.arena;
+ const write_file = arena.create(WriteFile) catch @panic("OOM");
write_file.* = .{
.step = Step.init(.{
.tag = base_tag,
@@ -95,7 +97,7 @@ pub fn create(owner: *std.Build) *WriteFile {
}),
.files = .empty,
.directories = .empty,
- .generated_directory = .{ .step = &write_file.step },
+ .generated_directory = graph.addGeneratedFile(&write_file.step),
};
return write_file;
}
@@ -111,7 +113,7 @@ pub fn add(write_file: *WriteFile, sub_path: []const u8, bytes: []const u8) std.
write_file.maybeUpdateName();
return .{
.generated = .{
- .file = &write_file.generated_directory,
+ .index = write_file.generated_directory,
.sub_path = file.sub_path,
},
};
@@ -137,7 +139,7 @@ pub fn addCopyFile(write_file: *WriteFile, source: std.Build.LazyPath, sub_path:
source.addStepDependencies(&write_file.step);
return .{
.generated = .{
- .file = &write_file.generated_directory,
+ .index = write_file.generated_directory,
.sub_path = file.sub_path,
},
};
@@ -165,7 +167,7 @@ pub fn addCopyDirectory(
source.addStepDependencies(&write_file.step);
return .{
.generated = .{
- .file = &write_file.generated_directory,
+ .index = write_file.generated_directory,
.sub_path = dir.sub_path,
},
};
@@ -174,7 +176,7 @@ pub fn addCopyDirectory(
/// Returns a `LazyPath` representing the base directory that contains all the
/// files from this `WriteFile`.
pub fn getDirectory(write_file: *WriteFile) std.Build.LazyPath {
- return .{ .generated = .{ .file = &write_file.generated_directory } };
+ return .{ .generated = .{ .index = write_file.generated_directory } };
}
fn maybeUpdateName(write_file: *WriteFile) void {
diff --git a/lib/std/zig/Configuration.zig b/lib/std/zig/Configuration.zig
@@ -15,6 +15,7 @@ system_integrations: []SystemIntegration,
available_options: []AvailableOption,
extra: []u32,
default_step: Step.Index,
+generated_files_len: u32,
/// The field order here matches `Configuration` which documents the order in
/// the serialized format.
@@ -28,6 +29,9 @@ pub const Header = extern struct {
extra_len: u32,
default_step: Step.Index,
+ /// There is not actually any data stored for this - it just provides a way
+ /// for maker process to preallocate an array for these.
+ generated_files_len: u32,
};
pub const Wip = struct {
@@ -44,6 +48,7 @@ pub const Wip = struct {
steps: std.ArrayList(Step) = .empty,
path_deps: std.MultiArrayList(Path) = .empty,
extra: std.ArrayList(u32) = .empty,
+ next_generated_file_index: u32 = 0,
const DedupeTable = std.HashMapUnmanaged(ExtraSlice, void, ExtraSlice.Context, std.hash_map.default_max_load_percentage);
const TargetsTable = std.HashMapUnmanaged(TargetQuery.Index, void, TargetsTableContext, std.hash_map.default_max_load_percentage);
@@ -127,6 +132,7 @@ pub const Wip = struct {
pub const Static = struct {
default_step: Step.Index,
+ generated_files_len: u32,
};
pub fn write(wip: *Wip, w: *Io.Writer, static: Static) Io.Writer.Error!void {
@@ -140,6 +146,7 @@ pub const Wip = struct {
.extra_len = @intCast(wip.extra.items.len),
.default_step = static.default_step,
+ .generated_files_len = static.generated_files_len,
};
var buffers = [_][]const u8{
@ptrCast(&header),
@@ -363,6 +370,11 @@ pub const Wip = struct {
const string = optional_string orelse return;
wip.extra.appendAssumeCapacity(@intFromEnum(string));
}
+
+ pub fn addGeneratedFile(wip: *Wip) GeneratedFileIndex {
+ defer wip.next_generated_file_index += 1;
+ return @enumFromInt(wip.next_generated_file_index);
+ }
};
pub const SystemIntegration = extern struct {
@@ -471,16 +483,16 @@ pub const Step = extern struct {
dest_dir: InstallDestDir,
dest_sub_path: String,
- emitted_bin: OptionalLazyPath,
+ emitted_bin: LazyPath.OptionalIndex,
implib_dir: InstallDestDir,
- emitted_implib: OptionalLazyPath,
+ emitted_implib: LazyPath.OptionalIndex,
pdb_dir: InstallDestDir,
- emitted_pdb: OptionalLazyPath,
+ emitted_pdb: LazyPath.OptionalIndex,
h_dir: InstallDestDir,
- emitted_h: OptionalLazyPath,
+ emitted_h: LazyPath.OptionalIndex,
/// Always a compile step.
artifact: Step.Index,
@@ -493,11 +505,11 @@ pub const Step = extern struct {
};
/// Trailing:
- /// * LazyPath for each file_inputs_len
+ /// * LazyPath.Index for each file_inputs_len
/// * Arg for each args_len
/// * environ_map if corresponding flag is set
/// * stdin: Bytes, // if StdIn.bytes is chosen
- /// * stdin: LazyPath, // if StdIn.lazy_path is chosen
+ /// * stdin: LazyPath.Index, // if StdIn.lazy_path is chosen
/// * checks: Checks, // if StdIo.check is chosen
/// * stdio_limit: u64, // if stdio_limit is set
/// * producer: Step.Index, // if producer is set. always compile step
@@ -505,7 +517,7 @@ pub const Step = extern struct {
flags: @This().Flags,
file_inputs_len: u32,
args_len: u32,
- cwd: OptionalLazyPath,
+ cwd: LazyPath.OptionalIndex,
captured_stdout: OptionalString, // basename
captured_stderr: OptionalString, // basename
@@ -514,7 +526,7 @@ pub const Step = extern struct {
/// * String if suffix set
/// * String if basename set
/// * Step.Index which is always a compile step if tag is artifact
- /// * LazyPath if tag is path_file, path_directory, or file_content
+ /// * LazyPath.Index if tag is path_file, path_directory, or file_content
pub const Arg = struct {
flags: Arg.Flags,
@@ -591,13 +603,13 @@ pub const Step = extern struct {
installed_headers: Storage.FlagLengthPrefixedList(.flags, .installed_headers_len, Storage.Extended(InstalledHeader.Flags, InstalledHeader)),
force_undefined_symbols: Storage.FlagLengthPrefixedList(.flags, .force_undefined_symbols_len, String),
expect_errors: Storage.FlagUnion(.flags4, .expect_errors, ExpectErrors),
- linker_script: Storage.FlagOptional(.flags4, .linker_script, LazyPath),
- version_script: Storage.FlagOptional(.flags4, .version_script, LazyPath),
- zig_lib_dir: Storage.FlagOptional(.flags3, .zig_lib_dir, LazyPath),
- libc_file: Storage.FlagOptional(.flags4, .libc_file, LazyPath),
- win32_manifest: Storage.FlagOptional(.flags3, .win32_manifest, LazyPath),
- win32_module_definition: Storage.FlagOptional(.flags3, .win32_module_definition, LazyPath),
- entitlements: Storage.FlagOptional(.flags4, .entitlements, LazyPath),
+ linker_script: Storage.FlagOptional(.flags4, .linker_script, LazyPath.Index),
+ version_script: Storage.FlagOptional(.flags4, .version_script, LazyPath.Index),
+ zig_lib_dir: Storage.FlagOptional(.flags3, .zig_lib_dir, LazyPath.Index),
+ libc_file: Storage.FlagOptional(.flags4, .libc_file, LazyPath.Index),
+ win32_manifest: Storage.FlagOptional(.flags3, .win32_manifest, LazyPath.Index),
+ win32_module_definition: Storage.FlagOptional(.flags3, .win32_module_definition, LazyPath.Index),
+ entitlements: Storage.FlagOptional(.flags4, .entitlements, LazyPath.Index),
version: Storage.FlagOptional(.flags3, .version, String), // semantic version string
entry: Storage.EnumOptional(.flags3, .entry, .symbol_name, String),
install_name: Storage.FlagOptional(.flags4, .install_name, String),
@@ -614,6 +626,16 @@ pub const Step = extern struct {
build_id: Storage.EnumOptional(.flags3, .build_id, .hexstring, String),
test_runner: Storage.FlagUnion(.flags3, .test_runner, TestRunner),
+ emit_directory: Storage.FlagOptional(.flags4, .emit_directory, GeneratedFileIndex),
+ generated_docs: Storage.FlagOptional(.flags4, .generated_docs, GeneratedFileIndex),
+ generated_asm: Storage.FlagOptional(.flags4, .generated_asm, GeneratedFileIndex),
+ generated_bin: Storage.FlagOptional(.flags4, .generated_bin, GeneratedFileIndex),
+ generated_pdb: Storage.FlagOptional(.flags4, .generated_pdb, GeneratedFileIndex),
+ generated_implib: Storage.FlagOptional(.flags4, .generated_implib, GeneratedFileIndex),
+ generated_llvm_bc: Storage.FlagOptional(.flags4, .generated_llvm_bc, GeneratedFileIndex),
+ generated_llvm_ir: Storage.FlagOptional(.flags4, .generated_llvm_ir, GeneratedFileIndex),
+ generated_h: Storage.FlagOptional(.flags4, .generated_h, GeneratedFileIndex),
+
pub const InstalledHeader = union(@This().Tag) {
file: File,
directory: Directory,
@@ -630,7 +652,7 @@ pub const Step = extern struct {
pub const File = struct {
flags: @This().Flags = .{},
- source: LazyPath,
+ source: LazyPath.Index,
dest_sub_path: String,
pub const Flags = packed struct(u32) {
@@ -641,7 +663,7 @@ pub const Step = extern struct {
pub const Directory = struct {
flags: @This().Flags,
- source: LazyPath,
+ source: LazyPath.Index,
dest_sub_path: String,
exclude_extensions: Storage.FlagLengthPrefixedList(.flags, .exclude_extensions, String),
include_extensions: Storage.FlagLengthPrefixedList(.flags, .include_extensions, String),
@@ -667,8 +689,8 @@ pub const Step = extern struct {
pub const Tag = enum(u2) { default, simple, server };
default: void,
- simple: LazyPath,
- server: LazyPath,
+ simple: LazyPath.Index,
+ server: LazyPath.Index,
};
pub const Entry = enum(u2) { default, disabled, enabled, symbol_name };
@@ -857,12 +879,37 @@ pub const Step = extern struct {
expect_errors: ExpectErrors.Tag,
linker_script: bool,
version_script: bool,
- _: u18 = 0,
+ emit_directory: bool,
+ generated_docs: bool,
+ generated_asm: bool,
+ generated_bin: bool,
+ generated_pdb: bool,
+ generated_implib: bool,
+ generated_llvm_bc: bool,
+ generated_llvm_ir: bool,
+ generated_h: bool,
+ _: u9 = 0,
};
pub fn isDynamicLibrary(compile: *const Compile) bool {
return compile.flags3.kind == .lib and compile.flags2.linkage == .dynamic;
}
+
+ pub fn isStaticLibrary(compile: *const Compile) bool {
+ return compile.flags3.kind == .lib and compile.flags2.linkage != .dynamic;
+ }
+
+ pub fn producesImplib(compile: *const Compile, c: *const Configuration) bool {
+ return isDll(compile, c);
+ }
+
+ pub fn isDll(compile: *const Compile, c: *const Configuration) bool {
+ return isDynamicLibrary(compile) and rootModuleTarget(compile, c).flags.os_tag == .windows;
+ }
+
+ pub fn rootModuleTarget(compile: *const Compile, c: *const Configuration) TargetQuery {
+ return compile.root_module.get(c).resolved_target.get(c).?.result.get(c);
+ }
};
pub const CheckFile = struct {
@@ -1001,32 +1048,49 @@ pub const MaxRss = enum(u32) {
}
};
-/// An index into `extra`, or `null`.
-pub const OptionalLazyPath = enum(u32) {
- none = maxInt(u32),
- _,
-
- pub fn unwrap(this: @This()) ?LazyPath {
- return switch (this) {
- .none => null,
- else => @enumFromInt(@intFromEnum(this)),
- };
- }
-};
-
-/// An index into `extra`.
-pub const LazyPath = enum(u32) {
- _,
+pub const LazyPath = union(@This().Tag) {
+ source_path: SourcePath,
+ relative: Relative,
+ generated: Generated,
pub const Tag = enum(u8) {
/// A source file path relative to build root.
source_path,
- generated,
+ /// Relative to the directory indicated in flags.
relative,
+ /// Path is available only after it is populated by its owning step.
+ generated,
+ };
+
+ pub const Flags = packed struct(u32) {
+ tag: Tag,
+ _: u24 = 0,
+ };
+
+ /// An index into `extra`.
+ pub const Index = enum(u32) {
+ _,
+
+ pub fn get(this: @This(), c: *const Configuration) LazyPath {
+ return extraData(c, LazyPath, @intFromEnum(this));
+ }
+ };
+
+ /// An index into `extra`, or `null`.
+ pub const OptionalIndex = enum(u32) {
+ none = maxInt(u32),
+ _,
+
+ pub fn unwrap(this: @This()) ?Index {
+ return switch (this) {
+ .none => null,
+ else => @enumFromInt(@intFromEnum(this)),
+ };
+ }
};
pub const SourcePath = struct {
- flags: Flags,
+ flags: @This().Flags,
owner: Package.Index,
sub_path: String,
@@ -1037,9 +1101,10 @@ pub const LazyPath = enum(u32) {
};
pub const Generated = struct {
- flags: Flags,
+ flags: @This().Flags = .{},
+ index: GeneratedFileIndex,
/// Applied after `up`.
- sub_path: String,
+ sub_path: String = .empty,
pub const Flags = packed struct(u32) {
tag: Tag = .generated,
@@ -1047,12 +1112,12 @@ pub const LazyPath = enum(u32) {
/// 0 means the generated file itself.
/// 1 means the directory of the generated file.
/// 2 means the parent of that directory, and so on.
- up: u24,
+ up: u24 = 0,
};
};
pub const Relative = struct {
- flags: Flags,
+ flags: @This().Flags,
sub_path: String,
pub const Flags = packed struct(u32) {
@@ -1063,6 +1128,26 @@ pub const LazyPath = enum(u32) {
};
};
+pub const GeneratedFileIndex = enum(u32) {
+ _,
+};
+
+pub const OptionalGeneratedFileIndex = enum(u32) {
+ none = maxInt(u32),
+ _,
+
+ pub fn init(i: ?GeneratedFileIndex) OptionalGeneratedFileIndex {
+ return @enumFromInt(@intFromEnum(i orelse return .none));
+ }
+
+ pub fn unwrap(this: @This()) ?GeneratedFileIndex {
+ return switch (this) {
+ .none => null,
+ else => @enumFromInt(@intFromEnum(this)),
+ };
+ }
+};
+
pub const Package = struct {
dep_prefix: String,
hash: String,
@@ -1071,9 +1156,15 @@ pub const Package = struct {
root = maxInt(u32),
_,
- pub fn depPrefixSlice(i: Index, c: *const Configuration) [:0]const u8 {
- if (i == .root) return "";
- return extraData(c, Package, @intFromEnum(i)).dep_prefix.slice(c);
+ /// Returns `null` for root package.
+ pub fn get(i: @This(), c: *const Configuration) ?Package {
+ if (i == .root) return null;
+ return extraData(c, Package, @intFromEnum(i));
+ }
+
+ pub fn depPrefixSlice(i: @This(), c: *const Configuration) [:0]const u8 {
+ const package = get(i, c) orelse return "";
+ return package.dep_prefix.slice(c);
}
};
};
@@ -1083,10 +1174,10 @@ pub const Module = struct {
flags2: Flags2,
import_table: ImportTable.Index,
owner: Package.Index,
- root_source_file: OptionalLazyPath,
+ root_source_file: LazyPath.OptionalIndex,
resolved_target: ResolvedTarget.OptionalIndex,
c_macros: Storage.FlagLengthPrefixedList(.flags, .c_macros, String),
- lib_paths: Storage.FlagLengthPrefixedList(.flags, .lib_paths, LazyPath),
+ lib_paths: Storage.FlagLengthPrefixedList(.flags, .lib_paths, LazyPath.Index),
export_symbol_names: Storage.FlagLengthPrefixedList(.flags, .export_symbol_names, String),
include_dirs: Storage.UnionList(.flags, .include_dirs, IncludeDir),
rpaths: Storage.UnionList(.flags, .rpaths, RPath),
@@ -1195,29 +1286,29 @@ pub const Module = struct {
};
pub const IncludeDir = union(enum(u3)) {
- path: LazyPath,
- path_system: LazyPath,
- path_after: LazyPath,
- framework_path: LazyPath,
- framework_path_system: LazyPath,
+ path: LazyPath.Index,
+ path_system: LazyPath.Index,
+ path_after: LazyPath.Index,
+ framework_path: LazyPath.Index,
+ framework_path_system: LazyPath.Index,
/// Always `Step.Tag.compile`.
other_step: Step.Index,
/// Always `Step.Tag.config_header`.
config_header_step: Step.Index,
- embed_path: LazyPath,
+ embed_path: LazyPath.Index,
};
pub const RPath = union(enum(u1)) {
- lazy_path: LazyPath,
+ lazy_path: LazyPath.Index,
special: String,
};
pub const LinkObject = union(enum(u3)) {
- static_path: LazyPath,
+ static_path: LazyPath.Index,
/// Always `Step.Tag.compile`.
other_step: Step.Index,
system_lib: SystemLib.Index,
- assembly_file: LazyPath,
+ assembly_file: LazyPath.Index,
c_source_file: CSourceFile.Index,
c_source_files: CSourceFiles.Index,
win32_resource_file: RcSourceFile.Index,
@@ -1376,6 +1467,10 @@ pub const SystemLib = struct {
pub const Index = enum(u32) {
_,
+
+ pub fn get(this: @This(), c: *const Configuration) SystemLib {
+ return extraData(c, SystemLib, @intFromEnum(this));
+ }
};
pub const UsePkgConfig = enum(u2) {
@@ -1405,12 +1500,16 @@ pub const SystemLib = struct {
pub const CSourceFiles = struct {
flags: Flags,
- root: LazyPath,
+ root: LazyPath.Index,
args: Storage.FlagList(.flags, .args_len, String),
sub_paths: Storage.LengthPrefixedList(String),
pub const Index = enum(u32) {
_,
+
+ pub fn get(this: @This(), c: *const Configuration) CSourceFiles {
+ return extraData(c, CSourceFiles, @intFromEnum(this));
+ }
};
pub const Flags = packed struct(u32) {
@@ -1422,11 +1521,15 @@ pub const CSourceFiles = struct {
pub const CSourceFile = struct {
flags: Flags,
- file: LazyPath,
+ file: LazyPath.Index,
args: Storage.FlagList(.flags, .args_len, String),
pub const Index = enum(u32) {
_,
+
+ pub fn get(this: @This(), c: *const Configuration) CSourceFile {
+ return extraData(c, CSourceFile, @intFromEnum(this));
+ }
};
pub const Flags = packed struct(u32) {
@@ -1438,12 +1541,16 @@ pub const CSourceFile = struct {
pub const RcSourceFile = struct {
flags: Flags,
- file: LazyPath,
+ file: LazyPath.Index,
args: Storage.FlagList(.flags, .args_len, String),
- include_paths: Storage.FlagLengthPrefixedList(.flags, .include_paths, LazyPath),
+ include_paths: Storage.FlagLengthPrefixedList(.flags, .include_paths, LazyPath.Index),
pub const Index = enum(u32) {
_,
+
+ pub fn get(this: @This(), c: *const Configuration) RcSourceFile {
+ return extraData(c, RcSourceFile, @intFromEnum(this));
+ }
};
pub const Flags = packed struct(u32) {
@@ -1472,6 +1579,18 @@ pub const OptionalCSourceLanguage = enum(u3) {
.assembly_with_preprocessor => .assembly_with_preprocessor,
};
}
+
+ pub fn get(this: @This()) ?std.Build.Module.CSourceLanguage {
+ return switch (this) {
+ .c => .c,
+ .cpp => .cpp,
+ .objective_c => .objective_c,
+ .objective_cpp => .objective_cpp,
+ .assembly => .assembly,
+ .assembly_with_preprocessor => .assembly_with_preprocessor,
+ .default => null,
+ };
+ }
};
pub const ResolvedTarget = struct {
@@ -1483,7 +1602,7 @@ pub const ResolvedTarget = struct {
pub const Index = enum(u32) {
_,
- pub fn get(this: @This(), c: *const Configuration) ?ResolvedTarget {
+ pub fn get(this: @This(), c: *const Configuration) ResolvedTarget {
return extraData(c, ResolvedTarget, @intFromEnum(this));
}
};
@@ -2006,13 +2125,27 @@ pub const Storage = enum {
return end - i;
}
- pub fn data(buffer: []const u32, i: *usize, comptime S: type) S {
- var result: S = undefined;
- const fields = @typeInfo(S).@"struct".fields;
- inline for (fields) |field| {
- @field(result, field.name) = dataField(buffer, i, &result, field.type);
+ pub fn data(buffer: []const u32, i: *usize, comptime T: type) T {
+ switch (@typeInfo(T)) {
+ .@"struct" => |info| {
+ var result: T = undefined;
+ inline for (info.fields) |field| {
+ @field(result, field.name) = dataField(buffer, i, &result, field.type);
+ }
+ return result;
+ },
+ .@"union" => |info| {
+ const flags: T.Flags = @bitCast(buffer[i.*]);
+ return switch (flags.tag) {
+ inline else => |comptime_tag| @unionInit(
+ T,
+ @tagName(comptime_tag),
+ data(buffer, i, info.fields[@intFromEnum(comptime_tag)].type),
+ ),
+ };
+ },
+ else => comptime unreachable,
}
- return result;
}
fn dataField(buffer: []const u32, i: *usize, container: anytype, comptime Field: type) Field {
@@ -2332,6 +2465,7 @@ pub fn load(arena: Allocator, reader: *Io.Reader) LoadError!Configuration {
.available_options = try arena.alloc(AvailableOption, header.available_options_len),
.extra = try arena.alloc(u32, header.extra_len),
.default_step = header.default_step,
+ .generated_files_len = header.generated_files_len,
};
var vecs = [_][]u8{
result.string_bytes,