commit 7e6be7ee6ee4223a4ef2b247002358cbfc714854 (tree)
parent f158262b30665b22c571373907a14f11eec809f7
Author: Andrew Kelley <andrew@ziglang.org>
Date: Fri, 8 May 2026 14:31:37 -0700
configurer: serialize Step.ObjCopy
Diffstat:
4 files changed, 120 insertions(+), 46 deletions(-)
diff --git a/lib/compiler/Maker/Step/ObjCopy.zig b/lib/compiler/Maker/Step/ObjCopy.zig
@@ -137,9 +137,7 @@ pub fn make(
}
const f = update.flags.section_flags;
- const default_flags: Configuration.Step.ObjCopy.SectionFlags = .{};
-
- if (f != default_flags) {
+ if (f != Configuration.Step.ObjCopy.SectionFlags.default) {
// trailing comma is allowed
argv.appendAssumeCapacity("--set-section-flags");
argv.appendAssumeCapacity(try allocPrint(arena, "{s}={s}{s}{s}{s}{s}{s}{s}{s}{s}", .{
diff --git a/lib/compiler/configurer.zig b/lib/compiler/configurer.zig
@@ -1065,7 +1065,52 @@ fn serialize(b: *std.Build, wc: *Configuration.Wip, writer: *Io.Writer) !void {
})));
},
.config_header => @panic("TODO"),
- .obj_copy => @panic("TODO"),
+ .obj_copy => e: {
+ const oc: *Step.ObjCopy = @fieldParentPtr("step", step);
+
+ const debug_basename: ?Configuration.String = if (oc.debug_file) |df|
+ df.basename.unwrap()
+ else
+ null;
+
+ const debug_file: ?Configuration.GeneratedFileIndex = if (oc.debug_file) |df|
+ df.output_file
+ else
+ null;
+
+ const add_sections = try arena.alloc(
+ Configuration.Step.ObjCopy.AddSection,
+ oc.add_sections.items.len,
+ );
+ for (add_sections, oc.add_sections.items) |*dest, src| dest.* = .{
+ .section_name = src.section_name,
+ .file_path = try s.addLazyPath(src.file_path),
+ };
+
+ break :e @enumFromInt(try wc.addExtra(@as(Configuration.Step.ObjCopy, .{
+ .flags = .{
+ .basename = oc.basename != .none,
+ .debug_file = debug_file != null,
+ .debug_basename = debug_basename != null,
+ .format = .init(oc.format),
+ .strip = oc.strip,
+ .compress_debug = oc.compress_debug,
+ .only_section = oc.only_section != .none,
+ .pad_to = oc.pad_to != null,
+ .add_section = add_sections.len != 0,
+ .update_section = oc.update_sections.items.len != 0,
+ },
+ .input_file = try s.addLazyPath(oc.input_file),
+ .output_file = oc.output_file,
+ .basename = .{ .value = oc.basename.unwrap() },
+ .debug_file = .{ .value = debug_file },
+ .debug_basename = .{ .value = debug_basename },
+ .only_section = .{ .value = oc.only_section.unwrap() },
+ .pad_to = .{ .value = oc.pad_to },
+ .add_section = .{ .slice = add_sections },
+ .update_section = .{ .slice = oc.update_sections.items },
+ })));
+ },
.options => e: {
const so: *Step.Options = @fieldParentPtr("step", step);
diff --git a/lib/std/Build/Configuration.zig b/lib/std/Build/Configuration.zig
@@ -1170,6 +1170,8 @@ pub const Step = extern struct {
merge: bool = false,
/// add SHF_STRINGS
strings: bool = false,
+
+ pub const default: @This() = .{};
};
pub const Flags = packed struct(u32) {
@@ -1776,6 +1778,11 @@ pub const Alignment = enum(u6) {
none = std.math.maxInt(u6),
_,
+ pub fn init(optional_alignment: ?std.mem.Alignment) @This() {
+ const a = optional_alignment orelse return .none;
+ return @enumFromInt(@intFromEnum(a));
+ }
+
pub fn toBytes(a: @This()) ?u64 {
return switch (a) {
.none => null,
diff --git a/lib/std/Build/Step/ObjCopy.zig b/lib/std/Build/Step/ObjCopy.zig
@@ -6,19 +6,18 @@ const Configuration = std.Build.Configuration;
step: Step,
input_file: std.Build.LazyPath,
-basename: ?[]const u8,
+basename: Configuration.OptionalString,
output_file: Configuration.GeneratedFileIndex,
-output_file_debug: Configuration.OptionalGeneratedFileIndex,
+debug_file: ?DebugFile,
format: ?Format,
-only_section: ?[]const u8,
+only_section: Configuration.OptionalString,
pad_to: ?u64,
strip: Strip,
compress_debug: bool,
-add_section: ?AddSection,
-set_section_alignment: ?SetSectionAlignment,
-set_section_flags: ?SetSectionFlags,
+add_sections: std.ArrayList(AddSection) = .empty,
+update_sections: std.ArrayList(Configuration.Step.ObjCopy.UpdateSection) = .empty,
pub const base_tag: Step.Tag = .obj_copy;
@@ -27,18 +26,13 @@ pub const Strip = Configuration.Step.ObjCopy.Strip;
pub const SectionFlags = Configuration.Step.ObjCopy.SectionFlags;
pub const AddSection = struct {
- section_name: []const u8,
+ section_name: Configuration.String,
file_path: std.Build.LazyPath,
};
-pub const SetSectionAlignment = struct {
- section_name: []const u8,
- alignment: u32,
-};
-
-pub const SetSectionFlags = struct {
- section_name: []const u8,
- flags: SectionFlags,
+pub const DebugFile = struct {
+ basename: Configuration.OptionalString,
+ output_file: Configuration.GeneratedFileIndex,
};
pub const Options = struct {
@@ -53,50 +47,80 @@ pub const Options = struct {
/// Put the stripped out debug sections in a separate file.
/// note: the `basename` is baked into the elf file to specify the link to the separate debug file.
/// see https://sourceware.org/gdb/onlinedocs/gdb/Separate-Debug-Files.html
- extract_to_separate_file: bool = false,
+ ///
+ /// Makes `getOutputSeparatedDebug` return non-null.
+ separate_debug_file: ?SeparateDebugFile = null,
- add_section: ?AddSection = null,
- set_section_alignment: ?SetSectionAlignment = null,
- set_section_flags: ?SetSectionFlags = null,
+ pub const SeparateDebugFile = struct {
+ basename: ?[]const u8,
+ };
};
-pub fn create(
- owner: *std.Build,
- input_file: std.Build.LazyPath,
- options: Options,
-) *ObjCopy {
+pub fn create(owner: *std.Build, input_file: std.Build.LazyPath, options: Options) *ObjCopy {
const graph = owner.graph;
- const obj_copy = graph.create(ObjCopy);
- obj_copy.* = .{
+ const wc = &graph.wip_configuration;
+ const oc = graph.create(ObjCopy);
+ oc.* = .{
.step = .init(.{
.tag = base_tag,
.name = owner.fmt("objcopy {f}", .{input_file.fmt(graph)}),
.owner = owner,
}),
.input_file = input_file,
- .basename = options.basename,
- .output_file = graph.addGeneratedFile(&obj_copy.step),
- .output_file_debug = if (options.strip != .none and options.extract_to_separate_file)
- .init(graph.addGeneratedFile(&obj_copy.step))
- else
- .none,
+ .basename = if (options.basename) |s| .init(wc.addString(s) catch @panic("OOM")) else .none,
+ .output_file = graph.addGeneratedFile(&oc.step),
+ .debug_file = if (options.separate_debug_file) |df| .{
+ .basename = if (df.basename) |s| .init(wc.addString(s) catch @panic("OOM")) else .none,
+ .output_file = graph.addGeneratedFile(&oc.step),
+ } else null,
.format = options.format,
- .only_section = options.only_section,
+ .only_section = if (options.only_section) |s| .init(wc.addString(s) catch @panic("OOM")) else .none,
.pad_to = options.pad_to,
.strip = options.strip,
.compress_debug = options.compress_debug,
- .add_section = options.add_section,
- .set_section_alignment = options.set_section_alignment,
- .set_section_flags = options.set_section_flags,
};
- input_file.addStepDependencies(&obj_copy.step);
- return obj_copy;
+ input_file.addStepDependencies(&oc.step);
+ return oc;
+}
+
+pub const UpdateSectionOptions = struct {
+ alignment: ?std.mem.Alignment = null,
+ flags: SectionFlags = .default,
+};
+
+pub fn updateSection(oc: *ObjCopy, section_name: []const u8, options: UpdateSectionOptions) void {
+ const graph = oc.owner.graph;
+ const arena = graph.arena;
+ const wc = &graph.wip_configuration;
+ oc.update_sections.append(arena, .{
+ .flags = .{
+ .section_flags = options.flags,
+ .alignment = .init(options.alignment),
+ },
+ .section_name = wc.addString(section_name) catch @panic("OOM"),
+ }) catch @panic("OOM");
+}
+
+pub const AddSectionOptions = struct {
+ file_path: std.Build.LazyPath,
+};
+
+pub fn addSection(oc: *ObjCopy, section_name: []const u8, options: AddSectionOptions) void {
+ const graph = oc.owner.graph;
+ const arena = graph.arena;
+ const wc = &graph.wip_configuration;
+ oc.add_sections.append(arena, .{
+ .section_name = wc.addString(section_name) catch @panic("OOM"),
+ .file_path = options.file_path,
+ }) catch @panic("OOM");
+ options.file_path.addStepDependencies(&oc.step);
}
-pub fn getOutput(obj_copy: *const ObjCopy) std.Build.LazyPath {
- return .{ .generated = .{ .index = obj_copy.output_file } };
+pub fn getOutput(oc: *const ObjCopy) std.Build.LazyPath {
+ return .{ .generated = .{ .index = oc.output_file } };
}
-pub fn getOutputSeparatedDebug(obj_copy: *const ObjCopy) ?std.Build.LazyPath {
- return if (obj_copy.output_file_debug.unwrap()) |index| .{ .generated = .{ .index = index } } else null;
+pub fn getOutputSeparatedDebug(oc: *const ObjCopy) ?std.Build.LazyPath {
+ const df = oc.debug_file orelse return null;
+ return .{ .generated = .{ .index = df.output_file } };
}