From 5a3c02137e6a15d3b8c1fb3595d55003ea44139a Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 8 Oct 2018 13:24:39 -0400 Subject: support building static libraries closes #1493 closes #54 --- src/codegen.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/codegen.cpp') diff --git a/src/codegen.cpp b/src/codegen.cpp index e792fd77aa..fd7a386078 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -7487,7 +7487,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"); } -- cgit v1.2.3 From 6b93495792678bd00a6205967bb2704a9a35e9c7 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 9 Oct 2018 12:18:09 -0400 Subject: more efficient builtin library code generation * introduce --disable-pic option which can generally be allowed to be the default. compiler_rt.a and builtin.a get this option when you build a static executable. * compiler_rt and builtin libraries are not built for build-lib --static * posix_spawn instead of fork/execv * disable the error limit on LLD. Fixes the blank lines printed --- src/all_types.hpp | 1 + src/codegen.cpp | 6 +++++- src/link.cpp | 19 ++++++++++--------- src/main.cpp | 12 ++++++++++++ src/os.cpp | 34 ++++++++++++++++------------------ 5 files changed, 44 insertions(+), 28 deletions(-) (limited to 'src/codegen.cpp') diff --git a/src/all_types.hpp b/src/all_types.hpp index d7071590d8..a144013947 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -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; diff --git a/src/codegen.cpp b/src/codegen.cpp index fd7a386078..02105b4d2a 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -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; @@ -8047,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); diff --git a/src/link.cpp b/src/link.cpp index c961042324..095d3d79d7 100644 --- a/src/link.cpp +++ b/src/link.cpp @@ -44,6 +44,7 @@ static Buf *build_a_raw(CodeGen *parent_gen, const char *aname, Buf *full_path) codegen_set_strip(child_gen, parent_gen->strip_debug_symbols); 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(aname)); @@ -209,10 +210,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) { @@ -236,7 +236,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 { @@ -287,7 +287,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"); @@ -309,7 +309,7 @@ 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_a_path = build_a(g, "builtin"); lj->args.append(buf_ptr(builtin_a_path)); @@ -339,7 +339,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"); @@ -540,7 +540,7 @@ 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_a_path = build_a(g, "builtin"); lj->args.append(buf_ptr(builtin_a_path)); @@ -872,7 +872,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)); } @@ -969,6 +969,7 @@ void codegen_link(CodeGen *g) { lj.link_in_crt = (g->libc_link_lib != nullptr && g->out_type == OutTypeExe); + lj.args.append("-error-limit=0"); construct_linker_job(&lj); diff --git a/src/main.cpp b/src/main.cpp index f9df802cb3..5e827b5ba6 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -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" @@ -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(1); BuildMode build_mode = BuildModeDebug; @@ -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) { @@ -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); diff --git a/src/os.cpp b/src/os.cpp index ed069b2ff8..e1bd6bd479 100644 --- a/src/os.cpp +++ b/src/os.cpp @@ -46,6 +46,7 @@ typedef SSIZE_T ssize_t; #include #include #include +#include #endif @@ -88,25 +89,22 @@ static void populate_termination(Termination *term, int status) { } static void os_spawn_process_posix(const char *exe, ZigList &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(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(argv)); - zig_panic("execvp failed: %s", strerror(errno)); - } else { - // parent - int status; - waitpid(pid, &status, 0); - populate_termination(term, status); + const char **argv = allocate(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(argv), environ); + if (rc != 0) { + zig_panic("posix_spawn failed: %s", strerror(rc)); + } + + int status; + waitpid(pid, &status, 0); + populate_termination(term, status); } #endif -- cgit v1.2.3