| author | |
| committer | |
| log | affe5ed867009c889f2df7b624387c2bceefcc0e |
| tree | fd99f28828e8eaf77cbf82c37f4f2078f4acf77b |
| parent | d3ec255a1f7cd38164de816462c29de4a2981490 |
11 files changed, 293 insertions(+), 209 deletions(-)
BRANCH_TODO+2| ... | @@ -28,6 +28,8 @@ | ... | @@ -28,6 +28,8 @@ |
| 28 | * no more "artifact arg" to run step. if you want to run the post-install binary, get the lazy path | 28 | * no more "artifact arg" to run step. if you want to run the post-install binary, get the lazy path |
| 29 | from the install step. | 29 | from the install step. |
| 30 | * fmt step: import zig fmt code directly rather than child proc | 30 | * fmt step: import zig fmt code directly rather than child proc |
| 31 | * UpdateSourceFiles: introduce Group | ||
| 32 | * WriteFiles: introduce Group | ||
| 31 | 33 | ||
| 32 | ## Already Filed Followup Issues | 34 | ## Already Filed Followup Issues |
| 33 | * build system fmt step with check=false does not acquire a write lock on source files #35204 | 35 | * build system fmt step with check=false does not acquire a write lock on source files #35204 |
lib/compiler/Maker/Step.zig+4-3| ... | @@ -22,6 +22,7 @@ pub const Compile = @import("Step/Compile.zig"); | ... | @@ -22,6 +22,7 @@ pub const Compile = @import("Step/Compile.zig"); |
| 22 | pub const Run = @import("Step/Run.zig"); | 22 | 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 | 26 | ||
| 26 | /// Avoid false sharing. | 27 | /// Avoid false sharing. |
| 27 | _: void align(std.atomic.cache_line) = {}, | 28 | _: void align(std.atomic.cache_line) = {}, |
| ... | @@ -75,13 +76,13 @@ pub const Extended = union(enum) { | ... | @@ -75,13 +76,13 @@ pub const Extended = union(enum) { |
| 75 | install_artifact: InstallArtifact, | 76 | install_artifact: InstallArtifact, |
| 76 | install_dir: Todo, | 77 | install_dir: Todo, |
| 77 | install_file: InstallFile, | 78 | install_file: InstallFile, |
| 78 | objcopy: Todo, | 79 | obj_copy: Todo, |
| 79 | options: Todo, | 80 | options: Todo, |
| 80 | remove_dir: Todo, | 81 | remove_dir: Todo, |
| 81 | run: Run, | 82 | run: Run, |
| 82 | top_level: TopLevel, | 83 | top_level: TopLevel, |
| 83 | translate_c: Todo, | 84 | translate_c: Todo, |
| 84 | update_source_files: Todo, | 85 | update_source_files: UpdateSourceFiles, |
| 85 | write_file: Todo, | 86 | write_file: Todo, |
| 86 | 87 | ||
| 87 | pub fn init(tag: Configuration.Step.Tag) Extended { | 88 | pub fn init(tag: Configuration.Step.Tag) Extended { |
| ... | @@ -95,7 +96,7 @@ pub const Extended = union(enum) { | ... | @@ -95,7 +96,7 @@ pub const Extended = union(enum) { |
| 95 | .install_artifact => .{ .install_artifact = .{} }, | 96 | .install_artifact => .{ .install_artifact = .{} }, |
| 96 | .install_dir => .{ .install_dir = .{} }, | 97 | .install_dir => .{ .install_dir = .{} }, |
| 97 | .install_file => .{ .install_file = .{} }, | 98 | .install_file => .{ .install_file = .{} }, |
| 98 | .objcopy => .{ .objcopy = .{} }, | 99 | .obj_copy => .{ .obj_copy = .{} }, |
| 99 | .options => .{ .options = .{} }, | 100 | .options => .{ .options = .{} }, |
| 100 | .remove_dir => .{ .remove_dir = .{} }, | 101 | .remove_dir => .{ .remove_dir = .{} }, |
| 101 | .run => .{ .run = .{} }, | 102 | .run => .{ .run = .{} }, |
lib/compiler/Maker/Step/ObjCopy.zig created+142| ... | @@ -0,0 +1,142 @@ | ||
| 1 | const ObjCopy = @This(); | ||
| 2 | |||
| 3 | const std = @import("std"); | ||
| 4 | const Io = std.Io; | ||
| 5 | const allocPrint = std.fmt.allocPrint; | ||
| 6 | const Configuration = std.Build.Configuration; | ||
| 7 | |||
| 8 | const Step = @import("../Step.zig"); | ||
| 9 | const Maker = @import("../../Maker.zig"); | ||
| 10 | |||
| 11 | pub fn make( | ||
| 12 | obj_copy: *ObjCopy, | ||
| 13 | step_index: Configuration.Step.Index, | ||
| 14 | maker: *Maker, | ||
| 15 | progress_node: std.Progress.Node, | ||
| 16 | ) Step.ExtendedMakeError!void { | ||
| 17 | _ = obj_copy; | ||
| 18 | const graph = maker.graph; | ||
| 19 | const arena = maker.graph.arena; // TODO don't leak into process arena | ||
| 20 | const io = graph.io; | ||
| 21 | const step = maker.stepByIndex(step_index); | ||
| 22 | const conf = &maker.scanned_config.configuration; | ||
| 23 | const conf_step = step_index.ptr(conf); | ||
| 24 | const conf_oc = conf_step.extended.get(conf.extra).obj_copy; | ||
| 25 | const cache_root = graph.local_cache_root; | ||
| 26 | |||
| 27 | try step.singleUnchangingWatchInput(maker, arena, conf_oc.input_file); | ||
| 28 | |||
| 29 | var man = graph.cache.obtain(); | ||
| 30 | defer man.deinit(); | ||
| 31 | |||
| 32 | const src_path = try maker.resolveLazyPathIndex(arena, conf_oc.input_file, step_index); | ||
| 33 | _ = try man.addFilePath(src_path, null); | ||
| 34 | man.hash.addOptionalBytes(conf_oc.only_section); | ||
| 35 | man.hash.addOptional(conf_oc.pad_to); | ||
| 36 | man.hash.addOptional(conf_oc.format); | ||
| 37 | man.hash.add(conf_oc.compress_debug); | ||
| 38 | man.hash.add(conf_oc.strip); | ||
| 39 | man.hash.add(conf_oc.output_file_debug != null); | ||
| 40 | |||
| 41 | if (try step.cacheHit(&man)) { | ||
| 42 | // Cache hit, skip subprocess execution. | ||
| 43 | const digest = man.final(); | ||
| 44 | conf_oc.output_file.path = try cache_root.join(arena, &.{ | ||
| 45 | "o", &digest, conf_oc.basename, | ||
| 46 | }); | ||
| 47 | if (conf_oc.output_file_debug) |*file| { | ||
| 48 | file.path = try cache_root.join(arena, &.{ | ||
| 49 | "o", &digest, try allocPrint(arena, "{s}.debug", .{conf_oc.basename}), | ||
| 50 | }); | ||
| 51 | } | ||
| 52 | return; | ||
| 53 | } | ||
| 54 | |||
| 55 | const digest = man.final(); | ||
| 56 | const cache_path = "o" ++ Io.Dir.path.sep_str ++ digest; | ||
| 57 | const full_dest_path = try cache_root.join(arena, &.{ cache_path, conf_oc.basename }); | ||
| 58 | const full_dest_path_debug = try cache_root.join(arena, &.{ | ||
| 59 | cache_path, try allocPrint(arena, "{s}.debug", .{conf_oc.basename}), | ||
| 60 | }); | ||
| 61 | cache_root.handle.createDirPath(io, cache_path) catch |err| | ||
| 62 | return step.fail("unable to make path {s}: {t}", .{ cache_path, err }); | ||
| 63 | |||
| 64 | var argv: std.ArrayList([]const u8) = .empty; | ||
| 65 | try argv.ensureUnusedCapacity(arena, 11); | ||
| 66 | |||
| 67 | argv.addManyAsArrayAssumeCapacity(2).* = .{ graph.zig_exe, "objcopy" }; | ||
| 68 | |||
| 69 | if (conf_oc.only_section) |only_section| | ||
| 70 | argv.addManyAsArrayAssumeCapacity(2).* = .{ "-j", only_section }; | ||
| 71 | |||
| 72 | switch (conf_oc.strip) { | ||
| 73 | .none => {}, | ||
| 74 | .debug => argv.appendAssumeCapacity("--strip-debug"), | ||
| 75 | .debug_and_symbols => argv.appendAssumeCapacity("--strip-all"), | ||
| 76 | } | ||
| 77 | |||
| 78 | if (conf_oc.pad_to) |pad_to| { | ||
| 79 | argv.addManyAsArrayAssumeCapacity(2).* = .{ | ||
| 80 | "--pad-to", try allocPrint(arena, "{d}", .{pad_to}), | ||
| 81 | }; | ||
| 82 | } | ||
| 83 | |||
| 84 | if (conf_oc.format) |format| { | ||
| 85 | argv.addManyAsArrayAssumeCapacity(2).* = .{ | ||
| 86 | "-O", | ||
| 87 | switch (format) { | ||
| 88 | .bin => "binary", | ||
| 89 | .hex => "hex", | ||
| 90 | .elf => "elf", | ||
| 91 | }, | ||
| 92 | }; | ||
| 93 | } | ||
| 94 | |||
| 95 | if (conf_oc.compress_debug) | ||
| 96 | argv.appendAssumeCapacity("--compress-debug-sections"); | ||
| 97 | |||
| 98 | if (conf_oc.output_file_debug != null) | ||
| 99 | argv.appendAssumeCapacity(try allocPrint(arena, "--extract-to={s}", .{full_dest_path_debug})); | ||
| 100 | |||
| 101 | try argv.ensureUnusedCapacity(arena, 9); | ||
| 102 | |||
| 103 | if (conf_oc.add_section) |section| { | ||
| 104 | argv.appendAssumeCapacity("--add-section"); | ||
| 105 | argv.appendAssumeCapacity(try allocPrint(arena, "{s}={f}", .{ | ||
| 106 | section.section_name, try maker.resolveLazyPathIndex(arena, section.file_path, step_index), | ||
| 107 | })); | ||
| 108 | } | ||
| 109 | |||
| 110 | if (conf_oc.set_section_alignment) |set_align| { | ||
| 111 | argv.appendAssumeCapacity("--set-section-alignment"); | ||
| 112 | argv.appendAssumeCapacity(try allocPrint(arena, "{s}={d}", .{ set_align.section_name, set_align.alignment })); | ||
| 113 | } | ||
| 114 | |||
| 115 | if (conf_oc.set_section_flags) |set_flags| { | ||
| 116 | const f = set_flags.flags; | ||
| 117 | // trailing comma is allowed | ||
| 118 | argv.appendAssumeCapacity("--set-section-flags"); | ||
| 119 | argv.appendAssumeCapacity(try allocPrint(arena, "{s}={s}{s}{s}{s}{s}{s}{s}{s}{s}", .{ | ||
| 120 | set_flags.section_name, | ||
| 121 | if (f.alloc) "alloc," else "", | ||
| 122 | if (f.contents) "contents," else "", | ||
| 123 | if (f.load) "load," else "", | ||
| 124 | if (f.readonly) "readonly," else "", | ||
| 125 | if (f.code) "code," else "", | ||
| 126 | if (f.exclude) "exclude," else "", | ||
| 127 | if (f.large) "large," else "", | ||
| 128 | if (f.merge) "merge," else "", | ||
| 129 | if (f.strings) "strings," else "", | ||
| 130 | })); | ||
| 131 | } | ||
| 132 | |||
| 133 | argv.appendAssumeCapacity(src_path); | ||
| 134 | argv.appendAssumeCapacity(full_dest_path); | ||
| 135 | |||
| 136 | argv.appendAssumeCapacity("--listen=-"); | ||
| 137 | _ = try Step.evalZigProcess(step_index, maker, argv.items, progress_node, false); | ||
| 138 | |||
| 139 | conf_oc.output_file.path = full_dest_path; | ||
| 140 | if (conf_oc.output_file_debug) |*file| file.path = full_dest_path_debug; | ||
| 141 | try man.writeManifest(); | ||
| 142 | } | ||
lib/compiler/Maker/Step/UpdateSourceFiles.zig created+87| ... | @@ -0,0 +1,87 @@ | ||
| 1 | const UpdateSourceFiles = @This(); | ||
| 2 | |||
| 3 | const std = @import("std"); | ||
| 4 | const Io = std.Io; | ||
| 5 | const Path = std.Build.Cache.Path; | ||
| 6 | const allocPrint = std.fmt.allocPrint; | ||
| 7 | const Configuration = std.Build.Configuration; | ||
| 8 | |||
| 9 | const Step = @import("../Step.zig"); | ||
| 10 | const Maker = @import("../../Maker.zig"); | ||
| 11 | |||
| 12 | pub fn make( | ||
| 13 | usf: *UpdateSourceFiles, | ||
| 14 | step_index: Configuration.Step.Index, | ||
| 15 | maker: *Maker, | ||
| 16 | progress_node: std.Progress.Node, | ||
| 17 | ) Step.ExtendedMakeError!void { | ||
| 18 | _ = usf; | ||
| 19 | const graph = maker.graph; | ||
| 20 | const arena = maker.graph.arena; // TODO don't leak into process arena | ||
| 21 | const io = graph.io; | ||
| 22 | const step = maker.stepByIndex(step_index); | ||
| 23 | const conf = &maker.scanned_config.configuration; | ||
| 24 | const conf_step = step_index.ptr(conf); | ||
| 25 | const conf_usf = conf_step.extended.get(conf.extra).update_source_files; | ||
| 26 | const build_root = graph.build_root_directory; | ||
| 27 | |||
| 28 | if (conf_step.owner != .root) | ||
| 29 | return step.fail(maker, "non-root package attempted to update its source files", .{}); | ||
| 30 | |||
| 31 | var any_miss = false; | ||
| 32 | |||
| 33 | progress_node.setEstimatedTotalItems(conf_usf.embeds.slice.len + conf_usf.copies.slice.len); | ||
| 34 | |||
| 35 | for (conf_usf.embeds.slice) |*embed| { | ||
| 36 | const dest_path: Path = .{ | ||
| 37 | .root_dir = build_root, | ||
| 38 | .sub_path = embed.dest_path.slice(conf), | ||
| 39 | }; | ||
| 40 | if (Io.Dir.path.dirname(dest_path.sub_path)) |dirname| { | ||
| 41 | const dirname_path: Path = .{ | ||
| 42 | .root_dir = build_root, | ||
| 43 | .sub_path = dirname, | ||
| 44 | }; | ||
| 45 | dirname_path.root_dir.handle.createDirPath(io, dirname_path.sub_path) catch |err| | ||
| 46 | return step.fail(maker, "failed to create path {f}: {t}", .{ dirname_path, err }); | ||
| 47 | } | ||
| 48 | dest_path.root_dir.handle.writeFile(io, .{ | ||
| 49 | .sub_path = dest_path.sub_path, | ||
| 50 | .data = embed.bytes.slice(conf), | ||
| 51 | }) catch |err| return step.fail(maker, "failed to write file {f}: {t}", .{ dest_path, err }); | ||
| 52 | any_miss = true; | ||
| 53 | progress_node.completeOne(); | ||
| 54 | } | ||
| 55 | |||
| 56 | for (conf_usf.copies.slice) |*copy| { | ||
| 57 | const dest_path: Path = .{ | ||
| 58 | .root_dir = build_root, | ||
| 59 | .sub_path = copy.dest_path.slice(conf), | ||
| 60 | }; | ||
| 61 | if (Io.Dir.path.dirname(dest_path.sub_path)) |dirname| { | ||
| 62 | const dirname_path: Path = .{ | ||
| 63 | .root_dir = build_root, | ||
| 64 | .sub_path = dirname, | ||
| 65 | }; | ||
| 66 | dirname_path.root_dir.handle.createDirPath(io, dirname_path.sub_path) catch |err| | ||
| 67 | return step.fail(maker, "failed to create path {f}: {t}", .{ dirname_path, err }); | ||
| 68 | } | ||
| 69 | const src_lazy_path = copy.src_path.get(conf); | ||
| 70 | const source_path = try maker.resolveLazyPath(arena, src_lazy_path, step_index); | ||
| 71 | if (!step.inputs.populated()) try step.addWatchInput(maker, arena, src_lazy_path); | ||
| 72 | |||
| 73 | const prev_status = source_path.root_dir.handle.updateFile( | ||
| 74 | io, | ||
| 75 | source_path.sub_path, | ||
| 76 | dest_path.root_dir.handle, | ||
| 77 | dest_path.sub_path, | ||
| 78 | .{}, | ||
| 79 | ) catch |err| return step.fail(maker, "unable to update file from {f} to {f}: {t}", .{ | ||
| 80 | source_path, dest_path, err, | ||
| 81 | }); | ||
| 82 | any_miss = any_miss or prev_status == .stale; | ||
| 83 | progress_node.completeOne(); | ||
| 84 | } | ||
| 85 | |||
| 86 | step.result_cached = !any_miss; | ||
| 87 | } | ||
lib/compiler/configurer.zig+1-1| ... | @@ -967,7 +967,7 @@ fn serialize(b: *std.Build, wc: *Configuration.Wip, writer: *Io.Writer) !void { | ... | @@ -967,7 +967,7 @@ fn serialize(b: *std.Build, wc: *Configuration.Wip, writer: *Io.Writer) !void { |
| 967 | }, | 967 | }, |
| 968 | .check_file => @panic("TODO"), | 968 | .check_file => @panic("TODO"), |
| 969 | .config_header => @panic("TODO"), | 969 | .config_header => @panic("TODO"), |
| 970 | .objcopy => @panic("TODO"), | 970 | .obj_copy => @panic("TODO"), |
| 971 | .options => @panic("TODO"), | 971 | .options => @panic("TODO"), |
| 972 | }, | 972 | }, |
| 973 | }); | 973 | }); |
lib/std/Build/Configuration.zig+21-5| ... | @@ -456,7 +456,7 @@ pub const Step = extern struct { | ... | @@ -456,7 +456,7 @@ pub const Step = extern struct { |
| 456 | install_artifact: InstallArtifact, | 456 | install_artifact: InstallArtifact, |
| 457 | install_dir: InstallDir, | 457 | install_dir: InstallDir, |
| 458 | install_file: InstallFile, | 458 | install_file: InstallFile, |
| 459 | objcopy: Objcopy, | 459 | obj_copy: ObjCopy, |
| 460 | options: Options, | 460 | options: Options, |
| 461 | remove_dir: RemoveDir, | 461 | remove_dir: RemoveDir, |
| 462 | run: Run, | 462 | run: Run, |
| ... | @@ -491,7 +491,7 @@ pub const Step = extern struct { | ... | @@ -491,7 +491,7 @@ pub const Step = extern struct { |
| 491 | install_artifact, | 491 | install_artifact, |
| 492 | install_dir, | 492 | install_dir, |
| 493 | install_file, | 493 | install_file, |
| 494 | objcopy, | 494 | obj_copy, |
| 495 | options, | 495 | options, |
| 496 | remove_dir, | 496 | remove_dir, |
| 497 | run, | 497 | run, |
| ... | @@ -1100,11 +1100,11 @@ pub const Step = extern struct { | ... | @@ -1100,11 +1100,11 @@ pub const Step = extern struct { |
| 1100 | }; | 1100 | }; |
| 1101 | }; | 1101 | }; |
| 1102 | 1102 | ||
| 1103 | pub const Objcopy = struct { | 1103 | pub const ObjCopy = struct { |
| 1104 | flags: @This().Flags, | 1104 | flags: @This().Flags, |
| 1105 | 1105 | ||
| 1106 | pub const Flags = packed struct(u32) { | 1106 | pub const Flags = packed struct(u32) { |
| 1107 | tag: Tag = .objcopy, | 1107 | tag: Tag = .obj_copy, |
| 1108 | _: u27 = 0, | 1108 | _: u27 = 0, |
| 1109 | }; | 1109 | }; |
| 1110 | }; | 1110 | }; |
| ... | @@ -1147,10 +1147,26 @@ pub const Step = extern struct { | ... | @@ -1147,10 +1147,26 @@ pub const Step = extern struct { |
| 1147 | 1147 | ||
| 1148 | pub const UpdateSourceFiles = struct { | 1148 | pub const UpdateSourceFiles = struct { |
| 1149 | flags: @This().Flags, | 1149 | flags: @This().Flags, |
| 1150 | embeds: Storage.FlagLengthPrefixedList(.flags, .embeds, Embed), | ||
| 1151 | copies: Storage.FlagLengthPrefixedList(.flags, .copies, Copy), | ||
| 1152 | |||
| 1153 | pub const Embed = extern struct { | ||
| 1154 | /// Relative to build root. | ||
| 1155 | dest_path: String, | ||
| 1156 | bytes: Bytes, | ||
| 1157 | }; | ||
| 1158 | |||
| 1159 | pub const Copy = extern struct { | ||
| 1160 | /// Relative to build root. | ||
| 1161 | dest_path: String, | ||
| 1162 | src_path: LazyPath.Index, | ||
| 1163 | }; | ||
| 1150 | 1164 | ||
| 1151 | pub const Flags = packed struct(u32) { | 1165 | pub const Flags = packed struct(u32) { |
| 1152 | tag: Tag = .update_source_files, | 1166 | tag: Tag = .update_source_files, |
| 1153 | _: u27 = 0, | 1167 | embeds: bool, |
| 1168 | copies: bool, | ||
| 1169 | _: u25 = 0, | ||
| 1154 | }; | 1170 | }; |
| 1155 | }; | 1171 | }; |
| 1156 | 1172 |
lib/std/Build/Step.zig+1-1| ... | @@ -72,7 +72,7 @@ pub fn Type(comptime tag: Tag) type { | ... | @@ -72,7 +72,7 @@ pub fn Type(comptime tag: Tag) type { |
| 72 | .run => Run, | 72 | .run => Run, |
| 73 | .check_file => CheckFile, | 73 | .check_file => CheckFile, |
| 74 | .config_header => ConfigHeader, | 74 | .config_header => ConfigHeader, |
| 75 | .objcopy => ObjCopy, | 75 | .obj_copy => ObjCopy, |
| 76 | .options => Options, | 76 | .options => Options, |
| 77 | }; | 77 | }; |
| 78 | } | 78 | } |
lib/std/Build/Step/ObjCopy.zig+31-148| ... | @@ -1,17 +1,26 @@ | ... | @@ -1,17 +1,26 @@ |
| 1 | const std = @import("std"); | ||
| 2 | const ObjCopy = @This(); | 1 | const ObjCopy = @This(); |
| 3 | 2 | ||
| 4 | const Allocator = std.mem.Allocator; | 3 | const std = @import("std"); |
| 5 | const ArenaAllocator = std.heap.ArenaAllocator; | ||
| 6 | const File = std.Io.File; | ||
| 7 | const InstallDir = std.Build.InstallDir; | ||
| 8 | const Step = std.Build.Step; | 4 | const Step = std.Build.Step; |
| 9 | const elf = std.elf; | ||
| 10 | const fs = std.fs; | ||
| 11 | const sort = std.sort; | ||
| 12 | const Configuration = std.Build.Configuration; | 5 | const Configuration = std.Build.Configuration; |
| 13 | 6 | ||
| 14 | pub const base_tag: Step.Tag = .objcopy; | 7 | step: Step, |
| 8 | input_file: std.Build.LazyPath, | ||
| 9 | basename: []const u8, | ||
| 10 | output_file: Configuration.GeneratedFileIndex, | ||
| 11 | output_file_debug: Configuration.OptionalGeneratedFileIndex, | ||
| 12 | |||
| 13 | format: ?RawFormat, | ||
| 14 | only_section: ?[]const u8, | ||
| 15 | pad_to: ?u64, | ||
| 16 | strip: Strip, | ||
| 17 | compress_debug: bool, | ||
| 18 | |||
| 19 | add_section: ?AddSection, | ||
| 20 | set_section_alignment: ?SetSectionAlignment, | ||
| 21 | set_section_flags: ?SetSectionFlags, | ||
| 22 | |||
| 23 | pub const base_tag: Step.Tag = .obj_copy; | ||
| 15 | 24 | ||
| 16 | pub const RawFormat = enum { | 25 | pub const RawFormat = enum { |
| 17 | bin, | 26 | bin, |
| ... | @@ -28,28 +37,20 @@ pub const Strip = enum { | ... | @@ -28,28 +37,20 @@ pub const Strip = enum { |
| 28 | pub const SectionFlags = packed struct { | 37 | pub const SectionFlags = packed struct { |
| 29 | /// add SHF_ALLOC | 38 | /// add SHF_ALLOC |
| 30 | alloc: bool = false, | 39 | alloc: bool = false, |
| 31 | |||
| 32 | /// if section is SHT_NOBITS, set SHT_PROGBITS, otherwise do nothing | 40 | /// if section is SHT_NOBITS, set SHT_PROGBITS, otherwise do nothing |
| 33 | contents: bool = false, | 41 | contents: bool = false, |
| 34 | |||
| 35 | /// if section is SHT_NOBITS, set SHT_PROGBITS, otherwise do nothing (same as contents) | 42 | /// if section is SHT_NOBITS, set SHT_PROGBITS, otherwise do nothing (same as contents) |
| 36 | load: bool = false, | 43 | load: bool = false, |
| 37 | |||
| 38 | /// readonly: clear default SHF_WRITE flag | 44 | /// readonly: clear default SHF_WRITE flag |
| 39 | readonly: bool = false, | 45 | readonly: bool = false, |
| 40 | |||
| 41 | /// add SHF_EXECINSTR | 46 | /// add SHF_EXECINSTR |
| 42 | code: bool = false, | 47 | code: bool = false, |
| 43 | |||
| 44 | /// add SHF_EXCLUDE | 48 | /// add SHF_EXCLUDE |
| 45 | exclude: bool = false, | 49 | exclude: bool = false, |
| 46 | |||
| 47 | /// add SHF_X86_64_LARGE. Fatal error if target is not x86_64 | 50 | /// add SHF_X86_64_LARGE. Fatal error if target is not x86_64 |
| 48 | large: bool = false, | 51 | large: bool = false, |
| 49 | |||
| 50 | /// add SHF_MERGE | 52 | /// add SHF_MERGE |
| 51 | merge: bool = false, | 53 | merge: bool = false, |
| 52 | |||
| 53 | /// add SHF_STRINGS | 54 | /// add SHF_STRINGS |
| 54 | strings: bool = false, | 55 | strings: bool = false, |
| 55 | }; | 56 | }; |
| ... | @@ -69,22 +70,6 @@ pub const SetSectionFlags = struct { | ... | @@ -69,22 +70,6 @@ pub const SetSectionFlags = struct { |
| 69 | flags: SectionFlags, | 70 | flags: SectionFlags, |
| 70 | }; | 71 | }; |
| 71 | 72 | ||
| 72 | step: Step, | ||
| 73 | input_file: std.Build.LazyPath, | ||
| 74 | basename: []const u8, | ||
| 75 | output_file: Configuration.GeneratedFileIndex, | ||
| 76 | output_file_debug: Configuration.OptionalGeneratedFileIndex, | ||
| 77 | |||
| 78 | format: ?RawFormat, | ||
| 79 | only_section: ?[]const u8, | ||
| 80 | pad_to: ?u64, | ||
| 81 | strip: Strip, | ||
| 82 | compress_debug: bool, | ||
| 83 | |||
| 84 | add_section: ?AddSection, | ||
| 85 | set_section_alignment: ?SetSectionAlignment, | ||
| 86 | set_section_flags: ?SetSectionFlags, | ||
| 87 | |||
| 88 | pub const Options = struct { | 73 | pub const Options = struct { |
| 89 | basename: ?[]const u8 = null, | 74 | basename: ?[]const u8 = null, |
| 90 | format: ?RawFormat = null, | 75 | format: ?RawFormat = null, |
| ... | @@ -111,20 +96,19 @@ pub fn create( | ... | @@ -111,20 +96,19 @@ pub fn create( |
| 111 | ) *ObjCopy { | 96 | ) *ObjCopy { |
| 112 | const graph = owner.graph; | 97 | const graph = owner.graph; |
| 113 | const arena = graph.arena; | 98 | const arena = graph.arena; |
| 114 | 99 | const obj_copy = graph.create(ObjCopy); | |
| 115 | const objcopy = arena.create(ObjCopy) catch @panic("OOM"); | 100 | obj_copy.* = .{ |
| 116 | objcopy.* = ObjCopy{ | 101 | .step = .init(.{ |
| 117 | .step = Step.init(.{ | ||
| 118 | .tag = base_tag, | 102 | .tag = base_tag, |
| 119 | .name = owner.fmt("objcopy {f}", .{input_file.fmt(graph)}), | 103 | .name = owner.fmt("objcopy {f}", .{input_file.fmt(graph)}), |
| 120 | .owner = owner, | 104 | .owner = owner, |
| 121 | .makeFn = make, | ||
| 122 | }), | 105 | }), |
| 123 | .input_file = input_file, | 106 | .input_file = input_file, |
| 124 | .basename = options.basename orelse std.fmt.allocPrint("{f}", .{input_file.fmt(graph)}) catch @panic("OOM"), | 107 | .basename = options.basename orelse |
| 125 | .output_file = graph.addGeneratedFile(&objcopy.step), | 108 | std.fmt.allocPrint(arena, "{f}", .{input_file.fmt(graph)}) catch @panic("OOM"), |
| 109 | .output_file = graph.addGeneratedFile(&obj_copy.step), | ||
| 126 | .output_file_debug = if (options.strip != .none and options.extract_to_separate_file) | 110 | .output_file_debug = if (options.strip != .none and options.extract_to_separate_file) |
| 127 | .init(graph.addGeneratedFile(&objcopy.step)) | 111 | .init(graph.addGeneratedFile(&obj_copy.step)) |
| 128 | else | 112 | else |
| 129 | .none, | 113 | .none, |
| 130 | .format = options.format, | 114 | .format = options.format, |
| ... | @@ -136,115 +120,14 @@ pub fn create( | ... | @@ -136,115 +120,14 @@ pub fn create( |
| 136 | .set_section_alignment = options.set_section_alignment, | 120 | .set_section_alignment = options.set_section_alignment, |
| 137 | .set_section_flags = options.set_section_flags, | 121 | .set_section_flags = options.set_section_flags, |
| 138 | }; | 122 | }; |
| 139 | input_file.addStepDependencies(&objcopy.step); | 123 | input_file.addStepDependencies(&obj_copy.step); |
| 140 | return objcopy; | 124 | return obj_copy; |
| 141 | } | 125 | } |
| 142 | 126 | ||
| 143 | pub fn getOutput(objcopy: *const ObjCopy) std.Build.LazyPath { | 127 | pub fn getOutput(obj_copy: *const ObjCopy) std.Build.LazyPath { |
| 144 | return .{ .generated = .{ .index = objcopy.output_file } }; | 128 | return .{ .generated = .{ .index = obj_copy.output_file } }; |
| 145 | } | ||
| 146 | pub fn getOutputSeparatedDebug(objcopy: *const ObjCopy) ?std.Build.LazyPath { | ||
| 147 | return if (objcopy.output_file_debug.unwrap()) |index| .{ .generated = .{ .index = index } } else null; | ||
| 148 | } | 129 | } |
| 149 | 130 | ||
| 150 | fn make(step: *Step, options: Step.MakeOptions) !void { | 131 | pub fn getOutputSeparatedDebug(obj_copy: *const ObjCopy) ?std.Build.LazyPath { |
| 151 | const prog_node = options.progress_node; | 132 | return if (obj_copy.output_file_debug.unwrap()) |index| .{ .generated = .{ .index = index } } else null; |
| 152 | const b = step.owner; | ||
| 153 | const io = b.graph.io; | ||
| 154 | const objcopy: *ObjCopy = @fieldParentPtr("step", step); | ||
| 155 | try step.singleUnchangingWatchInput(objcopy.input_file); | ||
| 156 | |||
| 157 | var man = b.graph.cache.obtain(); | ||
| 158 | defer man.deinit(); | ||
| 159 | |||
| 160 | const full_src_path = objcopy.input_file.getPath2(b, step); | ||
| 161 | _ = try man.addFile(full_src_path, null); | ||
| 162 | man.hash.addOptionalBytes(objcopy.only_section); | ||
| 163 | man.hash.addOptional(objcopy.pad_to); | ||
| 164 | man.hash.addOptional(objcopy.format); | ||
| 165 | man.hash.add(objcopy.compress_debug); | ||
| 166 | man.hash.add(objcopy.strip); | ||
| 167 | man.hash.add(objcopy.output_file_debug != null); | ||
| 168 | |||
| 169 | if (try step.cacheHit(&man)) { | ||
| 170 | // Cache hit, skip subprocess execution. | ||
| 171 | const digest = man.final(); | ||
| 172 | objcopy.output_file.path = try b.cache_root.join(b.allocator, &.{ | ||
| 173 | "o", &digest, objcopy.basename, | ||
| 174 | }); | ||
| 175 | if (objcopy.output_file_debug) |*file| { | ||
| 176 | file.path = try b.cache_root.join(b.allocator, &.{ | ||
| 177 | "o", &digest, b.fmt("{s}.debug", .{objcopy.basename}), | ||
| 178 | }); | ||
| 179 | } | ||
| 180 | return; | ||
| 181 | } | ||
| 182 | |||
| 183 | const digest = man.final(); | ||
| 184 | const cache_path = "o" ++ fs.path.sep_str ++ digest; | ||
| 185 | const full_dest_path = try b.cache_root.join(b.allocator, &.{ cache_path, objcopy.basename }); | ||
| 186 | const full_dest_path_debug = try b.cache_root.join(b.allocator, &.{ cache_path, b.fmt("{s}.debug", .{objcopy.basename}) }); | ||
| 187 | b.cache_root.handle.createDirPath(io, cache_path) catch |err| { | ||
| 188 | return step.fail("unable to make path {s}: {s}", .{ cache_path, @errorName(err) }); | ||
| 189 | }; | ||
| 190 | |||
| 191 | var argv = std.array_list.Managed([]const u8).init(b.allocator); | ||
| 192 | try argv.appendSlice(&.{ b.graph.zig_exe, "objcopy" }); | ||
| 193 | |||
| 194 | if (objcopy.only_section) |only_section| { | ||
| 195 | try argv.appendSlice(&.{ "-j", only_section }); | ||
| 196 | } | ||
| 197 | switch (objcopy.strip) { | ||
| 198 | .none => {}, | ||
| 199 | .debug => try argv.appendSlice(&.{"--strip-debug"}), | ||
| 200 | .debug_and_symbols => try argv.appendSlice(&.{"--strip-all"}), | ||
| 201 | } | ||
| 202 | if (objcopy.pad_to) |pad_to| { | ||
| 203 | try argv.appendSlice(&.{ "--pad-to", b.fmt("{d}", .{pad_to}) }); | ||
| 204 | } | ||
| 205 | if (objcopy.format) |format| switch (format) { | ||
| 206 | .bin => try argv.appendSlice(&.{ "-O", "binary" }), | ||
| 207 | .hex => try argv.appendSlice(&.{ "-O", "hex" }), | ||
| 208 | .elf => try argv.appendSlice(&.{ "-O", "elf" }), | ||
| 209 | }; | ||
| 210 | if (objcopy.compress_debug) { | ||
| 211 | try argv.appendSlice(&.{"--compress-debug-sections"}); | ||
| 212 | } | ||
| 213 | if (objcopy.output_file_debug != null) { | ||
| 214 | try argv.appendSlice(&.{b.fmt("--extract-to={s}", .{full_dest_path_debug})}); | ||
| 215 | } | ||
| 216 | if (objcopy.add_section) |section| { | ||
| 217 | try argv.append("--add-section"); | ||
| 218 | try argv.appendSlice(&.{b.fmt("{s}={s}", .{ section.section_name, section.file_path.getPath2(b, step) })}); | ||
| 219 | } | ||
| 220 | if (objcopy.set_section_alignment) |set_align| { | ||
| 221 | try argv.append("--set-section-alignment"); | ||
| 222 | try argv.appendSlice(&.{b.fmt("{s}={d}", .{ set_align.section_name, set_align.alignment })}); | ||
| 223 | } | ||
| 224 | if (objcopy.set_section_flags) |set_flags| { | ||
| 225 | const f = set_flags.flags; | ||
| 226 | // trailing comma is allowed | ||
| 227 | try argv.append("--set-section-flags"); | ||
| 228 | try argv.appendSlice(&.{b.fmt("{s}={s}{s}{s}{s}{s}{s}{s}{s}{s}", .{ | ||
| 229 | set_flags.section_name, | ||
| 230 | if (f.alloc) "alloc," else "", | ||
| 231 | if (f.contents) "contents," else "", | ||
| 232 | if (f.load) "load," else "", | ||
| 233 | if (f.readonly) "readonly," else "", | ||
| 234 | if (f.code) "code," else "", | ||
| 235 | if (f.exclude) "exclude," else "", | ||
| 236 | if (f.large) "large," else "", | ||
| 237 | if (f.merge) "merge," else "", | ||
| 238 | if (f.strings) "strings," else "", | ||
| 239 | })}); | ||
| 240 | } | ||
| 241 | |||
| 242 | try argv.appendSlice(&.{ full_src_path, full_dest_path }); | ||
| 243 | |||
| 244 | try argv.append("--listen=-"); | ||
| 245 | _ = try step.evalZigProcess(argv.items, prog_node, false, options.web_server, options.gpa); | ||
| 246 | |||
| 247 | objcopy.output_file.path = full_dest_path; | ||
| 248 | if (objcopy.output_file_debug) |*file| file.path = full_dest_path_debug; | ||
| 249 | try man.writeManifest(); | ||
| 250 | } | 133 | } |
lib/std/Build/Step/Run.zig+2-2| ... | @@ -421,7 +421,7 @@ pub fn addPrefixedOutputDirectoryArg( | ... | @@ -421,7 +421,7 @@ pub fn addPrefixedOutputDirectoryArg( |
| 421 | output.* = .{ | 421 | output.* = .{ |
| 422 | .prefix = graph.dupeString(prefix), | 422 | .prefix = graph.dupeString(prefix), |
| 423 | .basename = graph.dupeString(basename), | 423 | .basename = graph.dupeString(basename), |
| 424 | .generated_file = .{ .step = &run.step }, | 424 | .generated_file = graph.addGeneratedFile(&run.step), |
| 425 | }; | 425 | }; |
| 426 | run.argv.append(arena, .{ .output_directory = output }) catch @panic("OOM"); | 426 | run.argv.append(arena, .{ .output_directory = output }) catch @panic("OOM"); |
| 427 | 427 | ||
| ... | @@ -429,7 +429,7 @@ pub fn addPrefixedOutputDirectoryArg( | ... | @@ -429,7 +429,7 @@ pub fn addPrefixedOutputDirectoryArg( |
| 429 | run.setName(std.fmt.allocPrint(arena, "{s} ({s})", .{ run.step.name, basename }) catch @panic("OOM")); | 429 | run.setName(std.fmt.allocPrint(arena, "{s} ({s})", .{ run.step.name, basename }) catch @panic("OOM")); |
| 430 | } | 430 | } |
| 431 | 431 | ||
| 432 | return .{ .generated = .{ .file = &output.generated_file } }; | 432 | return .{ .generated = .{ .index = output.generated_file } }; |
| 433 | } | 433 | } |
| 434 | 434 | ||
| 435 | pub fn addDirectoryArg(run: *Run, lazy_directory: std.Build.LazyPath) void { | 435 | pub fn addDirectoryArg(run: *Run, lazy_directory: std.Build.LazyPath) void { |
lib/std/Build/Step/TranslateC.zig+1-1| ... | @@ -31,7 +31,7 @@ pub fn create(owner: *std.Build, options: Options) *TranslateC { | ... | @@ -31,7 +31,7 @@ pub fn create(owner: *std.Build, options: Options) *TranslateC { |
| 31 | const graph = owner.graph; | 31 | const graph = owner.graph; |
| 32 | const arena = graph.arena; | 32 | const arena = graph.arena; |
| 33 | const translate_c = arena.create(TranslateC) catch @panic("OOM"); | 33 | const translate_c = arena.create(TranslateC) catch @panic("OOM"); |
| 34 | const source = options.root_source_file.dupe(owner); | 34 | const source = options.root_source_file.dupe(graph); |
| 35 | translate_c.* = .{ | 35 | translate_c.* = .{ |
| 36 | .step = Step.init(.{ | 36 | .step = Step.init(.{ |
| 37 | .tag = base_tag, | 37 | .tag = base_tag, |
lib/std/Build/Step/UpdateSourceFiles.zig+1-48| ... | @@ -29,11 +29,10 @@ pub const Contents = union(enum) { | ... | @@ -29,11 +29,10 @@ pub const Contents = union(enum) { |
| 29 | pub fn create(owner: *std.Build) *UpdateSourceFiles { | 29 | pub fn create(owner: *std.Build) *UpdateSourceFiles { |
| 30 | const usf = owner.allocator.create(UpdateSourceFiles) catch @panic("OOM"); | 30 | const usf = owner.allocator.create(UpdateSourceFiles) catch @panic("OOM"); |
| 31 | usf.* = .{ | 31 | usf.* = .{ |
| 32 | .step = Step.init(.{ | 32 | .step = .init(.{ |
| 33 | .tag = base_tag, | 33 | .tag = base_tag, |
| 34 | .name = "UpdateSourceFiles", | 34 | .name = "UpdateSourceFiles", |
| 35 | .owner = owner, | 35 | .owner = owner, |
| 36 | .makeFn = make, | ||
| 37 | }), | 36 | }), |
| 38 | .output_source_files = .empty, | 37 | .output_source_files = .empty, |
| 39 | }; | 38 | }; |
| ... | @@ -68,49 +67,3 @@ pub fn addBytesToSource(usf: *UpdateSourceFiles, bytes: []const u8, sub_path: [] | ... | @@ -68,49 +67,3 @@ pub fn addBytesToSource(usf: *UpdateSourceFiles, bytes: []const u8, sub_path: [] |
| 68 | .sub_path = sub_path, | 67 | .sub_path = sub_path, |
| 69 | }) catch @panic("OOM"); | 68 | }) catch @panic("OOM"); |
| 70 | } | 69 | } |
| 71 | |||
| 72 | fn make(step: *Step, options: Step.MakeOptions) !void { | ||
| 73 | _ = options; | ||
| 74 | const b = step.owner; | ||
| 75 | const io = b.graph.io; | ||
| 76 | const usf: *UpdateSourceFiles = @fieldParentPtr("step", step); | ||
| 77 | |||
| 78 | var any_miss = false; | ||
| 79 | for (usf.output_source_files.items) |output_source_file| { | ||
| 80 | if (fs.path.dirname(output_source_file.sub_path)) |dirname| { | ||
| 81 | b.build_root.handle.createDirPath(io, dirname) catch |err| { | ||
| 82 | return step.fail("unable to make path '{f}{s}': {t}", .{ b.build_root, dirname, err }); | ||
| 83 | }; | ||
| 84 | } | ||
| 85 | switch (output_source_file.contents) { | ||
| 86 | .bytes => |bytes| { | ||
| 87 | b.build_root.handle.writeFile(io, .{ .sub_path = output_source_file.sub_path, .data = bytes }) catch |err| { | ||
| 88 | return step.fail("unable to write file '{f}{s}': {t}", .{ | ||
| 89 | b.build_root, output_source_file.sub_path, err, | ||
| 90 | }); | ||
| 91 | }; | ||
| 92 | any_miss = true; | ||
| 93 | }, | ||
| 94 | .copy => |file_source| { | ||
| 95 | if (!step.inputs.populated()) try step.addWatchInput(file_source); | ||
| 96 | |||
| 97 | const source_path = file_source.getPath2(b, step); | ||
| 98 | const prev_status = Io.Dir.updateFile( | ||
| 99 | .cwd(), | ||
| 100 | io, | ||
| 101 | source_path, | ||
| 102 | b.build_root.handle, | ||
| 103 | output_source_file.sub_path, | ||
| 104 | .{}, | ||
| 105 | ) catch |err| { | ||
| 106 | return step.fail("unable to update file from '{s}' to '{f}{s}': {t}", .{ | ||
| 107 | source_path, b.build_root, output_source_file.sub_path, err, | ||
| 108 | }); | ||
| 109 | }; | ||
| 110 | any_miss = any_miss or prev_status == .stale; | ||
| 111 | }, | ||
| 112 | } | ||
| 113 | } | ||
| 114 | |||
| 115 | step.result_cached = !any_miss; | ||
| 116 | } |