| ... | @@ -6,19 +6,18 @@ const Configuration = std.Build.Configuration; | ... | @@ -6,19 +6,18 @@ const Configuration = std.Build.Configuration; |
| 6 | | 6 | |
| 7 | step: Step, | 7 | step: Step, |
| 8 | input_file: std.Build.LazyPath, | 8 | input_file: std.Build.LazyPath, |
| 9 | basename: ?[]const u8, | 9 | basename: Configuration.OptionalString, |
| 10 | output_file: Configuration.GeneratedFileIndex, | 10 | output_file: Configuration.GeneratedFileIndex, |
| 11 | output_file_debug: Configuration.OptionalGeneratedFileIndex, | 11 | debug_file: ?DebugFile, |
| 12 | | 12 | |
| 13 | format: ?Format, | 13 | format: ?Format, |
| 14 | only_section: ?[]const u8, | 14 | only_section: Configuration.OptionalString, |
| 15 | pad_to: ?u64, | 15 | pad_to: ?u64, |
| 16 | strip: Strip, | 16 | strip: Strip, |
| 17 | compress_debug: bool, | 17 | compress_debug: bool, |
| 18 | | 18 | |
| 19 | add_section: ?AddSection, | 19 | add_sections: std.ArrayList(AddSection) = .empty, |
| 20 | set_section_alignment: ?SetSectionAlignment, | 20 | update_sections: std.ArrayList(Configuration.Step.ObjCopy.UpdateSection) = .empty, |
| 21 | set_section_flags: ?SetSectionFlags, | | |
| 22 | | 21 | |
| 23 | pub const base_tag: Step.Tag = .obj_copy; | 22 | pub const base_tag: Step.Tag = .obj_copy; |
| 24 | | 23 | |
| ... | @@ -27,18 +26,13 @@ pub const Strip = Configuration.Step.ObjCopy.Strip; | ... | @@ -27,18 +26,13 @@ pub const Strip = Configuration.Step.ObjCopy.Strip; |
| 27 | pub const SectionFlags = Configuration.Step.ObjCopy.SectionFlags; | 26 | pub const SectionFlags = Configuration.Step.ObjCopy.SectionFlags; |
| 28 | | 27 | |
| 29 | pub const AddSection = struct { | 28 | pub const AddSection = struct { |
| 30 | section_name: []const u8, | 29 | section_name: Configuration.String, |
| 31 | file_path: std.Build.LazyPath, | 30 | file_path: std.Build.LazyPath, |
| 32 | }; | 31 | }; |
| 33 | | 32 | |
| 34 | pub const SetSectionAlignment = struct { | 33 | pub const DebugFile = struct { |
| 35 | section_name: []const u8, | 34 | basename: Configuration.OptionalString, |
| 36 | alignment: u32, | 35 | output_file: Configuration.GeneratedFileIndex, |
| 37 | }; | | |
| 38 | | | |
| 39 | pub const SetSectionFlags = struct { | | |
| 40 | section_name: []const u8, | | |
| 41 | flags: SectionFlags, | | |
| 42 | }; | 36 | }; |
| 43 | | 37 | |
| 44 | pub const Options = struct { | 38 | pub const Options = struct { |
| ... | @@ -53,50 +47,80 @@ pub const Options = struct { | ... | @@ -53,50 +47,80 @@ pub const Options = struct { |
| 53 | /// Put the stripped out debug sections in a separate file. | 47 | /// Put the stripped out debug sections in a separate file. |
| 54 | /// note: the `basename` is baked into the elf file to specify the link to the separate debug file. | 48 | /// note: the `basename` is baked into the elf file to specify the link to the separate debug file. |
| 55 | /// see https://sourceware.org/gdb/onlinedocs/gdb/Separate-Debug-Files.html | 49 | /// 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, |
| 57 | | 53 | |
| 58 | add_section: ?AddSection = null, | 54 | pub const SeparateDebugFile = struct { |
| 59 | set_section_alignment: ?SetSectionAlignment = null, | 55 | basename: ?[]const u8, |
| 60 | set_section_flags: ?SetSectionFlags = null, | 56 | }; |
| 61 | }; | 57 | }; |
| 62 | | 58 | |
| 63 | pub fn create( | 59 | pub fn create(owner: *std.Build, input_file: std.Build.LazyPath, options: Options) *ObjCopy { |
| 64 | owner: *std.Build, | | |
| 65 | input_file: std.Build.LazyPath, | | |
| 66 | options: Options, | | |
| 67 | ) *ObjCopy { | | |
| 68 | const graph = owner.graph; | 60 | const graph = owner.graph; |
| 69 | const obj_copy = graph.create(ObjCopy); | 61 | const wc = &graph.wip_configuration; |
| 70 | obj_copy.* = .{ | 62 | const oc = graph.create(ObjCopy); |
| | 63 | oc.* = .{ |
| 71 | .step = .init(.{ | 64 | .step = .init(.{ |
| 72 | .tag = base_tag, | 65 | .tag = base_tag, |
| 73 | .name = owner.fmt("objcopy {f}", .{input_file.fmt(graph)}), | 66 | .name = owner.fmt("objcopy {f}", .{input_file.fmt(graph)}), |
| 74 | .owner = owner, | 67 | .owner = owner, |
| 75 | }), | 68 | }), |
| 76 | .input_file = input_file, | 69 | .input_file = input_file, |
| 77 | .basename = options.basename, | 70 | .basename = if (options.basename) |s| .init(wc.addString(s) catch @panic("OOM")) else .none, |
| 78 | .output_file = graph.addGeneratedFile(&obj_copy.step), | 71 | .output_file = graph.addGeneratedFile(&oc.step), |
| 79 | .output_file_debug = if (options.strip != .none and options.extract_to_separate_file) | 72 | .debug_file = if (options.separate_debug_file) |df| .{ |
| 80 | .init(graph.addGeneratedFile(&obj_copy.step)) | 73 | .basename = if (df.basename) |s| .init(wc.addString(s) catch @panic("OOM")) else .none, |
| 81 | else | 74 | .output_file = graph.addGeneratedFile(&oc.step), |
| 82 | .none, | 75 | } else null, |
| 83 | .format = options.format, | 76 | .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, |
| 85 | .pad_to = options.pad_to, | 78 | .pad_to = options.pad_to, |
| 86 | .strip = options.strip, | 79 | .strip = options.strip, |
| 87 | .compress_debug = options.compress_debug, | 80 | .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, | | |
| 91 | }; | 81 | }; |
| 92 | input_file.addStepDependencies(&obj_copy.step); | 82 | input_file.addStepDependencies(&oc.step); |
| 93 | return obj_copy; | 83 | return oc; |
| | 84 | } |
| | 85 | |
| | 86 | pub const UpdateSectionOptions = struct { |
| | 87 | alignment: ?std.mem.Alignment = null, |
| | 88 | flags: SectionFlags = .default, |
| | 89 | }; |
| | 90 | |
| | 91 | pub 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 | |
| | 104 | pub const AddSectionOptions = struct { |
| | 105 | file_path: std.Build.LazyPath, |
| | 106 | }; |
| | 107 | |
| | 108 | pub 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); |
| 94 | } | 117 | } |
| 95 | | 118 | |
| 96 | pub fn getOutput(obj_copy: *const ObjCopy) std.Build.LazyPath { | 119 | pub fn getOutput(oc: *const ObjCopy) std.Build.LazyPath { |
| 97 | return .{ .generated = .{ .index = obj_copy.output_file } }; | 120 | return .{ .generated = .{ .index = oc.output_file } }; |
| 98 | } | 121 | } |
| 99 | | 122 | |
| 100 | pub fn getOutputSeparatedDebug(obj_copy: *const ObjCopy) ?std.Build.LazyPath { | 123 | pub fn getOutputSeparatedDebug(oc: *const ObjCopy) ?std.Build.LazyPath { |
| 101 | return if (obj_copy.output_file_debug.unwrap()) |index| .{ .generated = .{ .index = index } } else null; | 124 | const df = oc.debug_file orelse return null; |
| | 125 | return .{ .generated = .{ .index = df.output_file } }; |
| 102 | } | 126 | } |