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.
This commit is contained in:
Andrew Kelley
2026-03-09 22:09:12 -07:00
parent 9c1219f96f
commit e5c7c510ae
15 changed files with 727 additions and 459 deletions
+12
View File
@@ -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
+104
View File
@@ -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 }),
};
}
+3
View File
@@ -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,
+254 -104
View File
@@ -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 = 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),
}));
}
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 }));
}
if (c_source_files.flags.lang != .default)
(try zig_args.addManyAsArray(gpa, 2)).* = .{ "-x", "none" };
if (c_source_files.language != null) {
try zig_args.append(gpa, "-x");
try zig_args.append(gpa, "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,";
@@ -1361,3 +1383,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 });
}
+27 -5
View File
@@ -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),
});
}
+19 -13
View File
@@ -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),
} },
+2 -139
View File
@@ -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.
+26 -77
View File
@@ -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,
@@ -710,13 +700,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.
@@ -789,46 +778,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;
+9 -8
View File
@@ -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);
+14 -7
View File
@@ -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 {
+9 -6
View File
@@ -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 {
+26 -17
View File
@@ -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
+11 -8
View File
@@ -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
+10 -8
View File
@@ -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 {
+201 -67
View File
@@ -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,