| author | |
| committer | |
| log | 9e38a81230bcaefb50fae610c071005449a7abfb |
| tree | f706728a6b853da0b66379539018645df583519b |
| parent | d40c4e7c896c5dfed9dd35e8c0d2117f7cf5c53c |
| parent | 81c6f087241b6b7a1c12de72a2061cb02df0f93f |
| signature | Signed by PGP key 4AEE18F83AFDEB23 |
Support building static libraries11 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; | ||
| 1766 | 1767 | ||
| 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; |
| 7230 | 7230 | ||
| 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; | ||
| 7232 | 7235 | ||
| 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 | } |
| 7493 | 7498 | ||
| ... | @@ -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 | } |
| 31 | 31 | ||
| 32 | static Buf *build_o_raw(CodeGen *parent_gen, const char *oname, Buf *full_path) { | 32 | static 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); | ||
| 36 | 46 | ||
| 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; |
| 44 | 54 | ||
| 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; | ||
| 47 | 58 | ||
| 48 | codegen_set_out_name(child_gen, buf_create_from_str(oname)); | 59 | codegen_set_out_name(child_gen, buf_create_from_str(aname)); |
| 49 | 60 | ||
| 50 | codegen_set_errmsg_color(child_gen, parent_gen->err_color); | 61 | codegen_set_errmsg_color(child_gen, parent_gen->err_color); |
| 51 | 62 | ||
| 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); |
| 54 | 65 | ||
| 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 | } |
| 60 | 73 | ||
| 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 | } |
| 65 | 78 | ||
| 66 | static Buf *build_o(CodeGen *parent_gen, const char *oname) { | 79 | static 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); |
| 70 | 83 | ||
| 71 | return build_o_raw(parent_gen, oname, full_path); | 84 | return build_a_raw(parent_gen, aname, full_path); |
| 72 | } | 85 | } |
| 73 | 86 | ||
| 74 | static Buf *build_compiler_rt(CodeGen *parent_gen) { | 87 | static 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); |
| 79 | 92 | ||
| 80 | return build_o_raw(parent_gen, "compiler_rt", full_path); | 93 | return build_a_raw(parent_gen, "compiler_rt", full_path); |
| 81 | } | 94 | } |
| 82 | 95 | ||
| 83 | static const char *get_darwin_arch_string(const ZigTarget *t) { | 96 | static 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) { |
| 197 | static void construct_linker_job_elf(LinkJob *lj) { | 210 | static void construct_linker_job_elf(LinkJob *lj) { |
| 198 | CodeGen *g = lj->codegen; | 211 | CodeGen *g = lj->codegen; |
| 199 | 212 | ||
| 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)); |
| 216 | 231 | ||
| 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 | } |
| 295 | 309 | ||
| 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 | } |
| 317 | 331 | ||
| 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 | } |
| 323 | 337 | ||
| 324 | // sometimes libgcc is missing stuff, so we still build compiler_rt and rely on weak linkage | 338 | // 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) { |
| 345 | 359 | ||
| 346 | // libc dep | 360 | // 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) { |
| 387 | static void construct_linker_job_wasm(LinkJob *lj) { | 401 | static void construct_linker_job_wasm(LinkJob *lj) { |
| 388 | CodeGen *g = lj->codegen; | 402 | CodeGen *g = lj->codegen; |
| 389 | 403 | ||
| 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 |
| 425 | static void construct_linker_job_coff(LinkJob *lj) { | 440 | static void construct_linker_job_coff(LinkJob *lj) { |
| 426 | CodeGen *g = lj->codegen; | 441 | CodeGen *g = lj->codegen; |
| 427 | 442 | ||
| 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 | } |
| 548 | 565 | ||
| 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 | } |
| 554 | 571 | ||
| 555 | // msvc compiler_rt is missing some stuff, so we still build it and rely on weak linkage | 572 | // 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) { |
| 761 | static void construct_linker_job_macho(LinkJob *lj) { | 778 | static void construct_linker_job_macho(LinkJob *lj) { |
| 762 | CodeGen *g = lj->codegen; | 779 | CodeGen *g = lj->codegen; |
| 763 | 780 | ||
| 781 | lj->args.append("-error-limit=0"); | ||
| 764 | lj->args.append("-demangle"); | 782 | lj->args.append("-demangle"); |
| 765 | 783 | ||
| 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 | } |
| 879 | 897 | ||
| 880 | // compiler_rt on darwin is missing some stuff, so we still build it and rely on LinkOnce | 898 | // 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 | } |
| 961 | 979 | ||
| 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 | } |
| 966 | 993 | ||
| 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> | ||
| 49 | 50 | ||
| 50 | #endif | 51 | #endif |
| 51 | 52 | ||
| ... | @@ -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> |
| 72 | 73 | ||
| 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) |
| 74 | static void populate_termination(Termination *term, int status) { | 81 | static 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 | } |
| 89 | 96 | ||
| 90 | static void os_spawn_process_posix(const char *exe, ZigList<const char *> &args, Termination *term) { | 97 | static 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 | // child | 102 | 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 | #endif | 115 | #endif |
| 112 | 116 |
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 | } |
| 252 | 252 | ||
| 253 | static ZigLLVM_OSType get_llvm_os_type(Os os_type) { | 253 | ZigLLVM_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 |
| 119 | Buf *target_dynamic_linker(ZigTarget *target); | 119 | Buf *target_dynamic_linker(ZigTarget *target); |
| 120 | 120 | ||
| 121 | bool target_can_exec(const ZigTarget *host_target, const ZigTarget *guest_target); | 121 | bool target_can_exec(const ZigTarget *host_target, const ZigTarget *guest_target); |
| 122 | 122 | ZigLLVM_OSType get_llvm_os_type(Os os_type); | |
| 123 | 123 | ||
| 124 | #endif | 124 | #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> |
| 47 | 49 | ||
| ... | @@ -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 | }; |
| 856 | 858 | ||
| 859 | bool 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 | |||
| 857 | 895 | ||
| 858 | bool ZigLLDLink(ZigLLVM_ObjectFormatType oformat, const char **args, size_t arg_count, | 896 | bool 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 |
| 406 | ZIG_EXTERN_C bool ZigLLDLink(enum ZigLLVM_ObjectFormatType oformat, const char **args, size_t arg_count, | 406 | ZIG_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); |
| 408 | 408 | ||
| 409 | ZIG_EXTERN_C bool ZigLLVMWriteArchive(const char *archive_name, const char **file_names, size_t file_name_count, | ||
| 410 | enum ZigLLVM_OSType os_type); | ||
| 411 | |||
| 409 | ZIG_EXTERN_C void ZigLLVMGetNativeTarget(enum ZigLLVM_ArchType *arch_type, enum ZigLLVM_SubArchType *sub_arch_type, | 412 | ZIG_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 | } |
| 68 | 68 | ||
| 69 | fn 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. | ||
| 71 | inline 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 | } |
| 81 | 83 | ||
| 82 | fn 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. | ||
| 86 | inline 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. |
| 2 | 2 | ||
| 3 | const std = @import("std"); | 3 | const std = @import("std"); |
| 4 | const builtin = @import("builtin"); | 4 | const builtin = @import("builtin"); |