authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-10-09 13:20:27-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2018-10-09 13:20:27-04:00
log9e38a81230bcaefb50fae610c071005449a7abfb
treef706728a6b853da0b66379539018645df583519b
parentd40c4e7c896c5dfed9dd35e8c0d2117f7cf5c53c
parent81c6f087241b6b7a1c12de72a2061cb02df0f93f
signature Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #1647 from ziglang/static-libs

Support building static libraries

11 files changed, 149 insertions(+), 54 deletions(-)

src/all_types.hpp+1
...@@ -1763,6 +1763,7 @@ struct CodeGen {...@@ -1763,6 +1763,7 @@ struct CodeGen {
1763 bool linker_rdynamic;1763 bool linker_rdynamic;
1764 bool no_rosegment_workaround;1764 bool no_rosegment_workaround;
1765 bool each_lib_rpath;1765 bool each_lib_rpath;
1766 bool disable_pic;
17661767
1767 Buf *mmacosx_version_min;1768 Buf *mmacosx_version_min;
1768 Buf *mios_version_min;1769 Buf *mios_version_min;
src/codegen.cpp+8-2
...@@ -7228,7 +7228,10 @@ static void init(CodeGen *g) {...@@ -7228,7 +7228,10 @@ static void init(CodeGen *g) {
7228 bool is_optimized = g->build_mode != BuildModeDebug;7228 bool is_optimized = g->build_mode != BuildModeDebug;
7229 LLVMCodeGenOptLevel opt_level = is_optimized ? LLVMCodeGenLevelAggressive : LLVMCodeGenLevelNone;7229 LLVMCodeGenOptLevel opt_level = is_optimized ? LLVMCodeGenLevelAggressive : LLVMCodeGenLevelNone;
72307230
7231 LLVMRelocMode reloc_mode = g->is_static ? LLVMRelocStatic : LLVMRelocPIC;7231 if (g->out_type == OutTypeExe && g->is_static) {
7232 g->disable_pic = true;
7233 }
7234 LLVMRelocMode reloc_mode = g->disable_pic ? LLVMRelocStatic : LLVMRelocPIC;
72327235
7233 const char *target_specific_cpu_args;7236 const char *target_specific_cpu_args;
7234 const char *target_specific_features;7237 const char *target_specific_features;
...@@ -7487,7 +7490,9 @@ static void gen_root_source(CodeGen *g) {...@@ -7487,7 +7490,9 @@ static void gen_root_source(CodeGen *g) {
7487 {7490 {
7488 g->bootstrap_import = add_special_code(g, create_bootstrap_pkg(g, g->root_package), "bootstrap.zig");7491 g->bootstrap_import = add_special_code(g, create_bootstrap_pkg(g, g->root_package), "bootstrap.zig");
7489 }7492 }
7490 if (g->zig_target.os == OsWindows && !g->have_dllmain_crt_startup && g->out_type == OutTypeLib) {7493 if (g->zig_target.os == OsWindows && !g->have_dllmain_crt_startup &&
7494 g->out_type == OutTypeLib && !g->is_static)
7495 {
7491 g->bootstrap_import = add_special_code(g, create_bootstrap_pkg(g, g->root_package), "bootstrap_lib.zig");7496 g->bootstrap_import = add_special_code(g, create_bootstrap_pkg(g, g->root_package), "bootstrap_lib.zig");
7492 }7497 }
74937498
...@@ -8045,6 +8050,7 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) {...@@ -8045,6 +8050,7 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) {
8045 cache_bool(ch, g->linker_rdynamic);8050 cache_bool(ch, g->linker_rdynamic);
8046 cache_bool(ch, g->no_rosegment_workaround);8051 cache_bool(ch, g->no_rosegment_workaround);
8047 cache_bool(ch, g->each_lib_rpath);8052 cache_bool(ch, g->each_lib_rpath);
8053 cache_bool(ch, g->disable_pic);
8048 cache_buf_opt(ch, g->mmacosx_version_min);8054 cache_buf_opt(ch, g->mmacosx_version_min);
8049 cache_buf_opt(ch, g->mios_version_min);8055 cache_buf_opt(ch, g->mios_version_min);
8050 cache_usize(ch, g->version_major);8056 cache_usize(ch, g->version_major);
src/link.cpp+55-28
...@@ -29,10 +29,20 @@ static const char *get_libc_static_file(CodeGen *g, const char *file) {...@@ -29,10 +29,20 @@ static const char *get_libc_static_file(CodeGen *g, const char *file) {
29 return buf_ptr(out_buf);29 return buf_ptr(out_buf);
30}30}
3131
32static Buf *build_o_raw(CodeGen *parent_gen, const char *oname, Buf *full_path) {32static Buf *build_a_raw(CodeGen *parent_gen, const char *aname, Buf *full_path) {
33 ZigTarget *child_target = parent_gen->is_native_target ? nullptr : &parent_gen->zig_target;33 ZigTarget *child_target = parent_gen->is_native_target ? nullptr : &parent_gen->zig_target;
34 CodeGen *child_gen = codegen_create(full_path, child_target, OutTypeObj, parent_gen->build_mode,34
35 parent_gen->zig_lib_dir);35 // The Mach-O LLD code is not well maintained, and trips an assertion
36 // when we link compiler_rt and builtin as libraries rather than objects.
37 // Here we workaround this by having compiler_rt and builtin be objects.
38 // TODO write our own linker. https://github.com/ziglang/zig/issues/1535
39 OutType child_out_type = OutTypeLib;
40 if (parent_gen->zig_target.os == OsMacOSX) {
41 child_out_type = OutTypeObj;
42 }
43
44 CodeGen *child_gen = codegen_create(full_path, child_target, child_out_type,
45 parent_gen->build_mode, parent_gen->zig_lib_dir);
3646
37 child_gen->out_h_path = nullptr;47 child_gen->out_h_path = nullptr;
38 child_gen->verbose_tokenize = parent_gen->verbose_tokenize;48 child_gen->verbose_tokenize = parent_gen->verbose_tokenize;
...@@ -43,19 +53,22 @@ static Buf *build_o_raw(CodeGen *parent_gen, const char *oname, Buf *full_path)...@@ -43,19 +53,22 @@ static Buf *build_o_raw(CodeGen *parent_gen, const char *oname, Buf *full_path)
43 child_gen->verbose_cimport = parent_gen->verbose_cimport;53 child_gen->verbose_cimport = parent_gen->verbose_cimport;
4454
45 codegen_set_strip(child_gen, parent_gen->strip_debug_symbols);55 codegen_set_strip(child_gen, parent_gen->strip_debug_symbols);
46 codegen_set_is_static(child_gen, parent_gen->is_static);56 codegen_set_is_static(child_gen, true);
57 child_gen->disable_pic = parent_gen->disable_pic;
4758
48 codegen_set_out_name(child_gen, buf_create_from_str(oname));59 codegen_set_out_name(child_gen, buf_create_from_str(aname));
4960
50 codegen_set_errmsg_color(child_gen, parent_gen->err_color);61 codegen_set_errmsg_color(child_gen, parent_gen->err_color);
5162
52 codegen_set_mmacosx_version_min(child_gen, parent_gen->mmacosx_version_min);63 codegen_set_mmacosx_version_min(child_gen, parent_gen->mmacosx_version_min);
53 codegen_set_mios_version_min(child_gen, parent_gen->mios_version_min);64 codegen_set_mios_version_min(child_gen, parent_gen->mios_version_min);
5465
55 for (size_t i = 0; i < parent_gen->link_libs_list.length; i += 1) {66 // This is so that compiler_rt and builtin libraries know whether they
56 LinkLib *link_lib = parent_gen->link_libs_list.at(i);67 // will eventually be linked with libc. They make different decisions
57 LinkLib *new_link_lib = codegen_add_link_lib(child_gen, link_lib->name);68 // about what to export depending on whether libc is linked.
58 new_link_lib->provided_explicitly = link_lib->provided_explicitly;69 if (parent_gen->libc_link_lib != nullptr) {
70 LinkLib *new_link_lib = codegen_add_link_lib(child_gen, parent_gen->libc_link_lib->name);
71 new_link_lib->provided_explicitly = parent_gen->libc_link_lib->provided_explicitly;
59 }72 }
6073
61 child_gen->enable_cache = true;74 child_gen->enable_cache = true;
...@@ -63,12 +76,12 @@ static Buf *build_o_raw(CodeGen *parent_gen, const char *oname, Buf *full_path)...@@ -63,12 +76,12 @@ static Buf *build_o_raw(CodeGen *parent_gen, const char *oname, Buf *full_path)
63 return &child_gen->output_file_path;76 return &child_gen->output_file_path;
64}77}
6578
66static Buf *build_o(CodeGen *parent_gen, const char *oname) {79static Buf *build_a(CodeGen *parent_gen, const char *aname) {
67 Buf *source_basename = buf_sprintf("%s.zig", oname);80 Buf *source_basename = buf_sprintf("%s.zig", aname);
68 Buf *full_path = buf_alloc();81 Buf *full_path = buf_alloc();
69 os_path_join(parent_gen->zig_std_special_dir, source_basename, full_path);82 os_path_join(parent_gen->zig_std_special_dir, source_basename, full_path);
7083
71 return build_o_raw(parent_gen, oname, full_path);84 return build_a_raw(parent_gen, aname, full_path);
72}85}
7386
74static Buf *build_compiler_rt(CodeGen *parent_gen) {87static Buf *build_compiler_rt(CodeGen *parent_gen) {
...@@ -77,7 +90,7 @@ static Buf *build_compiler_rt(CodeGen *parent_gen) {...@@ -77,7 +90,7 @@ static Buf *build_compiler_rt(CodeGen *parent_gen) {
77 Buf *full_path = buf_alloc();90 Buf *full_path = buf_alloc();
78 os_path_join(dir_path, buf_create_from_str("index.zig"), full_path);91 os_path_join(dir_path, buf_create_from_str("index.zig"), full_path);
7992
80 return build_o_raw(parent_gen, "compiler_rt", full_path);93 return build_a_raw(parent_gen, "compiler_rt", full_path);
81}94}
8295
83static const char *get_darwin_arch_string(const ZigTarget *t) {96static const char *get_darwin_arch_string(const ZigTarget *t) {
...@@ -197,6 +210,8 @@ static Buf *get_dynamic_linker_path(CodeGen *g) {...@@ -197,6 +210,8 @@ static Buf *get_dynamic_linker_path(CodeGen *g) {
197static void construct_linker_job_elf(LinkJob *lj) {210static void construct_linker_job_elf(LinkJob *lj) {
198 CodeGen *g = lj->codegen;211 CodeGen *g = lj->codegen;
199212
213 lj->args.append("-error-limit=0");
214
200 if (g->libc_link_lib != nullptr) {215 if (g->libc_link_lib != nullptr) {
201 find_libc_lib_path(g);216 find_libc_lib_path(g);
202 }217 }
...@@ -215,10 +230,9 @@ static void construct_linker_job_elf(LinkJob *lj) {...@@ -215,10 +230,9 @@ static void construct_linker_job_elf(LinkJob *lj) {
215 lj->args.append(getLDMOption(&g->zig_target));230 lj->args.append(getLDMOption(&g->zig_target));
216231
217 bool is_lib = g->out_type == OutTypeLib;232 bool is_lib = g->out_type == OutTypeLib;
218 bool is_static = g->is_static || (!is_lib && g->link_libs_list.length == 0);233 bool shared = !g->is_static && is_lib;
219 bool shared = !is_static && is_lib;
220 Buf *soname = nullptr;234 Buf *soname = nullptr;
221 if (is_static) {235 if (g->is_static) {
222 if (g->zig_target.arch.arch == ZigLLVM_arm || g->zig_target.arch.arch == ZigLLVM_armeb ||236 if (g->zig_target.arch.arch == ZigLLVM_arm || g->zig_target.arch.arch == ZigLLVM_armeb ||
223 g->zig_target.arch.arch == ZigLLVM_thumb || g->zig_target.arch.arch == ZigLLVM_thumbeb)237 g->zig_target.arch.arch == ZigLLVM_thumb || g->zig_target.arch.arch == ZigLLVM_thumbeb)
224 {238 {
...@@ -242,7 +256,7 @@ static void construct_linker_job_elf(LinkJob *lj) {...@@ -242,7 +256,7 @@ static void construct_linker_job_elf(LinkJob *lj) {
242 if (lj->link_in_crt) {256 if (lj->link_in_crt) {
243 const char *crt1o;257 const char *crt1o;
244 const char *crtbegino;258 const char *crtbegino;
245 if (is_static) {259 if (g->is_static) {
246 crt1o = "crt1.o";260 crt1o = "crt1.o";
247 crtbegino = "crtbeginT.o";261 crtbegino = "crtbeginT.o";
248 } else {262 } else {
...@@ -293,7 +307,7 @@ static void construct_linker_job_elf(LinkJob *lj) {...@@ -293,7 +307,7 @@ static void construct_linker_job_elf(LinkJob *lj) {
293 lj->args.append(buf_ptr(g->libc_static_lib_dir));307 lj->args.append(buf_ptr(g->libc_static_lib_dir));
294 }308 }
295309
296 if (!is_static) {310 if (!g->is_static) {
297 if (g->dynamic_linker != nullptr) {311 if (g->dynamic_linker != nullptr) {
298 assert(buf_len(g->dynamic_linker) != 0);312 assert(buf_len(g->dynamic_linker) != 0);
299 lj->args.append("-dynamic-linker");313 lj->args.append("-dynamic-linker");
...@@ -315,10 +329,10 @@ static void construct_linker_job_elf(LinkJob *lj) {...@@ -315,10 +329,10 @@ static void construct_linker_job_elf(LinkJob *lj) {
315 lj->args.append((const char *)buf_ptr(g->link_objects.at(i)));329 lj->args.append((const char *)buf_ptr(g->link_objects.at(i)));
316 }330 }
317331
318 if (g->out_type == OutTypeExe || g->out_type == OutTypeLib) {332 if (g->out_type == OutTypeExe || (g->out_type == OutTypeLib && !g->is_static)) {
319 if (g->libc_link_lib == nullptr) {333 if (g->libc_link_lib == nullptr) {
320 Buf *builtin_o_path = build_o(g, "builtin");334 Buf *builtin_a_path = build_a(g, "builtin");
321 lj->args.append(buf_ptr(builtin_o_path));335 lj->args.append(buf_ptr(builtin_a_path));
322 }336 }
323337
324 // sometimes libgcc is missing stuff, so we still build compiler_rt and rely on weak linkage338 // sometimes libgcc is missing stuff, so we still build compiler_rt and rely on weak linkage
...@@ -345,7 +359,7 @@ static void construct_linker_job_elf(LinkJob *lj) {...@@ -345,7 +359,7 @@ static void construct_linker_job_elf(LinkJob *lj) {
345359
346 // libc dep360 // libc dep
347 if (g->libc_link_lib != nullptr) {361 if (g->libc_link_lib != nullptr) {
348 if (is_static) {362 if (g->is_static) {
349 lj->args.append("--start-group");363 lj->args.append("--start-group");
350 lj->args.append("-lgcc");364 lj->args.append("-lgcc");
351 lj->args.append("-lgcc_eh");365 lj->args.append("-lgcc_eh");
...@@ -387,6 +401,7 @@ static void construct_linker_job_elf(LinkJob *lj) {...@@ -387,6 +401,7 @@ static void construct_linker_job_elf(LinkJob *lj) {
387static void construct_linker_job_wasm(LinkJob *lj) {401static void construct_linker_job_wasm(LinkJob *lj) {
388 CodeGen *g = lj->codegen;402 CodeGen *g = lj->codegen;
389403
404 lj->args.append("-error-limit=0");
390 lj->args.append("--no-entry"); // So lld doesn't look for _start.405 lj->args.append("--no-entry"); // So lld doesn't look for _start.
391 lj->args.append("-o");406 lj->args.append("-o");
392 lj->args.append(buf_ptr(&g->output_file_path));407 lj->args.append(buf_ptr(&g->output_file_path));
...@@ -425,6 +440,8 @@ static bool zig_lld_link(ZigLLVM_ObjectFormatType oformat, const char **args, si...@@ -425,6 +440,8 @@ static bool zig_lld_link(ZigLLVM_ObjectFormatType oformat, const char **args, si
425static void construct_linker_job_coff(LinkJob *lj) {440static void construct_linker_job_coff(LinkJob *lj) {
426 CodeGen *g = lj->codegen;441 CodeGen *g = lj->codegen;
427442
443 lj->args.append("/ERRORLIMIT:0");
444
428 if (g->libc_link_lib != nullptr) {445 if (g->libc_link_lib != nullptr) {
429 find_libc_lib_path(g);446 find_libc_lib_path(g);
430 }447 }
...@@ -546,10 +563,10 @@ static void construct_linker_job_coff(LinkJob *lj) {...@@ -546,10 +563,10 @@ static void construct_linker_job_coff(LinkJob *lj) {
546 lj->args.append((const char *)buf_ptr(g->link_objects.at(i)));563 lj->args.append((const char *)buf_ptr(g->link_objects.at(i)));
547 }564 }
548565
549 if (g->out_type == OutTypeExe || g->out_type == OutTypeLib) {566 if (g->out_type == OutTypeExe || (g->out_type == OutTypeLib && !g->is_static)) {
550 if (g->libc_link_lib == nullptr) {567 if (g->libc_link_lib == nullptr) {
551 Buf *builtin_o_path = build_o(g, "builtin");568 Buf *builtin_a_path = build_a(g, "builtin");
552 lj->args.append(buf_ptr(builtin_o_path));569 lj->args.append(buf_ptr(builtin_a_path));
553 }570 }
554571
555 // msvc compiler_rt is missing some stuff, so we still build it and rely on weak linkage572 // msvc compiler_rt is missing some stuff, so we still build it and rely on weak linkage
...@@ -761,6 +778,7 @@ static bool darwin_version_lt(DarwinPlatform *platform, int major, int minor) {...@@ -761,6 +778,7 @@ static bool darwin_version_lt(DarwinPlatform *platform, int major, int minor) {
761static void construct_linker_job_macho(LinkJob *lj) {778static void construct_linker_job_macho(LinkJob *lj) {
762 CodeGen *g = lj->codegen;779 CodeGen *g = lj->codegen;
763780
781 lj->args.append("-error-limit=0");
764 lj->args.append("-demangle");782 lj->args.append("-demangle");
765783
766 if (g->linker_rdynamic) {784 if (g->linker_rdynamic) {
...@@ -878,7 +896,7 @@ static void construct_linker_job_macho(LinkJob *lj) {...@@ -878,7 +896,7 @@ static void construct_linker_job_macho(LinkJob *lj) {
878 }896 }
879897
880 // compiler_rt on darwin is missing some stuff, so we still build it and rely on LinkOnce898 // compiler_rt on darwin is missing some stuff, so we still build it and rely on LinkOnce
881 if (g->out_type == OutTypeExe || g->out_type == OutTypeLib) {899 if (g->out_type == OutTypeExe || (g->out_type == OutTypeLib && !g->is_static)) {
882 Buf *compiler_rt_o_path = build_compiler_rt(g);900 Buf *compiler_rt_o_path = build_compiler_rt(g);
883 lj->args.append(buf_ptr(compiler_rt_o_path));901 lj->args.append(buf_ptr(compiler_rt_o_path));
884 }902 }
...@@ -960,8 +978,17 @@ void codegen_link(CodeGen *g) {...@@ -960,8 +978,17 @@ void codegen_link(CodeGen *g) {
960 }978 }
961979
962 if (g->out_type == OutTypeLib && g->is_static) {980 if (g->out_type == OutTypeLib && g->is_static) {
963 fprintf(stderr, "Zig does not yet support creating static libraries\nSee https://github.com/ziglang/zig/issues/1493\n");981 ZigList<const char *> file_names = {};
964 exit(1);982 for (size_t i = 0; i < g->link_objects.length; i += 1) {
983 file_names.append((const char *)buf_ptr(g->link_objects.at(i)));
984 }
985 ZigLLVM_OSType os_type = get_llvm_os_type(g->zig_target.os);
986 codegen_add_time_event(g, "LLVM Link");
987 if (ZigLLVMWriteArchive(buf_ptr(&g->output_file_path), file_names.items, file_names.length, os_type)) {
988 fprintf(stderr, "Unable to write archive '%s'\n", buf_ptr(&g->output_file_path));
989 exit(1);
990 }
991 return;
965 }992 }
966993
967 lj.link_in_crt = (g->libc_link_lib != nullptr && g->out_type == OutTypeExe);994 lj.link_in_crt = (g->libc_link_lib != nullptr && g->out_type == OutTypeExe);
src/main.cpp+12
...@@ -47,6 +47,7 @@ static int print_full_usage(const char *arg0) {...@@ -47,6 +47,7 @@ static int print_full_usage(const char *arg0) {
47 " --cache-dir [path] override the cache directory\n"47 " --cache-dir [path] override the cache directory\n"
48 " --cache [auto|off|on] build in global cache, print out paths to stdout\n"48 " --cache [auto|off|on] build in global cache, print out paths to stdout\n"
49 " --color [auto|off|on] enable or disable colored error messages\n"49 " --color [auto|off|on] enable or disable colored error messages\n"
50 " --disable-pic disable Position Independent Code for libraries\n"
50 " --emit [asm|bin|llvm-ir] emit a specific file format as compilation output\n"51 " --emit [asm|bin|llvm-ir] emit a specific file format as compilation output\n"
51 " -ftime-report print timing diagnostics\n"52 " -ftime-report print timing diagnostics\n"
52 " --libc-include-dir [path] directory where libc stdlib.h resides\n"53 " --libc-include-dir [path] directory where libc stdlib.h resides\n"
...@@ -386,6 +387,7 @@ int main(int argc, char **argv) {...@@ -386,6 +387,7 @@ int main(int argc, char **argv) {
386 size_t ver_minor = 0;387 size_t ver_minor = 0;
387 size_t ver_patch = 0;388 size_t ver_patch = 0;
388 bool timing_info = false;389 bool timing_info = false;
390 bool disable_pic = false;
389 const char *cache_dir = nullptr;391 const char *cache_dir = nullptr;
390 CliPkg *cur_pkg = allocate<CliPkg>(1);392 CliPkg *cur_pkg = allocate<CliPkg>(1);
391 BuildMode build_mode = BuildModeDebug;393 BuildMode build_mode = BuildModeDebug;
...@@ -556,6 +558,8 @@ int main(int argc, char **argv) {...@@ -556,6 +558,8 @@ int main(int argc, char **argv) {
556 each_lib_rpath = true;558 each_lib_rpath = true;
557 } else if (strcmp(arg, "-ftime-report") == 0) {559 } else if (strcmp(arg, "-ftime-report") == 0) {
558 timing_info = true;560 timing_info = true;
561 } else if (strcmp(arg, "--disable-pic") == 0) {
562 disable_pic = true;
559 } else if (strcmp(arg, "--test-cmd-bin") == 0) {563 } else if (strcmp(arg, "--test-cmd-bin") == 0) {
560 test_exec_args.append(nullptr);564 test_exec_args.append(nullptr);
561 } else if (arg[1] == 'L' && arg[2] != 0) {565 } else if (arg[1] == 'L' && arg[2] != 0) {
...@@ -849,6 +853,14 @@ int main(int argc, char **argv) {...@@ -849,6 +853,14 @@ int main(int argc, char **argv) {
849 buf_out_name = buf_create_from_str("run");853 buf_out_name = buf_create_from_str("run");
850 }854 }
851 CodeGen *g = codegen_create(zig_root_source_file, target, out_type, build_mode, get_zig_lib_dir());855 CodeGen *g = codegen_create(zig_root_source_file, target, out_type, build_mode, get_zig_lib_dir());
856 if (disable_pic) {
857 if (out_type != OutTypeLib || !is_static) {
858 fprintf(stderr, "--disable-pic only applies to static libraries");
859 return EXIT_FAILURE;
860 }
861 g->disable_pic = true;
862 }
863
852 g->enable_time_report = timing_info;864 g->enable_time_report = timing_info;
853 buf_init_from_str(&g->cache_dir, cache_dir ? cache_dir : default_zig_cache_name);865 buf_init_from_str(&g->cache_dir, cache_dir ? cache_dir : default_zig_cache_name);
854 codegen_set_out_name(g, buf_out_name);866 codegen_set_out_name(g, buf_out_name);
src/os.cpp+22-18
...@@ -46,6 +46,7 @@ typedef SSIZE_T ssize_t;...@@ -46,6 +46,7 @@ typedef SSIZE_T ssize_t;
46#include <sys/wait.h>46#include <sys/wait.h>
47#include <fcntl.h>47#include <fcntl.h>
48#include <limits.h>48#include <limits.h>
49#include <spawn.h>
4950
50#endif51#endif
5152
...@@ -70,6 +71,12 @@ static clock_serv_t cclock;...@@ -70,6 +71,12 @@ static clock_serv_t cclock;
70#include <errno.h>71#include <errno.h>
71#include <time.h>72#include <time.h>
7273
74// Apple doesn't provide the environ global variable
75#if defined(__APPLE__) && !defined(environ)
76#include <crt_externs.h>
77#define environ (*_NSGetEnviron())
78#endif
79
73#if defined(ZIG_OS_POSIX)80#if defined(ZIG_OS_POSIX)
74static void populate_termination(Termination *term, int status) {81static void populate_termination(Termination *term, int status) {
75 if (WIFEXITED(status)) {82 if (WIFEXITED(status)) {
...@@ -88,25 +95,22 @@ static void populate_termination(Termination *term, int status) {...@@ -88,25 +95,22 @@ static void populate_termination(Termination *term, int status) {
88}95}
8996
90static void os_spawn_process_posix(const char *exe, ZigList<const char *> &args, Termination *term) {97static void os_spawn_process_posix(const char *exe, ZigList<const char *> &args, Termination *term) {
91 pid_t pid = fork();98 const char **argv = allocate<const char *>(args.length + 2);
92 if (pid == -1)99 argv[0] = exe;
93 zig_panic("fork failed: %s", strerror(errno));100 argv[args.length + 1] = nullptr;
94 if (pid == 0) {101 for (size_t i = 0; i < args.length; i += 1) {
95 // child102 argv[i + 1] = args.at(i);
96 const char **argv = allocate<const char *>(args.length + 2);
97 argv[0] = exe;
98 argv[args.length + 1] = nullptr;
99 for (size_t i = 0; i < args.length; i += 1) {
100 argv[i + 1] = args.at(i);
101 }
102 execvp(exe, const_cast<char * const *>(argv));
103 zig_panic("execvp failed: %s", strerror(errno));
104 } else {
105 // parent
106 int status;
107 waitpid(pid, &status, 0);
108 populate_termination(term, status);
109 }103 }
104
105 pid_t pid;
106 int rc = posix_spawn(&pid, exe, nullptr, nullptr, const_cast<char *const*>(argv), environ);
107 if (rc != 0) {
108 zig_panic("posix_spawn failed: %s", strerror(rc));
109 }
110
111 int status;
112 waitpid(pid, &status, 0);
113 populate_termination(term, status);
110}114}
111#endif115#endif
112116
src/target.cpp+1-1
...@@ -250,7 +250,7 @@ Os get_target_os(size_t index) {...@@ -250,7 +250,7 @@ Os get_target_os(size_t index) {
250 return os_list[index];250 return os_list[index];
251}251}
252252
253static ZigLLVM_OSType get_llvm_os_type(Os os_type) {253ZigLLVM_OSType get_llvm_os_type(Os os_type) {
254 switch (os_type) {254 switch (os_type) {
255 case OsFreestanding:255 case OsFreestanding:
256 case OsZen:256 case OsZen:
src/target.hpp+1-1
...@@ -119,6 +119,6 @@ const char *target_lib_file_ext(ZigTarget *target, bool is_static, size_t versio...@@ -119,6 +119,6 @@ const char *target_lib_file_ext(ZigTarget *target, bool is_static, size_t versio
119Buf *target_dynamic_linker(ZigTarget *target);119Buf *target_dynamic_linker(ZigTarget *target);
120120
121bool target_can_exec(const ZigTarget *host_target, const ZigTarget *guest_target);121bool target_can_exec(const ZigTarget *host_target, const ZigTarget *guest_target);
122122ZigLLVM_OSType get_llvm_os_type(Os os_type);
123123
124#endif124#endif
src/zig_llvm.cpp+39-1
...@@ -32,6 +32,8 @@...@@ -32,6 +32,8 @@
32#include <llvm/IR/Verifier.h>32#include <llvm/IR/Verifier.h>
33#include <llvm/InitializePasses.h>33#include <llvm/InitializePasses.h>
34#include <llvm/MC/SubtargetFeature.h>34#include <llvm/MC/SubtargetFeature.h>
35#include <llvm/Object/Archive.h>
36#include <llvm/Object/ArchiveWriter.h>
35#include <llvm/PassRegistry.h>37#include <llvm/PassRegistry.h>
36#include <llvm/Support/FileSystem.h>38#include <llvm/Support/FileSystem.h>
37#include <llvm/Support/TargetParser.h>39#include <llvm/Support/TargetParser.h>
...@@ -40,8 +42,8 @@...@@ -40,8 +42,8 @@
40#include <llvm/Target/TargetMachine.h>42#include <llvm/Target/TargetMachine.h>
41#include <llvm/Transforms/Coroutines.h>43#include <llvm/Transforms/Coroutines.h>
42#include <llvm/Transforms/IPO.h>44#include <llvm/Transforms/IPO.h>
43#include <llvm/Transforms/IPO/PassManagerBuilder.h>
44#include <llvm/Transforms/IPO/AlwaysInliner.h>45#include <llvm/Transforms/IPO/AlwaysInliner.h>
46#include <llvm/Transforms/IPO/PassManagerBuilder.h>
45#include <llvm/Transforms/Scalar.h>47#include <llvm/Transforms/Scalar.h>
46#include <llvm/Transforms/Utils.h>48#include <llvm/Transforms/Utils.h>
4749
...@@ -854,6 +856,42 @@ class MyOStream: public raw_ostream {...@@ -854,6 +856,42 @@ class MyOStream: public raw_ostream {
854 size_t pos;856 size_t pos;
855};857};
856858
859bool ZigLLVMWriteArchive(const char *archive_name, const char **file_names, size_t file_name_count,
860 ZigLLVM_OSType os_type)
861{
862 object::Archive::Kind kind;
863 switch (os_type) {
864 case ZigLLVM_Win32:
865 // For some reason llvm-lib passes K_GNU on windows.
866 // See lib/ToolDrivers/llvm-lib/LibDriver.cpp:168 in libDriverMain
867 kind = object::Archive::K_GNU;
868 break;
869 case ZigLLVM_Linux:
870 kind = object::Archive::K_GNU;
871 break;
872 case ZigLLVM_Darwin:
873 case ZigLLVM_IOS:
874 kind = object::Archive::K_DARWIN;
875 break;
876 case ZigLLVM_OpenBSD:
877 case ZigLLVM_FreeBSD:
878 kind = object::Archive::K_BSD;
879 break;
880 default:
881 kind = object::Archive::K_GNU;
882 }
883 SmallVector<NewArchiveMember, 4> new_members;
884 for (size_t i = 0; i < file_name_count; i += 1) {
885 Expected<NewArchiveMember> new_member = NewArchiveMember::getFile(file_names[i], true);
886 Error err = new_member.takeError();
887 if (err) return true;
888 new_members.push_back(std::move(*new_member));
889 }
890 Error err = writeArchive(archive_name, new_members, true, kind, true, false, nullptr);
891 if (err) return true;
892 return false;
893}
894
857895
858bool ZigLLDLink(ZigLLVM_ObjectFormatType oformat, const char **args, size_t arg_count,896bool ZigLLDLink(ZigLLVM_ObjectFormatType oformat, const char **args, size_t arg_count,
859 void (*append_diagnostic)(void *, const char *, size_t), void *context)897 void (*append_diagnostic)(void *, const char *, size_t), void *context)
src/zig_llvm.h+3
...@@ -406,6 +406,9 @@ ZIG_EXTERN_C const char *ZigLLVMGetEnvironmentTypeName(enum ZigLLVM_EnvironmentT...@@ -406,6 +406,9 @@ ZIG_EXTERN_C const char *ZigLLVMGetEnvironmentTypeName(enum ZigLLVM_EnvironmentT
406ZIG_EXTERN_C bool ZigLLDLink(enum ZigLLVM_ObjectFormatType oformat, const char **args, size_t arg_count,406ZIG_EXTERN_C bool ZigLLDLink(enum ZigLLVM_ObjectFormatType oformat, const char **args, size_t arg_count,
407 void (*append_diagnostic)(void *, const char *, size_t), void *context);407 void (*append_diagnostic)(void *, const char *, size_t), void *context);
408408
409ZIG_EXTERN_C bool ZigLLVMWriteArchive(const char *archive_name, const char **file_names, size_t file_name_count,
410 enum ZigLLVM_OSType os_type);
411
409ZIG_EXTERN_C void ZigLLVMGetNativeTarget(enum ZigLLVM_ArchType *arch_type, enum ZigLLVM_SubArchType *sub_arch_type,412ZIG_EXTERN_C void ZigLLVMGetNativeTarget(enum ZigLLVM_ArchType *arch_type, enum ZigLLVM_SubArchType *sub_arch_type,
410 enum ZigLLVM_VendorType *vendor_type, enum ZigLLVM_OSType *os_type, enum ZigLLVM_EnvironmentType *environ_type,413 enum ZigLLVM_VendorType *vendor_type, enum ZigLLVM_OSType *os_type, enum ZigLLVM_EnvironmentType *environ_type,
411 enum ZigLLVM_ObjectFormatType *oformat);414 enum ZigLLVM_ObjectFormatType *oformat);
std/special/bootstrap.zig+6-2
...@@ -66,7 +66,9 @@ fn posixCallMainAndExit() noreturn {...@@ -66,7 +66,9 @@ fn posixCallMainAndExit() noreturn {
66 std.os.posix.exit(callMainWithArgs(argc, argv, envp));66 std.os.posix.exit(callMainWithArgs(argc, argv, envp));
67}67}
6868
69fn callMainWithArgs(argc: usize, argv: [*][*]u8, envp: [][*]u8) u8 {69// This is marked inline because for some reason LLVM in release mode fails to inline it,
70// and we want fewer call frames in stack traces.
71inline fn callMainWithArgs(argc: usize, argv: [*][*]u8, envp: [][*]u8) u8 {
70 std.os.ArgIteratorPosix.raw = argv[0..argc];72 std.os.ArgIteratorPosix.raw = argv[0..argc];
71 std.os.posix_environ_raw = envp;73 std.os.posix_environ_raw = envp;
72 return callMain();74 return callMain();
...@@ -79,7 +81,9 @@ extern fn main(c_argc: i32, c_argv: [*][*]u8, c_envp: [*]?[*]u8) i32 {...@@ -79,7 +81,9 @@ extern fn main(c_argc: i32, c_argv: [*][*]u8, c_envp: [*]?[*]u8) i32 {
79 return callMainWithArgs(@intCast(usize, c_argc), c_argv, envp);81 return callMainWithArgs(@intCast(usize, c_argc), c_argv, envp);
80}82}
8183
82fn callMain() u8 {84// This is marked inline because for some reason LLVM in release mode fails to inline it,
85// and we want fewer call frames in stack traces.
86inline fn callMain() u8 {
83 switch (@typeId(@typeOf(root.main).ReturnType)) {87 switch (@typeId(@typeOf(root.main).ReturnType)) {
84 builtin.TypeId.NoReturn => {88 builtin.TypeId.NoReturn => {
85 root.main();89 root.main();
std/special/bootstrap_lib.zig+1-1
...@@ -1,4 +1,4 @@...@@ -1,4 +1,4 @@
1// This file is included in the compilation unit when exporting a library on windows.1// This file is included in the compilation unit when exporting a DLL on windows.
22
3const std = @import("std");3const std = @import("std");
4const builtin = @import("builtin");4const builtin = @import("builtin");