| ... | ... | @@ -4,71 +4,620 @@ const io = std.io; |
| 4 | 4 | const os = std.os; |
| 5 | 5 | const heap = std.heap; |
| 6 | 6 | const warn = std.debug.warn; |
| 7 | | const Tokenizer = @import("tokenizer.zig").Tokenizer; |
| 8 | | const Token = @import("tokenizer.zig").Token; |
| 9 | | const Parser = @import("parser.zig").Parser; |
| 10 | 7 | const assert = std.debug.assert; |
| 11 | 8 | const target = @import("target.zig"); |
| 9 | const Target = target.Target; |
| 10 | const Module = @import("module.zig").Module; |
| 11 | const ErrColor = Module.ErrColor; |
| 12 | const Emit = Module.Emit; |
| 13 | const builtin = @import("builtin"); |
| 14 | const ArrayList = std.ArrayList; |
| 15 | |
| 16 | error InvalidCommandLineArguments; |
| 17 | error ZigLibDirNotFound; |
| 18 | error ZigInstallationNotFound; |
| 19 | |
| 20 | const default_zig_cache_name = "zig-cache"; |
| 12 | 21 | |
| 13 | 22 | pub fn main() -> %void { |
| 14 | 23 | main2() %% |err| { |
| 15 | | warn("{}\n", @errorName(err)); |
| 24 | if (err != error.InvalidCommandLineArguments) { |
| 25 | warn("{}\n", @errorName(err)); |
| 26 | } |
| 16 | 27 | return err; |
| 17 | 28 | }; |
| 18 | 29 | } |
| 19 | 30 | |
| 20 | | pub fn main2() -> %void { |
| 21 | | var incrementing_allocator = %return heap.IncrementingAllocator.init(10 * 1024 * 1024); |
| 22 | | defer incrementing_allocator.deinit(); |
| 31 | const Cmd = enum { |
| 32 | None, |
| 33 | Build, |
| 34 | Test, |
| 35 | Version, |
| 36 | Zen, |
| 37 | TranslateC, |
| 38 | Targets, |
| 39 | }; |
| 23 | 40 | |
| 24 | | const allocator = &incrementing_allocator.allocator; |
| 41 | fn badArgs(comptime format: []const u8, args: ...) -> error { |
| 42 | var stderr = %return io.getStdErr(); |
| 43 | var stderr_stream_adapter = io.FileOutStream.init(&stderr); |
| 44 | const stderr_stream = &stderr_stream_adapter.stream; |
| 45 | %return stderr_stream.print(format ++ "\n\n", args); |
| 46 | %return printUsage(&stderr_stream_adapter.stream); |
| 47 | return error.InvalidCommandLineArguments; |
| 48 | } |
| 49 | |
| 50 | pub fn main2() -> %void { |
| 51 | const allocator = std.heap.c_allocator; |
| 25 | 52 | |
| 26 | 53 | const args = %return os.argsAlloc(allocator); |
| 27 | 54 | defer os.argsFree(allocator, args); |
| 28 | 55 | |
| 29 | | target.initializeAll(); |
| 56 | var cmd = Cmd.None; |
| 57 | var build_kind: Module.Kind = undefined; |
| 58 | var build_mode: builtin.Mode = builtin.Mode.Debug; |
| 59 | var color = ErrColor.Auto; |
| 60 | var emit_file_type = Emit.Binary; |
| 61 | |
| 62 | var strip = false; |
| 63 | var is_static = false; |
| 64 | var verbose_tokenize = false; |
| 65 | var verbose_ast_tree = false; |
| 66 | var verbose_ast_fmt = false; |
| 67 | var verbose_link = false; |
| 68 | var verbose_ir = false; |
| 69 | var verbose_llvm_ir = false; |
| 70 | var verbose_cimport = false; |
| 71 | var mwindows = false; |
| 72 | var mconsole = false; |
| 73 | var rdynamic = false; |
| 74 | var each_lib_rpath = false; |
| 75 | var timing_info = false; |
| 76 | |
| 77 | var in_file_arg: ?[]u8 = null; |
| 78 | var out_file: ?[]u8 = null; |
| 79 | var out_file_h: ?[]u8 = null; |
| 80 | var out_name_arg: ?[]u8 = null; |
| 81 | var libc_lib_dir_arg: ?[]u8 = null; |
| 82 | var libc_static_lib_dir_arg: ?[]u8 = null; |
| 83 | var libc_include_dir_arg: ?[]u8 = null; |
| 84 | var msvc_lib_dir_arg: ?[]u8 = null; |
| 85 | var kernel32_lib_dir_arg: ?[]u8 = null; |
| 86 | var zig_install_prefix: ?[]u8 = null; |
| 87 | var dynamic_linker_arg: ?[]u8 = null; |
| 88 | var cache_dir_arg: ?[]const u8 = null; |
| 89 | var target_arch: ?[]u8 = null; |
| 90 | var target_os: ?[]u8 = null; |
| 91 | var target_environ: ?[]u8 = null; |
| 92 | var mmacosx_version_min: ?[]u8 = null; |
| 93 | var mios_version_min: ?[]u8 = null; |
| 94 | var linker_script_arg: ?[]u8 = null; |
| 95 | var test_name_prefix_arg: ?[]u8 = null; |
| 96 | |
| 97 | var test_filters = ArrayList([]const u8).init(allocator); |
| 98 | defer test_filters.deinit(); |
| 99 | |
| 100 | var lib_dirs = ArrayList([]const u8).init(allocator); |
| 101 | defer lib_dirs.deinit(); |
| 102 | |
| 103 | var clang_argv = ArrayList([]const u8).init(allocator); |
| 104 | defer clang_argv.deinit(); |
| 105 | |
| 106 | var llvm_argv = ArrayList([]const u8).init(allocator); |
| 107 | defer llvm_argv.deinit(); |
| 108 | |
| 109 | var link_libs = ArrayList([]const u8).init(allocator); |
| 110 | defer link_libs.deinit(); |
| 111 | |
| 112 | var frameworks = ArrayList([]const u8).init(allocator); |
| 113 | defer frameworks.deinit(); |
| 114 | |
| 115 | var objects = ArrayList([]const u8).init(allocator); |
| 116 | defer objects.deinit(); |
| 30 | 117 | |
| 31 | | const target_file = args[1]; |
| 118 | var asm_files = ArrayList([]const u8).init(allocator); |
| 119 | defer asm_files.deinit(); |
| 32 | 120 | |
| 33 | | const target_file_buf = %return io.readFileAlloc(target_file, allocator); |
| 34 | | defer allocator.free(target_file_buf); |
| 121 | var rpath_list = ArrayList([]const u8).init(allocator); |
| 122 | defer rpath_list.deinit(); |
| 35 | 123 | |
| 36 | | var stderr_file = %return std.io.getStdErr(); |
| 37 | | var stderr_file_out_stream = std.io.FileOutStream.init(&stderr_file); |
| 38 | | const out_stream = &stderr_file_out_stream.stream; |
| 124 | var ver_major: u32 = 0; |
| 125 | var ver_minor: u32 = 0; |
| 126 | var ver_patch: u32 = 0; |
| 39 | 127 | |
| 40 | | warn("====input:====\n"); |
| 128 | var arg_i: usize = 1; |
| 129 | while (arg_i < args.len) : (arg_i += 1) { |
| 130 | const arg = args[arg_i]; |
| 41 | 131 | |
| 42 | | warn("{}", target_file_buf); |
| 132 | if (arg.len != 0 and arg[0] == '-') { |
| 133 | if (mem.eql(u8, arg, "--release-fast")) { |
| 134 | build_mode = builtin.Mode.ReleaseFast; |
| 135 | } else if (mem.eql(u8, arg, "--release-safe")) { |
| 136 | build_mode = builtin.Mode.ReleaseSafe; |
| 137 | } else if (mem.eql(u8, arg, "--strip")) { |
| 138 | strip = true; |
| 139 | } else if (mem.eql(u8, arg, "--static")) { |
| 140 | is_static = true; |
| 141 | } else if (mem.eql(u8, arg, "--verbose-tokenize")) { |
| 142 | verbose_tokenize = true; |
| 143 | } else if (mem.eql(u8, arg, "--verbose-ast-tree")) { |
| 144 | verbose_ast_tree = true; |
| 145 | } else if (mem.eql(u8, arg, "--verbose-ast-fmt")) { |
| 146 | verbose_ast_fmt = true; |
| 147 | } else if (mem.eql(u8, arg, "--verbose-link")) { |
| 148 | verbose_link = true; |
| 149 | } else if (mem.eql(u8, arg, "--verbose-ir")) { |
| 150 | verbose_ir = true; |
| 151 | } else if (mem.eql(u8, arg, "--verbose-llvm-ir")) { |
| 152 | verbose_llvm_ir = true; |
| 153 | } else if (mem.eql(u8, arg, "--verbose-cimport")) { |
| 154 | verbose_cimport = true; |
| 155 | } else if (mem.eql(u8, arg, "-mwindows")) { |
| 156 | mwindows = true; |
| 157 | } else if (mem.eql(u8, arg, "-mconsole")) { |
| 158 | mconsole = true; |
| 159 | } else if (mem.eql(u8, arg, "-rdynamic")) { |
| 160 | rdynamic = true; |
| 161 | } else if (mem.eql(u8, arg, "--each-lib-rpath")) { |
| 162 | each_lib_rpath = true; |
| 163 | } else if (mem.eql(u8, arg, "--enable-timing-info")) { |
| 164 | timing_info = true; |
| 165 | } else if (mem.eql(u8, arg, "--test-cmd-bin")) { |
| 166 | @panic("TODO --test-cmd-bin"); |
| 167 | } else if (arg[1] == 'L' and arg.len > 2) { |
| 168 | // alias for --library-path |
| 169 | %return lib_dirs.append(arg[1..]); |
| 170 | } else if (mem.eql(u8, arg, "--pkg-begin")) { |
| 171 | @panic("TODO --pkg-begin"); |
| 172 | } else if (mem.eql(u8, arg, "--pkg-end")) { |
| 173 | @panic("TODO --pkg-end"); |
| 174 | } else if (arg_i + 1 >= args.len) { |
| 175 | return badArgs("expected another argument after {}", arg); |
| 176 | } else { |
| 177 | arg_i += 1; |
| 178 | if (mem.eql(u8, arg, "--output")) { |
| 179 | out_file = args[arg_i]; |
| 180 | } else if (mem.eql(u8, arg, "--output-h")) { |
| 181 | out_file_h = args[arg_i]; |
| 182 | } else if (mem.eql(u8, arg, "--color")) { |
| 183 | if (mem.eql(u8, args[arg_i], "auto")) { |
| 184 | color = ErrColor.Auto; |
| 185 | } else if (mem.eql(u8, args[arg_i], "on")) { |
| 186 | color = ErrColor.On; |
| 187 | } else if (mem.eql(u8, args[arg_i], "off")) { |
| 188 | color = ErrColor.Off; |
| 189 | } else { |
| 190 | return badArgs("--color options are 'auto', 'on', or 'off'"); |
| 191 | } |
| 192 | } else if (mem.eql(u8, arg, "--emit")) { |
| 193 | if (mem.eql(u8, args[arg_i], "asm")) { |
| 194 | emit_file_type = Emit.Assembly; |
| 195 | } else if (mem.eql(u8, args[arg_i], "bin")) { |
| 196 | emit_file_type = Emit.Binary; |
| 197 | } else if (mem.eql(u8, args[arg_i], "llvm-ir")) { |
| 198 | emit_file_type = Emit.LlvmIr; |
| 199 | } else { |
| 200 | return badArgs("--emit options are 'asm', 'bin', or 'llvm-ir'"); |
| 201 | } |
| 202 | } else if (mem.eql(u8, arg, "--name")) { |
| 203 | out_name_arg = args[arg_i]; |
| 204 | } else if (mem.eql(u8, arg, "--libc-lib-dir")) { |
| 205 | libc_lib_dir_arg = args[arg_i]; |
| 206 | } else if (mem.eql(u8, arg, "--libc-static-lib-dir")) { |
| 207 | libc_static_lib_dir_arg = args[arg_i]; |
| 208 | } else if (mem.eql(u8, arg, "--libc-include-dir")) { |
| 209 | libc_include_dir_arg = args[arg_i]; |
| 210 | } else if (mem.eql(u8, arg, "--msvc-lib-dir")) { |
| 211 | msvc_lib_dir_arg = args[arg_i]; |
| 212 | } else if (mem.eql(u8, arg, "--kernel32-lib-dir")) { |
| 213 | kernel32_lib_dir_arg = args[arg_i]; |
| 214 | } else if (mem.eql(u8, arg, "--zig-install-prefix")) { |
| 215 | zig_install_prefix = args[arg_i]; |
| 216 | } else if (mem.eql(u8, arg, "--dynamic-linker")) { |
| 217 | dynamic_linker_arg = args[arg_i]; |
| 218 | } else if (mem.eql(u8, arg, "-isystem")) { |
| 219 | %return clang_argv.append("-isystem"); |
| 220 | %return clang_argv.append(args[arg_i]); |
| 221 | } else if (mem.eql(u8, arg, "-dirafter")) { |
| 222 | %return clang_argv.append("-dirafter"); |
| 223 | %return clang_argv.append(args[arg_i]); |
| 224 | } else if (mem.eql(u8, arg, "-mllvm")) { |
| 225 | %return clang_argv.append("-mllvm"); |
| 226 | %return clang_argv.append(args[arg_i]); |
| 43 | 227 | |
| 44 | | warn("====tokenization:====\n"); |
| 45 | | { |
| 46 | | var tokenizer = Tokenizer.init(target_file_buf); |
| 47 | | while (true) { |
| 48 | | const token = tokenizer.next(); |
| 49 | | tokenizer.dump(token); |
| 50 | | if (token.id == Token.Id.Eof) { |
| 51 | | break; |
| 228 | %return llvm_argv.append(args[arg_i]); |
| 229 | } else if (mem.eql(u8, arg, "--library-path") or mem.eql(u8, arg, "-L")) { |
| 230 | %return lib_dirs.append(args[arg_i]); |
| 231 | } else if (mem.eql(u8, arg, "--library")) { |
| 232 | %return link_libs.append(args[arg_i]); |
| 233 | } else if (mem.eql(u8, arg, "--object")) { |
| 234 | %return objects.append(args[arg_i]); |
| 235 | } else if (mem.eql(u8, arg, "--assembly")) { |
| 236 | %return asm_files.append(args[arg_i]); |
| 237 | } else if (mem.eql(u8, arg, "--cache-dir")) { |
| 238 | cache_dir_arg = args[arg_i]; |
| 239 | } else if (mem.eql(u8, arg, "--target-arch")) { |
| 240 | target_arch = args[arg_i]; |
| 241 | } else if (mem.eql(u8, arg, "--target-os")) { |
| 242 | target_os = args[arg_i]; |
| 243 | } else if (mem.eql(u8, arg, "--target-environ")) { |
| 244 | target_environ = args[arg_i]; |
| 245 | } else if (mem.eql(u8, arg, "-mmacosx-version-min")) { |
| 246 | mmacosx_version_min = args[arg_i]; |
| 247 | } else if (mem.eql(u8, arg, "-mios-version-min")) { |
| 248 | mios_version_min = args[arg_i]; |
| 249 | } else if (mem.eql(u8, arg, "-framework")) { |
| 250 | %return frameworks.append(args[arg_i]); |
| 251 | } else if (mem.eql(u8, arg, "--linker-script")) { |
| 252 | linker_script_arg = args[arg_i]; |
| 253 | } else if (mem.eql(u8, arg, "-rpath")) { |
| 254 | %return rpath_list.append(args[arg_i]); |
| 255 | } else if (mem.eql(u8, arg, "--test-filter")) { |
| 256 | %return test_filters.append(args[arg_i]); |
| 257 | } else if (mem.eql(u8, arg, "--test-name-prefix")) { |
| 258 | test_name_prefix_arg = args[arg_i]; |
| 259 | } else if (mem.eql(u8, arg, "--ver-major")) { |
| 260 | ver_major = %return std.fmt.parseUnsigned(u32, args[arg_i], 10); |
| 261 | } else if (mem.eql(u8, arg, "--ver-minor")) { |
| 262 | ver_minor = %return std.fmt.parseUnsigned(u32, args[arg_i], 10); |
| 263 | } else if (mem.eql(u8, arg, "--ver-patch")) { |
| 264 | ver_patch = %return std.fmt.parseUnsigned(u32, args[arg_i], 10); |
| 265 | } else if (mem.eql(u8, arg, "--test-cmd")) { |
| 266 | @panic("TODO --test-cmd"); |
| 267 | } else { |
| 268 | return badArgs("invalid argument: {}", arg); |
| 269 | } |
| 52 | 270 | } |
| 271 | } else if (cmd == Cmd.None) { |
| 272 | if (mem.eql(u8, arg, "build-obj")) { |
| 273 | cmd = Cmd.Build; |
| 274 | build_kind = Module.Kind.Obj; |
| 275 | } else if (mem.eql(u8, arg, "build-exe")) { |
| 276 | cmd = Cmd.Build; |
| 277 | build_kind = Module.Kind.Exe; |
| 278 | } else if (mem.eql(u8, arg, "build-lib")) { |
| 279 | cmd = Cmd.Build; |
| 280 | build_kind = Module.Kind.Lib; |
| 281 | } else if (mem.eql(u8, arg, "version")) { |
| 282 | cmd = Cmd.Version; |
| 283 | } else if (mem.eql(u8, arg, "zen")) { |
| 284 | cmd = Cmd.Zen; |
| 285 | } else if (mem.eql(u8, arg, "translate-c")) { |
| 286 | cmd = Cmd.TranslateC; |
| 287 | } else if (mem.eql(u8, arg, "test")) { |
| 288 | cmd = Cmd.Test; |
| 289 | build_kind = Module.Kind.Exe; |
| 290 | } else { |
| 291 | return badArgs("unrecognized command: {}", arg); |
| 292 | } |
| 293 | } else switch (cmd) { |
| 294 | Cmd.Build, Cmd.TranslateC, Cmd.Test => { |
| 295 | if (in_file_arg == null) { |
| 296 | in_file_arg = arg; |
| 297 | } else { |
| 298 | return badArgs("unexpected extra parameter: {}", arg); |
| 299 | } |
| 300 | }, |
| 301 | Cmd.Version, Cmd.Zen, Cmd.Targets => { |
| 302 | return badArgs("unexpected extra parameter: {}", arg); |
| 303 | }, |
| 304 | Cmd.None => unreachable, |
| 53 | 305 | } |
| 54 | 306 | } |
| 55 | 307 | |
| 56 | | warn("====parse:====\n"); |
| 308 | target.initializeAll(); |
| 309 | |
| 310 | // TODO |
| 311 | // ZigTarget alloc_target; |
| 312 | // ZigTarget *target; |
| 313 | // if (!target_arch && !target_os && !target_environ) { |
| 314 | // target = nullptr; |
| 315 | // } else { |
| 316 | // target = &alloc_target; |
| 317 | // get_unknown_target(target); |
| 318 | // if (target_arch) { |
| 319 | // if (parse_target_arch(target_arch, &target->arch)) { |
| 320 | // fprintf(stderr, "invalid --target-arch argument\n"); |
| 321 | // return usage(arg0); |
| 322 | // } |
| 323 | // } |
| 324 | // if (target_os) { |
| 325 | // if (parse_target_os(target_os, &target->os)) { |
| 326 | // fprintf(stderr, "invalid --target-os argument\n"); |
| 327 | // return usage(arg0); |
| 328 | // } |
| 329 | // } |
| 330 | // if (target_environ) { |
| 331 | // if (parse_target_environ(target_environ, &target->env_type)) { |
| 332 | // fprintf(stderr, "invalid --target-environ argument\n"); |
| 333 | // return usage(arg0); |
| 334 | // } |
| 335 | // } |
| 336 | // } |
| 337 | |
| 338 | switch (cmd) { |
| 339 | Cmd.None => return badArgs("expected command"), |
| 340 | Cmd.Zen => return printZen(), |
| 341 | Cmd.Build, Cmd.Test, Cmd.TranslateC => { |
| 342 | if (cmd == Cmd.Build and in_file_arg == null and objects.len == 0 and asm_files.len == 0) { |
| 343 | return badArgs("expected source file argument or at least one --object or --assembly argument"); |
| 344 | } else if ((cmd == Cmd.TranslateC or cmd == Cmd.Test) and in_file_arg == null) { |
| 345 | return badArgs("expected source file argument"); |
| 346 | } else if (cmd == Cmd.Build and build_kind == Module.Kind.Obj and objects.len != 0) { |
| 347 | return badArgs("When building an object file, --object arguments are invalid"); |
| 348 | } |
| 349 | |
| 350 | const root_name = switch (cmd) { |
| 351 | Cmd.Build, Cmd.TranslateC => x: { |
| 352 | if (out_name_arg) |out_name| { |
| 353 | break :x out_name; |
| 354 | } else if (in_file_arg) |in_file_path| { |
| 355 | const basename = os.path.basename(in_file_path); |
| 356 | var it = mem.split(basename, "."); |
| 357 | break :x it.next() ?? return badArgs("file name cannot be empty"); |
| 358 | } else { |
| 359 | return badArgs("--name [name] not provided and unable to infer"); |
| 360 | } |
| 361 | }, |
| 362 | Cmd.Test => "test", |
| 363 | else => unreachable, |
| 364 | }; |
| 365 | |
| 366 | const zig_root_source_file = if (cmd == Cmd.TranslateC) null else in_file_arg; |
| 367 | |
| 368 | const chosen_cache_dir = cache_dir_arg ?? default_zig_cache_name; |
| 369 | const full_cache_dir = %return os.path.resolve(allocator, ".", chosen_cache_dir); |
| 370 | defer allocator.free(full_cache_dir); |
| 371 | |
| 372 | const zig_lib_dir = %return resolveZigLibDir(allocator, zig_install_prefix); |
| 373 | %defer allocator.free(zig_lib_dir); |
| 374 | |
| 375 | const module = %return Module.create(allocator, root_name, zig_root_source_file, |
| 376 | Target.Native, build_kind, build_mode, zig_lib_dir, full_cache_dir); |
| 377 | defer module.destroy(); |
| 378 | |
| 379 | module.version_major = ver_major; |
| 380 | module.version_minor = ver_minor; |
| 381 | module.version_patch = ver_patch; |
| 382 | |
| 383 | module.is_test = cmd == Cmd.Test; |
| 384 | if (linker_script_arg) |linker_script| { |
| 385 | module.linker_script = linker_script; |
| 386 | } |
| 387 | module.each_lib_rpath = each_lib_rpath; |
| 388 | module.clang_argv = clang_argv.toSliceConst(); |
| 389 | module.llvm_argv = llvm_argv.toSliceConst(); |
| 390 | module.strip = strip; |
| 391 | module.is_static = is_static; |
| 392 | |
| 393 | if (libc_lib_dir_arg) |libc_lib_dir| { |
| 394 | module.libc_lib_dir = libc_lib_dir; |
| 395 | } |
| 396 | if (libc_static_lib_dir_arg) |libc_static_lib_dir| { |
| 397 | module.libc_static_lib_dir = libc_static_lib_dir; |
| 398 | } |
| 399 | if (libc_include_dir_arg) |libc_include_dir| { |
| 400 | module.libc_include_dir = libc_include_dir; |
| 401 | } |
| 402 | if (msvc_lib_dir_arg) |msvc_lib_dir| { |
| 403 | module.msvc_lib_dir = msvc_lib_dir; |
| 404 | } |
| 405 | if (kernel32_lib_dir_arg) |kernel32_lib_dir| { |
| 406 | module.kernel32_lib_dir = kernel32_lib_dir; |
| 407 | } |
| 408 | if (dynamic_linker_arg) |dynamic_linker| { |
| 409 | module.dynamic_linker = dynamic_linker; |
| 410 | } |
| 411 | module.verbose_tokenize = verbose_tokenize; |
| 412 | module.verbose_ast_tree = verbose_ast_tree; |
| 413 | module.verbose_ast_fmt = verbose_ast_fmt; |
| 414 | module.verbose_link = verbose_link; |
| 415 | module.verbose_ir = verbose_ir; |
| 416 | module.verbose_llvm_ir = verbose_llvm_ir; |
| 417 | module.verbose_cimport = verbose_cimport; |
| 418 | |
| 419 | module.err_color = color; |
| 420 | |
| 421 | module.lib_dirs = lib_dirs.toSliceConst(); |
| 422 | module.darwin_frameworks = frameworks.toSliceConst(); |
| 423 | module.rpath_list = rpath_list.toSliceConst(); |
| 424 | |
| 425 | for (link_libs.toSliceConst()) |name| { |
| 426 | _ = %return module.addLinkLib(name, true); |
| 427 | } |
| 428 | |
| 429 | module.windows_subsystem_windows = mwindows; |
| 430 | module.windows_subsystem_console = mconsole; |
| 431 | module.linker_rdynamic = rdynamic; |
| 432 | |
| 433 | if (mmacosx_version_min != null and mios_version_min != null) { |
| 434 | return badArgs("-mmacosx-version-min and -mios-version-min options not allowed together"); |
| 435 | } |
| 436 | |
| 437 | if (mmacosx_version_min) |ver| { |
| 438 | module.darwin_version_min = Module.DarwinVersionMin { .MacOS = ver }; |
| 439 | } else if (mios_version_min) |ver| { |
| 440 | module.darwin_version_min = Module.DarwinVersionMin { .Ios = ver }; |
| 441 | } |
| 442 | |
| 443 | module.test_filters = test_filters.toSliceConst(); |
| 444 | module.test_name_prefix = test_name_prefix_arg; |
| 445 | module.out_h_path = out_file_h; |
| 446 | |
| 447 | // TODO |
| 448 | //add_package(g, cur_pkg, g->root_package); |
| 449 | |
| 450 | switch (cmd) { |
| 451 | Cmd.Build => { |
| 452 | module.emit_file_type = emit_file_type; |
| 453 | |
| 454 | module.link_objects = objects.toSliceConst(); |
| 455 | module.assembly_files = asm_files.toSliceConst(); |
| 456 | |
| 457 | %return module.build(); |
| 458 | %return module.link(out_file); |
| 459 | }, |
| 460 | Cmd.TranslateC => @panic("TODO translate-c"), |
| 461 | Cmd.Test => @panic("TODO test cmd"), |
| 462 | else => unreachable, |
| 463 | } |
| 464 | }, |
| 465 | Cmd.Version => @panic("TODO zig version"), |
| 466 | Cmd.Targets => @panic("TODO zig targets"), |
| 467 | } |
| 468 | } |
| 469 | |
| 470 | fn printUsage(stream: &io.OutStream) -> %void { |
| 471 | %return stream.write( |
| 472 | \\Usage: zig [command] [options] |
| 473 | \\ |
| 474 | \\Commands: |
| 475 | \\ build build project from build.zig |
| 476 | \\ build-exe [source] create executable from source or object files |
| 477 | \\ build-lib [source] create library from source or object files |
| 478 | \\ build-obj [source] create object from source or assembly |
| 479 | \\ translate-c [source] convert c code to zig code |
| 480 | \\ targets list available compilation targets |
| 481 | \\ test [source] create and run a test build |
| 482 | \\ version print version number and exit |
| 483 | \\ zen print zen of zig and exit |
| 484 | \\Compile Options: |
| 485 | \\ --assembly [source] add assembly file to build |
| 486 | \\ --cache-dir [path] override the cache directory |
| 487 | \\ --color [auto|off|on] enable or disable colored error messages |
| 488 | \\ --emit [filetype] emit a specific file format as compilation output |
| 489 | \\ --enable-timing-info print timing diagnostics |
| 490 | \\ --libc-include-dir [path] directory where libc stdlib.h resides |
| 491 | \\ --name [name] override output name |
| 492 | \\ --output [file] override destination path |
| 493 | \\ --output-h [file] override generated header file path |
| 494 | \\ --pkg-begin [name] [path] make package available to import and push current pkg |
| 495 | \\ --pkg-end pop current pkg |
| 496 | \\ --release-fast build with optimizations on and safety off |
| 497 | \\ --release-safe build with optimizations on and safety on |
| 498 | \\ --static output will be statically linked |
| 499 | \\ --strip exclude debug symbols |
| 500 | \\ --target-arch [name] specify target architecture |
| 501 | \\ --target-environ [name] specify target environment |
| 502 | \\ --target-os [name] specify target operating system |
| 503 | \\ --verbose-tokenize enable compiler debug info: tokenization |
| 504 | \\ --verbose-ast-tree enable compiler debug info: parsing into an AST (treeview) |
| 505 | \\ --verbose-ast-fmt enable compiler debug info: parsing into an AST (render source) |
| 506 | \\ --verbose-cimport enable compiler debug info: C imports |
| 507 | \\ --verbose-ir enable compiler debug info: Zig IR |
| 508 | \\ --verbose-llvm-ir enable compiler debug info: LLVM IR |
| 509 | \\ --verbose-link enable compiler debug info: linking |
| 510 | \\ --zig-install-prefix [path] override directory where zig thinks it is installed |
| 511 | \\ -dirafter [dir] same as -isystem but do it last |
| 512 | \\ -isystem [dir] add additional search path for other .h files |
| 513 | \\ -mllvm [arg] additional arguments to forward to LLVM's option processing |
| 514 | \\Link Options: |
| 515 | \\ --ar-path [path] set the path to ar |
| 516 | \\ --dynamic-linker [path] set the path to ld.so |
| 517 | \\ --each-lib-rpath add rpath for each used dynamic library |
| 518 | \\ --libc-lib-dir [path] directory where libc crt1.o resides |
| 519 | \\ --libc-static-lib-dir [path] directory where libc crtbegin.o resides |
| 520 | \\ --msvc-lib-dir [path] (windows) directory where vcruntime.lib resides |
| 521 | \\ --kernel32-lib-dir [path] (windows) directory where kernel32.lib resides |
| 522 | \\ --library [lib] link against lib |
| 523 | \\ --library-path [dir] add a directory to the library search path |
| 524 | \\ --linker-script [path] use a custom linker script |
| 525 | \\ --object [obj] add object file to build |
| 526 | \\ -L[dir] alias for --library-path |
| 527 | \\ -rdynamic add all symbols to the dynamic symbol table |
| 528 | \\ -rpath [path] add directory to the runtime library search path |
| 529 | \\ -mconsole (windows) --subsystem console to the linker |
| 530 | \\ -mwindows (windows) --subsystem windows to the linker |
| 531 | \\ -framework [name] (darwin) link against framework |
| 532 | \\ -mios-version-min [ver] (darwin) set iOS deployment target |
| 533 | \\ -mmacosx-version-min [ver] (darwin) set Mac OS X deployment target |
| 534 | \\ --ver-major [ver] dynamic library semver major version |
| 535 | \\ --ver-minor [ver] dynamic library semver minor version |
| 536 | \\ --ver-patch [ver] dynamic library semver patch version |
| 537 | \\Test Options: |
| 538 | \\ --test-filter [text] skip tests that do not match filter |
| 539 | \\ --test-name-prefix [text] add prefix to all tests |
| 540 | \\ --test-cmd [arg] specify test execution command one arg at a time |
| 541 | \\ --test-cmd-bin appends test binary path to test cmd args |
| 542 | \\ |
| 543 | ); |
| 544 | } |
| 57 | 545 | |
| 58 | | var tokenizer = Tokenizer.init(target_file_buf); |
| 59 | | var parser = Parser.init(&tokenizer, allocator, target_file); |
| 60 | | defer parser.deinit(); |
| 546 | fn printZen() -> %void { |
| 547 | var stdout_file = %return io.getStdErr(); |
| 548 | %return stdout_file.write( |
| 549 | \\ |
| 550 | \\ * Communicate intent precisely. |
| 551 | \\ * Edge cases matter. |
| 552 | \\ * Favor reading code over writing code. |
| 553 | \\ * Only one obvious way to do things. |
| 554 | \\ * Runtime crashes are better than bugs. |
| 555 | \\ * Compile errors are better than runtime crashes. |
| 556 | \\ * Incremental improvements. |
| 557 | \\ * Avoid local maximums. |
| 558 | \\ * Reduce the amount one must remember. |
| 559 | \\ * Minimize energy spent on coding style. |
| 560 | \\ * Together we serve end users. |
| 561 | \\ |
| 562 | \\ |
| 563 | ); |
| 564 | } |
| 565 | |
| 566 | /// Caller must free result |
| 567 | fn resolveZigLibDir(allocator: &mem.Allocator, zig_install_prefix_arg: ?[]const u8) -> %[]u8 { |
| 568 | if (zig_install_prefix_arg) |zig_install_prefix| { |
| 569 | return testZigInstallPrefix(allocator, zig_install_prefix) %% |err| { |
| 570 | warn("No Zig installation found at prefix {}: {}\n", zig_install_prefix_arg, @errorName(err)); |
| 571 | return error.ZigInstallationNotFound; |
| 572 | }; |
| 573 | } else { |
| 574 | return findZigLibDir(allocator) %% |err| { |
| 575 | warn("Unable to find zig lib directory: {}.\nReinstall Zig or use --zig-install-prefix.\n", |
| 576 | @errorName(err)); |
| 577 | return error.ZigLibDirNotFound; |
| 578 | }; |
| 579 | } |
| 580 | } |
| 61 | 581 | |
| 62 | | const root_node = %return parser.parse(); |
| 63 | | defer parser.freeAst(root_node); |
| 582 | /// Caller must free result |
| 583 | fn testZigInstallPrefix(allocator: &mem.Allocator, test_path: []const u8) -> %[]u8 { |
| 584 | const test_zig_dir = %return os.path.join(allocator, test_path, "lib", "zig"); |
| 585 | %defer allocator.free(test_zig_dir); |
| 64 | 586 | |
| 65 | | %return parser.renderAst(out_stream, root_node); |
| 587 | const test_index_file = %return os.path.join(allocator, test_zig_dir, "std", "index.zig"); |
| 588 | defer allocator.free(test_index_file); |
| 66 | 589 | |
| 67 | | warn("====fmt:====\n"); |
| 68 | | %return parser.renderSource(out_stream, root_node); |
| 590 | var file = %return io.File.openRead(test_index_file, allocator); |
| 591 | file.close(); |
| 592 | |
| 593 | return test_zig_dir; |
| 69 | 594 | } |
| 70 | 595 | |
| 71 | | test "import other tests" { |
| 72 | | _ = @import("parser.zig"); |
| 73 | | _ = @import("tokenizer.zig"); |
| 596 | /// Caller must free result |
| 597 | fn findZigLibDir(allocator: &mem.Allocator) -> %[]u8 { |
| 598 | const self_exe_path = %return os.selfExeDirPath(allocator); |
| 599 | defer allocator.free(self_exe_path); |
| 600 | |
| 601 | var cur_path: []const u8 = self_exe_path; |
| 602 | while (true) { |
| 603 | const test_dir = os.path.dirname(cur_path); |
| 604 | |
| 605 | if (mem.eql(u8, test_dir, cur_path)) { |
| 606 | break; |
| 607 | } |
| 608 | |
| 609 | return testZigInstallPrefix(allocator, test_dir) %% |err| { |
| 610 | cur_path = test_dir; |
| 611 | continue; |
| 612 | }; |
| 613 | } |
| 614 | |
| 615 | // TODO look in hard coded installation path from configuration |
| 616 | //if (ZIG_INSTALL_PREFIX != nullptr) { |
| 617 | // if (test_zig_install_prefix(buf_create_from_str(ZIG_INSTALL_PREFIX), out_path)) { |
| 618 | // return 0; |
| 619 | // } |
| 620 | //} |
| 621 | |
| 622 | return error.FileNotFound; |
| 74 | 623 | } |