| ... | @@ -17,22 +17,40 @@ pub const base_id: Step.Id = .objcopy; | ... | @@ -17,22 +17,40 @@ pub const base_id: Step.Id = .objcopy; |
| 17 | pub const RawFormat = enum { | 17 | pub const RawFormat = enum { |
| 18 | bin, | 18 | bin, |
| 19 | hex, | 19 | hex, |
| | 20 | elf, |
| | 21 | }; |
| | 22 | |
| | 23 | pub const Strip = enum { |
| | 24 | none, |
| | 25 | debug, |
| | 26 | debug_and_symbols, |
| 20 | }; | 27 | }; |
| 21 | | 28 | |
| 22 | step: Step, | 29 | step: Step, |
| 23 | input_file: std.Build.LazyPath, | 30 | input_file: std.Build.LazyPath, |
| 24 | basename: []const u8, | 31 | basename: []const u8, |
| 25 | output_file: std.Build.GeneratedFile, | 32 | output_file: std.Build.GeneratedFile, |
| | 33 | output_file_debug: ?std.Build.GeneratedFile, |
| 26 | | 34 | |
| 27 | format: ?RawFormat, | 35 | format: ?RawFormat, |
| 28 | only_section: ?[]const u8, | 36 | only_section: ?[]const u8, |
| 29 | pad_to: ?u64, | 37 | pad_to: ?u64, |
| | 38 | strip: Strip, |
| | 39 | compress_debug: bool, |
| 30 | | 40 | |
| 31 | pub const Options = struct { | 41 | pub const Options = struct { |
| 32 | basename: ?[]const u8 = null, | 42 | basename: ?[]const u8 = null, |
| 33 | format: ?RawFormat = null, | 43 | format: ?RawFormat = null, |
| 34 | only_section: ?[]const u8 = null, | 44 | only_section: ?[]const u8 = null, |
| 35 | pad_to: ?u64 = null, | 45 | pad_to: ?u64 = null, |
| | 46 | |
| | 47 | compress_debug: bool = false, |
| | 48 | strip: Strip = .none, |
| | 49 | |
| | 50 | /// Put the stripped out debug sections in a separate file. |
| | 51 | /// note: the `basename` is baked into the elf file to specify the link to the separate debug file. |
| | 52 | /// see https://sourceware.org/gdb/onlinedocs/gdb/Separate-Debug-Files.html |
| | 53 | extract_to_separate_file: bool = false, |
| 36 | }; | 54 | }; |
| 37 | | 55 | |
| 38 | pub fn create( | 56 | pub fn create( |
| ... | @@ -51,10 +69,12 @@ pub fn create( | ... | @@ -51,10 +69,12 @@ pub fn create( |
| 51 | .input_file = input_file, | 69 | .input_file = input_file, |
| 52 | .basename = options.basename orelse input_file.getDisplayName(), | 70 | .basename = options.basename orelse input_file.getDisplayName(), |
| 53 | .output_file = std.Build.GeneratedFile{ .step = &self.step }, | 71 | .output_file = std.Build.GeneratedFile{ .step = &self.step }, |
| 54 | | 72 | .output_file_debug = if (options.strip != .none and options.extract_to_separate_file) std.Build.GeneratedFile{ .step = &self.step } else null, |
| 55 | .format = options.format, | 73 | .format = options.format, |
| 56 | .only_section = options.only_section, | 74 | .only_section = options.only_section, |
| 57 | .pad_to = options.pad_to, | 75 | .pad_to = options.pad_to, |
| | 76 | .strip = options.strip, |
| | 77 | .compress_debug = options.compress_debug, |
| 58 | }; | 78 | }; |
| 59 | input_file.addStepDependencies(&self.step); | 79 | input_file.addStepDependencies(&self.step); |
| 60 | return self; | 80 | return self; |
| ... | @@ -66,6 +86,9 @@ pub const getOutputSource = getOutput; | ... | @@ -66,6 +86,9 @@ pub const getOutputSource = getOutput; |
| 66 | pub fn getOutput(self: *const ObjCopy) std.Build.LazyPath { | 86 | pub fn getOutput(self: *const ObjCopy) std.Build.LazyPath { |
| 67 | return .{ .generated = &self.output_file }; | 87 | return .{ .generated = &self.output_file }; |
| 68 | } | 88 | } |
| | 89 | pub fn getOutputSeparatedDebug(self: *const ObjCopy) ?std.Build.LazyPath { |
| | 90 | return if (self.output_file_debug) |*file| .{ .generated = file } else null; |
| | 91 | } |
| 69 | | 92 | |
| 70 | fn make(step: *Step, prog_node: *std.Progress.Node) !void { | 93 | fn make(step: *Step, prog_node: *std.Progress.Node) !void { |
| 71 | const b = step.owner; | 94 | const b = step.owner; |
| ... | @@ -83,6 +106,9 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { | ... | @@ -83,6 +106,9 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { |
| 83 | man.hash.addOptionalBytes(self.only_section); | 106 | man.hash.addOptionalBytes(self.only_section); |
| 84 | man.hash.addOptional(self.pad_to); | 107 | man.hash.addOptional(self.pad_to); |
| 85 | man.hash.addOptional(self.format); | 108 | man.hash.addOptional(self.format); |
| | 109 | man.hash.add(self.compress_debug); |
| | 110 | man.hash.add(self.strip); |
| | 111 | man.hash.add(self.output_file_debug != null); |
| 86 | | 112 | |
| 87 | if (try step.cacheHit(&man)) { | 113 | if (try step.cacheHit(&man)) { |
| 88 | // Cache hit, skip subprocess execution. | 114 | // Cache hit, skip subprocess execution. |
| ... | @@ -90,12 +116,18 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { | ... | @@ -90,12 +116,18 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { |
| 90 | self.output_file.path = try b.cache_root.join(b.allocator, &.{ | 116 | self.output_file.path = try b.cache_root.join(b.allocator, &.{ |
| 91 | "o", &digest, self.basename, | 117 | "o", &digest, self.basename, |
| 92 | }); | 118 | }); |
| | 119 | if (self.output_file_debug) |*file| { |
| | 120 | file.path = try b.cache_root.join(b.allocator, &.{ |
| | 121 | "o", &digest, b.fmt("{s}.debug", .{self.basename}), |
| | 122 | }); |
| | 123 | } |
| 93 | return; | 124 | return; |
| 94 | } | 125 | } |
| 95 | | 126 | |
| 96 | const digest = man.final(); | 127 | const digest = man.final(); |
| 97 | const full_dest_path = try b.cache_root.join(b.allocator, &.{ "o", &digest, self.basename }); | | |
| 98 | const cache_path = "o" ++ fs.path.sep_str ++ digest; | 128 | const cache_path = "o" ++ fs.path.sep_str ++ digest; |
| | 129 | const full_dest_path = try b.cache_root.join(b.allocator, &.{ cache_path, self.basename }); |
| | 130 | const full_dest_path_debug = try b.cache_root.join(b.allocator, &.{ cache_path, b.fmt("{s}.debug", .{self.basename}) }); |
| 99 | b.cache_root.handle.makePath(cache_path) catch |err| { | 131 | b.cache_root.handle.makePath(cache_path) catch |err| { |
| 100 | return step.fail("unable to make path {s}: {s}", .{ cache_path, @errorName(err) }); | 132 | return step.fail("unable to make path {s}: {s}", .{ cache_path, @errorName(err) }); |
| 101 | }; | 133 | }; |
| ... | @@ -106,13 +138,25 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { | ... | @@ -106,13 +138,25 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { |
| 106 | if (self.only_section) |only_section| { | 138 | if (self.only_section) |only_section| { |
| 107 | try argv.appendSlice(&.{ "-j", only_section }); | 139 | try argv.appendSlice(&.{ "-j", only_section }); |
| 108 | } | 140 | } |
| | 141 | switch (self.strip) { |
| | 142 | .none => {}, |
| | 143 | .debug => try argv.appendSlice(&.{"--strip-debug"}), |
| | 144 | .debug_and_symbols => try argv.appendSlice(&.{"--strip-all"}), |
| | 145 | } |
| 109 | if (self.pad_to) |pad_to| { | 146 | if (self.pad_to) |pad_to| { |
| 110 | try argv.appendSlice(&.{ "--pad-to", b.fmt("{d}", .{pad_to}) }); | 147 | try argv.appendSlice(&.{ "--pad-to", b.fmt("{d}", .{pad_to}) }); |
| 111 | } | 148 | } |
| 112 | if (self.format) |format| switch (format) { | 149 | if (self.format) |format| switch (format) { |
| 113 | .bin => try argv.appendSlice(&.{ "-O", "binary" }), | 150 | .bin => try argv.appendSlice(&.{ "-O", "binary" }), |
| 114 | .hex => try argv.appendSlice(&.{ "-O", "hex" }), | 151 | .hex => try argv.appendSlice(&.{ "-O", "hex" }), |
| | 152 | .elf => try argv.appendSlice(&.{ "-O", "elf" }), |
| 115 | }; | 153 | }; |
| | 154 | if (self.compress_debug) { |
| | 155 | try argv.appendSlice(&.{"--compress-debug-sections"}); |
| | 156 | } |
| | 157 | if (self.output_file_debug != null) { |
| | 158 | try argv.appendSlice(&.{b.fmt("--extract-to={s}", .{full_dest_path_debug})}); |
| | 159 | } |
| 116 | | 160 | |
| 117 | try argv.appendSlice(&.{ full_src_path, full_dest_path }); | 161 | try argv.appendSlice(&.{ full_src_path, full_dest_path }); |
| 118 | | 162 | |
| ... | @@ -120,5 +164,6 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { | ... | @@ -120,5 +164,6 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { |
| 120 | _ = try step.evalZigProcess(argv.items, prog_node); | 164 | _ = try step.evalZigProcess(argv.items, prog_node); |
| 121 | | 165 | |
| 122 | self.output_file.path = full_dest_path; | 166 | self.output_file.path = full_dest_path; |
| | 167 | if (self.output_file_debug) |*file| file.path = full_dest_path_debug; |
| 123 | try man.writeManifest(); | 168 | try man.writeManifest(); |
| 124 | } | 169 | } |