| author | |
| committer | |
| log | 8a8bf5ad023451a22fd7abf438e6c7ee105ac6bf |
| tree | 9053ae0292046c50120f690c28774c8a715d7a5f |
| parent | affe5ed867009c889f2df7b624387c2bceefcc0e |
6 files changed, 215 insertions(+), 114 deletions(-)
BRANCH_TODO+1| ... | @@ -20,6 +20,7 @@ | ... | @@ -20,6 +20,7 @@ |
| 20 | - and adjust dependencyInner to not openDir() | 20 | - and adjust dependencyInner to not openDir() |
| 21 | 21 | ||
| 22 | ## Followup Issues | 22 | ## Followup Issues |
| 23 | * stop leaking into global process arena | ||
| 23 | * reduce the size of Maker.Step.Extended (make Run smaller) probably by using an arena per make | 24 | * reduce the size of Maker.Step.Extended (make Run smaller) probably by using an arena per make |
| 24 | * link_eh_frame_hdr should be DefaultingBool | 25 | * link_eh_frame_hdr should be DefaultingBool |
| 25 | * make --foo, --no-foo CLI args uniform (make them -f args instead) | 26 | * make --foo, --no-foo CLI args uniform (make them -f args instead) |
lib/compiler/Maker.zig+2-3| ... | @@ -612,7 +612,7 @@ pub fn main(init: process.Init.Minimal) !void { | ... | @@ -612,7 +612,7 @@ pub fn main(init: process.Init.Minimal) !void { |
| 612 | step.state = .precheck_done; | 612 | step.state = .precheck_done; |
| 613 | const deps = step_index.ptr(c).deps.slice(c); | 613 | const deps = step_index.ptr(c).deps.slice(c); |
| 614 | step.pending_deps = @intCast(deps.len); | 614 | step.pending_deps = @intCast(deps.len); |
| 615 | step.reset(gpa); | 615 | step.reset(&maker); |
| 616 | } | 616 | } |
| 617 | continue :rebuild; | 617 | continue :rebuild; |
| 618 | }, | 618 | }, |
| ... | @@ -1506,10 +1506,9 @@ fn constructGraphAndCheckForDependencyLoop( | ... | @@ -1506,10 +1506,9 @@ fn constructGraphAndCheckForDependencyLoop( |
| 1506 | /// invalidated. | 1506 | /// invalidated. |
| 1507 | pub fn invalidateResult(maker: *Maker, step: *Step) bool { | 1507 | pub fn invalidateResult(maker: *Maker, step: *Step) bool { |
| 1508 | if (step.state == .precheck_done) return false; | 1508 | if (step.state == .precheck_done) return false; |
| 1509 | const gpa = maker.gpa; | ||
| 1510 | assert(step.pending_deps == 0); | 1509 | assert(step.pending_deps == 0); |
| 1511 | step.state = .precheck_done; | 1510 | step.state = .precheck_done; |
| 1512 | step.reset(gpa); | 1511 | step.reset(maker); |
| 1513 | for (step.dependants.items) |dependant_index| { | 1512 | for (step.dependants.items) |dependant_index| { |
| 1514 | const dependant = maker.stepByIndex(dependant_index); | 1513 | const dependant = maker.stepByIndex(dependant_index); |
| 1515 | _ = invalidateResult(maker, dependant); | 1514 | _ = invalidateResult(maker, dependant); |
lib/compiler/Maker/Step.zig+6-4| ... | @@ -23,6 +23,7 @@ pub const Run = @import("Step/Run.zig"); | ... | @@ -23,6 +23,7 @@ pub const Run = @import("Step/Run.zig"); |
| 23 | pub const InstallArtifact = @import("Step/InstallArtifact.zig"); | 23 | pub const InstallArtifact = @import("Step/InstallArtifact.zig"); |
| 24 | pub const InstallFile = @import("Step/InstallFile.zig"); | 24 | pub const InstallFile = @import("Step/InstallFile.zig"); |
| 25 | pub const UpdateSourceFiles = @import("Step/UpdateSourceFiles.zig"); | 25 | pub const UpdateSourceFiles = @import("Step/UpdateSourceFiles.zig"); |
| 26 | pub const ObjCopy = @import("Step/ObjCopy.zig"); | ||
| 26 | 27 | ||
| 27 | /// Avoid false sharing. | 28 | /// Avoid false sharing. |
| 28 | _: void align(std.atomic.cache_line) = {}, | 29 | _: void align(std.atomic.cache_line) = {}, |
| ... | @@ -76,7 +77,7 @@ pub const Extended = union(enum) { | ... | @@ -76,7 +77,7 @@ pub const Extended = union(enum) { |
| 76 | install_artifact: InstallArtifact, | 77 | install_artifact: InstallArtifact, |
| 77 | install_dir: Todo, | 78 | install_dir: Todo, |
| 78 | install_file: InstallFile, | 79 | install_file: InstallFile, |
| 79 | obj_copy: Todo, | 80 | obj_copy: ObjCopy, |
| 80 | options: Todo, | 81 | options: Todo, |
| 81 | remove_dir: Todo, | 82 | remove_dir: Todo, |
| 82 | run: Run, | 83 | run: Run, |
| ... | @@ -306,8 +307,9 @@ pub fn make( | ... | @@ -306,8 +307,9 @@ pub fn make( |
| 306 | } | 307 | } |
| 307 | 308 | ||
| 308 | /// Prepares the step for being re-evaluated. | 309 | /// Prepares the step for being re-evaluated. |
| 309 | pub fn reset(step: *Step, gpa: Allocator) void { | 310 | pub fn reset(step: *Step, maker: *Maker) void { |
| 310 | assert(step.state == .precheck_done); | 311 | assert(step.state == .precheck_done); |
| 312 | const gpa = maker.gpa; | ||
| 311 | 313 | ||
| 312 | if (step.result_failed_command) |cmd| gpa.free(cmd); | 314 | if (step.result_failed_command) |cmd| gpa.free(cmd); |
| 313 | 315 | ||
| ... | @@ -318,7 +320,7 @@ pub fn reset(step: *Step, gpa: Allocator) void { | ... | @@ -318,7 +320,7 @@ pub fn reset(step: *Step, gpa: Allocator) void { |
| 318 | step.result_peak_rss = 0; | 320 | step.result_peak_rss = 0; |
| 319 | step.result_failed_command = null; | 321 | step.result_failed_command = null; |
| 320 | step.test_results = .{}; | 322 | step.test_results = .{}; |
| 321 | step.clearWatchInputs(); | 323 | step.clearWatchInputs(maker); |
| 322 | 324 | ||
| 323 | step.result_error_bundle.deinit(gpa); | 325 | step.result_error_bundle.deinit(gpa); |
| 324 | step.result_error_bundle = std.zig.ErrorBundle.empty; | 326 | step.result_error_bundle = std.zig.ErrorBundle.empty; |
| ... | @@ -732,7 +734,7 @@ fn failWithCacheError( | ... | @@ -732,7 +734,7 @@ fn failWithCacheError( |
| 732 | pub fn writeManifest(s: *Step, maker: *Maker, man: *Cache.Manifest) !void { | 734 | pub fn writeManifest(s: *Step, maker: *Maker, man: *Cache.Manifest) !void { |
| 733 | if (s.test_results.isSuccess()) { | 735 | if (s.test_results.isSuccess()) { |
| 734 | man.writeManifest() catch |err| { | 736 | man.writeManifest() catch |err| { |
| 735 | try s.addError(maker, "unable to write cache manifest: {t}", .{err}); | 737 | try s.addError(maker, "failed writing cache manifest: {t}", .{err}); |
| 736 | }; | 738 | }; |
| 737 | } | 739 | } |
| 738 | } | 740 | } |
lib/compiler/Maker/Step/ObjCopy.zig+101-68| ... | @@ -2,6 +2,7 @@ const ObjCopy = @This(); | ... | @@ -2,6 +2,7 @@ const ObjCopy = @This(); |
| 2 | 2 | ||
| 3 | const std = @import("std"); | 3 | const std = @import("std"); |
| 4 | const Io = std.Io; | 4 | const Io = std.Io; |
| 5 | const Path = std.Build.Cache.Path; | ||
| 5 | const allocPrint = std.fmt.allocPrint; | 6 | const allocPrint = std.fmt.allocPrint; |
| 6 | const Configuration = std.Build.Configuration; | 7 | const Configuration = std.Build.Configuration; |
| 7 | 8 | ||
| ... | @@ -23,120 +24,152 @@ pub fn make( | ... | @@ -23,120 +24,152 @@ pub fn make( |
| 23 | const conf_step = step_index.ptr(conf); | 24 | const conf_step = step_index.ptr(conf); |
| 24 | const conf_oc = conf_step.extended.get(conf.extra).obj_copy; | 25 | const conf_oc = conf_step.extended.get(conf.extra).obj_copy; |
| 25 | const cache_root = graph.local_cache_root; | 26 | const cache_root = graph.local_cache_root; |
| 27 | const input_lazy_path = conf_oc.input_file.get(conf); | ||
| 28 | const only_section: ?[]const u8 = if (conf_oc.only_section.value) |s| s.slice(conf) else null; | ||
| 29 | const opt_basename: ?[]const u8 = if (conf_oc.basename.value) |s| s.slice(conf) else null; | ||
| 30 | const opt_debug_basename: ?[]const u8 = if (conf_oc.debug_basename.value) |s| s.slice(conf) else null; | ||
| 26 | 31 | ||
| 27 | try step.singleUnchangingWatchInput(maker, arena, conf_oc.input_file); | 32 | try step.singleUnchangingWatchInput(maker, arena, input_lazy_path); |
| 28 | 33 | ||
| 29 | var man = graph.cache.obtain(); | 34 | var man = graph.cache.obtain(); |
| 30 | defer man.deinit(); | 35 | defer man.deinit(); |
| 31 | 36 | ||
| 32 | const src_path = try maker.resolveLazyPathIndex(arena, conf_oc.input_file, step_index); | 37 | const input_path = try maker.resolveLazyPath(arena, input_lazy_path, step_index); |
| 33 | _ = try man.addFilePath(src_path, null); | 38 | _ = try man.addFilePath(input_path, null); |
| 34 | man.hash.addOptionalBytes(conf_oc.only_section); | 39 | man.hash.addOptionalBytes(only_section); |
| 35 | man.hash.addOptional(conf_oc.pad_to); | 40 | man.hash.addOptionalBytes(opt_basename); |
| 36 | man.hash.addOptional(conf_oc.format); | 41 | man.hash.addOptionalBytes(opt_debug_basename); |
| 37 | man.hash.add(conf_oc.compress_debug); | 42 | man.hash.addOptional(conf_oc.pad_to.value); |
| 38 | man.hash.add(conf_oc.strip); | 43 | man.hash.add(conf_oc.flags.format); |
| 39 | man.hash.add(conf_oc.output_file_debug != null); | 44 | man.hash.add(conf_oc.flags.compress_debug); |
| 45 | man.hash.add(conf_oc.flags.strip); | ||
| 46 | man.hash.add(conf_oc.debug_file.value != null); | ||
| 40 | 47 | ||
| 41 | if (try step.cacheHit(&man)) { | 48 | const basename = opt_basename orelse Io.Dir.path.basename(input_path.sub_path); |
| 49 | |||
| 50 | if (try step.cacheHit(maker, &man)) { | ||
| 42 | // Cache hit, skip subprocess execution. | 51 | // Cache hit, skip subprocess execution. |
| 43 | const digest = man.final(); | 52 | const digest = man.final(); |
| 44 | conf_oc.output_file.path = try cache_root.join(arena, &.{ | 53 | maker.generatedPath(conf_oc.output_file).* = .{ |
| 45 | "o", &digest, conf_oc.basename, | 54 | .root_dir = cache_root, |
| 46 | }); | 55 | .sub_path = try Io.Dir.path.join(arena, &.{ "o", &digest, basename }), |
| 47 | if (conf_oc.output_file_debug) |*file| { | 56 | }; |
| 48 | file.path = try cache_root.join(arena, &.{ | 57 | if (conf_oc.debug_file.value) |debug_file| { |
| 49 | "o", &digest, try allocPrint(arena, "{s}.debug", .{conf_oc.basename}), | 58 | const debug_basename = opt_debug_basename orelse try allocPrint(arena, "{s}.debug", .{ |
| 59 | Io.Dir.path.basename(input_path.sub_path), | ||
| 50 | }); | 60 | }); |
| 61 | maker.generatedPath(debug_file).* = .{ | ||
| 62 | .root_dir = cache_root, | ||
| 63 | .sub_path = try Io.Dir.path.join(arena, &.{ "o", &digest, debug_basename }), | ||
| 64 | }; | ||
| 51 | } | 65 | } |
| 52 | return; | 66 | return; |
| 53 | } | 67 | } |
| 54 | 68 | ||
| 69 | // We don't find out more input files while executing objcopy so we can | ||
| 70 | // already obtain the digest and use it directly as the output path. | ||
| 55 | const digest = man.final(); | 71 | const digest = man.final(); |
| 56 | const cache_path = "o" ++ Io.Dir.path.sep_str ++ digest; | 72 | const dest_path: Path = .{ |
| 57 | const full_dest_path = try cache_root.join(arena, &.{ cache_path, conf_oc.basename }); | 73 | .root_dir = cache_root, |
| 58 | const full_dest_path_debug = try cache_root.join(arena, &.{ | 74 | .sub_path = try Io.Dir.path.join(arena, &.{ "o", &digest, basename }), |
| 59 | cache_path, try allocPrint(arena, "{s}.debug", .{conf_oc.basename}), | 75 | }; |
| 60 | }); | 76 | const dest_dirname = dest_path.dirname().?; |
| 61 | cache_root.handle.createDirPath(io, cache_path) catch |err| | 77 | dest_dirname.root_dir.handle.createDirPath(io, dest_dirname.sub_path) catch |err| |
| 62 | return step.fail("unable to make path {s}: {t}", .{ cache_path, err }); | 78 | return step.fail(maker, "failed to create path {f}: {t}", .{ dest_dirname, err }); |
| 63 | 79 | ||
| 64 | var argv: std.ArrayList([]const u8) = .empty; | 80 | var argv: std.ArrayList([]const u8) = .empty; |
| 65 | try argv.ensureUnusedCapacity(arena, 11); | 81 | try argv.ensureUnusedCapacity(arena, 11); |
| 66 | 82 | ||
| 67 | argv.addManyAsArrayAssumeCapacity(2).* = .{ graph.zig_exe, "objcopy" }; | 83 | argv.addManyAsArrayAssumeCapacity(2).* = .{ graph.zig_exe, "objcopy" }; |
| 68 | 84 | ||
| 69 | if (conf_oc.only_section) |only_section| | 85 | if (only_section) |s| argv.addManyAsArrayAssumeCapacity(2).* = .{ "-j", s }; |
| 70 | argv.addManyAsArrayAssumeCapacity(2).* = .{ "-j", only_section }; | ||
| 71 | 86 | ||
| 72 | switch (conf_oc.strip) { | 87 | switch (conf_oc.flags.strip) { |
| 73 | .none => {}, | 88 | .none => {}, |
| 74 | .debug => argv.appendAssumeCapacity("--strip-debug"), | 89 | .debug => argv.appendAssumeCapacity("--strip-debug"), |
| 75 | .debug_and_symbols => argv.appendAssumeCapacity("--strip-all"), | 90 | .debug_and_symbols => argv.appendAssumeCapacity("--strip-all"), |
| 76 | } | 91 | } |
| 77 | 92 | ||
| 78 | if (conf_oc.pad_to) |pad_to| { | 93 | if (conf_oc.pad_to.value) |pad_to| { |
| 79 | argv.addManyAsArrayAssumeCapacity(2).* = .{ | 94 | argv.addManyAsArrayAssumeCapacity(2).* = .{ |
| 80 | "--pad-to", try allocPrint(arena, "{d}", .{pad_to}), | 95 | "--pad-to", try allocPrint(arena, "{d}", .{pad_to}), |
| 81 | }; | 96 | }; |
| 82 | } | 97 | } |
| 83 | 98 | ||
| 84 | if (conf_oc.format) |format| { | 99 | switch (conf_oc.flags.format) { |
| 85 | argv.addManyAsArrayAssumeCapacity(2).* = .{ | 100 | .default => {}, |
| 86 | "-O", | 101 | else => |t| argv.addManyAsArrayAssumeCapacity(2).* = .{ "-O", @tagName(t) }, |
| 87 | switch (format) { | ||
| 88 | .bin => "binary", | ||
| 89 | .hex => "hex", | ||
| 90 | .elf => "elf", | ||
| 91 | }, | ||
| 92 | }; | ||
| 93 | } | 102 | } |
| 94 | 103 | ||
| 95 | if (conf_oc.compress_debug) | 104 | if (conf_oc.flags.compress_debug) |
| 96 | argv.appendAssumeCapacity("--compress-debug-sections"); | 105 | argv.appendAssumeCapacity("--compress-debug-sections"); |
| 97 | 106 | ||
| 98 | if (conf_oc.output_file_debug != null) | 107 | if (conf_oc.debug_file.value) |debug_file| { |
| 99 | argv.appendAssumeCapacity(try allocPrint(arena, "--extract-to={s}", .{full_dest_path_debug})); | 108 | const debug_basename = opt_debug_basename orelse try allocPrint(arena, "{s}.debug", .{ |
| 109 | Io.Dir.path.basename(input_path.sub_path), | ||
| 110 | }); | ||
| 111 | const debug_dest_path: Path = .{ | ||
| 112 | .root_dir = cache_root, | ||
| 113 | .sub_path = try Io.Dir.path.join(arena, &.{ "o", &digest, debug_basename }), | ||
| 114 | }; | ||
| 115 | argv.appendAssumeCapacity(try allocPrint(arena, "--extract-to={f}", .{debug_dest_path})); | ||
| 116 | maker.generatedPath(debug_file).* = debug_dest_path; | ||
| 117 | } | ||
| 100 | 118 | ||
| 101 | try argv.ensureUnusedCapacity(arena, 9); | 119 | try argv.ensureUnusedCapacity(arena, conf_oc.add_section.slice.len * 2); |
| 102 | 120 | ||
| 103 | if (conf_oc.add_section) |section| { | 121 | for (conf_oc.add_section.slice) |section| { |
| 104 | argv.appendAssumeCapacity("--add-section"); | 122 | argv.appendAssumeCapacity("--add-section"); |
| 105 | argv.appendAssumeCapacity(try allocPrint(arena, "{s}={f}", .{ | 123 | argv.appendAssumeCapacity(try allocPrint(arena, "{s}={f}", .{ |
| 106 | section.section_name, try maker.resolveLazyPathIndex(arena, section.file_path, step_index), | 124 | section.section_name.slice(conf), |
| 125 | try maker.resolveLazyPathIndex(arena, section.file_path, step_index), | ||
| 107 | })); | 126 | })); |
| 108 | } | 127 | } |
| 109 | 128 | ||
| 110 | if (conf_oc.set_section_alignment) |set_align| { | 129 | for (conf_oc.update_section.slice) |update| { |
| 111 | argv.appendAssumeCapacity("--set-section-alignment"); | 130 | const name = update.section_name.slice(conf); |
| 112 | argv.appendAssumeCapacity(try allocPrint(arena, "{s}={d}", .{ set_align.section_name, set_align.alignment })); | ||
| 113 | } | ||
| 114 | 131 | ||
| 115 | if (conf_oc.set_section_flags) |set_flags| { | 132 | try argv.ensureUnusedCapacity(arena, 4); |
| 116 | const f = set_flags.flags; | 133 | |
| 117 | // trailing comma is allowed | 134 | if (update.flags.alignment.toBytes()) |a| { |
| 118 | argv.appendAssumeCapacity("--set-section-flags"); | 135 | argv.appendAssumeCapacity("--set-section-alignment"); |
| 119 | argv.appendAssumeCapacity(try allocPrint(arena, "{s}={s}{s}{s}{s}{s}{s}{s}{s}{s}", .{ | 136 | argv.appendAssumeCapacity(try allocPrint(arena, "{s}={d}", .{ name, a })); |
| 120 | set_flags.section_name, | 137 | } |
| 121 | if (f.alloc) "alloc," else "", | 138 | |
| 122 | if (f.contents) "contents," else "", | 139 | const f = update.flags.section_flags; |
| 123 | if (f.load) "load," else "", | 140 | const default_flags: Configuration.Step.ObjCopy.SectionFlags = .{}; |
| 124 | if (f.readonly) "readonly," else "", | 141 | |
| 125 | if (f.code) "code," else "", | 142 | if (f != default_flags) { |
| 126 | if (f.exclude) "exclude," else "", | 143 | // trailing comma is allowed |
| 127 | if (f.large) "large," else "", | 144 | argv.appendAssumeCapacity("--set-section-flags"); |
| 128 | if (f.merge) "merge," else "", | 145 | argv.appendAssumeCapacity(try allocPrint(arena, "{s}={s}{s}{s}{s}{s}{s}{s}{s}{s}", .{ |
| 129 | if (f.strings) "strings," else "", | 146 | name, |
| 130 | })); | 147 | if (f.alloc) "alloc," else "", |
| 148 | if (f.contents) "contents," else "", | ||
| 149 | if (f.load) "load," else "", | ||
| 150 | if (f.readonly) "readonly," else "", | ||
| 151 | if (f.code) "code," else "", | ||
| 152 | if (f.exclude) "exclude," else "", | ||
| 153 | if (f.large) "large," else "", | ||
| 154 | if (f.merge) "merge," else "", | ||
| 155 | if (f.strings) "strings," else "", | ||
| 156 | })); | ||
| 157 | } | ||
| 131 | } | 158 | } |
| 132 | 159 | ||
| 133 | argv.appendAssumeCapacity(src_path); | 160 | argv.appendAssumeCapacity(try allocPrint(arena, "{f}", .{input_path})); |
| 134 | argv.appendAssumeCapacity(full_dest_path); | 161 | argv.appendAssumeCapacity(try allocPrint(arena, "{f}", .{dest_path})); |
| 135 | 162 | ||
| 136 | argv.appendAssumeCapacity("--listen=-"); | 163 | argv.appendAssumeCapacity("--listen=-"); |
| 137 | _ = try Step.evalZigProcess(step_index, maker, argv.items, progress_node, false); | 164 | _ = Step.evalZigProcess(step_index, maker, argv.items, progress_node, false) catch |err| switch (err) { |
| 165 | error.NeedCompileErrorCheck => unreachable, | ||
| 166 | else => |e| return e, | ||
| 167 | }; | ||
| 168 | |||
| 169 | maker.generatedPath(conf_oc.output_file).* = dest_path; | ||
| 138 | 170 | ||
| 139 | conf_oc.output_file.path = full_dest_path; | 171 | man.writeManifest() catch |err| switch (err) { |
| 140 | if (conf_oc.output_file_debug) |*file| file.path = full_dest_path_debug; | 172 | error.Canceled => |e| return e, |
| 141 | try man.writeManifest(); | 173 | else => |e| try step.addError(maker, "failed writing cache manifest: {t}", .{e}), |
| 174 | }; | ||
| 142 | } | 175 | } |
lib/std/Build/Configuration.zig+98-1| ... | @@ -1102,10 +1102,87 @@ pub const Step = extern struct { | ... | @@ -1102,10 +1102,87 @@ pub const Step = extern struct { |
| 1102 | 1102 | ||
| 1103 | pub const ObjCopy = struct { | 1103 | pub const ObjCopy = struct { |
| 1104 | flags: @This().Flags, | 1104 | flags: @This().Flags, |
| 1105 | input_file: LazyPath.Index, | ||
| 1106 | output_file: GeneratedFileIndex, | ||
| 1107 | basename: Storage.FlagOptional(.flags, .basename, String), | ||
| 1108 | debug_file: Storage.FlagOptional(.flags, .debug_file, GeneratedFileIndex), | ||
| 1109 | debug_basename: Storage.FlagOptional(.flags, .debug_basename, String), | ||
| 1110 | only_section: Storage.FlagOptional(.flags, .only_section, String), | ||
| 1111 | pad_to: Storage.FlagOptional(.flags, .pad_to, u64), | ||
| 1112 | add_section: Storage.FlagLengthPrefixedList(.flags, .add_section, AddSection), | ||
| 1113 | update_section: Storage.FlagLengthPrefixedList(.flags, .update_section, UpdateSection), | ||
| 1114 | |||
| 1115 | pub const Format = enum(u2) { | ||
| 1116 | binary, | ||
| 1117 | hex, | ||
| 1118 | elf, | ||
| 1119 | default, | ||
| 1120 | |||
| 1121 | pub fn init(f: ?std.Build.Step.ObjCopy.Format) @This() { | ||
| 1122 | return switch (f orelse return .default) { | ||
| 1123 | .binary => .binary, | ||
| 1124 | .hex => .hex, | ||
| 1125 | .elf => .elf, | ||
| 1126 | }; | ||
| 1127 | } | ||
| 1128 | }; | ||
| 1129 | |||
| 1130 | pub const Strip = enum(u2) { | ||
| 1131 | none, | ||
| 1132 | debug, | ||
| 1133 | debug_and_symbols, | ||
| 1134 | }; | ||
| 1135 | |||
| 1136 | pub const AddSection = extern struct { | ||
| 1137 | section_name: String, | ||
| 1138 | file_path: LazyPath.Index, | ||
| 1139 | }; | ||
| 1140 | |||
| 1141 | pub const UpdateSection = extern struct { | ||
| 1142 | section_name: String, | ||
| 1143 | flags: @This().Flags, | ||
| 1144 | |||
| 1145 | pub const Flags = packed struct(u32) { | ||
| 1146 | section_flags: SectionFlags, | ||
| 1147 | alignment: Alignment, | ||
| 1148 | _: u17 = 0, | ||
| 1149 | }; | ||
| 1150 | }; | ||
| 1151 | |||
| 1152 | pub const SectionFlags = packed struct(u9) { | ||
| 1153 | /// add SHF_ALLOC | ||
| 1154 | alloc: bool = false, | ||
| 1155 | /// if section is SHT_NOBITS, set SHT_PROGBITS, otherwise do nothing | ||
| 1156 | contents: bool = false, | ||
| 1157 | /// if section is SHT_NOBITS, set SHT_PROGBITS, otherwise do nothing (same as contents) | ||
| 1158 | load: bool = false, | ||
| 1159 | /// readonly: clear default SHF_WRITE flag | ||
| 1160 | readonly: bool = false, | ||
| 1161 | /// add SHF_EXECINSTR | ||
| 1162 | code: bool = false, | ||
| 1163 | /// add SHF_EXCLUDE | ||
| 1164 | exclude: bool = false, | ||
| 1165 | /// add SHF_X86_64_LARGE. Fatal error if target is not x86_64 | ||
| 1166 | large: bool = false, | ||
| 1167 | /// add SHF_MERGE | ||
| 1168 | merge: bool = false, | ||
| 1169 | /// add SHF_STRINGS | ||
| 1170 | strings: bool = false, | ||
| 1171 | }; | ||
| 1105 | 1172 | ||
| 1106 | pub const Flags = packed struct(u32) { | 1173 | pub const Flags = packed struct(u32) { |
| 1107 | tag: Tag = .obj_copy, | 1174 | tag: Tag = .obj_copy, |
| 1108 | _: u27 = 0, | 1175 | basename: bool, |
| 1176 | debug_file: bool, | ||
| 1177 | debug_basename: bool, | ||
| 1178 | format: Format, | ||
| 1179 | strip: Strip, | ||
| 1180 | compress_debug: bool, | ||
| 1181 | only_section: bool, | ||
| 1182 | pad_to: bool, | ||
| 1183 | add_section: bool, | ||
| 1184 | update_section: bool, | ||
| 1185 | _: u15 = 0, | ||
| 1109 | }; | 1186 | }; |
| 1110 | }; | 1187 | }; |
| 1111 | 1188 | ||
| ... | @@ -1658,6 +1735,26 @@ pub const Bytes = extern struct { | ... | @@ -1658,6 +1735,26 @@ pub const Bytes = extern struct { |
| 1658 | } | 1735 | } |
| 1659 | }; | 1736 | }; |
| 1660 | 1737 | ||
| 1738 | /// Stored as a power-of-two, with one special value to indicate none. | ||
| 1739 | pub const Alignment = enum(u6) { | ||
| 1740 | @"1" = 0, | ||
| 1741 | @"2" = 1, | ||
| 1742 | @"4" = 2, | ||
| 1743 | @"8" = 3, | ||
| 1744 | @"16" = 4, | ||
| 1745 | @"32" = 5, | ||
| 1746 | @"64" = 6, | ||
| 1747 | none = std.math.maxInt(u6), | ||
| 1748 | _, | ||
| 1749 | |||
| 1750 | pub fn toBytes(a: @This()) ?u64 { | ||
| 1751 | return switch (a) { | ||
| 1752 | .none => null, | ||
| 1753 | else => @as(u64, 1) << @intFromEnum(a), | ||
| 1754 | }; | ||
| 1755 | } | ||
| 1756 | }; | ||
| 1757 | |||
| 1661 | pub const DefaultingBool = enum(u2) { | 1758 | pub const DefaultingBool = enum(u2) { |
| 1662 | false, | 1759 | false, |
| 1663 | true, | 1760 | true, |
lib/std/Build/Step/ObjCopy.zig+7-38| ... | @@ -6,11 +6,11 @@ const Configuration = std.Build.Configuration; | ... | @@ -6,11 +6,11 @@ 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: ?[]const u8, |
| 10 | output_file: Configuration.GeneratedFileIndex, | 10 | output_file: Configuration.GeneratedFileIndex, |
| 11 | output_file_debug: Configuration.OptionalGeneratedFileIndex, | 11 | output_file_debug: Configuration.OptionalGeneratedFileIndex, |
| 12 | 12 | ||
| 13 | format: ?RawFormat, | 13 | format: ?Format, |
| 14 | only_section: ?[]const u8, | 14 | only_section: ?[]const u8, |
| 15 | pad_to: ?u64, | 15 | pad_to: ?u64, |
| 16 | strip: Strip, | 16 | strip: Strip, |
| ... | @@ -22,38 +22,9 @@ set_section_flags: ?SetSectionFlags, | ... | @@ -22,38 +22,9 @@ set_section_flags: ?SetSectionFlags, |
| 22 | 22 | ||
| 23 | pub const base_tag: Step.Tag = .obj_copy; | 23 | pub const base_tag: Step.Tag = .obj_copy; |
| 24 | 24 | ||
| 25 | pub const RawFormat = enum { | 25 | pub const Format = enum { binary, hex, elf }; |
| 26 | bin, | 26 | pub const Strip = Configuration.Step.ObjCopy.Strip; |
| 27 | hex, | 27 | pub const SectionFlags = Configuration.Step.ObjCopy.SectionFlags; |
| 28 | elf, | ||
| 29 | }; | ||
| 30 | |||
| 31 | pub const Strip = enum { | ||
| 32 | none, | ||
| 33 | debug, | ||
| 34 | debug_and_symbols, | ||
| 35 | }; | ||
| 36 | |||
| 37 | pub const SectionFlags = packed struct { | ||
| 38 | /// add SHF_ALLOC | ||
| 39 | alloc: bool = false, | ||
| 40 | /// if section is SHT_NOBITS, set SHT_PROGBITS, otherwise do nothing | ||
| 41 | contents: bool = false, | ||
| 42 | /// if section is SHT_NOBITS, set SHT_PROGBITS, otherwise do nothing (same as contents) | ||
| 43 | load: bool = false, | ||
| 44 | /// readonly: clear default SHF_WRITE flag | ||
| 45 | readonly: bool = false, | ||
| 46 | /// add SHF_EXECINSTR | ||
| 47 | code: bool = false, | ||
| 48 | /// add SHF_EXCLUDE | ||
| 49 | exclude: bool = false, | ||
| 50 | /// add SHF_X86_64_LARGE. Fatal error if target is not x86_64 | ||
| 51 | large: bool = false, | ||
| 52 | /// add SHF_MERGE | ||
| 53 | merge: bool = false, | ||
| 54 | /// add SHF_STRINGS | ||
| 55 | strings: bool = false, | ||
| 56 | }; | ||
| 57 | 28 | ||
| 58 | pub const AddSection = struct { | 29 | pub const AddSection = struct { |
| 59 | section_name: []const u8, | 30 | section_name: []const u8, |
| ... | @@ -72,7 +43,7 @@ pub const SetSectionFlags = struct { | ... | @@ -72,7 +43,7 @@ pub const SetSectionFlags = struct { |
| 72 | 43 | ||
| 73 | pub const Options = struct { | 44 | pub const Options = struct { |
| 74 | basename: ?[]const u8 = null, | 45 | basename: ?[]const u8 = null, |
| 75 | format: ?RawFormat = null, | 46 | format: ?Format = null, |
| 76 | only_section: ?[]const u8 = null, | 47 | only_section: ?[]const u8 = null, |
| 77 | pad_to: ?u64 = null, | 48 | pad_to: ?u64 = null, |
| 78 | 49 | ||
| ... | @@ -95,7 +66,6 @@ pub fn create( | ... | @@ -95,7 +66,6 @@ pub fn create( |
| 95 | options: Options, | 66 | options: Options, |
| 96 | ) *ObjCopy { | 67 | ) *ObjCopy { |
| 97 | const graph = owner.graph; | 68 | const graph = owner.graph; |
| 98 | const arena = graph.arena; | ||
| 99 | const obj_copy = graph.create(ObjCopy); | 69 | const obj_copy = graph.create(ObjCopy); |
| 100 | obj_copy.* = .{ | 70 | obj_copy.* = .{ |
| 101 | .step = .init(.{ | 71 | .step = .init(.{ |
| ... | @@ -104,8 +74,7 @@ pub fn create( | ... | @@ -104,8 +74,7 @@ pub fn create( |
| 104 | .owner = owner, | 74 | .owner = owner, |
| 105 | }), | 75 | }), |
| 106 | .input_file = input_file, | 76 | .input_file = input_file, |
| 107 | .basename = options.basename orelse | 77 | .basename = options.basename, |
| 108 | std.fmt.allocPrint(arena, "{f}", .{input_file.fmt(graph)}) catch @panic("OOM"), | ||
| 109 | .output_file = graph.addGeneratedFile(&obj_copy.step), | 78 | .output_file = graph.addGeneratedFile(&obj_copy.step), |
| 110 | .output_file_debug = if (options.strip != .none and options.extract_to_separate_file) | 79 | .output_file_debug = if (options.strip != .none and options.extract_to_separate_file) |
| 111 | .init(graph.addGeneratedFile(&obj_copy.step)) | 80 | .init(graph.addGeneratedFile(&obj_copy.step)) |