mirror of
https://github.com/ziglang/zig.git
synced 2025-12-06 14:23:09 +00:00
Breaking API change to std.Build.addConfigHeader. It now uses an options struct. Introduce std.Build.CompileStep.installConfigHeader which also accepts an options struct. This is used to add a generated config file into the set of installed header files for a particular compilation artifact. std.Build.ConfigHeaderStep now additionally supports a "blank" style where a header is generated from scratch. It no longer exposes `output_dir`. Instead it exposes a FileSource via `output_file`. It now additionally accepts an `include_path` option which affects the include path of CompileStep when using the `#include` directive, as well as affecting the default installation subdirectory for header installation purposes. The hash used for the directory to store the generated config file now includes the contents of the generated file. This fixes possible race conditions when generating multiple header files simultaneously. The values hash table is now an array hash map, to preserve order for the "blank" use case. I also took the opportunity to remove output_dir from TranslateCStep and WriteFileStep. This is technically a breaking change, but it was always naughty to access these fields.
130 lines
4.5 KiB
Zig
130 lines
4.5 KiB
Zig
const std = @import("../std.zig");
|
|
const Step = std.Build.Step;
|
|
const CompileStep = std.Build.CompileStep;
|
|
const CheckFileStep = std.Build.CheckFileStep;
|
|
const fs = std.fs;
|
|
const mem = std.mem;
|
|
const CrossTarget = std.zig.CrossTarget;
|
|
|
|
const TranslateCStep = @This();
|
|
|
|
pub const base_id = .translate_c;
|
|
|
|
step: Step,
|
|
builder: *std.Build,
|
|
source: std.Build.FileSource,
|
|
include_dirs: std.ArrayList([]const u8),
|
|
c_macros: std.ArrayList([]const u8),
|
|
out_basename: []const u8,
|
|
target: CrossTarget,
|
|
optimize: std.builtin.OptimizeMode,
|
|
output_file: std.Build.GeneratedFile,
|
|
|
|
pub const Options = struct {
|
|
source_file: std.Build.FileSource,
|
|
target: CrossTarget,
|
|
optimize: std.builtin.OptimizeMode,
|
|
};
|
|
|
|
pub fn create(builder: *std.Build, options: Options) *TranslateCStep {
|
|
const self = builder.allocator.create(TranslateCStep) catch @panic("OOM");
|
|
const source = options.source_file.dupe(builder);
|
|
self.* = TranslateCStep{
|
|
.step = Step.init(.translate_c, "translate-c", builder.allocator, make),
|
|
.builder = builder,
|
|
.source = source,
|
|
.include_dirs = std.ArrayList([]const u8).init(builder.allocator),
|
|
.c_macros = std.ArrayList([]const u8).init(builder.allocator),
|
|
.out_basename = undefined,
|
|
.target = options.target,
|
|
.optimize = options.optimize,
|
|
.output_file = std.Build.GeneratedFile{ .step = &self.step },
|
|
};
|
|
source.addStepDependencies(&self.step);
|
|
return self;
|
|
}
|
|
|
|
pub const AddExecutableOptions = struct {
|
|
name: ?[]const u8 = null,
|
|
version: ?std.builtin.Version = null,
|
|
target: ?CrossTarget = null,
|
|
optimize: ?std.builtin.Mode = null,
|
|
linkage: ?CompileStep.Linkage = null,
|
|
};
|
|
|
|
/// Creates a step to build an executable from the translated source.
|
|
pub fn addExecutable(self: *TranslateCStep, options: AddExecutableOptions) *CompileStep {
|
|
return self.builder.addExecutable(.{
|
|
.root_source_file = .{ .generated = &self.output_file },
|
|
.name = options.name orelse "translated_c",
|
|
.version = options.version,
|
|
.target = options.target orelse self.target,
|
|
.optimize = options.optimize orelse self.optimize,
|
|
.linkage = options.linkage,
|
|
});
|
|
}
|
|
|
|
pub fn addIncludeDir(self: *TranslateCStep, include_dir: []const u8) void {
|
|
self.include_dirs.append(self.builder.dupePath(include_dir)) catch @panic("OOM");
|
|
}
|
|
|
|
pub fn addCheckFile(self: *TranslateCStep, expected_matches: []const []const u8) *CheckFileStep {
|
|
return CheckFileStep.create(self.builder, .{ .generated = &self.output_file }, self.builder.dupeStrings(expected_matches));
|
|
}
|
|
|
|
/// If the value is omitted, it is set to 1.
|
|
/// `name` and `value` need not live longer than the function call.
|
|
pub fn defineCMacro(self: *TranslateCStep, name: []const u8, value: ?[]const u8) void {
|
|
const macro = std.Build.constructCMacro(self.builder.allocator, name, value);
|
|
self.c_macros.append(macro) catch @panic("OOM");
|
|
}
|
|
|
|
/// name_and_value looks like [name]=[value]. If the value is omitted, it is set to 1.
|
|
pub fn defineCMacroRaw(self: *TranslateCStep, name_and_value: []const u8) void {
|
|
self.c_macros.append(self.builder.dupe(name_and_value)) catch @panic("OOM");
|
|
}
|
|
|
|
fn make(step: *Step) !void {
|
|
const self = @fieldParentPtr(TranslateCStep, "step", step);
|
|
|
|
var argv_list = std.ArrayList([]const u8).init(self.builder.allocator);
|
|
try argv_list.append(self.builder.zig_exe);
|
|
try argv_list.append("translate-c");
|
|
try argv_list.append("-lc");
|
|
|
|
try argv_list.append("--enable-cache");
|
|
|
|
if (!self.target.isNative()) {
|
|
try argv_list.append("-target");
|
|
try argv_list.append(try self.target.zigTriple(self.builder.allocator));
|
|
}
|
|
|
|
switch (self.optimize) {
|
|
.Debug => {}, // Skip since it's the default.
|
|
else => try argv_list.append(self.builder.fmt("-O{s}", .{@tagName(self.optimize)})),
|
|
}
|
|
|
|
for (self.include_dirs.items) |include_dir| {
|
|
try argv_list.append("-I");
|
|
try argv_list.append(include_dir);
|
|
}
|
|
|
|
for (self.c_macros.items) |c_macro| {
|
|
try argv_list.append("-D");
|
|
try argv_list.append(c_macro);
|
|
}
|
|
|
|
try argv_list.append(self.source.getPath(self.builder));
|
|
|
|
const output_path_nl = try self.builder.execFromStep(argv_list.items, &self.step);
|
|
const output_path = mem.trimRight(u8, output_path_nl, "\r\n");
|
|
|
|
self.out_basename = fs.path.basename(output_path);
|
|
const output_dir = fs.path.dirname(output_path).?;
|
|
|
|
self.output_file.path = try fs.path.join(
|
|
self.builder.allocator,
|
|
&[_][]const u8{ output_dir, self.out_basename },
|
|
);
|
|
}
|