From 7e11ef79d67d000675e90ddf93fdb78d71cc695d Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 27 Apr 2017 16:15:41 -0400 Subject: [PATCH] zig test no longer requires a separate test_runner.o file See #298 --- doc/style.md | 3 + src/all_types.hpp | 4 +- src/analyze.cpp | 84 ++++++++++++++++-- src/analyze.hpp | 4 + src/codegen.cpp | 164 +++++++++++++++--------------------- src/ir.cpp | 2 +- src/link.cpp | 15 ---- src/main.cpp | 6 +- std/index.zig | 21 +++++ std/special/test_runner.zig | 14 +-- 10 files changed, 185 insertions(+), 132 deletions(-) diff --git a/doc/style.md b/doc/style.md index 058b1a405e..a5a3ef5dec 100644 --- a/doc/style.md +++ b/doc/style.md @@ -29,6 +29,9 @@ rules in written English are subject to naming conventions just like any other word. Even acronyms that are only 2 letters long are subject to these conventions. +These are general rules of thumb; if it makes sense to do something different, +do what makes sense. + Examples: ```zig diff --git a/src/all_types.hpp b/src/all_types.hpp index c701529bf9..29801307f9 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -1095,6 +1095,7 @@ struct ImportTableEntry { ScopeDecls *decls_scope; AstNode *c_import_node; bool any_imports_failed; + bool scanned; ZigList use_decls; }; @@ -1398,6 +1399,7 @@ struct CodeGen { PackageTableEntry *root_package; PackageTableEntry *std_package; PackageTableEntry *zigrt_package; + PackageTableEntry *test_runner_package; Buf *root_out_name; bool windows_subsystem_windows; bool windows_subsystem_console; @@ -1451,7 +1453,7 @@ struct CodeGen { size_t clang_argv_len; ZigList lib_dirs; - uint32_t test_fn_count; + ZigList test_fns; TypeTableEntry *test_fn_type; bool each_lib_rpath; diff --git a/src/analyze.cpp b/src/analyze.cpp index 77edddb31c..bf432adff8 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -1413,6 +1413,71 @@ static bool type_allowed_in_packed_struct(TypeTableEntry *type_entry) { zig_unreachable(); } +TypeTableEntry *get_struct_type(CodeGen *g, const char *type_name, const char *field_names[], + TypeTableEntry *field_types[], size_t field_count) +{ + TypeTableEntry *struct_type = new_type_table_entry(TypeTableEntryIdStruct); + + buf_init_from_str(&struct_type->name, type_name); + + struct_type->data.structure.src_field_count = field_count; + struct_type->data.structure.gen_field_count = field_count; + struct_type->data.structure.zero_bits_known = true; + struct_type->data.structure.complete = true; + struct_type->data.structure.fields = allocate(field_count); + + ZigLLVMDIType **di_element_types = allocate(field_count); + LLVMTypeRef *element_types = allocate(field_count); + for (size_t i = 0; i < field_count; i += 1) { + element_types[i] = field_types[i]->type_ref; + + TypeStructField *field = &struct_type->data.structure.fields[i]; + field->name = buf_create_from_str(field_names[i]); + field->type_entry = field_types[i]; + field->src_index = i; + field->gen_index = i; + } + + struct_type->type_ref = LLVMStructCreateNamed(LLVMGetGlobalContext(), type_name); + LLVMStructSetBody(struct_type->type_ref, element_types, field_count, false); + + struct_type->di_type = ZigLLVMCreateReplaceableCompositeType(g->dbuilder, + ZigLLVMTag_DW_structure_type(), type_name, + ZigLLVMCompileUnitToScope(g->compile_unit), nullptr, 0); + + for (size_t i = 0; i < field_count; i += 1) { + TypeStructField *type_struct_field = &struct_type->data.structure.fields[i]; + TypeTableEntry *field_type = type_struct_field->type_entry; + uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, field_type->type_ref); + uint64_t debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, field_type->type_ref); + uint64_t debug_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, struct_type->type_ref, i); + di_element_types[i] = ZigLLVMCreateDebugMemberType(g->dbuilder, + ZigLLVMTypeToScope(struct_type->di_type), buf_ptr(type_struct_field->name), + nullptr, 0, + debug_size_in_bits, + debug_align_in_bits, + debug_offset_in_bits, + 0, field_type->di_type); + + assert(di_element_types[i]); + } + + uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, struct_type->type_ref); + uint64_t debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, struct_type->type_ref); + ZigLLVMDIType *replacement_di_type = ZigLLVMCreateDebugStructType(g->dbuilder, + ZigLLVMCompileUnitToScope(g->compile_unit), + type_name, nullptr, 0, + debug_size_in_bits, + debug_align_in_bits, + 0, + nullptr, di_element_types, field_count, 0, nullptr, ""); + + ZigLLVMReplaceTemporary(g->dbuilder, struct_type->di_type, replacement_di_type); + struct_type->di_type = replacement_di_type; + + return struct_type; +} + static void resolve_struct_type(CodeGen *g, TypeTableEntry *struct_type) { // if you change the logic of this function likely you must make a similar change in // parseh.cpp @@ -1823,7 +1888,7 @@ static void typecheck_panic_fn(CodeGen *g, FnTableEntry *panic_fn) { } } -static TypeTableEntry *get_test_fn_type(CodeGen *g) { +TypeTableEntry *get_test_fn_type(CodeGen *g) { if (g->test_fn_type) return g->test_fn_type; @@ -1875,7 +1940,10 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) { if (fn_def_node) g->fn_defs.append(fn_table_entry); - if (g->have_pub_main && import == g->root_import && scope_is_root_decls(tld_fn->base.parent_scope)) { + if (g->have_pub_main && scope_is_root_decls(tld_fn->base.parent_scope) && + ((!g->is_test_build && import == g->root_import) || + (g->is_test_build && import == g->test_runner_import))) + { if (buf_eql_str(&fn_table_entry->symbol_name, "main")) { g->main_fn = fn_table_entry; @@ -1909,10 +1977,10 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) { fn_table_entry->type_entry = get_test_fn_type(g); fn_table_entry->body_node = source_node->data.test_decl.body; fn_table_entry->is_test = true; - g->test_fn_count += 1; g->fn_protos.append(fn_table_entry); g->fn_defs.append(fn_table_entry); + g->test_fns.append(fn_table_entry); } else { zig_unreachable(); @@ -1926,7 +1994,7 @@ static void resolve_decl_comptime(CodeGen *g, TldCompTime *tld_comptime) { } static void add_top_level_decl(CodeGen *g, ScopeDecls *decls_scope, Tld *tld) { - if (tld->visib_mod == VisibModExport || (tld->id == TldIdVar && g->is_test_build)) { + if (tld->visib_mod == VisibModExport) { g->resolve_queue.append(tld); } @@ -2932,11 +3000,17 @@ ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package, Buf *a return import_entry; } +void scan_import(CodeGen *g, ImportTableEntry *import) { + if (!import->scanned) { + import->scanned = true; + scan_decls(g, import->decls_scope, import->root); + } +} void semantic_analyze(CodeGen *g) { for (; g->import_queue_index < g->import_queue.length; g->import_queue_index += 1) { ImportTableEntry *import = g->import_queue.at(g->import_queue_index); - scan_decls(g, import->decls_scope, import->root); + scan_import(g, import); } for (; g->use_queue_index < g->use_queue.length; g->use_queue_index += 1) { diff --git a/src/analyze.hpp b/src/analyze.hpp index cbcab31e62..785b8a697a 100644 --- a/src/analyze.hpp +++ b/src/analyze.hpp @@ -33,6 +33,9 @@ TypeTableEntry *get_smallest_unsigned_int_type(CodeGen *g, uint64_t x); TypeTableEntry *get_error_type(CodeGen *g, TypeTableEntry *child_type); TypeTableEntry *get_bound_fn_type(CodeGen *g, FnTableEntry *fn_entry); TypeTableEntry *get_opaque_type(CodeGen *g, Scope *scope, AstNode *source_node, const char *name); +TypeTableEntry *get_struct_type(CodeGen *g, const char *type_name, const char *field_names[], + TypeTableEntry *field_types[], size_t field_count); +TypeTableEntry *get_test_fn_type(CodeGen *g); bool handle_is_ptr(TypeTableEntry *type_entry); void find_libc_include_path(CodeGen *g); void find_libc_lib_path(CodeGen *g); @@ -60,6 +63,7 @@ ScopeDecls *get_container_scope(TypeTableEntry *type_entry); TypeEnumField *find_enum_type_field(TypeTableEntry *enum_type, Buf *name); bool is_container_ref(TypeTableEntry *type_entry); void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node); +void scan_import(CodeGen *g, ImportTableEntry *import); void preview_use_decl(CodeGen *g, AstNode *node); void resolve_use_decl(CodeGen *g, AstNode *node); FnTableEntry *scope_fn_entry(Scope *scope); diff --git a/src/codegen.cpp b/src/codegen.cpp index d779eb158e..a80610b731 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -2906,7 +2906,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, case IrInstructionIdDeclRef: case IrInstructionIdSwitchVar: case IrInstructionIdSetFnRefInline: - case IrInstructionIdOffsetOf: + case IrInstructionIdOffsetOf: zig_unreachable(); case IrInstructionIdReturn: return ir_render_return(g, executable, (IrInstructionReturn *)instruction); @@ -3087,7 +3087,7 @@ static LLVMValueRef gen_const_ptr_struct_recursive(CodeGen *g, ConstExprValue *s return LLVMConstInBoundsGEP(base_ptr, indices, 2); } -static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, ConstExprValue *const_val) { +static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, ConstExprValue *const_val) { switch (const_val->special) { case ConstValSpecialRuntime: zig_unreachable(); @@ -3501,50 +3501,6 @@ static void delete_unused_builtin_fns(CodeGen *g) { } } -static bool should_skip_fn_codegen(CodeGen *g, FnTableEntry *fn_entry) { - if (g->is_test_build) { - if (fn_entry->is_test) { - return false; - } - if (fn_entry == g->main_fn) { - return true; - } - return false; - } - - if (fn_entry->is_test) { - return true; - } - - return false; -} - -static LLVMValueRef gen_test_fn_val(CodeGen *g, FnTableEntry *fn_entry) { - // Must match TestFn struct from test_runner.zig - Buf *fn_name = &fn_entry->symbol_name; - LLVMValueRef str_init = LLVMConstString(buf_ptr(fn_name), (unsigned)buf_len(fn_name), true); - LLVMValueRef str_global_val = LLVMAddGlobal(g->module, LLVMTypeOf(str_init), ""); - LLVMSetInitializer(str_global_val, str_init); - LLVMSetLinkage(str_global_val, LLVMPrivateLinkage); - LLVMSetGlobalConstant(str_global_val, true); - LLVMSetUnnamedAddr(str_global_val, true); - - LLVMValueRef len_val = LLVMConstInt(g->builtin_types.entry_usize->type_ref, buf_len(fn_name), false); - - LLVMTypeRef ptr_type = LLVMPointerType(g->builtin_types.entry_u8->type_ref, 0); - LLVMValueRef name_fields[] = { - LLVMConstBitCast(str_global_val, ptr_type), - len_val, - }; - - LLVMValueRef name_val = LLVMConstStruct(name_fields, 2, false); - LLVMValueRef fields[] = { - name_val, - fn_llvm_value(g, fn_entry), - }; - return LLVMConstStruct(fields, 2, false); -} - static void generate_error_name_table(CodeGen *g) { if (g->err_name_table != nullptr || !g->generate_error_name_table || g->error_decls.length == 1) { return; @@ -3740,17 +3696,9 @@ static void do_code_gen(CodeGen *g) { var->value_ref = global_value; } - LLVMValueRef *test_fn_vals = nullptr; - uint32_t next_test_index = 0; - if (g->is_test_build) { - test_fn_vals = allocate(g->test_fn_count); - } - // Generate function prototypes for (size_t fn_proto_i = 0; fn_proto_i < g->fn_protos.length; fn_proto_i += 1) { FnTableEntry *fn_table_entry = g->fn_protos.at(fn_proto_i); - if (should_skip_fn_codegen(g, fn_table_entry)) - continue; TypeTableEntry *fn_type = fn_table_entry->type_entry; FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id; @@ -3797,51 +3745,11 @@ static void do_code_gen(CodeGen *g) { addLLVMArgAttr(fn_val, (unsigned)gen_index, "byval"); } } - - if (fn_table_entry->is_test) { - test_fn_vals[next_test_index] = gen_test_fn_val(g, fn_table_entry); - next_test_index += 1; - } - } - - // Generate the list of test function pointers. - if (g->is_test_build) { - if (g->test_fn_count == 0) { - fprintf(stderr, "No tests to run.\n"); - exit(0); - } - assert(g->test_fn_count > 0); - assert(next_test_index == g->test_fn_count); - - LLVMValueRef test_fn_array_init = LLVMConstArray(LLVMTypeOf(test_fn_vals[0]), - test_fn_vals, g->test_fn_count); - LLVMValueRef test_fn_array_val = LLVMAddGlobal(g->module, - LLVMTypeOf(test_fn_array_init), ""); - LLVMSetInitializer(test_fn_array_val, test_fn_array_init); - LLVMSetLinkage(test_fn_array_val, LLVMInternalLinkage); - LLVMSetGlobalConstant(test_fn_array_val, true); - LLVMSetUnnamedAddr(test_fn_array_val, true); - - LLVMValueRef len_val = LLVMConstInt(g->builtin_types.entry_usize->type_ref, g->test_fn_count, false); - LLVMTypeRef ptr_type = LLVMPointerType(LLVMTypeOf(test_fn_vals[0]), 0); - LLVMValueRef fields[] = { - LLVMConstBitCast(test_fn_array_val, ptr_type), - len_val, - }; - LLVMValueRef test_fn_slice_init = LLVMConstStruct(fields, 2, false); - LLVMValueRef test_fn_slice_val = LLVMAddGlobal(g->module, - LLVMTypeOf(test_fn_slice_init), "zig_test_fn_list"); - LLVMSetInitializer(test_fn_slice_val, test_fn_slice_init); - LLVMSetLinkage(test_fn_slice_val, LLVMExternalLinkage); - LLVMSetGlobalConstant(test_fn_slice_val, true); - LLVMSetUnnamedAddr(test_fn_slice_val, true); } // Generate function definitions. for (size_t fn_i = 0; fn_i < g->fn_defs.length; fn_i += 1) { FnTableEntry *fn_table_entry = g->fn_defs.at(fn_i); - if (should_skip_fn_codegen(g, fn_table_entry)) - continue; LLVMValueRef fn = fn_llvm_value(g, fn_table_entry); g->cur_fn = fn_table_entry; @@ -4737,10 +4645,16 @@ static ImportTableEntry *add_special_code(CodeGen *g, PackageTableEntry *package return add_source_file(g, package, abs_full_path, import_code); } -static PackageTableEntry *create_bootstrap_pkg(CodeGen *g) { +static PackageTableEntry *create_bootstrap_pkg(CodeGen *g, PackageTableEntry *pkg_with_main) { PackageTableEntry *package = new_package(buf_ptr(g->zig_std_special_dir), ""); package->package_table.put(buf_create_from_str("std"), g->std_package); - package->package_table.put(buf_create_from_str("@root"), g->root_package); + package->package_table.put(buf_create_from_str("@root"), pkg_with_main); + return package; +} + +static PackageTableEntry *create_test_runner_pkg(CodeGen *g) { + PackageTableEntry *package = new_package(buf_ptr(g->zig_std_special_dir), "test_runner.zig"); + package->package_table.put(buf_create_from_str("std"), g->std_package); return package; } @@ -4751,6 +4665,54 @@ static PackageTableEntry *create_zigrt_pkg(CodeGen *g) { return package; } +static void create_test_compile_var_and_add_test_runner(CodeGen *g) { + assert(g->is_test_build); + + if (g->test_fns.length == 0) { + fprintf(stderr, "No tests to run.\n"); + exit(0); + } + + TypeTableEntry *str_type = get_slice_type(g, g->builtin_types.entry_u8, true); + TypeTableEntry *fn_type = get_test_fn_type(g); + + const char *field_names[] = { "name", "func", }; + TypeTableEntry *field_types[] = { str_type, fn_type, }; + TypeTableEntry *struct_type = get_struct_type(g, "ZigTestFn", field_names, field_types, 2); + + ConstExprValue *test_fn_array = allocate(1); + test_fn_array->type = get_array_type(g, struct_type, g->test_fns.length); + test_fn_array->special = ConstValSpecialStatic; + test_fn_array->data.x_array.s_none.elements = allocate(g->test_fns.length); + + for (size_t i = 0; i < g->test_fns.length; i += 1) { + FnTableEntry *test_fn_entry = g->test_fns.at(i); + + ConstExprValue *this_val = &test_fn_array->data.x_array.s_none.elements[i]; + this_val->special = ConstValSpecialStatic; + this_val->type = struct_type; + this_val->data.x_struct.parent.id = ConstParentIdArray; + this_val->data.x_struct.parent.data.p_array.array_val = test_fn_array; + this_val->data.x_struct.parent.data.p_array.elem_index = i; + this_val->data.x_struct.fields = allocate(2); + + ConstExprValue *name_field = &this_val->data.x_struct.fields[0]; + ConstExprValue *name_array_val = create_const_str_lit(g, &test_fn_entry->symbol_name); + init_const_slice(g, name_field, name_array_val, 0, buf_len(&test_fn_entry->symbol_name), true); + + ConstExprValue *fn_field = &this_val->data.x_struct.fields[1]; + fn_field->type = fn_type; + fn_field->special = ConstValSpecialStatic; + fn_field->data.x_fn.fn_entry = test_fn_entry; + } + + ConstExprValue *test_fn_slice = create_const_slice(g, test_fn_array, 0, g->test_fns.length, true); + + g->compile_vars.put(buf_create_from_str("zig_test_fn_slice"), test_fn_slice); + g->test_runner_package = create_test_runner_pkg(g); + g->test_runner_import = add_special_code(g, g->test_runner_package, "test_runner.zig"); +} + static void gen_root_source(CodeGen *g) { if (buf_len(&g->root_package->root_src_path) == 0) return; @@ -4779,7 +4741,7 @@ static void gen_root_source(CodeGen *g) { if (!g->is_test_build && g->zig_target.os != ZigLLVM_UnknownOS && !g->have_c_main && ((g->have_pub_main && g->out_type == OutTypeObj) || g->out_type == OutTypeExe)) { - g->bootstrap_import = add_special_code(g, create_bootstrap_pkg(g), "bootstrap.zig"); + g->bootstrap_import = add_special_code(g, create_bootstrap_pkg(g, g->root_package), "bootstrap.zig"); } if (!g->omit_zigrt) { g->zigrt_package = create_zigrt_pkg(g); @@ -4793,6 +4755,14 @@ static void gen_root_source(CodeGen *g) { if (!g->error_during_imports) { semantic_analyze(g); } + if (g->is_test_build) { + create_test_compile_var_and_add_test_runner(g); + g->bootstrap_import = add_special_code(g, create_bootstrap_pkg(g, g->test_runner_package), "bootstrap.zig"); + + if (!g->error_during_imports) { + semantic_analyze(g); + } + } if (g->errors.length == 0) { if (g->verbose) { diff --git a/src/ir.cpp b/src/ir.cpp index 94c5490b28..8026d6f985 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -10920,7 +10920,7 @@ static TypeTableEntry *ir_analyze_instruction_import(IrAnalyze *ira, IrInstructi } ImportTableEntry *target_import = add_source_file(ira->codegen, target_package, abs_full_path, import_code); - scan_decls(ira->codegen, target_import->decls_scope, target_import->root); + scan_import(ira->codegen, target_import); ConstExprValue *out_val = ir_build_const_from(ira, &import_instruction->base); out_val->data.x_import = target_import; diff --git a/src/link.cpp b/src/link.cpp index 81c4f3506a..a771b5c6aa 100644 --- a/src/link.cpp +++ b/src/link.cpp @@ -263,11 +263,6 @@ static void construct_linker_job_elf(LinkJob *lj) { lj->args.append((const char *)buf_ptr(g->link_objects.at(i))); } - if (g->is_test_build) { - Buf *test_runner_o_path = build_o(g, "test_runner"); - lj->args.append(buf_ptr(test_runner_o_path)); - } - if (!g->link_libc && (g->out_type == OutTypeExe || g->out_type == OutTypeLib)) { Buf *builtin_o_path = build_o(g, "builtin"); lj->args.append(buf_ptr(builtin_o_path)); @@ -408,11 +403,6 @@ static void construct_linker_job_coff(LinkJob *lj) { lj->args.append((const char *)buf_ptr(g->link_objects.at(i))); } - if (g->is_test_build) { - Buf *test_runner_o_path = build_o(g, "test_runner"); - lj->args.append(buf_ptr(test_runner_o_path)); - } - if (!g->link_libc && (g->out_type == OutTypeExe || g->out_type == OutTypeLib)) { Buf *builtin_o_path = build_o(g, "builtin"); lj->args.append(buf_ptr(builtin_o_path)); @@ -674,11 +664,6 @@ static void construct_linker_job_macho(LinkJob *lj) { lj->args.append((const char *)buf_ptr(g->link_objects.at(i))); } - if (g->is_test_build) { - Buf *test_runner_o_path = build_o(g, "test_runner"); - lj->args.append(buf_ptr(test_runner_o_path)); - } - for (size_t i = 0; i < g->link_libs.length; i += 1) { Buf *link_lib = g->link_libs.at(i); if (buf_eql_str(link_lib, "c")) { diff --git a/src/main.cpp b/src/main.cpp index ee4d542e12..4df56066d2 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -558,13 +558,13 @@ int main(int argc, char **argv) { codegen_build(g); codegen_link(g, out_file); if (timing_info) - codegen_print_timing_report(g, stderr); + codegen_print_timing_report(g, stdout); return EXIT_SUCCESS; } else if (cmd == CmdParseH) { codegen_parseh(g, in_file_buf); ast_render_decls(g, stdout, 4, g->root_import); if (timing_info) - codegen_print_timing_report(g, stderr); + codegen_print_timing_report(g, stdout); return EXIT_SUCCESS; } else if (cmd == CmdTest) { codegen_build(g); @@ -576,7 +576,7 @@ int main(int argc, char **argv) { fprintf(stderr, "\nTests failed. Use the following command to reproduce the failure:\n"); fprintf(stderr, "./test\n"); } else if (timing_info) { - codegen_print_timing_report(g, stderr); + codegen_print_timing_report(g, stdout); } return (term.how == TerminationIdClean) ? term.code : -1; } else { diff --git a/std/index.zig b/std/index.zig index 5deb3d37c4..946a08c93e 100644 --- a/std/index.zig +++ b/std/index.zig @@ -16,3 +16,24 @@ pub const os = @import("os/index.zig"); pub const rand = @import("rand.zig"); pub const sort = @import("sort.zig"); pub const target = @import("target.zig"); + +test "std" { + // run tests from these + _ = @import("base64.zig"); + _ = @import("buffer.zig"); + _ = @import("build.zig"); + _ = @import("c/index.zig"); + _ = @import("cstr.zig"); + _ = @import("debug.zig"); + _ = @import("fmt.zig"); + _ = @import("hash_map.zig"); + _ = @import("io.zig"); + _ = @import("list.zig"); + _ = @import("math.zig"); + _ = @import("mem.zig"); + _ = @import("net.zig"); + _ = @import("os/index.zig"); + _ = @import("rand.zig"); + _ = @import("sort.zig"); + _ = @import("target.zig"); +} diff --git a/std/special/test_runner.zig b/std/special/test_runner.zig index bf85ed07e3..cae42fe0a5 100644 --- a/std/special/test_runner.zig +++ b/std/special/test_runner.zig @@ -1,17 +1,11 @@ const io = @import("std").io; - -const TestFn = struct { - name: []u8, - func: extern fn(), -}; - -extern var zig_test_fn_list: []TestFn; +const test_fn_list = @compileVar("zig_test_fn_slice"); pub fn main() -> %void { - for (zig_test_fn_list) |testFn, i| { - %%io.stderr.printf("Test {}/{} {}...", i + 1, zig_test_fn_list.len, testFn.name); + for (test_fn_list) |test_fn, i| { + %%io.stderr.printf("Test {}/{} {}...", i + 1, test_fn_list.len, test_fn.name); - testFn.func(); + test_fn.func(); %%io.stderr.printf("OK\n"); }