aboutsummaryrefslogtreecommitdiff
path: root/src/link.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/link.cpp')
-rw-r--r--src/link.cpp94
1 files changed, 69 insertions, 25 deletions
diff --git a/src/link.cpp b/src/link.cpp
index aa0edde61b..0e729fa918 100644
--- a/src/link.cpp
+++ b/src/link.cpp
@@ -29,12 +29,22 @@ static const char *get_libc_static_file(CodeGen *g, const char *file) {
return buf_ptr(out_buf);
}
-static Buf *build_o_raw(CodeGen *parent_gen, const char *oname, Buf *full_path) {
+static Buf *build_a_raw(CodeGen *parent_gen, const char *aname, Buf *full_path) {
ZigTarget *child_target = parent_gen->is_native_target ? nullptr : &parent_gen->zig_target;
- CodeGen *child_gen = codegen_create(full_path, child_target, OutTypeObj, parent_gen->build_mode,
- parent_gen->zig_lib_dir);
- child_gen->want_h_file = false;
+ // The Mach-O LLD code is not well maintained, and trips an assertion
+ // when we link compiler_rt and builtin as libraries rather than objects.
+ // Here we workaround this by having compiler_rt and builtin be objects.
+ // TODO write our own linker. https://github.com/ziglang/zig/issues/1535
+ OutType child_out_type = OutTypeLib;
+ if (parent_gen->zig_target.os == OsMacOSX) {
+ child_out_type = OutTypeObj;
+ }
+
+ CodeGen *child_gen = codegen_create(full_path, child_target, child_out_type,
+ parent_gen->build_mode, parent_gen->zig_lib_dir);
+
+ child_gen->out_h_path = nullptr;
child_gen->verbose_tokenize = parent_gen->verbose_tokenize;
child_gen->verbose_ast = parent_gen->verbose_ast;
child_gen->verbose_link = parent_gen->verbose_link;
@@ -43,19 +53,22 @@ static Buf *build_o_raw(CodeGen *parent_gen, const char *oname, Buf *full_path)
child_gen->verbose_cimport = parent_gen->verbose_cimport;
codegen_set_strip(child_gen, parent_gen->strip_debug_symbols);
- codegen_set_is_static(child_gen, parent_gen->is_static);
+ codegen_set_is_static(child_gen, true);
+ child_gen->disable_pic = parent_gen->disable_pic;
- codegen_set_out_name(child_gen, buf_create_from_str(oname));
+ codegen_set_out_name(child_gen, buf_create_from_str(aname));
codegen_set_errmsg_color(child_gen, parent_gen->err_color);
codegen_set_mmacosx_version_min(child_gen, parent_gen->mmacosx_version_min);
codegen_set_mios_version_min(child_gen, parent_gen->mios_version_min);
- for (size_t i = 0; i < parent_gen->link_libs_list.length; i += 1) {
- LinkLib *link_lib = parent_gen->link_libs_list.at(i);
- LinkLib *new_link_lib = codegen_add_link_lib(child_gen, link_lib->name);
- new_link_lib->provided_explicitly = link_lib->provided_explicitly;
+ // This is so that compiler_rt and builtin libraries know whether they
+ // will eventually be linked with libc. They make different decisions
+ // about what to export depending on whether libc is linked.
+ if (parent_gen->libc_link_lib != nullptr) {
+ LinkLib *new_link_lib = codegen_add_link_lib(child_gen, parent_gen->libc_link_lib->name);
+ new_link_lib->provided_explicitly = parent_gen->libc_link_lib->provided_explicitly;
}
child_gen->enable_cache = true;
@@ -63,12 +76,12 @@ static Buf *build_o_raw(CodeGen *parent_gen, const char *oname, Buf *full_path)
return &child_gen->output_file_path;
}
-static Buf *build_o(CodeGen *parent_gen, const char *oname) {
- Buf *source_basename = buf_sprintf("%s.zig", oname);
+static Buf *build_a(CodeGen *parent_gen, const char *aname) {
+ Buf *source_basename = buf_sprintf("%s.zig", aname);
Buf *full_path = buf_alloc();
os_path_join(parent_gen->zig_std_special_dir, source_basename, full_path);
- return build_o_raw(parent_gen, oname, full_path);
+ return build_a_raw(parent_gen, aname, full_path);
}
static Buf *build_compiler_rt(CodeGen *parent_gen) {
@@ -77,7 +90,7 @@ static Buf *build_compiler_rt(CodeGen *parent_gen) {
Buf *full_path = buf_alloc();
os_path_join(dir_path, buf_create_from_str("index.zig"), full_path);
- return build_o_raw(parent_gen, "compiler_rt", full_path);
+ return build_a_raw(parent_gen, "compiler_rt", full_path);
}
static const char *get_darwin_arch_string(const ZigTarget *t) {
@@ -197,6 +210,8 @@ static Buf *get_dynamic_linker_path(CodeGen *g) {
static void construct_linker_job_elf(LinkJob *lj) {
CodeGen *g = lj->codegen;
+ lj->args.append("-error-limit=0");
+
if (g->libc_link_lib != nullptr) {
find_libc_lib_path(g);
}
@@ -314,10 +329,10 @@ static void construct_linker_job_elf(LinkJob *lj) {
lj->args.append((const char *)buf_ptr(g->link_objects.at(i)));
}
- if (g->out_type == OutTypeExe || g->out_type == OutTypeLib) {
+ if (g->out_type == OutTypeExe || (g->out_type == OutTypeLib && !g->is_static)) {
if (g->libc_link_lib == nullptr) {
- Buf *builtin_o_path = build_o(g, "builtin");
- lj->args.append(buf_ptr(builtin_o_path));
+ Buf *builtin_a_path = build_a(g, "builtin");
+ lj->args.append(buf_ptr(builtin_a_path));
}
// sometimes libgcc is missing stuff, so we still build compiler_rt and rely on weak linkage
@@ -386,7 +401,8 @@ static void construct_linker_job_elf(LinkJob *lj) {
static void construct_linker_job_wasm(LinkJob *lj) {
CodeGen *g = lj->codegen;
- lj->args.append("--relocatable"); // So lld doesn't look for _start.
+ lj->args.append("-error-limit=0");
+ lj->args.append("--no-entry"); // So lld doesn't look for _start.
lj->args.append("-o");
lj->args.append(buf_ptr(&g->output_file_path));
@@ -424,6 +440,8 @@ static bool zig_lld_link(ZigLLVM_ObjectFormatType oformat, const char **args, si
static void construct_linker_job_coff(LinkJob *lj) {
CodeGen *g = lj->codegen;
+ lj->args.append("/ERRORLIMIT:0");
+
if (g->libc_link_lib != nullptr) {
find_libc_lib_path(g);
}
@@ -434,6 +452,11 @@ static void construct_linker_job_coff(LinkJob *lj) {
lj->args.append("-DEBUG");
}
+ if (g->out_type == OutTypeExe) {
+ // TODO compile time stack upper bound detection
+ lj->args.append("/STACK:16777216");
+ }
+
coff_append_machine_arg(g, &lj->args);
if (g->windows_subsystem_windows) {
@@ -540,10 +563,10 @@ static void construct_linker_job_coff(LinkJob *lj) {
lj->args.append((const char *)buf_ptr(g->link_objects.at(i)));
}
- if (g->out_type == OutTypeExe || g->out_type == OutTypeLib) {
+ if (g->out_type == OutTypeExe || (g->out_type == OutTypeLib && !g->is_static)) {
if (g->libc_link_lib == nullptr) {
- Buf *builtin_o_path = build_o(g, "builtin");
- lj->args.append(buf_ptr(builtin_o_path));
+ Buf *builtin_a_path = build_a(g, "builtin");
+ lj->args.append(buf_ptr(builtin_a_path));
}
// msvc compiler_rt is missing some stuff, so we still build it and rely on weak linkage
@@ -755,6 +778,8 @@ static bool darwin_version_lt(DarwinPlatform *platform, int major, int minor) {
static void construct_linker_job_macho(LinkJob *lj) {
CodeGen *g = lj->codegen;
+ // LLD MACH-O has no error limit option.
+ //lj->args.append("-error-limit=0");
lj->args.append("-demangle");
if (g->linker_rdynamic) {
@@ -872,7 +897,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 || g->out_type == OutTypeLib) {
+ if (g->out_type == OutTypeExe || (g->out_type == OutTypeLib && !g->is_static)) {
Buf *compiler_rt_o_path = build_compiler_rt(g);
lj->args.append(buf_ptr(compiler_rt_o_path));
}
@@ -954,8 +979,17 @@ void codegen_link(CodeGen *g) {
}
if (g->out_type == OutTypeLib && g->is_static) {
- fprintf(stderr, "Zig does not yet support creating static libraries\nSee https://github.com/ziglang/zig/issues/1493\n");
- exit(1);
+ ZigList<const char *> file_names = {};
+ for (size_t i = 0; i < g->link_objects.length; i += 1) {
+ file_names.append((const char *)buf_ptr(g->link_objects.at(i)));
+ }
+ ZigLLVM_OSType os_type = get_llvm_os_type(g->zig_target.os);
+ codegen_add_time_event(g, "LLVM Link");
+ if (ZigLLVMWriteArchive(buf_ptr(&g->output_file_path), file_names.items, file_names.length, os_type)) {
+ fprintf(stderr, "Unable to write archive '%s'\n", buf_ptr(&g->output_file_path));
+ exit(1);
+ }
+ return;
}
lj.link_in_crt = (g->libc_link_lib != nullptr && g->out_type == OutTypeExe);
@@ -974,7 +1008,17 @@ void codegen_link(CodeGen *g) {
Buf diag = BUF_INIT;
codegen_add_time_event(g, "LLVM Link");
- if (!zig_lld_link(g->zig_target.oformat, lj.args.items, lj.args.length, &diag)) {
+ if (g->system_linker_hack && g->zig_target.os == OsMacOSX) {
+ Termination term;
+ ZigList<const char *> args = {};
+ for (size_t i = 1; i < lj.args.length; i += 1) {
+ args.append(lj.args.at(i));
+ }
+ os_spawn_process("ld", args, &term);
+ if (term.how != TerminationIdClean || term.code != 0) {
+ exit(1);
+ }
+ } else if (!zig_lld_link(g->zig_target.oformat, lj.args.items, lj.args.length, &diag)) {
fprintf(stderr, "%s\n", buf_ptr(&diag));
exit(1);
}