Files
zig/lib/std/Build/Step/ObjCopy.zig
2026-05-08 14:31:37 -07:00

127 lines
4.1 KiB
Zig

const ObjCopy = @This();
const std = @import("std");
const Step = std.Build.Step;
const Configuration = std.Build.Configuration;
step: Step,
input_file: std.Build.LazyPath,
basename: Configuration.OptionalString,
output_file: Configuration.GeneratedFileIndex,
debug_file: ?DebugFile,
format: ?Format,
only_section: Configuration.OptionalString,
pad_to: ?u64,
strip: Strip,
compress_debug: bool,
add_sections: std.ArrayList(AddSection) = .empty,
update_sections: std.ArrayList(Configuration.Step.ObjCopy.UpdateSection) = .empty,
pub const base_tag: Step.Tag = .obj_copy;
pub const Format = enum { binary, hex, elf };
pub const Strip = Configuration.Step.ObjCopy.Strip;
pub const SectionFlags = Configuration.Step.ObjCopy.SectionFlags;
pub const AddSection = struct {
section_name: Configuration.String,
file_path: std.Build.LazyPath,
};
pub const DebugFile = struct {
basename: Configuration.OptionalString,
output_file: Configuration.GeneratedFileIndex,
};
pub const Options = struct {
basename: ?[]const u8 = null,
format: ?Format = null,
only_section: ?[]const u8 = null,
pad_to: ?u64 = null,
compress_debug: bool = false,
strip: Strip = .none,
/// Put the stripped out debug sections in a separate file.
/// note: the `basename` is baked into the elf file to specify the link to the separate debug file.
/// see https://sourceware.org/gdb/onlinedocs/gdb/Separate-Debug-Files.html
///
/// Makes `getOutputSeparatedDebug` return non-null.
separate_debug_file: ?SeparateDebugFile = null,
pub const SeparateDebugFile = struct {
basename: ?[]const u8,
};
};
pub fn create(owner: *std.Build, input_file: std.Build.LazyPath, options: Options) *ObjCopy {
const graph = owner.graph;
const wc = &graph.wip_configuration;
const oc = graph.create(ObjCopy);
oc.* = .{
.step = .init(.{
.tag = base_tag,
.name = owner.fmt("objcopy {f}", .{input_file.fmt(graph)}),
.owner = owner,
}),
.input_file = input_file,
.basename = if (options.basename) |s| .init(wc.addString(s) catch @panic("OOM")) else .none,
.output_file = graph.addGeneratedFile(&oc.step),
.debug_file = if (options.separate_debug_file) |df| .{
.basename = if (df.basename) |s| .init(wc.addString(s) catch @panic("OOM")) else .none,
.output_file = graph.addGeneratedFile(&oc.step),
} else null,
.format = options.format,
.only_section = if (options.only_section) |s| .init(wc.addString(s) catch @panic("OOM")) else .none,
.pad_to = options.pad_to,
.strip = options.strip,
.compress_debug = options.compress_debug,
};
input_file.addStepDependencies(&oc.step);
return oc;
}
pub const UpdateSectionOptions = struct {
alignment: ?std.mem.Alignment = null,
flags: SectionFlags = .default,
};
pub fn updateSection(oc: *ObjCopy, section_name: []const u8, options: UpdateSectionOptions) void {
const graph = oc.owner.graph;
const arena = graph.arena;
const wc = &graph.wip_configuration;
oc.update_sections.append(arena, .{
.flags = .{
.section_flags = options.flags,
.alignment = .init(options.alignment),
},
.section_name = wc.addString(section_name) catch @panic("OOM"),
}) catch @panic("OOM");
}
pub const AddSectionOptions = struct {
file_path: std.Build.LazyPath,
};
pub fn addSection(oc: *ObjCopy, section_name: []const u8, options: AddSectionOptions) void {
const graph = oc.owner.graph;
const arena = graph.arena;
const wc = &graph.wip_configuration;
oc.add_sections.append(arena, .{
.section_name = wc.addString(section_name) catch @panic("OOM"),
.file_path = options.file_path,
}) catch @panic("OOM");
options.file_path.addStepDependencies(&oc.step);
}
pub fn getOutput(oc: *const ObjCopy) std.Build.LazyPath {
return .{ .generated = .{ .index = oc.output_file } };
}
pub fn getOutputSeparatedDebug(oc: *const ObjCopy) ?std.Build.LazyPath {
const df = oc.debug_file orelse return null;
return .{ .generated = .{ .index = df.output_file } };
}