blob bf2dbcf6 (27653B) - Raw
1 /* 2 * Copyright (c) 2015 Andrew Kelley 3 * 4 * This file is part of zig, which is MIT licensed. 5 * See http://opensource.org/licenses/MIT 6 */ 7 8 #include "ast_render.hpp" 9 #include "buffer.hpp" 10 #include "codegen.hpp" 11 #include "config.h" 12 #include "error.hpp" 13 #include "link.hpp" 14 #include "os.hpp" 15 #include "target.hpp" 16 17 #include <stdio.h> 18 19 static int usage(const char *arg0) { 20 fprintf(stderr, "Usage: %s [command] [options]\n" 21 "Commands:\n" 22 " asm [source] create object from assembly\n" 23 " build build project from build.zig\n" 24 " build_exe [source] create executable from source\n" 25 " build_lib [source] create library from source\n" 26 " build_obj [source] create object from source\n" 27 " link_exe [objects] create executable from objects\n" 28 " link_lib [objects] create library from objects\n" 29 " parseh [source] convert a c header file to zig extern declarations\n" 30 " targets list available compilation targets\n" 31 " test [source] create and run a test build\n" 32 " version print version number and exit\n" 33 "Options:\n" 34 " --ar-path [path] set the path to ar\n" 35 " --color [auto|off|on] enable or disable colored error messages\n" 36 " --dynamic-linker [path] set the path to ld.so\n" 37 " --each-lib-rpath add rpath for each used dynamic library\n" 38 " --ld-path [path] set the path to the linker\n" 39 " --libc-include-dir [path] directory where libc stdlib.h resides\n" 40 " --libc-lib-dir [path] directory where libc crt1.o resides\n" 41 " --libc-static-lib-dir [path] directory where libc crtbegin.o resides\n" 42 " --library [lib] link against lib\n" 43 " --library-path [dir] add a directory to the library search path\n" 44 " --linker-script [path] use a custom linker script\n" 45 " --name [name] override output name\n" 46 " --output [file] override destination path\n" 47 " --release build with optimizations on and debug protection off\n" 48 " --static output will be statically linked\n" 49 " --strip exclude debug symbols\n" 50 " --target-arch [name] specify target architecture\n" 51 " --target-environ [name] specify target environment\n" 52 " --target-os [name] specify target operating system\n" 53 " --verbose turn on compiler debug output\n" 54 " --zig-std-dir [path] directory where zig standard library resides\n" 55 " -L[dir] alias for --library-path\n" 56 " -dirafter [dir] same as -isystem but do it last\n" 57 " -framework [name] (darwin only) link against framework\n" 58 " -isystem [dir] add additional search path for other .h files\n" 59 " -mconsole (windows only) --subsystem console to the linker\n" 60 " -mios-version-min [ver] (darwin only) set iOS deployment target\n" 61 " -mlinker-version [ver] (darwin only) override linker version\n" 62 " -mmacosx-version-min [ver] (darwin only) set Mac OS X deployment target\n" 63 " -municode (windows only) link with unicode\n" 64 " -mwindows (windows only) --subsystem windows to the linker\n" 65 " -rdynamic add all symbols to the dynamic symbol table\n" 66 " -rpath [path] add directory to the runtime library search path\n" 67 "Test Options:\n" 68 " --test-filter [text] skip tests that do not match filter\n" 69 " --test-name-prefix [text] add prefix to all tests\n" 70 "Dynamic Library Options:\n" 71 " --ver-major [ver] semver major version\n" 72 " --ver-minor [ver] semver minor version\n" 73 " --ver-patch [ver] semver patch version\n" 74 , arg0); 75 return EXIT_FAILURE; 76 } 77 78 static int print_target_list(FILE *f) { 79 ZigTarget native; 80 get_native_target(&native); 81 82 fprintf(f, "Architectures:\n"); 83 size_t arch_count = target_arch_count(); 84 for (size_t arch_i = 0; arch_i < arch_count; arch_i += 1) { 85 const ArchType *arch = get_target_arch(arch_i); 86 char arch_name[50]; 87 get_arch_name(arch_name, arch); 88 const char *native_str = (native.arch.arch == arch->arch && native.arch.sub_arch == arch->sub_arch) ? 89 " (native)" : ""; 90 fprintf(f, " %s%s\n", arch_name, native_str); 91 } 92 93 fprintf(f, "\nOperating Systems:\n"); 94 size_t os_count = target_os_count(); 95 for (size_t i = 0; i < os_count; i += 1) { 96 ZigLLVM_OSType os_type = get_target_os(i); 97 const char *native_str = (native.os == os_type) ? " (native)" : ""; 98 fprintf(f, " %s%s\n", get_target_os_name(os_type), native_str); 99 } 100 101 fprintf(f, "\nEnvironments:\n"); 102 size_t environ_count = target_environ_count(); 103 for (size_t i = 0; i < environ_count; i += 1) { 104 ZigLLVM_EnvironmentType environ_type = get_target_environ(i); 105 const char *native_str = (native.env_type == environ_type) ? " (native)" : ""; 106 fprintf(f, " %s%s\n", ZigLLVMGetEnvironmentTypeName(environ_type), native_str); 107 } 108 109 return EXIT_SUCCESS; 110 } 111 112 enum Cmd { 113 CmdInvalid, 114 CmdBuild, 115 CmdTest, 116 CmdVersion, 117 CmdParseH, 118 CmdTargets, 119 CmdAsm, 120 CmdLink, 121 }; 122 123 int main(int argc, char **argv) { 124 os_init(); 125 126 char *arg0 = argv[0]; 127 Cmd cmd = CmdInvalid; 128 const char *in_file = nullptr; 129 const char *out_file = nullptr; 130 bool is_release_build = false; 131 bool strip = false; 132 bool is_static = false; 133 OutType out_type = OutTypeUnknown; 134 const char *out_name = nullptr; 135 bool verbose = false; 136 ErrColor color = ErrColorAuto; 137 const char *libc_lib_dir = nullptr; 138 const char *libc_static_lib_dir = nullptr; 139 const char *libc_include_dir = nullptr; 140 const char *zig_std_dir = nullptr; 141 const char *dynamic_linker = nullptr; 142 ZigList<const char *> clang_argv = {0}; 143 ZigList<const char *> lib_dirs = {0}; 144 ZigList<const char *> link_libs = {0}; 145 ZigList<const char *> frameworks = {0}; 146 int err; 147 const char *target_arch = nullptr; 148 const char *target_os = nullptr; 149 const char *target_environ = nullptr; 150 bool mwindows = false; 151 bool mconsole = false; 152 bool municode = false; 153 const char *mlinker_version = nullptr; 154 bool rdynamic = false; 155 const char *mmacosx_version_min = nullptr; 156 const char *mios_version_min = nullptr; 157 const char *linker_script = nullptr; 158 ZigList<const char *> rpath_list = {0}; 159 bool each_lib_rpath = false; 160 ZigList<const char *> objects = {0}; 161 const char *test_filter = nullptr; 162 const char *test_name_prefix = nullptr; 163 size_t ver_major = 0; 164 size_t ver_minor = 0; 165 size_t ver_patch = 0; 166 167 if (argc >= 2 && strcmp(argv[1], "build") == 0) { 168 const char *zig_exe_path = arg0; 169 const char *build_file = "build.zig"; 170 bool asked_for_help = false; 171 172 init_all_targets(); 173 174 Buf *zig_std_dir = buf_create_from_str(ZIG_STD_DIR); 175 Buf *special_dir = buf_alloc(); 176 os_path_join(zig_std_dir, buf_sprintf("special"), special_dir); 177 178 Buf *build_runner_path = buf_alloc(); 179 os_path_join(special_dir, buf_create_from_str("build_runner.zig"), build_runner_path); 180 181 ZigList<const char *> args = {0}; 182 args.append(zig_exe_path); 183 args.append(NULL); // placeholder 184 for (int i = 2; i < argc; i += 1) { 185 if (strcmp(argv[i], "--debug-build-verbose") == 0) { 186 verbose = true; 187 } else if (strcmp(argv[i], "--help") == 0) { 188 asked_for_help = true; 189 args.append(argv[i]); 190 } else if (i + 1 < argc && strcmp(argv[i], "--build-file") == 0) { 191 build_file = argv[i + 1]; 192 i += 1; 193 } else { 194 args.append(argv[i]); 195 } 196 } 197 198 199 Buf root_source_dir = BUF_INIT; 200 Buf root_source_code = BUF_INIT; 201 Buf root_source_name = BUF_INIT; 202 os_path_split(build_runner_path, &root_source_dir, &root_source_name); 203 if ((err = os_fetch_file_path(build_runner_path, &root_source_code))) { 204 fprintf(stderr, "unable to open '%s': %s\n", buf_ptr(build_runner_path), err_str(err)); 205 return 1; 206 } 207 CodeGen *g = codegen_create(&root_source_dir, nullptr); 208 codegen_set_out_name(g, buf_create_from_str("build")); 209 codegen_set_out_type(g, OutTypeExe); 210 codegen_set_verbose(g, verbose); 211 212 Buf build_file_abs = BUF_INIT; 213 os_path_resolve(buf_create_from_str("."), buf_create_from_str(build_file), &build_file_abs); 214 Buf build_file_basename = BUF_INIT; 215 Buf build_file_dirname = BUF_INIT; 216 os_path_split(&build_file_abs, &build_file_dirname, &build_file_basename); 217 218 args.items[1] = buf_ptr(&build_file_dirname); 219 220 bool build_file_exists; 221 if ((err = os_file_exists(&build_file_abs, &build_file_exists))) { 222 fprintf(stderr, "unable to open '%s': %s\n", buf_ptr(&build_file_abs), err_str(err)); 223 return 1; 224 } 225 if (!build_file_exists) { 226 if (asked_for_help) { 227 // This usage text has to be synchronized with std/special/build_runner.zig 228 fprintf(stdout, 229 "Usage: %s build [options]\n" 230 "\n" 231 "General Options:\n" 232 " --help Print this help and exit\n" 233 " --build-file [file] Override path to build.zig\n" 234 " --verbose Print commands before executing them\n" 235 " --debug-build-verbose Print verbose debugging information for the build system itself\n" 236 " --prefix [prefix] Override default install prefix\n" 237 "\n" 238 "More options become available when the build file is found.\n" 239 "Run this command with no options to generate a build.zig template.\n" 240 , zig_exe_path); 241 return 0; 242 } 243 Buf *build_template_path = buf_alloc(); 244 os_path_join(special_dir, buf_create_from_str("build_file_template.zig"), build_template_path); 245 246 if ((err = os_copy_file(build_template_path, &build_file_abs))) { 247 fprintf(stderr, "Unable to write build.zig template: %s\n", err_str(err)); 248 } else { 249 fprintf(stderr, "Wrote build.zig template\n"); 250 } 251 return 1; 252 } 253 254 PackageTableEntry *build_pkg = new_package(buf_ptr(&build_file_dirname), buf_ptr(&build_file_basename)); 255 build_pkg->package_table.put(buf_create_from_str("std"), g->std_package); 256 g->root_package->package_table.put(buf_create_from_str("@build"), build_pkg); 257 codegen_add_root_code(g, &root_source_dir, &root_source_name, &root_source_code); 258 codegen_link(g, "build"); 259 260 Termination term; 261 os_spawn_process("./build", args, &term); 262 if (term.how != TerminationIdClean || term.code != 0) { 263 fprintf(stderr, "\nBuild failed. Use the following command to reproduce the failure:\n"); 264 fprintf(stderr, "./build"); 265 for (size_t i = 0; i < args.length; i += 1) { 266 fprintf(stderr, " %s", args.at(i)); 267 } 268 fprintf(stderr, "\n"); 269 } 270 return (term.how == TerminationIdClean) ? term.code : -1; 271 } 272 273 for (int i = 1; i < argc; i += 1) { 274 char *arg = argv[i]; 275 276 if (arg[0] == '-') { 277 if (strcmp(arg, "--release") == 0) { 278 is_release_build = true; 279 } else if (strcmp(arg, "--strip") == 0) { 280 strip = true; 281 } else if (strcmp(arg, "--static") == 0) { 282 is_static = true; 283 } else if (strcmp(arg, "--verbose") == 0) { 284 verbose = true; 285 } else if (strcmp(arg, "-mwindows") == 0) { 286 mwindows = true; 287 } else if (strcmp(arg, "-mconsole") == 0) { 288 mconsole = true; 289 } else if (strcmp(arg, "-municode") == 0) { 290 municode = true; 291 } else if (strcmp(arg, "-rdynamic") == 0) { 292 rdynamic = true; 293 } else if (strcmp(arg, "--each-lib-rpath") == 0) { 294 each_lib_rpath = true; 295 } else if (arg[1] == 'L' && arg[2] != 0) { 296 // alias for --library-path 297 lib_dirs.append(&arg[2]); 298 } else if (i + 1 >= argc) { 299 return usage(arg0); 300 } else { 301 i += 1; 302 if (i >= argc) { 303 return usage(arg0); 304 } else if (strcmp(arg, "--output") == 0) { 305 out_file = argv[i]; 306 } else if (strcmp(arg, "--color") == 0) { 307 if (strcmp(argv[i], "auto") == 0) { 308 color = ErrColorAuto; 309 } else if (strcmp(argv[i], "on") == 0) { 310 color = ErrColorOn; 311 } else if (strcmp(argv[i], "off") == 0) { 312 color = ErrColorOff; 313 } else { 314 return usage(arg0); 315 } 316 } else if (strcmp(arg, "--name") == 0) { 317 out_name = argv[i]; 318 } else if (strcmp(arg, "--libc-lib-dir") == 0) { 319 libc_lib_dir = argv[i]; 320 } else if (strcmp(arg, "--libc-static-lib-dir") == 0) { 321 libc_static_lib_dir = argv[i]; 322 } else if (strcmp(arg, "--libc-include-dir") == 0) { 323 libc_include_dir = argv[i]; 324 } else if (strcmp(arg, "--zig-std-dir") == 0) { 325 zig_std_dir = argv[i]; 326 } else if (strcmp(arg, "--dynamic-linker") == 0) { 327 dynamic_linker = argv[i]; 328 } else if (strcmp(arg, "-isystem") == 0) { 329 clang_argv.append("-isystem"); 330 clang_argv.append(argv[i]); 331 } else if (strcmp(arg, "-dirafter") == 0) { 332 clang_argv.append("-dirafter"); 333 clang_argv.append(argv[i]); 334 } else if (strcmp(arg, "--library-path") == 0 || strcmp(arg, "-L") == 0) { 335 lib_dirs.append(argv[i]); 336 } else if (strcmp(arg, "--library") == 0) { 337 link_libs.append(argv[i]); 338 } else if (strcmp(arg, "--target-arch") == 0) { 339 target_arch = argv[i]; 340 } else if (strcmp(arg, "--target-os") == 0) { 341 target_os = argv[i]; 342 } else if (strcmp(arg, "--target-environ") == 0) { 343 target_environ = argv[i]; 344 } else if (strcmp(arg, "-mlinker-version") == 0) { 345 mlinker_version = argv[i]; 346 } else if (strcmp(arg, "-mmacosx-version-min") == 0) { 347 mmacosx_version_min = argv[i]; 348 } else if (strcmp(arg, "-mios-version-min") == 0) { 349 mios_version_min = argv[i]; 350 } else if (strcmp(arg, "-framework") == 0) { 351 frameworks.append(argv[i]); 352 } else if (strcmp(arg, "--linker-script") == 0) { 353 linker_script = argv[i]; 354 } else if (strcmp(arg, "-rpath") == 0) { 355 rpath_list.append(argv[i]); 356 } else if (strcmp(arg, "--test-filter") == 0) { 357 test_filter = argv[i]; 358 } else if (strcmp(arg, "--test-name-prefix") == 0) { 359 test_name_prefix = argv[i]; 360 } else if (strcmp(arg, "--ver-major") == 0) { 361 ver_major = atoi(argv[i]); 362 } else if (strcmp(arg, "--ver-minor") == 0) { 363 ver_minor = atoi(argv[i]); 364 } else if (strcmp(arg, "--ver-patch") == 0) { 365 ver_patch = atoi(argv[i]); 366 } else { 367 fprintf(stderr, "Invalid argument: %s\n", arg); 368 return usage(arg0); 369 } 370 } 371 } else if (cmd == CmdInvalid) { 372 if (strcmp(arg, "build_exe") == 0) { 373 cmd = CmdBuild; 374 out_type = OutTypeExe; 375 } else if (strcmp(arg, "build_obj") == 0) { 376 cmd = CmdBuild; 377 out_type = OutTypeObj; 378 } else if (strcmp(arg, "build_lib") == 0) { 379 cmd = CmdBuild; 380 out_type = OutTypeLib; 381 } else if (strcmp(arg, "link_lib") == 0) { 382 cmd = CmdLink; 383 out_type = OutTypeLib; 384 } else if (strcmp(arg, "link_exe") == 0) { 385 cmd = CmdLink; 386 out_type = OutTypeExe; 387 } else if (strcmp(arg, "version") == 0) { 388 cmd = CmdVersion; 389 } else if (strcmp(arg, "parseh") == 0) { 390 cmd = CmdParseH; 391 } else if (strcmp(arg, "test") == 0) { 392 cmd = CmdTest; 393 } else if (strcmp(arg, "targets") == 0) { 394 cmd = CmdTargets; 395 } else if (strcmp(arg, "asm") == 0) { 396 cmd = CmdAsm; 397 } else { 398 fprintf(stderr, "Unrecognized command: %s\n", arg); 399 return usage(arg0); 400 } 401 } else { 402 switch (cmd) { 403 case CmdBuild: 404 case CmdParseH: 405 case CmdTest: 406 case CmdAsm: 407 if (!in_file) { 408 in_file = arg; 409 } else { 410 return usage(arg0); 411 } 412 break; 413 case CmdLink: 414 objects.append(arg); 415 break; 416 case CmdVersion: 417 case CmdTargets: 418 return usage(arg0); 419 case CmdInvalid: 420 zig_unreachable(); 421 } 422 } 423 } 424 425 switch (cmd) { 426 case CmdBuild: 427 case CmdParseH: 428 case CmdTest: 429 case CmdAsm: 430 case CmdLink: 431 { 432 bool one_source_input = (cmd == CmdBuild || cmd == CmdParseH || cmd == CmdTest || cmd == CmdAsm); 433 if (one_source_input) { 434 if (!in_file) { 435 fprintf(stderr, "Expected source file argument.\n"); 436 return usage(arg0); 437 } 438 } else if (cmd == CmdLink) { 439 if (objects.length == 0) { 440 fprintf(stderr, "Expected one or more object arguments.\n"); 441 return usage(arg0); 442 } 443 } else { 444 zig_unreachable(); 445 } 446 447 assert((cmd != CmdBuild && cmd != CmdLink) || out_type != OutTypeUnknown); 448 449 init_all_targets(); 450 451 ZigTarget alloc_target; 452 ZigTarget *target; 453 if (!target_arch && !target_os && !target_environ) { 454 target = nullptr; 455 } else { 456 target = &alloc_target; 457 get_unknown_target(target); 458 if (target_arch) { 459 if (parse_target_arch(target_arch, &target->arch)) { 460 fprintf(stderr, "invalid --target-arch argument\n"); 461 return usage(arg0); 462 } 463 } 464 if (target_os) { 465 if (parse_target_os(target_os, &target->os)) { 466 fprintf(stderr, "invalid --target-os argument\n"); 467 return usage(arg0); 468 } 469 } 470 if (target_environ) { 471 if (parse_target_environ(target_environ, &target->env_type)) { 472 fprintf(stderr, "invalid --target-environ argument\n"); 473 return usage(arg0); 474 } 475 } 476 } 477 478 bool need_name = (cmd == CmdBuild || cmd == CmdAsm || cmd == CmdLink); 479 480 Buf in_file_buf = BUF_INIT; 481 482 Buf root_source_dir = BUF_INIT; 483 Buf root_source_code = BUF_INIT; 484 Buf root_source_name = BUF_INIT; 485 486 Buf *buf_out_name = (cmd == CmdTest) ? buf_create_from_str("test") : 487 (out_name == nullptr) ? nullptr : buf_create_from_str(out_name); 488 489 if (one_source_input) { 490 buf_init_from_str(&in_file_buf, in_file); 491 492 if (buf_eql_str(&in_file_buf, "-")) { 493 os_get_cwd(&root_source_dir); 494 if ((err = os_fetch_file(stdin, &root_source_code))) { 495 fprintf(stderr, "unable to read stdin: %s\n", err_str(err)); 496 return 1; 497 } 498 buf_init_from_str(&root_source_name, ""); 499 500 } else { 501 os_path_split(&in_file_buf, &root_source_dir, &root_source_name); 502 if ((err = os_fetch_file_path(buf_create_from_str(in_file), &root_source_code))) { 503 fprintf(stderr, "unable to open '%s': %s\n", in_file, err_str(err)); 504 return 1; 505 } 506 507 if (need_name && buf_out_name == nullptr) { 508 buf_out_name = buf_alloc(); 509 Buf ext_name = BUF_INIT; 510 os_path_extname(&root_source_name, buf_out_name, &ext_name); 511 } 512 } 513 } else if (cmd == CmdLink) { 514 os_get_cwd(&root_source_dir); 515 } else { 516 zig_unreachable(); 517 } 518 519 if (need_name && buf_out_name == nullptr) { 520 fprintf(stderr, "--name [name] not provided and unable to infer\n\n"); 521 return usage(arg0); 522 } 523 524 CodeGen *g = codegen_create(&root_source_dir, target); 525 codegen_set_lib_version(g, ver_major, ver_minor, ver_patch); 526 codegen_set_is_release(g, is_release_build); 527 codegen_set_is_test(g, cmd == CmdTest); 528 codegen_set_linker_script(g, linker_script); 529 if (each_lib_rpath) 530 codegen_set_each_lib_rpath(g, each_lib_rpath); 531 532 codegen_set_clang_argv(g, clang_argv.items, clang_argv.length); 533 codegen_set_strip(g, strip); 534 codegen_set_is_static(g, is_static); 535 if (cmd == CmdAsm) { 536 codegen_set_out_type(g, OutTypeObj); 537 } else if (out_type != OutTypeUnknown) { 538 codegen_set_out_type(g, out_type); 539 } else if (cmd == CmdTest) { 540 codegen_set_out_type(g, OutTypeExe); 541 } 542 codegen_set_out_name(g, buf_out_name); 543 if (libc_lib_dir) 544 codegen_set_libc_lib_dir(g, buf_create_from_str(libc_lib_dir)); 545 if (libc_static_lib_dir) 546 codegen_set_libc_static_lib_dir(g, buf_create_from_str(libc_static_lib_dir)); 547 if (libc_include_dir) 548 codegen_set_libc_include_dir(g, buf_create_from_str(libc_include_dir)); 549 if (zig_std_dir) 550 codegen_set_zig_std_dir(g, buf_create_from_str(zig_std_dir)); 551 if (dynamic_linker) 552 codegen_set_dynamic_linker(g, buf_create_from_str(dynamic_linker)); 553 codegen_set_verbose(g, verbose); 554 codegen_set_errmsg_color(g, color); 555 556 for (size_t i = 0; i < lib_dirs.length; i += 1) { 557 codegen_add_lib_dir(g, lib_dirs.at(i)); 558 } 559 for (size_t i = 0; i < link_libs.length; i += 1) { 560 codegen_add_link_lib(g, link_libs.at(i)); 561 } 562 for (size_t i = 0; i < frameworks.length; i += 1) { 563 codegen_add_framework(g, frameworks.at(i)); 564 } 565 for (size_t i = 0; i < rpath_list.length; i += 1) { 566 codegen_add_rpath(g, rpath_list.at(i)); 567 } 568 569 codegen_set_windows_subsystem(g, mwindows, mconsole); 570 codegen_set_windows_unicode(g, municode); 571 codegen_set_rdynamic(g, rdynamic); 572 if (mlinker_version) { 573 codegen_set_mlinker_version(g, buf_create_from_str(mlinker_version)); 574 } 575 if (mmacosx_version_min && mios_version_min) { 576 fprintf(stderr, "-mmacosx-version-min and -mios-version-min options not allowed together\n"); 577 return EXIT_FAILURE; 578 } 579 580 if (mmacosx_version_min) { 581 codegen_set_mmacosx_version_min(g, buf_create_from_str(mmacosx_version_min)); 582 } 583 584 if (mios_version_min) { 585 codegen_set_mios_version_min(g, buf_create_from_str(mios_version_min)); 586 } 587 588 if (test_filter) { 589 codegen_set_test_filter(g, buf_create_from_str(test_filter)); 590 } 591 592 if (test_name_prefix) { 593 codegen_set_test_name_prefix(g, buf_create_from_str(test_name_prefix)); 594 } 595 596 if (cmd == CmdBuild) { 597 codegen_add_root_code(g, &root_source_dir, &root_source_name, &root_source_code); 598 codegen_link(g, out_file); 599 return EXIT_SUCCESS; 600 } else if (cmd == CmdLink) { 601 for (size_t i = 0; i < objects.length; i += 1) { 602 codegen_add_object(g, buf_create_from_str(objects.at(i))); 603 } 604 codegen_link(g, out_file); 605 return EXIT_SUCCESS; 606 } else if (cmd == CmdAsm) { 607 codegen_add_root_assembly(g, &root_source_dir, &root_source_name, &root_source_code); 608 codegen_link(g, out_file); 609 return EXIT_SUCCESS; 610 } else if (cmd == CmdParseH) { 611 codegen_parseh(g, &root_source_dir, &root_source_name, &root_source_code); 612 ast_render_decls(stdout, 4, g->root_import); 613 return EXIT_SUCCESS; 614 } else if (cmd == CmdTest) { 615 codegen_add_root_code(g, &root_source_dir, &root_source_name, &root_source_code); 616 codegen_link(g, "./test"); 617 ZigList<const char *> args = {0}; 618 Termination term; 619 os_spawn_process("./test", args, &term); 620 if (term.how != TerminationIdClean || term.code != 0) { 621 fprintf(stderr, "\nTests failed. Use the following command to reproduce the failure:\n"); 622 fprintf(stderr, "./test\n"); 623 } 624 return (term.how == TerminationIdClean) ? term.code : -1; 625 } else { 626 zig_unreachable(); 627 } 628 } 629 case CmdVersion: 630 printf("%s\n", ZIG_VERSION_STRING); 631 return EXIT_SUCCESS; 632 case CmdTargets: 633 return print_target_list(stdout); 634 case CmdInvalid: 635 return usage(arg0); 636 } 637 }