authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-05-08 14:31:37-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-05-25 18:54:35-07:00
log7e6be7ee6ee4223a4ef2b247002358cbfc714854
tree4642a619dff8152d770a372177eb5a6f4bbeec90
parentf158262b30665b22c571373907a14f11eec809f7

configurer: serialize Step.ObjCopy


4 files changed, 120 insertions(+), 46 deletions(-)

lib/compiler/Maker/Step/ObjCopy.zig+1-3
......@@ -137,9 +137,7 @@ pub fn make(
137137 }
138138
139139 const f = update.flags.section_flags;
140 const default_flags: Configuration.Step.ObjCopy.SectionFlags = .{};
141
142 if (f != default_flags) {
140 if (f != Configuration.Step.ObjCopy.SectionFlags.default) {
143141 // trailing comma is allowed
144142 argv.appendAssumeCapacity("--set-section-flags");
145143 argv.appendAssumeCapacity(try allocPrint(arena, "{s}={s}{s}{s}{s}{s}{s}{s}{s}{s}", .{
lib/compiler/configurer.zig+46-1
......@@ -1065,7 +1065,52 @@ fn serialize(b: *std.Build, wc: *Configuration.Wip, writer: *Io.Writer) !void {
10651065 })));
10661066 },
10671067 .config_header => @panic("TODO"),
1068 .obj_copy => @panic("TODO"),
1068 .obj_copy => e: {
1069 const oc: *Step.ObjCopy = @fieldParentPtr("step", step);
1070
1071 const debug_basename: ?Configuration.String = if (oc.debug_file) |df|
1072 df.basename.unwrap()
1073 else
1074 null;
1075
1076 const debug_file: ?Configuration.GeneratedFileIndex = if (oc.debug_file) |df|
1077 df.output_file
1078 else
1079 null;
1080
1081 const add_sections = try arena.alloc(
1082 Configuration.Step.ObjCopy.AddSection,
1083 oc.add_sections.items.len,
1084 );
1085 for (add_sections, oc.add_sections.items) |*dest, src| dest.* = .{
1086 .section_name = src.section_name,
1087 .file_path = try s.addLazyPath(src.file_path),
1088 };
1089
1090 break :e @enumFromInt(try wc.addExtra(@as(Configuration.Step.ObjCopy, .{
1091 .flags = .{
1092 .basename = oc.basename != .none,
1093 .debug_file = debug_file != null,
1094 .debug_basename = debug_basename != null,
1095 .format = .init(oc.format),
1096 .strip = oc.strip,
1097 .compress_debug = oc.compress_debug,
1098 .only_section = oc.only_section != .none,
1099 .pad_to = oc.pad_to != null,
1100 .add_section = add_sections.len != 0,
1101 .update_section = oc.update_sections.items.len != 0,
1102 },
1103 .input_file = try s.addLazyPath(oc.input_file),
1104 .output_file = oc.output_file,
1105 .basename = .{ .value = oc.basename.unwrap() },
1106 .debug_file = .{ .value = debug_file },
1107 .debug_basename = .{ .value = debug_basename },
1108 .only_section = .{ .value = oc.only_section.unwrap() },
1109 .pad_to = .{ .value = oc.pad_to },
1110 .add_section = .{ .slice = add_sections },
1111 .update_section = .{ .slice = oc.update_sections.items },
1112 })));
1113 },
10691114 .options => e: {
10701115 const so: *Step.Options = @fieldParentPtr("step", step);
10711116
lib/std/Build/Configuration.zig+7
......@@ -1170,6 +1170,8 @@ pub const Step = extern struct {
11701170 merge: bool = false,
11711171 /// add SHF_STRINGS
11721172 strings: bool = false,
1173
1174 pub const default: @This() = .{};
11731175 };
11741176
11751177 pub const Flags = packed struct(u32) {
......@@ -1776,6 +1778,11 @@ pub const Alignment = enum(u6) {
17761778 none = std.math.maxInt(u6),
17771779 _,
17781780
1781 pub fn init(optional_alignment: ?std.mem.Alignment) @This() {
1782 const a = optional_alignment orelse return .none;
1783 return @enumFromInt(@intFromEnum(a));
1784 }
1785
17791786 pub fn toBytes(a: @This()) ?u64 {
17801787 return switch (a) {
17811788 .none => null,
lib/std/Build/Step/ObjCopy.zig+66-42
......@@ -6,19 +6,18 @@ const Configuration = std.Build.Configuration;
66
77step: Step,
88input_file: std.Build.LazyPath,
9basename: ?[]const u8,
9basename: Configuration.OptionalString,
1010output_file: Configuration.GeneratedFileIndex,
11output_file_debug: Configuration.OptionalGeneratedFileIndex,
11debug_file: ?DebugFile,
1212
1313format: ?Format,
14only_section: ?[]const u8,
14only_section: Configuration.OptionalString,
1515pad_to: ?u64,
1616strip: Strip,
1717compress_debug: bool,
1818
19add_section: ?AddSection,
20set_section_alignment: ?SetSectionAlignment,
21set_section_flags: ?SetSectionFlags,
19add_sections: std.ArrayList(AddSection) = .empty,
20update_sections: std.ArrayList(Configuration.Step.ObjCopy.UpdateSection) = .empty,
2221
2322pub const base_tag: Step.Tag = .obj_copy;
2423
......@@ -27,18 +26,13 @@ pub const Strip = Configuration.Step.ObjCopy.Strip;
2726pub const SectionFlags = Configuration.Step.ObjCopy.SectionFlags;
2827
2928pub const AddSection = struct {
30 section_name: []const u8,
29 section_name: Configuration.String,
3130 file_path: std.Build.LazyPath,
3231};
3332
34pub const SetSectionAlignment = struct {
35 section_name: []const u8,
36 alignment: u32,
37};
38
39pub const SetSectionFlags = struct {
40 section_name: []const u8,
41 flags: SectionFlags,
33pub const DebugFile = struct {
34 basename: Configuration.OptionalString,
35 output_file: Configuration.GeneratedFileIndex,
4236};
4337
4438pub const Options = struct {
......@@ -53,50 +47,80 @@ pub const Options = struct {
5347 /// Put the stripped out debug sections in a separate file.
5448 /// note: the `basename` is baked into the elf file to specify the link to the separate debug file.
5549 /// see https://sourceware.org/gdb/onlinedocs/gdb/Separate-Debug-Files.html
56 extract_to_separate_file: bool = false,
50 ///
51 /// Makes `getOutputSeparatedDebug` return non-null.
52 separate_debug_file: ?SeparateDebugFile = null,
5753
58 add_section: ?AddSection = null,
59 set_section_alignment: ?SetSectionAlignment = null,
60 set_section_flags: ?SetSectionFlags = null,
54 pub const SeparateDebugFile = struct {
55 basename: ?[]const u8,
56 };
6157};
6258
63pub fn create(
64 owner: *std.Build,
65 input_file: std.Build.LazyPath,
66 options: Options,
67) *ObjCopy {
59pub fn create(owner: *std.Build, input_file: std.Build.LazyPath, options: Options) *ObjCopy {
6860 const graph = owner.graph;
69 const obj_copy = graph.create(ObjCopy);
70 obj_copy.* = .{
61 const wc = &graph.wip_configuration;
62 const oc = graph.create(ObjCopy);
63 oc.* = .{
7164 .step = .init(.{
7265 .tag = base_tag,
7366 .name = owner.fmt("objcopy {f}", .{input_file.fmt(graph)}),
7467 .owner = owner,
7568 }),
7669 .input_file = input_file,
77 .basename = options.basename,
78 .output_file = graph.addGeneratedFile(&obj_copy.step),
79 .output_file_debug = if (options.strip != .none and options.extract_to_separate_file)
80 .init(graph.addGeneratedFile(&obj_copy.step))
81 else
82 .none,
70 .basename = if (options.basename) |s| .init(wc.addString(s) catch @panic("OOM")) else .none,
71 .output_file = graph.addGeneratedFile(&oc.step),
72 .debug_file = if (options.separate_debug_file) |df| .{
73 .basename = if (df.basename) |s| .init(wc.addString(s) catch @panic("OOM")) else .none,
74 .output_file = graph.addGeneratedFile(&oc.step),
75 } else null,
8376 .format = options.format,
84 .only_section = options.only_section,
77 .only_section = if (options.only_section) |s| .init(wc.addString(s) catch @panic("OOM")) else .none,
8578 .pad_to = options.pad_to,
8679 .strip = options.strip,
8780 .compress_debug = options.compress_debug,
88 .add_section = options.add_section,
89 .set_section_alignment = options.set_section_alignment,
90 .set_section_flags = options.set_section_flags,
9181 };
92 input_file.addStepDependencies(&obj_copy.step);
93 return obj_copy;
82 input_file.addStepDependencies(&oc.step);
83 return oc;
84}
85
86pub const UpdateSectionOptions = struct {
87 alignment: ?std.mem.Alignment = null,
88 flags: SectionFlags = .default,
89};
90
91pub fn updateSection(oc: *ObjCopy, section_name: []const u8, options: UpdateSectionOptions) void {
92 const graph = oc.owner.graph;
93 const arena = graph.arena;
94 const wc = &graph.wip_configuration;
95 oc.update_sections.append(arena, .{
96 .flags = .{
97 .section_flags = options.flags,
98 .alignment = .init(options.alignment),
99 },
100 .section_name = wc.addString(section_name) catch @panic("OOM"),
101 }) catch @panic("OOM");
102}
103
104pub const AddSectionOptions = struct {
105 file_path: std.Build.LazyPath,
106};
107
108pub fn addSection(oc: *ObjCopy, section_name: []const u8, options: AddSectionOptions) void {
109 const graph = oc.owner.graph;
110 const arena = graph.arena;
111 const wc = &graph.wip_configuration;
112 oc.add_sections.append(arena, .{
113 .section_name = wc.addString(section_name) catch @panic("OOM"),
114 .file_path = options.file_path,
115 }) catch @panic("OOM");
116 options.file_path.addStepDependencies(&oc.step);
94117}
95118
96pub fn getOutput(obj_copy: *const ObjCopy) std.Build.LazyPath {
97 return .{ .generated = .{ .index = obj_copy.output_file } };
119pub fn getOutput(oc: *const ObjCopy) std.Build.LazyPath {
120 return .{ .generated = .{ .index = oc.output_file } };
98121}
99122
100pub fn getOutputSeparatedDebug(obj_copy: *const ObjCopy) ?std.Build.LazyPath {
101 return if (obj_copy.output_file_debug.unwrap()) |index| .{ .generated = .{ .index = index } } else null;
123pub fn getOutputSeparatedDebug(oc: *const ObjCopy) ?std.Build.LazyPath {
124 const df = oc.debug_file orelse return null;
125 return .{ .generated = .{ .index = df.output_file } };
102126}