| ... | ... | @@ -17,22 +17,40 @@ pub const base_id: Step.Id = .objcopy; |
| 17 | 17 | pub const RawFormat = enum { |
| 18 | 18 | bin, |
| 19 | 19 | hex, |
| 20 | elf, |
| 21 | }; |
| 22 | |
| 23 | pub const Strip = enum { |
| 24 | none, |
| 25 | debug, |
| 26 | debug_and_symbols, |
| 20 | 27 | }; |
| 21 | 28 | |
| 22 | 29 | step: Step, |
| 23 | 30 | input_file: std.Build.LazyPath, |
| 24 | 31 | basename: []const u8, |
| 25 | 32 | output_file: std.Build.GeneratedFile, |
| 33 | output_file_debug: ?std.Build.GeneratedFile, |
| 26 | 34 | |
| 27 | 35 | format: ?RawFormat, |
| 28 | 36 | only_section: ?[]const u8, |
| 29 | 37 | pad_to: ?u64, |
| 38 | strip: Strip, |
| 39 | compress_debug: bool, |
| 30 | 40 | |
| 31 | 41 | pub const Options = struct { |
| 32 | 42 | basename: ?[]const u8 = null, |
| 33 | 43 | format: ?RawFormat = null, |
| 34 | 44 | only_section: ?[]const u8 = null, |
| 35 | 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 | 56 | pub fn create( |
| ... | ... | @@ -51,10 +69,12 @@ pub fn create( |
| 51 | 69 | .input_file = input_file, |
| 52 | 70 | .basename = options.basename orelse input_file.getDisplayName(), |
| 53 | 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 | 73 | .format = options.format, |
| 56 | 74 | .only_section = options.only_section, |
| 57 | 75 | .pad_to = options.pad_to, |
| 76 | .strip = options.strip, |
| 77 | .compress_debug = options.compress_debug, |
| 58 | 78 | }; |
| 59 | 79 | input_file.addStepDependencies(&self.step); |
| 60 | 80 | return self; |
| ... | ... | @@ -66,6 +86,9 @@ pub const getOutputSource = getOutput; |
| 66 | 86 | pub fn getOutput(self: *const ObjCopy) std.Build.LazyPath { |
| 67 | 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 | 93 | fn make(step: *Step, prog_node: *std.Progress.Node) !void { |
| 71 | 94 | const b = step.owner; |
| ... | ... | @@ -83,6 +106,9 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { |
| 83 | 106 | man.hash.addOptionalBytes(self.only_section); |
| 84 | 107 | man.hash.addOptional(self.pad_to); |
| 85 | 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 | 113 | if (try step.cacheHit(&man)) { |
| 88 | 114 | // Cache hit, skip subprocess execution. |
| ... | ... | @@ -90,12 +116,18 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { |
| 90 | 116 | self.output_file.path = try b.cache_root.join(b.allocator, &.{ |
| 91 | 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 | 124 | return; |
| 94 | 125 | } |
| 95 | 126 | |
| 96 | 127 | const digest = man.final(); |
| 97 | | const full_dest_path = try b.cache_root.join(b.allocator, &.{ "o", &digest, self.basename }); |
| 98 | 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 | 131 | b.cache_root.handle.makePath(cache_path) catch |err| { |
| 100 | 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 | 138 | if (self.only_section) |only_section| { |
| 107 | 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 | 146 | if (self.pad_to) |pad_to| { |
| 110 | 147 | try argv.appendSlice(&.{ "--pad-to", b.fmt("{d}", .{pad_to}) }); |
| 111 | 148 | } |
| 112 | 149 | if (self.format) |format| switch (format) { |
| 113 | 150 | .bin => try argv.appendSlice(&.{ "-O", "binary" }), |
| 114 | 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 | 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 | 164 | _ = try step.evalZigProcess(argv.items, prog_node); |
| 121 | 165 | |
| 122 | 166 | self.output_file.path = full_dest_path; |
| 167 | if (self.output_file_debug) |*file| file.path = full_dest_path_debug; |
| 123 | 168 | try man.writeManifest(); |
| 124 | 169 | } |