mirror of
https://github.com/ziglang/zig.git
synced 2025-02-16 01:20:18 +00:00
self-hosted: manually parse args
This commit is contained in:
parent
c3d8b1ffeb
commit
7c1dbfab72
@ -14,7 +14,6 @@ fn traitFnWorkaround(comptime T: type) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub const TraitFn = @TypeOf(traitFnWorkaround);
|
pub const TraitFn = @TypeOf(traitFnWorkaround);
|
||||||
///
|
|
||||||
|
|
||||||
//////Trait generators
|
//////Trait generators
|
||||||
|
|
||||||
@ -55,7 +54,6 @@ test "std.meta.trait.multiTrait" {
|
|||||||
testing.expect(!isVector(u8));
|
testing.expect(!isVector(u8));
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
|
||||||
pub fn hasFn(comptime name: []const u8) TraitFn {
|
pub fn hasFn(comptime name: []const u8) TraitFn {
|
||||||
const Closure = struct {
|
const Closure = struct {
|
||||||
pub fn trait(comptime T: type) bool {
|
pub fn trait(comptime T: type) bool {
|
||||||
@ -79,7 +77,6 @@ test "std.meta.trait.hasFn" {
|
|||||||
testing.expect(!hasFn("useless")(u8));
|
testing.expect(!hasFn("useless")(u8));
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
|
||||||
pub fn hasField(comptime name: []const u8) TraitFn {
|
pub fn hasField(comptime name: []const u8) TraitFn {
|
||||||
const Closure = struct {
|
const Closure = struct {
|
||||||
pub fn trait(comptime T: type) bool {
|
pub fn trait(comptime T: type) bool {
|
||||||
@ -113,7 +110,6 @@ test "std.meta.trait.hasField" {
|
|||||||
testing.expect(!hasField("value")(u8));
|
testing.expect(!hasField("value")(u8));
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
|
||||||
pub fn is(comptime id: builtin.TypeId) TraitFn {
|
pub fn is(comptime id: builtin.TypeId) TraitFn {
|
||||||
const Closure = struct {
|
const Closure = struct {
|
||||||
pub fn trait(comptime T: type) bool {
|
pub fn trait(comptime T: type) bool {
|
||||||
@ -131,7 +127,6 @@ test "std.meta.trait.is" {
|
|||||||
testing.expect(!is(builtin.TypeId.Optional)(anyerror));
|
testing.expect(!is(builtin.TypeId.Optional)(anyerror));
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
|
||||||
pub fn isPtrTo(comptime id: builtin.TypeId) TraitFn {
|
pub fn isPtrTo(comptime id: builtin.TypeId) TraitFn {
|
||||||
const Closure = struct {
|
const Closure = struct {
|
||||||
pub fn trait(comptime T: type) bool {
|
pub fn trait(comptime T: type) bool {
|
||||||
@ -173,7 +168,6 @@ test "std.meta.trait.isExtern" {
|
|||||||
testing.expect(!isExtern(u8));
|
testing.expect(!isExtern(u8));
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
|
||||||
pub fn isPacked(comptime T: type) bool {
|
pub fn isPacked(comptime T: type) bool {
|
||||||
const Packed = builtin.TypeInfo.ContainerLayout.Packed;
|
const Packed = builtin.TypeInfo.ContainerLayout.Packed;
|
||||||
const info = @typeInfo(T);
|
const info = @typeInfo(T);
|
||||||
@ -194,7 +188,6 @@ test "std.meta.trait.isPacked" {
|
|||||||
testing.expect(!isPacked(u8));
|
testing.expect(!isPacked(u8));
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
|
||||||
pub fn isUnsignedInt(comptime T: type) bool {
|
pub fn isUnsignedInt(comptime T: type) bool {
|
||||||
return switch (@typeId(T)) {
|
return switch (@typeId(T)) {
|
||||||
builtin.TypeId.Int => !@typeInfo(T).Int.is_signed,
|
builtin.TypeId.Int => !@typeInfo(T).Int.is_signed,
|
||||||
@ -209,7 +202,6 @@ test "isUnsignedInt" {
|
|||||||
testing.expect(isUnsignedInt(f64) == false);
|
testing.expect(isUnsignedInt(f64) == false);
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
|
||||||
pub fn isSignedInt(comptime T: type) bool {
|
pub fn isSignedInt(comptime T: type) bool {
|
||||||
return switch (@typeId(T)) {
|
return switch (@typeId(T)) {
|
||||||
builtin.TypeId.ComptimeInt => true,
|
builtin.TypeId.ComptimeInt => true,
|
||||||
@ -225,7 +217,6 @@ test "isSignedInt" {
|
|||||||
testing.expect(isSignedInt(f64) == false);
|
testing.expect(isSignedInt(f64) == false);
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
|
||||||
pub fn isSingleItemPtr(comptime T: type) bool {
|
pub fn isSingleItemPtr(comptime T: type) bool {
|
||||||
if (comptime is(builtin.TypeId.Pointer)(T)) {
|
if (comptime is(builtin.TypeId.Pointer)(T)) {
|
||||||
const info = @typeInfo(T);
|
const info = @typeInfo(T);
|
||||||
@ -241,7 +232,6 @@ test "std.meta.trait.isSingleItemPtr" {
|
|||||||
testing.expect(!isSingleItemPtr(@TypeOf(array[0..1])));
|
testing.expect(!isSingleItemPtr(@TypeOf(array[0..1])));
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
|
||||||
pub fn isManyItemPtr(comptime T: type) bool {
|
pub fn isManyItemPtr(comptime T: type) bool {
|
||||||
if (comptime is(builtin.TypeId.Pointer)(T)) {
|
if (comptime is(builtin.TypeId.Pointer)(T)) {
|
||||||
const info = @typeInfo(T);
|
const info = @typeInfo(T);
|
||||||
@ -258,7 +248,6 @@ test "std.meta.trait.isManyItemPtr" {
|
|||||||
testing.expect(!isManyItemPtr(@TypeOf(array[0..1])));
|
testing.expect(!isManyItemPtr(@TypeOf(array[0..1])));
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
|
||||||
pub fn isSlice(comptime T: type) bool {
|
pub fn isSlice(comptime T: type) bool {
|
||||||
if (comptime is(builtin.TypeId.Pointer)(T)) {
|
if (comptime is(builtin.TypeId.Pointer)(T)) {
|
||||||
const info = @typeInfo(T);
|
const info = @typeInfo(T);
|
||||||
@ -274,7 +263,6 @@ test "std.meta.trait.isSlice" {
|
|||||||
testing.expect(!isSlice(@TypeOf(&array[0])));
|
testing.expect(!isSlice(@TypeOf(&array[0])));
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
|
||||||
pub fn isIndexable(comptime T: type) bool {
|
pub fn isIndexable(comptime T: type) bool {
|
||||||
if (comptime is(builtin.TypeId.Pointer)(T)) {
|
if (comptime is(builtin.TypeId.Pointer)(T)) {
|
||||||
const info = @typeInfo(T);
|
const info = @typeInfo(T);
|
||||||
@ -297,7 +285,6 @@ test "std.meta.trait.isIndexable" {
|
|||||||
testing.expect(!isIndexable(meta.Child(@TypeOf(slice))));
|
testing.expect(!isIndexable(meta.Child(@TypeOf(slice))));
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
|
||||||
pub fn isNumber(comptime T: type) bool {
|
pub fn isNumber(comptime T: type) bool {
|
||||||
return switch (@typeId(T)) {
|
return switch (@typeId(T)) {
|
||||||
builtin.TypeId.Int, builtin.TypeId.Float, builtin.TypeId.ComptimeInt, builtin.TypeId.ComptimeFloat => true,
|
builtin.TypeId.Int, builtin.TypeId.Float, builtin.TypeId.ComptimeInt, builtin.TypeId.ComptimeFloat => true,
|
||||||
|
@ -1,293 +0,0 @@
|
|||||||
const std = @import("std");
|
|
||||||
const debug = std.debug;
|
|
||||||
const testing = std.testing;
|
|
||||||
const mem = std.mem;
|
|
||||||
|
|
||||||
const Allocator = mem.Allocator;
|
|
||||||
const ArrayList = std.ArrayList;
|
|
||||||
const StringHashMap = std.StringHashMap;
|
|
||||||
|
|
||||||
fn trimStart(slice: []const u8, ch: u8) []const u8 {
|
|
||||||
var i: usize = 0;
|
|
||||||
for (slice) |b| {
|
|
||||||
if (b != '-') break;
|
|
||||||
i += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return slice[i..];
|
|
||||||
}
|
|
||||||
|
|
||||||
fn argInAllowedSet(maybe_set: ?[]const []const u8, arg: []const u8) bool {
|
|
||||||
if (maybe_set) |set| {
|
|
||||||
for (set) |possible| {
|
|
||||||
if (mem.eql(u8, arg, possible)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Modifies the current argument index during iteration
|
|
||||||
fn readFlagArguments(allocator: *Allocator, args: []const []const u8, required: usize, allowed_set: ?[]const []const u8, index: *usize) !FlagArg {
|
|
||||||
switch (required) {
|
|
||||||
0 => return FlagArg{ .None = undefined }, // TODO: Required to force non-tag but value?
|
|
||||||
1 => {
|
|
||||||
if (index.* + 1 >= args.len) {
|
|
||||||
return error.MissingFlagArguments;
|
|
||||||
}
|
|
||||||
|
|
||||||
index.* += 1;
|
|
||||||
const arg = args[index.*];
|
|
||||||
|
|
||||||
if (!argInAllowedSet(allowed_set, arg)) {
|
|
||||||
return error.ArgumentNotInAllowedSet;
|
|
||||||
}
|
|
||||||
|
|
||||||
return FlagArg{ .Single = arg };
|
|
||||||
},
|
|
||||||
else => |needed| {
|
|
||||||
var extra = ArrayList([]const u8).init(allocator);
|
|
||||||
errdefer extra.deinit();
|
|
||||||
|
|
||||||
var j: usize = 0;
|
|
||||||
while (j < needed) : (j += 1) {
|
|
||||||
if (index.* + 1 >= args.len) {
|
|
||||||
return error.MissingFlagArguments;
|
|
||||||
}
|
|
||||||
|
|
||||||
index.* += 1;
|
|
||||||
const arg = args[index.*];
|
|
||||||
|
|
||||||
if (!argInAllowedSet(allowed_set, arg)) {
|
|
||||||
return error.ArgumentNotInAllowedSet;
|
|
||||||
}
|
|
||||||
|
|
||||||
try extra.append(arg);
|
|
||||||
}
|
|
||||||
|
|
||||||
return FlagArg{ .Many = extra };
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const HashMapFlags = StringHashMap(FlagArg);
|
|
||||||
|
|
||||||
// A store for querying found flags and positional arguments.
|
|
||||||
pub const Args = struct {
|
|
||||||
flags: HashMapFlags,
|
|
||||||
positionals: ArrayList([]const u8),
|
|
||||||
|
|
||||||
pub fn parse(allocator: *Allocator, comptime spec: []const Flag, args: []const []const u8) !Args {
|
|
||||||
var parsed = Args{
|
|
||||||
.flags = HashMapFlags.init(allocator),
|
|
||||||
.positionals = ArrayList([]const u8).init(allocator),
|
|
||||||
};
|
|
||||||
|
|
||||||
var i: usize = 0;
|
|
||||||
next: while (i < args.len) : (i += 1) {
|
|
||||||
const arg = args[i];
|
|
||||||
|
|
||||||
if (arg.len != 0 and arg[0] == '-') {
|
|
||||||
// TODO: hashmap, although the linear scan is okay for small argument sets as is
|
|
||||||
for (spec) |flag| {
|
|
||||||
if (mem.eql(u8, arg, flag.name)) {
|
|
||||||
const flag_name_trimmed = trimStart(flag.name, '-');
|
|
||||||
const flag_args = readFlagArguments(allocator, args, flag.required, flag.allowed_set, &i) catch |err| {
|
|
||||||
switch (err) {
|
|
||||||
error.ArgumentNotInAllowedSet => {
|
|
||||||
std.debug.warn("argument '{}' is invalid for flag '{}'\n", .{ args[i], arg });
|
|
||||||
std.debug.warn("allowed options are ", .{});
|
|
||||||
for (flag.allowed_set.?) |possible| {
|
|
||||||
std.debug.warn("'{}' ", .{possible});
|
|
||||||
}
|
|
||||||
std.debug.warn("\n", .{});
|
|
||||||
},
|
|
||||||
error.MissingFlagArguments => {
|
|
||||||
std.debug.warn("missing argument for flag: {}\n", .{arg});
|
|
||||||
},
|
|
||||||
else => {},
|
|
||||||
}
|
|
||||||
|
|
||||||
return err;
|
|
||||||
};
|
|
||||||
|
|
||||||
if (flag.mergable) {
|
|
||||||
var prev = if (parsed.flags.get(flag_name_trimmed)) |entry| entry.value.Many else ArrayList([]const u8).init(allocator);
|
|
||||||
|
|
||||||
// MergeN creation disallows 0 length flag entry (doesn't make sense)
|
|
||||||
switch (flag_args) {
|
|
||||||
.None => unreachable,
|
|
||||||
.Single => |inner| try prev.append(inner),
|
|
||||||
.Many => |inner| try prev.appendSlice(inner.toSliceConst()),
|
|
||||||
}
|
|
||||||
|
|
||||||
_ = try parsed.flags.put(flag_name_trimmed, FlagArg{ .Many = prev });
|
|
||||||
} else {
|
|
||||||
_ = try parsed.flags.put(flag_name_trimmed, flag_args);
|
|
||||||
}
|
|
||||||
|
|
||||||
continue :next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Better errors with context, global error state and return is sufficient.
|
|
||||||
std.debug.warn("could not match flag: {}\n", .{arg});
|
|
||||||
return error.UnknownFlag;
|
|
||||||
} else {
|
|
||||||
try parsed.positionals.append(arg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return parsed;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn deinit(self: *Args) void {
|
|
||||||
self.flags.deinit();
|
|
||||||
self.positionals.deinit();
|
|
||||||
}
|
|
||||||
|
|
||||||
// e.g. --help
|
|
||||||
pub fn present(self: *const Args, name: []const u8) bool {
|
|
||||||
return self.flags.contains(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
// e.g. --name value
|
|
||||||
pub fn single(self: *Args, name: []const u8) ?[]const u8 {
|
|
||||||
if (self.flags.get(name)) |entry| {
|
|
||||||
switch (entry.value) {
|
|
||||||
.Single => |inner| {
|
|
||||||
return inner;
|
|
||||||
},
|
|
||||||
else => @panic("attempted to retrieve flag with wrong type"),
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// e.g. --names value1 value2 value3
|
|
||||||
pub fn many(self: *Args, name: []const u8) []const []const u8 {
|
|
||||||
if (self.flags.get(name)) |entry| {
|
|
||||||
switch (entry.value) {
|
|
||||||
.Many => |inner| {
|
|
||||||
return inner.toSliceConst();
|
|
||||||
},
|
|
||||||
else => @panic("attempted to retrieve flag with wrong type"),
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return &[_][]const u8{};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Arguments for a flag. e.g. arg1, arg2 in `--command arg1 arg2`.
|
|
||||||
const FlagArg = union(enum) {
|
|
||||||
None,
|
|
||||||
Single: []const u8,
|
|
||||||
Many: ArrayList([]const u8),
|
|
||||||
};
|
|
||||||
|
|
||||||
// Specification for how a flag should be parsed.
|
|
||||||
pub const Flag = struct {
|
|
||||||
name: []const u8,
|
|
||||||
required: usize,
|
|
||||||
mergable: bool,
|
|
||||||
allowed_set: ?[]const []const u8,
|
|
||||||
|
|
||||||
pub fn Bool(comptime name: []const u8) Flag {
|
|
||||||
return ArgN(name, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn Arg1(comptime name: []const u8) Flag {
|
|
||||||
return ArgN(name, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn ArgN(comptime name: []const u8, comptime n: usize) Flag {
|
|
||||||
return Flag{
|
|
||||||
.name = name,
|
|
||||||
.required = n,
|
|
||||||
.mergable = false,
|
|
||||||
.allowed_set = null,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn ArgMergeN(comptime name: []const u8, comptime n: usize) Flag {
|
|
||||||
if (n == 0) {
|
|
||||||
@compileError("n must be greater than 0");
|
|
||||||
}
|
|
||||||
|
|
||||||
return Flag{
|
|
||||||
.name = name,
|
|
||||||
.required = n,
|
|
||||||
.mergable = true,
|
|
||||||
.allowed_set = null,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn Option(comptime name: []const u8, comptime set: []const []const u8) Flag {
|
|
||||||
return Flag{
|
|
||||||
.name = name,
|
|
||||||
.required = 1,
|
|
||||||
.mergable = false,
|
|
||||||
.allowed_set = set,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
test "parse arguments" {
|
|
||||||
const spec1 = comptime [_]Flag{
|
|
||||||
Flag.Bool("--help"),
|
|
||||||
Flag.Bool("--init"),
|
|
||||||
Flag.Arg1("--build-file"),
|
|
||||||
Flag.Option("--color", [_][]const u8{
|
|
||||||
"on",
|
|
||||||
"off",
|
|
||||||
"auto",
|
|
||||||
}),
|
|
||||||
Flag.ArgN("--pkg-begin", 2),
|
|
||||||
Flag.ArgMergeN("--object", 1),
|
|
||||||
Flag.ArgN("--library", 1),
|
|
||||||
};
|
|
||||||
|
|
||||||
const cliargs = [_][]const u8{
|
|
||||||
"build",
|
|
||||||
"--help",
|
|
||||||
"pos1",
|
|
||||||
"--build-file",
|
|
||||||
"build.zig",
|
|
||||||
"--object",
|
|
||||||
"obj1",
|
|
||||||
"--object",
|
|
||||||
"obj2",
|
|
||||||
"--library",
|
|
||||||
"lib1",
|
|
||||||
"--library",
|
|
||||||
"lib2",
|
|
||||||
"--color",
|
|
||||||
"on",
|
|
||||||
"pos2",
|
|
||||||
};
|
|
||||||
|
|
||||||
var args = try Args.parse(std.debug.global_allocator, spec1, cliargs);
|
|
||||||
|
|
||||||
testing.expect(args.present("help"));
|
|
||||||
testing.expect(!args.present("help2"));
|
|
||||||
testing.expect(!args.present("init"));
|
|
||||||
|
|
||||||
testing.expect(mem.eql(u8, args.single("build-file").?, "build.zig"));
|
|
||||||
testing.expect(mem.eql(u8, args.single("color").?, "on"));
|
|
||||||
|
|
||||||
const objects = args.many("object").?;
|
|
||||||
testing.expect(mem.eql(u8, objects[0], "obj1"));
|
|
||||||
testing.expect(mem.eql(u8, objects[1], "obj2"));
|
|
||||||
|
|
||||||
testing.expect(mem.eql(u8, args.single("library").?, "lib2"));
|
|
||||||
|
|
||||||
const pos = args.positionals.toSliceConst();
|
|
||||||
testing.expect(mem.eql(u8, pos[0], "build"));
|
|
||||||
testing.expect(mem.eql(u8, pos[1], "pos1"));
|
|
||||||
testing.expect(mem.eql(u8, pos[2], "pos2"));
|
|
||||||
}
|
|
@ -101,8 +101,6 @@ pub async fn renderToLlvm(comp: *Compilation, fn_val: *Value.Fn, code: *ir.Code)
|
|||||||
_ = llvm.VerifyModule(ofile.module, llvm.AbortProcessAction, &error_ptr);
|
_ = llvm.VerifyModule(ofile.module, llvm.AbortProcessAction, &error_ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(comp.emit_file_type == Compilation.Emit.Binary); // TODO support other types
|
|
||||||
|
|
||||||
const is_small = comp.build_mode == .ReleaseSmall;
|
const is_small = comp.build_mode == .ReleaseSmall;
|
||||||
const is_debug = comp.build_mode == .Debug;
|
const is_debug = comp.build_mode == .Debug;
|
||||||
|
|
||||||
|
@ -135,22 +135,17 @@ pub const Compilation = struct {
|
|||||||
/// lazily created when we need it
|
/// lazily created when we need it
|
||||||
tmp_dir: event.Future(BuildError![]u8) = event.Future(BuildError![]u8).init(),
|
tmp_dir: event.Future(BuildError![]u8) = event.Future(BuildError![]u8).init(),
|
||||||
|
|
||||||
version_major: u32 = 0,
|
version: builtin.Version = builtin.Version{ .major = 0, .minor = 0, .patch = 0 },
|
||||||
version_minor: u32 = 0,
|
|
||||||
version_patch: u32 = 0,
|
|
||||||
|
|
||||||
linker_script: ?[]const u8 = null,
|
linker_script: ?[]const u8 = null,
|
||||||
out_h_path: ?[]const u8 = null,
|
out_h_path: ?[]const u8 = null,
|
||||||
|
|
||||||
is_test: bool = false,
|
is_test: bool = false,
|
||||||
each_lib_rpath: bool = false,
|
|
||||||
strip: bool = false,
|
strip: bool = false,
|
||||||
is_static: bool,
|
is_static: bool,
|
||||||
linker_rdynamic: bool = false,
|
linker_rdynamic: bool = false,
|
||||||
|
|
||||||
clang_argv: []const []const u8 = &[_][]const u8{},
|
clang_argv: []const []const u8 = &[_][]const u8{},
|
||||||
lib_dirs: []const []const u8 = &[_][]const u8{},
|
|
||||||
rpath_list: []const []const u8 = &[_][]const u8{},
|
|
||||||
assembly_files: []const []const u8 = &[_][]const u8{},
|
assembly_files: []const []const u8 = &[_][]const u8{},
|
||||||
|
|
||||||
/// paths that are explicitly provided by the user to link against
|
/// paths that are explicitly provided by the user to link against
|
||||||
@ -162,9 +157,6 @@ pub const Compilation = struct {
|
|||||||
|
|
||||||
pub const FnLinkSet = std.TailQueue(?*Value.Fn);
|
pub const FnLinkSet = std.TailQueue(?*Value.Fn);
|
||||||
|
|
||||||
windows_subsystem_windows: bool = false,
|
|
||||||
windows_subsystem_console: bool = false,
|
|
||||||
|
|
||||||
link_libs_list: ArrayList(*LinkLib),
|
link_libs_list: ArrayList(*LinkLib),
|
||||||
libc_link_lib: ?*LinkLib = null,
|
libc_link_lib: ?*LinkLib = null,
|
||||||
|
|
||||||
@ -178,17 +170,18 @@ pub const Compilation = struct {
|
|||||||
verbose_llvm_ir: bool = false,
|
verbose_llvm_ir: bool = false,
|
||||||
verbose_link: bool = false,
|
verbose_link: bool = false,
|
||||||
|
|
||||||
darwin_frameworks: []const []const u8 = &[_][]const u8{},
|
|
||||||
darwin_version_min: DarwinVersionMin = .None,
|
darwin_version_min: DarwinVersionMin = .None,
|
||||||
|
|
||||||
test_filters: []const []const u8 = &[_][]const u8{},
|
test_filters: []const []const u8 = &[_][]const u8{},
|
||||||
test_name_prefix: ?[]const u8 = null,
|
test_name_prefix: ?[]const u8 = null,
|
||||||
|
|
||||||
emit_file_type: Emit = .Binary,
|
emit_bin: bool = true,
|
||||||
|
emit_asm: bool = false,
|
||||||
|
emit_llvm_ir: bool = false,
|
||||||
|
emit_h: bool = false,
|
||||||
|
|
||||||
kind: Kind,
|
kind: Kind,
|
||||||
|
|
||||||
link_out_file: ?[]const u8 = null,
|
|
||||||
events: *event.Channel(Event),
|
events: *event.Channel(Event),
|
||||||
|
|
||||||
exported_symbol_names: event.Locked(Decl.Table),
|
exported_symbol_names: event.Locked(Decl.Table),
|
||||||
|
@ -36,21 +36,17 @@ pub fn link(comp: *Compilation) !void {
|
|||||||
ctx.args = std.ArrayList([*:0]const u8).init(&ctx.arena.allocator);
|
ctx.args = std.ArrayList([*:0]const u8).init(&ctx.arena.allocator);
|
||||||
ctx.link_msg = std.Buffer.initNull(&ctx.arena.allocator);
|
ctx.link_msg = std.Buffer.initNull(&ctx.arena.allocator);
|
||||||
|
|
||||||
if (comp.link_out_file) |out_file| {
|
ctx.out_file_path = try std.Buffer.init(&ctx.arena.allocator, comp.name.toSliceConst());
|
||||||
ctx.out_file_path = try std.Buffer.init(&ctx.arena.allocator, out_file);
|
switch (comp.kind) {
|
||||||
} else {
|
.Exe => {
|
||||||
ctx.out_file_path = try std.Buffer.init(&ctx.arena.allocator, comp.name.toSliceConst());
|
try ctx.out_file_path.append(comp.target.exeFileExt());
|
||||||
switch (comp.kind) {
|
},
|
||||||
.Exe => {
|
.Lib => {
|
||||||
try ctx.out_file_path.append(comp.target.exeFileExt());
|
try ctx.out_file_path.append(if (comp.is_static) comp.target.staticLibSuffix() else comp.target.dynamicLibSuffix());
|
||||||
},
|
},
|
||||||
.Lib => {
|
.Obj => {
|
||||||
try ctx.out_file_path.append(if (comp.is_static) comp.target.staticLibSuffix() else comp.target.dynamicLibSuffix());
|
try ctx.out_file_path.append(comp.target.oFileExt());
|
||||||
},
|
},
|
||||||
.Obj => {
|
|
||||||
try ctx.out_file_path.append(comp.target.oFileExt());
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// even though we're calling LLD as a library it thinks the first
|
// even though we're calling LLD as a library it thinks the first
|
||||||
@ -183,37 +179,6 @@ fn constructLinkerArgsElf(ctx: *Context) !void {
|
|||||||
try addPathJoin(ctx, ctx.libc.static_lib_dir.?, crtbegino);
|
try addPathJoin(ctx, ctx.libc.static_lib_dir.?, crtbegino);
|
||||||
}
|
}
|
||||||
|
|
||||||
//for (size_t i = 0; i < g->rpath_list.length; i += 1) {
|
|
||||||
// Buf *rpath = g->rpath_list.at(i);
|
|
||||||
// add_rpath(lj, rpath);
|
|
||||||
//}
|
|
||||||
//if (g->each_lib_rpath) {
|
|
||||||
// for (size_t i = 0; i < g->lib_dirs.length; i += 1) {
|
|
||||||
// const char *lib_dir = g->lib_dirs.at(i);
|
|
||||||
// for (size_t i = 0; i < g->link_libs_list.length; i += 1) {
|
|
||||||
// LinkLib *link_lib = g->link_libs_list.at(i);
|
|
||||||
// if (buf_eql_str(link_lib->name, "c")) {
|
|
||||||
// continue;
|
|
||||||
// }
|
|
||||||
// bool does_exist;
|
|
||||||
// Buf *test_path = buf_sprintf("%s/lib%s.so", lib_dir, buf_ptr(link_lib->name));
|
|
||||||
// if (os_file_exists(test_path, &does_exist) != ErrorNone) {
|
|
||||||
// zig_panic("link: unable to check if file exists: %s", buf_ptr(test_path));
|
|
||||||
// }
|
|
||||||
// if (does_exist) {
|
|
||||||
// add_rpath(lj, buf_create_from_str(lib_dir));
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
//for (size_t i = 0; i < g->lib_dirs.length; i += 1) {
|
|
||||||
// const char *lib_dir = g->lib_dirs.at(i);
|
|
||||||
// lj->args.append("-L");
|
|
||||||
// lj->args.append(lib_dir);
|
|
||||||
//}
|
|
||||||
|
|
||||||
if (ctx.comp.haveLibC()) {
|
if (ctx.comp.haveLibC()) {
|
||||||
try ctx.args.append("-L");
|
try ctx.args.append("-L");
|
||||||
// TODO addNullByte should probably return [:0]u8
|
// TODO addNullByte should probably return [:0]u8
|
||||||
@ -326,12 +291,6 @@ fn constructLinkerArgsCoff(ctx: *Context) !void {
|
|||||||
else => return error.UnsupportedLinkArchitecture,
|
else => return error.UnsupportedLinkArchitecture,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctx.comp.windows_subsystem_windows) {
|
|
||||||
try ctx.args.append("/SUBSYSTEM:windows");
|
|
||||||
} else if (ctx.comp.windows_subsystem_console) {
|
|
||||||
try ctx.args.append("/SUBSYSTEM:console");
|
|
||||||
}
|
|
||||||
|
|
||||||
const is_library = ctx.comp.kind == .Lib;
|
const is_library = ctx.comp.kind == .Lib;
|
||||||
|
|
||||||
const out_arg = try std.fmt.allocPrint(&ctx.arena.allocator, "-OUT:{}\x00", .{ctx.out_file_path.toSliceConst()});
|
const out_arg = try std.fmt.allocPrint(&ctx.arena.allocator, "-OUT:{}\x00", .{ctx.out_file_path.toSliceConst()});
|
||||||
@ -374,12 +333,6 @@ fn constructLinkerArgsCoff(ctx: *Context) !void {
|
|||||||
try ctx.args.append("-NODEFAULTLIB");
|
try ctx.args.append("-NODEFAULTLIB");
|
||||||
if (!is_library) {
|
if (!is_library) {
|
||||||
try ctx.args.append("-ENTRY:WinMainCRTStartup");
|
try ctx.args.append("-ENTRY:WinMainCRTStartup");
|
||||||
// TODO
|
|
||||||
//if (g->have_winmain) {
|
|
||||||
// lj->args.append("-ENTRY:WinMain");
|
|
||||||
//} else {
|
|
||||||
// lj->args.append("-ENTRY:WinMainCRTStartup");
|
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -387,11 +340,6 @@ fn constructLinkerArgsCoff(ctx: *Context) !void {
|
|||||||
try ctx.args.append("-DLL");
|
try ctx.args.append("-DLL");
|
||||||
}
|
}
|
||||||
|
|
||||||
//for (size_t i = 0; i < g->lib_dirs.length; i += 1) {
|
|
||||||
// const char *lib_dir = g->lib_dirs.at(i);
|
|
||||||
// lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", lib_dir)));
|
|
||||||
//}
|
|
||||||
|
|
||||||
for (ctx.comp.link_objects) |link_object| {
|
for (ctx.comp.link_objects) |link_object| {
|
||||||
const link_obj_with_null = try std.cstr.addNullByte(&ctx.arena.allocator, link_object);
|
const link_obj_with_null = try std.cstr.addNullByte(&ctx.arena.allocator, link_object);
|
||||||
try ctx.args.append(@ptrCast([*:0]const u8, link_obj_with_null.ptr));
|
try ctx.args.append(@ptrCast([*:0]const u8, link_obj_with_null.ptr));
|
||||||
@ -402,63 +350,10 @@ fn constructLinkerArgsCoff(ctx: *Context) !void {
|
|||||||
.Exe, .Lib => {
|
.Exe, .Lib => {
|
||||||
if (!ctx.comp.haveLibC()) {
|
if (!ctx.comp.haveLibC()) {
|
||||||
@panic("TODO");
|
@panic("TODO");
|
||||||
//Buf *builtin_o_path = build_o(g, "builtin");
|
|
||||||
//lj->args.append(buf_ptr(builtin_o_path));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// msvc compiler_rt is missing some stuff, so we still build it and rely on weak linkage
|
|
||||||
// TODO
|
|
||||||
//Buf *compiler_rt_o_path = build_compiler_rt(g);
|
|
||||||
//lj->args.append(buf_ptr(compiler_rt_o_path));
|
|
||||||
},
|
},
|
||||||
.Obj => {},
|
.Obj => {},
|
||||||
}
|
}
|
||||||
|
|
||||||
//Buf *def_contents = buf_alloc();
|
|
||||||
//ZigList<const char *> gen_lib_args = {0};
|
|
||||||
//for (size_t lib_i = 0; lib_i < g->link_libs_list.length; lib_i += 1) {
|
|
||||||
// LinkLib *link_lib = g->link_libs_list.at(lib_i);
|
|
||||||
// if (buf_eql_str(link_lib->name, "c")) {
|
|
||||||
// continue;
|
|
||||||
// }
|
|
||||||
// if (link_lib->provided_explicitly) {
|
|
||||||
// if (lj->codegen->zig_target.env_type == ZigLLVM_GNU) {
|
|
||||||
// Buf *arg = buf_sprintf("-l%s", buf_ptr(link_lib->name));
|
|
||||||
// lj->args.append(buf_ptr(arg));
|
|
||||||
// }
|
|
||||||
// else {
|
|
||||||
// lj->args.append(buf_ptr(link_lib->name));
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// buf_resize(def_contents, 0);
|
|
||||||
// buf_appendf(def_contents, "LIBRARY %s\nEXPORTS\n", buf_ptr(link_lib->name));
|
|
||||||
// for (size_t exp_i = 0; exp_i < link_lib->symbols.length; exp_i += 1) {
|
|
||||||
// Buf *symbol_name = link_lib->symbols.at(exp_i);
|
|
||||||
// buf_appendf(def_contents, "%s\n", buf_ptr(symbol_name));
|
|
||||||
// }
|
|
||||||
// buf_appendf(def_contents, "\n");
|
|
||||||
|
|
||||||
// Buf *def_path = buf_alloc();
|
|
||||||
// os_path_join(g->cache_dir, buf_sprintf("%s.def", buf_ptr(link_lib->name)), def_path);
|
|
||||||
// os_write_file(def_path, def_contents);
|
|
||||||
|
|
||||||
// Buf *generated_lib_path = buf_alloc();
|
|
||||||
// os_path_join(g->cache_dir, buf_sprintf("%s.lib", buf_ptr(link_lib->name)), generated_lib_path);
|
|
||||||
|
|
||||||
// gen_lib_args.resize(0);
|
|
||||||
// gen_lib_args.append("link");
|
|
||||||
|
|
||||||
// coff_append_machine_arg(g, &gen_lib_args);
|
|
||||||
// gen_lib_args.append(buf_ptr(buf_sprintf("-DEF:%s", buf_ptr(def_path))));
|
|
||||||
// gen_lib_args.append(buf_ptr(buf_sprintf("-OUT:%s", buf_ptr(generated_lib_path))));
|
|
||||||
// Buf diag = BUF_INIT;
|
|
||||||
// if (!zig_lld_link(g->zig_target.oformat, gen_lib_args.items, gen_lib_args.length, &diag)) {
|
|
||||||
// fprintf(stderr, "%s\n", buf_ptr(&diag));
|
|
||||||
// exit(1);
|
|
||||||
// }
|
|
||||||
// lj->args.append(buf_ptr(generated_lib_path));
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn constructLinkerArgsMachO(ctx: *Context) !void {
|
fn constructLinkerArgsMachO(ctx: *Context) !void {
|
||||||
@ -476,32 +371,6 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {
|
|||||||
try ctx.args.append("-dynamic");
|
try ctx.args.append("-dynamic");
|
||||||
}
|
}
|
||||||
|
|
||||||
//if (is_lib) {
|
|
||||||
// if (!g->is_static) {
|
|
||||||
// lj->args.append("-dylib");
|
|
||||||
|
|
||||||
// Buf *compat_vers = buf_sprintf("%" ZIG_PRI_usize ".0.0", g->version_major);
|
|
||||||
// lj->args.append("-compatibility_version");
|
|
||||||
// lj->args.append(buf_ptr(compat_vers));
|
|
||||||
|
|
||||||
// Buf *cur_vers = buf_sprintf("%" ZIG_PRI_usize ".%" ZIG_PRI_usize ".%" ZIG_PRI_usize,
|
|
||||||
// g->version_major, g->version_minor, g->version_patch);
|
|
||||||
// lj->args.append("-current_version");
|
|
||||||
// lj->args.append(buf_ptr(cur_vers));
|
|
||||||
|
|
||||||
// // TODO getting an error when running an executable when doing this rpath thing
|
|
||||||
// //Buf *dylib_install_name = buf_sprintf("@rpath/lib%s.%" ZIG_PRI_usize ".dylib",
|
|
||||||
// // buf_ptr(g->root_out_name), g->version_major);
|
|
||||||
// //lj->args.append("-install_name");
|
|
||||||
// //lj->args.append(buf_ptr(dylib_install_name));
|
|
||||||
|
|
||||||
// if (buf_len(&lj->out_file) == 0) {
|
|
||||||
// buf_appendf(&lj->out_file, "lib%s.%" ZIG_PRI_usize ".%" ZIG_PRI_usize ".%" ZIG_PRI_usize ".dylib",
|
|
||||||
// buf_ptr(g->root_out_name), g->version_major, g->version_minor, g->version_patch);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
try ctx.args.append("-arch");
|
try ctx.args.append("-arch");
|
||||||
try ctx.args.append(util.getDarwinArchString(ctx.comp.target));
|
try ctx.args.append(util.getDarwinArchString(ctx.comp.target));
|
||||||
|
|
||||||
@ -529,12 +398,6 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {
|
|||||||
try ctx.args.append("-o");
|
try ctx.args.append("-o");
|
||||||
try ctx.args.append(ctx.out_file_path.toSliceConst());
|
try ctx.args.append(ctx.out_file_path.toSliceConst());
|
||||||
|
|
||||||
//for (size_t i = 0; i < g->rpath_list.length; i += 1) {
|
|
||||||
// Buf *rpath = g->rpath_list.at(i);
|
|
||||||
// add_rpath(lj, rpath);
|
|
||||||
//}
|
|
||||||
//add_rpath(lj, &lj->out_file);
|
|
||||||
|
|
||||||
if (shared) {
|
if (shared) {
|
||||||
try ctx.args.append("-headerpad_max_install_names");
|
try ctx.args.append("-headerpad_max_install_names");
|
||||||
} else if (ctx.comp.is_static) {
|
} else if (ctx.comp.is_static) {
|
||||||
@ -563,24 +426,12 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//for (size_t i = 0; i < g->lib_dirs.length; i += 1) {
|
|
||||||
// const char *lib_dir = g->lib_dirs.at(i);
|
|
||||||
// lj->args.append("-L");
|
|
||||||
// lj->args.append(lib_dir);
|
|
||||||
//}
|
|
||||||
|
|
||||||
for (ctx.comp.link_objects) |link_object| {
|
for (ctx.comp.link_objects) |link_object| {
|
||||||
const link_obj_with_null = try std.cstr.addNullByte(&ctx.arena.allocator, link_object);
|
const link_obj_with_null = try std.cstr.addNullByte(&ctx.arena.allocator, link_object);
|
||||||
try ctx.args.append(@ptrCast([*:0]const u8, link_obj_with_null.ptr));
|
try ctx.args.append(@ptrCast([*:0]const u8, link_obj_with_null.ptr));
|
||||||
}
|
}
|
||||||
try addFnObjects(ctx);
|
try addFnObjects(ctx);
|
||||||
|
|
||||||
//// compiler_rt on darwin is missing some stuff, so we still build it and rely on LinkOnce
|
|
||||||
//if (g->out_type == OutTypeExe || g->out_type == OutTypeLib) {
|
|
||||||
// Buf *compiler_rt_o_path = build_compiler_rt(g);
|
|
||||||
// lj->args.append(buf_ptr(compiler_rt_o_path));
|
|
||||||
//}
|
|
||||||
|
|
||||||
if (ctx.comp.target == Target.Native) {
|
if (ctx.comp.target == Target.Native) {
|
||||||
for (ctx.comp.link_libs_list.toSliceConst()) |lib| {
|
for (ctx.comp.link_libs_list.toSliceConst()) |lib| {
|
||||||
if (mem.eql(u8, lib.name, "c")) {
|
if (mem.eql(u8, lib.name, "c")) {
|
||||||
@ -613,11 +464,6 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {
|
|||||||
} else {
|
} else {
|
||||||
@panic("TODO");
|
@panic("TODO");
|
||||||
}
|
}
|
||||||
|
|
||||||
//for (size_t i = 0; i < g->darwin_frameworks.length; i += 1) {
|
|
||||||
// lj->args.append("-framework");
|
|
||||||
// lj->args.append(buf_ptr(g->darwin_frameworks.at(i)));
|
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn constructLinkerArgsWasm(ctx: *Context) void {
|
fn constructLinkerArgsWasm(ctx: *Context) void {
|
||||||
|
@ -11,11 +11,8 @@ const Allocator = mem.Allocator;
|
|||||||
const ArrayList = std.ArrayList;
|
const ArrayList = std.ArrayList;
|
||||||
const Buffer = std.Buffer;
|
const Buffer = std.Buffer;
|
||||||
|
|
||||||
const arg = @import("arg.zig");
|
|
||||||
const c = @import("c.zig");
|
const c = @import("c.zig");
|
||||||
const introspect = @import("introspect.zig");
|
const introspect = @import("introspect.zig");
|
||||||
const Args = arg.Args;
|
|
||||||
const Flag = arg.Flag;
|
|
||||||
const ZigCompiler = @import("compilation.zig").ZigCompiler;
|
const ZigCompiler = @import("compilation.zig").ZigCompiler;
|
||||||
const Compilation = @import("compilation.zig").Compilation;
|
const Compilation = @import("compilation.zig").Compilation;
|
||||||
const Target = std.Target;
|
const Target = std.Target;
|
||||||
@ -53,11 +50,7 @@ const Command = struct {
|
|||||||
};
|
};
|
||||||
|
|
||||||
pub fn main() !void {
|
pub fn main() !void {
|
||||||
// This allocator needs to be thread-safe because we use it for the event.Loop
|
const allocator = std.heap.c_allocator;
|
||||||
// which multiplexes async functions onto kernel threads.
|
|
||||||
// libc allocator is guaranteed to have this property.
|
|
||||||
// TODO https://github.com/ziglang/zig/issues/3783
|
|
||||||
const allocator = std.heap.page_allocator;
|
|
||||||
|
|
||||||
stdout = &std.io.getStdOut().outStream().stream;
|
stdout = &std.io.getStdOut().outStream().stream;
|
||||||
|
|
||||||
@ -65,7 +58,7 @@ pub fn main() !void {
|
|||||||
stderr = &stderr_file.outStream().stream;
|
stderr = &stderr_file.outStream().stream;
|
||||||
|
|
||||||
const args = try process.argsAlloc(allocator);
|
const args = try process.argsAlloc(allocator);
|
||||||
// TODO I'm getting unreachable code here, which shouldn't happen
|
// TODO I'm getting unreachable code here, which shouldn't happen
|
||||||
//defer process.argsFree(allocator, args);
|
//defer process.argsFree(allocator, args);
|
||||||
|
|
||||||
if (args.len <= 1) {
|
if (args.len <= 1) {
|
||||||
@ -182,8 +175,6 @@ const usage_build_generic =
|
|||||||
\\ --object [obj] Add object file to build
|
\\ --object [obj] Add object file to build
|
||||||
\\ -rdynamic Add all symbols to the dynamic symbol table
|
\\ -rdynamic Add all symbols to the dynamic symbol table
|
||||||
\\ -rpath [path] Add directory to the runtime library search path
|
\\ -rpath [path] Add directory to the runtime library search path
|
||||||
\\ -mconsole (windows) --subsystem console to the linker
|
|
||||||
\\ -mwindows (windows) --subsystem windows to the linker
|
|
||||||
\\ -framework [name] (darwin) link against framework
|
\\ -framework [name] (darwin) link against framework
|
||||||
\\ -mios-version-min [ver] (darwin) set iOS deployment target
|
\\ -mios-version-min [ver] (darwin) set iOS deployment target
|
||||||
\\ -mmacosx-version-min [ver] (darwin) set Mac OS X deployment target
|
\\ -mmacosx-version-min [ver] (darwin) set Mac OS X deployment target
|
||||||
@ -194,143 +185,244 @@ const usage_build_generic =
|
|||||||
\\
|
\\
|
||||||
;
|
;
|
||||||
|
|
||||||
const args_build_generic = [_]Flag{
|
|
||||||
Flag.Bool("--help"),
|
|
||||||
Flag.Option("--color", &[_][]const u8{
|
|
||||||
"auto",
|
|
||||||
"off",
|
|
||||||
"on",
|
|
||||||
}),
|
|
||||||
Flag.Option("--mode", &[_][]const u8{
|
|
||||||
"debug",
|
|
||||||
"release-fast",
|
|
||||||
"release-safe",
|
|
||||||
"release-small",
|
|
||||||
}),
|
|
||||||
|
|
||||||
Flag.ArgMergeN("--assembly", 1),
|
|
||||||
Flag.Option("--emit", &[_][]const u8{
|
|
||||||
"asm",
|
|
||||||
"bin",
|
|
||||||
"llvm-ir",
|
|
||||||
}),
|
|
||||||
Flag.Bool("--enable-timing-info"),
|
|
||||||
Flag.Arg1("--libc"),
|
|
||||||
Flag.Arg1("--name"),
|
|
||||||
Flag.Arg1("--output"),
|
|
||||||
Flag.Arg1("--output-h"),
|
|
||||||
// NOTE: Parsed manually after initial check
|
|
||||||
Flag.ArgN("--pkg-begin", 2),
|
|
||||||
Flag.Bool("--pkg-end"),
|
|
||||||
Flag.Bool("--static"),
|
|
||||||
Flag.Bool("--strip"),
|
|
||||||
Flag.Arg1("-target"),
|
|
||||||
Flag.Bool("--verbose-tokenize"),
|
|
||||||
Flag.Bool("--verbose-ast-tree"),
|
|
||||||
Flag.Bool("--verbose-ast-fmt"),
|
|
||||||
Flag.Bool("--verbose-link"),
|
|
||||||
Flag.Bool("--verbose-ir"),
|
|
||||||
Flag.Bool("--verbose-llvm-ir"),
|
|
||||||
Flag.Bool("--verbose-cimport"),
|
|
||||||
Flag.Arg1("-dirafter"),
|
|
||||||
Flag.ArgMergeN("-isystem", 1),
|
|
||||||
Flag.Arg1("-mllvm"),
|
|
||||||
|
|
||||||
Flag.Arg1("--ar-path"),
|
|
||||||
Flag.Bool("--each-lib-rpath"),
|
|
||||||
Flag.ArgMergeN("--library", 1),
|
|
||||||
Flag.ArgMergeN("--forbid-library", 1),
|
|
||||||
Flag.ArgMergeN("--library-path", 1),
|
|
||||||
Flag.Arg1("--linker-script"),
|
|
||||||
Flag.ArgMergeN("--object", 1),
|
|
||||||
// NOTE: Removed -L since it would need to be special-cased and we have an alias in library-path
|
|
||||||
Flag.Bool("-rdynamic"),
|
|
||||||
Flag.Arg1("-rpath"),
|
|
||||||
Flag.Bool("-mconsole"),
|
|
||||||
Flag.Bool("-mwindows"),
|
|
||||||
Flag.ArgMergeN("-framework", 1),
|
|
||||||
Flag.Arg1("-mios-version-min"),
|
|
||||||
Flag.Arg1("-mmacosx-version-min"),
|
|
||||||
Flag.Arg1("--ver-major"),
|
|
||||||
Flag.Arg1("--ver-minor"),
|
|
||||||
Flag.Arg1("--ver-patch"),
|
|
||||||
};
|
|
||||||
|
|
||||||
fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Compilation.Kind) !void {
|
fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Compilation.Kind) !void {
|
||||||
var flags = try Args.parse(allocator, &args_build_generic, args);
|
var color: errmsg.Color = .Auto;
|
||||||
defer flags.deinit();
|
var build_mode: std.builtin.Mode = .Debug;
|
||||||
|
var emit_bin = true;
|
||||||
|
var emit_asm = false;
|
||||||
|
var emit_llvm_ir = false;
|
||||||
|
var emit_h = false;
|
||||||
|
var provided_name: ?[]const u8 = null;
|
||||||
|
var is_dynamic = false;
|
||||||
|
var root_src_file: ?[]const u8 = null;
|
||||||
|
var libc_arg: ?[]const u8 = null;
|
||||||
|
var version: std.builtin.Version = .{ .major = 0, .minor = 0, .patch = 0 };
|
||||||
|
var linker_script: ?[]const u8 = null;
|
||||||
|
var strip = false;
|
||||||
|
var verbose_tokenize = false;
|
||||||
|
var verbose_ast_tree = false;
|
||||||
|
var verbose_ast_fmt = false;
|
||||||
|
var verbose_link = false;
|
||||||
|
var verbose_ir = false;
|
||||||
|
var verbose_llvm_ir = false;
|
||||||
|
var verbose_cimport = false;
|
||||||
|
var linker_rdynamic = false;
|
||||||
|
var macosx_version_min: ?[]const u8 = null;
|
||||||
|
var ios_version_min: ?[]const u8 = null;
|
||||||
|
|
||||||
if (flags.present("help")) {
|
var assembly_files = ArrayList([]const u8).init(allocator);
|
||||||
try stdout.write(usage_build_generic);
|
defer assembly_files.deinit();
|
||||||
process.exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
const build_mode: std.builtin.Mode = blk: {
|
var link_objects = ArrayList([]const u8).init(allocator);
|
||||||
if (flags.single("mode")) |mode_flag| {
|
defer link_objects.deinit();
|
||||||
if (mem.eql(u8, mode_flag, "debug")) {
|
|
||||||
break :blk .Debug;
|
|
||||||
} else if (mem.eql(u8, mode_flag, "release-fast")) {
|
|
||||||
break :blk .ReleaseFast;
|
|
||||||
} else if (mem.eql(u8, mode_flag, "release-safe")) {
|
|
||||||
break :blk .ReleaseSafe;
|
|
||||||
} else if (mem.eql(u8, mode_flag, "release-small")) {
|
|
||||||
break :blk .ReleaseSmall;
|
|
||||||
} else unreachable;
|
|
||||||
} else {
|
|
||||||
break :blk .Debug;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const color: errmsg.Color = blk: {
|
var clang_argv_buf = ArrayList([]const u8).init(allocator);
|
||||||
if (flags.single("color")) |color_flag| {
|
defer clang_argv_buf.deinit();
|
||||||
if (mem.eql(u8, color_flag, "auto")) {
|
|
||||||
break :blk .Auto;
|
|
||||||
} else if (mem.eql(u8, color_flag, "on")) {
|
|
||||||
break :blk .On;
|
|
||||||
} else if (mem.eql(u8, color_flag, "off")) {
|
|
||||||
break :blk .Off;
|
|
||||||
} else unreachable;
|
|
||||||
} else {
|
|
||||||
break :blk .Auto;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const emit_type: Compilation.Emit = blk: {
|
var mllvm_flags = ArrayList([]const u8).init(allocator);
|
||||||
if (flags.single("emit")) |emit_flag| {
|
defer mllvm_flags.deinit();
|
||||||
if (mem.eql(u8, emit_flag, "asm")) {
|
|
||||||
break :blk .Assembly;
|
|
||||||
} else if (mem.eql(u8, emit_flag, "bin")) {
|
|
||||||
break :blk .Binary;
|
|
||||||
} else if (mem.eql(u8, emit_flag, "llvm-ir")) {
|
|
||||||
break :blk .LlvmIr;
|
|
||||||
} else unreachable;
|
|
||||||
} else {
|
|
||||||
break :blk .Binary;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var cur_pkg = try CliPkg.init(allocator, "", "", null);
|
var cur_pkg = try CliPkg.init(allocator, "", "", null);
|
||||||
defer cur_pkg.deinit();
|
defer cur_pkg.deinit();
|
||||||
|
|
||||||
var i: usize = 0;
|
var system_libs = ArrayList([]const u8).init(allocator);
|
||||||
while (i < args.len) : (i += 1) {
|
defer system_libs.deinit();
|
||||||
const arg_name = args[i];
|
|
||||||
if (mem.eql(u8, "--pkg-begin", arg_name)) {
|
|
||||||
// following two arguments guaranteed to exist due to arg parsing
|
|
||||||
i += 1;
|
|
||||||
const new_pkg_name = args[i];
|
|
||||||
i += 1;
|
|
||||||
const new_pkg_path = args[i];
|
|
||||||
|
|
||||||
var new_cur_pkg = try CliPkg.init(allocator, new_pkg_name, new_pkg_path, cur_pkg);
|
var c_src_files = ArrayList([]const u8).init(allocator);
|
||||||
try cur_pkg.children.append(new_cur_pkg);
|
defer c_src_files.deinit();
|
||||||
cur_pkg = new_cur_pkg;
|
|
||||||
} else if (mem.eql(u8, "--pkg-end", arg_name)) {
|
{
|
||||||
if (cur_pkg.parent) |parent| {
|
var i: usize = 0;
|
||||||
cur_pkg = parent;
|
while (i < args.len) : (i += 1) {
|
||||||
|
const arg = args[i];
|
||||||
|
if (mem.startsWith(u8, arg, "-")) {
|
||||||
|
if (mem.eql(u8, arg, "--help")) {
|
||||||
|
try stdout.write(usage_build_generic);
|
||||||
|
process.exit(0);
|
||||||
|
} else if (mem.eql(u8, arg, "--color")) {
|
||||||
|
if (i + 1 >= args.len) {
|
||||||
|
try stderr.write("expected [auto|on|off] after --color\n");
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
i += 1;
|
||||||
|
const next_arg = args[i];
|
||||||
|
if (mem.eql(u8, next_arg, "auto")) {
|
||||||
|
color = .Auto;
|
||||||
|
} else if (mem.eql(u8, next_arg, "on")) {
|
||||||
|
color = .On;
|
||||||
|
} else if (mem.eql(u8, next_arg, "off")) {
|
||||||
|
color = .Off;
|
||||||
|
} else {
|
||||||
|
try stderr.print("expected [auto|on|off] after --color, found '{}'\n", .{next_arg});
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
} else if (mem.eql(u8, arg, "--mode")) {
|
||||||
|
if (i + 1 >= args.len) {
|
||||||
|
try stderr.write("expected [Debug|ReleaseSafe|ReleaseFast|ReleaseSmall] after --mode\n");
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
i += 1;
|
||||||
|
const next_arg = args[i];
|
||||||
|
if (mem.eql(u8, next_arg, "Debug")) {
|
||||||
|
build_mode = .Debug;
|
||||||
|
} else if (mem.eql(u8, next_arg, "ReleaseSafe")) {
|
||||||
|
build_mode = .ReleaseSafe;
|
||||||
|
} else if (mem.eql(u8, next_arg, "ReleaseFast")) {
|
||||||
|
build_mode = .ReleaseFast;
|
||||||
|
} else if (mem.eql(u8, next_arg, "ReleaseSmall")) {
|
||||||
|
build_mode = .ReleaseSmall;
|
||||||
|
} else {
|
||||||
|
try stderr.print("expected [Debug|ReleaseSafe|ReleaseFast|ReleaseSmall] after --mode, found '{}'\n", .{next_arg});
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
} else if (mem.eql(u8, arg, "--name")) {
|
||||||
|
if (i + 1 >= args.len) {
|
||||||
|
try stderr.write("expected parameter after --name\n");
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
i += 1;
|
||||||
|
provided_name = args[i];
|
||||||
|
} else if (mem.eql(u8, arg, "--ver-major")) {
|
||||||
|
if (i + 1 >= args.len) {
|
||||||
|
try stderr.write("expected parameter after --ver-major\n");
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
i += 1;
|
||||||
|
version.major = try std.fmt.parseInt(u32, args[i], 10);
|
||||||
|
} else if (mem.eql(u8, arg, "--ver-minor")) {
|
||||||
|
if (i + 1 >= args.len) {
|
||||||
|
try stderr.write("expected parameter after --ver-minor\n");
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
i += 1;
|
||||||
|
version.minor = try std.fmt.parseInt(u32, args[i], 10);
|
||||||
|
} else if (mem.eql(u8, arg, "--ver-patch")) {
|
||||||
|
if (i + 1 >= args.len) {
|
||||||
|
try stderr.write("expected parameter after --ver-patch\n");
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
i += 1;
|
||||||
|
version.patch = try std.fmt.parseInt(u32, args[i], 10);
|
||||||
|
} else if (mem.eql(u8, arg, "--linker-script")) {
|
||||||
|
if (i + 1 >= args.len) {
|
||||||
|
try stderr.write("expected parameter after --linker-script\n");
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
i += 1;
|
||||||
|
linker_script = args[i];
|
||||||
|
} else if (mem.eql(u8, arg, "--libc")) {
|
||||||
|
if (i + 1 >= args.len) {
|
||||||
|
try stderr.write("expected parameter after --libc\n");
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
i += 1;
|
||||||
|
libc_arg = args[i];
|
||||||
|
} else if (mem.eql(u8, arg, "-mllvm")) {
|
||||||
|
if (i + 1 >= args.len) {
|
||||||
|
try stderr.write("expected parameter after -mllvm\n");
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
i += 1;
|
||||||
|
try clang_argv_buf.append("-mllvm");
|
||||||
|
try clang_argv_buf.append(args[i]);
|
||||||
|
|
||||||
|
try mllvm_flags.append(args[i]);
|
||||||
|
} else if (mem.eql(u8, arg, "-mmacosx-version-min")) {
|
||||||
|
if (i + 1 >= args.len) {
|
||||||
|
try stderr.write("expected parameter after -mmacosx-version-min\n");
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
i += 1;
|
||||||
|
macosx_version_min = args[i];
|
||||||
|
} else if (mem.eql(u8, arg, "-mios-version-min")) {
|
||||||
|
if (i + 1 >= args.len) {
|
||||||
|
try stderr.write("expected parameter after -mios-version-min\n");
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
i += 1;
|
||||||
|
ios_version_min = args[i];
|
||||||
|
} else if (mem.eql(u8, arg, "-femit-bin")) {
|
||||||
|
emit_bin = true;
|
||||||
|
} else if (mem.eql(u8, arg, "-fno-emit-bin")) {
|
||||||
|
emit_bin = false;
|
||||||
|
} else if (mem.eql(u8, arg, "-femit-asm")) {
|
||||||
|
emit_asm = true;
|
||||||
|
} else if (mem.eql(u8, arg, "-fno-emit-asm")) {
|
||||||
|
emit_asm = false;
|
||||||
|
} else if (mem.eql(u8, arg, "-femit-llvm-ir")) {
|
||||||
|
emit_llvm_ir = true;
|
||||||
|
} else if (mem.eql(u8, arg, "-fno-emit-llvm-ir")) {
|
||||||
|
emit_llvm_ir = false;
|
||||||
|
} else if (mem.eql(u8, arg, "-dynamic")) {
|
||||||
|
is_dynamic = true;
|
||||||
|
} else if (mem.eql(u8, arg, "--strip")) {
|
||||||
|
strip = true;
|
||||||
|
} else if (mem.eql(u8, arg, "--verbose-tokenize")) {
|
||||||
|
verbose_tokenize = true;
|
||||||
|
} else if (mem.eql(u8, arg, "--verbose-ast-tree")) {
|
||||||
|
verbose_ast_tree = true;
|
||||||
|
} else if (mem.eql(u8, arg, "--verbose-ast-fmt")) {
|
||||||
|
verbose_ast_fmt = true;
|
||||||
|
} else if (mem.eql(u8, arg, "--verbose-link")) {
|
||||||
|
verbose_link = true;
|
||||||
|
} else if (mem.eql(u8, arg, "--verbose-ir")) {
|
||||||
|
verbose_ir = true;
|
||||||
|
} else if (mem.eql(u8, arg, "--verbose-llvm-ir")) {
|
||||||
|
verbose_llvm_ir = true;
|
||||||
|
} else if (mem.eql(u8, arg, "--verbose-cimport")) {
|
||||||
|
verbose_cimport = true;
|
||||||
|
} else if (mem.eql(u8, arg, "-rdynamic")) {
|
||||||
|
linker_rdynamic = true;
|
||||||
|
} else if (mem.eql(u8, arg, "--pkg-begin")) {
|
||||||
|
if (i + 2 >= args.len) {
|
||||||
|
try stderr.write("expected [name] [path] after --pkg-begin\n");
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
i += 1;
|
||||||
|
const new_pkg_name = args[i];
|
||||||
|
i += 1;
|
||||||
|
const new_pkg_path = args[i];
|
||||||
|
|
||||||
|
var new_cur_pkg = try CliPkg.init(allocator, new_pkg_name, new_pkg_path, cur_pkg);
|
||||||
|
try cur_pkg.children.append(new_cur_pkg);
|
||||||
|
cur_pkg = new_cur_pkg;
|
||||||
|
} else if (mem.eql(u8, arg, "--pkg-end")) {
|
||||||
|
if (cur_pkg.parent) |parent| {
|
||||||
|
cur_pkg = parent;
|
||||||
|
} else {
|
||||||
|
try stderr.write("encountered --pkg-end with no matching --pkg-begin\n");
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
} else if (mem.startsWith(u8, arg, "-l")) {
|
||||||
|
try system_libs.append(arg[2..]);
|
||||||
|
} else {
|
||||||
|
try stderr.print("unrecognized parameter: '{}'", .{arg});
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
} else if (mem.endsWith(u8, arg, ".s")) {
|
||||||
|
try assembly_files.append(arg);
|
||||||
|
} else if (mem.endsWith(u8, arg, ".o") or
|
||||||
|
mem.endsWith(u8, arg, ".obj") or
|
||||||
|
mem.endsWith(u8, arg, ".a") or
|
||||||
|
mem.endsWith(u8, arg, ".lib"))
|
||||||
|
{
|
||||||
|
try link_objects.append(arg);
|
||||||
|
} else if (mem.endsWith(u8, arg, ".c") or
|
||||||
|
mem.endsWith(u8, arg, ".cpp"))
|
||||||
|
{
|
||||||
|
try c_src_files.append(arg);
|
||||||
|
} else if (mem.endsWith(u8, arg, ".zig")) {
|
||||||
|
if (root_src_file) |other| {
|
||||||
|
try stderr.print("found another zig file '{}' after root source file '{}'", .{
|
||||||
|
arg,
|
||||||
|
other,
|
||||||
|
});
|
||||||
|
process.exit(1);
|
||||||
|
} else {
|
||||||
|
root_src_file = arg;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
try stderr.print("encountered --pkg-end with no matching --pkg-begin\n", .{});
|
try stderr.print("unrecognized file extension of parameter '{}'", .{arg});
|
||||||
process.exit(1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -340,18 +432,8 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co
|
|||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
const provided_name = flags.single("name");
|
|
||||||
const root_source_file = switch (flags.positionals.len) {
|
|
||||||
0 => null,
|
|
||||||
1 => flags.positionals.at(0),
|
|
||||||
else => {
|
|
||||||
try stderr.print("unexpected extra parameter: {}\n", .{flags.positionals.at(1)});
|
|
||||||
process.exit(1);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const root_name = if (provided_name) |n| n else blk: {
|
const root_name = if (provided_name) |n| n else blk: {
|
||||||
if (root_source_file) |file| {
|
if (root_src_file) |file| {
|
||||||
const basename = fs.path.basename(file);
|
const basename = fs.path.basename(file);
|
||||||
var it = mem.separate(basename, ".");
|
var it = mem.separate(basename, ".");
|
||||||
break :blk it.next() orelse basename;
|
break :blk it.next() orelse basename;
|
||||||
@ -361,11 +443,7 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const is_static = flags.present("static");
|
if (root_src_file == null and link_objects.len == 0 and assembly_files.len == 0) {
|
||||||
|
|
||||||
const assembly_files = flags.many("assembly");
|
|
||||||
const link_objects = flags.many("object");
|
|
||||||
if (root_source_file == null and link_objects.len == 0 and assembly_files.len == 0) {
|
|
||||||
try stderr.write("Expected source file argument or at least one --object or --assembly argument\n");
|
try stderr.write("Expected source file argument or at least one --object or --assembly argument\n");
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
@ -375,15 +453,7 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co
|
|||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
var clang_argv_buf = ArrayList([]const u8).init(allocator);
|
try ZigCompiler.setLlvmArgv(allocator, mllvm_flags.toSliceConst());
|
||||||
defer clang_argv_buf.deinit();
|
|
||||||
|
|
||||||
const mllvm_flags = flags.many("mllvm");
|
|
||||||
for (mllvm_flags) |mllvm| {
|
|
||||||
try clang_argv_buf.append("-mllvm");
|
|
||||||
try clang_argv_buf.append(mllvm);
|
|
||||||
}
|
|
||||||
try ZigCompiler.setLlvmArgv(allocator, mllvm_flags);
|
|
||||||
|
|
||||||
const zig_lib_dir = introspect.resolveZigLibDir(allocator) catch process.exit(1);
|
const zig_lib_dir = introspect.resolveZigLibDir(allocator) catch process.exit(1);
|
||||||
defer allocator.free(zig_lib_dir);
|
defer allocator.free(zig_lib_dir);
|
||||||
@ -396,74 +466,60 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co
|
|||||||
var comp = try Compilation.create(
|
var comp = try Compilation.create(
|
||||||
&zig_compiler,
|
&zig_compiler,
|
||||||
root_name,
|
root_name,
|
||||||
root_source_file,
|
root_src_file,
|
||||||
Target.Native,
|
Target.Native,
|
||||||
out_type,
|
out_type,
|
||||||
build_mode,
|
build_mode,
|
||||||
is_static,
|
!is_dynamic,
|
||||||
zig_lib_dir,
|
zig_lib_dir,
|
||||||
);
|
);
|
||||||
defer comp.destroy();
|
defer comp.destroy();
|
||||||
|
|
||||||
if (flags.single("libc")) |libc_path| {
|
if (libc_arg) |libc_path| {
|
||||||
parseLibcPaths(allocator, &override_libc, libc_path);
|
parseLibcPaths(allocator, &override_libc, libc_path);
|
||||||
comp.override_libc = &override_libc;
|
comp.override_libc = &override_libc;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (flags.many("library")) |lib| {
|
for (system_libs.toSliceConst()) |lib| {
|
||||||
_ = try comp.addLinkLib(lib, true);
|
_ = try comp.addLinkLib(lib, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
comp.version_major = try std.fmt.parseUnsigned(u32, flags.single("ver-major") orelse "0", 10);
|
comp.version = version;
|
||||||
comp.version_minor = try std.fmt.parseUnsigned(u32, flags.single("ver-minor") orelse "0", 10);
|
|
||||||
comp.version_patch = try std.fmt.parseUnsigned(u32, flags.single("ver-patch") orelse "0", 10);
|
|
||||||
|
|
||||||
comp.is_test = false;
|
comp.is_test = false;
|
||||||
|
comp.linker_script = linker_script;
|
||||||
comp.linker_script = flags.single("linker-script");
|
|
||||||
comp.each_lib_rpath = flags.present("each-lib-rpath");
|
|
||||||
|
|
||||||
comp.clang_argv = clang_argv_buf.toSliceConst();
|
comp.clang_argv = clang_argv_buf.toSliceConst();
|
||||||
|
comp.strip = strip;
|
||||||
|
|
||||||
comp.strip = flags.present("strip");
|
comp.verbose_tokenize = verbose_tokenize;
|
||||||
|
comp.verbose_ast_tree = verbose_ast_tree;
|
||||||
comp.verbose_tokenize = flags.present("verbose-tokenize");
|
comp.verbose_ast_fmt = verbose_ast_fmt;
|
||||||
comp.verbose_ast_tree = flags.present("verbose-ast-tree");
|
comp.verbose_link = verbose_link;
|
||||||
comp.verbose_ast_fmt = flags.present("verbose-ast-fmt");
|
comp.verbose_ir = verbose_ir;
|
||||||
comp.verbose_link = flags.present("verbose-link");
|
comp.verbose_llvm_ir = verbose_llvm_ir;
|
||||||
comp.verbose_ir = flags.present("verbose-ir");
|
comp.verbose_cimport = verbose_cimport;
|
||||||
comp.verbose_llvm_ir = flags.present("verbose-llvm-ir");
|
|
||||||
comp.verbose_cimport = flags.present("verbose-cimport");
|
|
||||||
|
|
||||||
comp.err_color = color;
|
comp.err_color = color;
|
||||||
comp.lib_dirs = flags.many("library-path");
|
|
||||||
comp.darwin_frameworks = flags.many("framework");
|
|
||||||
comp.rpath_list = flags.many("rpath");
|
|
||||||
|
|
||||||
if (flags.single("output-h")) |output_h| {
|
comp.linker_rdynamic = linker_rdynamic;
|
||||||
comp.out_h_path = output_h;
|
|
||||||
}
|
|
||||||
|
|
||||||
comp.windows_subsystem_windows = flags.present("mwindows");
|
if (macosx_version_min != null and ios_version_min != null) {
|
||||||
comp.windows_subsystem_console = flags.present("mconsole");
|
|
||||||
comp.linker_rdynamic = flags.present("rdynamic");
|
|
||||||
|
|
||||||
if (flags.single("mmacosx-version-min") != null and flags.single("mios-version-min") != null) {
|
|
||||||
try stderr.write("-mmacosx-version-min and -mios-version-min options not allowed together\n");
|
try stderr.write("-mmacosx-version-min and -mios-version-min options not allowed together\n");
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags.single("mmacosx-version-min")) |ver| {
|
if (macosx_version_min) |ver| {
|
||||||
comp.darwin_version_min = Compilation.DarwinVersionMin{ .MacOS = ver };
|
comp.darwin_version_min = Compilation.DarwinVersionMin{ .MacOS = ver };
|
||||||
}
|
}
|
||||||
if (flags.single("mios-version-min")) |ver| {
|
if (ios_version_min) |ver| {
|
||||||
comp.darwin_version_min = Compilation.DarwinVersionMin{ .Ios = ver };
|
comp.darwin_version_min = Compilation.DarwinVersionMin{ .Ios = ver };
|
||||||
}
|
}
|
||||||
|
|
||||||
comp.emit_file_type = emit_type;
|
comp.emit_bin = emit_bin;
|
||||||
comp.assembly_files = assembly_files;
|
comp.emit_asm = emit_asm;
|
||||||
comp.link_out_file = flags.single("output");
|
comp.emit_llvm_ir = emit_llvm_ir;
|
||||||
comp.link_objects = link_objects;
|
comp.emit_h = emit_h;
|
||||||
|
comp.assembly_files = assembly_files.toSliceConst();
|
||||||
|
comp.link_objects = link_objects.toSliceConst();
|
||||||
|
|
||||||
comp.start();
|
comp.start();
|
||||||
processBuildEvents(comp, color);
|
processBuildEvents(comp, color);
|
||||||
@ -522,17 +578,6 @@ pub const usage_fmt =
|
|||||||
\\
|
\\
|
||||||
;
|
;
|
||||||
|
|
||||||
pub const args_fmt_spec = [_]Flag{
|
|
||||||
Flag.Bool("--help"),
|
|
||||||
Flag.Bool("--check"),
|
|
||||||
Flag.Option("--color", &[_][]const u8{
|
|
||||||
"auto",
|
|
||||||
"off",
|
|
||||||
"on",
|
|
||||||
}),
|
|
||||||
Flag.Bool("--stdin"),
|
|
||||||
};
|
|
||||||
|
|
||||||
const Fmt = struct {
|
const Fmt = struct {
|
||||||
seen: event.Locked(SeenMap),
|
seen: event.Locked(SeenMap),
|
||||||
any_error: bool,
|
any_error: bool,
|
||||||
@ -578,30 +623,52 @@ fn cmdLibC(allocator: *Allocator, args: []const []const u8) !void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void {
|
fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void {
|
||||||
var flags = try Args.parse(allocator, &args_fmt_spec, args);
|
var color: errmsg.Color = .Auto;
|
||||||
defer flags.deinit();
|
var stdin_flag: bool = false;
|
||||||
|
var check_flag: bool = false;
|
||||||
|
var input_files = ArrayList([]const u8).init(allocator);
|
||||||
|
|
||||||
if (flags.present("help")) {
|
{
|
||||||
try stdout.write(usage_fmt);
|
var i: usize = 0;
|
||||||
process.exit(0);
|
while (i < args.len) : (i += 1) {
|
||||||
|
const arg = args[i];
|
||||||
|
if (mem.startsWith(u8, arg, "-")) {
|
||||||
|
if (mem.eql(u8, arg, "--help")) {
|
||||||
|
try stdout.write(usage_fmt);
|
||||||
|
process.exit(0);
|
||||||
|
} else if (mem.eql(u8, arg, "--color")) {
|
||||||
|
if (i + 1 >= args.len) {
|
||||||
|
try stderr.write("expected [auto|on|off] after --color\n");
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
i += 1;
|
||||||
|
const next_arg = args[i];
|
||||||
|
if (mem.eql(u8, next_arg, "auto")) {
|
||||||
|
color = .Auto;
|
||||||
|
} else if (mem.eql(u8, next_arg, "on")) {
|
||||||
|
color = .On;
|
||||||
|
} else if (mem.eql(u8, next_arg, "off")) {
|
||||||
|
color = .Off;
|
||||||
|
} else {
|
||||||
|
try stderr.print("expected [auto|on|off] after --color, found '{}'\n", .{next_arg});
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
} else if (mem.eql(u8, arg, "--stdin")) {
|
||||||
|
stdin_flag = true;
|
||||||
|
} else if (mem.eql(u8, arg, "--check")) {
|
||||||
|
check_flag = true;
|
||||||
|
} else {
|
||||||
|
try stderr.print("unrecognized parameter: '{}'", .{arg});
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
try input_files.append(arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const color: errmsg.Color = blk: {
|
if (stdin_flag) {
|
||||||
if (flags.single("color")) |color_flag| {
|
if (input_files.len != 0) {
|
||||||
if (mem.eql(u8, color_flag, "auto")) {
|
|
||||||
break :blk .Auto;
|
|
||||||
} else if (mem.eql(u8, color_flag, "on")) {
|
|
||||||
break :blk .On;
|
|
||||||
} else if (mem.eql(u8, color_flag, "off")) {
|
|
||||||
break :blk .Off;
|
|
||||||
} else unreachable;
|
|
||||||
} else {
|
|
||||||
break :blk .Auto;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if (flags.present("stdin")) {
|
|
||||||
if (flags.positionals.len != 0) {
|
|
||||||
try stderr.write("cannot use --stdin with positional arguments\n");
|
try stderr.write("cannot use --stdin with positional arguments\n");
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
@ -628,7 +695,7 @@ fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void {
|
|||||||
if (tree.errors.len != 0) {
|
if (tree.errors.len != 0) {
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
if (flags.present("check")) {
|
if (check_flag) {
|
||||||
const anything_changed = try std.zig.render(allocator, io.null_out_stream, tree);
|
const anything_changed = try std.zig.render(allocator, io.null_out_stream, tree);
|
||||||
const code: u8 = if (anything_changed) 1 else 0;
|
const code: u8 = if (anything_changed) 1 else 0;
|
||||||
process.exit(code);
|
process.exit(code);
|
||||||
@ -638,7 +705,7 @@ fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags.positionals.len == 0) {
|
if (input_files.len == 0) {
|
||||||
try stderr.write("expected at least one source file argument\n");
|
try stderr.write("expected at least one source file argument\n");
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
@ -650,11 +717,9 @@ fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void {
|
|||||||
.color = color,
|
.color = color,
|
||||||
};
|
};
|
||||||
|
|
||||||
const check_mode = flags.present("check");
|
|
||||||
|
|
||||||
var group = event.Group(FmtError!void).init(allocator);
|
var group = event.Group(FmtError!void).init(allocator);
|
||||||
for (flags.positionals.toSliceConst()) |file_path| {
|
for (input_files.toSliceConst()) |file_path| {
|
||||||
try group.call(fmtPath, .{ &fmt, file_path, check_mode });
|
try group.call(fmtPath, .{ &fmt, file_path, check_flag });
|
||||||
}
|
}
|
||||||
try group.wait();
|
try group.wait();
|
||||||
if (fmt.any_error) {
|
if (fmt.any_error) {
|
||||||
@ -808,8 +873,6 @@ fn cmdVersion(allocator: *Allocator, args: []const []const u8) !void {
|
|||||||
try stdout.print("{}\n", .{std.mem.toSliceConst(u8, c.ZIG_VERSION_STRING)});
|
try stdout.print("{}\n", .{std.mem.toSliceConst(u8, c.ZIG_VERSION_STRING)});
|
||||||
}
|
}
|
||||||
|
|
||||||
const args_test_spec = [_]Flag{Flag.Bool("--help")};
|
|
||||||
|
|
||||||
fn cmdHelp(allocator: *Allocator, args: []const []const u8) !void {
|
fn cmdHelp(allocator: *Allocator, args: []const []const u8) !void {
|
||||||
try stdout.write(usage);
|
try stdout.write(usage);
|
||||||
}
|
}
|
||||||
|
@ -9,10 +9,7 @@ const process = std.process;
|
|||||||
const Allocator = mem.Allocator;
|
const Allocator = mem.Allocator;
|
||||||
const ArrayList = std.ArrayList;
|
const ArrayList = std.ArrayList;
|
||||||
const Buffer = std.Buffer;
|
const Buffer = std.Buffer;
|
||||||
const arg = @import("arg.zig");
|
|
||||||
const self_hosted_main = @import("main.zig");
|
const self_hosted_main = @import("main.zig");
|
||||||
const Args = arg.Args;
|
|
||||||
const Flag = arg.Flag;
|
|
||||||
const errmsg = @import("errmsg.zig");
|
const errmsg = @import("errmsg.zig");
|
||||||
const DepTokenizer = @import("dep_tokenizer.zig").Tokenizer;
|
const DepTokenizer = @import("dep_tokenizer.zig").Tokenizer;
|
||||||
|
|
||||||
@ -169,31 +166,54 @@ fn fmtMain(argc: c_int, argv: [*]const [*:0]const u8) !void {
|
|||||||
stderr_file = std.io.getStdErr();
|
stderr_file = std.io.getStdErr();
|
||||||
stderr = &stderr_file.outStream().stream;
|
stderr = &stderr_file.outStream().stream;
|
||||||
|
|
||||||
const args = args_list.toSliceConst();
|
const args = args_list.toSliceConst()[2..];
|
||||||
var flags = try Args.parse(allocator, &self_hosted_main.args_fmt_spec, args[2..]);
|
|
||||||
defer flags.deinit();
|
|
||||||
|
|
||||||
if (flags.present("help")) {
|
var color: errmsg.Color = .Auto;
|
||||||
try stdout.write(self_hosted_main.usage_fmt);
|
var stdin_flag: bool = false;
|
||||||
process.exit(0);
|
var check_flag: bool = false;
|
||||||
|
var input_files = ArrayList([]const u8).init(allocator);
|
||||||
|
|
||||||
|
{
|
||||||
|
var i: usize = 0;
|
||||||
|
while (i < args.len) : (i += 1) {
|
||||||
|
const arg = args[i];
|
||||||
|
if (mem.startsWith(u8, arg, "-")) {
|
||||||
|
if (mem.eql(u8, arg, "--help")) {
|
||||||
|
try stdout.write(self_hosted_main.usage_fmt);
|
||||||
|
process.exit(0);
|
||||||
|
} else if (mem.eql(u8, arg, "--color")) {
|
||||||
|
if (i + 1 >= args.len) {
|
||||||
|
try stderr.write("expected [auto|on|off] after --color\n");
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
i += 1;
|
||||||
|
const next_arg = args[i];
|
||||||
|
if (mem.eql(u8, next_arg, "auto")) {
|
||||||
|
color = .Auto;
|
||||||
|
} else if (mem.eql(u8, next_arg, "on")) {
|
||||||
|
color = .On;
|
||||||
|
} else if (mem.eql(u8, next_arg, "off")) {
|
||||||
|
color = .Off;
|
||||||
|
} else {
|
||||||
|
try stderr.print("expected [auto|on|off] after --color, found '{}'\n", .{next_arg});
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
} else if (mem.eql(u8, arg, "--stdin")) {
|
||||||
|
stdin_flag = true;
|
||||||
|
} else if (mem.eql(u8, arg, "--check")) {
|
||||||
|
check_flag = true;
|
||||||
|
} else {
|
||||||
|
try stderr.print("unrecognized parameter: '{}'", .{arg});
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
try input_files.append(arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const color = blk: {
|
if (stdin_flag) {
|
||||||
if (flags.single("color")) |color_flag| {
|
if (input_files.len != 0) {
|
||||||
if (mem.eql(u8, color_flag, "auto")) {
|
|
||||||
break :blk errmsg.Color.Auto;
|
|
||||||
} else if (mem.eql(u8, color_flag, "on")) {
|
|
||||||
break :blk errmsg.Color.On;
|
|
||||||
} else if (mem.eql(u8, color_flag, "off")) {
|
|
||||||
break :blk errmsg.Color.Off;
|
|
||||||
} else unreachable;
|
|
||||||
} else {
|
|
||||||
break :blk errmsg.Color.Auto;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if (flags.present("stdin")) {
|
|
||||||
if (flags.positionals.len != 0) {
|
|
||||||
try stderr.write("cannot use --stdin with positional arguments\n");
|
try stderr.write("cannot use --stdin with positional arguments\n");
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
@ -217,7 +237,7 @@ fn fmtMain(argc: c_int, argv: [*]const [*:0]const u8) !void {
|
|||||||
if (tree.errors.len != 0) {
|
if (tree.errors.len != 0) {
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
if (flags.present("check")) {
|
if (check_flag) {
|
||||||
const anything_changed = try std.zig.render(allocator, io.null_out_stream, tree);
|
const anything_changed = try std.zig.render(allocator, io.null_out_stream, tree);
|
||||||
const code = if (anything_changed) @as(u8, 1) else @as(u8, 0);
|
const code = if (anything_changed) @as(u8, 1) else @as(u8, 0);
|
||||||
process.exit(code);
|
process.exit(code);
|
||||||
@ -227,7 +247,7 @@ fn fmtMain(argc: c_int, argv: [*]const [*:0]const u8) !void {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags.positionals.len == 0) {
|
if (input_files.len == 0) {
|
||||||
try stderr.write("expected at least one source file argument\n");
|
try stderr.write("expected at least one source file argument\n");
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
@ -239,10 +259,8 @@ fn fmtMain(argc: c_int, argv: [*]const [*:0]const u8) !void {
|
|||||||
.allocator = allocator,
|
.allocator = allocator,
|
||||||
};
|
};
|
||||||
|
|
||||||
const check_mode = flags.present("check");
|
for (input_files.toSliceConst()) |file_path| {
|
||||||
|
try fmtPath(&fmt, file_path, check_flag);
|
||||||
for (flags.positionals.toSliceConst()) |file_path| {
|
|
||||||
try fmtPath(&fmt, file_path, check_mode);
|
|
||||||
}
|
}
|
||||||
if (fmt.any_error) {
|
if (fmt.any_error) {
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
|
Loading…
Reference in New Issue
Block a user