zig/lib/std/build/translate_c.zig
Andrew Kelley dbe4d72bcf
separate std.Target and std.zig.CrossTarget
Zig now supports a more fine-grained sense of what is native and what is
not. Some examples:

This is now allowed:
-target native

Different OS but native CPU, default Windows C ABI:
-target native-windows
This could be useful for example when running in Wine.

Different CPU but native OS, native C ABI.
-target x86_64-native -mcpu=skylake

Different C ABI but otherwise native target:
-target native-native-musl
-target native-native-gnu

Lots of breaking changes to related std lib APIs.
Calls to getOs() will need to be changed to getOsTag().
Calls to getArch() will need to be changed to getCpuArch().

Usage of Target.Cross and Target.Native need to be updated to use
CrossTarget API.

`std.build.Builder.standardTargetOptions` is changed to accept its
parameters as a struct with default values. It now has the ability to
specify a whitelist of targets allowed, as well as the default target.
Rather than two different ways of collecting the target, it's now always
a string that is validated, and prints helpful diagnostics for invalid
targets. This feature should now be actually useful, and contributions
welcome to further improve the user experience.

`std.build.LibExeObjStep.setTheTarget` is removed.
`std.build.LibExeObjStep.setTarget` is updated to take a CrossTarget
parameter.

`std.build.LibExeObjStep.setTargetGLibC` is removed. glibc versions are
handled in the CrossTarget API and can be specified with the `-target`
triple.

`std.builtin.Version` gains a `format` method.
2020-02-28 14:51:54 -05:00

86 lines
3.2 KiB
Zig

const std = @import("../std.zig");
const build = std.build;
const Step = build.Step;
const Builder = build.Builder;
const WriteFileStep = build.WriteFileStep;
const LibExeObjStep = build.LibExeObjStep;
const CheckFileStep = build.CheckFileStep;
const fs = std.fs;
const mem = std.mem;
const CrossTarget = std.zig.CrossTarget;
pub const TranslateCStep = struct {
step: Step,
builder: *Builder,
source: build.FileSource,
output_dir: ?[]const u8,
out_basename: []const u8,
target: CrossTarget = CrossTarget{},
pub fn create(builder: *Builder, source: build.FileSource) *TranslateCStep {
const self = builder.allocator.create(TranslateCStep) catch unreachable;
self.* = TranslateCStep{
.step = Step.init("translate-c", builder.allocator, make),
.builder = builder,
.source = source,
.output_dir = null,
.out_basename = undefined,
};
source.addStepDependencies(&self.step);
return self;
}
/// Unless setOutputDir was called, this function must be called only in
/// the make step, from a step that has declared a dependency on this one.
/// To run an executable built with zig build, use `run`, or create an install step and invoke it.
pub fn getOutputPath(self: *TranslateCStep) []const u8 {
return fs.path.join(
self.builder.allocator,
&[_][]const u8{ self.output_dir.?, self.out_basename },
) catch unreachable;
}
pub fn setTarget(self: *TranslateCStep, target: CrossTarget) void {
self.target = target;
}
/// Creates a step to build an executable from the translated source.
pub fn addExecutable(self: *TranslateCStep) *LibExeObjStep {
return self.builder.addExecutableSource("translated_c", @as(build.FileSource, .{ .translate_c = self }));
}
pub fn addCheckFile(self: *TranslateCStep, expected_matches: []const []const u8) *CheckFileStep {
return CheckFileStep.create(self.builder, .{ .translate_c = self }, expected_matches);
}
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("--cache");
try argv_list.append("on");
if (!self.target.isNative()) {
try argv_list.append("-target");
try argv_list.append(try self.target.zigTriple(self.builder.allocator));
}
try argv_list.append(self.source.getPath(self.builder));
const output_path_nl = try self.builder.execFromStep(argv_list.toSliceConst(), &self.step);
const output_path = mem.trimRight(u8, output_path_nl, "\r\n");
self.out_basename = fs.path.basename(output_path);
if (self.output_dir) |output_dir| {
const full_dest = try fs.path.join(self.builder.allocator, &[_][]const u8{ output_dir, self.out_basename });
try self.builder.updateFile(output_path, full_dest);
} else {
self.output_dir = fs.path.dirname(output_path).?;
}
}
};