aboutsummaryrefslogtreecommitdiff
path: root/src/link.cpp
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2020-01-16 13:01:36 -0500
committerAndrew Kelley <andrew@ziglang.org>2020-01-16 13:01:36 -0500
commitfbe6af81fdb1b964bb0c28f51de2458800b8274c (patch)
tree6d65a49b911ba665a7e2c28c6619d1aa6517a744 /src/link.cpp
parent230d27c1cd00e7adf0ccfca2c8bb73ae1779aa4c (diff)
parent7e5e767ba0fdde91dd66690168eff96b75c28e33 (diff)
downloadzig-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.cpp377
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 = {};