From 87bc97daefc8b5d8b665ea2fb2b6c232b80344bc Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 22 Mar 2017 11:26:30 -0400 Subject: unify main entry point regardless of whether linking libc closes #248 --- CMakeLists.txt | 3 +-- src/all_types.hpp | 5 +++-- src/analyze.cpp | 4 ++-- src/codegen.cpp | 43 ++++++++++++++++++++++++++++++++++++------- src/ir.cpp | 25 ++++--------------------- src/link.cpp | 27 +++++++++++++++++++++------ std/bootstrap.zig | 9 ++++----- std/build.zig | 13 +++++++++++++ std/index.zig | 1 + std/test_runner.zig | 2 +- std/test_runner_libc.zig | 6 ------ std/test_runner_nolibc.zig | 5 ----- 12 files changed, 86 insertions(+), 57 deletions(-) create mode 100644 std/build.zig delete mode 100644 std/test_runner_libc.zig delete mode 100644 std/test_runner_nolibc.zig diff --git a/CMakeLists.txt b/CMakeLists.txt index ca78d6b281..4ded1c29fb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -202,6 +202,7 @@ install(TARGETS zig DESTINATION bin) install(FILES ${C_HEADERS} DESTINATION ${C_HEADERS_DEST}) install(FILES "${CMAKE_SOURCE_DIR}/std/bootstrap.zig" DESTINATION "${ZIG_STD_DEST}") +install(FILES "${CMAKE_SOURCE_DIR}/std/build.zig" DESTINATION "${ZIG_STD_DEST}") install(FILES "${CMAKE_SOURCE_DIR}/std/builtin.zig" DESTINATION "${ZIG_STD_DEST}") install(FILES "${CMAKE_SOURCE_DIR}/std/compiler_rt.zig" DESTINATION "${ZIG_STD_DEST}") install(FILES "${CMAKE_SOURCE_DIR}/std/cstr.zig" DESTINATION "${ZIG_STD_DEST}") @@ -230,8 +231,6 @@ install(FILES "${CMAKE_SOURCE_DIR}/std/rand.zig" DESTINATION "${ZIG_STD_DEST}") install(FILES "${CMAKE_SOURCE_DIR}/std/rand_test.zig" DESTINATION "${ZIG_STD_DEST}") install(FILES "${CMAKE_SOURCE_DIR}/std/sort.zig" DESTINATION "${ZIG_STD_DEST}") install(FILES "${CMAKE_SOURCE_DIR}/std/test_runner.zig" DESTINATION "${ZIG_STD_DEST}") -install(FILES "${CMAKE_SOURCE_DIR}/std/test_runner_libc.zig" DESTINATION "${ZIG_STD_DEST}") -install(FILES "${CMAKE_SOURCE_DIR}/std/test_runner_nolibc.zig" DESTINATION "${ZIG_STD_DEST}") add_executable(run_tests ${TEST_SOURCES}) target_link_libraries(run_tests) diff --git a/src/all_types.hpp b/src/all_types.hpp index b3faff2212..35ed95fbdb 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -1291,6 +1291,7 @@ struct CodeGen { HashMap generic_table; HashMap memoized_fn_eval_table; HashMap llvm_fn_table; + HashMap compile_vars; ZigList import_queue; size_t import_queue_index; @@ -1346,8 +1347,8 @@ struct CodeGen { bool is_static; bool strip_debug_symbols; bool want_h_file; - bool have_exported_main; - bool have_exported_panic; + bool have_pub_main; + bool have_pub_panic; bool link_libc; Buf *libc_lib_dir; Buf *libc_static_lib_dir; diff --git a/src/analyze.cpp b/src/analyze.cpp index e6c95c58f6..1a0f0b8fe8 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -2878,9 +2878,9 @@ ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package, if (is_pub) { if (buf_eql_str(proto_name, "main")) { - g->have_exported_main = true; + g->have_pub_main = true; } else if (buf_eql_str(proto_name, "panic")) { - g->have_exported_panic = true; + g->have_pub_panic = true; } } } diff --git a/src/codegen.cpp b/src/codegen.cpp index a1dac1cca1..f67cdf2ab2 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -66,6 +66,7 @@ CodeGen *codegen_create(Buf *root_source_dir, const ZigTarget *target) { g->generic_table.init(16); g->llvm_fn_table.init(16); g->memoized_fn_eval_table.init(16); + g->compile_vars.init(16); g->is_release_build = false; g->is_test_build = false; g->want_h_file = true; @@ -191,9 +192,8 @@ void codegen_add_rpath(CodeGen *g, const char *name) { void codegen_add_link_lib(CodeGen *g, const char *lib) { if (strcmp(lib, "c") == 0) { g->link_libc = true; - } else { - g->link_libs.append(buf_create_from_str(lib)); } + g->link_libs.append(buf_create_from_str(lib)); } void codegen_add_framework(CodeGen *g, const char *framework) { @@ -4057,6 +4057,36 @@ static void define_builtin_fns(CodeGen *g) { create_builtin_fn(g, BuiltinFnIdSetGlobalSection, "setGlobalSection", 2); } +static void add_compile_var(CodeGen *g, const char *name, ConstExprValue *value) { + g->compile_vars.put_unique(buf_create_from_str(name), value); +} + +static void define_builtin_compile_vars(CodeGen *g) { + add_compile_var(g, "is_big_endian", create_const_bool(g, g->is_big_endian)); + add_compile_var(g, "is_release", create_const_bool(g, g->is_release_build)); + add_compile_var(g, "is_test", create_const_bool(g, g->is_test_build)); + add_compile_var(g, "os", create_const_enum_tag(g->builtin_types.entry_os_enum, g->target_os_index)); + add_compile_var(g, "arch", create_const_enum_tag(g->builtin_types.entry_arch_enum, g->target_arch_index)); + add_compile_var(g, "environ", create_const_enum_tag(g->builtin_types.entry_environ_enum, g->target_environ_index)); + add_compile_var(g, "object_format", create_const_enum_tag( + g->builtin_types.entry_oformat_enum, g->target_oformat_index)); + + { + TypeTableEntry *str_type = get_slice_type(g, g->builtin_types.entry_u8, true); + ConstExprValue *const_val = allocate(1); + const_val->special = ConstValSpecialStatic; + const_val->type = get_array_type(g, str_type, g->link_libs.length); + const_val->data.x_array.elements = allocate(g->link_libs.length); + for (size_t i = 0; i < g->link_libs.length; i += 1) { + Buf *link_lib_buf = g->link_libs.at(i); + ConstExprValue *array_val = create_const_str_lit(g, link_lib_buf); + init_const_slice(g, &const_val->data.x_array.elements[i], array_val, 0, buf_len(link_lib_buf), true); + } + + add_compile_var(g, "link_libs", const_val); + } +} + static void init(CodeGen *g, Buf *source_path) { g->module = LLVMModuleCreateWithName(buf_ptr(source_path)); @@ -4120,6 +4150,7 @@ static void init(CodeGen *g, Buf *source_path) { define_builtin_types(g); define_builtin_fns(g); + define_builtin_compile_vars(g); g->invalid_instruction = allocate(1); g->invalid_instruction->value.type = g->builtin_types.entry_invalid; @@ -4209,12 +4240,10 @@ void codegen_add_root_code(CodeGen *g, Buf *src_dir, Buf *src_basename, Buf *sou assert(g->root_out_name); assert(g->out_type != OutTypeUnknown); - if (!g->link_libc && !g->is_test_build) { - if (g->have_exported_main && (g->out_type == OutTypeObj || g->out_type == OutTypeExe)) { - g->bootstrap_import = add_special_code(g, create_bootstrap_pkg(g), "bootstrap.zig"); - } + if (!g->is_test_build && 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"); } - if (!g->have_exported_panic) { + if (!g->have_pub_panic) { g->panic_package = create_panic_pkg(g); add_special_code(g, g->panic_package, "panic.zig"); } diff --git a/src/ir.cpp b/src/ir.cpp index e9d0b2f311..ca80f58677 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -9869,27 +9869,10 @@ static TypeTableEntry *ir_analyze_instruction_compile_var(IrAnalyze *ira, return ira->codegen->builtin_types.entry_invalid; ConstExprValue *out_val = ir_build_const_from(ira, &compile_var_instruction->base); - if (buf_eql_str(var_name, "is_big_endian")) { - out_val->data.x_bool = ira->codegen->is_big_endian; - return ira->codegen->builtin_types.entry_bool; - } else if (buf_eql_str(var_name, "is_release")) { - out_val->data.x_bool = ira->codegen->is_release_build; - return ira->codegen->builtin_types.entry_bool; - } else if (buf_eql_str(var_name, "is_test")) { - out_val->data.x_bool = ira->codegen->is_test_build; - return ira->codegen->builtin_types.entry_bool; - } else if (buf_eql_str(var_name, "os")) { - out_val->data.x_enum.tag = ira->codegen->target_os_index; - return ira->codegen->builtin_types.entry_os_enum; - } else if (buf_eql_str(var_name, "arch")) { - out_val->data.x_enum.tag = ira->codegen->target_arch_index; - return ira->codegen->builtin_types.entry_arch_enum; - } else if (buf_eql_str(var_name, "environ")) { - out_val->data.x_enum.tag = ira->codegen->target_environ_index; - return ira->codegen->builtin_types.entry_environ_enum; - } else if (buf_eql_str(var_name, "object_format")) { - out_val->data.x_enum.tag = ira->codegen->target_oformat_index; - return ira->codegen->builtin_types.entry_oformat_enum; + auto entry = ira->codegen->compile_vars.maybe_get(var_name); + if (entry) { + *out_val = *entry->value; + return out_val->type; } else { ir_add_error_node(ira, name_value->source_node, buf_sprintf("unrecognized compile variable: '%s'", buf_ptr(var_name))); diff --git a/src/link.cpp b/src/link.cpp index 3447110a2c..d0af76a47d 100644 --- a/src/link.cpp +++ b/src/link.cpp @@ -47,6 +47,12 @@ static Buf *build_o(CodeGen *parent_gen, const char *oname) { ZigTarget *child_target = parent_gen->is_native_target ? nullptr : &parent_gen->zig_target; CodeGen *child_gen = codegen_create(std_dir_path, child_target); child_gen->link_libc = parent_gen->link_libc; + + child_gen->link_libs.resize(parent_gen->link_libs.length); + for (size_t i = 0; i < parent_gen->link_libs.length; i += 1) { + child_gen->link_libs.items[i] = parent_gen->link_libs.items[i]; + } + child_gen->want_h_file = false; codegen_set_is_release(child_gen, parent_gen->is_release_build); @@ -223,6 +229,9 @@ static void construct_linker_job_elf(LinkJob *lj) { const char *lib_dir = g->lib_dirs.at(i); 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")) { + continue; + } bool does_exist; Buf *test_path = buf_sprintf("%s/lib%s.so", lib_dir, buf_ptr(link_lib)); if (os_file_exists(test_path, &does_exist) != ErrorNone) { @@ -267,8 +276,7 @@ static void construct_linker_job_elf(LinkJob *lj) { lj->args.append((const char *)buf_ptr(&lj->out_file_o)); if (g->is_test_build) { - const char *test_runner_name = g->link_libc ? "test_runner_libc" : "test_runner_nolibc"; - Buf *test_runner_o_path = build_o(g, test_runner_name); + Buf *test_runner_o_path = build_o(g, "test_runner"); lj->args.append(buf_ptr(test_runner_o_path)); } @@ -282,6 +290,9 @@ static void construct_linker_job_elf(LinkJob *lj) { 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")) { + continue; + } Buf *arg; if (buf_starts_with_str(link_lib, "/") || buf_ends_with_str(link_lib, ".a") || buf_ends_with_str(link_lib, ".so")) @@ -408,8 +419,7 @@ static void construct_linker_job_coff(LinkJob *lj) { lj->args.append((const char *)buf_ptr(&lj->out_file_o)); if (g->is_test_build) { - const char *test_runner_name = g->link_libc ? "test_runner_libc" : "test_runner_nolibc"; - Buf *test_runner_o_path = build_o(g, test_runner_name); + Buf *test_runner_o_path = build_o(g, "test_runner"); lj->args.append(buf_ptr(test_runner_o_path)); } @@ -424,6 +434,9 @@ static void construct_linker_job_coff(LinkJob *lj) { 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")) { + continue; + } Buf *arg = buf_sprintf("-l%s", buf_ptr(link_lib)); lj->args.append(buf_ptr(arg)); } @@ -685,13 +698,15 @@ static void construct_linker_job_macho(LinkJob *lj) { lj->args.append((const char *)buf_ptr(&lj->out_file_o)); if (g->is_test_build) { - const char *test_runner_name = g->link_libc ? "test_runner_libc" : "test_runner_nolibc"; - Buf *test_runner_o_path = build_o(g, test_runner_name); + 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")) { + continue; + } Buf *arg = buf_sprintf("-l%s", buf_ptr(link_lib)); lj->args.append(buf_ptr(arg)); } diff --git a/std/bootstrap.zig b/std/bootstrap.zig index f520834654..074f06557e 100644 --- a/std/bootstrap.zig +++ b/std/bootstrap.zig @@ -1,17 +1,16 @@ // This file is in a package which has the root source file exposed as "@root". +// It is included in the compilation unit when exporting an executable. const root = @import("@root"); const std = @import("std"); -const want_start_symbol = switch(@compileVar("os")) { - Os.linux => true, - else => false, -}; -const want_main_symbol = !want_start_symbol; +const want_main_symbol = std.build.linkingLibrary("c"); +const want_start_symbol = !want_main_symbol; const exit = switch(@compileVar("os")) { Os.linux => std.linux.exit, Os.darwin => std.darwin.exit, + else => @compileError("Unsupported OS"), }; var argc: usize = undefined; diff --git a/std/build.zig b/std/build.zig new file mode 100644 index 0000000000..a21baa387d --- /dev/null +++ b/std/build.zig @@ -0,0 +1,13 @@ +const mem = @import("mem.zig"); + +pub fn linkingLibrary(lib_name: []const u8) -> bool { + // TODO shouldn't need this if + if (@compileVar("link_libs").len != 0) { + for (@compileVar("link_libs")) |link_lib| { + if (mem.eql(u8, link_lib, lib_name)) { + return true; + } + } + } + return false; +} diff --git a/std/index.zig b/std/index.zig index b4a86f0f9d..0a0b9557ad 100644 --- a/std/index.zig +++ b/std/index.zig @@ -1,3 +1,4 @@ +pub const build = @import("build.zig"); pub const cstr = @import("cstr.zig"); pub const debug = @import("debug.zig"); pub const fmt = @import("fmt.zig"); diff --git a/std/test_runner.zig b/std/test_runner.zig index 7aa11e523e..f494801671 100644 --- a/std/test_runner.zig +++ b/std/test_runner.zig @@ -7,7 +7,7 @@ const TestFn = struct { extern var zig_test_fn_list: []TestFn; -pub fn runTests() -> %void { +pub fn main(args: [][]u8) -> %void { for (zig_test_fn_list) |testFn, i| { %%io.stderr.printf("Test {}/{} {}...", i + 1, zig_test_fn_list.len, testFn.name); diff --git a/std/test_runner_libc.zig b/std/test_runner_libc.zig deleted file mode 100644 index bbd4f71d8b..0000000000 --- a/std/test_runner_libc.zig +++ /dev/null @@ -1,6 +0,0 @@ -const test_runner = @import("test_runner.zig"); - -export fn main(argc: c_int, argv: &&u8) -> c_int { - test_runner.runTests() %% return -1; - return 0; -} diff --git a/std/test_runner_nolibc.zig b/std/test_runner_nolibc.zig deleted file mode 100644 index 226cbb2a5c..0000000000 --- a/std/test_runner_nolibc.zig +++ /dev/null @@ -1,5 +0,0 @@ -const test_runner = @import("test_runner.zig"); - -pub fn main(args: [][]u8) -> %void { - return test_runner.runTests(); -} -- cgit v1.2.3