diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2020-01-16 13:01:36 -0500 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2020-01-16 13:01:36 -0500 |
| commit | fbe6af81fdb1b964bb0c28f51de2458800b8274c (patch) | |
| tree | 6d65a49b911ba665a7e2c28c6619d1aa6517a744 /src/link.cpp | |
| parent | 230d27c1cd00e7adf0ccfca2c8bb73ae1779aa4c (diff) | |
| parent | 7e5e767ba0fdde91dd66690168eff96b75c28e33 (diff) | |
| download | zig-fbe6af81fdb1b964bb0c28f51de2458800b8274c.tar.gz zig-fbe6af81fdb1b964bb0c28f51de2458800b8274c.zip | |
Merge remote-tracking branch 'origin/master' into llvm10
Diffstat (limited to 'src/link.cpp')
| -rw-r--r-- | src/link.cpp | 377 |
1 files changed, 209 insertions, 168 deletions
diff --git a/src/link.cpp b/src/link.cpp index cf473b8cd7..61a5ad5664 100644 --- a/src/link.cpp +++ b/src/link.cpp @@ -552,28 +552,41 @@ static const char *mingwex_arm64_src[] = { struct MinGWDef { const char *name; - const char *path; bool always_link; }; static const MinGWDef mingw_def_list[] = { - {"msvcrt", "lib-common" OS_SEP "msvcrt.def.in", true}, - {"setupapi", "libarm32" OS_SEP "setupapi.def", false}, - {"setupapi", "libarm64" OS_SEP "setupapi.def", false}, - {"setupapi", "lib32" OS_SEP "setupapi.def", false}, - {"setupapi", "lib64" OS_SEP "setupapi.def", false}, - {"winmm", "lib-common" OS_SEP "winmm.def", false}, - {"gdi32", "lib-common" OS_SEP "gdi32.def", false}, - {"imm32", "lib-common" OS_SEP "imm32.def", false}, - {"version", "lib-common" OS_SEP "version.def", false}, - {"advapi32", "lib-common" OS_SEP "advapi32.def.in", true}, - {"oleaut32", "lib-common" OS_SEP "oleaut32.def.in", false}, - {"ole32", "lib-common" OS_SEP "ole32.def.in", false}, - {"shell32", "lib-common" OS_SEP "shell32.def", true}, - {"user32", "lib-common" OS_SEP "user32.def.in", true}, - {"kernel32", "lib-common" OS_SEP "kernel32.def.in", true}, - {"ntdll", "libarm32" OS_SEP "ntdll.def", true}, - {"ntdll", "lib32" OS_SEP "ntdll.def", true}, - {"ntdll", "lib64" OS_SEP "ntdll.def", true}, + {"advapi32",true}, + {"bcrypt", false}, + {"comctl32",false}, + {"comdlg32",false}, + {"crypt32", false}, + {"cryptnet",false}, + {"gdi32", false}, + {"imm32", false}, + {"kernel32",true}, + {"lz32", false}, + {"mpr", false}, + {"msvcrt", true}, + {"mswsock", false}, + {"ncrypt", false}, + {"netapi32",false}, + {"ntdll", true}, + {"ole32", false}, + {"oleaut32",false}, + {"opengl32",false}, + {"rpcns4", false}, + {"rpcrt4", false}, + {"scarddlg",false}, + {"setupapi",false}, + {"shell32", true}, + {"urlmon", false}, + {"user32", true}, + {"version", false}, + {"winmm", false}, + {"winscard",false}, + {"winspool",false}, + {"wintrust",false}, + {"ws2_32", false}, }; struct LinkJob { @@ -581,11 +594,13 @@ struct LinkJob { ZigList<const char *> args; bool link_in_crt; HashMap<Buf *, bool, buf_hash, buf_eql_buf> rpath_table; + Stage2ProgressNode *build_dep_prog_node; }; -static const char *build_libc_object(CodeGen *parent_gen, const char *name, CFile *c_file) { - CodeGen *child_gen = create_child_codegen(parent_gen, nullptr, OutTypeObj, nullptr); - codegen_set_out_name(child_gen, buf_create_from_str(name)); +static const char *build_libc_object(CodeGen *parent_gen, const char *name, CFile *c_file, + Stage2ProgressNode *progress_node) +{ + CodeGen *child_gen = create_child_codegen(parent_gen, nullptr, OutTypeObj, nullptr, name, progress_node); ZigList<CFile *> c_source_files = {0}; c_source_files.append(c_file); child_gen->c_source_files = c_source_files; @@ -609,9 +624,8 @@ static const char *path_from_libunwind(CodeGen *g, const char *subpath) { return path_from_zig_lib(g, "libunwind", subpath); } -static const char *build_libunwind(CodeGen *parent) { - CodeGen *child_gen = create_child_codegen(parent, nullptr, OutTypeLib, nullptr); - codegen_set_out_name(child_gen, buf_create_from_str("unwind")); +static const char *build_libunwind(CodeGen *parent, Stage2ProgressNode *progress_node) { + CodeGen *child_gen = create_child_codegen(parent, nullptr, OutTypeLib, nullptr, "unwind", progress_node); LinkLib *new_link_lib = codegen_add_link_lib(child_gen, buf_create_from_str("c")); new_link_lib->provided_explicitly = false; enum SrcKind { @@ -1004,9 +1018,8 @@ static bool is_musl_arch_name(const char *name) { return false; } -static const char *build_musl(CodeGen *parent) { - CodeGen *child_gen = create_child_codegen(parent, nullptr, OutTypeLib, nullptr); - codegen_set_out_name(child_gen, buf_create_from_str("c")); +static const char *build_musl(CodeGen *parent, Stage2ProgressNode *progress_node) { + CodeGen *child_gen = create_child_codegen(parent, nullptr, OutTypeLib, nullptr, "c", progress_node); // When there is a src/<arch>/foo.* then it should substitute for src/foo.* // Even a .s file can substitute for a .c file. @@ -1162,7 +1175,7 @@ static void add_mingwex_os_dep(CodeGen *parent, CodeGen *child_gen, const char * child_gen->c_source_files.append(c_file); } -static const char *get_libc_crt_file(CodeGen *parent, const char *file) { +static const char *get_libc_crt_file(CodeGen *parent, const char *file, Stage2ProgressNode *progress_node) { if (parent->libc == nullptr && parent->zig_target->os == OsWindows) { if (strcmp(file, "crt2.o") == 0) { CFile *c_file = allocate<CFile>(1); @@ -1175,7 +1188,7 @@ static const char *get_libc_crt_file(CodeGen *parent, const char *file) { //c_file->args.append("-DUNICODE"); //c_file->args.append("-D_UNICODE"); //c_file->args.append("-DWPRFLAG=1"); - return build_libc_object(parent, "crt2", c_file); + return build_libc_object(parent, "crt2", c_file, progress_node); } else if (strcmp(file, "dllcrt2.o") == 0) { CFile *c_file = allocate<CFile>(1); c_file->source_path = buf_ptr(buf_sprintf( @@ -1183,10 +1196,9 @@ static const char *get_libc_crt_file(CodeGen *parent, const char *file) { mingw_add_cc_args(parent, c_file); c_file->args.append("-U__CRTDLL__"); c_file->args.append("-D__MSVCRT__"); - return build_libc_object(parent, "dllcrt2", c_file); + return build_libc_object(parent, "dllcrt2", c_file, progress_node); } else if (strcmp(file, "mingw32.lib") == 0) { - CodeGen *child_gen = create_child_codegen(parent, nullptr, OutTypeLib, nullptr); - codegen_set_out_name(child_gen, buf_create_from_str("mingw32")); + CodeGen *child_gen = create_child_codegen(parent, nullptr, OutTypeLib, nullptr, "mingw32", progress_node); static const char *deps[] = { "mingw" OS_SEP "crt" OS_SEP "crt0_c.c", @@ -1243,8 +1255,7 @@ static const char *get_libc_crt_file(CodeGen *parent, const char *file) { codegen_build_and_link(child_gen); return buf_ptr(&child_gen->output_file_path); } else if (strcmp(file, "msvcrt-os.lib") == 0) { - CodeGen *child_gen = create_child_codegen(parent, nullptr, OutTypeLib, nullptr); - codegen_set_out_name(child_gen, buf_create_from_str("msvcrt-os")); + CodeGen *child_gen = create_child_codegen(parent, nullptr, OutTypeLib, nullptr, "msvcrt-os", progress_node); for (size_t i = 0; i < array_length(msvcrt_common_src); i += 1) { add_msvcrt_os_dep(parent, child_gen, msvcrt_common_src[i]); @@ -1261,8 +1272,7 @@ static const char *get_libc_crt_file(CodeGen *parent, const char *file) { codegen_build_and_link(child_gen); return buf_ptr(&child_gen->output_file_path); } else if (strcmp(file, "mingwex.lib") == 0) { - CodeGen *child_gen = create_child_codegen(parent, nullptr, OutTypeLib, nullptr); - codegen_set_out_name(child_gen, buf_create_from_str("mingwex")); + CodeGen *child_gen = create_child_codegen(parent, nullptr, OutTypeLib, nullptr, "mingwex", progress_node); for (size_t i = 0; i < array_length(mingwex_generic_src); i += 1) { add_mingwex_os_dep(parent, child_gen, mingwex_generic_src[i]); @@ -1305,7 +1315,7 @@ static const char *get_libc_crt_file(CodeGen *parent, const char *file) { c_file->args.append("-DASSEMBLER"); c_file->args.append("-g"); c_file->args.append("-Wa,--noexecstack"); - return build_libc_object(parent, "crti", c_file); + return build_libc_object(parent, "crti", c_file, progress_node); } else if (strcmp(file, "crtn.o") == 0) { CFile *c_file = allocate<CFile>(1); c_file->source_path = glibc_start_asm_path(parent, "crtn.S"); @@ -1316,7 +1326,7 @@ static const char *get_libc_crt_file(CodeGen *parent, const char *file) { c_file->args.append("-DASSEMBLER"); c_file->args.append("-g"); c_file->args.append("-Wa,--noexecstack"); - return build_libc_object(parent, "crtn", c_file); + return build_libc_object(parent, "crtn", c_file, progress_node); } else if (strcmp(file, "start.os") == 0) { CFile *c_file = allocate<CFile>(1); c_file->source_path = glibc_start_asm_path(parent, "start.S"); @@ -1334,7 +1344,7 @@ static const char *get_libc_crt_file(CodeGen *parent, const char *file) { c_file->args.append("-DASSEMBLER"); c_file->args.append("-g"); c_file->args.append("-Wa,--noexecstack"); - return build_libc_object(parent, "start", c_file); + return build_libc_object(parent, "start", c_file, progress_node); } else if (strcmp(file, "abi-note.o") == 0) { CFile *c_file = allocate<CFile>(1); c_file->source_path = path_from_libc(parent, "glibc" OS_SEP "csu" OS_SEP "abi-note.S"); @@ -1347,19 +1357,17 @@ static const char *get_libc_crt_file(CodeGen *parent, const char *file) { c_file->args.append("-DASSEMBLER"); c_file->args.append("-g"); c_file->args.append("-Wa,--noexecstack"); - return build_libc_object(parent, "abi-note", c_file); + return build_libc_object(parent, "abi-note", c_file, progress_node); } else if (strcmp(file, "Scrt1.o") == 0) { - const char *start_os = get_libc_crt_file(parent, "start.os"); - const char *abi_note_o = get_libc_crt_file(parent, "abi-note.o"); - CodeGen *child_gen = create_child_codegen(parent, nullptr, OutTypeObj, nullptr); - codegen_set_out_name(child_gen, buf_create_from_str("Scrt1")); + const char *start_os = get_libc_crt_file(parent, "start.os", progress_node); + const char *abi_note_o = get_libc_crt_file(parent, "abi-note.o", progress_node); + CodeGen *child_gen = create_child_codegen(parent, nullptr, OutTypeObj, nullptr, "Scrt1", progress_node); codegen_add_object(child_gen, buf_create_from_str(start_os)); codegen_add_object(child_gen, buf_create_from_str(abi_note_o)); codegen_build_and_link(child_gen); return buf_ptr(&child_gen->output_file_path); } else if (strcmp(file, "libc_nonshared.a") == 0) { - CodeGen *child_gen = create_child_codegen(parent, nullptr, OutTypeLib, nullptr); - codegen_set_out_name(child_gen, buf_create_from_str("c_nonshared")); + CodeGen *child_gen = create_child_codegen(parent, nullptr, OutTypeLib, nullptr, "c_nonshared", progress_node); { CFile *c_file = allocate<CFile>(1); c_file->source_path = path_from_libc(parent, "glibc" OS_SEP "csu" OS_SEP "elf-init.c"); @@ -1388,7 +1396,8 @@ static const char *get_libc_crt_file(CodeGen *parent, const char *file) { c_file->args.append("-DPIC"); c_file->args.append("-DLIBC_NONSHARED=1"); c_file->args.append("-DTOP_NAMESPACE=glibc"); - codegen_add_object(child_gen, buf_create_from_str(build_libc_object(parent, "elf-init", c_file))); + codegen_add_object(child_gen, buf_create_from_str( + build_libc_object(parent, "elf-init", c_file, progress_node))); } static const struct { const char *name; @@ -1432,7 +1441,8 @@ static const char *get_libc_crt_file(CodeGen *parent, const char *file) { c_file->args.append("-DPIC"); c_file->args.append("-DLIBC_NONSHARED=1"); c_file->args.append("-DTOP_NAMESPACE=glibc"); - codegen_add_object(child_gen, buf_create_from_str(build_libc_object(parent, deps[i].name, c_file))); + codegen_add_object(child_gen, buf_create_from_str( + build_libc_object(parent, deps[i].name, c_file, progress_node))); } codegen_build_and_link(child_gen); return buf_ptr(&child_gen->output_file_path); @@ -1445,20 +1455,20 @@ static const char *get_libc_crt_file(CodeGen *parent, const char *file) { c_file->source_path = musl_start_asm_path(parent, "crti.s"); musl_add_cc_args(parent, c_file, false); c_file->args.append("-Qunused-arguments"); - return build_libc_object(parent, "crti", c_file); + return build_libc_object(parent, "crti", c_file, progress_node); } else if (strcmp(file, "crtn.o") == 0) { CFile *c_file = allocate<CFile>(1); c_file->source_path = musl_start_asm_path(parent, "crtn.s"); c_file->args.append("-Qunused-arguments"); musl_add_cc_args(parent, c_file, false); - return build_libc_object(parent, "crtn", c_file); + return build_libc_object(parent, "crtn", c_file, progress_node); } else if (strcmp(file, "crt1.o") == 0) { CFile *c_file = allocate<CFile>(1); c_file->source_path = path_from_libc(parent, "musl" OS_SEP "crt" OS_SEP "crt1.c"); musl_add_cc_args(parent, c_file, false); c_file->args.append("-fno-stack-protector"); c_file->args.append("-DCRT"); - return build_libc_object(parent, "crt1", c_file); + return build_libc_object(parent, "crt1", c_file, progress_node); } else if (strcmp(file, "Scrt1.o") == 0) { CFile *c_file = allocate<CFile>(1); c_file->source_path = path_from_libc(parent, "musl" OS_SEP "crt" OS_SEP "Scrt1.c"); @@ -1466,7 +1476,7 @@ static const char *get_libc_crt_file(CodeGen *parent, const char *file) { c_file->args.append("-fPIC"); c_file->args.append("-fno-stack-protector"); c_file->args.append("-DCRT"); - return build_libc_object(parent, "Scrt1", c_file); + return build_libc_object(parent, "Scrt1", c_file, progress_node); } else { zig_unreachable(); } @@ -1478,10 +1488,11 @@ static const char *get_libc_crt_file(CodeGen *parent, const char *file) { } } -static Buf *build_a_raw(CodeGen *parent_gen, const char *aname, Buf *full_path, OutType child_out_type) { - CodeGen *child_gen = create_child_codegen(parent_gen, full_path, child_out_type, - parent_gen->libc); - codegen_set_out_name(child_gen, buf_create_from_str(aname)); +static Buf *build_a_raw(CodeGen *parent_gen, const char *aname, Buf *full_path, OutType child_out_type, + Stage2ProgressNode *progress_node) +{ + CodeGen *child_gen = create_child_codegen(parent_gen, full_path, child_out_type, parent_gen->libc, aname, + progress_node); // This is so that compiler_rt and libc.zig libraries know whether they // will eventually be linked with libc. They make different decisions @@ -1498,18 +1509,18 @@ static Buf *build_a_raw(CodeGen *parent_gen, const char *aname, Buf *full_path, return &child_gen->output_file_path; } -static Buf *build_compiler_rt(CodeGen *parent_gen, OutType child_out_type) { +static Buf *build_compiler_rt(CodeGen *parent_gen, OutType child_out_type, Stage2ProgressNode *progress_node) { Buf *full_path = buf_alloc(); os_path_join(parent_gen->zig_std_special_dir, buf_create_from_str("compiler_rt.zig"), full_path); - return build_a_raw(parent_gen, "compiler_rt", full_path, child_out_type); + return build_a_raw(parent_gen, "compiler_rt", full_path, child_out_type, progress_node); } -static Buf *build_c(CodeGen *parent_gen, OutType child_out_type) { +static Buf *build_c(CodeGen *parent_gen, OutType child_out_type, Stage2ProgressNode *progress_node) { Buf *full_path = buf_alloc(); os_path_join(parent_gen->zig_std_special_dir, buf_create_from_str("c.zig"), full_path); - return build_a_raw(parent_gen, "c", full_path, child_out_type); + return build_a_raw(parent_gen, "c", full_path, child_out_type, progress_node); } static const char *get_darwin_arch_string(const ZigTarget *t) { @@ -1603,7 +1614,7 @@ static void add_glibc_libs(LinkJob *lj) { Buf *artifact_dir; if ((err = glibc_build_dummies_and_maps(lj->codegen, glibc_abi, lj->codegen->zig_target, - &artifact_dir, true))) + &artifact_dir, true, lj->build_dep_prog_node))) { fprintf(stderr, "%s\n", err_str(err)); exit(1); @@ -1636,6 +1647,10 @@ static void construct_linker_job_elf(LinkJob *lj) { lj->args.append("--gc-sections"); } + if (g->link_eh_frame_hdr) { + lj->args.append("--eh-frame-hdr"); + } + lj->args.append("-m"); lj->args.append(getLDMOption(g->zig_target)); @@ -1679,9 +1694,9 @@ static void construct_linker_job_elf(LinkJob *lj) { } else { crt1o = "Scrt1.o"; } - lj->args.append(get_libc_crt_file(g, crt1o)); + lj->args.append(get_libc_crt_file(g, crt1o, lj->build_dep_prog_node)); if (target_libc_needs_crti_crtn(g->zig_target)) { - lj->args.append(get_libc_crt_file(g, "crti.o")); + lj->args.append(get_libc_crt_file(g, "crti.o", lj->build_dep_prog_node)); } } @@ -1746,11 +1761,11 @@ static void construct_linker_job_elf(LinkJob *lj) { if (!g->is_dummy_so && (g->out_type == OutTypeExe || is_dyn_lib)) { if (g->libc_link_lib == nullptr) { - Buf *libc_a_path = build_c(g, OutTypeLib); + Buf *libc_a_path = build_c(g, OutTypeLib, lj->build_dep_prog_node); lj->args.append(buf_ptr(libc_a_path)); } - Buf *compiler_rt_o_path = build_compiler_rt(g, OutTypeLib); + Buf *compiler_rt_o_path = build_compiler_rt(g, OutTypeLib, lj->build_dep_prog_node); lj->args.append(buf_ptr(compiler_rt_o_path)); } @@ -1781,28 +1796,12 @@ static void construct_linker_job_elf(LinkJob *lj) { if (g->libc != nullptr) { if (!g->have_dynamic_link) { lj->args.append("--start-group"); - if (!target_is_android(g->zig_target)) { - lj->args.append("-lgcc"); - lj->args.append("-lgcc_eh"); - } lj->args.append("-lc"); lj->args.append("-lm"); lj->args.append("--end-group"); } else { - if (!target_is_android(g->zig_target)) { - lj->args.append("-lgcc"); - lj->args.append("--as-needed"); - lj->args.append("-lgcc_s"); - lj->args.append("--no-as-needed"); - } lj->args.append("-lc"); lj->args.append("-lm"); - if (!target_is_android(g->zig_target)) { - lj->args.append("-lgcc"); - lj->args.append("--as-needed"); - lj->args.append("-lgcc_s"); - lj->args.append("--no-as-needed"); - } } if (g->zig_target->os == OsFreeBSD) { @@ -1810,15 +1809,15 @@ static void construct_linker_job_elf(LinkJob *lj) { } } else if (target_is_glibc(g->zig_target)) { if (target_supports_libunwind(g->zig_target)) { - lj->args.append(build_libunwind(g)); + lj->args.append(build_libunwind(g, lj->build_dep_prog_node)); } add_glibc_libs(lj); - lj->args.append(get_libc_crt_file(g, "libc_nonshared.a")); + lj->args.append(get_libc_crt_file(g, "libc_nonshared.a", lj->build_dep_prog_node)); } else if (target_is_musl(g->zig_target)) { if (target_supports_libunwind(g->zig_target)) { - lj->args.append(build_libunwind(g)); + lj->args.append(build_libunwind(g, lj->build_dep_prog_node)); } - lj->args.append(build_musl(g)); + lj->args.append(build_musl(g, lj->build_dep_prog_node)); } else { zig_unreachable(); } @@ -1827,21 +1826,15 @@ static void construct_linker_job_elf(LinkJob *lj) { // crt end if (lj->link_in_crt) { if (target_is_android(g->zig_target)) { - lj->args.append(get_libc_crt_file(g, "crtend_android.o")); + lj->args.append(get_libc_crt_file(g, "crtend_android.o", lj->build_dep_prog_node)); } else if (target_libc_needs_crti_crtn(g->zig_target)) { - lj->args.append(get_libc_crt_file(g, "crtn.o")); + lj->args.append(get_libc_crt_file(g, "crtn.o", lj->build_dep_prog_node)); } } if (!g->zig_target->is_native) { lj->args.append("--allow-shlib-undefined"); } - - if (g->zig_target->os == OsZen) { - lj->args.append("-e"); - lj->args.append("_start"); - lj->args.append("--image-base=0x10000000"); - } } static void construct_linker_job_wasm(LinkJob *lj) { @@ -1874,10 +1867,10 @@ static void construct_linker_job_wasm(LinkJob *lj) { } if (g->out_type != OutTypeObj) { - Buf *libc_o_path = build_c(g, OutTypeObj); + Buf *libc_o_path = build_c(g, OutTypeObj, lj->build_dep_prog_node); lj->args.append(buf_ptr(libc_o_path)); - Buf *compiler_rt_o_path = build_compiler_rt(g, OutTypeObj); + Buf *compiler_rt_o_path = build_compiler_rt(g, OutTypeObj, lj->build_dep_prog_node); lj->args.append(buf_ptr(compiler_rt_o_path)); } } @@ -1955,7 +1948,7 @@ static void print_zig_cc_cmd(ZigList<const char *> *args) { fprintf(stderr, "\n"); } -static const char *get_def_lib(CodeGen *parent, const char *name, Buf *def_in_rel_path) { +static const char *get_def_lib(CodeGen *parent, const char *name, Buf *def_in_file) { Error err; Buf *self_exe_path = buf_alloc(); @@ -1969,12 +1962,10 @@ static const char *get_def_lib(CodeGen *parent, const char *name, Buf *def_in_re exit(1); } - Buf *cache_dir = get_stage1_cache_path(); + Buf *cache_dir = get_global_cache_dir(); Buf *o_dir = buf_sprintf("%s" OS_SEP CACHE_OUT_SUBDIR, buf_ptr(cache_dir)); Buf *manifest_dir = buf_sprintf("%s" OS_SEP CACHE_HASH_SUBDIR, buf_ptr(cache_dir)); - Buf *def_in_file = buf_sprintf("%s" OS_SEP "libc" OS_SEP "mingw" OS_SEP "%s", - buf_ptr(parent->zig_lib_dir), buf_ptr(def_in_rel_path)); Buf *def_include_dir = buf_sprintf("%s" OS_SEP "libc" OS_SEP "mingw" OS_SEP "def-include", buf_ptr(parent->zig_lib_dir)); @@ -2062,18 +2053,12 @@ static const char *get_def_lib(CodeGen *parent, const char *name, Buf *def_in_re lib_final_path = buf_alloc(); os_path_join(artifact_dir, final_lib_basename, lib_final_path); - args.resize(0); - args.append("link"); - coff_append_machine_arg(parent, &args); - - args.append(buf_ptr(buf_sprintf("-DEF:%s", buf_ptr(def_final_path)))); - args.append(buf_ptr(buf_sprintf("-OUT:%s", buf_ptr(lib_final_path)))); - - Buf diag = BUF_INIT; - ZigLLVM_ObjectFormatType target_ofmt = target_object_format(parent->zig_target); - if (!zig_lld_link(target_ofmt, args.items, args.length, &diag)) { - fprintf(stderr, "%s\n", buf_ptr(&diag)); - exit(1); + if (ZigLLVMWriteImportLibrary(buf_ptr(def_final_path), + parent->zig_target->arch, + buf_ptr(lib_final_path), + /* kill_at */ true)) + { + zig_panic("link: could not emit %s", buf_ptr(lib_final_path)); } } else { // cache hit @@ -2097,6 +2082,60 @@ static bool is_linking_system_lib(CodeGen *g, const char *name) { return false; } +static Error find_mingw_lib_def(LinkJob *lj, const char *name, Buf *out_path) { + CodeGen *g = lj->codegen; + Buf override_path = BUF_INIT; + Error err; + + char const *lib_path = nullptr; + if (g->zig_target->arch == ZigLLVM_x86) { + lib_path = "lib32"; + } else if (g->zig_target->arch == ZigLLVM_x86_64) { + lib_path = "lib64"; + } else if (target_is_arm(g->zig_target)) { + const bool is_32 = target_arch_pointer_bit_width(g->zig_target->arch) == 32; + lib_path = is_32 ? "libarm32" : "libarm64"; + } else { + zig_unreachable(); + } + + // Try the archtecture-specific path first + buf_resize(&override_path, 0); + buf_appendf(&override_path, "%s" OS_SEP "libc" OS_SEP "mingw" OS_SEP "%s" OS_SEP "%s.def", buf_ptr(g->zig_lib_dir), lib_path, name); + + bool does_exist; + if ((err = os_file_exists(&override_path, &does_exist)) != ErrorNone) { + return err; + } + + if (!does_exist) { + // Try the generic version + buf_resize(&override_path, 0); + buf_appendf(&override_path, "%s" OS_SEP "libc" OS_SEP "mingw" OS_SEP "lib-common" OS_SEP "%s.def", buf_ptr(g->zig_lib_dir), name); + + if ((err = os_file_exists(&override_path, &does_exist)) != ErrorNone) { + return err; + } + } + + if (!does_exist) { + // Try the generic version and preprocess it + buf_resize(&override_path, 0); + buf_appendf(&override_path, "%s" OS_SEP "libc" OS_SEP "mingw" OS_SEP "lib-common" OS_SEP "%s.def.in", buf_ptr(g->zig_lib_dir), name); + + if ((err = os_file_exists(&override_path, &does_exist)) != ErrorNone) { + return err; + } + } + + if (!does_exist) { + return ErrorFileNotFound; + } + + buf_init_from_buf(out_path, &override_path); + return ErrorNone; +} + static void add_mingw_link_args(LinkJob *lj, bool is_library) { CodeGen *g = lj->codegen; @@ -2111,35 +2150,31 @@ static void add_mingw_link_args(LinkJob *lj, bool is_library) { } if (is_dll) { - lj->args.append(get_libc_crt_file(g, "dllcrt2.o")); + lj->args.append(get_libc_crt_file(g, "dllcrt2.o", lj->build_dep_prog_node)); } else { - lj->args.append(get_libc_crt_file(g, "crt2.o")); + lj->args.append(get_libc_crt_file(g, "crt2.o", lj->build_dep_prog_node)); } - lj->args.append(get_libc_crt_file(g, "mingw32.lib")); - lj->args.append(get_libc_crt_file(g, "mingwex.lib")); - lj->args.append(get_libc_crt_file(g, "msvcrt-os.lib")); + lj->args.append(get_libc_crt_file(g, "mingw32.lib", lj->build_dep_prog_node)); + lj->args.append(get_libc_crt_file(g, "mingwex.lib", lj->build_dep_prog_node)); + lj->args.append(get_libc_crt_file(g, "msvcrt-os.lib", lj->build_dep_prog_node)); for (size_t def_i = 0; def_i < array_length(mingw_def_list); def_i += 1) { const char *name = mingw_def_list[def_i].name; - Buf *path = buf_create_from_str(mingw_def_list[def_i].path); - bool always_link = mingw_def_list[def_i].always_link; - bool is_this_arch = false; - if (buf_starts_with_str(path, "lib-common" OS_SEP)) { - is_this_arch = true; - } else if (target_is_arm(g->zig_target)) { - if (target_arch_pointer_bit_width(g->zig_target->arch) == 32) { - is_this_arch = buf_starts_with_str(path, "libarm32" OS_SEP); - } else { - is_this_arch = buf_starts_with_str(path, "libarm64" OS_SEP); + const bool always_link = mingw_def_list[def_i].always_link; + + if (always_link || is_linking_system_lib(g, name)) { + Buf lib_path = BUF_INIT; + Error err = find_mingw_lib_def(lj, name, &lib_path); + + if (err == ErrorFileNotFound) { + zig_panic("link: could not find .def file to build %s\n", name); + } else if (err != ErrorNone) { + zig_panic("link: unable to check if .def file for %s exists: %s", + name, err_str(err)); } - } else if (g->zig_target->arch == ZigLLVM_x86) { - is_this_arch = buf_starts_with_str(path, "lib32" OS_SEP); - } else if (g->zig_target->arch == ZigLLVM_x86_64) { - is_this_arch = buf_starts_with_str(path, "lib64" OS_SEP); - } - if (is_this_arch && (always_link || is_linking_system_lib(g, name))) { - lj->args.append(get_def_lib(g, name, path)); + + lj->args.append(get_def_lib(g, name, &lib_path)); } } } @@ -2264,17 +2299,15 @@ static void construct_linker_job_coff(LinkJob *lj) { if (g->out_type == OutTypeExe || (g->out_type == OutTypeLib && g->is_dynamic)) { if (g->libc_link_lib == nullptr && !g->is_dummy_so) { - Buf *libc_a_path = build_c(g, OutTypeLib); + Buf *libc_a_path = build_c(g, OutTypeLib, lj->build_dep_prog_node); lj->args.append(buf_ptr(libc_a_path)); } // msvc compiler_rt is missing some stuff, so we still build it and rely on weak linkage - Buf *compiler_rt_o_path = build_compiler_rt(g, OutTypeLib); + Buf *compiler_rt_o_path = build_compiler_rt(g, OutTypeLib, lj->build_dep_prog_node); lj->args.append(buf_ptr(compiler_rt_o_path)); } - Buf *def_contents = buf_alloc(); - ZigList<const char *> gen_lib_args = {0}; for (size_t lib_i = 0; lib_i < g->link_libs_list.length; lib_i += 1) { LinkLib *link_lib = g->link_libs_list.at(lib_i); if (buf_eql_str(link_lib->name, "c")) { @@ -2297,36 +2330,27 @@ static void construct_linker_job_coff(LinkJob *lj) { continue; } - buf_resize(def_contents, 0); - buf_appendf(def_contents, "LIBRARY %s\nEXPORTS\n", buf_ptr(link_lib->name)); - for (size_t exp_i = 0; exp_i < link_lib->symbols.length; exp_i += 1) { - Buf *symbol_name = link_lib->symbols.at(exp_i); - buf_appendf(def_contents, "%s\n", buf_ptr(symbol_name)); - } - buf_appendf(def_contents, "\n"); - - Buf *def_path = buf_alloc(); - os_path_join(g->output_dir, buf_sprintf("%s.def", buf_ptr(link_lib->name)), def_path); - if ((err = os_write_file(def_path, def_contents))) { - zig_panic("error writing def file: %s", err_str(err)); - } + // This library may be a system one and we may have a suitable .lib file - Buf *generated_lib_path = buf_alloc(); - os_path_join(g->output_dir, buf_sprintf("%s.lib", buf_ptr(link_lib->name)), generated_lib_path); + // Normalize the library name to lower case, the FS may be + // case-sensitive + char *name = strdup(buf_ptr(link_lib->name)); + assert(name != nullptr); + for (char *ch = name; *ch; ++ch) *ch = tolower(*ch); - gen_lib_args.resize(0); - gen_lib_args.append("link"); + Buf lib_path = BUF_INIT; + err = find_mingw_lib_def(lj, name, &lib_path); - coff_append_machine_arg(g, &gen_lib_args); - gen_lib_args.append(buf_ptr(buf_sprintf("-DEF:%s", buf_ptr(def_path)))); - gen_lib_args.append(buf_ptr(buf_sprintf("-OUT:%s", buf_ptr(generated_lib_path)))); - Buf diag = BUF_INIT; - ZigLLVM_ObjectFormatType target_ofmt = target_object_format(g->zig_target); - if (!zig_lld_link(target_ofmt, gen_lib_args.items, gen_lib_args.length, &diag)) { - fprintf(stderr, "%s\n", buf_ptr(&diag)); - exit(1); + if (err == ErrorFileNotFound) { + zig_panic("link: could not find .def file to build %s\n", name); + } else if (err != ErrorNone) { + zig_panic("link: unable to check if .def file for %s exists: %s", + name, err_str(err)); } - lj->args.append(buf_ptr(generated_lib_path)); + + lj->args.append(get_def_lib(g, name, &lib_path)); + + free(name); } } @@ -2519,7 +2543,7 @@ static void construct_linker_job_macho(LinkJob *lj) { // compiler_rt on darwin is missing some stuff, so we still build it and rely on LinkOnce if (g->out_type == OutTypeExe || is_dyn_lib) { - Buf *compiler_rt_o_path = build_compiler_rt(g, OutTypeLib); + Buf *compiler_rt_o_path = build_compiler_rt(g, OutTypeLib, lj->build_dep_prog_node); lj->args.append(buf_ptr(compiler_rt_o_path)); } @@ -2577,16 +2601,23 @@ static void construct_linker_job(LinkJob *lj) { } } -void zig_link_add_compiler_rt(CodeGen *g) { - Buf *compiler_rt_o_path = build_compiler_rt(g, OutTypeObj); +void zig_link_add_compiler_rt(CodeGen *g, Stage2ProgressNode *progress_node) { + Buf *compiler_rt_o_path = build_compiler_rt(g, OutTypeObj, progress_node); g->link_objects.append(compiler_rt_o_path); } void codegen_link(CodeGen *g) { codegen_add_time_event(g, "Build Dependencies"); - LinkJob lj = {0}; + { + const char *progress_name = "Build Dependencies"; + codegen_switch_sub_prog_node(g, stage2_progress_start(g->main_progress_node, + progress_name, strlen(progress_name), 0)); + lj.build_dep_prog_node = g->sub_progress_node; + } + + // even though we're calling LLD as a library it thinks the first // argument is its own exe name lj.args.append("lld"); @@ -2612,6 +2643,11 @@ void codegen_link(CodeGen *g) { } ZigLLVM_OSType os_type = get_llvm_os_type(g->zig_target->os); codegen_add_time_event(g, "LLVM Link"); + { + const char *progress_name = "Link"; + codegen_switch_sub_prog_node(g, stage2_progress_start(g->main_progress_node, + progress_name, strlen(progress_name), 0)); + } if (g->verbose_link) { fprintf(stderr, "ar rcs %s", buf_ptr(&g->output_file_path)); for (size_t i = 0; i < file_names.length; i += 1) { @@ -2642,6 +2678,11 @@ void codegen_link(CodeGen *g) { Buf diag = BUF_INIT; codegen_add_time_event(g, "LLVM Link"); + { + const char *progress_name = "Link"; + codegen_switch_sub_prog_node(g, stage2_progress_start(g->main_progress_node, + progress_name, strlen(progress_name), 0)); + } if (g->system_linker_hack && g->zig_target->os == OsMacOSX) { Termination term; ZigList<const char *> args = {}; |
