| author | |
| committer | |
| log | 2e5115b0687ee9b7078dbf70da7d7070a7c80399 |
| tree | 23f3acc2db17931b0bbb2ef4837de7b06dcfcc25 |
| parent | 67f11190d10caac1d08b76d60ec28eb2f5173946 |
'zig run file.zig' builds a file and stores the artifacts in the global
cache. On successful compilation the binary is executed.
'zig run file.zig -- a b c' does the same, but passes the arguments a,
b and c as runtime arguments to the program. Everything after an '--' are
treated as runtime arguments.
On a posix system, a shebang can be used to run a zig file directly. An
example shebang would be '#!/usr/bin/zig run'. You may not be able pass
extra compile arguments currently as part of the shebang. Linux for example
treats all arguments after the first as a single argument which will result
in an 'invalid command'.
Currently there is no customisability for the cache path as a compile
argument. For a posix system you can use `TMPDIR=. zig run file.zig` to
override, in this case using the current directory for the run cache.
The input file is always recompiled, even if it has changed. This is
intended to be cached but further discussion/thought needs to go into
this.
Closes #466.5 files changed, 129 insertions(+), 20 deletions(-)
src/codegen.cpp+3-3| ... | ... | @@ -6286,7 +6286,7 @@ static ImportTableEntry *add_special_code(CodeGen *g, PackageTableEntry *package |
| 6286 | 6286 | zig_panic("unable to open '%s': %s", buf_ptr(&path_to_code_src), err_str(err)); |
| 6287 | 6287 | } |
| 6288 | 6288 | Buf *import_code = buf_alloc(); |
| 6289 | if ((err = os_fetch_file_path(abs_full_path, import_code))) { | |
| 6289 | if ((err = os_fetch_file_path(abs_full_path, import_code, false))) { | |
| 6290 | 6290 | zig_panic("unable to open '%s': %s", buf_ptr(&path_to_code_src), err_str(err)); |
| 6291 | 6291 | } |
| 6292 | 6292 | |
| ... | ... | @@ -6374,7 +6374,7 @@ static void gen_root_source(CodeGen *g) { |
| 6374 | 6374 | } |
| 6375 | 6375 | |
| 6376 | 6376 | Buf *source_code = buf_alloc(); |
| 6377 | if ((err = os_fetch_file_path(rel_full_path, source_code))) { | |
| 6377 | if ((err = os_fetch_file_path(rel_full_path, source_code, true))) { | |
| 6378 | 6378 | zig_panic("unable to open '%s': %s", buf_ptr(rel_full_path), err_str(err)); |
| 6379 | 6379 | } |
| 6380 | 6380 | |
| ... | ... | @@ -6439,7 +6439,7 @@ static void gen_global_asm(CodeGen *g) { |
| 6439 | 6439 | int err; |
| 6440 | 6440 | for (size_t i = 0; i < g->assembly_files.length; i += 1) { |
| 6441 | 6441 | Buf *asm_file = g->assembly_files.at(i); |
| 6442 | if ((err = os_fetch_file_path(asm_file, &contents))) { | |
| 6442 | if ((err = os_fetch_file_path(asm_file, &contents, false))) { | |
| 6443 | 6443 | zig_panic("Unable to read %s: %s", buf_ptr(asm_file), err_str(err)); |
| 6444 | 6444 | } |
| 6445 | 6445 | buf_append_buf(&g->global_asm, &contents); |
src/ir.cpp+2-2| ... | ... | @@ -14709,7 +14709,7 @@ static TypeTableEntry *ir_analyze_instruction_import(IrAnalyze *ira, IrInstructi |
| 14709 | 14709 | return ira->codegen->builtin_types.entry_namespace; |
| 14710 | 14710 | } |
| 14711 | 14711 | |
| 14712 | if ((err = os_fetch_file_path(abs_full_path, import_code))) { | |
| 14712 | if ((err = os_fetch_file_path(abs_full_path, import_code, true))) { | |
| 14713 | 14713 | if (err == ErrorFileNotFound) { |
| 14714 | 14714 | ir_add_error_node(ira, source_node, |
| 14715 | 14715 | buf_sprintf("unable to find '%s'", buf_ptr(import_target_path))); |
| ... | ... | @@ -15570,7 +15570,7 @@ static TypeTableEntry *ir_analyze_instruction_embed_file(IrAnalyze *ira, IrInstr |
| 15570 | 15570 | // load from file system into const expr |
| 15571 | 15571 | Buf *file_contents = buf_alloc(); |
| 15572 | 15572 | int err; |
| 15573 | if ((err = os_fetch_file_path(&file_path, file_contents))) { | |
| 15573 | if ((err = os_fetch_file_path(&file_path, file_contents, false))) { | |
| 15574 | 15574 | if (err == ErrorFileNotFound) { |
| 15575 | 15575 | ir_add_error(ira, instruction->name, buf_sprintf("unable to find '%s'", buf_ptr(&file_path))); |
| 15576 | 15576 | return ira->codegen->builtin_types.entry_invalid; |
src/main.cpp+50-8| ... | ... | @@ -23,6 +23,7 @@ static int usage(const char *arg0) { |
| 23 | 23 | " build-exe [source] create executable from source or object files\n" |
| 24 | 24 | " build-lib [source] create library from source or object files\n" |
| 25 | 25 | " build-obj [source] create object from source or assembly\n" |
| 26 | " run [source] create executable and run immediately\n" | |
| 26 | 27 | " translate-c [source] convert c code to zig code\n" |
| 27 | 28 | " targets list available compilation targets\n" |
| 28 | 29 | " test [source] create and run a test build\n" |
| ... | ... | @@ -220,6 +221,7 @@ static Buf *resolve_zig_lib_dir(const char *zig_install_prefix_arg) { |
| 220 | 221 | enum Cmd { |
| 221 | 222 | CmdInvalid, |
| 222 | 223 | CmdBuild, |
| 224 | CmdRun, | |
| 223 | 225 | CmdTest, |
| 224 | 226 | CmdVersion, |
| 225 | 227 | CmdZen, |
| ... | ... | @@ -329,6 +331,8 @@ int main(int argc, char **argv) { |
| 329 | 331 | CliPkg *cur_pkg = allocate<CliPkg>(1); |
| 330 | 332 | BuildMode build_mode = BuildModeDebug; |
| 331 | 333 | ZigList<const char *> test_exec_args = {0}; |
| 334 | int comptime_args_end = 0; | |
| 335 | int runtime_args_start = argc; | |
| 332 | 336 | |
| 333 | 337 | if (argc >= 2 && strcmp(argv[1], "build") == 0) { |
| 334 | 338 | const char *zig_exe_path = arg0; |
| ... | ... | @@ -481,11 +485,15 @@ int main(int argc, char **argv) { |
| 481 | 485 | return (term.how == TerminationIdClean) ? term.code : -1; |
| 482 | 486 | } |
| 483 | 487 | |
| 484 | for (int i = 1; i < argc; i += 1) { | |
| 488 | for (int i = 1; i < argc; i += 1, comptime_args_end += 1) { | |
| 485 | 489 | char *arg = argv[i]; |
| 486 | 490 | |
| 487 | 491 | if (arg[0] == '-') { |
| 488 | if (strcmp(arg, "--release-fast") == 0) { | |
| 492 | if (strcmp(arg, "--") == 0) { | |
| 493 | // ignore -- from both compile and runtime arg sets | |
| 494 | runtime_args_start = i + 1; | |
| 495 | break; | |
| 496 | } else if (strcmp(arg, "--release-fast") == 0) { | |
| 489 | 497 | build_mode = BuildModeFastRelease; |
| 490 | 498 | } else if (strcmp(arg, "--release-safe") == 0) { |
| 491 | 499 | build_mode = BuildModeSafeRelease; |
| ... | ... | @@ -652,6 +660,9 @@ int main(int argc, char **argv) { |
| 652 | 660 | } else if (strcmp(arg, "build-lib") == 0) { |
| 653 | 661 | cmd = CmdBuild; |
| 654 | 662 | out_type = OutTypeLib; |
| 663 | } else if (strcmp(arg, "run") == 0) { | |
| 664 | cmd = CmdRun; | |
| 665 | out_type = OutTypeExe; | |
| 655 | 666 | } else if (strcmp(arg, "version") == 0) { |
| 656 | 667 | cmd = CmdVersion; |
| 657 | 668 | } else if (strcmp(arg, "zen") == 0) { |
| ... | ... | @@ -670,6 +681,7 @@ int main(int argc, char **argv) { |
| 670 | 681 | } else { |
| 671 | 682 | switch (cmd) { |
| 672 | 683 | case CmdBuild: |
| 684 | case CmdRun: | |
| 673 | 685 | case CmdTranslateC: |
| 674 | 686 | case CmdTest: |
| 675 | 687 | if (!in_file) { |
| ... | ... | @@ -724,8 +736,8 @@ int main(int argc, char **argv) { |
| 724 | 736 | } |
| 725 | 737 | } |
| 726 | 738 | |
| 727 | ||
| 728 | 739 | switch (cmd) { |
| 740 | case CmdRun: | |
| 729 | 741 | case CmdBuild: |
| 730 | 742 | case CmdTranslateC: |
| 731 | 743 | case CmdTest: |
| ... | ... | @@ -733,7 +745,7 @@ int main(int argc, char **argv) { |
| 733 | 745 | if (cmd == CmdBuild && !in_file && objects.length == 0 && asm_files.length == 0) { |
| 734 | 746 | fprintf(stderr, "Expected source file argument or at least one --object or --assembly argument.\n"); |
| 735 | 747 | return usage(arg0); |
| 736 | } else if ((cmd == CmdTranslateC || cmd == CmdTest) && !in_file) { | |
| 748 | } else if ((cmd == CmdTranslateC || cmd == CmdTest || cmd == CmdRun) && !in_file) { | |
| 737 | 749 | fprintf(stderr, "Expected source file argument.\n"); |
| 738 | 750 | return usage(arg0); |
| 739 | 751 | } else if (cmd == CmdBuild && out_type == OutTypeObj && objects.length != 0) { |
| ... | ... | @@ -745,6 +757,10 @@ int main(int argc, char **argv) { |
| 745 | 757 | |
| 746 | 758 | bool need_name = (cmd == CmdBuild || cmd == CmdTranslateC); |
| 747 | 759 | |
| 760 | if (cmd == CmdRun) { | |
| 761 | out_name = "run"; | |
| 762 | } | |
| 763 | ||
| 748 | 764 | Buf *in_file_buf = nullptr; |
| 749 | 765 | |
| 750 | 766 | Buf *buf_out_name = (cmd == CmdTest) ? buf_create_from_str("test") : |
| ... | ... | @@ -769,9 +785,23 @@ int main(int argc, char **argv) { |
| 769 | 785 | Buf *zig_root_source_file = (cmd == CmdTranslateC) ? nullptr : in_file_buf; |
| 770 | 786 | |
| 771 | 787 | Buf *full_cache_dir = buf_alloc(); |
| 772 | os_path_resolve(buf_create_from_str("."), | |
| 773 | buf_create_from_str((cache_dir == nullptr) ? default_zig_cache_name : cache_dir), | |
| 774 | full_cache_dir); | |
| 788 | Buf *run_exec_path = buf_alloc(); | |
| 789 | if (cmd == CmdRun) { | |
| 790 | if (buf_out_name == nullptr) { | |
| 791 | buf_out_name = buf_create_from_str("run"); | |
| 792 | } | |
| 793 | ||
| 794 | Buf *global_cache_dir = buf_alloc(); | |
| 795 | os_get_global_cache_directory(global_cache_dir); | |
| 796 | os_path_join(global_cache_dir, buf_out_name, run_exec_path); | |
| 797 | os_path_resolve(buf_create_from_str("."), global_cache_dir, full_cache_dir); | |
| 798 | ||
| 799 | out_file = buf_ptr(run_exec_path); | |
| 800 | } else { | |
| 801 | os_path_resolve(buf_create_from_str("."), | |
| 802 | buf_create_from_str((cache_dir == nullptr) ? default_zig_cache_name : cache_dir), | |
| 803 | full_cache_dir); | |
| 804 | } | |
| 775 | 805 | |
| 776 | 806 | Buf *zig_lib_dir_buf = resolve_zig_lib_dir(zig_install_prefix); |
| 777 | 807 | |
| ... | ... | @@ -855,7 +885,7 @@ int main(int argc, char **argv) { |
| 855 | 885 | |
| 856 | 886 | add_package(g, cur_pkg, g->root_package); |
| 857 | 887 | |
| 858 | if (cmd == CmdBuild) { | |
| 888 | if (cmd == CmdBuild || cmd == CmdRun) { | |
| 859 | 889 | codegen_set_emit_file_type(g, emit_file_type); |
| 860 | 890 | |
| 861 | 891 | for (size_t i = 0; i < objects.length; i += 1) { |
| ... | ... | @@ -868,6 +898,18 @@ int main(int argc, char **argv) { |
| 868 | 898 | codegen_link(g, out_file); |
| 869 | 899 | if (timing_info) |
| 870 | 900 | codegen_print_timing_report(g, stdout); |
| 901 | ||
| 902 | if (cmd == CmdRun) { | |
| 903 | ZigList<const char*> args = {0}; | |
| 904 | for (int i = runtime_args_start; i < argc; ++i) { | |
| 905 | args.append(argv[i]); | |
| 906 | } | |
| 907 | ||
| 908 | Termination term; | |
| 909 | os_spawn_process(buf_ptr(run_exec_path), args, &term); | |
| 910 | return term.code; | |
| 911 | } | |
| 912 | ||
| 871 | 913 | return EXIT_SUCCESS; |
| 872 | 914 | } else if (cmd == CmdTranslateC) { |
| 873 | 915 | codegen_translate_c(g, in_file_buf); |
src/os.cpp+70-5| ... | ... | @@ -288,13 +288,39 @@ void os_path_resolve(Buf *ref_path, Buf *target_path, Buf *out_abs_path) { |
| 288 | 288 | return; |
| 289 | 289 | } |
| 290 | 290 | |
| 291 | int os_fetch_file(FILE *f, Buf *out_buf) { | |
| 291 | int os_fetch_file(FILE *f, Buf *out_buf, bool skip_shebang) { | |
| 292 | 292 | static const ssize_t buf_size = 0x2000; |
| 293 | 293 | buf_resize(out_buf, buf_size); |
| 294 | 294 | ssize_t actual_buf_len = 0; |
| 295 | ||
| 296 | bool first_read = true; | |
| 297 | ||
| 295 | 298 | for (;;) { |
| 296 | 299 | size_t amt_read = fread(buf_ptr(out_buf) + actual_buf_len, 1, buf_size, f); |
| 297 | 300 | actual_buf_len += amt_read; |
| 301 | ||
| 302 | if (skip_shebang && first_read && buf_starts_with_str(out_buf, "#!")) { | |
| 303 | size_t i = 0; | |
| 304 | while (true) { | |
| 305 | if (i > buf_len(out_buf)) { | |
| 306 | zig_panic("shebang line exceeded %zd characters", buf_size); | |
| 307 | } | |
| 308 | ||
| 309 | size_t current_pos = i; | |
| 310 | i += 1; | |
| 311 | ||
| 312 | if (out_buf->list.at(current_pos) == '\n') { | |
| 313 | break; | |
| 314 | } | |
| 315 | } | |
| 316 | ||
| 317 | ZigList<char> *list = &out_buf->list; | |
| 318 | memmove(list->items, list->items + i, list->length - i); | |
| 319 | list->length -= i; | |
| 320 | ||
| 321 | actual_buf_len -= i; | |
| 322 | } | |
| 323 | ||
| 298 | 324 | if (amt_read != buf_size) { |
| 299 | 325 | if (feof(f)) { |
| 300 | 326 | buf_resize(out_buf, actual_buf_len); |
| ... | ... | @@ -305,6 +331,7 @@ int os_fetch_file(FILE *f, Buf *out_buf) { |
| 305 | 331 | } |
| 306 | 332 | |
| 307 | 333 | buf_resize(out_buf, actual_buf_len + buf_size); |
| 334 | first_read = false; | |
| 308 | 335 | } |
| 309 | 336 | zig_unreachable(); |
| 310 | 337 | } |
| ... | ... | @@ -374,8 +401,8 @@ static int os_exec_process_posix(const char *exe, ZigList<const char *> &args, |
| 374 | 401 | |
| 375 | 402 | FILE *stdout_f = fdopen(stdout_pipe[0], "rb"); |
| 376 | 403 | FILE *stderr_f = fdopen(stderr_pipe[0], "rb"); |
| 377 | os_fetch_file(stdout_f, out_stdout); | |
| 378 | os_fetch_file(stderr_f, out_stderr); | |
| 404 | os_fetch_file(stdout_f, out_stdout, false); | |
| 405 | os_fetch_file(stderr_f, out_stderr, false); | |
| 379 | 406 | |
| 380 | 407 | fclose(stdout_f); |
| 381 | 408 | fclose(stderr_f); |
| ... | ... | @@ -588,7 +615,7 @@ int os_copy_file(Buf *src_path, Buf *dest_path) { |
| 588 | 615 | } |
| 589 | 616 | } |
| 590 | 617 | |
| 591 | int os_fetch_file_path(Buf *full_path, Buf *out_contents) { | |
| 618 | int os_fetch_file_path(Buf *full_path, Buf *out_contents, bool skip_shebang) { | |
| 592 | 619 | FILE *f = fopen(buf_ptr(full_path), "rb"); |
| 593 | 620 | if (!f) { |
| 594 | 621 | switch (errno) { |
| ... | ... | @@ -607,7 +634,7 @@ int os_fetch_file_path(Buf *full_path, Buf *out_contents) { |
| 607 | 634 | return ErrorFileSystem; |
| 608 | 635 | } |
| 609 | 636 | } |
| 610 | int result = os_fetch_file(f, out_contents); | |
| 637 | int result = os_fetch_file(f, out_contents, skip_shebang); | |
| 611 | 638 | fclose(f); |
| 612 | 639 | return result; |
| 613 | 640 | } |
| ... | ... | @@ -780,6 +807,44 @@ int os_buf_to_tmp_file(Buf *contents, Buf *suffix, Buf *out_tmp_path) { |
| 780 | 807 | #endif |
| 781 | 808 | } |
| 782 | 809 | |
| 810 | #if defined(ZIG_OS_POSIX) | |
| 811 | int os_get_global_cache_directory(Buf *out_tmp_path) { | |
| 812 | const char *tmp_dir = getenv("TMPDIR"); | |
| 813 | if (!tmp_dir) { | |
| 814 | tmp_dir = P_tmpdir; | |
| 815 | } | |
| 816 | ||
| 817 | Buf *tmp_dir_buf = buf_create_from_str(tmp_dir); | |
| 818 | Buf *cache_dirname_buf = buf_create_from_str("zig-cache"); | |
| 819 | ||
| 820 | buf_resize(out_tmp_path, 0); | |
| 821 | os_path_join(tmp_dir_buf, cache_dirname_buf, out_tmp_path); | |
| 822 | ||
| 823 | buf_deinit(tmp_dir_buf); | |
| 824 | buf_deinit(cache_dirname_buf); | |
| 825 | return 0; | |
| 826 | } | |
| 827 | #endif | |
| 828 | ||
| 829 | #if defined(ZIG_OS_WINDOWS) | |
| 830 | int os_get_global_cache_directory(Buf *out_tmp_path) { | |
| 831 | char tmp_dir[MAX_PATH + 1]; | |
| 832 | if (GetTempPath(MAX_PATH, tmp_dir) == 0) { | |
| 833 | zig_panic("GetTempPath failed"); | |
| 834 | } | |
| 835 | ||
| 836 | Buf *tmp_dir_buf = buf_create_from_str(tmp_dir); | |
| 837 | Buf *cache_dirname_buf = buf_create_from_str("zig-cache"); | |
| 838 | ||
| 839 | buf_resize(out_tmp_path, 0); | |
| 840 | os_path_join(tmp_dir_buf, cache_dirname_buf, out_tmp_path); | |
| 841 | ||
| 842 | buf_deinit(tmp_dir_buf); | |
| 843 | buf_deinit(cache_dirname_buf); | |
| 844 | return 0; | |
| 845 | } | |
| 846 | #endif | |
| 847 | ||
| 783 | 848 | int os_delete_file(Buf *path) { |
| 784 | 849 | if (remove(buf_ptr(path))) { |
| 785 | 850 | return ErrorFileSystem; |
src/os.hpp+4-2| ... | ... | @@ -51,14 +51,16 @@ int os_path_real(Buf *rel_path, Buf *out_abs_path); |
| 51 | 51 | void os_path_resolve(Buf *ref_path, Buf *target_path, Buf *out_abs_path); |
| 52 | 52 | bool os_path_is_absolute(Buf *path); |
| 53 | 53 | |
| 54 | int os_get_global_cache_directory(Buf *out_tmp_path); | |
| 55 | ||
| 54 | 56 | int os_make_path(Buf *path); |
| 55 | 57 | int os_make_dir(Buf *path); |
| 56 | 58 | |
| 57 | 59 | void os_write_file(Buf *full_path, Buf *contents); |
| 58 | 60 | int os_copy_file(Buf *src_path, Buf *dest_path); |
| 59 | 61 | |
| 60 | int os_fetch_file(FILE *file, Buf *out_contents); | |
| 61 | int os_fetch_file_path(Buf *full_path, Buf *out_contents); | |
| 62 | int os_fetch_file(FILE *file, Buf *out_contents, bool skip_shebang); | |
| 63 | int os_fetch_file_path(Buf *full_path, Buf *out_contents, bool skip_shebang); | |
| 62 | 64 | |
| 63 | 65 | int os_get_cwd(Buf *out_cwd); |
| 64 | 66 |