diff options
| author | Andrew Kelley <superjoe30@gmail.com> | 2015-12-15 12:44:42 -0700 |
|---|---|---|
| committer | Andrew Kelley <superjoe30@gmail.com> | 2015-12-15 12:44:42 -0700 |
| commit | f5a32818773835bdeaa8f0db1d036a1506c69982 (patch) | |
| tree | cec14b3ed641e3916613e5ff24f9db7943177c18 /src/codegen.cpp | |
| parent | f2a9b40231f982b10c4d098c60b47da890396c1f (diff) | |
| download | zig-f5a32818773835bdeaa8f0db1d036a1506c69982.tar.gz zig-f5a32818773835bdeaa8f0db1d036a1506c69982.zip | |
when linking with libc use the C runtime library
Diffstat (limited to 'src/codegen.cpp')
| -rw-r--r-- | src/codegen.cpp | 81 |
1 files changed, 76 insertions, 5 deletions
diff --git a/src/codegen.cpp b/src/codegen.cpp index 699769f513..b0a7eae2c8 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -58,6 +58,10 @@ void codegen_set_out_name(CodeGen *g, Buf *out_name) { g->root_out_name = out_name; } +void codegen_set_libc_path(CodeGen *g, Buf *libc_path) { + g->libc_path = libc_path; +} + static LLVMValueRef gen_expr(CodeGen *g, AstNode *expr_node); @@ -1517,6 +1521,18 @@ static void init(CodeGen *g, Buf *source_path) { } +static bool directives_contains_link_libc(ZigList<AstNode*> *directives) { + for (int i = 0; i < directives->length; i += 1) { + AstNode *directive_node = directives->at(i); + if (buf_eql_str(&directive_node->data.directive.name, "link") && + buf_eql_str(&directive_node->data.directive.param, "c")) + { + return true; + } + } + return false; +} + static ImportTableEntry *codegen_add_code(CodeGen *g, Buf *src_dirname, Buf *src_basename, Buf *source_code) { int err; Buf *full_path = buf_alloc(); @@ -1613,11 +1629,13 @@ static ImportTableEntry *codegen_add_code(CodeGen *g, Buf *src_dirname, Buf *src assert(proto_node->type == NodeTypeFnProto); Buf *proto_name = &proto_node->data.fn_proto.name; - bool is_exported = (proto_node->data.fn_proto.visib_mod != FnProtoVisibModPrivate); + bool is_private = (proto_node->data.fn_proto.visib_mod == FnProtoVisibModPrivate); - if (buf_eql_str(proto_name, "main") && is_exported) { - g->insert_bootstrap_code = true; + if (buf_eql_str(proto_name, "main") && !is_private) { + g->have_exported_main = true; } + } else if (top_level_decl->type == NodeTypeExternBlock) { + g->link_libc = directives_contains_link_libc(top_level_decl->data.extern_block.directives); } } @@ -1633,7 +1651,7 @@ void codegen_add_root_code(CodeGen *g, Buf *src_dir, Buf *src_basename, Buf *sou g->root_import = codegen_add_code(g, src_dir, src_basename, source_code); - if (g->insert_bootstrap_code) { + if (g->have_exported_main && !g->link_libc && g->out_type != OutTypeLib) { Buf *bootstrap_dir = buf_create_from_str(ZIG_STD_DIR); Buf *bootstrap_basename = buf_create_from_str("bootstrap.zig"); Buf path_to_bootstrap_src = BUF_INIT; @@ -1788,6 +1806,22 @@ static void generate_h_file(CodeGen *g) { zig_panic("unable to close h file: %s", strerror(errno)); } +static void find_libc_path(CodeGen *g) { + if (g->libc_path && buf_len(g->libc_path)) + return; + g->libc_path = buf_create_from_str(ZIG_LIBC_DIR); + if (g->libc_path && buf_len(g->libc_path)) + return; + fprintf(stderr, "Unable to determine libc path. Consider using `--libc-path [path]`\n"); + exit(1); +} + +static const char *get_libc_file(CodeGen *g, const char *file) { + Buf *out_buf = buf_alloc(); + os_path_join(g->libc_path, buf_create_from_str(file), out_buf); + return buf_ptr(out_buf); +} + void codegen_link(CodeGen *g, const char *out_file) { bool is_optimized = (g->build_type == CodeGenBuildTypeRelease); if (is_optimized) { @@ -1826,6 +1860,9 @@ void codegen_link(CodeGen *g, const char *out_file) { } if (g->out_type == OutTypeObj) { + if (g->verbose) { + fprintf(stderr, "OK\n"); + } return; } @@ -1840,8 +1877,12 @@ void codegen_link(CodeGen *g, const char *out_file) { // invoke `ld` ZigList<const char *> args = {0}; + const char *crt1o; if (g->is_static) { args.append("-static"); + crt1o = "crt1.o"; + } else { + crt1o = "Scrt1.o"; } char *ZIG_NATIVE_DYNAMIC_LINKER = getenv("ZIG_NATIVE_DYNAMIC_LINKER"); @@ -1868,8 +1909,21 @@ void codegen_link(CodeGen *g, const char *out_file) { args.append("-o"); args.append(out_file); + bool link_in_crt = (g->link_libc && g->out_type == OutTypeExe); + + if (link_in_crt) { + find_libc_path(g); + + args.append(get_libc_file(g, crt1o)); + args.append(get_libc_file(g, "crti.o")); + } + args.append((const char *)buf_ptr(&out_file_o)); + if (link_in_crt) { + args.append(get_libc_file(g, "crtn.o")); + } + auto it = g->link_table.entry_iterator(); for (;;) { auto *entry = it.next(); @@ -1880,7 +1934,24 @@ void codegen_link(CodeGen *g, const char *out_file) { args.append(buf_ptr(arg)); } - os_spawn_process("ld", args, false); + if (g->verbose) { + fprintf(stderr, "ld"); + for (int i = 0; i < args.length; i += 1) { + fprintf(stderr, " %s", args.at(i)); + } + fprintf(stderr, "\n"); + } + + int return_code; + Buf ld_stderr = BUF_INIT; + Buf ld_stdout = BUF_INIT; + os_exec_process("ld", args, &return_code, &ld_stderr, &ld_stdout); + + if (return_code != 0) { + fprintf(stderr, "ld failed with return code %d\n", return_code); + fprintf(stderr, "%s\n", buf_ptr(&ld_stderr)); + exit(1); + } if (g->out_type == OutTypeLib) { generate_h_file(g); |
