Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/all_types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1763,6 +1763,7 @@ struct CodeGen {
bool linker_rdynamic;
bool no_rosegment_workaround;
bool each_lib_rpath;
bool disable_pic;

Buf *mmacosx_version_min;
Buf *mios_version_min;
Expand Down
10 changes: 8 additions & 2 deletions src/codegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7228,7 +7228,10 @@ static void init(CodeGen *g) {
bool is_optimized = g->build_mode != BuildModeDebug;
LLVMCodeGenOptLevel opt_level = is_optimized ? LLVMCodeGenLevelAggressive : LLVMCodeGenLevelNone;

LLVMRelocMode reloc_mode = g->is_static ? LLVMRelocStatic : LLVMRelocPIC;
if (g->out_type == OutTypeExe && g->is_static) {
g->disable_pic = true;
}
LLVMRelocMode reloc_mode = g->disable_pic ? LLVMRelocStatic : LLVMRelocPIC;

const char *target_specific_cpu_args;
const char *target_specific_features;
Expand Down Expand Up @@ -7487,7 +7490,9 @@ static void gen_root_source(CodeGen *g) {
{
g->bootstrap_import = add_special_code(g, create_bootstrap_pkg(g, g->root_package), "bootstrap.zig");
}
if (g->zig_target.os == OsWindows && !g->have_dllmain_crt_startup && g->out_type == OutTypeLib) {
if (g->zig_target.os == OsWindows && !g->have_dllmain_crt_startup &&
g->out_type == OutTypeLib && !g->is_static)
{
g->bootstrap_import = add_special_code(g, create_bootstrap_pkg(g, g->root_package), "bootstrap_lib.zig");
}

Expand Down Expand Up @@ -8045,6 +8050,7 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) {
cache_bool(ch, g->linker_rdynamic);
cache_bool(ch, g->no_rosegment_workaround);
cache_bool(ch, g->each_lib_rpath);
cache_bool(ch, g->disable_pic);
cache_buf_opt(ch, g->mmacosx_version_min);
cache_buf_opt(ch, g->mios_version_min);
cache_usize(ch, g->version_major);
Expand Down
83 changes: 55 additions & 28 deletions src/link.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,20 @@ 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);

// 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;
Expand All @@ -43,32 +53,35 @@ 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;
codegen_build_and_link(child_gen);
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) {
Expand All @@ -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) {
Expand Down Expand Up @@ -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);
}
Expand All @@ -215,10 +230,9 @@ static void construct_linker_job_elf(LinkJob *lj) {
lj->args.append(getLDMOption(&g->zig_target));

bool is_lib = g->out_type == OutTypeLib;
bool is_static = g->is_static || (!is_lib && g->link_libs_list.length == 0);
bool shared = !is_static && is_lib;
bool shared = !g->is_static && is_lib;
Buf *soname = nullptr;
if (is_static) {
if (g->is_static) {
if (g->zig_target.arch.arch == ZigLLVM_arm || g->zig_target.arch.arch == ZigLLVM_armeb ||
g->zig_target.arch.arch == ZigLLVM_thumb || g->zig_target.arch.arch == ZigLLVM_thumbeb)
{
Expand All @@ -242,7 +256,7 @@ static void construct_linker_job_elf(LinkJob *lj) {
if (lj->link_in_crt) {
const char *crt1o;
const char *crtbegino;
if (is_static) {
if (g->is_static) {
crt1o = "crt1.o";
crtbegino = "crtbeginT.o";
} else {
Expand Down Expand Up @@ -293,7 +307,7 @@ static void construct_linker_job_elf(LinkJob *lj) {
lj->args.append(buf_ptr(g->libc_static_lib_dir));
}

if (!is_static) {
if (!g->is_static) {
if (g->dynamic_linker != nullptr) {
assert(buf_len(g->dynamic_linker) != 0);
lj->args.append("-dynamic-linker");
Expand All @@ -315,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
Expand All @@ -345,7 +359,7 @@ static void construct_linker_job_elf(LinkJob *lj) {

// libc dep
if (g->libc_link_lib != nullptr) {
if (is_static) {
if (g->is_static) {
lj->args.append("--start-group");
lj->args.append("-lgcc");
lj->args.append("-lgcc_eh");
Expand Down Expand Up @@ -387,6 +401,7 @@ static void construct_linker_job_elf(LinkJob *lj) {
static void construct_linker_job_wasm(LinkJob *lj) {
CodeGen *g = lj->codegen;

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));
Expand Down Expand Up @@ -425,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);
}
Expand Down Expand Up @@ -546,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
Expand Down Expand Up @@ -761,6 +778,7 @@ static bool darwin_version_lt(DarwinPlatform *platform, int major, int minor) {
static void construct_linker_job_macho(LinkJob *lj) {
CodeGen *g = lj->codegen;

lj->args.append("-error-limit=0");
lj->args.append("-demangle");

if (g->linker_rdynamic) {
Expand Down Expand Up @@ -878,7 +896,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));
}
Expand Down Expand Up @@ -960,8 +978,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);
Expand Down
12 changes: 12 additions & 0 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ static int print_full_usage(const char *arg0) {
" --cache-dir [path] override the cache directory\n"
" --cache [auto|off|on] build in global cache, print out paths to stdout\n"
" --color [auto|off|on] enable or disable colored error messages\n"
" --disable-pic disable Position Independent Code for libraries\n"
" --emit [asm|bin|llvm-ir] emit a specific file format as compilation output\n"
" -ftime-report print timing diagnostics\n"
" --libc-include-dir [path] directory where libc stdlib.h resides\n"
Expand Down Expand Up @@ -386,6 +387,7 @@ int main(int argc, char **argv) {
size_t ver_minor = 0;
size_t ver_patch = 0;
bool timing_info = false;
bool disable_pic = false;
const char *cache_dir = nullptr;
CliPkg *cur_pkg = allocate<CliPkg>(1);
BuildMode build_mode = BuildModeDebug;
Expand Down Expand Up @@ -556,6 +558,8 @@ int main(int argc, char **argv) {
each_lib_rpath = true;
} else if (strcmp(arg, "-ftime-report") == 0) {
timing_info = true;
} else if (strcmp(arg, "--disable-pic") == 0) {
disable_pic = true;
} else if (strcmp(arg, "--test-cmd-bin") == 0) {
test_exec_args.append(nullptr);
} else if (arg[1] == 'L' && arg[2] != 0) {
Expand Down Expand Up @@ -849,6 +853,14 @@ int main(int argc, char **argv) {
buf_out_name = buf_create_from_str("run");
}
CodeGen *g = codegen_create(zig_root_source_file, target, out_type, build_mode, get_zig_lib_dir());
if (disable_pic) {
if (out_type != OutTypeLib || !is_static) {
fprintf(stderr, "--disable-pic only applies to static libraries");
return EXIT_FAILURE;
}
g->disable_pic = true;
}

g->enable_time_report = timing_info;
buf_init_from_str(&g->cache_dir, cache_dir ? cache_dir : default_zig_cache_name);
codegen_set_out_name(g, buf_out_name);
Expand Down
40 changes: 22 additions & 18 deletions src/os.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ typedef SSIZE_T ssize_t;
#include <sys/wait.h>
#include <fcntl.h>
#include <limits.h>
#include <spawn.h>

#endif

Expand All @@ -70,6 +71,12 @@ static clock_serv_t cclock;
#include <errno.h>
#include <time.h>

// Apple doesn't provide the environ global variable
#if defined(__APPLE__) && !defined(environ)
#include <crt_externs.h>
#define environ (*_NSGetEnviron())
#endif

#if defined(ZIG_OS_POSIX)
static void populate_termination(Termination *term, int status) {
if (WIFEXITED(status)) {
Expand All @@ -88,25 +95,22 @@ static void populate_termination(Termination *term, int status) {
}

static void os_spawn_process_posix(const char *exe, ZigList<const char *> &args, Termination *term) {
pid_t pid = fork();
if (pid == -1)
zig_panic("fork failed: %s", strerror(errno));
if (pid == 0) {
// child
const char **argv = allocate<const char *>(args.length + 2);
argv[0] = exe;
argv[args.length + 1] = nullptr;
for (size_t i = 0; i < args.length; i += 1) {
argv[i + 1] = args.at(i);
}
execvp(exe, const_cast<char * const *>(argv));
zig_panic("execvp failed: %s", strerror(errno));
} else {
// parent
int status;
waitpid(pid, &status, 0);
populate_termination(term, status);
const char **argv = allocate<const char *>(args.length + 2);
argv[0] = exe;
argv[args.length + 1] = nullptr;
for (size_t i = 0; i < args.length; i += 1) {
argv[i + 1] = args.at(i);
}

pid_t pid;
int rc = posix_spawn(&pid, exe, nullptr, nullptr, const_cast<char *const*>(argv), environ);
if (rc != 0) {
zig_panic("posix_spawn failed: %s", strerror(rc));
}

int status;
waitpid(pid, &status, 0);
populate_termination(term, status);
}
#endif

Expand Down
2 changes: 1 addition & 1 deletion src/target.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ Os get_target_os(size_t index) {
return os_list[index];
}

static ZigLLVM_OSType get_llvm_os_type(Os os_type) {
ZigLLVM_OSType get_llvm_os_type(Os os_type) {
switch (os_type) {
case OsFreestanding:
case OsZen:
Expand Down
2 changes: 1 addition & 1 deletion src/target.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,6 @@ const char *target_lib_file_ext(ZigTarget *target, bool is_static, size_t versio
Buf *target_dynamic_linker(ZigTarget *target);

bool target_can_exec(const ZigTarget *host_target, const ZigTarget *guest_target);

ZigLLVM_OSType get_llvm_os_type(Os os_type);

#endif
Loading