| author | |
| committer | |
| log | 7c1dbfab724291b492be5e64fd93ec14e48b202c |
| tree | e109e0fd711ca766ea148b1965b8762f3e24f4ea |
| parent | c3d8b1ffebb94d180c382bd74128d17dc21c1392 |
| signature |
7 files changed, 372 insertions(+), 760 deletions(-)
lib/std/meta/trait.zig-13| ... | ... | @@ -14,7 +14,6 @@ fn traitFnWorkaround(comptime T: type) bool { |
| 14 | 14 | } |
| 15 | 15 | |
| 16 | 16 | pub const TraitFn = @TypeOf(traitFnWorkaround); |
| 17 | /// | |
| 18 | 17 | |
| 19 | 18 | //////Trait generators |
| 20 | 19 | |
| ... | ... | @@ -55,7 +54,6 @@ test "std.meta.trait.multiTrait" { |
| 55 | 54 | testing.expect(!isVector(u8)); |
| 56 | 55 | } |
| 57 | 56 | |
| 58 | /// | |
| 59 | 57 | pub fn hasFn(comptime name: []const u8) TraitFn { |
| 60 | 58 | const Closure = struct { |
| 61 | 59 | pub fn trait(comptime T: type) bool { |
| ... | ... | @@ -79,7 +77,6 @@ test "std.meta.trait.hasFn" { |
| 79 | 77 | testing.expect(!hasFn("useless")(u8)); |
| 80 | 78 | } |
| 81 | 79 | |
| 82 | /// | |
| 83 | 80 | pub fn hasField(comptime name: []const u8) TraitFn { |
| 84 | 81 | const Closure = struct { |
| 85 | 82 | pub fn trait(comptime T: type) bool { |
| ... | ... | @@ -113,7 +110,6 @@ test "std.meta.trait.hasField" { |
| 113 | 110 | testing.expect(!hasField("value")(u8)); |
| 114 | 111 | } |
| 115 | 112 | |
| 116 | /// | |
| 117 | 113 | pub fn is(comptime id: builtin.TypeId) TraitFn { |
| 118 | 114 | const Closure = struct { |
| 119 | 115 | pub fn trait(comptime T: type) bool { |
| ... | ... | @@ -131,7 +127,6 @@ test "std.meta.trait.is" { |
| 131 | 127 | testing.expect(!is(builtin.TypeId.Optional)(anyerror)); |
| 132 | 128 | } |
| 133 | 129 | |
| 134 | /// | |
| 135 | 130 | pub fn isPtrTo(comptime id: builtin.TypeId) TraitFn { |
| 136 | 131 | const Closure = struct { |
| 137 | 132 | pub fn trait(comptime T: type) bool { |
| ... | ... | @@ -173,7 +168,6 @@ test "std.meta.trait.isExtern" { |
| 173 | 168 | testing.expect(!isExtern(u8)); |
| 174 | 169 | } |
| 175 | 170 | |
| 176 | /// | |
| 177 | 171 | pub fn isPacked(comptime T: type) bool { |
| 178 | 172 | const Packed = builtin.TypeInfo.ContainerLayout.Packed; |
| 179 | 173 | const info = @typeInfo(T); |
| ... | ... | @@ -194,7 +188,6 @@ test "std.meta.trait.isPacked" { |
| 194 | 188 | testing.expect(!isPacked(u8)); |
| 195 | 189 | } |
| 196 | 190 | |
| 197 | /// | |
| 198 | 191 | pub fn isUnsignedInt(comptime T: type) bool { |
| 199 | 192 | return switch (@typeId(T)) { |
| 200 | 193 | builtin.TypeId.Int => !@typeInfo(T).Int.is_signed, |
| ... | ... | @@ -209,7 +202,6 @@ test "isUnsignedInt" { |
| 209 | 202 | testing.expect(isUnsignedInt(f64) == false); |
| 210 | 203 | } |
| 211 | 204 | |
| 212 | /// | |
| 213 | 205 | pub fn isSignedInt(comptime T: type) bool { |
| 214 | 206 | return switch (@typeId(T)) { |
| 215 | 207 | builtin.TypeId.ComptimeInt => true, |
| ... | ... | @@ -225,7 +217,6 @@ test "isSignedInt" { |
| 225 | 217 | testing.expect(isSignedInt(f64) == false); |
| 226 | 218 | } |
| 227 | 219 | |
| 228 | /// | |
| 229 | 220 | pub fn isSingleItemPtr(comptime T: type) bool { |
| 230 | 221 | if (comptime is(builtin.TypeId.Pointer)(T)) { |
| 231 | 222 | const info = @typeInfo(T); |
| ... | ... | @@ -241,7 +232,6 @@ test "std.meta.trait.isSingleItemPtr" { |
| 241 | 232 | testing.expect(!isSingleItemPtr(@TypeOf(array[0..1]))); |
| 242 | 233 | } |
| 243 | 234 | |
| 244 | /// | |
| 245 | 235 | pub fn isManyItemPtr(comptime T: type) bool { |
| 246 | 236 | if (comptime is(builtin.TypeId.Pointer)(T)) { |
| 247 | 237 | const info = @typeInfo(T); |
| ... | ... | @@ -258,7 +248,6 @@ test "std.meta.trait.isManyItemPtr" { |
| 258 | 248 | testing.expect(!isManyItemPtr(@TypeOf(array[0..1]))); |
| 259 | 249 | } |
| 260 | 250 | |
| 261 | /// | |
| 262 | 251 | pub fn isSlice(comptime T: type) bool { |
| 263 | 252 | if (comptime is(builtin.TypeId.Pointer)(T)) { |
| 264 | 253 | const info = @typeInfo(T); |
| ... | ... | @@ -274,7 +263,6 @@ test "std.meta.trait.isSlice" { |
| 274 | 263 | testing.expect(!isSlice(@TypeOf(&array[0]))); |
| 275 | 264 | } |
| 276 | 265 | |
| 277 | /// | |
| 278 | 266 | pub fn isIndexable(comptime T: type) bool { |
| 279 | 267 | if (comptime is(builtin.TypeId.Pointer)(T)) { |
| 280 | 268 | const info = @typeInfo(T); |
| ... | ... | @@ -297,7 +285,6 @@ test "std.meta.trait.isIndexable" { |
| 297 | 285 | testing.expect(!isIndexable(meta.Child(@TypeOf(slice)))); |
| 298 | 286 | } |
| 299 | 287 | |
| 300 | /// | |
| 301 | 288 | pub fn isNumber(comptime T: type) bool { |
| 302 | 289 | return switch (@typeId(T)) { |
| 303 | 290 | builtin.TypeId.Int, builtin.TypeId.Float, builtin.TypeId.ComptimeInt, builtin.TypeId.ComptimeFloat => true, |
src-self-hosted/arg.zig deleted-293| ... | ... | @@ -1,293 +0,0 @@ |
| 1 | const std = @import("std"); | |
| 2 | const debug = std.debug; | |
| 3 | const testing = std.testing; | |
| 4 | const mem = std.mem; | |
| 5 | ||
| 6 | const Allocator = mem.Allocator; | |
| 7 | const ArrayList = std.ArrayList; | |
| 8 | const StringHashMap = std.StringHashMap; | |
| 9 | ||
| 10 | fn trimStart(slice: []const u8, ch: u8) []const u8 { | |
| 11 | var i: usize = 0; | |
| 12 | for (slice) |b| { | |
| 13 | if (b != '-') break; | |
| 14 | i += 1; | |
| 15 | } | |
| 16 | ||
| 17 | return slice[i..]; | |
| 18 | } | |
| 19 | ||
| 20 | fn argInAllowedSet(maybe_set: ?[]const []const u8, arg: []const u8) bool { | |
| 21 | if (maybe_set) |set| { | |
| 22 | for (set) |possible| { | |
| 23 | if (mem.eql(u8, arg, possible)) { | |
| 24 | return true; | |
| 25 | } | |
| 26 | } | |
| 27 | return false; | |
| 28 | } else { | |
| 29 | return true; | |
| 30 | } | |
| 31 | } | |
| 32 | ||
| 33 | // Modifies the current argument index during iteration | |
| 34 | fn readFlagArguments(allocator: *Allocator, args: []const []const u8, required: usize, allowed_set: ?[]const []const u8, index: *usize) !FlagArg { | |
| 35 | switch (required) { | |
| 36 | 0 => return FlagArg{ .None = undefined }, // TODO: Required to force non-tag but value? | |
| 37 | 1 => { | |
| 38 | if (index.* + 1 >= args.len) { | |
| 39 | return error.MissingFlagArguments; | |
| 40 | } | |
| 41 | ||
| 42 | index.* += 1; | |
| 43 | const arg = args[index.*]; | |
| 44 | ||
| 45 | if (!argInAllowedSet(allowed_set, arg)) { | |
| 46 | return error.ArgumentNotInAllowedSet; | |
| 47 | } | |
| 48 | ||
| 49 | return FlagArg{ .Single = arg }; | |
| 50 | }, | |
| 51 | else => |needed| { | |
| 52 | var extra = ArrayList([]const u8).init(allocator); | |
| 53 | errdefer extra.deinit(); | |
| 54 | ||
| 55 | var j: usize = 0; | |
| 56 | while (j < needed) : (j += 1) { | |
| 57 | if (index.* + 1 >= args.len) { | |
| 58 | return error.MissingFlagArguments; | |
| 59 | } | |
| 60 | ||
| 61 | index.* += 1; | |
| 62 | const arg = args[index.*]; | |
| 63 | ||
| 64 | if (!argInAllowedSet(allowed_set, arg)) { | |
| 65 | return error.ArgumentNotInAllowedSet; | |
| 66 | } | |
| 67 | ||
| 68 | try extra.append(arg); | |
| 69 | } | |
| 70 | ||
| 71 | return FlagArg{ .Many = extra }; | |
| 72 | }, | |
| 73 | } | |
| 74 | } | |
| 75 | ||
| 76 | const HashMapFlags = StringHashMap(FlagArg); | |
| 77 | ||
| 78 | // A store for querying found flags and positional arguments. | |
| 79 | pub const Args = struct { | |
| 80 | flags: HashMapFlags, | |
| 81 | positionals: ArrayList([]const u8), | |
| 82 | ||
| 83 | pub fn parse(allocator: *Allocator, comptime spec: []const Flag, args: []const []const u8) !Args { | |
| 84 | var parsed = Args{ | |
| 85 | .flags = HashMapFlags.init(allocator), | |
| 86 | .positionals = ArrayList([]const u8).init(allocator), | |
| 87 | }; | |
| 88 | ||
| 89 | var i: usize = 0; | |
| 90 | next: while (i < args.len) : (i += 1) { | |
| 91 | const arg = args[i]; | |
| 92 | ||
| 93 | if (arg.len != 0 and arg[0] == '-') { | |
| 94 | // TODO: hashmap, although the linear scan is okay for small argument sets as is | |
| 95 | for (spec) |flag| { | |
| 96 | if (mem.eql(u8, arg, flag.name)) { | |
| 97 | const flag_name_trimmed = trimStart(flag.name, '-'); | |
| 98 | const flag_args = readFlagArguments(allocator, args, flag.required, flag.allowed_set, &i) catch |err| { | |
| 99 | switch (err) { | |
| 100 | error.ArgumentNotInAllowedSet => { | |
| 101 | std.debug.warn("argument '{}' is invalid for flag '{}'\n", .{ args[i], arg }); | |
| 102 | std.debug.warn("allowed options are ", .{}); | |
| 103 | for (flag.allowed_set.?) |possible| { | |
| 104 | std.debug.warn("'{}' ", .{possible}); | |
| 105 | } | |
| 106 | std.debug.warn("\n", .{}); | |
| 107 | }, | |
| 108 | error.MissingFlagArguments => { | |
| 109 | std.debug.warn("missing argument for flag: {}\n", .{arg}); | |
| 110 | }, | |
| 111 | else => {}, | |
| 112 | } | |
| 113 | ||
| 114 | return err; | |
| 115 | }; | |
| 116 | ||
| 117 | if (flag.mergable) { | |
| 118 | var prev = if (parsed.flags.get(flag_name_trimmed)) |entry| entry.value.Many else ArrayList([]const u8).init(allocator); | |
| 119 | ||
| 120 | // MergeN creation disallows 0 length flag entry (doesn't make sense) | |
| 121 | switch (flag_args) { | |
| 122 | .None => unreachable, | |
| 123 | .Single => |inner| try prev.append(inner), | |
| 124 | .Many => |inner| try prev.appendSlice(inner.toSliceConst()), | |
| 125 | } | |
| 126 | ||
| 127 | _ = try parsed.flags.put(flag_name_trimmed, FlagArg{ .Many = prev }); | |
| 128 | } else { | |
| 129 | _ = try parsed.flags.put(flag_name_trimmed, flag_args); | |
| 130 | } | |
| 131 | ||
| 132 | continue :next; | |
| 133 | } | |
| 134 | } | |
| 135 | ||
| 136 | // TODO: Better errors with context, global error state and return is sufficient. | |
| 137 | std.debug.warn("could not match flag: {}\n", .{arg}); | |
| 138 | return error.UnknownFlag; | |
| 139 | } else { | |
| 140 | try parsed.positionals.append(arg); | |
| 141 | } | |
| 142 | } | |
| 143 | ||
| 144 | return parsed; | |
| 145 | } | |
| 146 | ||
| 147 | pub fn deinit(self: *Args) void { | |
| 148 | self.flags.deinit(); | |
| 149 | self.positionals.deinit(); | |
| 150 | } | |
| 151 | ||
| 152 | // e.g. --help | |
| 153 | pub fn present(self: *const Args, name: []const u8) bool { | |
| 154 | return self.flags.contains(name); | |
| 155 | } | |
| 156 | ||
| 157 | // e.g. --name value | |
| 158 | pub fn single(self: *Args, name: []const u8) ?[]const u8 { | |
| 159 | if (self.flags.get(name)) |entry| { | |
| 160 | switch (entry.value) { | |
| 161 | .Single => |inner| { | |
| 162 | return inner; | |
| 163 | }, | |
| 164 | else => @panic("attempted to retrieve flag with wrong type"), | |
| 165 | } | |
| 166 | } else { | |
| 167 | return null; | |
| 168 | } | |
| 169 | } | |
| 170 | ||
| 171 | // e.g. --names value1 value2 value3 | |
| 172 | pub fn many(self: *Args, name: []const u8) []const []const u8 { | |
| 173 | if (self.flags.get(name)) |entry| { | |
| 174 | switch (entry.value) { | |
| 175 | .Many => |inner| { | |
| 176 | return inner.toSliceConst(); | |
| 177 | }, | |
| 178 | else => @panic("attempted to retrieve flag with wrong type"), | |
| 179 | } | |
| 180 | } else { | |
| 181 | return &[_][]const u8{}; | |
| 182 | } | |
| 183 | } | |
| 184 | }; | |
| 185 | ||
| 186 | // Arguments for a flag. e.g. arg1, arg2 in `--command arg1 arg2`. | |
| 187 | const FlagArg = union(enum) { | |
| 188 | None, | |
| 189 | Single: []const u8, | |
| 190 | Many: ArrayList([]const u8), | |
| 191 | }; | |
| 192 | ||
| 193 | // Specification for how a flag should be parsed. | |
| 194 | pub const Flag = struct { | |
| 195 | name: []const u8, | |
| 196 | required: usize, | |
| 197 | mergable: bool, | |
| 198 | allowed_set: ?[]const []const u8, | |
| 199 | ||
| 200 | pub fn Bool(comptime name: []const u8) Flag { | |
| 201 | return ArgN(name, 0); | |
| 202 | } | |
| 203 | ||
| 204 | pub fn Arg1(comptime name: []const u8) Flag { | |
| 205 | return ArgN(name, 1); | |
| 206 | } | |
| 207 | ||
| 208 | pub fn ArgN(comptime name: []const u8, comptime n: usize) Flag { | |
| 209 | return Flag{ | |
| 210 | .name = name, | |
| 211 | .required = n, | |
| 212 | .mergable = false, | |
| 213 | .allowed_set = null, | |
| 214 | }; | |
| 215 | } | |
| 216 | ||
| 217 | pub fn ArgMergeN(comptime name: []const u8, comptime n: usize) Flag { | |
| 218 | if (n == 0) { | |
| 219 | @compileError("n must be greater than 0"); | |
| 220 | } | |
| 221 | ||
| 222 | return Flag{ | |
| 223 | .name = name, | |
| 224 | .required = n, | |
| 225 | .mergable = true, | |
| 226 | .allowed_set = null, | |
| 227 | }; | |
| 228 | } | |
| 229 | ||
| 230 | pub fn Option(comptime name: []const u8, comptime set: []const []const u8) Flag { | |
| 231 | return Flag{ | |
| 232 | .name = name, | |
| 233 | .required = 1, | |
| 234 | .mergable = false, | |
| 235 | .allowed_set = set, | |
| 236 | }; | |
| 237 | } | |
| 238 | }; | |
| 239 | ||
| 240 | test "parse arguments" { | |
| 241 | const spec1 = comptime [_]Flag{ | |
| 242 | Flag.Bool("--help"), | |
| 243 | Flag.Bool("--init"), | |
| 244 | Flag.Arg1("--build-file"), | |
| 245 | Flag.Option("--color", [_][]const u8{ | |
| 246 | "on", | |
| 247 | "off", | |
| 248 | "auto", | |
| 249 | }), | |
| 250 | Flag.ArgN("--pkg-begin", 2), | |
| 251 | Flag.ArgMergeN("--object", 1), | |
| 252 | Flag.ArgN("--library", 1), | |
| 253 | }; | |
| 254 | ||
| 255 | const cliargs = [_][]const u8{ | |
| 256 | "build", | |
| 257 | "--help", | |
| 258 | "pos1", | |
| 259 | "--build-file", | |
| 260 | "build.zig", | |
| 261 | "--object", | |
| 262 | "obj1", | |
| 263 | "--object", | |
| 264 | "obj2", | |
| 265 | "--library", | |
| 266 | "lib1", | |
| 267 | "--library", | |
| 268 | "lib2", | |
| 269 | "--color", | |
| 270 | "on", | |
| 271 | "pos2", | |
| 272 | }; | |
| 273 | ||
| 274 | var args = try Args.parse(std.debug.global_allocator, spec1, cliargs); | |
| 275 | ||
| 276 | testing.expect(args.present("help")); | |
| 277 | testing.expect(!args.present("help2")); | |
| 278 | testing.expect(!args.present("init")); | |
| 279 | ||
| 280 | testing.expect(mem.eql(u8, args.single("build-file").?, "build.zig")); | |
| 281 | testing.expect(mem.eql(u8, args.single("color").?, "on")); | |
| 282 | ||
| 283 | const objects = args.many("object").?; | |
| 284 | testing.expect(mem.eql(u8, objects[0], "obj1")); | |
| 285 | testing.expect(mem.eql(u8, objects[1], "obj2")); | |
| 286 | ||
| 287 | testing.expect(mem.eql(u8, args.single("library").?, "lib2")); | |
| 288 | ||
| 289 | const pos = args.positionals.toSliceConst(); | |
| 290 | testing.expect(mem.eql(u8, pos[0], "build")); | |
| 291 | testing.expect(mem.eql(u8, pos[1], "pos1")); | |
| 292 | testing.expect(mem.eql(u8, pos[2], "pos2")); | |
| 293 | } |
src-self-hosted/codegen.zig-2| ... | ... | @@ -101,8 +101,6 @@ pub async fn renderToLlvm(comp: *Compilation, fn_val: *Value.Fn, code: *ir.Code) |
| 101 | 101 | _ = llvm.VerifyModule(ofile.module, llvm.AbortProcessAction, &error_ptr); |
| 102 | 102 | } |
| 103 | 103 | |
| 104 | assert(comp.emit_file_type == Compilation.Emit.Binary); // TODO support other types | |
| 105 | ||
| 106 | 104 | const is_small = comp.build_mode == .ReleaseSmall; |
| 107 | 105 | const is_debug = comp.build_mode == .Debug; |
| 108 | 106 |
src-self-hosted/compilation.zig+5-12| ... | ... | @@ -135,22 +135,17 @@ pub const Compilation = struct { |
| 135 | 135 | /// lazily created when we need it |
| 136 | 136 | tmp_dir: event.Future(BuildError![]u8) = event.Future(BuildError![]u8).init(), |
| 137 | 137 | |
| 138 | version_major: u32 = 0, | |
| 139 | version_minor: u32 = 0, | |
| 140 | version_patch: u32 = 0, | |
| 138 | version: builtin.Version = builtin.Version{ .major = 0, .minor = 0, .patch = 0 }, | |
| 141 | 139 | |
| 142 | 140 | linker_script: ?[]const u8 = null, |
| 143 | 141 | out_h_path: ?[]const u8 = null, |
| 144 | 142 | |
| 145 | 143 | is_test: bool = false, |
| 146 | each_lib_rpath: bool = false, | |
| 147 | 144 | strip: bool = false, |
| 148 | 145 | is_static: bool, |
| 149 | 146 | linker_rdynamic: bool = false, |
| 150 | 147 | |
| 151 | 148 | clang_argv: []const []const u8 = &[_][]const u8{}, |
| 152 | lib_dirs: []const []const u8 = &[_][]const u8{}, | |
| 153 | rpath_list: []const []const u8 = &[_][]const u8{}, | |
| 154 | 149 | assembly_files: []const []const u8 = &[_][]const u8{}, |
| 155 | 150 | |
| 156 | 151 | /// paths that are explicitly provided by the user to link against |
| ... | ... | @@ -162,9 +157,6 @@ pub const Compilation = struct { |
| 162 | 157 | |
| 163 | 158 | pub const FnLinkSet = std.TailQueue(?*Value.Fn); |
| 164 | 159 | |
| 165 | windows_subsystem_windows: bool = false, | |
| 166 | windows_subsystem_console: bool = false, | |
| 167 | ||
| 168 | 160 | link_libs_list: ArrayList(*LinkLib), |
| 169 | 161 | libc_link_lib: ?*LinkLib = null, |
| 170 | 162 | |
| ... | ... | @@ -178,17 +170,18 @@ pub const Compilation = struct { |
| 178 | 170 | verbose_llvm_ir: bool = false, |
| 179 | 171 | verbose_link: bool = false, |
| 180 | 172 | |
| 181 | darwin_frameworks: []const []const u8 = &[_][]const u8{}, | |
| 182 | 173 | darwin_version_min: DarwinVersionMin = .None, |
| 183 | 174 | |
| 184 | 175 | test_filters: []const []const u8 = &[_][]const u8{}, |
| 185 | 176 | test_name_prefix: ?[]const u8 = null, |
| 186 | 177 | |
| 187 | emit_file_type: Emit = .Binary, | |
| 178 | emit_bin: bool = true, | |
| 179 | emit_asm: bool = false, | |
| 180 | emit_llvm_ir: bool = false, | |
| 181 | emit_h: bool = false, | |
| 188 | 182 | |
| 189 | 183 | kind: Kind, |
| 190 | 184 | |
| 191 | link_out_file: ?[]const u8 = null, | |
| 192 | 185 | events: *event.Channel(Event), |
| 193 | 186 | |
| 194 | 187 | exported_symbol_names: event.Locked(Decl.Table), |
src-self-hosted/link.zig+11-165| ... | ... | @@ -36,21 +36,17 @@ pub fn link(comp: *Compilation) !void { |
| 36 | 36 | ctx.args = std.ArrayList([*:0]const u8).init(&ctx.arena.allocator); |
| 37 | 37 | ctx.link_msg = std.Buffer.initNull(&ctx.arena.allocator); |
| 38 | 38 | |
| 39 | if (comp.link_out_file) |out_file| { | |
| 40 | ctx.out_file_path = try std.Buffer.init(&ctx.arena.allocator, out_file); | |
| 41 | } else { | |
| 42 | ctx.out_file_path = try std.Buffer.init(&ctx.arena.allocator, comp.name.toSliceConst()); | |
| 43 | switch (comp.kind) { | |
| 44 | .Exe => { | |
| 45 | try ctx.out_file_path.append(comp.target.exeFileExt()); | |
| 46 | }, | |
| 47 | .Lib => { | |
| 48 | try ctx.out_file_path.append(if (comp.is_static) comp.target.staticLibSuffix() else comp.target.dynamicLibSuffix()); | |
| 49 | }, | |
| 50 | .Obj => { | |
| 51 | try ctx.out_file_path.append(comp.target.oFileExt()); | |
| 52 | }, | |
| 53 | } | |
| 39 | ctx.out_file_path = try std.Buffer.init(&ctx.arena.allocator, comp.name.toSliceConst()); | |
| 40 | switch (comp.kind) { | |
| 41 | .Exe => { | |
| 42 | try ctx.out_file_path.append(comp.target.exeFileExt()); | |
| 43 | }, | |
| 44 | .Lib => { | |
| 45 | try ctx.out_file_path.append(if (comp.is_static) comp.target.staticLibSuffix() else comp.target.dynamicLibSuffix()); | |
| 46 | }, | |
| 47 | .Obj => { | |
| 48 | try ctx.out_file_path.append(comp.target.oFileExt()); | |
| 49 | }, | |
| 54 | 50 | } |
| 55 | 51 | |
| 56 | 52 | // even though we're calling LLD as a library it thinks the first |
| ... | ... | @@ -183,37 +179,6 @@ fn constructLinkerArgsElf(ctx: *Context) !void { |
| 183 | 179 | try addPathJoin(ctx, ctx.libc.static_lib_dir.?, crtbegino); |
| 184 | 180 | } |
| 185 | 181 | |
| 186 | //for (size_t i = 0; i < g->rpath_list.length; i += 1) { | |
| 187 | // Buf *rpath = g->rpath_list.at(i); | |
| 188 | // add_rpath(lj, rpath); | |
| 189 | //} | |
| 190 | //if (g->each_lib_rpath) { | |
| 191 | // for (size_t i = 0; i < g->lib_dirs.length; i += 1) { | |
| 192 | // const char *lib_dir = g->lib_dirs.at(i); | |
| 193 | // for (size_t i = 0; i < g->link_libs_list.length; i += 1) { | |
| 194 | // LinkLib *link_lib = g->link_libs_list.at(i); | |
| 195 | // if (buf_eql_str(link_lib->name, "c")) { | |
| 196 | // continue; | |
| 197 | // } | |
| 198 | // bool does_exist; | |
| 199 | // Buf *test_path = buf_sprintf("%s/lib%s.so", lib_dir, buf_ptr(link_lib->name)); | |
| 200 | // if (os_file_exists(test_path, &does_exist) != ErrorNone) { | |
| 201 | // zig_panic("link: unable to check if file exists: %s", buf_ptr(test_path)); | |
| 202 | // } | |
| 203 | // if (does_exist) { | |
| 204 | // add_rpath(lj, buf_create_from_str(lib_dir)); | |
| 205 | // break; | |
| 206 | // } | |
| 207 | // } | |
| 208 | // } | |
| 209 | //} | |
| 210 | ||
| 211 | //for (size_t i = 0; i < g->lib_dirs.length; i += 1) { | |
| 212 | // const char *lib_dir = g->lib_dirs.at(i); | |
| 213 | // lj->args.append("-L"); | |
| 214 | // lj->args.append(lib_dir); | |
| 215 | //} | |
| 216 | ||
| 217 | 182 | if (ctx.comp.haveLibC()) { |
| 218 | 183 | try ctx.args.append("-L"); |
| 219 | 184 | // TODO addNullByte should probably return [:0]u8 |
| ... | ... | @@ -326,12 +291,6 @@ fn constructLinkerArgsCoff(ctx: *Context) !void { |
| 326 | 291 | else => return error.UnsupportedLinkArchitecture, |
| 327 | 292 | } |
| 328 | 293 | |
| 329 | if (ctx.comp.windows_subsystem_windows) { | |
| 330 | try ctx.args.append("/SUBSYSTEM:windows"); | |
| 331 | } else if (ctx.comp.windows_subsystem_console) { | |
| 332 | try ctx.args.append("/SUBSYSTEM:console"); | |
| 333 | } | |
| 334 | ||
| 335 | 294 | const is_library = ctx.comp.kind == .Lib; |
| 336 | 295 | |
| 337 | 296 | 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 { |
| 374 | 333 | try ctx.args.append("-NODEFAULTLIB"); |
| 375 | 334 | if (!is_library) { |
| 376 | 335 | try ctx.args.append("-ENTRY:WinMainCRTStartup"); |
| 377 | // TODO | |
| 378 | //if (g->have_winmain) { | |
| 379 | // lj->args.append("-ENTRY:WinMain"); | |
| 380 | //} else { | |
| 381 | // lj->args.append("-ENTRY:WinMainCRTStartup"); | |
| 382 | //} | |
| 383 | 336 | } |
| 384 | 337 | } |
| 385 | 338 | |
| ... | ... | @@ -387,11 +340,6 @@ fn constructLinkerArgsCoff(ctx: *Context) !void { |
| 387 | 340 | try ctx.args.append("-DLL"); |
| 388 | 341 | } |
| 389 | 342 | |
| 390 | //for (size_t i = 0; i < g->lib_dirs.length; i += 1) { | |
| 391 | // const char *lib_dir = g->lib_dirs.at(i); | |
| 392 | // lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", lib_dir))); | |
| 393 | //} | |
| 394 | ||
| 395 | 343 | for (ctx.comp.link_objects) |link_object| { |
| 396 | 344 | const link_obj_with_null = try std.cstr.addNullByte(&ctx.arena.allocator, link_object); |
| 397 | 345 | try ctx.args.append(@ptrCast([*:0]const u8, link_obj_with_null.ptr)); |
| ... | ... | @@ -402,63 +350,10 @@ fn constructLinkerArgsCoff(ctx: *Context) !void { |
| 402 | 350 | .Exe, .Lib => { |
| 403 | 351 | if (!ctx.comp.haveLibC()) { |
| 404 | 352 | @panic("TODO"); |
| 405 | //Buf *builtin_o_path = build_o(g, "builtin"); | |
| 406 | //lj->args.append(buf_ptr(builtin_o_path)); | |
| 407 | 353 | } |
| 408 | ||
| 409 | // msvc compiler_rt is missing some stuff, so we still build it and rely on weak linkage | |
| 410 | // TODO | |
| 411 | //Buf *compiler_rt_o_path = build_compiler_rt(g); | |
| 412 | //lj->args.append(buf_ptr(compiler_rt_o_path)); | |
| 413 | 354 | }, |
| 414 | 355 | .Obj => {}, |
| 415 | 356 | } |
| 416 | ||
| 417 | //Buf *def_contents = buf_alloc(); | |
| 418 | //ZigList<const char *> gen_lib_args = {0}; | |
| 419 | //for (size_t lib_i = 0; lib_i < g->link_libs_list.length; lib_i += 1) { | |
| 420 | // LinkLib *link_lib = g->link_libs_list.at(lib_i); | |
| 421 | // if (buf_eql_str(link_lib->name, "c")) { | |
| 422 | // continue; | |
| 423 | // } | |
| 424 | // if (link_lib->provided_explicitly) { | |
| 425 | // if (lj->codegen->zig_target.env_type == ZigLLVM_GNU) { | |
| 426 | // Buf *arg = buf_sprintf("-l%s", buf_ptr(link_lib->name)); | |
| 427 | // lj->args.append(buf_ptr(arg)); | |
| 428 | // } | |
| 429 | // else { | |
| 430 | // lj->args.append(buf_ptr(link_lib->name)); | |
| 431 | // } | |
| 432 | // } else { | |
| 433 | // buf_resize(def_contents, 0); | |
| 434 | // buf_appendf(def_contents, "LIBRARY %s\nEXPORTS\n", buf_ptr(link_lib->name)); | |
| 435 | // for (size_t exp_i = 0; exp_i < link_lib->symbols.length; exp_i += 1) { | |
| 436 | // Buf *symbol_name = link_lib->symbols.at(exp_i); | |
| 437 | // buf_appendf(def_contents, "%s\n", buf_ptr(symbol_name)); | |
| 438 | // } | |
| 439 | // buf_appendf(def_contents, "\n"); | |
| 440 | ||
| 441 | // Buf *def_path = buf_alloc(); | |
| 442 | // os_path_join(g->cache_dir, buf_sprintf("%s.def", buf_ptr(link_lib->name)), def_path); | |
| 443 | // os_write_file(def_path, def_contents); | |
| 444 | ||
| 445 | // Buf *generated_lib_path = buf_alloc(); | |
| 446 | // os_path_join(g->cache_dir, buf_sprintf("%s.lib", buf_ptr(link_lib->name)), generated_lib_path); | |
| 447 | ||
| 448 | // gen_lib_args.resize(0); | |
| 449 | // gen_lib_args.append("link"); | |
| 450 | ||
| 451 | // coff_append_machine_arg(g, &gen_lib_args); | |
| 452 | // gen_lib_args.append(buf_ptr(buf_sprintf("-DEF:%s", buf_ptr(def_path)))); | |
| 453 | // gen_lib_args.append(buf_ptr(buf_sprintf("-OUT:%s", buf_ptr(generated_lib_path)))); | |
| 454 | // Buf diag = BUF_INIT; | |
| 455 | // if (!zig_lld_link(g->zig_target.oformat, gen_lib_args.items, gen_lib_args.length, &diag)) { | |
| 456 | // fprintf(stderr, "%s\n", buf_ptr(&diag)); | |
| 457 | // exit(1); | |
| 458 | // } | |
| 459 | // lj->args.append(buf_ptr(generated_lib_path)); | |
| 460 | // } | |
| 461 | //} | |
| 462 | 357 | } |
| 463 | 358 | |
| 464 | 359 | fn constructLinkerArgsMachO(ctx: *Context) !void { |
| ... | ... | @@ -476,32 +371,6 @@ fn constructLinkerArgsMachO(ctx: *Context) !void { |
| 476 | 371 | try ctx.args.append("-dynamic"); |
| 477 | 372 | } |
| 478 | 373 | |
| 479 | //if (is_lib) { | |
| 480 | // if (!g->is_static) { | |
| 481 | // lj->args.append("-dylib"); | |
| 482 | ||
| 483 | // Buf *compat_vers = buf_sprintf("%" ZIG_PRI_usize ".0.0", g->version_major); | |
| 484 | // lj->args.append("-compatibility_version"); | |
| 485 | // lj->args.append(buf_ptr(compat_vers)); | |
| 486 | ||
| 487 | // Buf *cur_vers = buf_sprintf("%" ZIG_PRI_usize ".%" ZIG_PRI_usize ".%" ZIG_PRI_usize, | |
| 488 | // g->version_major, g->version_minor, g->version_patch); | |
| 489 | // lj->args.append("-current_version"); | |
| 490 | // lj->args.append(buf_ptr(cur_vers)); | |
| 491 | ||
| 492 | // // TODO getting an error when running an executable when doing this rpath thing | |
| 493 | // //Buf *dylib_install_name = buf_sprintf("@rpath/lib%s.%" ZIG_PRI_usize ".dylib", | |
| 494 | // // buf_ptr(g->root_out_name), g->version_major); | |
| 495 | // //lj->args.append("-install_name"); | |
| 496 | // //lj->args.append(buf_ptr(dylib_install_name)); | |
| 497 | ||
| 498 | // if (buf_len(&lj->out_file) == 0) { | |
| 499 | // buf_appendf(&lj->out_file, "lib%s.%" ZIG_PRI_usize ".%" ZIG_PRI_usize ".%" ZIG_PRI_usize ".dylib", | |
| 500 | // buf_ptr(g->root_out_name), g->version_major, g->version_minor, g->version_patch); | |
| 501 | // } | |
| 502 | // } | |
| 503 | //} | |
| 504 | ||
| 505 | 374 | try ctx.args.append("-arch"); |
| 506 | 375 | try ctx.args.append(util.getDarwinArchString(ctx.comp.target)); |
| 507 | 376 | |
| ... | ... | @@ -529,12 +398,6 @@ fn constructLinkerArgsMachO(ctx: *Context) !void { |
| 529 | 398 | try ctx.args.append("-o"); |
| 530 | 399 | try ctx.args.append(ctx.out_file_path.toSliceConst()); |
| 531 | 400 | |
| 532 | //for (size_t i = 0; i < g->rpath_list.length; i += 1) { | |
| 533 | // Buf *rpath = g->rpath_list.at(i); | |
| 534 | // add_rpath(lj, rpath); | |
| 535 | //} | |
| 536 | //add_rpath(lj, &lj->out_file); | |
| 537 | ||
| 538 | 401 | if (shared) { |
| 539 | 402 | try ctx.args.append("-headerpad_max_install_names"); |
| 540 | 403 | } else if (ctx.comp.is_static) { |
| ... | ... | @@ -563,24 +426,12 @@ fn constructLinkerArgsMachO(ctx: *Context) !void { |
| 563 | 426 | } |
| 564 | 427 | } |
| 565 | 428 | |
| 566 | //for (size_t i = 0; i < g->lib_dirs.length; i += 1) { | |
| 567 | // const char *lib_dir = g->lib_dirs.at(i); | |
| 568 | // lj->args.append("-L"); | |
| 569 | // lj->args.append(lib_dir); | |
| 570 | //} | |
| 571 | ||
| 572 | 429 | for (ctx.comp.link_objects) |link_object| { |
| 573 | 430 | const link_obj_with_null = try std.cstr.addNullByte(&ctx.arena.allocator, link_object); |
| 574 | 431 | try ctx.args.append(@ptrCast([*:0]const u8, link_obj_with_null.ptr)); |
| 575 | 432 | } |
| 576 | 433 | try addFnObjects(ctx); |
| 577 | 434 | |
| 578 | //// compiler_rt on darwin is missing some stuff, so we still build it and rely on LinkOnce | |
| 579 | //if (g->out_type == OutTypeExe || g->out_type == OutTypeLib) { | |
| 580 | // Buf *compiler_rt_o_path = build_compiler_rt(g); | |
| 581 | // lj->args.append(buf_ptr(compiler_rt_o_path)); | |
| 582 | //} | |
| 583 | ||
| 584 | 435 | if (ctx.comp.target == Target.Native) { |
| 585 | 436 | for (ctx.comp.link_libs_list.toSliceConst()) |lib| { |
| 586 | 437 | if (mem.eql(u8, lib.name, "c")) { |
| ... | ... | @@ -613,11 +464,6 @@ fn constructLinkerArgsMachO(ctx: *Context) !void { |
| 613 | 464 | } else { |
| 614 | 465 | @panic("TODO"); |
| 615 | 466 | } |
| 616 | ||
| 617 | //for (size_t i = 0; i < g->darwin_frameworks.length; i += 1) { | |
| 618 | // lj->args.append("-framework"); | |
| 619 | // lj->args.append(buf_ptr(g->darwin_frameworks.at(i))); | |
| 620 | //} | |
| 621 | 467 | } |
| 622 | 468 | |
| 623 | 469 | fn constructLinkerArgsWasm(ctx: *Context) void { |
src-self-hosted/main.zig+306-243| ... | ... | @@ -11,11 +11,8 @@ const Allocator = mem.Allocator; |
| 11 | 11 | const ArrayList = std.ArrayList; |
| 12 | 12 | const Buffer = std.Buffer; |
| 13 | 13 | |
| 14 | const arg = @import("arg.zig"); | |
| 15 | 14 | const c = @import("c.zig"); |
| 16 | 15 | const introspect = @import("introspect.zig"); |
| 17 | const Args = arg.Args; | |
| 18 | const Flag = arg.Flag; | |
| 19 | 16 | const ZigCompiler = @import("compilation.zig").ZigCompiler; |
| 20 | 17 | const Compilation = @import("compilation.zig").Compilation; |
| 21 | 18 | const Target = std.Target; |
| ... | ... | @@ -53,11 +50,7 @@ const Command = struct { |
| 53 | 50 | }; |
| 54 | 51 | |
| 55 | 52 | pub fn main() !void { |
| 56 | // This allocator needs to be thread-safe because we use it for the event.Loop | |
| 57 | // which multiplexes async functions onto kernel threads. | |
| 58 | // libc allocator is guaranteed to have this property. | |
| 59 | // TODO https://github.com/ziglang/zig/issues/3783 | |
| 60 | const allocator = std.heap.page_allocator; | |
| 53 | const allocator = std.heap.c_allocator; | |
| 61 | 54 | |
| 62 | 55 | stdout = &std.io.getStdOut().outStream().stream; |
| 63 | 56 | |
| ... | ... | @@ -65,7 +58,7 @@ pub fn main() !void { |
| 65 | 58 | stderr = &stderr_file.outStream().stream; |
| 66 | 59 | |
| 67 | 60 | const args = try process.argsAlloc(allocator); |
| 68 | // TODO I'm getting unreachable code here, which shouldn't happen | |
| 61 | // TODO I'm getting unreachable code here, which shouldn't happen | |
| 69 | 62 | //defer process.argsFree(allocator, args); |
| 70 | 63 | |
| 71 | 64 | if (args.len <= 1) { |
| ... | ... | @@ -182,8 +175,6 @@ const usage_build_generic = |
| 182 | 175 | \\ --object [obj] Add object file to build |
| 183 | 176 | \\ -rdynamic Add all symbols to the dynamic symbol table |
| 184 | 177 | \\ -rpath [path] Add directory to the runtime library search path |
| 185 | \\ -mconsole (windows) --subsystem console to the linker | |
| 186 | \\ -mwindows (windows) --subsystem windows to the linker | |
| 187 | 178 | \\ -framework [name] (darwin) link against framework |
| 188 | 179 | \\ -mios-version-min [ver] (darwin) set iOS deployment target |
| 189 | 180 | \\ -mmacosx-version-min [ver] (darwin) set Mac OS X deployment target |
| ... | ... | @@ -194,143 +185,244 @@ const usage_build_generic = |
| 194 | 185 | \\ |
| 195 | 186 | ; |
| 196 | 187 | |
| 197 | const args_build_generic = [_]Flag{ | |
| 198 | Flag.Bool("--help"), | |
| 199 | Flag.Option("--color", &[_][]const u8{ | |
| 200 | "auto", | |
| 201 | "off", | |
| 202 | "on", | |
| 203 | }), | |
| 204 | Flag.Option("--mode", &[_][]const u8{ | |
| 205 | "debug", | |
| 206 | "release-fast", | |
| 207 | "release-safe", | |
| 208 | "release-small", | |
| 209 | }), | |
| 210 | ||
| 211 | Flag.ArgMergeN("--assembly", 1), | |
| 212 | Flag.Option("--emit", &[_][]const u8{ | |
| 213 | "asm", | |
| 214 | "bin", | |
| 215 | "llvm-ir", | |
| 216 | }), | |
| 217 | Flag.Bool("--enable-timing-info"), | |
| 218 | Flag.Arg1("--libc"), | |
| 219 | Flag.Arg1("--name"), | |
| 220 | Flag.Arg1("--output"), | |
| 221 | Flag.Arg1("--output-h"), | |
| 222 | // NOTE: Parsed manually after initial check | |
| 223 | Flag.ArgN("--pkg-begin", 2), | |
| 224 | Flag.Bool("--pkg-end"), | |
| 225 | Flag.Bool("--static"), | |
| 226 | Flag.Bool("--strip"), | |
| 227 | Flag.Arg1("-target"), | |
| 228 | Flag.Bool("--verbose-tokenize"), | |
| 229 | Flag.Bool("--verbose-ast-tree"), | |
| 230 | Flag.Bool("--verbose-ast-fmt"), | |
| 231 | Flag.Bool("--verbose-link"), | |
| 232 | Flag.Bool("--verbose-ir"), | |
| 233 | Flag.Bool("--verbose-llvm-ir"), | |
| 234 | Flag.Bool("--verbose-cimport"), | |
| 235 | Flag.Arg1("-dirafter"), | |
| 236 | Flag.ArgMergeN("-isystem", 1), | |
| 237 | Flag.Arg1("-mllvm"), | |
| 238 | ||
| 239 | Flag.Arg1("--ar-path"), | |
| 240 | Flag.Bool("--each-lib-rpath"), | |
| 241 | Flag.ArgMergeN("--library", 1), | |
| 242 | Flag.ArgMergeN("--forbid-library", 1), | |
| 243 | Flag.ArgMergeN("--library-path", 1), | |
| 244 | Flag.Arg1("--linker-script"), | |
| 245 | Flag.ArgMergeN("--object", 1), | |
| 246 | // NOTE: Removed -L since it would need to be special-cased and we have an alias in library-path | |
| 247 | Flag.Bool("-rdynamic"), | |
| 248 | Flag.Arg1("-rpath"), | |
| 249 | Flag.Bool("-mconsole"), | |
| 250 | Flag.Bool("-mwindows"), | |
| 251 | Flag.ArgMergeN("-framework", 1), | |
| 252 | Flag.Arg1("-mios-version-min"), | |
| 253 | Flag.Arg1("-mmacosx-version-min"), | |
| 254 | Flag.Arg1("--ver-major"), | |
| 255 | Flag.Arg1("--ver-minor"), | |
| 256 | Flag.Arg1("--ver-patch"), | |
| 257 | }; | |
| 258 | ||
| 259 | 188 | fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Compilation.Kind) !void { |
| 260 | var flags = try Args.parse(allocator, &args_build_generic, args); | |
| 261 | defer flags.deinit(); | |
| 262 | ||
| 263 | if (flags.present("help")) { | |
| 264 | try stdout.write(usage_build_generic); | |
| 265 | process.exit(0); | |
| 266 | } | |
| 189 | var color: errmsg.Color = .Auto; | |
| 190 | var build_mode: std.builtin.Mode = .Debug; | |
| 191 | var emit_bin = true; | |
| 192 | var emit_asm = false; | |
| 193 | var emit_llvm_ir = false; | |
| 194 | var emit_h = false; | |
| 195 | var provided_name: ?[]const u8 = null; | |
| 196 | var is_dynamic = false; | |
| 197 | var root_src_file: ?[]const u8 = null; | |
| 198 | var libc_arg: ?[]const u8 = null; | |
| 199 | var version: std.builtin.Version = .{ .major = 0, .minor = 0, .patch = 0 }; | |
| 200 | var linker_script: ?[]const u8 = null; | |
| 201 | var strip = false; | |
| 202 | var verbose_tokenize = false; | |
| 203 | var verbose_ast_tree = false; | |
| 204 | var verbose_ast_fmt = false; | |
| 205 | var verbose_link = false; | |
| 206 | var verbose_ir = false; | |
| 207 | var verbose_llvm_ir = false; | |
| 208 | var verbose_cimport = false; | |
| 209 | var linker_rdynamic = false; | |
| 210 | var macosx_version_min: ?[]const u8 = null; | |
| 211 | var ios_version_min: ?[]const u8 = null; | |
| 212 | ||
| 213 | var assembly_files = ArrayList([]const u8).init(allocator); | |
| 214 | defer assembly_files.deinit(); | |
| 215 | ||
| 216 | var link_objects = ArrayList([]const u8).init(allocator); | |
| 217 | defer link_objects.deinit(); | |
| 267 | 218 | |
| 268 | const build_mode: std.builtin.Mode = blk: { | |
| 269 | if (flags.single("mode")) |mode_flag| { | |
| 270 | if (mem.eql(u8, mode_flag, "debug")) { | |
| 271 | break :blk .Debug; | |
| 272 | } else if (mem.eql(u8, mode_flag, "release-fast")) { | |
| 273 | break :blk .ReleaseFast; | |
| 274 | } else if (mem.eql(u8, mode_flag, "release-safe")) { | |
| 275 | break :blk .ReleaseSafe; | |
| 276 | } else if (mem.eql(u8, mode_flag, "release-small")) { | |
| 277 | break :blk .ReleaseSmall; | |
| 278 | } else unreachable; | |
| 279 | } else { | |
| 280 | break :blk .Debug; | |
| 281 | } | |
| 282 | }; | |
| 219 | var clang_argv_buf = ArrayList([]const u8).init(allocator); | |
| 220 | defer clang_argv_buf.deinit(); | |
| 283 | 221 | |
| 284 | const color: errmsg.Color = blk: { | |
| 285 | if (flags.single("color")) |color_flag| { | |
| 286 | if (mem.eql(u8, color_flag, "auto")) { | |
| 287 | break :blk .Auto; | |
| 288 | } else if (mem.eql(u8, color_flag, "on")) { | |
| 289 | break :blk .On; | |
| 290 | } else if (mem.eql(u8, color_flag, "off")) { | |
| 291 | break :blk .Off; | |
| 292 | } else unreachable; | |
| 293 | } else { | |
| 294 | break :blk .Auto; | |
| 295 | } | |
| 296 | }; | |
| 297 | ||
| 298 | const emit_type: Compilation.Emit = blk: { | |
| 299 | if (flags.single("emit")) |emit_flag| { | |
| 300 | if (mem.eql(u8, emit_flag, "asm")) { | |
| 301 | break :blk .Assembly; | |
| 302 | } else if (mem.eql(u8, emit_flag, "bin")) { | |
| 303 | break :blk .Binary; | |
| 304 | } else if (mem.eql(u8, emit_flag, "llvm-ir")) { | |
| 305 | break :blk .LlvmIr; | |
| 306 | } else unreachable; | |
| 307 | } else { | |
| 308 | break :blk .Binary; | |
| 309 | } | |
| 310 | }; | |
| 222 | var mllvm_flags = ArrayList([]const u8).init(allocator); | |
| 223 | defer mllvm_flags.deinit(); | |
| 311 | 224 | |
| 312 | 225 | var cur_pkg = try CliPkg.init(allocator, "", "", null); |
| 313 | 226 | defer cur_pkg.deinit(); |
| 314 | 227 | |
| 315 | var i: usize = 0; | |
| 316 | while (i < args.len) : (i += 1) { | |
| 317 | const arg_name = args[i]; | |
| 318 | if (mem.eql(u8, "--pkg-begin", arg_name)) { | |
| 319 | // following two arguments guaranteed to exist due to arg parsing | |
| 320 | i += 1; | |
| 321 | const new_pkg_name = args[i]; | |
| 322 | i += 1; | |
| 323 | const new_pkg_path = args[i]; | |
| 324 | ||
| 325 | var new_cur_pkg = try CliPkg.init(allocator, new_pkg_name, new_pkg_path, cur_pkg); | |
| 326 | try cur_pkg.children.append(new_cur_pkg); | |
| 327 | cur_pkg = new_cur_pkg; | |
| 328 | } else if (mem.eql(u8, "--pkg-end", arg_name)) { | |
| 329 | if (cur_pkg.parent) |parent| { | |
| 330 | cur_pkg = parent; | |
| 228 | var system_libs = ArrayList([]const u8).init(allocator); | |
| 229 | defer system_libs.deinit(); | |
| 230 | ||
| 231 | var c_src_files = ArrayList([]const u8).init(allocator); | |
| 232 | defer c_src_files.deinit(); | |
| 233 | ||
| 234 | { | |
| 235 | var i: usize = 0; | |
| 236 | while (i < args.len) : (i += 1) { | |
| 237 | const arg = args[i]; | |
| 238 | if (mem.startsWith(u8, arg, "-")) { | |
| 239 | if (mem.eql(u8, arg, "--help")) { | |
| 240 | try stdout.write(usage_build_generic); | |
| 241 | process.exit(0); | |
| 242 | } else if (mem.eql(u8, arg, "--color")) { | |
| 243 | if (i + 1 >= args.len) { | |
| 244 | try stderr.write("expected [auto|on|off] after --color\n"); | |
| 245 | process.exit(1); | |
| 246 | } | |
| 247 | i += 1; | |
| 248 | const next_arg = args[i]; | |
| 249 | if (mem.eql(u8, next_arg, "auto")) { | |
| 250 | color = .Auto; | |
| 251 | } else if (mem.eql(u8, next_arg, "on")) { | |
| 252 | color = .On; | |
| 253 | } else if (mem.eql(u8, next_arg, "off")) { | |
| 254 | color = .Off; | |
| 255 | } else { | |
| 256 | try stderr.print("expected [auto|on|off] after --color, found '{}'\n", .{next_arg}); | |
| 257 | process.exit(1); | |
| 258 | } | |
| 259 | } else if (mem.eql(u8, arg, "--mode")) { | |
| 260 | if (i + 1 >= args.len) { | |
| 261 | try stderr.write("expected [Debug|ReleaseSafe|ReleaseFast|ReleaseSmall] after --mode\n"); | |
| 262 | process.exit(1); | |
| 263 | } | |
| 264 | i += 1; | |
| 265 | const next_arg = args[i]; | |
| 266 | if (mem.eql(u8, next_arg, "Debug")) { | |
| 267 | build_mode = .Debug; | |
| 268 | } else if (mem.eql(u8, next_arg, "ReleaseSafe")) { | |
| 269 | build_mode = .ReleaseSafe; | |
| 270 | } else if (mem.eql(u8, next_arg, "ReleaseFast")) { | |
| 271 | build_mode = .ReleaseFast; | |
| 272 | } else if (mem.eql(u8, next_arg, "ReleaseSmall")) { | |
| 273 | build_mode = .ReleaseSmall; | |
| 274 | } else { | |
| 275 | try stderr.print("expected [Debug|ReleaseSafe|ReleaseFast|ReleaseSmall] after --mode, found '{}'\n", .{next_arg}); | |
| 276 | process.exit(1); | |
| 277 | } | |
| 278 | } else if (mem.eql(u8, arg, "--name")) { | |
| 279 | if (i + 1 >= args.len) { | |
| 280 | try stderr.write("expected parameter after --name\n"); | |
| 281 | process.exit(1); | |
| 282 | } | |
| 283 | i += 1; | |
| 284 | provided_name = args[i]; | |
| 285 | } else if (mem.eql(u8, arg, "--ver-major")) { | |
| 286 | if (i + 1 >= args.len) { | |
| 287 | try stderr.write("expected parameter after --ver-major\n"); | |
| 288 | process.exit(1); | |
| 289 | } | |
| 290 | i += 1; | |
| 291 | version.major = try std.fmt.parseInt(u32, args[i], 10); | |
| 292 | } else if (mem.eql(u8, arg, "--ver-minor")) { | |
| 293 | if (i + 1 >= args.len) { | |
| 294 | try stderr.write("expected parameter after --ver-minor\n"); | |
| 295 | process.exit(1); | |
| 296 | } | |
| 297 | i += 1; | |
| 298 | version.minor = try std.fmt.parseInt(u32, args[i], 10); | |
| 299 | } else if (mem.eql(u8, arg, "--ver-patch")) { | |
| 300 | if (i + 1 >= args.len) { | |
| 301 | try stderr.write("expected parameter after --ver-patch\n"); | |
| 302 | process.exit(1); | |
| 303 | } | |
| 304 | i += 1; | |
| 305 | version.patch = try std.fmt.parseInt(u32, args[i], 10); | |
| 306 | } else if (mem.eql(u8, arg, "--linker-script")) { | |
| 307 | if (i + 1 >= args.len) { | |
| 308 | try stderr.write("expected parameter after --linker-script\n"); | |
| 309 | process.exit(1); | |
| 310 | } | |
| 311 | i += 1; | |
| 312 | linker_script = args[i]; | |
| 313 | } else if (mem.eql(u8, arg, "--libc")) { | |
| 314 | if (i + 1 >= args.len) { | |
| 315 | try stderr.write("expected parameter after --libc\n"); | |
| 316 | process.exit(1); | |
| 317 | } | |
| 318 | i += 1; | |
| 319 | libc_arg = args[i]; | |
| 320 | } else if (mem.eql(u8, arg, "-mllvm")) { | |
| 321 | if (i + 1 >= args.len) { | |
| 322 | try stderr.write("expected parameter after -mllvm\n"); | |
| 323 | process.exit(1); | |
| 324 | } | |
| 325 | i += 1; | |
| 326 | try clang_argv_buf.append("-mllvm"); | |
| 327 | try clang_argv_buf.append(args[i]); | |
| 328 | ||
| 329 | try mllvm_flags.append(args[i]); | |
| 330 | } else if (mem.eql(u8, arg, "-mmacosx-version-min")) { | |
| 331 | if (i + 1 >= args.len) { | |
| 332 | try stderr.write("expected parameter after -mmacosx-version-min\n"); | |
| 333 | process.exit(1); | |
| 334 | } | |
| 335 | i += 1; | |
| 336 | macosx_version_min = args[i]; | |
| 337 | } else if (mem.eql(u8, arg, "-mios-version-min")) { | |
| 338 | if (i + 1 >= args.len) { | |
| 339 | try stderr.write("expected parameter after -mios-version-min\n"); | |
| 340 | process.exit(1); | |
| 341 | } | |
| 342 | i += 1; | |
| 343 | ios_version_min = args[i]; | |
| 344 | } else if (mem.eql(u8, arg, "-femit-bin")) { | |
| 345 | emit_bin = true; | |
| 346 | } else if (mem.eql(u8, arg, "-fno-emit-bin")) { | |
| 347 | emit_bin = false; | |
| 348 | } else if (mem.eql(u8, arg, "-femit-asm")) { | |
| 349 | emit_asm = true; | |
| 350 | } else if (mem.eql(u8, arg, "-fno-emit-asm")) { | |
| 351 | emit_asm = false; | |
| 352 | } else if (mem.eql(u8, arg, "-femit-llvm-ir")) { | |
| 353 | emit_llvm_ir = true; | |
| 354 | } else if (mem.eql(u8, arg, "-fno-emit-llvm-ir")) { | |
| 355 | emit_llvm_ir = false; | |
| 356 | } else if (mem.eql(u8, arg, "-dynamic")) { | |
| 357 | is_dynamic = true; | |
| 358 | } else if (mem.eql(u8, arg, "--strip")) { | |
| 359 | strip = true; | |
| 360 | } else if (mem.eql(u8, arg, "--verbose-tokenize")) { | |
| 361 | verbose_tokenize = true; | |
| 362 | } else if (mem.eql(u8, arg, "--verbose-ast-tree")) { | |
| 363 | verbose_ast_tree = true; | |
| 364 | } else if (mem.eql(u8, arg, "--verbose-ast-fmt")) { | |
| 365 | verbose_ast_fmt = true; | |
| 366 | } else if (mem.eql(u8, arg, "--verbose-link")) { | |
| 367 | verbose_link = true; | |
| 368 | } else if (mem.eql(u8, arg, "--verbose-ir")) { | |
| 369 | verbose_ir = true; | |
| 370 | } else if (mem.eql(u8, arg, "--verbose-llvm-ir")) { | |
| 371 | verbose_llvm_ir = true; | |
| 372 | } else if (mem.eql(u8, arg, "--verbose-cimport")) { | |
| 373 | verbose_cimport = true; | |
| 374 | } else if (mem.eql(u8, arg, "-rdynamic")) { | |
| 375 | linker_rdynamic = true; | |
| 376 | } else if (mem.eql(u8, arg, "--pkg-begin")) { | |
| 377 | if (i + 2 >= args.len) { | |
| 378 | try stderr.write("expected [name] [path] after --pkg-begin\n"); | |
| 379 | process.exit(1); | |
| 380 | } | |
| 381 | i += 1; | |
| 382 | const new_pkg_name = args[i]; | |
| 383 | i += 1; | |
| 384 | const new_pkg_path = args[i]; | |
| 385 | ||
| 386 | var new_cur_pkg = try CliPkg.init(allocator, new_pkg_name, new_pkg_path, cur_pkg); | |
| 387 | try cur_pkg.children.append(new_cur_pkg); | |
| 388 | cur_pkg = new_cur_pkg; | |
| 389 | } else if (mem.eql(u8, arg, "--pkg-end")) { | |
| 390 | if (cur_pkg.parent) |parent| { | |
| 391 | cur_pkg = parent; | |
| 392 | } else { | |
| 393 | try stderr.write("encountered --pkg-end with no matching --pkg-begin\n"); | |
| 394 | process.exit(1); | |
| 395 | } | |
| 396 | } else if (mem.startsWith(u8, arg, "-l")) { | |
| 397 | try system_libs.append(arg[2..]); | |
| 398 | } else { | |
| 399 | try stderr.print("unrecognized parameter: '{}'", .{arg}); | |
| 400 | process.exit(1); | |
| 401 | } | |
| 402 | } else if (mem.endsWith(u8, arg, ".s")) { | |
| 403 | try assembly_files.append(arg); | |
| 404 | } else if (mem.endsWith(u8, arg, ".o") or | |
| 405 | mem.endsWith(u8, arg, ".obj") or | |
| 406 | mem.endsWith(u8, arg, ".a") or | |
| 407 | mem.endsWith(u8, arg, ".lib")) | |
| 408 | { | |
| 409 | try link_objects.append(arg); | |
| 410 | } else if (mem.endsWith(u8, arg, ".c") or | |
| 411 | mem.endsWith(u8, arg, ".cpp")) | |
| 412 | { | |
| 413 | try c_src_files.append(arg); | |
| 414 | } else if (mem.endsWith(u8, arg, ".zig")) { | |
| 415 | if (root_src_file) |other| { | |
| 416 | try stderr.print("found another zig file '{}' after root source file '{}'", .{ | |
| 417 | arg, | |
| 418 | other, | |
| 419 | }); | |
| 420 | process.exit(1); | |
| 421 | } else { | |
| 422 | root_src_file = arg; | |
| 423 | } | |
| 331 | 424 | } else { |
| 332 | try stderr.print("encountered --pkg-end with no matching --pkg-begin\n", .{}); | |
| 333 | process.exit(1); | |
| 425 | try stderr.print("unrecognized file extension of parameter '{}'", .{arg}); | |
| 334 | 426 | } |
| 335 | 427 | } |
| 336 | 428 | } |
| ... | ... | @@ -340,18 +432,8 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co |
| 340 | 432 | process.exit(1); |
| 341 | 433 | } |
| 342 | 434 | |
| 343 | const provided_name = flags.single("name"); | |
| 344 | const root_source_file = switch (flags.positionals.len) { | |
| 345 | 0 => null, | |
| 346 | 1 => flags.positionals.at(0), | |
| 347 | else => { | |
| 348 | try stderr.print("unexpected extra parameter: {}\n", .{flags.positionals.at(1)}); | |
| 349 | process.exit(1); | |
| 350 | }, | |
| 351 | }; | |
| 352 | ||
| 353 | 435 | const root_name = if (provided_name) |n| n else blk: { |
| 354 | if (root_source_file) |file| { | |
| 436 | if (root_src_file) |file| { | |
| 355 | 437 | const basename = fs.path.basename(file); |
| 356 | 438 | var it = mem.separate(basename, "."); |
| 357 | 439 | break :blk it.next() orelse basename; |
| ... | ... | @@ -361,11 +443,7 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co |
| 361 | 443 | } |
| 362 | 444 | }; |
| 363 | 445 | |
| 364 | const is_static = flags.present("static"); | |
| 365 | ||
| 366 | const assembly_files = flags.many("assembly"); | |
| 367 | const link_objects = flags.many("object"); | |
| 368 | if (root_source_file == null and link_objects.len == 0 and assembly_files.len == 0) { | |
| 446 | if (root_src_file == null and link_objects.len == 0 and assembly_files.len == 0) { | |
| 369 | 447 | try stderr.write("Expected source file argument or at least one --object or --assembly argument\n"); |
| 370 | 448 | process.exit(1); |
| 371 | 449 | } |
| ... | ... | @@ -375,15 +453,7 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co |
| 375 | 453 | process.exit(1); |
| 376 | 454 | } |
| 377 | 455 | |
| 378 | var clang_argv_buf = ArrayList([]const u8).init(allocator); | |
| 379 | defer clang_argv_buf.deinit(); | |
| 380 | ||
| 381 | const mllvm_flags = flags.many("mllvm"); | |
| 382 | for (mllvm_flags) |mllvm| { | |
| 383 | try clang_argv_buf.append("-mllvm"); | |
| 384 | try clang_argv_buf.append(mllvm); | |
| 385 | } | |
| 386 | try ZigCompiler.setLlvmArgv(allocator, mllvm_flags); | |
| 456 | try ZigCompiler.setLlvmArgv(allocator, mllvm_flags.toSliceConst()); | |
| 387 | 457 | |
| 388 | 458 | const zig_lib_dir = introspect.resolveZigLibDir(allocator) catch process.exit(1); |
| 389 | 459 | defer allocator.free(zig_lib_dir); |
| ... | ... | @@ -396,74 +466,60 @@ fn buildOutputType(allocator: *Allocator, args: []const []const u8, out_type: Co |
| 396 | 466 | var comp = try Compilation.create( |
| 397 | 467 | &zig_compiler, |
| 398 | 468 | root_name, |
| 399 | root_source_file, | |
| 469 | root_src_file, | |
| 400 | 470 | Target.Native, |
| 401 | 471 | out_type, |
| 402 | 472 | build_mode, |
| 403 | is_static, | |
| 473 | !is_dynamic, | |
| 404 | 474 | zig_lib_dir, |
| 405 | 475 | ); |
| 406 | 476 | defer comp.destroy(); |
| 407 | 477 | |
| 408 | if (flags.single("libc")) |libc_path| { | |
| 478 | if (libc_arg) |libc_path| { | |
| 409 | 479 | parseLibcPaths(allocator, &override_libc, libc_path); |
| 410 | 480 | comp.override_libc = &override_libc; |
| 411 | 481 | } |
| 412 | 482 | |
| 413 | for (flags.many("library")) |lib| { | |
| 483 | for (system_libs.toSliceConst()) |lib| { | |
| 414 | 484 | _ = try comp.addLinkLib(lib, true); |
| 415 | 485 | } |
| 416 | 486 | |
| 417 | comp.version_major = try std.fmt.parseUnsigned(u32, flags.single("ver-major") orelse "0", 10); | |
| 418 | comp.version_minor = try std.fmt.parseUnsigned(u32, flags.single("ver-minor") orelse "0", 10); | |
| 419 | comp.version_patch = try std.fmt.parseUnsigned(u32, flags.single("ver-patch") orelse "0", 10); | |
| 420 | ||
| 487 | comp.version = version; | |
| 421 | 488 | comp.is_test = false; |
| 422 | ||
| 423 | comp.linker_script = flags.single("linker-script"); | |
| 424 | comp.each_lib_rpath = flags.present("each-lib-rpath"); | |
| 425 | ||
| 489 | comp.linker_script = linker_script; | |
| 426 | 490 | comp.clang_argv = clang_argv_buf.toSliceConst(); |
| 491 | comp.strip = strip; | |
| 427 | 492 | |
| 428 | comp.strip = flags.present("strip"); | |
| 429 | ||
| 430 | comp.verbose_tokenize = flags.present("verbose-tokenize"); | |
| 431 | comp.verbose_ast_tree = flags.present("verbose-ast-tree"); | |
| 432 | comp.verbose_ast_fmt = flags.present("verbose-ast-fmt"); | |
| 433 | comp.verbose_link = flags.present("verbose-link"); | |
| 434 | comp.verbose_ir = flags.present("verbose-ir"); | |
| 435 | comp.verbose_llvm_ir = flags.present("verbose-llvm-ir"); | |
| 436 | comp.verbose_cimport = flags.present("verbose-cimport"); | |
| 493 | comp.verbose_tokenize = verbose_tokenize; | |
| 494 | comp.verbose_ast_tree = verbose_ast_tree; | |
| 495 | comp.verbose_ast_fmt = verbose_ast_fmt; | |
| 496 | comp.verbose_link = verbose_link; | |
| 497 | comp.verbose_ir = verbose_ir; | |
| 498 | comp.verbose_llvm_ir = verbose_llvm_ir; | |
| 499 | comp.verbose_cimport = verbose_cimport; | |
| 437 | 500 | |
| 438 | 501 | comp.err_color = color; |
| 439 | comp.lib_dirs = flags.many("library-path"); | |
| 440 | comp.darwin_frameworks = flags.many("framework"); | |
| 441 | comp.rpath_list = flags.many("rpath"); | |
| 442 | 502 | |
| 443 | if (flags.single("output-h")) |output_h| { | |
| 444 | comp.out_h_path = output_h; | |
| 445 | } | |
| 446 | ||
| 447 | comp.windows_subsystem_windows = flags.present("mwindows"); | |
| 448 | comp.windows_subsystem_console = flags.present("mconsole"); | |
| 449 | comp.linker_rdynamic = flags.present("rdynamic"); | |
| 503 | comp.linker_rdynamic = linker_rdynamic; | |
| 450 | 504 | |
| 451 | if (flags.single("mmacosx-version-min") != null and flags.single("mios-version-min") != null) { | |
| 505 | if (macosx_version_min != null and ios_version_min != null) { | |
| 452 | 506 | try stderr.write("-mmacosx-version-min and -mios-version-min options not allowed together\n"); |
| 453 | 507 | process.exit(1); |
| 454 | 508 | } |
| 455 | 509 | |
| 456 | if (flags.single("mmacosx-version-min")) |ver| { | |
| 510 | if (macosx_version_min) |ver| { | |
| 457 | 511 | comp.darwin_version_min = Compilation.DarwinVersionMin{ .MacOS = ver }; |
| 458 | 512 | } |
| 459 | if (flags.single("mios-version-min")) |ver| { | |
| 513 | if (ios_version_min) |ver| { | |
| 460 | 514 | comp.darwin_version_min = Compilation.DarwinVersionMin{ .Ios = ver }; |
| 461 | 515 | } |
| 462 | 516 | |
| 463 | comp.emit_file_type = emit_type; | |
| 464 | comp.assembly_files = assembly_files; | |
| 465 | comp.link_out_file = flags.single("output"); | |
| 466 | comp.link_objects = link_objects; | |
| 517 | comp.emit_bin = emit_bin; | |
| 518 | comp.emit_asm = emit_asm; | |
| 519 | comp.emit_llvm_ir = emit_llvm_ir; | |
| 520 | comp.emit_h = emit_h; | |
| 521 | comp.assembly_files = assembly_files.toSliceConst(); | |
| 522 | comp.link_objects = link_objects.toSliceConst(); | |
| 467 | 523 | |
| 468 | 524 | comp.start(); |
| 469 | 525 | processBuildEvents(comp, color); |
| ... | ... | @@ -522,17 +578,6 @@ pub const usage_fmt = |
| 522 | 578 | \\ |
| 523 | 579 | ; |
| 524 | 580 | |
| 525 | pub const args_fmt_spec = [_]Flag{ | |
| 526 | Flag.Bool("--help"), | |
| 527 | Flag.Bool("--check"), | |
| 528 | Flag.Option("--color", &[_][]const u8{ | |
| 529 | "auto", | |
| 530 | "off", | |
| 531 | "on", | |
| 532 | }), | |
| 533 | Flag.Bool("--stdin"), | |
| 534 | }; | |
| 535 | ||
| 536 | 581 | const Fmt = struct { |
| 537 | 582 | seen: event.Locked(SeenMap), |
| 538 | 583 | any_error: bool, |
| ... | ... | @@ -578,30 +623,52 @@ fn cmdLibC(allocator: *Allocator, args: []const []const u8) !void { |
| 578 | 623 | } |
| 579 | 624 | |
| 580 | 625 | fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void { |
| 581 | var flags = try Args.parse(allocator, &args_fmt_spec, args); | |
| 582 | defer flags.deinit(); | |
| 583 | ||
| 584 | if (flags.present("help")) { | |
| 585 | try stdout.write(usage_fmt); | |
| 586 | process.exit(0); | |
| 587 | } | |
| 626 | var color: errmsg.Color = .Auto; | |
| 627 | var stdin_flag: bool = false; | |
| 628 | var check_flag: bool = false; | |
| 629 | var input_files = ArrayList([]const u8).init(allocator); | |
| 588 | 630 | |
| 589 | const color: errmsg.Color = blk: { | |
| 590 | if (flags.single("color")) |color_flag| { | |
| 591 | if (mem.eql(u8, color_flag, "auto")) { | |
| 592 | break :blk .Auto; | |
| 593 | } else if (mem.eql(u8, color_flag, "on")) { | |
| 594 | break :blk .On; | |
| 595 | } else if (mem.eql(u8, color_flag, "off")) { | |
| 596 | break :blk .Off; | |
| 597 | } else unreachable; | |
| 598 | } else { | |
| 599 | break :blk .Auto; | |
| 631 | { | |
| 632 | var i: usize = 0; | |
| 633 | while (i < args.len) : (i += 1) { | |
| 634 | const arg = args[i]; | |
| 635 | if (mem.startsWith(u8, arg, "-")) { | |
| 636 | if (mem.eql(u8, arg, "--help")) { | |
| 637 | try stdout.write(usage_fmt); | |
| 638 | process.exit(0); | |
| 639 | } else if (mem.eql(u8, arg, "--color")) { | |
| 640 | if (i + 1 >= args.len) { | |
| 641 | try stderr.write("expected [auto|on|off] after --color\n"); | |
| 642 | process.exit(1); | |
| 643 | } | |
| 644 | i += 1; | |
| 645 | const next_arg = args[i]; | |
| 646 | if (mem.eql(u8, next_arg, "auto")) { | |
| 647 | color = .Auto; | |
| 648 | } else if (mem.eql(u8, next_arg, "on")) { | |
| 649 | color = .On; | |
| 650 | } else if (mem.eql(u8, next_arg, "off")) { | |
| 651 | color = .Off; | |
| 652 | } else { | |
| 653 | try stderr.print("expected [auto|on|off] after --color, found '{}'\n", .{next_arg}); | |
| 654 | process.exit(1); | |
| 655 | } | |
| 656 | } else if (mem.eql(u8, arg, "--stdin")) { | |
| 657 | stdin_flag = true; | |
| 658 | } else if (mem.eql(u8, arg, "--check")) { | |
| 659 | check_flag = true; | |
| 660 | } else { | |
| 661 | try stderr.print("unrecognized parameter: '{}'", .{arg}); | |
| 662 | process.exit(1); | |
| 663 | } | |
| 664 | } else { | |
| 665 | try input_files.append(arg); | |
| 666 | } | |
| 600 | 667 | } |
| 601 | }; | |
| 668 | } | |
| 602 | 669 | |
| 603 | if (flags.present("stdin")) { | |
| 604 | if (flags.positionals.len != 0) { | |
| 670 | if (stdin_flag) { | |
| 671 | if (input_files.len != 0) { | |
| 605 | 672 | try stderr.write("cannot use --stdin with positional arguments\n"); |
| 606 | 673 | process.exit(1); |
| 607 | 674 | } |
| ... | ... | @@ -628,7 +695,7 @@ fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void { |
| 628 | 695 | if (tree.errors.len != 0) { |
| 629 | 696 | process.exit(1); |
| 630 | 697 | } |
| 631 | if (flags.present("check")) { | |
| 698 | if (check_flag) { | |
| 632 | 699 | const anything_changed = try std.zig.render(allocator, io.null_out_stream, tree); |
| 633 | 700 | const code: u8 = if (anything_changed) 1 else 0; |
| 634 | 701 | process.exit(code); |
| ... | ... | @@ -638,7 +705,7 @@ fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void { |
| 638 | 705 | return; |
| 639 | 706 | } |
| 640 | 707 | |
| 641 | if (flags.positionals.len == 0) { | |
| 708 | if (input_files.len == 0) { | |
| 642 | 709 | try stderr.write("expected at least one source file argument\n"); |
| 643 | 710 | process.exit(1); |
| 644 | 711 | } |
| ... | ... | @@ -650,11 +717,9 @@ fn cmdFmt(allocator: *Allocator, args: []const []const u8) !void { |
| 650 | 717 | .color = color, |
| 651 | 718 | }; |
| 652 | 719 | |
| 653 | const check_mode = flags.present("check"); | |
| 654 | ||
| 655 | 720 | var group = event.Group(FmtError!void).init(allocator); |
| 656 | for (flags.positionals.toSliceConst()) |file_path| { | |
| 657 | try group.call(fmtPath, .{ &fmt, file_path, check_mode }); | |
| 721 | for (input_files.toSliceConst()) |file_path| { | |
| 722 | try group.call(fmtPath, .{ &fmt, file_path, check_flag }); | |
| 658 | 723 | } |
| 659 | 724 | try group.wait(); |
| 660 | 725 | if (fmt.any_error) { |
| ... | ... | @@ -808,8 +873,6 @@ fn cmdVersion(allocator: *Allocator, args: []const []const u8) !void { |
| 808 | 873 | try stdout.print("{}\n", .{std.mem.toSliceConst(u8, c.ZIG_VERSION_STRING)}); |
| 809 | 874 | } |
| 810 | 875 | |
| 811 | const args_test_spec = [_]Flag{Flag.Bool("--help")}; | |
| 812 | ||
| 813 | 876 | fn cmdHelp(allocator: *Allocator, args: []const []const u8) !void { |
| 814 | 877 | try stdout.write(usage); |
| 815 | 878 | } |
src-self-hosted/stage1.zig+50-32| ... | ... | @@ -9,10 +9,7 @@ const process = std.process; |
| 9 | 9 | const Allocator = mem.Allocator; |
| 10 | 10 | const ArrayList = std.ArrayList; |
| 11 | 11 | const Buffer = std.Buffer; |
| 12 | const arg = @import("arg.zig"); | |
| 13 | 12 | const self_hosted_main = @import("main.zig"); |
| 14 | const Args = arg.Args; | |
| 15 | const Flag = arg.Flag; | |
| 16 | 13 | const errmsg = @import("errmsg.zig"); |
| 17 | 14 | const DepTokenizer = @import("dep_tokenizer.zig").Tokenizer; |
| 18 | 15 | |
| ... | ... | @@ -169,31 +166,54 @@ fn fmtMain(argc: c_int, argv: [*]const [*:0]const u8) !void { |
| 169 | 166 | stderr_file = std.io.getStdErr(); |
| 170 | 167 | stderr = &stderr_file.outStream().stream; |
| 171 | 168 | |
| 172 | const args = args_list.toSliceConst(); | |
| 173 | var flags = try Args.parse(allocator, &self_hosted_main.args_fmt_spec, args[2..]); | |
| 174 | defer flags.deinit(); | |
| 175 | ||
| 176 | if (flags.present("help")) { | |
| 177 | try stdout.write(self_hosted_main.usage_fmt); | |
| 178 | process.exit(0); | |
| 179 | } | |
| 180 | ||
| 181 | const color = blk: { | |
| 182 | if (flags.single("color")) |color_flag| { | |
| 183 | if (mem.eql(u8, color_flag, "auto")) { | |
| 184 | break :blk errmsg.Color.Auto; | |
| 185 | } else if (mem.eql(u8, color_flag, "on")) { | |
| 186 | break :blk errmsg.Color.On; | |
| 187 | } else if (mem.eql(u8, color_flag, "off")) { | |
| 188 | break :blk errmsg.Color.Off; | |
| 189 | } else unreachable; | |
| 190 | } else { | |
| 191 | break :blk errmsg.Color.Auto; | |
| 169 | const args = args_list.toSliceConst()[2..]; | |
| 170 | ||
| 171 | var color: errmsg.Color = .Auto; | |
| 172 | var stdin_flag: bool = false; | |
| 173 | var check_flag: bool = false; | |
| 174 | var input_files = ArrayList([]const u8).init(allocator); | |
| 175 | ||
| 176 | { | |
| 177 | var i: usize = 0; | |
| 178 | while (i < args.len) : (i += 1) { | |
| 179 | const arg = args[i]; | |
| 180 | if (mem.startsWith(u8, arg, "-")) { | |
| 181 | if (mem.eql(u8, arg, "--help")) { | |
| 182 | try stdout.write(self_hosted_main.usage_fmt); | |
| 183 | process.exit(0); | |
| 184 | } else if (mem.eql(u8, arg, "--color")) { | |
| 185 | if (i + 1 >= args.len) { | |
| 186 | try stderr.write("expected [auto|on|off] after --color\n"); | |
| 187 | process.exit(1); | |
| 188 | } | |
| 189 | i += 1; | |
| 190 | const next_arg = args[i]; | |
| 191 | if (mem.eql(u8, next_arg, "auto")) { | |
| 192 | color = .Auto; | |
| 193 | } else if (mem.eql(u8, next_arg, "on")) { | |
| 194 | color = .On; | |
| 195 | } else if (mem.eql(u8, next_arg, "off")) { | |
| 196 | color = .Off; | |
| 197 | } else { | |
| 198 | try stderr.print("expected [auto|on|off] after --color, found '{}'\n", .{next_arg}); | |
| 199 | process.exit(1); | |
| 200 | } | |
| 201 | } else if (mem.eql(u8, arg, "--stdin")) { | |
| 202 | stdin_flag = true; | |
| 203 | } else if (mem.eql(u8, arg, "--check")) { | |
| 204 | check_flag = true; | |
| 205 | } else { | |
| 206 | try stderr.print("unrecognized parameter: '{}'", .{arg}); | |
| 207 | process.exit(1); | |
| 208 | } | |
| 209 | } else { | |
| 210 | try input_files.append(arg); | |
| 211 | } | |
| 192 | 212 | } |
| 193 | }; | |
| 213 | } | |
| 194 | 214 | |
| 195 | if (flags.present("stdin")) { | |
| 196 | if (flags.positionals.len != 0) { | |
| 215 | if (stdin_flag) { | |
| 216 | if (input_files.len != 0) { | |
| 197 | 217 | try stderr.write("cannot use --stdin with positional arguments\n"); |
| 198 | 218 | process.exit(1); |
| 199 | 219 | } |
| ... | ... | @@ -217,7 +237,7 @@ fn fmtMain(argc: c_int, argv: [*]const [*:0]const u8) !void { |
| 217 | 237 | if (tree.errors.len != 0) { |
| 218 | 238 | process.exit(1); |
| 219 | 239 | } |
| 220 | if (flags.present("check")) { | |
| 240 | if (check_flag) { | |
| 221 | 241 | const anything_changed = try std.zig.render(allocator, io.null_out_stream, tree); |
| 222 | 242 | const code = if (anything_changed) @as(u8, 1) else @as(u8, 0); |
| 223 | 243 | process.exit(code); |
| ... | ... | @@ -227,7 +247,7 @@ fn fmtMain(argc: c_int, argv: [*]const [*:0]const u8) !void { |
| 227 | 247 | return; |
| 228 | 248 | } |
| 229 | 249 | |
| 230 | if (flags.positionals.len == 0) { | |
| 250 | if (input_files.len == 0) { | |
| 231 | 251 | try stderr.write("expected at least one source file argument\n"); |
| 232 | 252 | process.exit(1); |
| 233 | 253 | } |
| ... | ... | @@ -239,10 +259,8 @@ fn fmtMain(argc: c_int, argv: [*]const [*:0]const u8) !void { |
| 239 | 259 | .allocator = allocator, |
| 240 | 260 | }; |
| 241 | 261 | |
| 242 | const check_mode = flags.present("check"); | |
| 243 | ||
| 244 | for (flags.positionals.toSliceConst()) |file_path| { | |
| 245 | try fmtPath(&fmt, file_path, check_mode); | |
| 262 | for (input_files.toSliceConst()) |file_path| { | |
| 263 | try fmtPath(&fmt, file_path, check_flag); | |
| 246 | 264 | } |
| 247 | 265 | if (fmt.any_error) { |
| 248 | 266 | process.exit(1); |