authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-04-26 19:17:05-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-04-26 19:17:05-04:00
log7b0542d08b7e8e5ccbe81f495d641305b3b8a264
tree67060c5620c5a36700abfa9c44d3ce31e35f9da4
parent09bc4d6ba366c1a642b3c92c7ec554e95a369053

build system: consolidate duplicate code and more

* 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 file

13 files changed, 322 insertions(+), 693 deletions(-)

src/all_types.hpp+2
...@@ -1296,6 +1296,7 @@ struct CodeGen {...@@ -1296,6 +1296,7 @@ struct CodeGen {
1296 LLVMBuilderRef builder;1296 LLVMBuilderRef builder;
1297 ZigLLVMDIBuilder *dbuilder;1297 ZigLLVMDIBuilder *dbuilder;
1298 ZigLLVMDICompileUnit *compile_unit;1298 ZigLLVMDICompileUnit *compile_unit;
1299 ZigLLVMDIFile *compile_unit_file;
12991300
1300 ZigList<Buf *> link_libs; // non-libc link libs1301 ZigList<Buf *> link_libs; // non-libc link libs
1301 // add -framework [name] args to linker1302 // add -framework [name] args to linker
...@@ -1468,6 +1469,7 @@ struct CodeGen {...@@ -1468,6 +1469,7 @@ struct CodeGen {
14681469
1469 Buf global_asm;1470 Buf global_asm;
1470 ZigList<Buf *> link_objects;1471 ZigList<Buf *> link_objects;
1472 ZigList<Buf *> assembly_files;
14711473
1472 ZigList<TypeTableEntry *> name_table_enums;1474 ZigList<TypeTableEntry *> name_table_enums;
14731475
src/analyze.cpp+5-4
...@@ -2851,9 +2851,7 @@ void preview_use_decl(CodeGen *g, AstNode *node) {...@@ -2851,9 +2851,7 @@ void preview_use_decl(CodeGen *g, AstNode *node) {
2851 node->data.use.value = result;2851 node->data.use.value = result;
2852}2852}
28532853
2854ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package,2854ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package, Buf *abs_full_path, Buf *source_code) {
2855 Buf *abs_full_path, Buf *src_dirname, Buf *src_basename, Buf *source_code)
2856{
2857 if (g->verbose) {2855 if (g->verbose) {
2858 fprintf(stderr, "\nOriginal Source (%s):\n", buf_ptr(abs_full_path));2856 fprintf(stderr, "\nOriginal Source (%s):\n", buf_ptr(abs_full_path));
2859 fprintf(stderr, "----------------\n");2857 fprintf(stderr, "----------------\n");
...@@ -2894,7 +2892,10 @@ ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package,...@@ -2894,7 +2892,10 @@ ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package,
2894 ast_print(stderr, import_entry->root, 0);2892 ast_print(stderr, import_entry->root, 0);
2895 }2893 }
28962894
2897 // TODO: assert that src_basename has no '/' in it2895 Buf *src_dirname = buf_alloc();
2896 Buf *src_basename = buf_alloc();
2897 os_path_split(abs_full_path, src_dirname, src_basename);
2898
2898 import_entry->di_file = ZigLLVMCreateFile(g->dbuilder, buf_ptr(src_basename), buf_ptr(src_dirname));2899 import_entry->di_file = ZigLLVMCreateFile(g->dbuilder, buf_ptr(src_basename), buf_ptr(src_dirname));
2899 g->import_table.put(abs_full_path, import_entry);2900 g->import_table.put(abs_full_path, import_entry);
2900 g->import_queue.append(import_entry);2901 g->import_queue.append(import_entry);
src/analyze.hpp+1-2
...@@ -40,8 +40,7 @@ void find_libc_lib_path(CodeGen *g);...@@ -40,8 +40,7 @@ void find_libc_lib_path(CodeGen *g);
40bool type_has_bits(TypeTableEntry *type_entry);40bool type_has_bits(TypeTableEntry *type_entry);
4141
4242
43ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package,43ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package, Buf *abs_full_path, Buf *source_code);
44 Buf *abs_full_path, Buf *src_dirname, Buf *src_basename, Buf *source_code);
4544
4645
47// TODO move these over, these used to be static46// 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,7 +55,7 @@ PackageTableEntry *new_package(const char *root_src_dir, const char *root_src_pa
55 return entry;55 return entry;
56}56}
5757
58CodeGen *codegen_create(Buf *root_source_dir, const ZigTarget *target) {58CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target) {
59 CodeGen *g = allocate<CodeGen>(1);59 CodeGen *g = allocate<CodeGen>(1);
6060
61 codegen_add_time_event(g, "Initialize");61 codegen_add_time_event(g, "Initialize");
...@@ -81,9 +81,17 @@ CodeGen *codegen_create(Buf *root_source_dir, const ZigTarget *target) {...@@ -81,9 +81,17 @@ CodeGen *codegen_create(Buf *root_source_dir, const ZigTarget *target) {
81 // reserve index 0 to indicate no error81 // reserve index 0 to indicate no error
82 g->error_decls.append(nullptr);82 g->error_decls.append(nullptr);
8383
84 g->root_package = new_package(buf_ptr(root_source_dir), "");84 if (root_src_path) {
85 g->std_package = new_package(ZIG_STD_DIR, "index.zig");85 Buf *src_basename = buf_alloc();
86 g->root_package->package_table.put(buf_create_from_str("std"), g->std_package);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 g->zig_std_dir = buf_create_from_str(ZIG_STD_DIR);95 g->zig_std_dir = buf_create_from_str(ZIG_STD_DIR);
8896
89 g->zig_std_special_dir = buf_alloc();97 g->zig_std_special_dir = buf_alloc();
...@@ -757,7 +765,7 @@ static LLVMValueRef get_safety_crash_err_fn(CodeGen *g) {...@@ -757,7 +765,7 @@ static LLVMValueRef get_safety_crash_err_fn(CodeGen *g) {
757765
758static void gen_debug_safety_crash_for_err(CodeGen *g, LLVMValueRef err_val) {766static void gen_debug_safety_crash_for_err(CodeGen *g, LLVMValueRef err_val) {
759 LLVMValueRef safety_crash_err_fn = get_safety_crash_err_fn(g);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 LLVMBuildUnreachable(g->builder);769 LLVMBuildUnreachable(g->builder);
762}770}
763771
...@@ -3655,6 +3663,10 @@ static LLVMValueRef build_alloca(CodeGen *g, TypeTableEntry *type_entry, const c...@@ -3655,6 +3663,10 @@ static LLVMValueRef build_alloca(CodeGen *g, TypeTableEntry *type_entry, const c
3655}3663}
36563664
3657static void do_code_gen(CodeGen *g) {3665static void do_code_gen(CodeGen *g) {
3666 if (g->verbose) {
3667 fprintf(stderr, "\nCode Generation:\n");
3668 fprintf(stderr, "------------------\n");
3669 }
3658 assert(!g->errors.length);3670 assert(!g->errors.length);
36593671
3660 codegen_add_time_event(g, "Code Generation");3672 codegen_add_time_event(g, "Code Generation");
...@@ -4602,8 +4614,9 @@ static void define_builtin_compile_vars(CodeGen *g) {...@@ -4602,8 +4614,9 @@ static void define_builtin_compile_vars(CodeGen *g) {
4602 add_compile_var(g, "panic_implementation_provided", create_const_bool(g, false));4614 add_compile_var(g, "panic_implementation_provided", create_const_bool(g, false));
4603}4615}
46044616
4605static void init(CodeGen *g, Buf *source_path) {4617static void init(CodeGen *g) {
4606 g->module = LLVMModuleCreateWithName(buf_ptr(source_path));4618 assert(g->root_out_name);
4619 g->module = LLVMModuleCreateWithName(buf_ptr(g->root_out_name));
46074620
4608 get_target_triple(&g->triple_str, &g->zig_target);4621 get_target_triple(&g->triple_str, &g->zig_target);
46094622
...@@ -4674,23 +4687,25 @@ static void init(CodeGen *g, Buf *source_path) {...@@ -4674,23 +4687,25 @@ static void init(CodeGen *g, Buf *source_path) {
4674 g->const_void_val.type = g->builtin_types.entry_void;4687 g->const_void_val.type = g->builtin_types.entry_void;
4675}4688}
46764689
4677void codegen_parseh(CodeGen *g, Buf *src_dirname, Buf *src_basename, Buf *source_code) {4690void codegen_parseh(CodeGen *g, Buf *full_path) {
4678 find_libc_include_path(g);4691 find_libc_include_path(g);
4679 Buf *full_path = buf_alloc();4692
4680 os_path_join(src_dirname, src_basename, full_path);4693 Buf *src_basename = buf_alloc();
4694 Buf *src_dirname = buf_alloc();
4695 os_path_split(full_path, src_dirname, src_basename);
46814696
4682 ImportTableEntry *import = allocate<ImportTableEntry>(1);4697 ImportTableEntry *import = allocate<ImportTableEntry>(1);
4683 import->source_code = source_code;4698 import->source_code = nullptr;
4684 import->path = full_path;4699 import->path = full_path;
4685 g->root_import = import;4700 g->root_import = import;
4686 import->decls_scope = create_decls_scope(nullptr, nullptr, nullptr, import);4701 import->decls_scope = create_decls_scope(nullptr, nullptr, nullptr, import);
46874702
4688 init(g, full_path);4703 init(g);
46894704
4690 import->di_file = ZigLLVMCreateFile(g->dbuilder, buf_ptr(src_basename), buf_ptr(src_dirname));4705 import->di_file = ZigLLVMCreateFile(g->dbuilder, buf_ptr(src_basename), buf_ptr(src_dirname));
46914706
4692 ZigList<ErrorMsg *> errors = {0};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 if (err) {4709 if (err) {
4695 fprintf(stderr, "unable to parse .h file: %s\n", err_str(err));4710 fprintf(stderr, "unable to parse .h file: %s\n", err_str(err));
4696 exit(1);4711 exit(1);
...@@ -4719,7 +4734,7 @@ static ImportTableEntry *add_special_code(CodeGen *g, PackageTableEntry *package...@@ -4719,7 +4734,7 @@ static ImportTableEntry *add_special_code(CodeGen *g, PackageTableEntry *package
4719 zig_panic("unable to open '%s': %s", buf_ptr(&path_to_code_src), err_str(err));4734 zig_panic("unable to open '%s': %s", buf_ptr(&path_to_code_src), err_str(err));
4720 }4735 }
47214736
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}
47244739
4725static PackageTableEntry *create_bootstrap_pkg(CodeGen *g) {4740static PackageTableEntry *create_bootstrap_pkg(CodeGen *g) {
...@@ -4736,23 +4751,27 @@ static PackageTableEntry *create_zigrt_pkg(CodeGen *g) {...@@ -4736,23 +4751,27 @@ static PackageTableEntry *create_zigrt_pkg(CodeGen *g) {
4736 return package;4751 return package;
4737}4752}
47384753
4739void codegen_add_root_code(CodeGen *g, Buf *src_dir, Buf *src_basename, Buf *source_code) {4754static void gen_root_source(CodeGen *g) {
4740 codegen_add_time_event(g, "Semantic Analysis");4755 if (buf_len(&g->root_package->root_src_path) == 0)
47414756 return;
4742 Buf source_path = BUF_INIT;
4743 os_path_join(src_dir, src_basename, &source_path);
47444757
4745 buf_init_from_buf(&g->root_package->root_src_path, src_basename);4758 codegen_add_time_event(g, "Semantic Analysis");
47464759
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);
47484762
4749 Buf *abs_full_path = buf_alloc();4763 Buf *abs_full_path = buf_alloc();
4750 int err;4764 int err;
4751 if ((err = os_path_real(&source_path, abs_full_path))) {4765 if ((err = os_path_real(rel_full_path, abs_full_path))) {
4752 zig_panic("unable to open '%s': %s", buf_ptr(&source_path), err_str(err));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 }
47544773
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);
47564775
4757 assert(g->root_out_name);4776 assert(g->root_out_name);
4758 assert(g->out_type != OutTypeUnknown);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,27 +4806,33 @@ void codegen_add_root_code(CodeGen *g, Buf *src_dir, Buf *src_basename, Buf *sou
4787 exit(1);4806 exit(1);
4788 }4807 }
47894808
4790 if (g->verbose) {
4791 fprintf(stderr, "\nCode Generation:\n");
4792 fprintf(stderr, "------------------\n");
4793
4794 }
4795
4796 do_code_gen(g);
4797}4809}
47984810
4799void codegen_add_root_assembly(CodeGen *g, Buf *src_dir, Buf *src_basename, Buf *source_code) {4811void codegen_add_assembly(CodeGen *g, Buf *path) {
4800 Buf source_path = BUF_INIT;4812 g->assembly_files.append(path);
4801 os_path_join(src_dir, src_basename, &source_path);4813}
48024814
4803 init(g, &source_path);4815static 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}
48044829
4805 assert(g->root_out_name);4830void codegen_build(CodeGen *g) {
4806 assert(g->out_type != OutTypeUnknown);4831 assert(g->out_type != OutTypeUnknown);
4832 init(g);
48074833
4808 buf_init_from_str(&g->global_asm, ".intel_syntax noprefix\n");4834 gen_global_asm(g);
4809 buf_append_buf(&g->global_asm, source_code);4835 gen_root_source(g);
4810
4811 do_code_gen(g);4836 do_code_gen(g);
4812}4837}
48134838
src/codegen.hpp+4-4
...@@ -14,7 +14,7 @@...@@ -14,7 +14,7 @@
1414
15#include <stdio.h>15#include <stdio.h>
1616
17CodeGen *codegen_create(Buf *root_source_dir, const ZigTarget *target);17CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target);
1818
19void codegen_set_clang_argv(CodeGen *codegen, const char **args, size_t len);19void codegen_set_clang_argv(CodeGen *codegen, const char **args, size_t len);
20void codegen_set_is_release(CodeGen *codegen, bool is_release);20void codegen_set_is_release(CodeGen *codegen, bool is_release);
...@@ -49,13 +49,13 @@ void codegen_set_test_name_prefix(CodeGen *g, Buf *prefix);...@@ -49,13 +49,13 @@ void codegen_set_test_name_prefix(CodeGen *g, Buf *prefix);
49void codegen_set_lib_version(CodeGen *g, size_t major, size_t minor, size_t patch);49void codegen_set_lib_version(CodeGen *g, size_t major, size_t minor, size_t patch);
50void codegen_add_time_event(CodeGen *g, const char *name);50void codegen_add_time_event(CodeGen *g, const char *name);
51void codegen_print_timing_report(CodeGen *g, FILE *f);51void codegen_print_timing_report(CodeGen *g, FILE *f);
52void codegen_build(CodeGen *g);
5253
53PackageTableEntry *new_package(const char *root_src_dir, const char *root_src_path);54PackageTableEntry *new_package(const char *root_src_dir, const char *root_src_path);
54void codegen_add_root_code(CodeGen *g, Buf *source_dir, Buf *source_basename, Buf *source_code);55void codegen_add_assembly(CodeGen *g, Buf *path);
55void codegen_add_root_assembly(CodeGen *g, Buf *source_dir, Buf *source_basename, Buf *source_code);
56void codegen_add_object(CodeGen *g, Buf *object_path);56void codegen_add_object(CodeGen *g, Buf *object_path);
5757
58void codegen_parseh(CodeGen *g, Buf *src_dirname, Buf *src_basename, Buf *source_code);58void codegen_parseh(CodeGen *g, Buf *path);
59void codegen_render_ast(CodeGen *g, FILE *f, int indent_size);59void codegen_render_ast(CodeGen *g, FILE *f, int indent_size);
6060
61void codegen_generate_h_file(CodeGen *g);61void 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,6 +6043,21 @@ static ImplicitCastMatchResult ir_types_match_with_implicit_cast(IrAnalyze *ira,
6043 }6043 }
6044 }6044 }
60456045
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 // implicit number literal to typed number6061 // implicit number literal to typed number
6047 // implicit number literal to &const integer6062 // implicit number literal to &const integer
6048 if (actual_type->id == TypeTableEntryIdNumLitFloat ||6063 if (actual_type->id == TypeTableEntryIdNumLitFloat ||
...@@ -7093,6 +7108,29 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -7093,6 +7108,29 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
7093 }7108 }
7094 }7109 }
70957110
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 // explicit cast from []T to []u8 or []u8 to []T7134 // explicit cast from []T to []u8 or []u8 to []T
7097 if (is_slice(wanted_type) && is_slice(actual_type) &&7135 if (is_slice(wanted_type) && is_slice(actual_type) &&
7098 (is_u8(wanted_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.child_type) ||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,8 +10918,7 @@ static TypeTableEntry *ir_analyze_instruction_import(IrAnalyze *ira, IrInstructi
10880 return ira->codegen->builtin_types.entry_invalid;10918 return ira->codegen->builtin_types.entry_invalid;
10881 }10919 }
10882 }10920 }
10883 ImportTableEntry *target_import = add_source_file(ira->codegen, target_package,10921 ImportTableEntry *target_import = add_source_file(ira->codegen, target_package, abs_full_path, import_code);
10884 abs_full_path, search_dir, import_target_path, import_code);
1088510922
10886 scan_decls(ira->codegen, target_import->decls_scope, target_import->root);10923 scan_decls(ira->codegen, target_import->decls_scope, target_import->root);
1088710924
src/link.cpp+4-10
...@@ -33,9 +33,11 @@ static const char *get_libc_static_file(CodeGen *g, const char *file) {...@@ -33,9 +33,11 @@ static const char *get_libc_static_file(CodeGen *g, const char *file) {
3333
34static Buf *build_o(CodeGen *parent_gen, const char *oname) {34static Buf *build_o(CodeGen *parent_gen, const char *oname) {
35 Buf *source_basename = buf_sprintf("%s.zig", oname);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);
3638
37 ZigTarget *child_target = parent_gen->is_native_target ? nullptr : &parent_gen->zig_target;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 child_gen->link_libc = parent_gen->link_libc;41 child_gen->link_libc = parent_gen->link_libc;
4042
41 child_gen->link_libs.resize(parent_gen->link_libs.length);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,15 +62,7 @@ static Buf *build_o(CodeGen *parent_gen, const char *oname) {
60 codegen_set_mmacosx_version_min(child_gen, parent_gen->mmacosx_version_min);62 codegen_set_mmacosx_version_min(child_gen, parent_gen->mmacosx_version_min);
61 codegen_set_mios_version_min(child_gen, parent_gen->mios_version_min);63 codegen_set_mios_version_min(child_gen, parent_gen->mios_version_min);
6264
63 Buf *full_path = buf_alloc();65 codegen_build(child_gen);
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);
72 const char *o_ext = target_o_file_ext(&child_gen->zig_target);66 const char *o_ext = target_o_file_ext(&child_gen->zig_target);
73 Buf *o_out = buf_sprintf("%s%s", oname, o_ext);67 Buf *o_out = buf_sprintf("%s%s", oname, o_ext);
74 codegen_link(child_gen, buf_ptr(o_out));68 codegen_link(child_gen, buf_ptr(o_out));
src/main.cpp+64-121
...@@ -19,29 +19,19 @@...@@ -19,29 +19,19 @@
19static int usage(const char *arg0) {19static int usage(const char *arg0) {
20 fprintf(stderr, "Usage: %s [command] [options]\n"20 fprintf(stderr, "Usage: %s [command] [options]\n"
21 "Commands:\n"21 "Commands:\n"
22 " asm [source] create object from assembly\n"
23 " build build project from build.zig\n"22 " build build project from build.zig\n"
24 " build_exe [source] create executable from source\n"23 " build_exe [source] create executable from source or object files\n"
25 " build_lib [source] create library from source\n"24 " build_lib [source] create library from source or object files\n"
26 " build_obj [source] create object from source\n"25 " build_obj [source] create object from source or assembly\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"26 " parseh [source] convert a c header file to zig extern declarations\n"
30 " targets list available compilation targets\n"27 " targets list available compilation targets\n"
31 " test [source] create and run a test build\n"28 " test [source] create and run a test build\n"
32 " version print version number and exit\n"29 " version print version number and exit\n"
33 "Options:\n"30 "Compile Options:\n"
34 " --ar-path [path] set the path to ar\n"31 " --assembly [source] add assembly file to build\n"
35 " --color [auto|off|on] enable or disable colored error messages\n"32 " --color [auto|off|on] enable or disable colored error messages\n"
36 " --dynamic-linker [path] set the path to ld.so\n"33 " --enable-timing-info print timing diagnostics\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"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 " --name [name] override output name\n"35 " --name [name] override output name\n"
46 " --output [file] override destination path\n"36 " --output [file] override destination path\n"
47 " --release build with optimizations on and debug protection off\n"37 " --release build with optimizations on and debug protection off\n"
...@@ -52,26 +42,34 @@ static int usage(const char *arg0) {...@@ -52,26 +42,34 @@ static int usage(const char *arg0) {
52 " --target-os [name] specify target operating system\n"42 " --target-os [name] specify target operating system\n"
53 " --verbose turn on compiler debug output\n"43 " --verbose turn on compiler debug output\n"
54 " --zig-std-dir [path] directory where zig standard library resides\n"44 " --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"45 " -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"46 " -isystem [dir] add additional search path for other .h files\n"
59 " -mconsole (windows only) --subsystem console to the linker\n"47 "Link Options:\n"
60 " -mios-version-min [ver] (darwin only) set iOS deployment target\n"48 " --ar-path [path] set the path to ar\n"
61 " -mlinker-version [ver] (darwin only) override linker version\n"49 " --dynamic-linker [path] set the path to ld.so\n"
62 " -mmacosx-version-min [ver] (darwin only) set Mac OS X deployment target\n"50 " --each-lib-rpath add rpath for each used dynamic library\n"
63 " -municode (windows only) link with unicode\n"51 " --libc-lib-dir [path] directory where libc crt1.o resides\n"
64 " -mwindows (windows only) --subsystem windows to the linker\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 " -rdynamic add all symbols to the dynamic symbol table\n"58 " -rdynamic add all symbols to the dynamic symbol table\n"
66 " -rpath [path] add directory to the runtime library search path\n"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 "Test Options:\n"70 "Test Options:\n"
69 " --test-filter [text] skip tests that do not match filter\n"71 " --test-filter [text] skip tests that do not match filter\n"
70 " --test-name-prefix [text] add prefix to all tests\n"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 , arg0);73 , arg0);
76 return EXIT_FAILURE;74 return EXIT_FAILURE;
77}75}
...@@ -117,8 +115,6 @@ enum Cmd {...@@ -117,8 +115,6 @@ enum Cmd {
117 CmdVersion,115 CmdVersion,
118 CmdParseH,116 CmdParseH,
119 CmdTargets,117 CmdTargets,
120 CmdAsm,
121 CmdLink,
122};118};
123119
124int main(int argc, char **argv) {120int main(int argc, char **argv) {
...@@ -159,6 +155,7 @@ int main(int argc, char **argv) {...@@ -159,6 +155,7 @@ int main(int argc, char **argv) {
159 ZigList<const char *> rpath_list = {0};155 ZigList<const char *> rpath_list = {0};
160 bool each_lib_rpath = false;156 bool each_lib_rpath = false;
161 ZigList<const char *> objects = {0};157 ZigList<const char *> objects = {0};
158 ZigList<const char *> asm_files = {0};
162 const char *test_filter = nullptr;159 const char *test_filter = nullptr;
163 const char *test_name_prefix = nullptr;160 const char *test_name_prefix = nullptr;
164 size_t ver_major = 0;161 size_t ver_major = 0;
...@@ -197,16 +194,7 @@ int main(int argc, char **argv) {...@@ -197,16 +194,7 @@ int main(int argc, char **argv) {
197 }194 }
198 }195 }
199196
200197 CodeGen *g = codegen_create(build_runner_path, nullptr);
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);
210 codegen_set_out_name(g, buf_create_from_str("build"));198 codegen_set_out_name(g, buf_create_from_str("build"));
211 codegen_set_out_type(g, OutTypeExe);199 codegen_set_out_type(g, OutTypeExe);
212 codegen_set_verbose(g, verbose);200 codegen_set_verbose(g, verbose);
...@@ -256,7 +244,7 @@ int main(int argc, char **argv) {...@@ -256,7 +244,7 @@ int main(int argc, char **argv) {
256 PackageTableEntry *build_pkg = new_package(buf_ptr(&build_file_dirname), buf_ptr(&build_file_basename));244 PackageTableEntry *build_pkg = new_package(buf_ptr(&build_file_dirname), buf_ptr(&build_file_basename));
257 build_pkg->package_table.put(buf_create_from_str("std"), g->std_package);245 build_pkg->package_table.put(buf_create_from_str("std"), g->std_package);
258 g->root_package->package_table.put(buf_create_from_str("@build"), build_pkg);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 codegen_link(g, "build");248 codegen_link(g, "build");
261249
262 Termination term;250 Termination term;
...@@ -339,6 +327,10 @@ int main(int argc, char **argv) {...@@ -339,6 +327,10 @@ int main(int argc, char **argv) {
339 lib_dirs.append(argv[i]);327 lib_dirs.append(argv[i]);
340 } else if (strcmp(arg, "--library") == 0) {328 } else if (strcmp(arg, "--library") == 0) {
341 link_libs.append(argv[i]);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 } else if (strcmp(arg, "--target-arch") == 0) {334 } else if (strcmp(arg, "--target-arch") == 0) {
343 target_arch = argv[i];335 target_arch = argv[i];
344 } else if (strcmp(arg, "--target-os") == 0) {336 } else if (strcmp(arg, "--target-os") == 0) {
...@@ -382,12 +374,6 @@ int main(int argc, char **argv) {...@@ -382,12 +374,6 @@ int main(int argc, char **argv) {
382 } else if (strcmp(arg, "build_lib") == 0) {374 } else if (strcmp(arg, "build_lib") == 0) {
383 cmd = CmdBuild;375 cmd = CmdBuild;
384 out_type = OutTypeLib;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 } else if (strcmp(arg, "version") == 0) {377 } else if (strcmp(arg, "version") == 0) {
392 cmd = CmdVersion;378 cmd = CmdVersion;
393 } else if (strcmp(arg, "parseh") == 0) {379 } else if (strcmp(arg, "parseh") == 0) {
...@@ -396,8 +382,6 @@ int main(int argc, char **argv) {...@@ -396,8 +382,6 @@ int main(int argc, char **argv) {
396 cmd = CmdTest;382 cmd = CmdTest;
397 } else if (strcmp(arg, "targets") == 0) {383 } else if (strcmp(arg, "targets") == 0) {
398 cmd = CmdTargets;384 cmd = CmdTargets;
399 } else if (strcmp(arg, "asm") == 0) {
400 cmd = CmdAsm;
401 } else {385 } else {
402 fprintf(stderr, "Unrecognized command: %s\n", arg);386 fprintf(stderr, "Unrecognized command: %s\n", arg);
403 return usage(arg0);387 return usage(arg0);
...@@ -407,16 +391,12 @@ int main(int argc, char **argv) {...@@ -407,16 +391,12 @@ int main(int argc, char **argv) {
407 case CmdBuild:391 case CmdBuild:
408 case CmdParseH:392 case CmdParseH:
409 case CmdTest:393 case CmdTest:
410 case CmdAsm:
411 if (!in_file) {394 if (!in_file) {
412 in_file = arg;395 in_file = arg;
413 } else {396 } else {
414 return usage(arg0);397 return usage(arg0);
415 }398 }
416 break;399 break;
417 case CmdLink:
418 objects.append(arg);
419 break;
420 case CmdVersion:400 case CmdVersion:
421 case CmdTargets:401 case CmdTargets:
422 return usage(arg0);402 return usage(arg0);
...@@ -430,25 +410,19 @@ int main(int argc, char **argv) {...@@ -430,25 +410,19 @@ int main(int argc, char **argv) {
430 case CmdBuild:410 case CmdBuild:
431 case CmdParseH:411 case CmdParseH:
432 case CmdTest:412 case CmdTest:
433 case CmdAsm:
434 case CmdLink:
435 {413 {
436 bool one_source_input = (cmd == CmdBuild || cmd == CmdParseH || cmd == CmdTest || cmd == CmdAsm);414 if (cmd == CmdBuild && !in_file && objects.length == 0 && asm_files.length == 0) {
437 if (one_source_input) {415 fprintf(stderr, "Expected source file argument or at least one --object or --assembly argument.\n");
438 if (!in_file) {416 return usage(arg0);
439 fprintf(stderr, "Expected source file argument.\n");417 } else if ((cmd == CmdParseH || cmd == CmdTest) && !in_file) {
440 return usage(arg0);418 fprintf(stderr, "Expected source file argument.\n");
441 }419 return usage(arg0);
442 } else if (cmd == CmdLink) {420 } else if (cmd == CmdBuild && out_type == OutTypeObj && objects.length != 0) {
443 if (objects.length == 0) {421 fprintf(stderr, "When building an object file, --object arguments are invalid.\n");
444 fprintf(stderr, "Expected one or more object arguments.\n");422 return usage(arg0);
445 return usage(arg0);
446 }
447 } else {
448 zig_unreachable();
449 }423 }
450424
451 assert((cmd != CmdBuild && cmd != CmdLink) || out_type != OutTypeUnknown);425 assert(cmd != CmdBuild || out_type != OutTypeUnknown);
452426
453 init_all_targets();427 init_all_targets();
454428
...@@ -479,45 +453,22 @@ int main(int argc, char **argv) {...@@ -479,45 +453,22 @@ int main(int argc, char **argv) {
479 }453 }
480 }454 }
481455
482 bool need_name = (cmd == CmdBuild || cmd == CmdAsm || cmd == CmdLink || cmd == CmdParseH);456 bool need_name = (cmd == CmdBuild || cmd == CmdParseH);
483457
484 Buf in_file_buf = BUF_INIT;458 Buf *in_file_buf = nullptr;
485
486 Buf root_source_dir = BUF_INIT;
487 Buf root_source_code = BUF_INIT;
488 Buf root_source_name = BUF_INIT;
489459
490 Buf *buf_out_name = (cmd == CmdTest) ? buf_create_from_str("test") :460 Buf *buf_out_name = (cmd == CmdTest) ? buf_create_from_str("test") :
491 (out_name == nullptr) ? nullptr : buf_create_from_str(out_name);461 (out_name == nullptr) ? nullptr : buf_create_from_str(out_name);
492462
493 if (one_source_input) {463 if (in_file) {
494 buf_init_from_str(&in_file_buf, in_file);464 in_file_buf = buf_create_from_str(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, "");
503465
504 } else {466 if (need_name && buf_out_name == nullptr) {
505 os_path_split(&in_file_buf, &root_source_dir, &root_source_name);467 Buf basename = BUF_INIT;
506 if ((err = os_fetch_file_path(buf_create_from_str(in_file), &root_source_code))) {468 os_path_split(in_file_buf, nullptr, &basename);
507 fprintf(stderr, "unable to open '%s': %s\n", in_file, err_str(err));469 buf_out_name = buf_alloc();
508 return 1;470 os_path_extname(&basename, buf_out_name, nullptr);
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 }
516 }471 }
517 } else if (cmd == CmdLink) {
518 os_get_cwd(&root_source_dir);
519 } else {
520 zig_unreachable();
521 }472 }
522473
523 if (need_name && buf_out_name == nullptr) {474 if (need_name && buf_out_name == nullptr) {
...@@ -525,7 +476,10 @@ int main(int argc, char **argv) {...@@ -525,7 +476,10 @@ int main(int argc, char **argv) {
525 return usage(arg0);476 return usage(arg0);
526 }477 }
527478
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 codegen_set_lib_version(g, ver_major, ver_minor, ver_patch);483 codegen_set_lib_version(g, ver_major, ver_minor, ver_patch);
530 codegen_set_is_release(g, is_release_build);484 codegen_set_is_release(g, is_release_build);
531 codegen_set_is_test(g, cmd == CmdTest);485 codegen_set_is_test(g, cmd == CmdTest);
...@@ -536,14 +490,11 @@ int main(int argc, char **argv) {...@@ -536,14 +490,11 @@ int main(int argc, char **argv) {
536 codegen_set_clang_argv(g, clang_argv.items, clang_argv.length);490 codegen_set_clang_argv(g, clang_argv.items, clang_argv.length);
537 codegen_set_strip(g, strip);491 codegen_set_strip(g, strip);
538 codegen_set_is_static(g, is_static);492 codegen_set_is_static(g, is_static);
539 if (cmd == CmdAsm) {493 if (out_type != OutTypeUnknown) {
540 codegen_set_out_type(g, OutTypeObj);
541 } else if (out_type != OutTypeUnknown) {
542 codegen_set_out_type(g, out_type);494 codegen_set_out_type(g, out_type);
543 } else if (cmd == CmdTest) {495 } else if (cmd == CmdTest) {
544 codegen_set_out_type(g, OutTypeExe);496 codegen_set_out_type(g, OutTypeExe);
545 }497 }
546 codegen_set_out_name(g, buf_out_name);
547 if (libc_lib_dir)498 if (libc_lib_dir)
548 codegen_set_libc_lib_dir(g, buf_create_from_str(libc_lib_dir));499 codegen_set_libc_lib_dir(g, buf_create_from_str(libc_lib_dir));
549 if (libc_static_lib_dir)500 if (libc_static_lib_dir)
...@@ -598,33 +549,25 @@ int main(int argc, char **argv) {...@@ -598,33 +549,25 @@ int main(int argc, char **argv) {
598 }549 }
599550
600 if (cmd == CmdBuild) {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 for (size_t i = 0; i < objects.length; i += 1) {552 for (size_t i = 0; i < objects.length; i += 1) {
608 codegen_add_object(g, buf_create_from_str(objects.at(i)));553 codegen_add_object(g, buf_create_from_str(objects.at(i)));
609 }554 }
610 codegen_link(g, out_file);555 for (size_t i = 0; i < asm_files.length; i += 1) {
611 if (timing_info)556 codegen_add_assembly(g, buf_create_from_str(asm_files.at(i)));
612 codegen_print_timing_report(g, stderr);557 }
613 return EXIT_SUCCESS;558 codegen_build(g);
614 } else if (cmd == CmdAsm) {
615 codegen_add_root_assembly(g, &root_source_dir, &root_source_name, &root_source_code);
616 codegen_link(g, out_file);559 codegen_link(g, out_file);
617 if (timing_info)560 if (timing_info)
618 codegen_print_timing_report(g, stderr);561 codegen_print_timing_report(g, stderr);
619 return EXIT_SUCCESS;562 return EXIT_SUCCESS;
620 } else if (cmd == CmdParseH) {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 ast_render_decls(g, stdout, 4, g->root_import);565 ast_render_decls(g, stdout, 4, g->root_import);
623 if (timing_info)566 if (timing_info)
624 codegen_print_timing_report(g, stderr);567 codegen_print_timing_report(g, stderr);
625 return EXIT_SUCCESS;568 return EXIT_SUCCESS;
626 } else if (cmd == CmdTest) {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 codegen_link(g, "./test");571 codegen_link(g, "./test");
629 ZigList<const char *> args = {0};572 ZigList<const char *> args = {0};
630 Termination term;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,24 +146,28 @@ void os_path_split(Buf *full_path, Buf *out_dirname, Buf *out_basename) {
146146
147void os_path_extname(Buf *full_path, Buf *out_basename, Buf *out_extname) {147void os_path_extname(Buf *full_path, Buf *out_basename, Buf *out_extname) {
148 if (buf_len(full_path) == 0) {148 if (buf_len(full_path) == 0) {
149 buf_init_from_str(out_basename, "");149 if (out_basename) buf_init_from_str(out_basename, "");
150 buf_init_from_str(out_extname, "");150 if (out_extname) buf_init_from_str(out_extname, "");
151 return;151 return;
152 }152 }
153 size_t i = buf_len(full_path) - 1;153 size_t i = buf_len(full_path) - 1;
154 while (true) {154 while (true) {
155 if (buf_ptr(full_path)[i] == '.') {155 if (buf_ptr(full_path)[i] == '.') {
156 buf_resize(out_basename, 0);156 if (out_basename) {
157 buf_append_mem(out_basename, buf_ptr(full_path), i);157 buf_resize(out_basename, 0);
158 buf_append_mem(out_basename, buf_ptr(full_path), i);
159 }
158160
159 buf_resize(out_extname, 0);161 if (out_extname) {
160 buf_append_mem(out_extname, buf_ptr(full_path) + i, buf_len(full_path) - i);162 buf_resize(out_extname, 0);
163 buf_append_mem(out_extname, buf_ptr(full_path) + i, buf_len(full_path) - i);
164 }
161 return;165 return;
162 }166 }
163167
164 if (i == 0) {168 if (i == 0) {
165 buf_init_from_buf(out_basename, full_path);169 if (out_basename) buf_init_from_buf(out_basename, full_path);
166 buf_init_from_str(out_extname, "");170 if (out_extname) buf_init_from_str(out_extname, "");
167 return;171 return;
168 }172 }
169 i -= 1;173 i -= 1;
std/build.zig+109-496
...@@ -120,28 +120,22 @@ pub const Builder = struct {...@@ -120,28 +120,22 @@ pub const Builder = struct {
120 self.lib_dir = %%os.path.join(self.allocator, self.prefix, "lib");120 self.lib_dir = %%os.path.join(self.allocator, self.prefix, "lib");
121 }121 }
122122
123 pub fn addExecutable(self: &Builder, name: []const u8, root_src: []const u8) -> &LibOrExeStep {123 pub fn addExecutable(self: &Builder, name: []const u8, root_src: ?[]const u8) -> &LibExeObjStep {
124 const exe = %%self.allocator.create(LibOrExeStep);124 return LibExeObjStep.createExecutable(self, name, root_src);
125 *exe = LibOrExeStep.initExecutable(self, name, root_src);
126 return exe;
127 }125 }
128126
129 pub fn addObject(self: &Builder, name: []const u8, root_src: []const u8) -> &ObjectStep {127 pub fn addObject(self: &Builder, name: []const u8, root_src: []const u8) -> &LibExeObjStep {
130 const obj_step = %%self.allocator.create(ObjectStep);128 return LibExeObjStep.createObject(self, name, root_src);
131 *obj_step = ObjectStep.init(self, name, root_src);
132 return obj_step;
133 }129 }
134130
135 pub fn addSharedLibrary(self: &Builder, name: []const u8, root_src: []const u8, ver: &const Version) -> &LibOrExeStep {131 pub fn addSharedLibrary(self: &Builder, name: []const u8, root_src: ?[]const u8,
136 const lib_step = %%self.allocator.create(LibOrExeStep);132 ver: &const Version) -> &LibExeObjStep
137 *lib_step = LibOrExeStep.initSharedLibrary(self, name, root_src, ver);133 {
138 return lib_step;134 return LibExeObjStep.createSharedLibrary(self, name, root_src, ver);
139 }135 }
140136
141 pub fn addStaticLibrary(self: &Builder, name: []const u8, root_src: []const u8) -> &LibOrExeStep {137 pub fn addStaticLibrary(self: &Builder, name: []const u8, root_src: ?[]const u8) -> &LibExeObjStep {
142 const lib_step = %%self.allocator.create(LibOrExeStep);138 return LibExeObjStep.createStaticLibrary(self, name, root_src);
143 *lib_step = LibOrExeStep.initStaticLibrary(self, name, root_src);
144 return lib_step;
145 }139 }
146140
147 pub fn addTest(self: &Builder, root_src: []const u8) -> &TestStep {141 pub fn addTest(self: &Builder, root_src: []const u8) -> &TestStep {
...@@ -150,28 +144,10 @@ pub const Builder = struct {...@@ -150,28 +144,10 @@ pub const Builder = struct {
150 return test_step;144 return test_step;
151 }145 }
152146
153 pub fn addAssemble(self: &Builder, name: []const u8, src: []const u8) -> &AsmStep {147 pub fn addAssemble(self: &Builder, name: []const u8, src: []const u8) -> &LibExeObjStep {
154 const asm_step = %%self.allocator.create(AsmStep);148 const obj_step = LibExeObjStep.createObject(self, name, null);
155 *asm_step = AsmStep.init(self, name, src);149 obj_step.addAssemblyFile(src);
156 return asm_step;150 return obj_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;
175 }151 }
176152
177 pub fn addCStaticLibrary(self: &Builder, name: []const u8) -> &CLibrary {153 pub fn addCStaticLibrary(self: &Builder, name: []const u8) -> &CLibrary {
...@@ -635,10 +611,10 @@ const LinkerScript = enum {...@@ -635,10 +611,10 @@ const LinkerScript = enum {
635 Path: []const u8,611 Path: []const u8,
636};612};
637613
638pub const LibOrExeStep = struct {614pub const LibExeObjStep = struct {
639 step: Step,615 step: Step,
640 builder: &Builder,616 builder: &Builder,
641 root_src: []const u8,617 root_src: ?[]const u8,
642 name: []const u8,618 name: []const u8,
643 target: Target,619 target: Target,
644 linker_script: LinkerScript,620 linker_script: LinkerScript,
...@@ -652,30 +628,45 @@ pub const LibOrExeStep = struct {...@@ -652,30 +628,45 @@ pub const LibOrExeStep = struct {
652 out_filename: []const u8,628 out_filename: []const u8,
653 out_filename_major_only: []const u8,629 out_filename_major_only: []const u8,
654 out_filename_name_only: []const u8,630 out_filename_name_only: []const u8,
631 object_files: List([]const u8),
632 assembly_files: List([]const u8),
655633
656 const Kind = enum {634 const Kind = enum {
657 Exe,635 Exe,
658 Lib,636 Lib,
637 Obj,
659 };638 };
660639
661 pub fn initExecutable(builder: &Builder, name: []const u8, root_src: []const u8) -> LibOrExeStep {640 pub fn createSharedLibrary(builder: &Builder, name: []const u8, root_src: ?[]const u8,
662 return initExtraArgs(builder, name, root_src, Kind.Exe, false, builder.version(0, 0, 0));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 }
664647
665 pub fn initSharedLibrary(builder: &Builder, name: []const u8, root_src: []const u8,648 pub fn createStaticLibrary(builder: &Builder, name: []const u8, root_src: ?[]const u8) -> &LibExeObjStep {
666 ver: &const Version) -> LibOrExeStep649 const self = %%builder.allocator.create(LibExeObjStep);
667 {650 *self = initExtraArgs(builder, name, root_src, Kind.Lib, true, builder.version(0, 0, 0));
668 return initExtraArgs(builder, name, root_src, Kind.Lib, false, ver);651 return self;
669 }652 }
670653
671 pub fn initStaticLibrary(builder: &Builder, name: []const u8, root_src: []const u8) -> LibOrExeStep {654 pub fn createObject(builder: &Builder, name: []const u8, root_src: []const u8) -> &LibExeObjStep {
672 return initExtraArgs(builder, name, root_src, Kind.Lib, true, builder.version(0, 0, 0));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 }
674659
675 fn initExtraArgs(builder: &Builder, name: []const u8, root_src: []const u8, kind: Kind,660 pub fn createExecutable(builder: &Builder, name: []const u8, root_src: ?[]const u8) -> &LibExeObjStep {
676 static: bool, ver: &const Version) -> LibOrExeStep661 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 .builder = builder,670 .builder = builder,
680 .verbose = false,671 .verbose = false,
681 .release = false,672 .release = false,
...@@ -692,13 +683,18 @@ pub const LibOrExeStep = struct {...@@ -692,13 +683,18 @@ pub const LibOrExeStep = struct {
692 .out_filename = undefined,683 .out_filename = undefined,
693 .out_filename_major_only = undefined,684 .out_filename_major_only = undefined,
694 .out_filename_name_only = undefined,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 self.computeOutFileNames();689 self.computeOutFileNames();
697 return self;690 return self;
698 }691 }
699692
700 fn computeOutFileNames(self: &LibOrExeStep) {693 fn computeOutFileNames(self: &LibExeObjStep) {
701 switch (self.kind) {694 switch (self.kind) {
695 Kind.Obj => {
696 self.out_filename = self.builder.fmt("{}{}", self.name, self.target.oFileExt());
697 },
702 Kind.Exe => {698 Kind.Exe => {
703 self.out_filename = self.builder.fmt("{}{}", self.name, self.target.exeFileExt());699 self.out_filename = self.builder.fmt("{}{}", self.name, self.target.exeFileExt());
704 },700 },
...@@ -715,7 +711,7 @@ pub const LibOrExeStep = struct {...@@ -715,7 +711,7 @@ pub const LibOrExeStep = struct {
715 }711 }
716 }712 }
717713
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 self.target = Target.Cross {715 self.target = Target.Cross {
720 CrossTarget {716 CrossTarget {
721 .arch = target_arch,717 .arch = target_arch,
...@@ -723,414 +719,49 @@ pub const LibOrExeStep = struct {...@@ -723,414 +719,49 @@ pub const LibOrExeStep = struct {
723 .environ = target_environ,719 .environ = target_environ,
724 }720 }
725 };721 };
722 self.computeOutFileNames();
726 }723 }
727724
728 /// LibOrExeStep keeps a reference to script for its lifetime or until this function725 /// LibExeObjStep keeps a reference to script for its lifetime or until this function
729 /// is called again.726 /// is called again.
730 pub fn setLinkerScriptContents(self: &LibOrExeStep, script: []const u8) {727 pub fn setLinkerScriptContents(self: &LibExeObjStep, script: []const u8) {
731 self.linker_script = LinkerScript.Embed { script };728 self.linker_script = LinkerScript.Embed { script };
732 }729 }
733730
734 pub fn setLinkerScriptPath(self: &LibOrExeStep, path: []const u8) {731 pub fn setLinkerScriptPath(self: &LibExeObjStep, path: []const u8) {
735 self.linker_script = LinkerScript.Path { path };732 self.linker_script = LinkerScript.Path { path };
736 }733 }
737734
738 pub fn linkSystemLibrary(self: &LibOrExeStep, name: []const u8) {735 pub fn linkSystemLibrary(self: &LibExeObjStep, name: []const u8) {
739 %%self.link_libs.put(name);736 %%self.link_libs.put(name);
740 }737 }
741738
742 pub fn setVerbose(self: &LibOrExeStep, value: bool) {739 pub fn setVerbose(self: &LibExeObjStep, 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
859pub 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
963pub 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) {
998 self.verbose = value;740 self.verbose = value;
999 }741 }
1000742
1001 pub fn setRelease(self: &AsmStep, value: bool) {743 pub fn setRelease(self: &LibExeObjStep, value: bool) {
1002 self.release = value;744 self.release = value;
1003 }745 }
1004746
1005 pub fn setOutputPath(self: &AsmStep, value: []const u8) {747 pub fn setOutputPath(self: &LibExeObjStep, value: []const u8) {
1006 self.output_path = value;748 self.output_path = value;
1007 }749 }
1008750
1009 fn make(step: &Step) -> %void {751 pub fn addAssemblyFile(self: &LibExeObjStep, path: []const u8) {
1010 const self = @fieldParentPtr(AsmStep, "step", step);752 %%self.assembly_files.append(path);
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());
1050 }753 }
1051};
1052754
1053pub const LinkStep = struct {755 pub fn addObjectFile(self: &LibExeObjStep, path: []const u8) {
1054 step: Step,756 assert(self.kind != Kind.Obj);
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 };
1075757
1076 pub fn initExecutable(builder: &Builder, name: []const u8) -> LinkStep {758 %%self.object_files.append(path);
1077 return init(builder, name, OutType.Exe, builder.version(0, 0, 0), false)
1078 }759 }
1079760
1080 pub fn initSharedLibrary(builder: &Builder, name: []const u8, version: &const Version) -> LinkStep {761 pub fn addObject(self: &LibExeObjStep, obj: &LibExeObjStep) {
1081 return init(builder, name, OutType.Lib, version, false)762 assert(obj.kind == Kind.Obj);
1082 }763 assert(self.kind != Kind.Obj);
1083764
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 self.step.dependOn(&obj.step);765 self.step.dependOn(&obj.step);
1135766
1136 const path_to_obj = test (obj.output_path) |explicit_out_path| {767 const path_to_obj = test (obj.output_path) |explicit_out_path| {
...@@ -1143,61 +774,11 @@ pub const LinkStep = struct {...@@ -1143,61 +774,11 @@ pub const LinkStep = struct {
1143 %%self.object_files.append(path_to_obj);774 %%self.object_files.append(path_to_obj);
1144 }775 }
1145776
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 fn make(step: &Step) -> %void {777 fn make(step: &Step) -> %void {
1197 const self = @fieldParentPtr(LinkStep, "step", step);778 const self = @fieldParentPtr(LibExeObjStep, "step", step);
1198 const builder = self.builder;779 const builder = self.builder;
1199780
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 %%io.stderr.printf("{}: linker needs 1 or more objects to link\n", step.name);782 %%io.stderr.printf("{}: linker needs 1 or more objects to link\n", step.name);
1202 return error.NeedAnObject;783 return error.NeedAnObject;
1203 }784 }
...@@ -1205,16 +786,27 @@ pub const LinkStep = struct {...@@ -1205,16 +786,27 @@ pub const LinkStep = struct {
1205 var zig_args = List([]const u8).init(builder.allocator);786 var zig_args = List([]const u8).init(builder.allocator);
1206 defer zig_args.deinit();787 defer zig_args.deinit();
1207788
1208 const cmd = switch (self.out_type) {789 const cmd = switch (self.kind) {
1209 OutType.Exe => "link_exe",790 Kind.Lib => "build_lib",
1210 OutType.Lib => "link_lib",791 Kind.Exe => "build_exe",
792 Kind.Obj => "build_obj",
1211 };793 };
1212 %%zig_args.append(cmd);794 %%zig_args.append(cmd);
1213795
796 test (self.root_src) |root_src| {
797 %%zig_args.append(builder.pathFromRoot(root_src));
798 }
799
1214 for (self.object_files.toSliceConst()) |object_file| {800 for (self.object_files.toSliceConst()) |object_file| {
801 %%zig_args.append("--object");
1215 %%zig_args.append(builder.pathFromRoot(object_file));802 %%zig_args.append(builder.pathFromRoot(object_file));
1216 }803 }
1217804
805 for (self.assembly_files.toSliceConst()) |asm_file| {
806 %%zig_args.append("--assembly");
807 %%zig_args.append(builder.pathFromRoot(asm_file));
808 }
809
1218 if (self.verbose) {810 if (self.verbose) {
1219 %%zig_args.append("--verbose");811 %%zig_args.append("--verbose");
1220 }812 }
...@@ -1223,10 +815,6 @@ pub const LinkStep = struct {...@@ -1223,10 +815,6 @@ pub const LinkStep = struct {
1223 %%zig_args.append("--release");815 %%zig_args.append("--release");
1224 }816 }
1225817
1226 if (self.static) {
1227 %%zig_args.append("--static");
1228 }
1229
1230 test (self.output_path) |output_path| {818 test (self.output_path) |output_path| {
1231 %%zig_args.append("--output");819 %%zig_args.append("--output");
1232 %%zig_args.append(builder.pathFromRoot(output_path));820 %%zig_args.append(builder.pathFromRoot(output_path));
...@@ -1235,6 +823,17 @@ pub const LinkStep = struct {...@@ -1235,6 +823,17 @@ pub const LinkStep = struct {
1235 %%zig_args.append("--name");823 %%zig_args.append("--name");
1236 %%zig_args.append(self.name);824 %%zig_args.append(self.name);
1237825
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 switch (self.target) {837 switch (self.target) {
1239 Target.Native => {},838 Target.Native => {},
1240 Target.Cross => |cross_target| {839 Target.Cross => |cross_target| {
...@@ -1273,6 +872,11 @@ pub const LinkStep = struct {...@@ -1273,6 +872,11 @@ pub const LinkStep = struct {
1273 }872 }
1274 }873 }
1275874
875 for (builder.include_paths.toSliceConst()) |include_path| {
876 %%zig_args.append("-isystem");
877 %%zig_args.append(include_path);
878 }
879
1276 for (builder.rpaths.toSliceConst()) |rpath| {880 for (builder.rpaths.toSliceConst()) |rpath| {
1277 %%zig_args.append("-rpath");881 %%zig_args.append("-rpath");
1278 %%zig_args.append(rpath);882 %%zig_args.append(rpath);
...@@ -1284,6 +888,13 @@ pub const LinkStep = struct {...@@ -1284,6 +888,13 @@ pub const LinkStep = struct {
1284 }888 }
1285889
1286 %%builder.spawnChild(builder.zig_exe, zig_args.toSliceConst());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};
1289900
...@@ -1592,15 +1203,17 @@ pub const CExecutable = struct {...@@ -1592,15 +1203,17 @@ pub const CExecutable = struct {
1592 %%self.full_path_libs.append(clib.out_filename);1203 %%self.full_path_libs.append(clib.out_filename);
1593 }1204 }
15941205
1595 pub fn linkLibrary(self: &CExecutable, lib: &LibOrExeStep) {1206 pub fn linkLibrary(self: &CExecutable, lib: &LibExeObjStep) {
1596 assert(lib.kind == LibOrExeStep.Kind.Lib);1207 assert(lib.kind == LibExeObjStep.Kind.Lib);
1597 self.step.dependOn(&lib.step);1208 self.step.dependOn(&lib.step);
1598 %%self.full_path_libs.append(lib.out_filename);1209 %%self.full_path_libs.append(lib.out_filename);
1599 // TODO should be some kind of isolated directory that only has this header in it1210 // TODO should be some kind of isolated directory that only has this header in it
1600 %%self.include_dirs.append(self.builder.out_dir);1211 %%self.include_dirs.append(self.builder.out_dir);
1601 }1212 }
16021213
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 self.step.dependOn(&obj.step);1217 self.step.dependOn(&obj.step);
16051218
1606 // TODO make it so we always know where this will be1219 // 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,7 +90,11 @@ pub fn writeStackTrace(out_stream: &io.OutStream, allocator: &mem.Allocator, tty
90 // at compile time. I'll call it issue #31390 // at compile time. I'll call it issue #313
91 const ptr_hex = if (@sizeOf(usize) == 4) "0x{x8}" else "0x{x16}";91 const ptr_hex = if (@sizeOf(usize) == 4) "0x{x8}" else "0x{x16}";
9292
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 const compile_unit_name = %return compile_unit.die.getAttrString(st, DW.AT_name);98 const compile_unit_name = %return compile_unit.die.getAttrString(st, DW.AT_name);
95 try (getLineNumberInfo(st, compile_unit, usize(return_address) - 1)) |line_info| {99 try (getLineNumberInfo(st, compile_unit, usize(return_address) - 1)) |line_info| {
96 defer line_info.deinit();100 defer line_info.deinit();
test/cases/cast.zig+9
...@@ -150,3 +150,12 @@ fn peerTypeEmptyArrayAndSlice(a: bool, slice: []const u8) -> []const u8 {...@@ -150,3 +150,12 @@ fn peerTypeEmptyArrayAndSlice(a: bool, slice: []const u8) -> []const u8 {
150150
151 return slice[0...1];151 return slice[0...1];
152}152}
153
154test "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
159fn castToMaybeSlice() -> ?[]const u8 {
160 return "hi";
161}
test/tests.zig+4-6
...@@ -355,18 +355,16 @@ pub const CompareOutputContext = struct {...@@ -355,18 +355,16 @@ pub const CompareOutputContext = struct {
355 return;355 return;
356 }356 }
357357
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);
359361
360 for (case.sources.toSliceConst()) |src_file| {362 for (case.sources.toSliceConst()) |src_file| {
361 const expanded_src_path = %%os.path.join(b.allocator, "test_artifacts", src_file.filename);363 const expanded_src_path = %%os.path.join(b.allocator, "test_artifacts", src_file.filename);
362 const write_src = b.addWriteFile(expanded_src_path, src_file.source);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 }
365367
366 const exe = b.addLinkExecutable("test");
367 exe.addAssembly(assembly);
368 exe.setOutputPath(exe_path);
369
370 const run_and_cmp_output = RunCompareOutputStep.create(self, exe_path, annotated_case_name,368 const run_and_cmp_output = RunCompareOutputStep.create(self, exe_path, annotated_case_name,
371 case.expected_output);369 case.expected_output);
372 run_and_cmp_output.step.dependOn(&exe.step);370 run_and_cmp_output.step.dependOn(&exe.step);