Commit 87bc97daef

Andrew Kelley <superjoe30@gmail.com>
2017-03-22 16:26:30
unify main entry point regardless of whether linking libc
closes #248
1 parent e1c47d6
src/all_types.hpp
@@ -1291,6 +1291,7 @@ struct CodeGen {
     HashMap<GenericFnTypeId *, FnTableEntry *, generic_fn_type_id_hash, generic_fn_type_id_eql> generic_table;
     HashMap<Scope *, IrInstruction *, fn_eval_hash, fn_eval_eql> memoized_fn_eval_table;
     HashMap<ZigLLVMFnKey, LLVMValueRef, zig_llvm_fn_key_hash, zig_llvm_fn_key_eql> llvm_fn_table;
+    HashMap<Buf *, ConstExprValue *, buf_hash, buf_eql_buf> compile_vars;
 
     ZigList<ImportTableEntry *> 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;
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;
                 }
             }
         }
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<ConstExprValue>(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<ConstExprValue>(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<IrInstruction>(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");
     }
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)));
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));
     }
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;
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;
+}
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");
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);
 
std/test_runner_libc.zig
@@ -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;
-}
std/test_runner_nolibc.zig
@@ -1,5 +0,0 @@
-const test_runner = @import("test_runner.zig");
-
-pub fn main(args: [][]u8) -> %void {
-    return test_runner.runTests();
-}
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)