diff options
Diffstat (limited to 'lib/std/Build/InstallRawStep.zig')
| -rw-r--r-- | lib/std/Build/InstallRawStep.zig | 110 |
1 files changed, 110 insertions, 0 deletions
diff --git a/lib/std/Build/InstallRawStep.zig b/lib/std/Build/InstallRawStep.zig new file mode 100644 index 0000000000..014c44f287 --- /dev/null +++ b/lib/std/Build/InstallRawStep.zig @@ -0,0 +1,110 @@ +//! TODO: Rename this to ObjCopyStep now that it invokes the `zig objcopy` +//! subcommand rather than containing an implementation directly. + +const std = @import("std"); +const InstallRawStep = @This(); + +const Allocator = std.mem.Allocator; +const ArenaAllocator = std.heap.ArenaAllocator; +const ArrayListUnmanaged = std.ArrayListUnmanaged; +const File = std.fs.File; +const InstallDir = std.Build.InstallDir; +const CompileStep = std.Build.CompileStep; +const Step = std.Build.Step; +const elf = std.elf; +const fs = std.fs; +const io = std.io; +const sort = std.sort; + +pub const base_id = .install_raw; + +pub const RawFormat = enum { + bin, + hex, +}; + +step: Step, +builder: *std.Build, +artifact: *CompileStep, +dest_dir: InstallDir, +dest_filename: []const u8, +options: CreateOptions, +output_file: std.Build.GeneratedFile, + +pub const CreateOptions = struct { + format: ?RawFormat = null, + dest_dir: ?InstallDir = null, + only_section: ?[]const u8 = null, + pad_to: ?u64 = null, +}; + +pub fn create( + builder: *std.Build, + artifact: *CompileStep, + dest_filename: []const u8, + options: CreateOptions, +) *InstallRawStep { + const self = builder.allocator.create(InstallRawStep) catch @panic("OOM"); + self.* = InstallRawStep{ + .step = Step.init(.install_raw, builder.fmt("install raw binary {s}", .{artifact.step.name}), builder.allocator, make), + .builder = builder, + .artifact = artifact, + .dest_dir = if (options.dest_dir) |d| d else switch (artifact.kind) { + .obj => unreachable, + .@"test" => unreachable, + .exe, .test_exe => .bin, + .lib => unreachable, + }, + .dest_filename = dest_filename, + .options = options, + .output_file = std.Build.GeneratedFile{ .step = &self.step }, + }; + self.step.dependOn(&artifact.step); + + builder.pushInstalledFile(self.dest_dir, dest_filename); + return self; +} + +pub fn getOutputSource(self: *const InstallRawStep) std.Build.FileSource { + return std.Build.FileSource{ .generated = &self.output_file }; +} + +fn make(step: *Step) !void { + const self = @fieldParentPtr(InstallRawStep, "step", step); + const b = self.builder; + + if (self.artifact.target.getObjectFormat() != .elf) { + std.debug.print("InstallRawStep only works with ELF format.\n", .{}); + return error.InvalidObjectFormat; + } + + const full_src_path = self.artifact.getOutputSource().getPath(b); + const full_dest_path = b.getInstallPath(self.dest_dir, self.dest_filename); + self.output_file.path = full_dest_path; + + try fs.cwd().makePath(b.getInstallPath(self.dest_dir, "")); + + var argv_list = std.ArrayList([]const u8).init(b.allocator); + try argv_list.appendSlice(&.{ b.zig_exe, "objcopy" }); + + if (self.options.only_section) |only_section| { + try argv_list.appendSlice(&.{ "-j", only_section }); + } + if (self.options.pad_to) |pad_to| { + try argv_list.appendSlice(&.{ + "--pad-to", + b.fmt("{d}", .{pad_to}), + }); + } + if (self.options.format) |format| switch (format) { + .bin => try argv_list.appendSlice(&.{ "-O", "binary" }), + .hex => try argv_list.appendSlice(&.{ "-O", "hex" }), + }; + + try argv_list.appendSlice(&.{ full_src_path, full_dest_path }); + _ = try self.builder.execFromStep(argv_list.items, &self.step); +} + +test { + std.testing.refAllDecls(InstallRawStep); +} |
