| author | |
| committer | |
| log | 7b0542d08b7e8e5ccbe81f495d641305b3b8a264 |
| tree | 67060c5620c5a36700abfa9c44d3ce31e35f9da4 |
| parent | 09bc4d6ba366c1a642b3c92c7ec554e95a369053 |
* add ability to add assembly files when building an exe, obj, or lib
* add implicit cast from `[N]T` to `?[]const T` (closes #343)
* remove link_exe and link_lib in favor of allowing build_exe and
build_lib support no root zig source file13 files changed, 322 insertions(+), 693 deletions(-)
src/all_types.hpp+2| ... | ... | @@ -1296,6 +1296,7 @@ struct CodeGen { |
| 1296 | 1296 | LLVMBuilderRef builder; |
| 1297 | 1297 | ZigLLVMDIBuilder *dbuilder; |
| 1298 | 1298 | ZigLLVMDICompileUnit *compile_unit; |
| 1299 | ZigLLVMDIFile *compile_unit_file; | |
| 1299 | 1300 | |
| 1300 | 1301 | ZigList<Buf *> link_libs; // non-libc link libs |
| 1301 | 1302 | // add -framework [name] args to linker |
| ... | ... | @@ -1468,6 +1469,7 @@ struct CodeGen { |
| 1468 | 1469 | |
| 1469 | 1470 | Buf global_asm; |
| 1470 | 1471 | ZigList<Buf *> link_objects; |
| 1472 | ZigList<Buf *> assembly_files; | |
| 1471 | 1473 | |
| 1472 | 1474 | ZigList<TypeTableEntry *> name_table_enums; |
| 1473 | 1475 |
src/analyze.cpp+5-4| ... | ... | @@ -2851,9 +2851,7 @@ void preview_use_decl(CodeGen *g, AstNode *node) { |
| 2851 | 2851 | node->data.use.value = result; |
| 2852 | 2852 | } |
| 2853 | 2853 | |
| 2854 | ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package, | |
| 2855 | Buf *abs_full_path, Buf *src_dirname, Buf *src_basename, Buf *source_code) | |
| 2856 | { | |
| 2854 | ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package, Buf *abs_full_path, Buf *source_code) { | |
| 2857 | 2855 | if (g->verbose) { |
| 2858 | 2856 | fprintf(stderr, "\nOriginal Source (%s):\n", buf_ptr(abs_full_path)); |
| 2859 | 2857 | fprintf(stderr, "----------------\n"); |
| ... | ... | @@ -2894,7 +2892,10 @@ ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package, |
| 2894 | 2892 | ast_print(stderr, import_entry->root, 0); |
| 2895 | 2893 | } |
| 2896 | 2894 | |
| 2897 | // TODO: assert that src_basename has no '/' in it | |
| 2895 | Buf *src_dirname = buf_alloc(); | |
| 2896 | Buf *src_basename = buf_alloc(); | |
| 2897 | os_path_split(abs_full_path, src_dirname, src_basename); | |
| 2898 | ||
| 2898 | 2899 | import_entry->di_file = ZigLLVMCreateFile(g->dbuilder, buf_ptr(src_basename), buf_ptr(src_dirname)); |
| 2899 | 2900 | g->import_table.put(abs_full_path, import_entry); |
| 2900 | 2901 | g->import_queue.append(import_entry); |
src/analyze.hpp+1-2| ... | ... | @@ -40,8 +40,7 @@ void find_libc_lib_path(CodeGen *g); |
| 40 | 40 | bool type_has_bits(TypeTableEntry *type_entry); |
| 41 | 41 | |
| 42 | 42 | |
| 43 | ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package, | |
| 44 | Buf *abs_full_path, Buf *src_dirname, Buf *src_basename, Buf *source_code); | |
| 43 | ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package, Buf *abs_full_path, Buf *source_code); | |
| 45 | 44 | |
| 46 | 45 | |
| 47 | 46 | // TODO move these over, these used to be static |
src/codegen.cpp+64-39| ... | ... | @@ -55,7 +55,7 @@ PackageTableEntry *new_package(const char *root_src_dir, const char *root_src_pa |
| 55 | 55 | return entry; |
| 56 | 56 | } |
| 57 | 57 | |
| 58 | CodeGen *codegen_create(Buf *root_source_dir, const ZigTarget *target) { | |
| 58 | CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target) { | |
| 59 | 59 | CodeGen *g = allocate<CodeGen>(1); |
| 60 | 60 | |
| 61 | 61 | codegen_add_time_event(g, "Initialize"); |
| ... | ... | @@ -81,9 +81,17 @@ CodeGen *codegen_create(Buf *root_source_dir, const ZigTarget *target) { |
| 81 | 81 | // reserve index 0 to indicate no error |
| 82 | 82 | g->error_decls.append(nullptr); |
| 83 | 83 | |
| 84 | g->root_package = new_package(buf_ptr(root_source_dir), ""); | |
| 85 | g->std_package = new_package(ZIG_STD_DIR, "index.zig"); | |
| 86 | g->root_package->package_table.put(buf_create_from_str("std"), g->std_package); | |
| 84 | if (root_src_path) { | |
| 85 | Buf *src_basename = buf_alloc(); | |
| 86 | Buf *src_dir = buf_alloc(); | |
| 87 | os_path_split(root_src_path, src_dir, src_basename); | |
| 88 | ||
| 89 | g->root_package = new_package(buf_ptr(src_dir), buf_ptr(src_basename)); | |
| 90 | g->std_package = new_package(ZIG_STD_DIR, "index.zig"); | |
| 91 | g->root_package->package_table.put(buf_create_from_str("std"), g->std_package); | |
| 92 | } else { | |
| 93 | g->root_package = new_package(".", ""); | |
| 94 | } | |
| 87 | 95 | g->zig_std_dir = buf_create_from_str(ZIG_STD_DIR); |
| 88 | 96 | |
| 89 | 97 | g->zig_std_special_dir = buf_alloc(); |
| ... | ... | @@ -757,7 +765,7 @@ static LLVMValueRef get_safety_crash_err_fn(CodeGen *g) { |
| 757 | 765 | |
| 758 | 766 | static void gen_debug_safety_crash_for_err(CodeGen *g, LLVMValueRef err_val) { |
| 759 | 767 | LLVMValueRef safety_crash_err_fn = get_safety_crash_err_fn(g); |
| 760 | LLVMBuildCall(g->builder, safety_crash_err_fn, &err_val, 1, ""); | |
| 768 | ZigLLVMBuildCall(g->builder, safety_crash_err_fn, &err_val, 1, LLVMFastCallConv, false, ""); | |
| 761 | 769 | LLVMBuildUnreachable(g->builder); |
| 762 | 770 | } |
| 763 | 771 | |
| ... | ... | @@ -3655,6 +3663,10 @@ static LLVMValueRef build_alloca(CodeGen *g, TypeTableEntry *type_entry, const c |
| 3655 | 3663 | } |
| 3656 | 3664 | |
| 3657 | 3665 | static void do_code_gen(CodeGen *g) { |
| 3666 | if (g->verbose) { | |
| 3667 | fprintf(stderr, "\nCode Generation:\n"); | |
| 3668 | fprintf(stderr, "------------------\n"); | |
| 3669 | } | |
| 3658 | 3670 | assert(!g->errors.length); |
| 3659 | 3671 | |
| 3660 | 3672 | codegen_add_time_event(g, "Code Generation"); |
| ... | ... | @@ -4602,8 +4614,9 @@ static void define_builtin_compile_vars(CodeGen *g) { |
| 4602 | 4614 | add_compile_var(g, "panic_implementation_provided", create_const_bool(g, false)); |
| 4603 | 4615 | } |
| 4604 | 4616 | |
| 4605 | static void init(CodeGen *g, Buf *source_path) { | |
| 4606 | g->module = LLVMModuleCreateWithName(buf_ptr(source_path)); | |
| 4617 | static void init(CodeGen *g) { | |
| 4618 | assert(g->root_out_name); | |
| 4619 | g->module = LLVMModuleCreateWithName(buf_ptr(g->root_out_name)); | |
| 4607 | 4620 | |
| 4608 | 4621 | get_target_triple(&g->triple_str, &g->zig_target); |
| 4609 | 4622 | |
| ... | ... | @@ -4674,23 +4687,25 @@ static void init(CodeGen *g, Buf *source_path) { |
| 4674 | 4687 | g->const_void_val.type = g->builtin_types.entry_void; |
| 4675 | 4688 | } |
| 4676 | 4689 | |
| 4677 | void codegen_parseh(CodeGen *g, Buf *src_dirname, Buf *src_basename, Buf *source_code) { | |
| 4690 | void codegen_parseh(CodeGen *g, Buf *full_path) { | |
| 4678 | 4691 | find_libc_include_path(g); |
| 4679 | Buf *full_path = buf_alloc(); | |
| 4680 | os_path_join(src_dirname, src_basename, full_path); | |
| 4692 | ||
| 4693 | Buf *src_basename = buf_alloc(); | |
| 4694 | Buf *src_dirname = buf_alloc(); | |
| 4695 | os_path_split(full_path, src_dirname, src_basename); | |
| 4681 | 4696 | |
| 4682 | 4697 | ImportTableEntry *import = allocate<ImportTableEntry>(1); |
| 4683 | import->source_code = source_code; | |
| 4698 | import->source_code = nullptr; | |
| 4684 | 4699 | import->path = full_path; |
| 4685 | 4700 | g->root_import = import; |
| 4686 | 4701 | import->decls_scope = create_decls_scope(nullptr, nullptr, nullptr, import); |
| 4687 | 4702 | |
| 4688 | init(g, full_path); | |
| 4703 | init(g); | |
| 4689 | 4704 | |
| 4690 | 4705 | import->di_file = ZigLLVMCreateFile(g->dbuilder, buf_ptr(src_basename), buf_ptr(src_dirname)); |
| 4691 | 4706 | |
| 4692 | 4707 | ZigList<ErrorMsg *> errors = {0}; |
| 4693 | int err = parse_h_buf(import, &errors, source_code, g, nullptr); | |
| 4708 | int err = parse_h_file(import, &errors, buf_ptr(full_path), g, nullptr); | |
| 4694 | 4709 | if (err) { |
| 4695 | 4710 | fprintf(stderr, "unable to parse .h file: %s\n", err_str(err)); |
| 4696 | 4711 | exit(1); |
| ... | ... | @@ -4719,7 +4734,7 @@ static ImportTableEntry *add_special_code(CodeGen *g, PackageTableEntry *package |
| 4719 | 4734 | zig_panic("unable to open '%s': %s", buf_ptr(&path_to_code_src), err_str(err)); |
| 4720 | 4735 | } |
| 4721 | 4736 | |
| 4722 | return add_source_file(g, package, abs_full_path, g->zig_std_special_dir, code_basename, import_code); | |
| 4737 | return add_source_file(g, package, abs_full_path, import_code); | |
| 4723 | 4738 | } |
| 4724 | 4739 | |
| 4725 | 4740 | static PackageTableEntry *create_bootstrap_pkg(CodeGen *g) { |
| ... | ... | @@ -4736,23 +4751,27 @@ static PackageTableEntry *create_zigrt_pkg(CodeGen *g) { |
| 4736 | 4751 | return package; |
| 4737 | 4752 | } |
| 4738 | 4753 | |
| 4739 | void codegen_add_root_code(CodeGen *g, Buf *src_dir, Buf *src_basename, Buf *source_code) { | |
| 4740 | codegen_add_time_event(g, "Semantic Analysis"); | |
| 4741 | ||
| 4742 | Buf source_path = BUF_INIT; | |
| 4743 | os_path_join(src_dir, src_basename, &source_path); | |
| 4754 | static void gen_root_source(CodeGen *g) { | |
| 4755 | if (buf_len(&g->root_package->root_src_path) == 0) | |
| 4756 | return; | |
| 4744 | 4757 | |
| 4745 | buf_init_from_buf(&g->root_package->root_src_path, src_basename); | |
| 4758 | codegen_add_time_event(g, "Semantic Analysis"); | |
| 4746 | 4759 | |
| 4747 | init(g, &source_path); | |
| 4760 | Buf *rel_full_path = buf_alloc(); | |
| 4761 | os_path_join(&g->root_package->root_src_dir, &g->root_package->root_src_path, rel_full_path); | |
| 4748 | 4762 | |
| 4749 | 4763 | Buf *abs_full_path = buf_alloc(); |
| 4750 | 4764 | int err; |
| 4751 | if ((err = os_path_real(&source_path, abs_full_path))) { | |
| 4752 | zig_panic("unable to open '%s': %s", buf_ptr(&source_path), err_str(err)); | |
| 4765 | if ((err = os_path_real(rel_full_path, abs_full_path))) { | |
| 4766 | zig_panic("unable to open '%s': %s", buf_ptr(rel_full_path), err_str(err)); | |
| 4767 | } | |
| 4768 | ||
| 4769 | Buf *source_code = buf_alloc(); | |
| 4770 | if ((err = os_fetch_file_path(rel_full_path, source_code))) { | |
| 4771 | zig_panic("unable to open '%s': %s", buf_ptr(rel_full_path), err_str(err)); | |
| 4753 | 4772 | } |
| 4754 | 4773 | |
| 4755 | g->root_import = add_source_file(g, g->root_package, abs_full_path, src_dir, src_basename, source_code); | |
| 4774 | g->root_import = add_source_file(g, g->root_package, abs_full_path, source_code); | |
| 4756 | 4775 | |
| 4757 | 4776 | assert(g->root_out_name); |
| 4758 | 4777 | assert(g->out_type != OutTypeUnknown); |
| ... | ... | @@ -4787,27 +4806,33 @@ void codegen_add_root_code(CodeGen *g, Buf *src_dir, Buf *src_basename, Buf *sou |
| 4787 | 4806 | exit(1); |
| 4788 | 4807 | } |
| 4789 | 4808 | |
| 4790 | if (g->verbose) { | |
| 4791 | fprintf(stderr, "\nCode Generation:\n"); | |
| 4792 | fprintf(stderr, "------------------\n"); | |
| 4793 | ||
| 4794 | } | |
| 4795 | ||
| 4796 | do_code_gen(g); | |
| 4797 | 4809 | } |
| 4798 | 4810 | |
| 4799 | void codegen_add_root_assembly(CodeGen *g, Buf *src_dir, Buf *src_basename, Buf *source_code) { | |
| 4800 | Buf source_path = BUF_INIT; | |
| 4801 | os_path_join(src_dir, src_basename, &source_path); | |
| 4811 | void codegen_add_assembly(CodeGen *g, Buf *path) { | |
| 4812 | g->assembly_files.append(path); | |
| 4813 | } | |
| 4802 | 4814 | |
| 4803 | init(g, &source_path); | |
| 4815 | static void gen_global_asm(CodeGen *g) { | |
| 4816 | Buf contents = BUF_INIT; | |
| 4817 | int err; | |
| 4818 | for (size_t i = 0; i < g->assembly_files.length; i += 1) { | |
| 4819 | Buf *asm_file = g->assembly_files.at(i); | |
| 4820 | if ((err = os_fetch_file_path(asm_file, &contents))) { | |
| 4821 | zig_panic("Unable to read %s: %s", buf_ptr(asm_file), err_str(err)); | |
| 4822 | } | |
| 4823 | if (g->zig_target.arch.arch == ZigLLVM_x86 || g->zig_target.arch.arch == ZigLLVM_x86_64) { | |
| 4824 | buf_append_str(&g->global_asm, ".intel_syntax noprefix\n"); | |
| 4825 | } | |
| 4826 | buf_append_buf(&g->global_asm, &contents); | |
| 4827 | } | |
| 4828 | } | |
| 4804 | 4829 | |
| 4805 | assert(g->root_out_name); | |
| 4830 | void codegen_build(CodeGen *g) { | |
| 4806 | 4831 | assert(g->out_type != OutTypeUnknown); |
| 4832 | init(g); | |
| 4807 | 4833 | |
| 4808 | buf_init_from_str(&g->global_asm, ".intel_syntax noprefix\n"); | |
| 4809 | buf_append_buf(&g->global_asm, source_code); | |
| 4810 | ||
| 4834 | gen_global_asm(g); | |
| 4835 | gen_root_source(g); | |
| 4811 | 4836 | do_code_gen(g); |
| 4812 | 4837 | } |
| 4813 | 4838 |
src/codegen.hpp+4-4| ... | ... | @@ -14,7 +14,7 @@ |
| 14 | 14 | |
| 15 | 15 | #include <stdio.h> |
| 16 | 16 | |
| 17 | CodeGen *codegen_create(Buf *root_source_dir, const ZigTarget *target); | |
| 17 | CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target); | |
| 18 | 18 | |
| 19 | 19 | void codegen_set_clang_argv(CodeGen *codegen, const char **args, size_t len); |
| 20 | 20 | void codegen_set_is_release(CodeGen *codegen, bool is_release); |
| ... | ... | @@ -49,13 +49,13 @@ void codegen_set_test_name_prefix(CodeGen *g, Buf *prefix); |
| 49 | 49 | void codegen_set_lib_version(CodeGen *g, size_t major, size_t minor, size_t patch); |
| 50 | 50 | void codegen_add_time_event(CodeGen *g, const char *name); |
| 51 | 51 | void codegen_print_timing_report(CodeGen *g, FILE *f); |
| 52 | void codegen_build(CodeGen *g); | |
| 52 | 53 | |
| 53 | 54 | PackageTableEntry *new_package(const char *root_src_dir, const char *root_src_path); |
| 54 | void codegen_add_root_code(CodeGen *g, Buf *source_dir, Buf *source_basename, Buf *source_code); | |
| 55 | void codegen_add_root_assembly(CodeGen *g, Buf *source_dir, Buf *source_basename, Buf *source_code); | |
| 55 | void codegen_add_assembly(CodeGen *g, Buf *path); | |
| 56 | 56 | void codegen_add_object(CodeGen *g, Buf *object_path); |
| 57 | 57 | |
| 58 | void codegen_parseh(CodeGen *g, Buf *src_dirname, Buf *src_basename, Buf *source_code); | |
| 58 | void codegen_parseh(CodeGen *g, Buf *path); | |
| 59 | 59 | void codegen_render_ast(CodeGen *g, FILE *f, int indent_size); |
| 60 | 60 | |
| 61 | 61 | void codegen_generate_h_file(CodeGen *g); |
src/ir.cpp+39-2| ... | ... | @@ -6043,6 +6043,21 @@ static ImplicitCastMatchResult ir_types_match_with_implicit_cast(IrAnalyze *ira, |
| 6043 | 6043 | } |
| 6044 | 6044 | } |
| 6045 | 6045 | |
| 6046 | // implicit [N]T to ?[]const N | |
| 6047 | if (expected_type->id == TypeTableEntryIdMaybe && | |
| 6048 | is_slice(expected_type->data.maybe.child_type) && | |
| 6049 | actual_type->id == TypeTableEntryIdArray) | |
| 6050 | { | |
| 6051 | TypeTableEntry *ptr_type = | |
| 6052 | expected_type->data.maybe.child_type->data.structure.fields[slice_ptr_index].type_entry; | |
| 6053 | assert(ptr_type->id == TypeTableEntryIdPointer); | |
| 6054 | if ((ptr_type->data.pointer.is_const || actual_type->data.array.len == 0) && | |
| 6055 | types_match_const_cast_only(ptr_type->data.pointer.child_type, actual_type->data.array.child_type)) | |
| 6056 | { | |
| 6057 | return ImplicitCastMatchResultYes; | |
| 6058 | } | |
| 6059 | } | |
| 6060 | ||
| 6046 | 6061 | // implicit number literal to typed number |
| 6047 | 6062 | // implicit number literal to &const integer |
| 6048 | 6063 | if (actual_type->id == TypeTableEntryIdNumLitFloat || |
| ... | ... | @@ -7093,6 +7108,29 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 7093 | 7108 | } |
| 7094 | 7109 | } |
| 7095 | 7110 | |
| 7111 | // explicit cast from [N]T to ?[]const N | |
| 7112 | if (wanted_type->id == TypeTableEntryIdMaybe && | |
| 7113 | is_slice(wanted_type->data.maybe.child_type) && | |
| 7114 | actual_type->id == TypeTableEntryIdArray) | |
| 7115 | { | |
| 7116 | TypeTableEntry *ptr_type = | |
| 7117 | wanted_type->data.maybe.child_type->data.structure.fields[slice_ptr_index].type_entry; | |
| 7118 | assert(ptr_type->id == TypeTableEntryIdPointer); | |
| 7119 | if ((ptr_type->data.pointer.is_const || actual_type->data.array.len == 0) && | |
| 7120 | types_match_const_cast_only(ptr_type->data.pointer.child_type, actual_type->data.array.child_type)) | |
| 7121 | { | |
| 7122 | IrInstruction *cast1 = ir_analyze_cast(ira, source_instr, wanted_type->data.maybe.child_type, value); | |
| 7123 | if (type_is_invalid(cast1->value.type)) | |
| 7124 | return ira->codegen->invalid_instruction; | |
| 7125 | ||
| 7126 | IrInstruction *cast2 = ir_analyze_cast(ira, source_instr, wanted_type, cast1); | |
| 7127 | if (type_is_invalid(cast2->value.type)) | |
| 7128 | return ira->codegen->invalid_instruction; | |
| 7129 | ||
| 7130 | return cast2; | |
| 7131 | } | |
| 7132 | } | |
| 7133 | ||
| 7096 | 7134 | // explicit cast from []T to []u8 or []u8 to []T |
| 7097 | 7135 | if (is_slice(wanted_type) && is_slice(actual_type) && |
| 7098 | 7136 | (is_u8(wanted_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.child_type) || |
| ... | ... | @@ -10880,8 +10918,7 @@ static TypeTableEntry *ir_analyze_instruction_import(IrAnalyze *ira, IrInstructi |
| 10880 | 10918 | return ira->codegen->builtin_types.entry_invalid; |
| 10881 | 10919 | } |
| 10882 | 10920 | } |
| 10883 | ImportTableEntry *target_import = add_source_file(ira->codegen, target_package, | |
| 10884 | abs_full_path, search_dir, import_target_path, import_code); | |
| 10921 | ImportTableEntry *target_import = add_source_file(ira->codegen, target_package, abs_full_path, import_code); | |
| 10885 | 10922 | |
| 10886 | 10923 | scan_decls(ira->codegen, target_import->decls_scope, target_import->root); |
| 10887 | 10924 |
src/link.cpp+4-10| ... | ... | @@ -33,9 +33,11 @@ static const char *get_libc_static_file(CodeGen *g, const char *file) { |
| 33 | 33 | |
| 34 | 34 | static Buf *build_o(CodeGen *parent_gen, const char *oname) { |
| 35 | 35 | Buf *source_basename = buf_sprintf("%s.zig", oname); |
| 36 | Buf *full_path = buf_alloc(); | |
| 37 | os_path_join(parent_gen->zig_std_special_dir, source_basename, full_path); | |
| 36 | 38 | |
| 37 | 39 | ZigTarget *child_target = parent_gen->is_native_target ? nullptr : &parent_gen->zig_target; |
| 38 | CodeGen *child_gen = codegen_create(parent_gen->zig_std_special_dir, child_target); | |
| 40 | CodeGen *child_gen = codegen_create(full_path, child_target); | |
| 39 | 41 | child_gen->link_libc = parent_gen->link_libc; |
| 40 | 42 | |
| 41 | 43 | child_gen->link_libs.resize(parent_gen->link_libs.length); |
| ... | ... | @@ -60,15 +62,7 @@ static Buf *build_o(CodeGen *parent_gen, const char *oname) { |
| 60 | 62 | codegen_set_mmacosx_version_min(child_gen, parent_gen->mmacosx_version_min); |
| 61 | 63 | codegen_set_mios_version_min(child_gen, parent_gen->mios_version_min); |
| 62 | 64 | |
| 63 | Buf *full_path = buf_alloc(); | |
| 64 | os_path_join(parent_gen->zig_std_special_dir, source_basename, full_path); | |
| 65 | ||
| 66 | Buf source_code = BUF_INIT; | |
| 67 | if (os_fetch_file_path(full_path, &source_code)) { | |
| 68 | zig_panic("unable to fetch file: %s\n", buf_ptr(full_path)); | |
| 69 | } | |
| 70 | ||
| 71 | codegen_add_root_code(child_gen, parent_gen->zig_std_special_dir, source_basename, &source_code); | |
| 65 | codegen_build(child_gen); | |
| 72 | 66 | const char *o_ext = target_o_file_ext(&child_gen->zig_target); |
| 73 | 67 | Buf *o_out = buf_sprintf("%s%s", oname, o_ext); |
| 74 | 68 | codegen_link(child_gen, buf_ptr(o_out)); |
src/main.cpp+64-121| ... | ... | @@ -19,29 +19,19 @@ |
| 19 | 19 | static int usage(const char *arg0) { |
| 20 | 20 | fprintf(stderr, "Usage: %s [command] [options]\n" |
| 21 | 21 | "Commands:\n" |
| 22 | " asm [source] create object from assembly\n" | |
| 23 | 22 | " 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" | |
| 23 | " build_exe [source] create executable from source or object files\n" | |
| 24 | " build_lib [source] create library from source or object files\n" | |
| 25 | " build_obj [source] create object from source or assembly\n" | |
| 29 | 26 | " parseh [source] convert a c header file to zig extern declarations\n" |
| 30 | 27 | " targets list available compilation targets\n" |
| 31 | 28 | " test [source] create and run a test build\n" |
| 32 | 29 | " version print version number and exit\n" |
| 33 | "Options:\n" | |
| 34 | " --ar-path [path] set the path to ar\n" | |
| 30 | "Compile Options:\n" | |
| 31 | " --assembly [source] add assembly file to build\n" | |
| 35 | 32 | " --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" | |
| 33 | " --enable-timing-info print timing diagnostics\n" | |
| 39 | 34 | " --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 | 35 | " --name [name] override output name\n" |
| 46 | 36 | " --output [file] override destination path\n" |
| 47 | 37 | " --release build with optimizations on and debug protection off\n" |
| ... | ... | @@ -52,26 +42,34 @@ static int usage(const char *arg0) { |
| 52 | 42 | " --target-os [name] specify target operating system\n" |
| 53 | 43 | " --verbose turn on compiler debug output\n" |
| 54 | 44 | " --zig-std-dir [path] directory where zig standard library resides\n" |
| 55 | " -L[dir] alias for --library-path\n" | |
| 56 | 45 | " -dirafter [dir] same as -isystem but do it last\n" |
| 57 | " -framework [name] (darwin only) link against framework\n" | |
| 58 | 46 | " -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" | |
| 47 | "Link Options:\n" | |
| 48 | " --ar-path [path] set the path to ar\n" | |
| 49 | " --dynamic-linker [path] set the path to ld.so\n" | |
| 50 | " --each-lib-rpath add rpath for each used dynamic library\n" | |
| 51 | " --libc-lib-dir [path] directory where libc crt1.o resides\n" | |
| 52 | " --libc-static-lib-dir [path] directory where libc crtbegin.o resides\n" | |
| 53 | " --library [lib] link against lib\n" | |
| 54 | " --library-path [dir] add a directory to the library search path\n" | |
| 55 | " --linker-script [path] use a custom linker script\n" | |
| 56 | " --object [obj] add object file to build\n" | |
| 57 | " -L[dir] alias for --library-path\n" | |
| 65 | 58 | " -rdynamic add all symbols to the dynamic symbol table\n" |
| 66 | 59 | " -rpath [path] add directory to the runtime library search path\n" |
| 67 | " --enable-timing-info print timing diagnostics\n" | |
| 60 | " -mconsole (windows) --subsystem console to the linker\n" | |
| 61 | " -mwindows (windows) --subsystem windows to the linker\n" | |
| 62 | " -municode (windows) link with unicode\n" | |
| 63 | " -framework [name] (darwin) link against framework\n" | |
| 64 | " -mios-version-min [ver] (darwin) set iOS deployment target\n" | |
| 65 | " -mlinker-version [ver] (darwin) override linker version\n" | |
| 66 | " -mmacosx-version-min [ver] (darwin) set Mac OS X deployment target\n" | |
| 67 | " --ver-major [ver] dynamic library semver major version\n" | |
| 68 | " --ver-minor [ver] dynamic library semver minor version\n" | |
| 69 | " --ver-patch [ver] dynamic library semver patch version\n" | |
| 68 | 70 | "Test Options:\n" |
| 69 | 71 | " --test-filter [text] skip tests that do not match filter\n" |
| 70 | 72 | " --test-name-prefix [text] add prefix to all tests\n" |
| 71 | "Dynamic Library Options:\n" | |
| 72 | " --ver-major [ver] semver major version\n" | |
| 73 | " --ver-minor [ver] semver minor version\n" | |
| 74 | " --ver-patch [ver] semver patch version\n" | |
| 75 | 73 | , arg0); |
| 76 | 74 | return EXIT_FAILURE; |
| 77 | 75 | } |
| ... | ... | @@ -117,8 +115,6 @@ enum Cmd { |
| 117 | 115 | CmdVersion, |
| 118 | 116 | CmdParseH, |
| 119 | 117 | CmdTargets, |
| 120 | CmdAsm, | |
| 121 | CmdLink, | |
| 122 | 118 | }; |
| 123 | 119 | |
| 124 | 120 | int main(int argc, char **argv) { |
| ... | ... | @@ -159,6 +155,7 @@ int main(int argc, char **argv) { |
| 159 | 155 | ZigList<const char *> rpath_list = {0}; |
| 160 | 156 | bool each_lib_rpath = false; |
| 161 | 157 | ZigList<const char *> objects = {0}; |
| 158 | ZigList<const char *> asm_files = {0}; | |
| 162 | 159 | const char *test_filter = nullptr; |
| 163 | 160 | const char *test_name_prefix = nullptr; |
| 164 | 161 | size_t ver_major = 0; |
| ... | ... | @@ -197,16 +194,7 @@ int main(int argc, char **argv) { |
| 197 | 194 | } |
| 198 | 195 | } |
| 199 | 196 | |
| 200 | ||
| 201 | Buf root_source_dir = BUF_INIT; | |
| 202 | Buf root_source_code = BUF_INIT; | |
| 203 | Buf root_source_name = BUF_INIT; | |
| 204 | os_path_split(build_runner_path, &root_source_dir, &root_source_name); | |
| 205 | if ((err = os_fetch_file_path(build_runner_path, &root_source_code))) { | |
| 206 | fprintf(stderr, "unable to open '%s': %s\n", buf_ptr(build_runner_path), err_str(err)); | |
| 207 | return 1; | |
| 208 | } | |
| 209 | CodeGen *g = codegen_create(&root_source_dir, nullptr); | |
| 197 | CodeGen *g = codegen_create(build_runner_path, nullptr); | |
| 210 | 198 | codegen_set_out_name(g, buf_create_from_str("build")); |
| 211 | 199 | codegen_set_out_type(g, OutTypeExe); |
| 212 | 200 | codegen_set_verbose(g, verbose); |
| ... | ... | @@ -256,7 +244,7 @@ int main(int argc, char **argv) { |
| 256 | 244 | PackageTableEntry *build_pkg = new_package(buf_ptr(&build_file_dirname), buf_ptr(&build_file_basename)); |
| 257 | 245 | build_pkg->package_table.put(buf_create_from_str("std"), g->std_package); |
| 258 | 246 | g->root_package->package_table.put(buf_create_from_str("@build"), build_pkg); |
| 259 | codegen_add_root_code(g, &root_source_dir, &root_source_name, &root_source_code); | |
| 247 | codegen_build(g); | |
| 260 | 248 | codegen_link(g, "build"); |
| 261 | 249 | |
| 262 | 250 | Termination term; |
| ... | ... | @@ -339,6 +327,10 @@ int main(int argc, char **argv) { |
| 339 | 327 | lib_dirs.append(argv[i]); |
| 340 | 328 | } else if (strcmp(arg, "--library") == 0) { |
| 341 | 329 | link_libs.append(argv[i]); |
| 330 | } else if (strcmp(arg, "--object") == 0) { | |
| 331 | objects.append(argv[i]); | |
| 332 | } else if (strcmp(arg, "--assembly") == 0) { | |
| 333 | asm_files.append(argv[i]); | |
| 342 | 334 | } else if (strcmp(arg, "--target-arch") == 0) { |
| 343 | 335 | target_arch = argv[i]; |
| 344 | 336 | } else if (strcmp(arg, "--target-os") == 0) { |
| ... | ... | @@ -382,12 +374,6 @@ int main(int argc, char **argv) { |
| 382 | 374 | } else if (strcmp(arg, "build_lib") == 0) { |
| 383 | 375 | cmd = CmdBuild; |
| 384 | 376 | out_type = OutTypeLib; |
| 385 | } else if (strcmp(arg, "link_lib") == 0) { | |
| 386 | cmd = CmdLink; | |
| 387 | out_type = OutTypeLib; | |
| 388 | } else if (strcmp(arg, "link_exe") == 0) { | |
| 389 | cmd = CmdLink; | |
| 390 | out_type = OutTypeExe; | |
| 391 | 377 | } else if (strcmp(arg, "version") == 0) { |
| 392 | 378 | cmd = CmdVersion; |
| 393 | 379 | } else if (strcmp(arg, "parseh") == 0) { |
| ... | ... | @@ -396,8 +382,6 @@ int main(int argc, char **argv) { |
| 396 | 382 | cmd = CmdTest; |
| 397 | 383 | } else if (strcmp(arg, "targets") == 0) { |
| 398 | 384 | cmd = CmdTargets; |
| 399 | } else if (strcmp(arg, "asm") == 0) { | |
| 400 | cmd = CmdAsm; | |
| 401 | 385 | } else { |
| 402 | 386 | fprintf(stderr, "Unrecognized command: %s\n", arg); |
| 403 | 387 | return usage(arg0); |
| ... | ... | @@ -407,16 +391,12 @@ int main(int argc, char **argv) { |
| 407 | 391 | case CmdBuild: |
| 408 | 392 | case CmdParseH: |
| 409 | 393 | case CmdTest: |
| 410 | case CmdAsm: | |
| 411 | 394 | if (!in_file) { |
| 412 | 395 | in_file = arg; |
| 413 | 396 | } else { |
| 414 | 397 | return usage(arg0); |
| 415 | 398 | } |
| 416 | 399 | break; |
| 417 | case CmdLink: | |
| 418 | objects.append(arg); | |
| 419 | break; | |
| 420 | 400 | case CmdVersion: |
| 421 | 401 | case CmdTargets: |
| 422 | 402 | return usage(arg0); |
| ... | ... | @@ -430,25 +410,19 @@ int main(int argc, char **argv) { |
| 430 | 410 | case CmdBuild: |
| 431 | 411 | case CmdParseH: |
| 432 | 412 | case CmdTest: |
| 433 | case CmdAsm: | |
| 434 | case CmdLink: | |
| 435 | 413 | { |
| 436 | bool one_source_input = (cmd == CmdBuild || cmd == CmdParseH || cmd == CmdTest || cmd == CmdAsm); | |
| 437 | if (one_source_input) { | |
| 438 | if (!in_file) { | |
| 439 | fprintf(stderr, "Expected source file argument.\n"); | |
| 440 | return usage(arg0); | |
| 441 | } | |
| 442 | } else if (cmd == CmdLink) { | |
| 443 | if (objects.length == 0) { | |
| 444 | fprintf(stderr, "Expected one or more object arguments.\n"); | |
| 445 | return usage(arg0); | |
| 446 | } | |
| 447 | } else { | |
| 448 | zig_unreachable(); | |
| 414 | if (cmd == CmdBuild && !in_file && objects.length == 0 && asm_files.length == 0) { | |
| 415 | fprintf(stderr, "Expected source file argument or at least one --object or --assembly argument.\n"); | |
| 416 | return usage(arg0); | |
| 417 | } else if ((cmd == CmdParseH || cmd == CmdTest) && !in_file) { | |
| 418 | fprintf(stderr, "Expected source file argument.\n"); | |
| 419 | return usage(arg0); | |
| 420 | } else if (cmd == CmdBuild && out_type == OutTypeObj && objects.length != 0) { | |
| 421 | fprintf(stderr, "When building an object file, --object arguments are invalid.\n"); | |
| 422 | return usage(arg0); | |
| 449 | 423 | } |
| 450 | 424 | |
| 451 | assert((cmd != CmdBuild && cmd != CmdLink) || out_type != OutTypeUnknown); | |
| 425 | assert(cmd != CmdBuild || out_type != OutTypeUnknown); | |
| 452 | 426 | |
| 453 | 427 | init_all_targets(); |
| 454 | 428 | |
| ... | ... | @@ -479,45 +453,22 @@ int main(int argc, char **argv) { |
| 479 | 453 | } |
| 480 | 454 | } |
| 481 | 455 | |
| 482 | bool need_name = (cmd == CmdBuild || cmd == CmdAsm || cmd == CmdLink || cmd == CmdParseH); | |
| 456 | bool need_name = (cmd == CmdBuild || cmd == CmdParseH); | |
| 483 | 457 | |
| 484 | Buf in_file_buf = BUF_INIT; | |
| 485 | ||
| 486 | Buf root_source_dir = BUF_INIT; | |
| 487 | Buf root_source_code = BUF_INIT; | |
| 488 | Buf root_source_name = BUF_INIT; | |
| 458 | Buf *in_file_buf = nullptr; | |
| 489 | 459 | |
| 490 | 460 | Buf *buf_out_name = (cmd == CmdTest) ? buf_create_from_str("test") : |
| 491 | 461 | (out_name == nullptr) ? nullptr : buf_create_from_str(out_name); |
| 492 | 462 | |
| 493 | if (one_source_input) { | |
| 494 | buf_init_from_str(&in_file_buf, in_file); | |
| 495 | ||
| 496 | if (buf_eql_str(&in_file_buf, "-")) { | |
| 497 | os_get_cwd(&root_source_dir); | |
| 498 | if ((err = os_fetch_file(stdin, &root_source_code))) { | |
| 499 | fprintf(stderr, "unable to read stdin: %s\n", err_str(err)); | |
| 500 | return 1; | |
| 501 | } | |
| 502 | buf_init_from_str(&root_source_name, ""); | |
| 463 | if (in_file) { | |
| 464 | in_file_buf = buf_create_from_str(in_file); | |
| 503 | 465 | |
| 504 | } else { | |
| 505 | os_path_split(&in_file_buf, &root_source_dir, &root_source_name); | |
| 506 | if ((err = os_fetch_file_path(buf_create_from_str(in_file), &root_source_code))) { | |
| 507 | fprintf(stderr, "unable to open '%s': %s\n", in_file, err_str(err)); | |
| 508 | return 1; | |
| 509 | } | |
| 510 | ||
| 511 | if (need_name && buf_out_name == nullptr) { | |
| 512 | buf_out_name = buf_alloc(); | |
| 513 | Buf ext_name = BUF_INIT; | |
| 514 | os_path_extname(&root_source_name, buf_out_name, &ext_name); | |
| 515 | } | |
| 466 | if (need_name && buf_out_name == nullptr) { | |
| 467 | Buf basename = BUF_INIT; | |
| 468 | os_path_split(in_file_buf, nullptr, &basename); | |
| 469 | buf_out_name = buf_alloc(); | |
| 470 | os_path_extname(&basename, buf_out_name, nullptr); | |
| 516 | 471 | } |
| 517 | } else if (cmd == CmdLink) { | |
| 518 | os_get_cwd(&root_source_dir); | |
| 519 | } else { | |
| 520 | zig_unreachable(); | |
| 521 | 472 | } |
| 522 | 473 | |
| 523 | 474 | if (need_name && buf_out_name == nullptr) { |
| ... | ... | @@ -525,7 +476,10 @@ int main(int argc, char **argv) { |
| 525 | 476 | return usage(arg0); |
| 526 | 477 | } |
| 527 | 478 | |
| 528 | CodeGen *g = codegen_create(&root_source_dir, target); | |
| 479 | Buf *zig_root_source_file = (cmd == CmdParseH) ? nullptr : in_file_buf; | |
| 480 | ||
| 481 | CodeGen *g = codegen_create(zig_root_source_file, target); | |
| 482 | codegen_set_out_name(g, buf_out_name); | |
| 529 | 483 | codegen_set_lib_version(g, ver_major, ver_minor, ver_patch); |
| 530 | 484 | codegen_set_is_release(g, is_release_build); |
| 531 | 485 | codegen_set_is_test(g, cmd == CmdTest); |
| ... | ... | @@ -536,14 +490,11 @@ int main(int argc, char **argv) { |
| 536 | 490 | codegen_set_clang_argv(g, clang_argv.items, clang_argv.length); |
| 537 | 491 | codegen_set_strip(g, strip); |
| 538 | 492 | codegen_set_is_static(g, is_static); |
| 539 | if (cmd == CmdAsm) { | |
| 540 | codegen_set_out_type(g, OutTypeObj); | |
| 541 | } else if (out_type != OutTypeUnknown) { | |
| 493 | if (out_type != OutTypeUnknown) { | |
| 542 | 494 | codegen_set_out_type(g, out_type); |
| 543 | 495 | } else if (cmd == CmdTest) { |
| 544 | 496 | codegen_set_out_type(g, OutTypeExe); |
| 545 | 497 | } |
| 546 | codegen_set_out_name(g, buf_out_name); | |
| 547 | 498 | if (libc_lib_dir) |
| 548 | 499 | codegen_set_libc_lib_dir(g, buf_create_from_str(libc_lib_dir)); |
| 549 | 500 | if (libc_static_lib_dir) |
| ... | ... | @@ -598,33 +549,25 @@ int main(int argc, char **argv) { |
| 598 | 549 | } |
| 599 | 550 | |
| 600 | 551 | if (cmd == CmdBuild) { |
| 601 | codegen_add_root_code(g, &root_source_dir, &root_source_name, &root_source_code); | |
| 602 | codegen_link(g, out_file); | |
| 603 | if (timing_info) | |
| 604 | codegen_print_timing_report(g, stderr); | |
| 605 | return EXIT_SUCCESS; | |
| 606 | } else if (cmd == CmdLink) { | |
| 607 | 552 | for (size_t i = 0; i < objects.length; i += 1) { |
| 608 | 553 | codegen_add_object(g, buf_create_from_str(objects.at(i))); |
| 609 | 554 | } |
| 610 | codegen_link(g, out_file); | |
| 611 | if (timing_info) | |
| 612 | codegen_print_timing_report(g, stderr); | |
| 613 | return EXIT_SUCCESS; | |
| 614 | } else if (cmd == CmdAsm) { | |
| 615 | codegen_add_root_assembly(g, &root_source_dir, &root_source_name, &root_source_code); | |
| 555 | for (size_t i = 0; i < asm_files.length; i += 1) { | |
| 556 | codegen_add_assembly(g, buf_create_from_str(asm_files.at(i))); | |
| 557 | } | |
| 558 | codegen_build(g); | |
| 616 | 559 | codegen_link(g, out_file); |
| 617 | 560 | if (timing_info) |
| 618 | 561 | codegen_print_timing_report(g, stderr); |
| 619 | 562 | return EXIT_SUCCESS; |
| 620 | 563 | } else if (cmd == CmdParseH) { |
| 621 | codegen_parseh(g, &root_source_dir, &root_source_name, &root_source_code); | |
| 564 | codegen_parseh(g, in_file_buf); | |
| 622 | 565 | ast_render_decls(g, stdout, 4, g->root_import); |
| 623 | 566 | if (timing_info) |
| 624 | 567 | codegen_print_timing_report(g, stderr); |
| 625 | 568 | return EXIT_SUCCESS; |
| 626 | 569 | } else if (cmd == CmdTest) { |
| 627 | codegen_add_root_code(g, &root_source_dir, &root_source_name, &root_source_code); | |
| 570 | codegen_build(g); | |
| 628 | 571 | codegen_link(g, "./test"); |
| 629 | 572 | ZigList<const char *> args = {0}; |
| 630 | 573 | Termination term; |
src/os.cpp+12-8| ... | ... | @@ -146,24 +146,28 @@ void os_path_split(Buf *full_path, Buf *out_dirname, Buf *out_basename) { |
| 146 | 146 | |
| 147 | 147 | void os_path_extname(Buf *full_path, Buf *out_basename, Buf *out_extname) { |
| 148 | 148 | if (buf_len(full_path) == 0) { |
| 149 | buf_init_from_str(out_basename, ""); | |
| 150 | buf_init_from_str(out_extname, ""); | |
| 149 | if (out_basename) buf_init_from_str(out_basename, ""); | |
| 150 | if (out_extname) buf_init_from_str(out_extname, ""); | |
| 151 | 151 | return; |
| 152 | 152 | } |
| 153 | 153 | size_t i = buf_len(full_path) - 1; |
| 154 | 154 | while (true) { |
| 155 | 155 | if (buf_ptr(full_path)[i] == '.') { |
| 156 | buf_resize(out_basename, 0); | |
| 157 | buf_append_mem(out_basename, buf_ptr(full_path), i); | |
| 156 | if (out_basename) { | |
| 157 | buf_resize(out_basename, 0); | |
| 158 | buf_append_mem(out_basename, buf_ptr(full_path), i); | |
| 159 | } | |
| 158 | 160 | |
| 159 | buf_resize(out_extname, 0); | |
| 160 | buf_append_mem(out_extname, buf_ptr(full_path) + i, buf_len(full_path) - i); | |
| 161 | if (out_extname) { | |
| 162 | buf_resize(out_extname, 0); | |
| 163 | buf_append_mem(out_extname, buf_ptr(full_path) + i, buf_len(full_path) - i); | |
| 164 | } | |
| 161 | 165 | return; |
| 162 | 166 | } |
| 163 | 167 | |
| 164 | 168 | if (i == 0) { |
| 165 | buf_init_from_buf(out_basename, full_path); | |
| 166 | buf_init_from_str(out_extname, ""); | |
| 169 | if (out_basename) buf_init_from_buf(out_basename, full_path); | |
| 170 | if (out_extname) buf_init_from_str(out_extname, ""); | |
| 167 | 171 | return; |
| 168 | 172 | } |
| 169 | 173 | i -= 1; |
std/build.zig+109-496| ... | ... | @@ -120,28 +120,22 @@ pub const Builder = struct { |
| 120 | 120 | self.lib_dir = %%os.path.join(self.allocator, self.prefix, "lib"); |
| 121 | 121 | } |
| 122 | 122 | |
| 123 | pub fn addExecutable(self: &Builder, name: []const u8, root_src: []const u8) -> &LibOrExeStep { | |
| 124 | const exe = %%self.allocator.create(LibOrExeStep); | |
| 125 | *exe = LibOrExeStep.initExecutable(self, name, root_src); | |
| 126 | return exe; | |
| 123 | pub fn addExecutable(self: &Builder, name: []const u8, root_src: ?[]const u8) -> &LibExeObjStep { | |
| 124 | return LibExeObjStep.createExecutable(self, name, root_src); | |
| 127 | 125 | } |
| 128 | 126 | |
| 129 | pub fn addObject(self: &Builder, name: []const u8, root_src: []const u8) -> &ObjectStep { | |
| 130 | const obj_step = %%self.allocator.create(ObjectStep); | |
| 131 | *obj_step = ObjectStep.init(self, name, root_src); | |
| 132 | return obj_step; | |
| 127 | pub fn addObject(self: &Builder, name: []const u8, root_src: []const u8) -> &LibExeObjStep { | |
| 128 | return LibExeObjStep.createObject(self, name, root_src); | |
| 133 | 129 | } |
| 134 | 130 | |
| 135 | pub fn addSharedLibrary(self: &Builder, name: []const u8, root_src: []const u8, ver: &const Version) -> &LibOrExeStep { | |
| 136 | const lib_step = %%self.allocator.create(LibOrExeStep); | |
| 137 | *lib_step = LibOrExeStep.initSharedLibrary(self, name, root_src, ver); | |
| 138 | return lib_step; | |
| 131 | pub fn addSharedLibrary(self: &Builder, name: []const u8, root_src: ?[]const u8, | |
| 132 | ver: &const Version) -> &LibExeObjStep | |
| 133 | { | |
| 134 | return LibExeObjStep.createSharedLibrary(self, name, root_src, ver); | |
| 139 | 135 | } |
| 140 | 136 | |
| 141 | pub fn addStaticLibrary(self: &Builder, name: []const u8, root_src: []const u8) -> &LibOrExeStep { | |
| 142 | const lib_step = %%self.allocator.create(LibOrExeStep); | |
| 143 | *lib_step = LibOrExeStep.initStaticLibrary(self, name, root_src); | |
| 144 | return lib_step; | |
| 137 | pub fn addStaticLibrary(self: &Builder, name: []const u8, root_src: ?[]const u8) -> &LibExeObjStep { | |
| 138 | return LibExeObjStep.createStaticLibrary(self, name, root_src); | |
| 145 | 139 | } |
| 146 | 140 | |
| 147 | 141 | pub fn addTest(self: &Builder, root_src: []const u8) -> &TestStep { |
| ... | ... | @@ -150,28 +144,10 @@ pub const Builder = struct { |
| 150 | 144 | return test_step; |
| 151 | 145 | } |
| 152 | 146 | |
| 153 | pub fn addAssemble(self: &Builder, name: []const u8, src: []const u8) -> &AsmStep { | |
| 154 | const asm_step = %%self.allocator.create(AsmStep); | |
| 155 | *asm_step = AsmStep.init(self, name, src); | |
| 156 | return asm_step; | |
| 157 | } | |
| 158 | ||
| 159 | pub fn addLinkExecutable(self: &Builder, name: []const u8) -> &LinkStep { | |
| 160 | const exe = %%self.allocator.create(LinkStep); | |
| 161 | *exe = LinkStep.initExecutable(self, name); | |
| 162 | return exe; | |
| 163 | } | |
| 164 | ||
| 165 | pub fn addLinkStaticLibrary(self: &Builder, name: []const u8) -> &LinkStep { | |
| 166 | const exe = %%self.allocator.create(LinkStep); | |
| 167 | *exe = LinkStep.initStaticLibrary(self, name); | |
| 168 | return exe; | |
| 169 | } | |
| 170 | ||
| 171 | pub fn addLinkSharedLibrary(self: &Builder, name: []const u8, ver: &const Version) -> &LinkStep { | |
| 172 | const exe = %%self.allocator.create(LinkStep); | |
| 173 | *exe = LinkStep.initSharedLibrary(self, name, ver); | |
| 174 | return exe; | |
| 147 | pub fn addAssemble(self: &Builder, name: []const u8, src: []const u8) -> &LibExeObjStep { | |
| 148 | const obj_step = LibExeObjStep.createObject(self, name, null); | |
| 149 | obj_step.addAssemblyFile(src); | |
| 150 | return obj_step; | |
| 175 | 151 | } |
| 176 | 152 | |
| 177 | 153 | pub fn addCStaticLibrary(self: &Builder, name: []const u8) -> &CLibrary { |
| ... | ... | @@ -635,10 +611,10 @@ const LinkerScript = enum { |
| 635 | 611 | Path: []const u8, |
| 636 | 612 | }; |
| 637 | 613 | |
| 638 | pub const LibOrExeStep = struct { | |
| 614 | pub const LibExeObjStep = struct { | |
| 639 | 615 | step: Step, |
| 640 | 616 | builder: &Builder, |
| 641 | root_src: []const u8, | |
| 617 | root_src: ?[]const u8, | |
| 642 | 618 | name: []const u8, |
| 643 | 619 | target: Target, |
| 644 | 620 | linker_script: LinkerScript, |
| ... | ... | @@ -652,30 +628,45 @@ pub const LibOrExeStep = struct { |
| 652 | 628 | out_filename: []const u8, |
| 653 | 629 | out_filename_major_only: []const u8, |
| 654 | 630 | out_filename_name_only: []const u8, |
| 631 | object_files: List([]const u8), | |
| 632 | assembly_files: List([]const u8), | |
| 655 | 633 | |
| 656 | 634 | const Kind = enum { |
| 657 | 635 | Exe, |
| 658 | 636 | Lib, |
| 637 | Obj, | |
| 659 | 638 | }; |
| 660 | 639 | |
| 661 | pub fn initExecutable(builder: &Builder, name: []const u8, root_src: []const u8) -> LibOrExeStep { | |
| 662 | return initExtraArgs(builder, name, root_src, Kind.Exe, false, builder.version(0, 0, 0)); | |
| 640 | pub fn createSharedLibrary(builder: &Builder, name: []const u8, root_src: ?[]const u8, | |
| 641 | ver: &const Version) -> &LibExeObjStep | |
| 642 | { | |
| 643 | const self = %%builder.allocator.create(LibExeObjStep); | |
| 644 | *self = initExtraArgs(builder, name, root_src, Kind.Lib, false, ver); | |
| 645 | return self; | |
| 663 | 646 | } |
| 664 | 647 | |
| 665 | pub fn initSharedLibrary(builder: &Builder, name: []const u8, root_src: []const u8, | |
| 666 | ver: &const Version) -> LibOrExeStep | |
| 667 | { | |
| 668 | return initExtraArgs(builder, name, root_src, Kind.Lib, false, ver); | |
| 648 | pub fn createStaticLibrary(builder: &Builder, name: []const u8, root_src: ?[]const u8) -> &LibExeObjStep { | |
| 649 | const self = %%builder.allocator.create(LibExeObjStep); | |
| 650 | *self = initExtraArgs(builder, name, root_src, Kind.Lib, true, builder.version(0, 0, 0)); | |
| 651 | return self; | |
| 669 | 652 | } |
| 670 | 653 | |
| 671 | pub fn initStaticLibrary(builder: &Builder, name: []const u8, root_src: []const u8) -> LibOrExeStep { | |
| 672 | return initExtraArgs(builder, name, root_src, Kind.Lib, true, builder.version(0, 0, 0)); | |
| 654 | pub fn createObject(builder: &Builder, name: []const u8, root_src: []const u8) -> &LibExeObjStep { | |
| 655 | const self = %%builder.allocator.create(LibExeObjStep); | |
| 656 | *self = initExtraArgs(builder, name, root_src, Kind.Obj, false, builder.version(0, 0, 0)); | |
| 657 | return self; | |
| 673 | 658 | } |
| 674 | 659 | |
| 675 | fn initExtraArgs(builder: &Builder, name: []const u8, root_src: []const u8, kind: Kind, | |
| 676 | static: bool, ver: &const Version) -> LibOrExeStep | |
| 660 | pub fn createExecutable(builder: &Builder, name: []const u8, root_src: ?[]const u8) -> &LibExeObjStep { | |
| 661 | const self = %%builder.allocator.create(LibExeObjStep); | |
| 662 | *self = initExtraArgs(builder, name, root_src, Kind.Exe, false, builder.version(0, 0, 0)); | |
| 663 | return self; | |
| 664 | } | |
| 665 | ||
| 666 | fn initExtraArgs(builder: &Builder, name: []const u8, root_src: ?[]const u8, kind: Kind, | |
| 667 | static: bool, ver: &const Version) -> LibExeObjStep | |
| 677 | 668 | { |
| 678 | var self = LibOrExeStep { | |
| 669 | var self = LibExeObjStep { | |
| 679 | 670 | .builder = builder, |
| 680 | 671 | .verbose = false, |
| 681 | 672 | .release = false, |
| ... | ... | @@ -692,13 +683,18 @@ pub const LibOrExeStep = struct { |
| 692 | 683 | .out_filename = undefined, |
| 693 | 684 | .out_filename_major_only = undefined, |
| 694 | 685 | .out_filename_name_only = undefined, |
| 686 | .object_files = List([]const u8).init(builder.allocator), | |
| 687 | .assembly_files = List([]const u8).init(builder.allocator), | |
| 695 | 688 | }; |
| 696 | 689 | self.computeOutFileNames(); |
| 697 | 690 | return self; |
| 698 | 691 | } |
| 699 | 692 | |
| 700 | fn computeOutFileNames(self: &LibOrExeStep) { | |
| 693 | fn computeOutFileNames(self: &LibExeObjStep) { | |
| 701 | 694 | switch (self.kind) { |
| 695 | Kind.Obj => { | |
| 696 | self.out_filename = self.builder.fmt("{}{}", self.name, self.target.oFileExt()); | |
| 697 | }, | |
| 702 | 698 | Kind.Exe => { |
| 703 | 699 | self.out_filename = self.builder.fmt("{}{}", self.name, self.target.exeFileExt()); |
| 704 | 700 | }, |
| ... | ... | @@ -715,7 +711,7 @@ pub const LibOrExeStep = struct { |
| 715 | 711 | } |
| 716 | 712 | } |
| 717 | 713 | |
| 718 | pub fn setTarget(self: &LibOrExeStep, target_arch: Arch, target_os: Os, target_environ: Environ) { | |
| 714 | pub fn setTarget(self: &LibExeObjStep, target_arch: Arch, target_os: Os, target_environ: Environ) { | |
| 719 | 715 | self.target = Target.Cross { |
| 720 | 716 | CrossTarget { |
| 721 | 717 | .arch = target_arch, |
| ... | ... | @@ -723,414 +719,49 @@ pub const LibOrExeStep = struct { |
| 723 | 719 | .environ = target_environ, |
| 724 | 720 | } |
| 725 | 721 | }; |
| 722 | self.computeOutFileNames(); | |
| 726 | 723 | } |
| 727 | 724 | |
| 728 | /// LibOrExeStep keeps a reference to script for its lifetime or until this function | |
| 725 | /// LibExeObjStep keeps a reference to script for its lifetime or until this function | |
| 729 | 726 | /// is called again. |
| 730 | pub fn setLinkerScriptContents(self: &LibOrExeStep, script: []const u8) { | |
| 727 | pub fn setLinkerScriptContents(self: &LibExeObjStep, script: []const u8) { | |
| 731 | 728 | self.linker_script = LinkerScript.Embed { script }; |
| 732 | 729 | } |
| 733 | 730 | |
| 734 | pub fn setLinkerScriptPath(self: &LibOrExeStep, path: []const u8) { | |
| 731 | pub fn setLinkerScriptPath(self: &LibExeObjStep, path: []const u8) { | |
| 735 | 732 | self.linker_script = LinkerScript.Path { path }; |
| 736 | 733 | } |
| 737 | 734 | |
| 738 | pub fn linkSystemLibrary(self: &LibOrExeStep, name: []const u8) { | |
| 735 | pub fn linkSystemLibrary(self: &LibExeObjStep, name: []const u8) { | |
| 739 | 736 | %%self.link_libs.put(name); |
| 740 | 737 | } |
| 741 | 738 | |
| 742 | pub fn setVerbose(self: &LibOrExeStep, value: bool) { | |
| 743 | self.verbose = value; | |
| 744 | } | |
| 745 | ||
| 746 | pub fn setRelease(self: &LibOrExeStep, value: bool) { | |
| 747 | self.release = value; | |
| 748 | } | |
| 749 | ||
| 750 | pub fn setOutputPath(self: &LibOrExeStep, value: []const u8) { | |
| 751 | self.output_path = value; | |
| 752 | } | |
| 753 | ||
| 754 | fn make(step: &Step) -> %void { | |
| 755 | const self = @fieldParentPtr(LibOrExeStep, "step", step); | |
| 756 | const builder = self.builder; | |
| 757 | ||
| 758 | var zig_args = List([]const u8).init(builder.allocator); | |
| 759 | defer zig_args.deinit(); | |
| 760 | ||
| 761 | const cmd = switch (self.kind) { | |
| 762 | Kind.Lib => "build_lib", | |
| 763 | Kind.Exe => "build_exe", | |
| 764 | }; | |
| 765 | %%zig_args.append(cmd); | |
| 766 | %%zig_args.append(builder.pathFromRoot(self.root_src)); | |
| 767 | ||
| 768 | if (self.verbose) { | |
| 769 | %%zig_args.append("--verbose"); | |
| 770 | } | |
| 771 | ||
| 772 | if (self.release) { | |
| 773 | %%zig_args.append("--release"); | |
| 774 | } | |
| 775 | ||
| 776 | test (self.output_path) |output_path| { | |
| 777 | %%zig_args.append("--output"); | |
| 778 | %%zig_args.append(builder.pathFromRoot(output_path)); | |
| 779 | } | |
| 780 | ||
| 781 | %%zig_args.append("--name"); | |
| 782 | %%zig_args.append(self.name); | |
| 783 | ||
| 784 | if (self.kind == Kind.Lib and !self.static) { | |
| 785 | %%zig_args.append("--ver-major"); | |
| 786 | %%zig_args.append(builder.fmt("{}", self.version.major)); | |
| 787 | ||
| 788 | %%zig_args.append("--ver-minor"); | |
| 789 | %%zig_args.append(builder.fmt("{}", self.version.minor)); | |
| 790 | ||
| 791 | %%zig_args.append("--ver-patch"); | |
| 792 | %%zig_args.append(builder.fmt("{}", self.version.patch)); | |
| 793 | } | |
| 794 | ||
| 795 | switch (self.target) { | |
| 796 | Target.Native => {}, | |
| 797 | Target.Cross => |cross_target| { | |
| 798 | %%zig_args.append("--target-arch"); | |
| 799 | %%zig_args.append(@enumTagName(cross_target.arch)); | |
| 800 | ||
| 801 | %%zig_args.append("--target-os"); | |
| 802 | %%zig_args.append(@enumTagName(cross_target.os)); | |
| 803 | ||
| 804 | %%zig_args.append("--target-environ"); | |
| 805 | %%zig_args.append(@enumTagName(cross_target.environ)); | |
| 806 | }, | |
| 807 | } | |
| 808 | ||
| 809 | switch (self.linker_script) { | |
| 810 | LinkerScript.None => {}, | |
| 811 | LinkerScript.Embed => |script| { | |
| 812 | const tmp_file_name = "linker.ld.tmp"; // TODO issue #298 | |
| 813 | io.writeFile(tmp_file_name, script, builder.allocator) | |
| 814 | %% |err| debug.panic("unable to write linker script: {}\n", @errorName(err)); | |
| 815 | %%zig_args.append("--linker-script"); | |
| 816 | %%zig_args.append(tmp_file_name); | |
| 817 | }, | |
| 818 | LinkerScript.Path => |path| { | |
| 819 | %%zig_args.append("--linker-script"); | |
| 820 | %%zig_args.append(path); | |
| 821 | }, | |
| 822 | } | |
| 823 | ||
| 824 | { | |
| 825 | var it = self.link_libs.iterator(); | |
| 826 | while (true) { | |
| 827 | const entry = it.next() ?? break; | |
| 828 | %%zig_args.append("--library"); | |
| 829 | %%zig_args.append(entry.key); | |
| 830 | } | |
| 831 | } | |
| 832 | ||
| 833 | for (builder.include_paths.toSliceConst()) |include_path| { | |
| 834 | %%zig_args.append("-isystem"); | |
| 835 | %%zig_args.append(include_path); | |
| 836 | } | |
| 837 | ||
| 838 | for (builder.rpaths.toSliceConst()) |rpath| { | |
| 839 | %%zig_args.append("-rpath"); | |
| 840 | %%zig_args.append(rpath); | |
| 841 | } | |
| 842 | ||
| 843 | for (builder.lib_paths.toSliceConst()) |lib_path| { | |
| 844 | %%zig_args.append("--library-path"); | |
| 845 | %%zig_args.append(lib_path); | |
| 846 | } | |
| 847 | ||
| 848 | %%builder.spawnChild(builder.zig_exe, zig_args.toSliceConst()); | |
| 849 | ||
| 850 | if (self.kind == Kind.Lib and !self.static) { | |
| 851 | // sym link for libfoo.so.1 to libfoo.so.1.2.3 | |
| 852 | %%os.atomicSymLink(builder.allocator, self.out_filename, self.out_filename_major_only); | |
| 853 | // sym link for libfoo.so to libfoo.so.1 | |
| 854 | %%os.atomicSymLink(builder.allocator, self.out_filename_major_only, self.out_filename_name_only); | |
| 855 | } | |
| 856 | } | |
| 857 | }; | |
| 858 | ||
| 859 | pub const ObjectStep = struct { | |
| 860 | step: Step, | |
| 861 | builder: &Builder, | |
| 862 | root_src: []const u8, | |
| 863 | name: []const u8, | |
| 864 | target: Target, | |
| 865 | verbose: bool, | |
| 866 | release: bool, | |
| 867 | output_path: ?[]const u8, | |
| 868 | ||
| 869 | pub fn init(builder: &Builder, name: []const u8, root_src: []const u8) -> ObjectStep { | |
| 870 | ObjectStep { | |
| 871 | .builder = builder, | |
| 872 | .verbose = false, | |
| 873 | .release = false, | |
| 874 | .root_src = root_src, | |
| 875 | .name = name, | |
| 876 | .target = Target.Native, | |
| 877 | .step = Step.init(name, builder.allocator, make), | |
| 878 | .output_path = null, | |
| 879 | } | |
| 880 | } | |
| 881 | ||
| 882 | pub fn setTarget(self: &ObjectStep, target_arch: Arch, target_os: Os, target_environ: Environ) { | |
| 883 | self.target = Target.Cross { | |
| 884 | CrossTarget { | |
| 885 | .arch = target_arch, | |
| 886 | .os = target_os, | |
| 887 | .environ = target_environ, | |
| 888 | } | |
| 889 | }; | |
| 890 | } | |
| 891 | ||
| 892 | pub fn setVerbose(self: &ObjectStep, value: bool) { | |
| 893 | self.verbose = value; | |
| 894 | } | |
| 895 | ||
| 896 | pub fn setRelease(self: &ObjectStep, value: bool) { | |
| 897 | self.release = value; | |
| 898 | } | |
| 899 | ||
| 900 | pub fn setOutputPath(self: &ObjectStep, value: []const u8) { | |
| 901 | self.output_path = value; | |
| 902 | } | |
| 903 | ||
| 904 | fn make(step: &Step) -> %void { | |
| 905 | const self = @fieldParentPtr(ObjectStep, "step", step); | |
| 906 | const builder = self.builder; | |
| 907 | ||
| 908 | var zig_args = List([]const u8).init(builder.allocator); | |
| 909 | defer zig_args.deinit(); | |
| 910 | ||
| 911 | %%zig_args.append("build_obj"); | |
| 912 | %%zig_args.append(builder.pathFromRoot(self.root_src)); | |
| 913 | ||
| 914 | if (self.verbose) { | |
| 915 | %%zig_args.append("--verbose"); | |
| 916 | } | |
| 917 | ||
| 918 | if (self.release) { | |
| 919 | %%zig_args.append("--release"); | |
| 920 | } | |
| 921 | ||
| 922 | test (self.output_path) |output_path| { | |
| 923 | %%zig_args.append("--output"); | |
| 924 | %%zig_args.append(builder.pathFromRoot(output_path)); | |
| 925 | } | |
| 926 | ||
| 927 | %%zig_args.append("--name"); | |
| 928 | %%zig_args.append(self.name); | |
| 929 | ||
| 930 | switch (self.target) { | |
| 931 | Target.Native => {}, | |
| 932 | Target.Cross => |cross_target| { | |
| 933 | %%zig_args.append("--target-arch"); | |
| 934 | %%zig_args.append(@enumTagName(cross_target.arch)); | |
| 935 | ||
| 936 | %%zig_args.append("--target-os"); | |
| 937 | %%zig_args.append(@enumTagName(cross_target.os)); | |
| 938 | ||
| 939 | %%zig_args.append("--target-environ"); | |
| 940 | %%zig_args.append(@enumTagName(cross_target.environ)); | |
| 941 | }, | |
| 942 | } | |
| 943 | ||
| 944 | for (builder.include_paths.toSliceConst()) |include_path| { | |
| 945 | %%zig_args.append("-isystem"); | |
| 946 | %%zig_args.append(include_path); | |
| 947 | } | |
| 948 | ||
| 949 | for (builder.rpaths.toSliceConst()) |rpath| { | |
| 950 | %%zig_args.append("-rpath"); | |
| 951 | %%zig_args.append(rpath); | |
| 952 | } | |
| 953 | ||
| 954 | for (builder.lib_paths.toSliceConst()) |lib_path| { | |
| 955 | %%zig_args.append("--library-path"); | |
| 956 | %%zig_args.append(lib_path); | |
| 957 | } | |
| 958 | ||
| 959 | %%builder.spawnChild(builder.zig_exe, zig_args.toSliceConst()); | |
| 960 | } | |
| 961 | }; | |
| 962 | ||
| 963 | pub const AsmStep = struct { | |
| 964 | step: Step, | |
| 965 | builder: &Builder, | |
| 966 | name: []const u8, | |
| 967 | target: Target, | |
| 968 | verbose: bool, | |
| 969 | release: bool, | |
| 970 | output_path: ?[]const u8, | |
| 971 | src_path: []const u8, | |
| 972 | ||
| 973 | pub fn init(builder: &Builder, name: []const u8, src_path: []const u8) -> AsmStep { | |
| 974 | var self = AsmStep { | |
| 975 | .step = Step.init(name, builder.allocator, make), | |
| 976 | .builder = builder, | |
| 977 | .name = name, | |
| 978 | .target = Target.Native, | |
| 979 | .verbose = false, | |
| 980 | .release = false, | |
| 981 | .output_path = null, | |
| 982 | .src_path = src_path, | |
| 983 | }; | |
| 984 | return self; | |
| 985 | } | |
| 986 | ||
| 987 | pub fn setTarget(self: &AsmStep, target_arch: Arch, target_os: Os, target_environ: Environ) { | |
| 988 | self.target = Target.Cross { | |
| 989 | CrossTarget { | |
| 990 | .arch = target_arch, | |
| 991 | .os = target_os, | |
| 992 | .environ = target_environ, | |
| 993 | } | |
| 994 | }; | |
| 995 | } | |
| 996 | ||
| 997 | pub fn setVerbose(self: &AsmStep, value: bool) { | |
| 739 | pub fn setVerbose(self: &LibExeObjStep, value: bool) { | |
| 998 | 740 | self.verbose = value; |
| 999 | 741 | } |
| 1000 | 742 | |
| 1001 | pub fn setRelease(self: &AsmStep, value: bool) { | |
| 743 | pub fn setRelease(self: &LibExeObjStep, value: bool) { | |
| 1002 | 744 | self.release = value; |
| 1003 | 745 | } |
| 1004 | 746 | |
| 1005 | pub fn setOutputPath(self: &AsmStep, value: []const u8) { | |
| 747 | pub fn setOutputPath(self: &LibExeObjStep, value: []const u8) { | |
| 1006 | 748 | self.output_path = value; |
| 1007 | 749 | } |
| 1008 | 750 | |
| 1009 | fn make(step: &Step) -> %void { | |
| 1010 | const self = @fieldParentPtr(AsmStep, "step", step); | |
| 1011 | const builder = self.builder; | |
| 1012 | ||
| 1013 | var zig_args = List([]const u8).init(builder.allocator); | |
| 1014 | defer zig_args.deinit(); | |
| 1015 | ||
| 1016 | %%zig_args.append("asm"); | |
| 1017 | %%zig_args.append(builder.pathFromRoot(self.src_path)); | |
| 1018 | ||
| 1019 | if (self.verbose) { | |
| 1020 | %%zig_args.append("--verbose"); | |
| 1021 | } | |
| 1022 | ||
| 1023 | if (self.release) { | |
| 1024 | %%zig_args.append("--release"); | |
| 1025 | } | |
| 1026 | ||
| 1027 | test (self.output_path) |output_path| { | |
| 1028 | %%zig_args.append("--output"); | |
| 1029 | %%zig_args.append(builder.pathFromRoot(output_path)); | |
| 1030 | } | |
| 1031 | ||
| 1032 | %%zig_args.append("--name"); | |
| 1033 | %%zig_args.append(self.name); | |
| 1034 | ||
| 1035 | switch (self.target) { | |
| 1036 | Target.Native => {}, | |
| 1037 | Target.Cross => |cross_target| { | |
| 1038 | %%zig_args.append("--target-arch"); | |
| 1039 | %%zig_args.append(@enumTagName(cross_target.arch)); | |
| 1040 | ||
| 1041 | %%zig_args.append("--target-os"); | |
| 1042 | %%zig_args.append(@enumTagName(cross_target.os)); | |
| 1043 | ||
| 1044 | %%zig_args.append("--target-environ"); | |
| 1045 | %%zig_args.append(@enumTagName(cross_target.environ)); | |
| 1046 | }, | |
| 1047 | } | |
| 1048 | ||
| 1049 | %%builder.spawnChild(builder.zig_exe, zig_args.toSliceConst()); | |
| 751 | pub fn addAssemblyFile(self: &LibExeObjStep, path: []const u8) { | |
| 752 | %%self.assembly_files.append(path); | |
| 1050 | 753 | } |
| 1051 | }; | |
| 1052 | 754 | |
| 1053 | pub const LinkStep = struct { | |
| 1054 | step: Step, | |
| 1055 | builder: &Builder, | |
| 1056 | name: []const u8, | |
| 1057 | target: Target, | |
| 1058 | linker_script: LinkerScript, | |
| 1059 | link_libs: BufSet, | |
| 1060 | verbose: bool, | |
| 1061 | release: bool, | |
| 1062 | output_path: ?[]const u8, | |
| 1063 | object_files: List([]const u8), | |
| 1064 | static: bool, | |
| 1065 | out_filename: []const u8, | |
| 1066 | out_type: OutType, | |
| 1067 | version: Version, | |
| 1068 | major_only_filename: []const u8, | |
| 1069 | name_only_filename: []const u8, | |
| 1070 | ||
| 1071 | const OutType = enum { | |
| 1072 | Exe, | |
| 1073 | Lib, | |
| 1074 | }; | |
| 755 | pub fn addObjectFile(self: &LibExeObjStep, path: []const u8) { | |
| 756 | assert(self.kind != Kind.Obj); | |
| 1075 | 757 | |
| 1076 | pub fn initExecutable(builder: &Builder, name: []const u8) -> LinkStep { | |
| 1077 | return init(builder, name, OutType.Exe, builder.version(0, 0, 0), false) | |
| 758 | %%self.object_files.append(path); | |
| 1078 | 759 | } |
| 1079 | 760 | |
| 1080 | pub fn initSharedLibrary(builder: &Builder, name: []const u8, version: &const Version) -> LinkStep { | |
| 1081 | return init(builder, name, OutType.Lib, version, false) | |
| 1082 | } | |
| 761 | pub fn addObject(self: &LibExeObjStep, obj: &LibExeObjStep) { | |
| 762 | assert(obj.kind == Kind.Obj); | |
| 763 | assert(self.kind != Kind.Obj); | |
| 1083 | 764 | |
| 1084 | pub fn initStaticLibrary(builder: &Builder, name: []const u8) -> LinkStep { | |
| 1085 | return init(builder, name, OutType.Lib, builder.version(0, 0, 0), true) | |
| 1086 | } | |
| 1087 | ||
| 1088 | fn init(builder: &Builder, name: []const u8, out_type: OutType, version: &const Version, static: bool) -> LinkStep { | |
| 1089 | var self = LinkStep { | |
| 1090 | .builder = builder, | |
| 1091 | .verbose = false, | |
| 1092 | .release = false, | |
| 1093 | .name = name, | |
| 1094 | .target = Target.Native, | |
| 1095 | .linker_script = LinkerScript.None, | |
| 1096 | .link_libs = BufSet.init(builder.allocator), | |
| 1097 | .step = Step.init(name, builder.allocator, make), | |
| 1098 | .output_path = null, | |
| 1099 | .object_files = List([]const u8).init(builder.allocator), | |
| 1100 | .out_type = out_type, | |
| 1101 | .version = *version, | |
| 1102 | .static = static, | |
| 1103 | .out_filename = undefined, | |
| 1104 | .major_only_filename = undefined, | |
| 1105 | .name_only_filename = undefined, | |
| 1106 | }; | |
| 1107 | self.computeOutFileName(); | |
| 1108 | return self; | |
| 1109 | } | |
| 1110 | ||
| 1111 | fn computeOutFileName(self: &LinkStep) { | |
| 1112 | switch (self.out_type) { | |
| 1113 | OutType.Exe => { | |
| 1114 | self.out_filename = self.builder.fmt("{}{}", self.name, self.target.exeFileExt()); | |
| 1115 | }, | |
| 1116 | OutType.Lib => { | |
| 1117 | if (self.static) { | |
| 1118 | self.out_filename = self.builder.fmt("lib{}.a", self.name); | |
| 1119 | } else { | |
| 1120 | self.out_filename = self.builder.fmt("lib{}.so.{d}.{d}.{d}", | |
| 1121 | self.name, self.version.major, self.version.minor, self.version.patch); | |
| 1122 | self.major_only_filename = self.builder.fmt("lib{}.so.{d}", self.name, self.version.major); | |
| 1123 | self.name_only_filename = self.builder.fmt("lib{}.so", self.name); | |
| 1124 | } | |
| 1125 | }, | |
| 1126 | } | |
| 1127 | } | |
| 1128 | ||
| 1129 | pub fn addObjectFile(self: &LinkStep, file: []const u8) { | |
| 1130 | %%self.object_files.append(file); | |
| 1131 | } | |
| 1132 | ||
| 1133 | pub fn addObject(self: &LinkStep, obj: &ObjectStep) { | |
| 1134 | 765 | self.step.dependOn(&obj.step); |
| 1135 | 766 | |
| 1136 | 767 | const path_to_obj = test (obj.output_path) |explicit_out_path| { |
| ... | ... | @@ -1143,61 +774,11 @@ pub const LinkStep = struct { |
| 1143 | 774 | %%self.object_files.append(path_to_obj); |
| 1144 | 775 | } |
| 1145 | 776 | |
| 1146 | pub fn addAssembly(self: &LinkStep, assembly: &AsmStep) { | |
| 1147 | self.step.dependOn(&assembly.step); | |
| 1148 | ||
| 1149 | const path_to_obj = test (assembly.output_path) |explicit_out_path| { | |
| 1150 | explicit_out_path | |
| 1151 | } else { | |
| 1152 | // TODO make it so we always know where this will be | |
| 1153 | %%os.path.join(self.builder.allocator, self.builder.out_dir, | |
| 1154 | self.builder.fmt("{}{}", assembly.name, assembly.target.oFileExt())) | |
| 1155 | }; | |
| 1156 | %%self.object_files.append(path_to_obj); | |
| 1157 | } | |
| 1158 | ||
| 1159 | pub fn setTarget(self: &LinkStep, target_arch: Arch, target_os: Os, target_environ: Environ) { | |
| 1160 | self.target = Target.Cross { | |
| 1161 | CrossTarget { | |
| 1162 | .arch = target_arch, | |
| 1163 | .os = target_os, | |
| 1164 | .environ = target_environ, | |
| 1165 | } | |
| 1166 | }; | |
| 1167 | self.computeOutFileName(); | |
| 1168 | } | |
| 1169 | ||
| 1170 | /// LinkStep keeps a reference to script for its lifetime or until this function | |
| 1171 | /// is called again. | |
| 1172 | pub fn setLinkerScriptContents(self: &LinkStep, script: []const u8) { | |
| 1173 | self.linker_script = LinkerScript.Embed { script }; | |
| 1174 | } | |
| 1175 | ||
| 1176 | pub fn setLinkerScriptPath(self: &LinkStep, path: []const u8) { | |
| 1177 | self.linker_script = LinkerScript.Path { path }; | |
| 1178 | } | |
| 1179 | ||
| 1180 | pub fn linkSystemLibrary(self: &LinkStep, name: []const u8) { | |
| 1181 | %%self.link_libs.put(name); | |
| 1182 | } | |
| 1183 | ||
| 1184 | pub fn setVerbose(self: &LinkStep, value: bool) { | |
| 1185 | self.verbose = value; | |
| 1186 | } | |
| 1187 | ||
| 1188 | pub fn setRelease(self: &LinkStep, value: bool) { | |
| 1189 | self.release = value; | |
| 1190 | } | |
| 1191 | ||
| 1192 | pub fn setOutputPath(self: &LinkStep, value: []const u8) { | |
| 1193 | self.output_path = value; | |
| 1194 | } | |
| 1195 | ||
| 1196 | 777 | fn make(step: &Step) -> %void { |
| 1197 | const self = @fieldParentPtr(LinkStep, "step", step); | |
| 778 | const self = @fieldParentPtr(LibExeObjStep, "step", step); | |
| 1198 | 779 | const builder = self.builder; |
| 1199 | 780 | |
| 1200 | if (self.object_files.len == 0) { | |
| 781 | if (self.root_src == null and self.object_files.len == 0 and self.assembly_files.len == 0) { | |
| 1201 | 782 | %%io.stderr.printf("{}: linker needs 1 or more objects to link\n", step.name); |
| 1202 | 783 | return error.NeedAnObject; |
| 1203 | 784 | } |
| ... | ... | @@ -1205,16 +786,27 @@ pub const LinkStep = struct { |
| 1205 | 786 | var zig_args = List([]const u8).init(builder.allocator); |
| 1206 | 787 | defer zig_args.deinit(); |
| 1207 | 788 | |
| 1208 | const cmd = switch (self.out_type) { | |
| 1209 | OutType.Exe => "link_exe", | |
| 1210 | OutType.Lib => "link_lib", | |
| 789 | const cmd = switch (self.kind) { | |
| 790 | Kind.Lib => "build_lib", | |
| 791 | Kind.Exe => "build_exe", | |
| 792 | Kind.Obj => "build_obj", | |
| 1211 | 793 | }; |
| 1212 | 794 | %%zig_args.append(cmd); |
| 1213 | 795 | |
| 796 | test (self.root_src) |root_src| { | |
| 797 | %%zig_args.append(builder.pathFromRoot(root_src)); | |
| 798 | } | |
| 799 | ||
| 1214 | 800 | for (self.object_files.toSliceConst()) |object_file| { |
| 801 | %%zig_args.append("--object"); | |
| 1215 | 802 | %%zig_args.append(builder.pathFromRoot(object_file)); |
| 1216 | 803 | } |
| 1217 | 804 | |
| 805 | for (self.assembly_files.toSliceConst()) |asm_file| { | |
| 806 | %%zig_args.append("--assembly"); | |
| 807 | %%zig_args.append(builder.pathFromRoot(asm_file)); | |
| 808 | } | |
| 809 | ||
| 1218 | 810 | if (self.verbose) { |
| 1219 | 811 | %%zig_args.append("--verbose"); |
| 1220 | 812 | } |
| ... | ... | @@ -1223,10 +815,6 @@ pub const LinkStep = struct { |
| 1223 | 815 | %%zig_args.append("--release"); |
| 1224 | 816 | } |
| 1225 | 817 | |
| 1226 | if (self.static) { | |
| 1227 | %%zig_args.append("--static"); | |
| 1228 | } | |
| 1229 | ||
| 1230 | 818 | test (self.output_path) |output_path| { |
| 1231 | 819 | %%zig_args.append("--output"); |
| 1232 | 820 | %%zig_args.append(builder.pathFromRoot(output_path)); |
| ... | ... | @@ -1235,6 +823,17 @@ pub const LinkStep = struct { |
| 1235 | 823 | %%zig_args.append("--name"); |
| 1236 | 824 | %%zig_args.append(self.name); |
| 1237 | 825 | |
| 826 | if (self.kind == Kind.Lib and !self.static) { | |
| 827 | %%zig_args.append("--ver-major"); | |
| 828 | %%zig_args.append(builder.fmt("{}", self.version.major)); | |
| 829 | ||
| 830 | %%zig_args.append("--ver-minor"); | |
| 831 | %%zig_args.append(builder.fmt("{}", self.version.minor)); | |
| 832 | ||
| 833 | %%zig_args.append("--ver-patch"); | |
| 834 | %%zig_args.append(builder.fmt("{}", self.version.patch)); | |
| 835 | } | |
| 836 | ||
| 1238 | 837 | switch (self.target) { |
| 1239 | 838 | Target.Native => {}, |
| 1240 | 839 | Target.Cross => |cross_target| { |
| ... | ... | @@ -1273,6 +872,11 @@ pub const LinkStep = struct { |
| 1273 | 872 | } |
| 1274 | 873 | } |
| 1275 | 874 | |
| 875 | for (builder.include_paths.toSliceConst()) |include_path| { | |
| 876 | %%zig_args.append("-isystem"); | |
| 877 | %%zig_args.append(include_path); | |
| 878 | } | |
| 879 | ||
| 1276 | 880 | for (builder.rpaths.toSliceConst()) |rpath| { |
| 1277 | 881 | %%zig_args.append("-rpath"); |
| 1278 | 882 | %%zig_args.append(rpath); |
| ... | ... | @@ -1284,6 +888,13 @@ pub const LinkStep = struct { |
| 1284 | 888 | } |
| 1285 | 889 | |
| 1286 | 890 | %%builder.spawnChild(builder.zig_exe, zig_args.toSliceConst()); |
| 891 | ||
| 892 | if (self.kind == Kind.Lib and !self.static) { | |
| 893 | // sym link for libfoo.so.1 to libfoo.so.1.2.3 | |
| 894 | %%os.atomicSymLink(builder.allocator, self.out_filename, self.out_filename_major_only); | |
| 895 | // sym link for libfoo.so to libfoo.so.1 | |
| 896 | %%os.atomicSymLink(builder.allocator, self.out_filename_major_only, self.out_filename_name_only); | |
| 897 | } | |
| 1287 | 898 | } |
| 1288 | 899 | }; |
| 1289 | 900 | |
| ... | ... | @@ -1592,15 +1203,17 @@ pub const CExecutable = struct { |
| 1592 | 1203 | %%self.full_path_libs.append(clib.out_filename); |
| 1593 | 1204 | } |
| 1594 | 1205 | |
| 1595 | pub fn linkLibrary(self: &CExecutable, lib: &LibOrExeStep) { | |
| 1596 | assert(lib.kind == LibOrExeStep.Kind.Lib); | |
| 1206 | pub fn linkLibrary(self: &CExecutable, lib: &LibExeObjStep) { | |
| 1207 | assert(lib.kind == LibExeObjStep.Kind.Lib); | |
| 1597 | 1208 | self.step.dependOn(&lib.step); |
| 1598 | 1209 | %%self.full_path_libs.append(lib.out_filename); |
| 1599 | 1210 | // TODO should be some kind of isolated directory that only has this header in it |
| 1600 | 1211 | %%self.include_dirs.append(self.builder.out_dir); |
| 1601 | 1212 | } |
| 1602 | 1213 | |
| 1603 | pub fn addObject(self: &CExecutable, obj: &ObjectStep) { | |
| 1214 | pub fn addObject(self: &CExecutable, obj: &LibExeObjStep) { | |
| 1215 | assert(obj.kind == LibExeObjStep.Kind.Obj); | |
| 1216 | ||
| 1604 | 1217 | self.step.dependOn(&obj.step); |
| 1605 | 1218 | |
| 1606 | 1219 | // TODO make it so we always know where this will be |
std/debug.zig+5-1| ... | ... | @@ -90,7 +90,11 @@ pub fn writeStackTrace(out_stream: &io.OutStream, allocator: &mem.Allocator, tty |
| 90 | 90 | // at compile time. I'll call it issue #313 |
| 91 | 91 | const ptr_hex = if (@sizeOf(usize) == 4) "0x{x8}" else "0x{x16}"; |
| 92 | 92 | |
| 93 | const compile_unit = findCompileUnit(st, return_address) ?? return error.MissingDebugInfo; | |
| 93 | const compile_unit = findCompileUnit(st, return_address) ?? { | |
| 94 | %return out_stream.print(DIM ++ ptr_hex ++ " in ??? (???)" ++ RESET ++ "\n\n\n", return_address); | |
| 95 | %return out_stream.flush(); | |
| 96 | continue; | |
| 97 | }; | |
| 94 | 98 | const compile_unit_name = %return compile_unit.die.getAttrString(st, DW.AT_name); |
| 95 | 99 | try (getLineNumberInfo(st, compile_unit, usize(return_address) - 1)) |line_info| { |
| 96 | 100 | defer line_info.deinit(); |
test/cases/cast.zig+9| ... | ... | @@ -150,3 +150,12 @@ fn peerTypeEmptyArrayAndSlice(a: bool, slice: []const u8) -> []const u8 { |
| 150 | 150 | |
| 151 | 151 | return slice[0...1]; |
| 152 | 152 | } |
| 153 | ||
| 154 | test "implicitly cast from [N]T to ?[]const T" { | |
| 155 | assert(mem.eql(u8, ??castToMaybeSlice(), "hi")); | |
| 156 | comptime assert(mem.eql(u8, ??castToMaybeSlice(), "hi")); | |
| 157 | } | |
| 158 | ||
| 159 | fn castToMaybeSlice() -> ?[]const u8 { | |
| 160 | return "hi"; | |
| 161 | } |
test/tests.zig+4-6| ... | ... | @@ -355,18 +355,16 @@ pub const CompareOutputContext = struct { |
| 355 | 355 | return; |
| 356 | 356 | } |
| 357 | 357 | |
| 358 | const assembly = b.addAssemble("test", root_src); | |
| 358 | const exe = b.addExecutable("test", null); | |
| 359 | exe.addAssemblyFile(root_src); | |
| 360 | exe.setOutputPath(exe_path); | |
| 359 | 361 | |
| 360 | 362 | for (case.sources.toSliceConst()) |src_file| { |
| 361 | 363 | const expanded_src_path = %%os.path.join(b.allocator, "test_artifacts", src_file.filename); |
| 362 | 364 | const write_src = b.addWriteFile(expanded_src_path, src_file.source); |
| 363 | assembly.step.dependOn(&write_src.step); | |
| 365 | exe.step.dependOn(&write_src.step); | |
| 364 | 366 | } |
| 365 | 367 | |
| 366 | const exe = b.addLinkExecutable("test"); | |
| 367 | exe.addAssembly(assembly); | |
| 368 | exe.setOutputPath(exe_path); | |
| 369 | ||
| 370 | 368 | const run_and_cmp_output = RunCompareOutputStep.create(self, exe_path, annotated_case_name, |
| 371 | 369 | case.expected_output); |
| 372 | 370 | run_and_cmp_output.step.dependOn(&exe.step); |