authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-02-23 09:35:56-05:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2019-02-23 09:35:56-05:00
log6fd8d455bcc6765e7411fa00d23dca1eb270aac9
tree047a654678400140fd46ffa64d7c4248050247cd
parent52bb71867d8d6e738eefb7dafead875eb21a4ae7
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

better libc detection (#1996)

* better libc detection This introduces a new command `zig libc` which prints the various paths of libc files. It outputs them to stdout in a simple text file format that it is capable of parsing. You can use `zig libc libc.txt` to validate a file. These arguments are gone: --libc-lib-dir [path] directory where libc crt1.o resides --libc-static-lib-dir [path] directory where libc crtbegin.o resides --msvc-lib-dir [path] (windows) directory where vcruntime.lib resides --kernel32-lib-dir [path] (windows) directory where kernel32.lib resides Instead we have this argument: --libc [file] Provide a file which specifies libc paths This is used to pass a libc text file (which can be generated with `zig libc`). So it is easier to manage multiple cross compilation environments. `--cache on` now works when linking against libc. `ZigTarget` now has a bool field `is_native` Better error messaging when you try to link against libc or use `@cImport` but the various paths cannot be found. It should also be faster. * save native_libc.txt in zig-cache This avoids having to detect libc at runtime on every invocation.

18 files changed, 774 insertions(+), 592 deletions(-)

CMakeLists.txt+1
......@@ -414,6 +414,7 @@ set(ZIG_SOURCES
414414 "${CMAKE_SOURCE_DIR}/src/error.cpp"
415415 "${CMAKE_SOURCE_DIR}/src/ir.cpp"
416416 "${CMAKE_SOURCE_DIR}/src/ir_print.cpp"
417 "${CMAKE_SOURCE_DIR}/src/libc_installation.cpp"
417418 "${CMAKE_SOURCE_DIR}/src/link.cpp"
418419 "${CMAKE_SOURCE_DIR}/src/main.cpp"
419420 "${CMAKE_SOURCE_DIR}/src/os.cpp"
src/all_types.hpp+11-16
......@@ -18,6 +18,7 @@
1818#include "bigfloat.hpp"
1919#include "target.hpp"
2020#include "tokenizer.hpp"
21#include "libc_installation.hpp"
2122
2223struct AstNode;
2324struct ImportTableEntry;
......@@ -1743,6 +1744,9 @@ struct CodeGen {
17431744 Buf *wanted_output_file_path;
17441745 Buf cache_dir;
17451746
1747 Buf *zig_c_headers_dir; // Cannot be overridden; derived from zig_lib_dir.
1748 Buf *zig_std_special_dir; // Cannot be overridden; derived from zig_lib_dir.
1749
17461750 IrInstruction *invalid_instruction;
17471751 IrInstruction *unreach_instruction;
17481752
......@@ -1791,6 +1795,8 @@ struct CodeGen {
17911795 bool system_linker_hack;
17921796
17931797 //////////////////////////// Participates in Input Parameter Cache Hash
1798 /////// Note: there is a separate cache hash for builtin.zig, when adding fields,
1799 /////// consider if they need to go into both.
17941800 ZigList<LinkLib *> link_libs_list;
17951801 // add -framework [name] args to linker
17961802 ZigList<Buf *> darwin_frameworks;
......@@ -1801,6 +1807,8 @@ struct CodeGen {
18011807 ZigList<Buf *> assembly_files;
18021808 ZigList<const char *> lib_dirs;
18031809
1810 ZigLibCInstallation *libc;
1811
18041812 size_t version_major;
18051813 size_t version_minor;
18061814 size_t version_patch;
......@@ -1809,14 +1817,13 @@ struct CodeGen {
18091817 EmitFileType emit_file_type;
18101818 BuildMode build_mode;
18111819 OutType out_type;
1812 ZigTarget zig_target;
1820 const ZigTarget *zig_target;
18131821 TargetSubsystem subsystem;
18141822 ValgrindSupport valgrind_support;
18151823 bool is_static;
18161824 bool strip_debug_symbols;
18171825 bool is_test_build;
18181826 bool is_single_threaded;
1819 bool is_native_target;
18201827 bool linker_rdynamic;
18211828 bool each_lib_rpath;
18221829 bool disable_pic;
......@@ -1827,26 +1834,14 @@ struct CodeGen {
18271834 Buf *test_filter;
18281835 Buf *test_name_prefix;
18291836 PackageTableEntry *root_package;
1837 Buf *zig_lib_dir;
1838 Buf *zig_std_dir;
18301839
18311840 const char **llvm_argv;
18321841 size_t llvm_argv_len;
18331842
18341843 const char **clang_argv;
18351844 size_t clang_argv_len;
1836
1837 //////////////////////////// Unsorted
1838
1839 Buf *libc_lib_dir;
1840 Buf *libc_static_lib_dir;
1841 Buf *libc_include_dir;
1842 Buf *msvc_lib_dir;
1843 Buf *kernel32_lib_dir;
1844 Buf *zig_lib_dir;
1845 Buf *zig_std_dir;
1846 Buf *zig_c_headers_dir;
1847 Buf *zig_std_special_dir;
1848 Buf *dynamic_linker;
1849 ZigWindowsSDK *win_sdk;
18501845};
18511846
18521847enum VarLinkage {
src/analyze.cpp+5-193
......@@ -1102,10 +1102,10 @@ bool want_first_arg_sret(CodeGen *g, FnTypeId *fn_type_id) {
11021102 if (type_is_c_abi_int(g, fn_type_id->return_type)) {
11031103 return false;
11041104 }
1105 if (g->zig_target.arch.arch == ZigLLVM_x86_64) {
1105 if (g->zig_target->arch.arch == ZigLLVM_x86_64) {
11061106 X64CABIClass abi_class = type_c_abi_x86_64_class(g, fn_type_id->return_type);
11071107 return abi_class == X64CABIClass_MEMORY;
1108 } else if (target_is_arm(&g->zig_target)) {
1108 } else if (target_is_arm(g->zig_target)) {
11091109 return type_size(g, fn_type_id->return_type) > 16;
11101110 }
11111111 zig_panic("TODO implement C ABI for this architecture. See https://github.com/ziglang/zig/issues/1481");
......@@ -3304,16 +3304,16 @@ void add_fn_export(CodeGen *g, ZigFn *fn_table_entry, Buf *symbol_name, GlobalLi
33043304 g->have_c_main = true;
33053305 g->subsystem = TargetSubsystemConsole;
33063306 } else if (buf_eql_str(symbol_name, "WinMain") &&
3307 g->zig_target.os == OsWindows)
3307 g->zig_target->os == OsWindows)
33083308 {
33093309 g->have_winmain = true;
33103310 g->subsystem = TargetSubsystemWindows;
33113311 } else if (buf_eql_str(symbol_name, "WinMainCRTStartup") &&
3312 g->zig_target.os == OsWindows)
3312 g->zig_target->os == OsWindows)
33133313 {
33143314 g->have_winmain_crt_startup = true;
33153315 } else if (buf_eql_str(symbol_name, "DllMainCRTStartup") &&
3316 g->zig_target.os == OsWindows)
3316 g->zig_target->os == OsWindows)
33173317 {
33183318 g->have_dllmain_crt_startup = true;
33193319 }
......@@ -4651,186 +4651,6 @@ bool handle_is_ptr(ZigType *type_entry) {
46514651 zig_unreachable();
46524652}
46534653
4654static ZigWindowsSDK *get_windows_sdk(CodeGen *g) {
4655 if (g->win_sdk == nullptr) {
4656 if (zig_find_windows_sdk(&g->win_sdk)) {
4657 fprintf(stderr, "unable to determine windows sdk path\n");
4658 exit(1);
4659 }
4660 }
4661 assert(g->win_sdk != nullptr);
4662 return g->win_sdk;
4663}
4664
4665
4666static Buf *get_linux_libc_lib_path(const char *o_file) {
4667 const char *cc_exe = getenv("CC");
4668 cc_exe = (cc_exe == nullptr) ? "cc" : cc_exe;
4669 ZigList<const char *> args = {};
4670 args.append(buf_ptr(buf_sprintf("-print-file-name=%s", o_file)));
4671 Termination term;
4672 Buf *out_stderr = buf_alloc();
4673 Buf *out_stdout = buf_alloc();
4674 Error err;
4675 if ((err = os_exec_process(cc_exe, args, &term, out_stderr, out_stdout))) {
4676 zig_panic("unable to determine libc lib path: executing C compiler: %s", err_str(err));
4677 }
4678 if (term.how != TerminationIdClean || term.code != 0) {
4679 zig_panic("unable to determine libc lib path: executing C compiler command failed");
4680 }
4681 if (buf_ends_with_str(out_stdout, "\n")) {
4682 buf_resize(out_stdout, buf_len(out_stdout) - 1);
4683 }
4684 if (buf_len(out_stdout) == 0 || buf_eql_str(out_stdout, o_file)) {
4685 zig_panic("unable to determine libc lib path: C compiler could not find %s", o_file);
4686 }
4687 Buf *result = buf_alloc();
4688 os_path_dirname(out_stdout, result);
4689 return result;
4690}
4691
4692static Buf *get_posix_libc_include_path(void) {
4693 const char *cc_exe = getenv("CC");
4694 cc_exe = (cc_exe == nullptr) ? "cc" : cc_exe;
4695 ZigList<const char *> args = {};
4696 args.append("-E");
4697 args.append("-Wp,-v");
4698 args.append("-xc");
4699 args.append("/dev/null");
4700 Termination term;
4701 Buf *out_stderr = buf_alloc();
4702 Buf *out_stdout = buf_alloc();
4703 Error err;
4704 if ((err = os_exec_process(cc_exe, args, &term, out_stderr, out_stdout))) {
4705 zig_panic("unable to determine libc include path: executing C compiler: %s", err_str(err));
4706 }
4707 if (term.how != TerminationIdClean || term.code != 0) {
4708 zig_panic("unable to determine libc include path: executing C compiler command failed");
4709 }
4710 char *prev_newline = buf_ptr(out_stderr);
4711 ZigList<const char *> search_paths = {};
4712 for (;;) {
4713 char *newline = strchr(prev_newline, '\n');
4714 if (newline == nullptr) {
4715 break;
4716 }
4717 *newline = 0;
4718 if (prev_newline[0] == ' ') {
4719 search_paths.append(prev_newline);
4720 }
4721 prev_newline = newline + 1;
4722 }
4723 if (search_paths.length == 0) {
4724 zig_panic("unable to determine libc include path: even C compiler does not know where libc headers are");
4725 }
4726 for (size_t i = 0; i < search_paths.length; i += 1) {
4727 // search in reverse order
4728 const char *search_path = search_paths.items[search_paths.length - i - 1];
4729 // cut off spaces
4730 while (*search_path == ' ') {
4731 search_path += 1;
4732 }
4733 Buf *stdlib_path = buf_sprintf("%s/stdlib.h", search_path);
4734 bool exists;
4735 if ((err = os_file_exists(stdlib_path, &exists))) {
4736 exists = false;
4737 }
4738 if (exists) {
4739 return buf_create_from_str(search_path);
4740 }
4741 }
4742 zig_panic("unable to determine libc include path: stdlib.h not found in C compiler search paths");
4743}
4744
4745void find_libc_include_path(CodeGen *g) {
4746 if (g->libc_include_dir == nullptr) {
4747 if (!g->is_native_target) {
4748 return;
4749 }
4750
4751 if (g->zig_target.os == OsWindows) {
4752 ZigWindowsSDK *sdk = get_windows_sdk(g);
4753 g->libc_include_dir = buf_alloc();
4754 if (os_get_win32_ucrt_include_path(sdk, g->libc_include_dir)) {
4755 fprintf(stderr, "Unable to determine libc include path. --libc-include-dir");
4756 exit(1);
4757 }
4758 } else if (g->zig_target.os == OsLinux ||
4759 g->zig_target.os == OsMacOSX ||
4760 g->zig_target.os == OsFreeBSD ||
4761 g->zig_target.os == OsNetBSD)
4762 {
4763 g->libc_include_dir = get_posix_libc_include_path();
4764 } else {
4765 fprintf(stderr, "Unable to determine libc include path.\n"
4766 "TODO: implement finding libc at runtime for other operating systems.\n"
4767 "in the meantime, you can use as a workaround: --libc-include-dir\n");
4768 exit(1);
4769 }
4770 }
4771 assert(buf_len(g->libc_include_dir) != 0);
4772}
4773
4774void find_libc_lib_path(CodeGen *g) {
4775 // later we can handle this better by reporting an error via the normal mechanism
4776 if (g->libc_lib_dir == nullptr ||
4777 (g->zig_target.os == OsWindows && (g->msvc_lib_dir == nullptr || g->kernel32_lib_dir == nullptr)))
4778 {
4779 if (g->zig_target.os == OsWindows) {
4780 ZigWindowsSDK *sdk = get_windows_sdk(g);
4781
4782 if (g->msvc_lib_dir == nullptr) {
4783 if (sdk->msvc_lib_dir_ptr == nullptr) {
4784 fprintf(stderr, "Unable to determine vcruntime path. --msvc-lib-dir");
4785 exit(1);
4786 }
4787 g->msvc_lib_dir = buf_create_from_mem(sdk->msvc_lib_dir_ptr, sdk->msvc_lib_dir_len);
4788 }
4789
4790 if (g->libc_lib_dir == nullptr) {
4791 Buf* ucrt_lib_path = buf_alloc();
4792 if (os_get_win32_ucrt_lib_path(sdk, ucrt_lib_path, g->zig_target.arch.arch)) {
4793 fprintf(stderr, "Unable to determine ucrt path. --libc-lib-dir");
4794 exit(1);
4795 }
4796 g->libc_lib_dir = ucrt_lib_path;
4797 }
4798
4799 if (g->kernel32_lib_dir == nullptr) {
4800 Buf* kern_lib_path = buf_alloc();
4801 if (os_get_win32_kern32_path(sdk, kern_lib_path, g->zig_target.arch.arch)) {
4802 fprintf(stderr, "Unable to determine kernel32 path. --kernel32-lib-dir");
4803 exit(1);
4804 }
4805 g->kernel32_lib_dir = kern_lib_path;
4806 }
4807
4808 } else if (g->zig_target.os == OsLinux) {
4809 g->libc_lib_dir = get_linux_libc_lib_path("crt1.o");
4810 } else if ((g->zig_target.os == OsFreeBSD) || (g->zig_target.os == OsNetBSD)) {
4811 g->libc_lib_dir = buf_create_from_str("/usr/lib");
4812 } else {
4813 zig_panic("Unable to determine libc lib path.");
4814 }
4815 } else {
4816 assert(buf_len(g->libc_lib_dir) != 0);
4817 }
4818
4819 if (g->libc_static_lib_dir == nullptr) {
4820 if ((g->zig_target.os == OsWindows) && (g->msvc_lib_dir != NULL)) {
4821 return;
4822 } else if (g->zig_target.os == OsLinux) {
4823 g->libc_static_lib_dir = get_linux_libc_lib_path("crtbegin.o");
4824 } else if ((g->zig_target.os == OsFreeBSD) || (g->zig_target.os == OsNetBSD)) {
4825 g->libc_static_lib_dir = buf_create_from_str("/usr/lib");
4826 } else {
4827 zig_panic("Unable to determine libc static lib path.");
4828 }
4829 } else {
4830 assert(buf_len(g->libc_static_lib_dir) != 0);
4831 }
4832}
4833
48344654static uint32_t hash_ptr(void *ptr) {
48354655 return (uint32_t)(((uintptr_t)ptr) % UINT32_MAX);
48364656}
......@@ -6736,14 +6556,6 @@ LinkLib *add_link_lib(CodeGen *g, Buf *name) {
67366556 if (is_libc && g->libc_link_lib != nullptr)
67376557 return g->libc_link_lib;
67386558
6739 if (g->enable_cache && is_libc && g->zig_target.os != OsMacOSX &&
6740 g->zig_target.os != OsIOS && g->zig_target.os != OsFreeBSD &&
6741 g->zig_target.os != OsNetBSD) {
6742 fprintf(stderr, "TODO linking against libc is currently incompatible with `--cache on`.\n"
6743 "Zig is not yet capable of determining whether the libc installation has changed on subsequent builds.\n");
6744 exit(1);
6745 }
6746
67476559 for (size_t i = 0; i < g->link_libs_list.length; i += 1) {
67486560 LinkLib *existing_lib = g->link_libs_list.at(i);
67496561 if (buf_eql_buf(existing_lib->name, name)) {
src/analyze.hpp-2
......@@ -40,8 +40,6 @@ ZigType *get_promise_type(CodeGen *g, ZigType *result_type);
4040ZigType *get_promise_frame_type(CodeGen *g, ZigType *return_type);
4141ZigType *get_test_fn_type(CodeGen *g);
4242bool handle_is_ptr(ZigType *type_entry);
43void find_libc_include_path(CodeGen *g);
44void find_libc_lib_path(CodeGen *g);
4543
4644bool type_has_bits(ZigType *type_entry);
4745bool type_allowed_in_extern(CodeGen *g, ZigType *type_entry);
src/codegen.cpp+127-107
......@@ -29,9 +29,9 @@ static void init_darwin_native(CodeGen *g) {
2929
3030 // Allow conflicts among OSX and iOS, but choose the default platform.
3131 if (osx_target && ios_target) {
32 if (g->zig_target.arch.arch == ZigLLVM_arm ||
33 g->zig_target.arch.arch == ZigLLVM_aarch64 ||
34 g->zig_target.arch.arch == ZigLLVM_thumb)
32 if (g->zig_target->arch.arch == ZigLLVM_arm ||
33 g->zig_target->arch.arch == ZigLLVM_aarch64 ||
34 g->zig_target->arch.arch == ZigLLVM_thumb)
3535 {
3636 osx_target = nullptr;
3737 } else {
......@@ -43,7 +43,7 @@ static void init_darwin_native(CodeGen *g) {
4343 g->mmacosx_version_min = buf_create_from_str(osx_target);
4444 } else if (ios_target) {
4545 g->mios_version_min = buf_create_from_str(ios_target);
46 } else if (g->zig_target.os != OsIOS) {
46 } else if (g->zig_target->os != OsIOS) {
4747 g->mmacosx_version_min = buf_create_from_str("10.10");
4848 }
4949}
......@@ -88,13 +88,15 @@ static const char *symbols_that_llvm_depends_on[] = {
8888};
8989
9090CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out_type, BuildMode build_mode,
91 Buf *zig_lib_dir, Buf *override_std_dir)
91 Buf *zig_lib_dir, Buf *override_std_dir, ZigLibCInstallation *libc)
9292{
9393 CodeGen *g = allocate<CodeGen>(1);
9494
9595 codegen_add_time_event(g, "Initialize");
9696
97 g->libc = libc;
9798 g->zig_lib_dir = zig_lib_dir;
99 g->zig_target = target;
98100
99101 if (override_std_dir == nullptr) {
100102 g->zig_std_dir = buf_alloc();
......@@ -149,44 +151,19 @@ CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out
149151 g->zig_std_special_dir = buf_alloc();
150152 os_path_join(g->zig_std_dir, buf_sprintf("special"), g->zig_std_special_dir);
151153
152 if (target) {
153 // cross compiling, so we can't rely on all the configured stuff since
154 // that's for native compilation
155 g->zig_target = *target;
156 resolve_target_object_format(&g->zig_target);
157 g->dynamic_linker = nullptr;
158 g->libc_lib_dir = nullptr;
159 g->libc_static_lib_dir = nullptr;
160 g->libc_include_dir = nullptr;
161 g->msvc_lib_dir = nullptr;
162 g->kernel32_lib_dir = nullptr;
154 assert(target != nullptr);
155 if (!target->is_native) {
163156 g->each_lib_rpath = false;
164157 } else {
165 // native compilation, we can rely on the configuration stuff
166 g->is_native_target = true;
167 get_native_target(&g->zig_target);
168 g->dynamic_linker = nullptr; // find it at runtime
169 g->libc_lib_dir = nullptr; // find it at runtime
170 g->libc_static_lib_dir = nullptr; // find it at runtime
171 g->libc_include_dir = nullptr; // find it at runtime
172 g->msvc_lib_dir = nullptr; // find it at runtime
173 g->kernel32_lib_dir = nullptr; // find it at runtime
174158 g->each_lib_rpath = true;
175159
176 if (g->zig_target.os == OsMacOSX ||
177 g->zig_target.os == OsIOS)
178 {
160 if (target_is_darwin(g->zig_target)) {
179161 init_darwin_native(g);
180162 }
181163
182164 }
183165
184 // On Darwin/MacOS/iOS, we always link libSystem which contains libc.
185 if (g->zig_target.os == OsMacOSX ||
186 g->zig_target.os == OsIOS ||
187 g->zig_target.os == OsFreeBSD ||
188 g->zig_target.os == OsNetBSD)
189 {
166 if (target_requires_libc(g->zig_target)) {
190167 g->libc_link_lib = create_link_lib(buf_create_from_str("c"));
191168 g->link_libs_list.append(g->libc_link_lib);
192169 }
......@@ -254,30 +231,6 @@ void codegen_set_out_name(CodeGen *g, Buf *out_name) {
254231 g->root_out_name = out_name;
255232}
256233
257void codegen_set_libc_lib_dir(CodeGen *g, Buf *libc_lib_dir) {
258 g->libc_lib_dir = libc_lib_dir;
259}
260
261void codegen_set_libc_static_lib_dir(CodeGen *g, Buf *libc_static_lib_dir) {
262 g->libc_static_lib_dir = libc_static_lib_dir;
263}
264
265void codegen_set_libc_include_dir(CodeGen *g, Buf *libc_include_dir) {
266 g->libc_include_dir = libc_include_dir;
267}
268
269void codegen_set_msvc_lib_dir(CodeGen *g, Buf *msvc_lib_dir) {
270 g->msvc_lib_dir = msvc_lib_dir;
271}
272
273void codegen_set_kernel32_lib_dir(CodeGen *g, Buf *kernel32_lib_dir) {
274 g->kernel32_lib_dir = kernel32_lib_dir;
275}
276
277void codegen_set_dynamic_linker(CodeGen *g, Buf *dynamic_linker) {
278 g->dynamic_linker = dynamic_linker;
279}
280
281234void codegen_add_lib_dir(CodeGen *g, const char *dir) {
282235 g->lib_dirs.append(dir);
283236}
......@@ -390,11 +343,11 @@ static LLVMCallConv get_llvm_cc(CodeGen *g, CallingConvention cc) {
390343 case CallingConventionC: return LLVMCCallConv;
391344 case CallingConventionCold:
392345 // cold calling convention only works on x86.
393 if (g->zig_target.arch.arch == ZigLLVM_x86 ||
394 g->zig_target.arch.arch == ZigLLVM_x86_64)
346 if (g->zig_target->arch.arch == ZigLLVM_x86 ||
347 g->zig_target->arch.arch == ZigLLVM_x86_64)
395348 {
396349 // cold calling convention is not supported on windows
397 if (g->zig_target.os == OsWindows) {
350 if (g->zig_target->os == OsWindows) {
398351 return LLVMCCallConv;
399352 } else {
400353 return LLVMColdCallConv;
......@@ -407,7 +360,7 @@ static LLVMCallConv get_llvm_cc(CodeGen *g, CallingConvention cc) {
407360 zig_unreachable();
408361 case CallingConventionStdcall:
409362 // stdcall calling convention only works on x86.
410 if (g->zig_target.arch.arch == ZigLLVM_x86) {
363 if (g->zig_target->arch.arch == ZigLLVM_x86) {
411364 return LLVMX86StdcallCallConv;
412365 } else {
413366 return LLVMCCallConv;
......@@ -419,7 +372,7 @@ static LLVMCallConv get_llvm_cc(CodeGen *g, CallingConvention cc) {
419372}
420373
421374static void add_uwtable_attr(CodeGen *g, LLVMValueRef fn_val) {
422 if (g->zig_target.os == OsWindows) {
375 if (g->zig_target->os == OsWindows) {
423376 addLLVMFnAttr(fn_val, "uwtable");
424377 }
425378}
......@@ -455,13 +408,13 @@ static uint32_t get_err_ret_trace_arg_index(CodeGen *g, ZigFn *fn_table_entry) {
455408}
456409
457410static void maybe_export_dll(CodeGen *g, LLVMValueRef global_value, GlobalLinkageId linkage) {
458 if (linkage != GlobalLinkageIdInternal && g->zig_target.os == OsWindows) {
411 if (linkage != GlobalLinkageIdInternal && g->zig_target->os == OsWindows) {
459412 LLVMSetDLLStorageClass(global_value, LLVMDLLExportStorageClass);
460413 }
461414}
462415
463416static void maybe_import_dll(CodeGen *g, LLVMValueRef global_value, GlobalLinkageId linkage) {
464 if (linkage != GlobalLinkageIdInternal && g->zig_target.os == OsWindows) {
417 if (linkage != GlobalLinkageIdInternal && g->zig_target->os == OsWindows) {
465418 // TODO come up with a good explanation/understanding for why we never do
466419 // DLLImportStorageClass. Empirically it only causes problems. But let's have
467420 // this documented and then clean up the code accordingly.
......@@ -506,7 +459,7 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) {
506459 bool external_linkage = linkage != GlobalLinkageIdInternal;
507460 CallingConvention cc = fn_table_entry->type_entry->data.fn.fn_type_id.cc;
508461 if (cc == CallingConventionStdcall && external_linkage &&
509 g->zig_target.arch.arch == ZigLLVM_x86)
462 g->zig_target->arch.arch == ZigLLVM_x86)
510463 {
511464 // prevent llvm name mangling
512465 symbol_name = buf_sprintf("\x01_%s", buf_ptr(symbol_name));
......@@ -2138,7 +2091,7 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_
21382091 return true;
21392092 }
21402093
2141 if (g->zig_target.arch.arch == ZigLLVM_x86_64) {
2094 if (g->zig_target->arch.arch == ZigLLVM_x86_64) {
21422095 X64CABIClass abi_class = type_c_abi_x86_64_class(g, ty);
21432096 size_t ty_size = type_size(g, ty);
21442097 if (abi_class == X64CABIClass_MEMORY) {
......@@ -3381,15 +3334,15 @@ static bool value_is_all_undef(ConstExprValue *const_val) {
33813334static LLVMValueRef gen_valgrind_client_request(CodeGen *g, LLVMValueRef default_value, LLVMValueRef request,
33823335 LLVMValueRef a1, LLVMValueRef a2, LLVMValueRef a3, LLVMValueRef a4, LLVMValueRef a5)
33833336{
3384 if (!target_has_valgrind_support(&g->zig_target)) {
3337 if (!target_has_valgrind_support(g->zig_target)) {
33853338 return default_value;
33863339 }
33873340 LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->type_ref;
33883341 bool asm_has_side_effects = true;
33893342 bool asm_is_alignstack = false;
3390 if (g->zig_target.arch.arch == ZigLLVM_x86_64) {
3391 if (g->zig_target.os == OsLinux || target_is_darwin(&g->zig_target) || g->zig_target.os == OsSolaris ||
3392 (g->zig_target.os == OsWindows && g->zig_target.env_type != ZigLLVM_MSVC))
3343 if (g->zig_target->arch.arch == ZigLLVM_x86_64) {
3344 if (g->zig_target->os == OsLinux || target_is_darwin(g->zig_target) || g->zig_target->os == OsSolaris ||
3345 (g->zig_target->os == OsWindows && g->zig_target->env_type != ZigLLVM_MSVC))
33933346 {
33943347 if (g->cur_fn->valgrind_client_request_array == nullptr) {
33953348 LLVMBasicBlockRef prev_block = LLVMGetInsertBlock(g->builder);
......@@ -3436,7 +3389,7 @@ static LLVMValueRef gen_valgrind_client_request(CodeGen *g, LLVMValueRef default
34363389}
34373390
34383391static bool want_valgrind_support(CodeGen *g) {
3439 if (!target_has_valgrind_support(&g->zig_target))
3392 if (!target_has_valgrind_support(g->zig_target))
34403393 return false;
34413394 switch (g->valgrind_support) {
34423395 case ValgrindSupportDisabled:
......@@ -3629,7 +3582,7 @@ static void gen_set_stack_pointer(CodeGen *g, LLVMValueRef aligned_end_addr) {
36293582 LLVMValueRef write_register_fn_val = get_write_register_fn_val(g);
36303583
36313584 if (g->sp_md_node == nullptr) {
3632 Buf *sp_reg_name = buf_create_from_str(arch_stack_pointer_register_name(&g->zig_target.arch));
3585 Buf *sp_reg_name = buf_create_from_str(arch_stack_pointer_register_name(&g->zig_target->arch));
36333586 LLVMValueRef str_node = LLVMMDString(buf_ptr(sp_reg_name), buf_len(sp_reg_name) + 1);
36343587 g->sp_md_node = LLVMMDNode(&str_node, 1);
36353588 }
......@@ -7042,7 +6995,7 @@ static void define_builtin_types(CodeGen *g) {
70426995
70436996 for (size_t i = 0; i < array_length(c_int_type_infos); i += 1) {
70446997 const CIntTypeInfo *info = &c_int_type_infos[i];
7045 uint32_t size_in_bits = target_c_type_size_in_bits(&g->zig_target, info->id);
6998 uint32_t size_in_bits = target_c_type_size_in_bits(g->zig_target, info->id);
70466999 bool is_signed = info->is_signed;
70477000
70487001 ZigType *entry = new_type_table_entry(ZigTypeIdInt);
......@@ -7309,6 +7262,9 @@ static const char *build_mode_to_str(BuildMode build_mode) {
73097262Buf *codegen_generate_builtin_source(CodeGen *g) {
73107263 Buf *contents = buf_alloc();
73117264
7265 // NOTE: when editing this file, you may need to make modifications to the
7266 // cache input parameters in define_builtin_compile_vars
7267
73127268 // Modifications to this struct must be coordinated with code that does anything with
73137269 // g->stack_trace_type. There are hard-coded references to the field indexes.
73147270 buf_append_str(contents,
......@@ -7328,7 +7284,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
73287284 const char *name = get_target_os_name(os_type);
73297285 buf_appendf(contents, " %s,\n", name);
73307286
7331 if (os_type == g->zig_target.os) {
7287 if (os_type == g->zig_target->os) {
73327288 g->target_os_index = i;
73337289 cur_os = name;
73347290 }
......@@ -7350,8 +7306,8 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
73507306
73517307 buf_appendf(contents, " %s,\n", buf_ptr(arch_name));
73527308
7353 if (arch_type->arch == g->zig_target.arch.arch &&
7354 arch_type->sub_arch == g->zig_target.arch.sub_arch)
7309 if (arch_type->arch == g->zig_target->arch.arch &&
7310 arch_type->sub_arch == g->zig_target->arch.sub_arch)
73557311 {
73567312 g->target_arch_index = i;
73577313 cur_arch = buf_ptr(arch_name);
......@@ -7370,7 +7326,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
73707326 const char *name = ZigLLVMGetEnvironmentTypeName(environ_type);
73717327 buf_appendf(contents, " %s,\n", name);
73727328
7373 if (environ_type == g->zig_target.env_type) {
7329 if (environ_type == g->zig_target->env_type) {
73747330 g->target_environ_index = i;
73757331 cur_environ = name;
73767332 }
......@@ -7388,7 +7344,8 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
73887344 const char *name = get_target_oformat_name(oformat);
73897345 buf_appendf(contents, " %s,\n", name);
73907346
7391 if (oformat == g->zig_target.oformat) {
7347 ZigLLVM_ObjectFormatType target_oformat = target_object_format(g->zig_target);
7348 if (oformat == target_oformat) {
73927349 g->target_oformat_index = i;
73937350 cur_obj_fmt = name;
73947351 }
......@@ -7707,14 +7664,15 @@ static Error define_builtin_compile_vars(CodeGen *g) {
77077664 cache_int(&cache_hash, g->build_mode);
77087665 cache_bool(&cache_hash, g->is_test_build);
77097666 cache_bool(&cache_hash, g->is_single_threaded);
7710 cache_int(&cache_hash, g->zig_target.arch.arch);
7711 cache_int(&cache_hash, g->zig_target.arch.sub_arch);
7712 cache_int(&cache_hash, g->zig_target.vendor);
7713 cache_int(&cache_hash, g->zig_target.os);
7714 cache_int(&cache_hash, g->zig_target.env_type);
7715 cache_int(&cache_hash, g->zig_target.oformat);
7667 cache_int(&cache_hash, g->zig_target->is_native);
7668 cache_int(&cache_hash, g->zig_target->arch.arch);
7669 cache_int(&cache_hash, g->zig_target->arch.sub_arch);
7670 cache_int(&cache_hash, g->zig_target->vendor);
7671 cache_int(&cache_hash, g->zig_target->os);
7672 cache_int(&cache_hash, g->zig_target->env_type);
77167673 cache_bool(&cache_hash, g->have_err_ret_tracing);
77177674 cache_bool(&cache_hash, g->libc_link_lib != nullptr);
7675 cache_bool(&cache_hash, g->valgrind_support);
77187676
77197677 Buf digest = BUF_INIT;
77207678 buf_resize(&digest, 0);
......@@ -7783,11 +7741,11 @@ static void init(CodeGen *g) {
77837741 assert(g->root_out_name);
77847742 g->module = LLVMModuleCreateWithName(buf_ptr(g->root_out_name));
77857743
7786 get_target_triple(&g->triple_str, &g->zig_target);
7744 get_target_triple(&g->triple_str, g->zig_target);
77877745
77887746 LLVMSetTarget(g->module, buf_ptr(&g->triple_str));
77897747
7790 if (g->zig_target.oformat == ZigLLVM_COFF) {
7748 if (target_object_format(g->zig_target) == ZigLLVM_COFF) {
77917749 ZigLLVMAddModuleCodeViewFlag(g->module);
77927750 } else {
77937751 ZigLLVMAddModuleDebugInfoFlag(g->module);
......@@ -7815,11 +7773,11 @@ static void init(CodeGen *g) {
78157773
78167774 const char *target_specific_cpu_args;
78177775 const char *target_specific_features;
7818 if (g->is_native_target) {
7776 if (g->zig_target->is_native) {
78197777 // LLVM creates invalid binaries on Windows sometimes.
78207778 // See https://github.com/ziglang/zig/issues/508
78217779 // As a workaround we do not use target native features on Windows.
7822 if (g->zig_target.os == OsWindows || g->zig_target.os == OsUefi) {
7780 if (g->zig_target->os == OsWindows || g->zig_target->os == OsUefi) {
78237781 target_specific_cpu_args = "";
78247782 target_specific_features = "";
78257783 } else {
......@@ -7892,9 +7850,59 @@ static void init(CodeGen *g) {
78927850 }
78937851}
78947852
7895void codegen_translate_c(CodeGen *g, Buf *full_path) {
7896 find_libc_include_path(g);
7853static void detect_libc(CodeGen *g) {
7854 Error err;
7855
7856 if (g->libc != nullptr || g->libc_link_lib == nullptr)
7857 return;
78977858
7859 if (g->zig_target->is_native) {
7860 g->libc = allocate<ZigLibCInstallation>(1);
7861
7862 // Look for zig-cache/native_libc.txt
7863 Buf *native_libc_txt = buf_alloc();
7864 os_path_join(&g->cache_dir, buf_create_from_str("native_libc.txt"), native_libc_txt);
7865 if ((err = zig_libc_parse(g->libc, native_libc_txt, g->zig_target, false))) {
7866 if ((err = zig_libc_find_native(g->libc, true))) {
7867 fprintf(stderr,
7868 "Unable to link against libc: Unable to find libc installation: %s\n"
7869 "See `zig libc --help` for more details.\n", err_str(err));
7870 exit(1);
7871 }
7872 if ((err = os_make_path(&g->cache_dir))) {
7873 fprintf(stderr, "Unable to create %s directory: %s\n",
7874 buf_ptr(&g->cache_dir), err_str(err));
7875 exit(1);
7876 }
7877 Buf *native_libc_tmp = buf_sprintf("%s.tmp", buf_ptr(native_libc_txt));
7878 FILE *file = fopen(buf_ptr(native_libc_tmp), "wb");
7879 if (file == nullptr) {
7880 fprintf(stderr, "Unable to open %s: %s\n", buf_ptr(native_libc_tmp), strerror(errno));
7881 exit(1);
7882 }
7883 zig_libc_render(g->libc, file);
7884 if (fclose(file) != 0) {
7885 fprintf(stderr, "Unable to save %s: %s\n", buf_ptr(native_libc_tmp), strerror(errno));
7886 exit(1);
7887 }
7888 if (rename(buf_ptr(native_libc_tmp), buf_ptr(native_libc_txt)) == -1) {
7889 fprintf(stderr, "Unable to create %s: %s\n", buf_ptr(native_libc_txt), strerror(errno));
7890 exit(1);
7891 }
7892 }
7893 } else if ((g->out_type == OutTypeExe || (g->out_type == OutTypeLib && !g->is_static)) &&
7894 !target_is_darwin(g->zig_target))
7895 {
7896 // Currently darwin is the only platform that we can link libc on when not compiling natively,
7897 // without a cross compiling libc kit.
7898 fprintf(stderr,
7899 "Cannot link against libc for non-native OS '%s' without providing a libc installation file.\n"
7900 "See `zig libc --help` for more details.\n", get_target_os_name(g->zig_target->os));
7901 exit(1);
7902 }
7903}
7904
7905void codegen_translate_c(CodeGen *g, Buf *full_path) {
78987906 Buf *src_basename = buf_alloc();
78997907 Buf *src_dirname = buf_alloc();
79007908 os_path_split(full_path, src_dirname, src_basename);
......@@ -7905,6 +7913,8 @@ void codegen_translate_c(CodeGen *g, Buf *full_path) {
79057913 g->root_import = import;
79067914 import->decls_scope = create_decls_scope(g, nullptr, nullptr, nullptr, import);
79077915
7916 detect_libc(g);
7917
79087918 init(g);
79097919
79107920 import->di_file = ZigLLVMCreateFile(g->dbuilder, buf_ptr(src_basename), buf_ptr(src_dirname));
......@@ -8064,14 +8074,14 @@ static void gen_root_source(CodeGen *g) {
80648074 }
80658075 report_errors_and_maybe_exit(g);
80668076
8067 if (!g->is_test_build && g->zig_target.os != OsFreestanding &&
8068 g->zig_target.os != OsUefi &&
8077 if (!g->is_test_build && g->zig_target->os != OsFreestanding &&
8078 g->zig_target->os != OsUefi &&
80698079 !g->have_c_main && !g->have_winmain && !g->have_winmain_crt_startup &&
80708080 ((g->have_pub_main && g->out_type == OutTypeObj) || g->out_type == OutTypeExe))
80718081 {
80728082 g->bootstrap_import = add_special_code(g, create_bootstrap_pkg(g, g->root_package), "bootstrap.zig");
80738083 }
8074 if (g->zig_target.os == OsWindows && !g->have_dllmain_crt_startup &&
8084 if (g->zig_target->os == OsWindows && !g->have_dllmain_crt_startup &&
80758085 g->out_type == OutTypeLib && !g->is_static)
80768086 {
80778087 g->bootstrap_import = add_special_code(g, create_bootstrap_pkg(g, g->root_package), "bootstrap_lib.zig");
......@@ -8619,6 +8629,8 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) {
86198629 }
86208630 cache_buf(ch, compiler_id);
86218631 cache_buf(ch, g->root_out_name);
8632 cache_buf(ch, g->zig_lib_dir);
8633 cache_buf(ch, g->zig_std_dir);
86228634 cache_list_of_link_lib(ch, g->link_libs_list.items, g->link_libs_list.length);
86238635 cache_list_of_buf(ch, g->darwin_frameworks.items, g->darwin_frameworks.length);
86248636 cache_list_of_buf(ch, g->rpath_list.items, g->rpath_list.length);
......@@ -8628,18 +8640,17 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) {
86288640 cache_int(ch, g->emit_file_type);
86298641 cache_int(ch, g->build_mode);
86308642 cache_int(ch, g->out_type);
8631 cache_int(ch, g->zig_target.arch.arch);
8632 cache_int(ch, g->zig_target.arch.sub_arch);
8633 cache_int(ch, g->zig_target.vendor);
8634 cache_int(ch, g->zig_target.os);
8635 cache_int(ch, g->zig_target.env_type);
8636 cache_int(ch, g->zig_target.oformat);
8643 cache_bool(ch, g->zig_target->is_native);
8644 cache_int(ch, g->zig_target->arch.arch);
8645 cache_int(ch, g->zig_target->arch.sub_arch);
8646 cache_int(ch, g->zig_target->vendor);
8647 cache_int(ch, g->zig_target->os);
8648 cache_int(ch, g->zig_target->env_type);
86378649 cache_int(ch, g->subsystem);
86388650 cache_bool(ch, g->is_static);
86398651 cache_bool(ch, g->strip_debug_symbols);
86408652 cache_bool(ch, g->is_test_build);
86418653 cache_bool(ch, g->is_single_threaded);
8642 cache_bool(ch, g->is_native_target);
86438654 cache_bool(ch, g->linker_rdynamic);
86448655 cache_bool(ch, g->each_lib_rpath);
86458656 cache_bool(ch, g->disable_pic);
......@@ -8654,6 +8665,14 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) {
86548665 cache_list_of_str(ch, g->llvm_argv, g->llvm_argv_len);
86558666 cache_list_of_str(ch, g->clang_argv, g->clang_argv_len);
86568667 cache_list_of_str(ch, g->lib_dirs.items, g->lib_dirs.length);
8668 if (g->libc) {
8669 cache_buf(ch, &g->libc->include_dir);
8670 cache_buf(ch, &g->libc->lib_dir);
8671 cache_buf(ch, &g->libc->static_lib_dir);
8672 cache_buf(ch, &g->libc->msvc_lib_dir);
8673 cache_buf(ch, &g->libc->kernel32_lib_dir);
8674 cache_buf(ch, &g->libc->dynamic_linker_path);
8675 }
86578676
86588677 buf_resize(digest, 0);
86598678 if ((err = cache_hit(ch, digest)))
......@@ -8668,19 +8687,19 @@ static void resolve_out_paths(CodeGen *g) {
86688687 switch (g->emit_file_type) {
86698688 case EmitFileTypeBinary:
86708689 {
8671 const char *o_ext = target_o_file_ext(&g->zig_target);
8690 const char *o_ext = target_o_file_ext(g->zig_target);
86728691 buf_append_str(o_basename, o_ext);
86738692 break;
86748693 }
86758694 case EmitFileTypeAssembly:
86768695 {
8677 const char *asm_ext = target_asm_file_ext(&g->zig_target);
8696 const char *asm_ext = target_asm_file_ext(g->zig_target);
86788697 buf_append_str(o_basename, asm_ext);
86798698 break;
86808699 }
86818700 case EmitFileTypeLLVMIr:
86828701 {
8683 const char *llvm_ir_ext = target_llvm_ir_file_ext(&g->zig_target);
8702 const char *llvm_ir_ext = target_llvm_ir_file_ext(g->zig_target);
86848703 buf_append_str(o_basename, llvm_ir_ext);
86858704 break;
86868705 }
......@@ -8706,7 +8725,7 @@ static void resolve_out_paths(CodeGen *g) {
87068725
87078726 Buf basename = BUF_INIT;
87088727 buf_init_from_buf(&basename, g->root_out_name);
8709 buf_append_str(&basename, target_exe_file_ext(&g->zig_target));
8728 buf_append_str(&basename, target_exe_file_ext(g->zig_target));
87108729 if (g->enable_cache || g->is_test_build) {
87118730 os_path_join(&g->artifact_dir, &basename, &g->output_file_path);
87128731 } else {
......@@ -8719,7 +8738,7 @@ static void resolve_out_paths(CodeGen *g) {
87198738 } else {
87208739 Buf basename = BUF_INIT;
87218740 buf_init_from_buf(&basename, g->root_out_name);
8722 buf_append_str(&basename, target_lib_file_ext(&g->zig_target, g->is_static,
8741 buf_append_str(&basename, target_lib_file_ext(g->zig_target, g->is_static,
87238742 g->version_major, g->version_minor, g->version_patch));
87248743 if (g->enable_cache) {
87258744 os_path_join(&g->artifact_dir, &basename, &g->output_file_path);
......@@ -8732,11 +8751,12 @@ static void resolve_out_paths(CodeGen *g) {
87328751 }
87338752}
87348753
8735
87368754void codegen_build_and_link(CodeGen *g) {
87378755 Error err;
87388756 assert(g->out_type != OutTypeUnknown);
87398757
8758 detect_libc(g);
8759
87408760 Buf *stage1_dir = get_stage1_cache_path();
87418761 Buf *artifact_dir = buf_alloc();
87428762 Buf digest = BUF_INIT;
src/codegen.hpp+2-7
......@@ -11,11 +11,12 @@
1111#include "parser.hpp"
1212#include "errmsg.hpp"
1313#include "target.hpp"
14#include "libc_installation.hpp"
1415
1516#include <stdio.h>
1617
1718CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out_type, BuildMode build_mode,
18 Buf *zig_lib_dir, Buf *override_std_dir);
19 Buf *zig_lib_dir, Buf *override_std_dir, ZigLibCInstallation *libc);
1920
2021void codegen_set_clang_argv(CodeGen *codegen, const char **args, size_t len);
2122void codegen_set_llvm_argv(CodeGen *codegen, const char **args, size_t len);
......@@ -27,12 +28,6 @@ void codegen_set_is_static(CodeGen *codegen, bool is_static);
2728void codegen_set_strip(CodeGen *codegen, bool strip);
2829void codegen_set_errmsg_color(CodeGen *codegen, ErrColor err_color);
2930void codegen_set_out_name(CodeGen *codegen, Buf *out_name);
30void codegen_set_libc_lib_dir(CodeGen *codegen, Buf *libc_lib_dir);
31void codegen_set_libc_static_lib_dir(CodeGen *g, Buf *libc_static_lib_dir);
32void codegen_set_libc_include_dir(CodeGen *codegen, Buf *libc_include_dir);
33void codegen_set_msvc_lib_dir(CodeGen *g, Buf *msvc_lib_dir);
34void codegen_set_kernel32_lib_dir(CodeGen *codegen, Buf *kernel32_lib_dir);
35void codegen_set_dynamic_linker(CodeGen *g, Buf *dynamic_linker);
3631void codegen_add_lib_dir(CodeGen *codegen, const char *dir);
3732void codegen_add_forbidden_lib(CodeGen *codegen, Buf *lib);
3833LinkLib *codegen_add_link_lib(CodeGen *codegen, Buf *lib);
src/error.cpp+2
......@@ -34,6 +34,8 @@ const char *err_str(Error err) {
3434 case ErrorPipeBusy: return "pipe busy";
3535 case ErrorPrimitiveTypeNotFound: return "primitive type not found";
3636 case ErrorCacheUnavailable: return "cache unavailable";
37 case ErrorPathTooLong: return "path too long";
38 case ErrorCCompilerCannotFindFile: return "C compiler cannot find file";
3739 }
3840 return "(invalid error)";
3941}
src/error.hpp+2
......@@ -36,6 +36,8 @@ enum Error {
3636 ErrorPipeBusy,
3737 ErrorPrimitiveTypeNotFound,
3838 ErrorCacheUnavailable,
39 ErrorPathTooLong,
40 ErrorCCompilerCannotFindFile,
3941};
4042
4143const char *err_str(Error err);
src/ir.cpp-2
......@@ -18690,8 +18690,6 @@ static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruct
1869018690 if (type_is_invalid(cimport_result->type))
1869118691 return ira->codegen->invalid_instruction;
1869218692
18693 find_libc_include_path(ira->codegen);
18694
1869518693 ImportTableEntry *child_import = allocate<ImportTableEntry>(1);
1869618694 child_import->decls_scope = create_decls_scope(ira->codegen, node, nullptr, nullptr, child_import);
1869718695 child_import->c_import_node = node;
src/libc_installation.cpp created+408
......@@ -0,0 +1,408 @@
1/*
2 * Copyright (c) 2019 Andrew Kelley
3 *
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
7
8#include "libc_installation.hpp"
9#include "os.hpp"
10#include "windows_sdk.h"
11#include "target.hpp"
12
13static const size_t zig_libc_keys_len = 6;
14
15static const char *zig_libc_keys[] = {
16 "include_dir",
17 "lib_dir",
18 "static_lib_dir",
19 "msvc_lib_dir",
20 "kernel32_lib_dir",
21 "dynamic_linker_path",
22};
23
24static bool zig_libc_match_key(Slice<uint8_t> name, Slice<uint8_t> value, bool *found_keys,
25 size_t index, Buf *field_ptr)
26{
27 if (!memEql(name, str(zig_libc_keys[index]))) return false;
28 buf_init_from_mem(field_ptr, (const char*)value.ptr, value.len);
29 found_keys[index] = true;
30 return true;
31}
32
33static void zig_libc_init_empty(ZigLibCInstallation *libc) {
34 *libc = {};
35 buf_init_from_str(&libc->include_dir, "");
36 buf_init_from_str(&libc->lib_dir, "");
37 buf_init_from_str(&libc->static_lib_dir, "");
38 buf_init_from_str(&libc->msvc_lib_dir, "");
39 buf_init_from_str(&libc->kernel32_lib_dir, "");
40 buf_init_from_str(&libc->dynamic_linker_path, "");
41}
42
43Error zig_libc_parse(ZigLibCInstallation *libc, Buf *libc_file, const ZigTarget *target, bool verbose) {
44 Error err;
45 zig_libc_init_empty(libc);
46
47 bool found_keys[6] = {}; // zig_libc_keys_len
48
49 Buf *contents = buf_alloc();
50 if ((err = os_fetch_file_path(libc_file, contents, false))) {
51 if (err != ErrorFileNotFound && verbose) {
52 fprintf(stderr, "Unable to read '%s': %s\n", buf_ptr(libc_file), err_str(err));
53 }
54 return err;
55 }
56
57 SplitIterator it = memSplit(buf_to_slice(contents), str("\n"));
58 for (;;) {
59 Optional<Slice<uint8_t>> opt_line = SplitIterator_next(&it);
60 if (!opt_line.is_some)
61 break;
62
63 if (opt_line.value.len == 0 || opt_line.value.ptr[0] == '#')
64 continue;
65
66 SplitIterator line_it = memSplit(opt_line.value, str("="));
67 Slice<uint8_t> name;
68 if (!SplitIterator_next(&line_it).unwrap(&name)) {
69 if (verbose) {
70 fprintf(stderr, "missing equal sign after field name\n");
71 }
72 return ErrorSemanticAnalyzeFail;
73 }
74 Slice<uint8_t> value = SplitIterator_rest(&line_it);
75 bool match = false;
76 match = match || zig_libc_match_key(name, value, found_keys, 0, &libc->include_dir);
77 match = match || zig_libc_match_key(name, value, found_keys, 1, &libc->lib_dir);
78 match = match || zig_libc_match_key(name, value, found_keys, 2, &libc->static_lib_dir);
79 match = match || zig_libc_match_key(name, value, found_keys, 3, &libc->msvc_lib_dir);
80 match = match || zig_libc_match_key(name, value, found_keys, 4, &libc->kernel32_lib_dir);
81 match = match || zig_libc_match_key(name, value, found_keys, 5, &libc->dynamic_linker_path);
82 }
83
84 for (size_t i = 0; i < zig_libc_keys_len; i += 1) {
85 if (!found_keys[i]) {
86 if (verbose) {
87 fprintf(stderr, "missing field: %s\n", zig_libc_keys[i]);
88 }
89 return ErrorSemanticAnalyzeFail;
90 }
91 }
92
93 if (buf_len(&libc->include_dir) == 0) {
94 if (verbose) {
95 fprintf(stderr, "include_dir may not be empty\n");
96 }
97 return ErrorSemanticAnalyzeFail;
98 }
99
100 if (buf_len(&libc->lib_dir) == 0) {
101 if (!target_is_darwin(target)) {
102 if (verbose) {
103 fprintf(stderr, "lib_dir may not be empty for %s\n", get_target_os_name(target->os));
104 }
105 return ErrorSemanticAnalyzeFail;
106 }
107 }
108
109 if (buf_len(&libc->static_lib_dir) == 0) {
110 if (!target_is_darwin(target) && target->os != OsWindows) {
111 if (verbose) {
112 fprintf(stderr, "static_lib_dir may not be empty for %s\n", get_target_os_name(target->os));
113 }
114 return ErrorSemanticAnalyzeFail;
115 }
116 }
117
118 if (buf_len(&libc->msvc_lib_dir) == 0) {
119 if (target->os == OsWindows) {
120 if (verbose) {
121 fprintf(stderr, "msvc_lib_dir may not be empty for %s\n", get_target_os_name(target->os));
122 }
123 return ErrorSemanticAnalyzeFail;
124 }
125 }
126
127 if (buf_len(&libc->kernel32_lib_dir) == 0) {
128 if (target->os == OsWindows) {
129 if (verbose) {
130 fprintf(stderr, "kernel32_lib_dir may not be empty for %s\n", get_target_os_name(target->os));
131 }
132 return ErrorSemanticAnalyzeFail;
133 }
134 }
135
136 if (buf_len(&libc->dynamic_linker_path) == 0) {
137 if (target->os == OsLinux) {
138 if (verbose) {
139 fprintf(stderr, "dynamic_linker_path may not be empty for %s\n", get_target_os_name(target->os));
140 }
141 return ErrorSemanticAnalyzeFail;
142 }
143 }
144
145 return ErrorNone;
146}
147
148#if defined(ZIG_OS_WINDOWS)
149static Error zig_libc_find_native_include_dir_windows(ZigLibCInstallation *self, ZigWindowsSDK *sdk, bool verbose) {
150 Error err;
151 if ((err = os_get_win32_ucrt_include_path(sdk, &self->include_dir))) {
152 if (verbose) {
153 fprintf(stderr, "Unable to determine libc include path: %s\n", err_str(err));
154 }
155 return err;
156 }
157 return ErrorNone;
158}
159static Error zig_libc_find_lib_dir_windows(ZigLibCInstallation *self, ZigWindowsSDK *sdk, ZigTarget *target,
160 bool verbose)
161{
162 Error err;
163 if ((err = os_get_win32_ucrt_lib_path(sdk, &self->lib_dir, target->arch.arch))) {
164 if (verbose) {
165 fprintf(stderr, "Unable to determine ucrt path: %s\n", err_str(err));
166 }
167 return err;
168 }
169 return ErrorNone;
170}
171static Error zig_libc_find_kernel32_lib_dir(ZigLibCInstallation *self, ZigWindowsSDK *sdk, ZigTarget *target,
172 bool verbose)
173{
174 Error err;
175 if ((err = os_get_win32_kern32_path(sdk, &self->kernel32_lib_dir, target->arch.arch))) {
176 if (verbose) {
177 fprintf(stderr, "Unable to determine kernel32 path: %s\n", err_str(err));
178 }
179 return err;
180 }
181 return ErrorNone;
182}
183static Error zig_libc_find_native_msvc_lib_dir(ZigLibCInstallation *self, ZigWindowsSDK *sdk, bool verbose) {
184 if (sdk->msvc_lib_dir_ptr == nullptr) {
185 if (verbose) {
186 fprintf(stderr, "Unable to determine vcruntime path\n");
187 }
188 return ErrorFileNotFound;
189 }
190 buf_init_from_mem(&self->msvc_lib_dir, sdk->msvc_lib_dir_ptr, sdk->msvc_lib_dir_len);
191 return ErrorNone;
192}
193#else
194static Error zig_libc_find_native_include_dir_posix(ZigLibCInstallation *self, bool verbose) {
195 const char *cc_exe = getenv("CC");
196 cc_exe = (cc_exe == nullptr) ? "cc" : cc_exe;
197 ZigList<const char *> args = {};
198 args.append("-E");
199 args.append("-Wp,-v");
200 args.append("-xc");
201 args.append("/dev/null");
202 Termination term;
203 Buf *out_stderr = buf_alloc();
204 Buf *out_stdout = buf_alloc();
205 Error err;
206 if ((err = os_exec_process(cc_exe, args, &term, out_stderr, out_stdout))) {
207 if (verbose) {
208 fprintf(stderr, "unable to determine libc include path: executing '%s': %s\n", cc_exe, err_str(err));
209 }
210 return err;
211 }
212 if (term.how != TerminationIdClean || term.code != 0) {
213 if (verbose) {
214 fprintf(stderr, "unable to determine libc include path: executing '%s' failed\n", cc_exe);
215 }
216 return ErrorCCompileErrors;
217 }
218 char *prev_newline = buf_ptr(out_stderr);
219 ZigList<const char *> search_paths = {};
220 for (;;) {
221 char *newline = strchr(prev_newline, '\n');
222 if (newline == nullptr) {
223 break;
224 }
225 *newline = 0;
226 if (prev_newline[0] == ' ') {
227 search_paths.append(prev_newline);
228 }
229 prev_newline = newline + 1;
230 }
231 if (search_paths.length == 0) {
232 if (verbose) {
233 fprintf(stderr, "unable to determine libc include path: '%s' cannot find libc headers\n", cc_exe);
234 }
235 return ErrorCCompileErrors;
236 }
237 for (size_t i = 0; i < search_paths.length; i += 1) {
238 // search in reverse order
239 const char *search_path = search_paths.items[search_paths.length - i - 1];
240 // cut off spaces
241 while (*search_path == ' ') {
242 search_path += 1;
243 }
244 Buf *stdlib_path = buf_sprintf("%s/stdlib.h", search_path);
245 bool exists;
246 if ((err = os_file_exists(stdlib_path, &exists))) {
247 exists = false;
248 }
249 if (exists) {
250 buf_init_from_str(&self->include_dir, search_path);
251 return ErrorNone;
252 }
253 }
254 if (verbose) {
255 fprintf(stderr, "unable to determine libc include path: stdlib.h not found in '%s' search paths\n", cc_exe);
256 }
257 return ErrorFileNotFound;
258}
259#if !defined(ZIG_OS_DARWIN)
260static Error zig_libc_cc_print_file_name(const char *o_file, Buf *out, bool want_dirname, bool verbose) {
261 const char *cc_exe = getenv("CC");
262 cc_exe = (cc_exe == nullptr) ? "cc" : cc_exe;
263 ZigList<const char *> args = {};
264 args.append(buf_ptr(buf_sprintf("-print-file-name=%s", o_file)));
265 Termination term;
266 Buf *out_stderr = buf_alloc();
267 Buf *out_stdout = buf_alloc();
268 Error err;
269 if ((err = os_exec_process(cc_exe, args, &term, out_stderr, out_stdout))) {
270 if (verbose) {
271 fprintf(stderr, "unable to determine libc include path: executing '%s': %s\n", cc_exe, err_str(err));
272 }
273 return err;
274 }
275 if (term.how != TerminationIdClean || term.code != 0) {
276 if (verbose) {
277 fprintf(stderr, "unable to determine libc include path: executing '%s' failed\n", cc_exe);
278 }
279 return ErrorCCompileErrors;
280 }
281 if (buf_ends_with_str(out_stdout, "\n")) {
282 buf_resize(out_stdout, buf_len(out_stdout) - 1);
283 }
284 if (buf_len(out_stdout) == 0 || buf_eql_str(out_stdout, o_file)) {
285 return ErrorCCompilerCannotFindFile;
286 }
287 if (want_dirname) {
288 os_path_dirname(out_stdout, out);
289 } else {
290 buf_init_from_buf(out, out_stdout);
291 }
292 return ErrorNone;
293}
294static Error zig_libc_find_native_lib_dir_posix(ZigLibCInstallation *self, bool verbose) {
295 return zig_libc_cc_print_file_name("crt1.o", &self->lib_dir, true, verbose);
296}
297
298static Error zig_libc_find_native_static_lib_dir_posix(ZigLibCInstallation *self, bool verbose) {
299 return zig_libc_cc_print_file_name("crtbegin.o", &self->static_lib_dir, true, verbose);
300}
301#endif
302
303static Error zig_libc_find_native_dynamic_linker_posix(ZigLibCInstallation *self, bool verbose) {
304#if defined(ZIG_OS_LINUX)
305 Error err;
306 static const char *dyn_tests[] = {
307 "ld-linux-x86-64.so.2",
308 "ld-musl-x86_64.so.1",
309 };
310 for (size_t i = 0; i < array_length(dyn_tests); i += 1) {
311 const char *lib_name = dyn_tests[i];
312 if ((err = zig_libc_cc_print_file_name(lib_name, &self->dynamic_linker_path, false, true))) {
313 if (err != ErrorCCompilerCannotFindFile)
314 return err;
315 continue;
316 }
317 return ErrorNone;
318 }
319#endif
320 ZigTarget native_target;
321 get_native_target(&native_target);
322 Buf *dynamic_linker_path = target_dynamic_linker(&native_target);
323 buf_init_from_buf(&self->dynamic_linker_path, dynamic_linker_path);
324 return ErrorNone;
325}
326#endif
327
328void zig_libc_render(ZigLibCInstallation *self, FILE *file) {
329 fprintf(file,
330 "# The directory that contains `stdlib.h`.\n"
331 "# On Linux, can be found with: `cc -E -Wp,-v -xc /dev/null`\n"
332 "include_dir=%s\n"
333 "\n"
334 "# The directory that contains `crt1.o`.\n"
335 "# On Linux, can be found with `cc -print-file-name=crt1.o`.\n"
336 "# Not needed when targeting MacOS.\n"
337 "lib_dir=%s\n"
338 "\n"
339 "# The directory that contains `crtbegin.o`.\n"
340 "# On Linux, can be found with `cc -print-file-name=crtbegin.o`.\n"
341 "# Not needed when targeting MacOS or Windows.\n"
342 "static_lib_dir=%s\n"
343 "\n"
344 "# The directory that contains `vcruntime.lib`.\n"
345 "# Only needed when targeting Windows.\n"
346 "msvc_lib_dir=%s\n"
347 "\n"
348 "# The directory that contains `kernel32.lib`.\n"
349 "# Only needed when targeting Windows.\n"
350 "kernel32_lib_dir=%s\n"
351 "\n"
352 "# The full path to the dynamic linker, on the target system.\n"
353 "# Only needed when targeting Linux.\n"
354 "dynamic_linker_path=%s\n"
355 "\n"
356 ,
357 buf_ptr(&self->include_dir),
358 buf_ptr(&self->lib_dir),
359 buf_ptr(&self->static_lib_dir),
360 buf_ptr(&self->msvc_lib_dir),
361 buf_ptr(&self->kernel32_lib_dir),
362 buf_ptr(&self->dynamic_linker_path)
363 );
364}
365
366Error zig_libc_find_native(ZigLibCInstallation *self, bool verbose) {
367 Error err;
368 zig_libc_init_empty(self);
369#if defined(ZIG_OS_WINDOWS)
370 ZigTarget native_target;
371 get_native_target(&native_target);
372 ZigWindowsSDK *sdk;
373 switch (zig_find_windows_sdk(&sdk)) {
374 case ZigFindWindowsSdkErrorNone:
375 if ((err = zig_libc_find_native_msvc_lib_dir(self, sdk, verbose)))
376 return err;
377 if ((err = zig_libc_find_kernel32_lib_dir(self, sdk, &native_target, verbose)))
378 return err;
379 if ((err = zig_libc_find_native_include_dir_windows(self, sdk, verbose)))
380 return err;
381 if ((err = zig_libc_find_lib_dir_windows(self, sdk, &native_target, verbose)))
382 return err;
383 return ErrorNone;
384 case ZigFindWindowsSdkErrorOutOfMemory:
385 return ErrorNoMem;
386 case ZigFindWindowsSdkErrorNotFound:
387 return ErrorFileNotFound;
388 case ZigFindWindowsSdkErrorPathTooLong:
389 return ErrorPathTooLong;
390 }
391 zig_unreachable();
392#else
393 if ((err = zig_libc_find_native_include_dir_posix(self, verbose)))
394 return err;
395#if defined(ZIG_OS_FREEBSD) || defined(ZIG_OS_NETBSD)
396 buf_init_from_str(&self->lib_dir, "/usr/lib");
397 buf_init_from_str(&self->static_lib_dir, "/usr/lib");
398#elif !defined(ZIG_OS_DARWIN)
399 if ((err = zig_libc_find_native_lib_dir_posix(self, verbose)))
400 return err;
401 if ((err = zig_libc_find_native_static_lib_dir_posix(self, verbose)))
402 return err;
403#endif
404 if ((err = zig_libc_find_native_dynamic_linker_posix(self, verbose)))
405 return err;
406 return ErrorNone;
407#endif
408}
src/libc_installation.hpp created+33
......@@ -0,0 +1,33 @@
1/*
2 * Copyright (c) 2019 Andrew Kelley
3 *
4 * This file is part of zig, which is MIT licensed.
5 * See http://opensource.org/licenses/MIT
6 */
7
8#ifndef ZIG_LIBC_INSTALLATION_HPP
9#define ZIG_LIBC_INSTALLATION_HPP
10
11#include <stdio.h>
12
13#include "buffer.hpp"
14#include "error.hpp"
15#include "target.hpp"
16
17// Must be synchronized with zig_libc_keys
18struct ZigLibCInstallation {
19 Buf include_dir;
20 Buf lib_dir;
21 Buf static_lib_dir;
22 Buf msvc_lib_dir;
23 Buf kernel32_lib_dir;
24 Buf dynamic_linker_path;
25};
26
27Error ATTRIBUTE_MUST_USE zig_libc_parse(ZigLibCInstallation *libc, Buf *libc_file,
28 const ZigTarget *target, bool verbose);
29void zig_libc_render(ZigLibCInstallation *self, FILE *file);
30
31Error ATTRIBUTE_MUST_USE zig_libc_find_native(ZigLibCInstallation *self, bool verbose);
32
33#endif
src/link.cpp+45-104
......@@ -18,31 +18,32 @@ struct LinkJob {
1818};
1919
2020static const char *get_libc_file(CodeGen *g, const char *file) {
21 assert(g->libc != nullptr);
2122 Buf *out_buf = buf_alloc();
22 os_path_join(g->libc_lib_dir, buf_create_from_str(file), out_buf);
23 os_path_join(&g->libc->lib_dir, buf_create_from_str(file), out_buf);
2324 return buf_ptr(out_buf);
2425}
2526
2627static const char *get_libc_static_file(CodeGen *g, const char *file) {
28 assert(g->libc != nullptr);
2729 Buf *out_buf = buf_alloc();
28 os_path_join(g->libc_static_lib_dir, buf_create_from_str(file), out_buf);
30 os_path_join(&g->libc->static_lib_dir, buf_create_from_str(file), out_buf);
2931 return buf_ptr(out_buf);
3032}
3133
3234static 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;
34
3535 // The Mach-O LLD code is not well maintained, and trips an assertion
3636 // when we link compiler_rt and builtin as libraries rather than objects.
3737 // Here we workaround this by having compiler_rt and builtin be objects.
3838 // TODO write our own linker. https://github.com/ziglang/zig/issues/1535
3939 OutType child_out_type = OutTypeLib;
40 if (parent_gen->zig_target.os == OsMacOSX) {
40 if (parent_gen->zig_target->os == OsMacOSX) {
4141 child_out_type = OutTypeObj;
4242 }
4343
44 CodeGen *child_gen = codegen_create(full_path, child_target, child_out_type,
45 parent_gen->build_mode, parent_gen->zig_lib_dir, parent_gen->zig_std_dir);
44 CodeGen *child_gen = codegen_create(full_path, parent_gen->zig_target, child_out_type,
45 parent_gen->build_mode, parent_gen->zig_lib_dir, parent_gen->zig_std_dir,
46 parent_gen->libc);
4647
4748 child_gen->out_h_path = nullptr;
4849 child_gen->verbose_tokenize = parent_gen->verbose_tokenize;
......@@ -171,62 +172,11 @@ static void add_rpath(LinkJob *lj, Buf *rpath) {
171172 lj->rpath_table.put(rpath, true);
172173}
173174
174static Buf *try_dynamic_linker_path(const char *ld_name) {
175 const char *cc_exe = getenv("CC");
176 cc_exe = (cc_exe == nullptr) ? "cc" : cc_exe;
177 ZigList<const char *> args = {};
178 args.append(buf_ptr(buf_sprintf("-print-file-name=%s", ld_name)));
179 Termination term;
180 Buf *out_stderr = buf_alloc();
181 Buf *out_stdout = buf_alloc();
182 int err;
183 if ((err = os_exec_process(cc_exe, args, &term, out_stderr, out_stdout))) {
184 return nullptr;
185 }
186 if (term.how != TerminationIdClean || term.code != 0) {
187 return nullptr;
188 }
189 if (buf_ends_with_str(out_stdout, "\n")) {
190 buf_resize(out_stdout, buf_len(out_stdout) - 1);
191 }
192 if (buf_len(out_stdout) == 0 || buf_eql_str(out_stdout, ld_name)) {
193 return nullptr;
194 }
195 return out_stdout;
196}
197
198static Buf *get_dynamic_linker_path(CodeGen *g) {
199 if (g->zig_target.os == OsFreeBSD) {
200 return buf_create_from_str("/libexec/ld-elf.so.1");
201 }
202 if (g->zig_target.os == OsNetBSD) {
203 return buf_create_from_str("/libexec/ld.elf_so");
204 }
205 if (g->is_native_target && g->zig_target.arch.arch == ZigLLVM_x86_64) {
206 static const char *ld_names[] = {
207 "ld-linux-x86-64.so.2",
208 "ld-musl-x86_64.so.1",
209 };
210 for (size_t i = 0; i < array_length(ld_names); i += 1) {
211 const char *ld_name = ld_names[i];
212 Buf *result = try_dynamic_linker_path(ld_name);
213 if (result != nullptr) {
214 return result;
215 }
216 }
217 }
218 return target_dynamic_linker(&g->zig_target);
219}
220
221175static void construct_linker_job_elf(LinkJob *lj) {
222176 CodeGen *g = lj->codegen;
223177
224178 lj->args.append("-error-limit=0");
225179
226 if (g->libc_link_lib != nullptr) {
227 find_libc_lib_path(g);
228 }
229
230180 if (g->linker_script) {
231181 lj->args.append("-T");
232182 lj->args.append(g->linker_script);
......@@ -235,14 +185,14 @@ static void construct_linker_job_elf(LinkJob *lj) {
235185 lj->args.append("--gc-sections");
236186
237187 lj->args.append("-m");
238 lj->args.append(getLDMOption(&g->zig_target));
188 lj->args.append(getLDMOption(g->zig_target));
239189
240190 bool is_lib = g->out_type == OutTypeLib;
241191 bool shared = !g->is_static && is_lib;
242192 Buf *soname = nullptr;
243193 if (g->is_static) {
244 if (g->zig_target.arch.arch == ZigLLVM_arm || g->zig_target.arch.arch == ZigLLVM_armeb ||
245 g->zig_target.arch.arch == ZigLLVM_thumb || g->zig_target.arch.arch == ZigLLVM_thumbeb)
194 if (g->zig_target->arch.arch == ZigLLVM_arm || g->zig_target->arch.arch == ZigLLVM_armeb ||
195 g->zig_target->arch.arch == ZigLLVM_thumb || g->zig_target->arch.arch == ZigLLVM_thumbeb)
246196 {
247197 lj->args.append("-Bstatic");
248198 } else {
......@@ -264,13 +214,13 @@ static void construct_linker_job_elf(LinkJob *lj) {
264214 if (lj->link_in_crt) {
265215 const char *crt1o;
266216 const char *crtbegino;
267 if (g->zig_target.os == OsNetBSD) {
268 crt1o = "crt0.o";
269 crtbegino = "crtbegin.o";
270 } else if (g->is_static) {
217 if (g->zig_target->os == OsNetBSD) {
218 crt1o = "crt0.o";
219 crtbegino = "crtbegin.o";
220 } else if (g->is_static) {
271221 crt1o = "crt1.o";
272222 crtbegino = "crtbeginT.o";
273 } else {
223 } else {
274224 crt1o = "Scrt1.o";
275225 crtbegino = "crtbegin.o";
276226 }
......@@ -311,23 +261,19 @@ static void construct_linker_job_elf(LinkJob *lj) {
311261 }
312262
313263 if (g->libc_link_lib != nullptr) {
264 assert(g->libc != nullptr);
314265 lj->args.append("-L");
315 lj->args.append(buf_ptr(g->libc_lib_dir));
266 lj->args.append(buf_ptr(&g->libc->lib_dir));
316267
317268 lj->args.append("-L");
318 lj->args.append(buf_ptr(g->libc_static_lib_dir));
319 }
269 lj->args.append(buf_ptr(&g->libc->static_lib_dir));
320270
321 if (!g->is_static) {
322 if (g->dynamic_linker != nullptr) {
323 assert(buf_len(g->dynamic_linker) != 0);
324 lj->args.append("-dynamic-linker");
325 lj->args.append(buf_ptr(g->dynamic_linker));
326 } else {
327 Buf *resolved_dynamic_linker = get_dynamic_linker_path(g);
271 if (!g->is_static) {
272 assert(buf_len(&g->libc->dynamic_linker_path) != 0);
328273 lj->args.append("-dynamic-linker");
329 lj->args.append(buf_ptr(resolved_dynamic_linker));
274 lj->args.append(buf_ptr(&g->libc->dynamic_linker_path));
330275 }
276
331277 }
332278
333279 if (shared) {
......@@ -397,11 +343,11 @@ static void construct_linker_job_elf(LinkJob *lj) {
397343 lj->args.append(get_libc_file(g, "crtn.o"));
398344 }
399345
400 if (!g->is_native_target) {
346 if (!g->zig_target->is_native) {
401347 lj->args.append("--allow-shlib-undefined");
402348 }
403349
404 if (g->zig_target.os == OsZen) {
350 if (g->zig_target->os == OsZen) {
405351 lj->args.append("-e");
406352 lj->args.append("_start");
407353
......@@ -429,11 +375,11 @@ static void construct_linker_job_wasm(LinkJob *lj) {
429375//}
430376
431377static void coff_append_machine_arg(CodeGen *g, ZigList<const char *> *list) {
432 if (g->zig_target.arch.arch == ZigLLVM_x86) {
378 if (g->zig_target->arch.arch == ZigLLVM_x86) {
433379 list->append("-MACHINE:X86");
434 } else if (g->zig_target.arch.arch == ZigLLVM_x86_64) {
380 } else if (g->zig_target->arch.arch == ZigLLVM_x86_64) {
435381 list->append("-MACHINE:X64");
436 } else if (g->zig_target.arch.arch == ZigLLVM_arm) {
382 } else if (g->zig_target->arch.arch == ZigLLVM_arm) {
437383 list->append("-MACHINE:ARM");
438384 }
439385}
......@@ -592,10 +538,6 @@ static void construct_linker_job_coff(LinkJob *lj) {
592538
593539 lj->args.append("/ERRORLIMIT:0");
594540
595 if (g->libc_link_lib != nullptr) {
596 find_libc_lib_path(g);
597 }
598
599541 lj->args.append("/NOLOGO");
600542
601543 if (!g->strip_debug_symbols) {
......@@ -650,13 +592,11 @@ static void construct_linker_job_coff(LinkJob *lj) {
650592 lj->args.append(buf_ptr(buf_sprintf("-OUT:%s", buf_ptr(&g->output_file_path))));
651593
652594 if (g->libc_link_lib != nullptr) {
653 lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(g->msvc_lib_dir))));
654 lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(g->kernel32_lib_dir))));
595 assert(g->libc != nullptr);
655596
656 lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(g->libc_lib_dir))));
657 if (g->libc_static_lib_dir != nullptr) {
658 lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(g->libc_static_lib_dir))));
659 }
597 lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(&g->libc->msvc_lib_dir))));
598 lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(&g->libc->kernel32_lib_dir))));
599 lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(&g->libc->lib_dir))));
660600 }
661601
662602 if (is_library && !g->is_static) {
......@@ -691,7 +631,7 @@ static void construct_linker_job_coff(LinkJob *lj) {
691631 continue;
692632 }
693633 if (link_lib->provided_explicitly) {
694 if (lj->codegen->zig_target.env_type == ZigLLVM_GNU) {
634 if (lj->codegen->zig_target->env_type == ZigLLVM_GNU) {
695635 Buf *arg = buf_sprintf("-l%s", buf_ptr(link_lib->name));
696636 lj->args.append(buf_ptr(arg));
697637 }
......@@ -721,7 +661,8 @@ static void construct_linker_job_coff(LinkJob *lj) {
721661 gen_lib_args.append(buf_ptr(buf_sprintf("-DEF:%s", buf_ptr(def_path))));
722662 gen_lib_args.append(buf_ptr(buf_sprintf("-OUT:%s", buf_ptr(generated_lib_path))));
723663 Buf diag = BUF_INIT;
724 if (!zig_lld_link(g->zig_target.oformat, gen_lib_args.items, gen_lib_args.length, &diag)) {
664 ZigLLVM_ObjectFormatType target_ofmt = target_object_format(g->zig_target);
665 if (!zig_lld_link(target_ofmt, gen_lib_args.items, gen_lib_args.length, &diag)) {
725666 fprintf(stderr, "%s\n", buf_ptr(&diag));
726667 exit(1);
727668 }
......@@ -790,7 +731,7 @@ static void get_darwin_platform(LinkJob *lj, DarwinPlatform *platform) {
790731 platform->kind = MacOS;
791732 } else if (g->mios_version_min) {
792733 platform->kind = IPhoneOS;
793 } else if (g->zig_target.os == OsMacOSX) {
734 } else if (g->zig_target->os == OsMacOSX) {
794735 platform->kind = MacOS;
795736 g->mmacosx_version_min = buf_create_from_str("10.10");
796737 } else {
......@@ -817,8 +758,8 @@ static void get_darwin_platform(LinkJob *lj, DarwinPlatform *platform) {
817758 }
818759
819760 if (platform->kind == IPhoneOS &&
820 (g->zig_target.arch.arch == ZigLLVM_x86 ||
821 g->zig_target.arch.arch == ZigLLVM_x86_64))
761 (g->zig_target->arch.arch == ZigLLVM_x86 ||
762 g->zig_target->arch.arch == ZigLLVM_x86_64))
822763 {
823764 platform->kind = IPhoneOSSimulator;
824765 }
......@@ -882,7 +823,7 @@ static void construct_linker_job_macho(LinkJob *lj) {
882823 }
883824
884825 lj->args.append("-arch");
885 lj->args.append(get_darwin_arch_string(&g->zig_target));
826 lj->args.append(get_darwin_arch_string(g->zig_target));
886827
887828 DarwinPlatform platform;
888829 get_darwin_platform(lj, &platform);
......@@ -939,7 +880,7 @@ static void construct_linker_job_macho(LinkJob *lj) {
939880 }
940881 break;
941882 case IPhoneOS:
942 if (g->zig_target.arch.arch == ZigLLVM_aarch64) {
883 if (g->zig_target->arch.arch == ZigLLVM_aarch64) {
943884 // iOS does not need any crt1 files for arm64
944885 } else if (darwin_version_lt(&platform, 3, 1)) {
945886 lj->args.append("-lcrt1.o");
......@@ -969,7 +910,7 @@ static void construct_linker_job_macho(LinkJob *lj) {
969910 lj->args.append(buf_ptr(compiler_rt_o_path));
970911 }
971912
972 if (g->is_native_target) {
913 if (g->zig_target->is_native) {
973914 for (size_t lib_i = 0; lib_i < g->link_libs_list.length; lib_i += 1) {
974915 LinkLib *link_lib = g->link_libs_list.at(lib_i);
975916 if (buf_eql_str(link_lib->name, "c")) {
......@@ -1010,7 +951,7 @@ static void construct_linker_job_macho(LinkJob *lj) {
1010951}
1011952
1012953static void construct_linker_job(LinkJob *lj) {
1013 switch (lj->codegen->zig_target.oformat) {
954 switch (target_object_format(lj->codegen->zig_target)) {
1014955 case ZigLLVM_UnknownObjectFormat:
1015956 zig_unreachable();
1016957
......@@ -1050,7 +991,7 @@ void codegen_link(CodeGen *g) {
1050991 for (size_t i = 0; i < g->link_objects.length; i += 1) {
1051992 file_names.append((const char *)buf_ptr(g->link_objects.at(i)));
1052993 }
1053 ZigLLVM_OSType os_type = get_llvm_os_type(g->zig_target.os);
994 ZigLLVM_OSType os_type = get_llvm_os_type(g->zig_target->os);
1054995 codegen_add_time_event(g, "LLVM Link");
1055996 if (ZigLLVMWriteArchive(buf_ptr(&g->output_file_path), file_names.items, file_names.length, os_type)) {
1056997 fprintf(stderr, "Unable to write archive '%s'\n", buf_ptr(&g->output_file_path));
......@@ -1075,7 +1016,7 @@ void codegen_link(CodeGen *g) {
10751016 Buf diag = BUF_INIT;
10761017
10771018 codegen_add_time_event(g, "LLVM Link");
1078 if (g->system_linker_hack && g->zig_target.os == OsMacOSX) {
1019 if (g->system_linker_hack && g->zig_target->os == OsMacOSX) {
10791020 Termination term;
10801021 ZigList<const char *> args = {};
10811022 for (size_t i = 1; i < lj.args.length; i += 1) {
......@@ -1085,7 +1026,7 @@ void codegen_link(CodeGen *g) {
10851026 if (term.how != TerminationIdClean || term.code != 0) {
10861027 exit(1);
10871028 }
1088 } else if (!zig_lld_link(g->zig_target.oformat, lj.args.items, lj.args.length, &diag)) {
1029 } else if (!zig_lld_link(target_object_format(g->zig_target), lj.args.items, lj.args.length, &diag)) {
10891030 fprintf(stderr, "%s\n", buf_ptr(&diag));
10901031 exit(1);
10911032 }
src/main.cpp+75-52
......@@ -13,6 +13,7 @@
1313#include "error.hpp"
1414#include "os.hpp"
1515#include "target.hpp"
16#include "libc_installation.hpp"
1617
1718#include <stdio.h>
1819
......@@ -36,6 +37,7 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) {
3637 " id print the base64-encoded compiler id\n"
3738 " init-exe initialize a `zig build` application in the cwd\n"
3839 " init-lib initialize a `zig build` library in the cwd\n"
40 " libc [paths_file] Display native libc paths file or validate one\n"
3941 " run [source] create executable and run immediately\n"
4042 " translate-c [source] convert c code to zig code\n"
4143 " targets list available compilation targets\n"
......@@ -53,7 +55,7 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) {
5355 " --enable-valgrind include valgrind client requests release builds\n"
5456 " --emit [asm|bin|llvm-ir] emit a specific file format as compilation output\n"
5557 " -ftime-report print timing diagnostics\n"
56 " --libc-include-dir [path] directory where libc stdlib.h resides\n"
58 " --libc [file] Provide a file which specifies libc paths\n"
5759 " --name [name] override output name\n"
5860 " --output [file] override destination path\n"
5961 " --output-h [file] generate header file\n"
......@@ -82,10 +84,6 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) {
8284 "Link Options:\n"
8385 " --dynamic-linker [path] set the path to ld.so\n"
8486 " --each-lib-rpath add rpath for each used dynamic library\n"
85 " --libc-lib-dir [path] directory where libc crt1.o resides\n"
86 " --libc-static-lib-dir [path] directory where libc crtbegin.o resides\n"
87 " --msvc-lib-dir [path] (windows) directory where vcruntime.lib resides\n"
88 " --kernel32-lib-dir [path] (windows) directory where kernel32.lib resides\n"
8987 " --library [lib] link against lib\n"
9088 " --forbid-library [lib] make it an error to link against lib\n"
9189 " --library-path [dir] add a directory to the library search path\n"
......@@ -111,6 +109,26 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) {
111109 return return_code;
112110}
113111
112static int print_libc_usage(const char *arg0, FILE *file, int return_code) {
113 fprintf(file,
114 "Usage: %s libc\n"
115 "\n"
116 "Detect the native libc installation and print the resulting paths to stdout.\n"
117 "You can save this into a file and then edit the paths to create a cross\n"
118 "compilation libc kit. Then you can pass `--libc [file]` for Zig to use it.\n"
119 "\n"
120 "When compiling natively and no `--libc` argument provided, Zig automatically\n"
121 "creates zig-cache/native_libc.txt so that it does not have to detect libc\n"
122 "on every invocation. You can remove this file to have Zig re-detect the\n"
123 "native libc.\n"
124 "\n\n"
125 "Usage: %s libc [file]\n"
126 "\n"
127 "Parse a libc installation text file and validate it.\n"
128 , arg0, arg0);
129 return return_code;
130}
131
114132static const char *ZIG_ZEN = "\n"
115133" * Communicate intent precisely.\n"
116134" * Edge cases matter.\n"
......@@ -169,6 +187,7 @@ enum Cmd {
169187 CmdTranslateC,
170188 CmdVersion,
171189 CmdZen,
190 CmdLibC,
172191};
173192
174193static const char *default_zig_cache_name = "zig-cache";
......@@ -359,12 +378,7 @@ int main(int argc, char **argv) {
359378 bool verbose_cimport = false;
360379 ErrColor color = ErrColorAuto;
361380 CacheOpt enable_cache = CacheOptAuto;
362 const char *libc_lib_dir = nullptr;
363 const char *libc_static_lib_dir = nullptr;
364 const char *libc_include_dir = nullptr;
365 const char *msvc_lib_dir = nullptr;
366 const char *kernel32_lib_dir = nullptr;
367 const char *dynamic_linker = nullptr;
381 const char *libc_txt = nullptr;
368382 ZigList<const char *> clang_argv = {0};
369383 ZigList<const char *> llvm_argv = {0};
370384 ZigList<const char *> lib_dirs = {0};
......@@ -434,8 +448,10 @@ int main(int argc, char **argv) {
434448 Buf *build_runner_path = buf_alloc();
435449 os_path_join(get_zig_special_dir(), buf_create_from_str("build_runner.zig"), build_runner_path);
436450
437 CodeGen *g = codegen_create(build_runner_path, nullptr, OutTypeExe, BuildModeDebug, get_zig_lib_dir(),
438 override_std_dir);
451 ZigTarget target;
452 get_native_target(&target);
453 CodeGen *g = codegen_create(build_runner_path, &target, OutTypeExe, BuildModeDebug, get_zig_lib_dir(),
454 override_std_dir, nullptr);
439455 g->valgrind_support = valgrind_support;
440456 g->enable_time_report = timing_info;
441457 buf_init_from_str(&g->cache_dir, cache_dir ? cache_dir : default_zig_cache_name);
......@@ -520,10 +536,12 @@ int main(int argc, char **argv) {
520536 return (term.how == TerminationIdClean) ? term.code : -1;
521537 } else if (argc >= 2 && strcmp(argv[1], "fmt") == 0) {
522538 init_all_targets();
539 ZigTarget target;
540 get_native_target(&target);
523541 Buf *fmt_runner_path = buf_alloc();
524542 os_path_join(get_zig_special_dir(), buf_create_from_str("fmt_runner.zig"), fmt_runner_path);
525 CodeGen *g = codegen_create(fmt_runner_path, nullptr, OutTypeExe, BuildModeDebug, get_zig_lib_dir(),
526 nullptr);
543 CodeGen *g = codegen_create(fmt_runner_path, &target, OutTypeExe, BuildModeDebug, get_zig_lib_dir(),
544 nullptr, nullptr);
527545 g->valgrind_support = valgrind_support;
528546 g->is_single_threaded = true;
529547 codegen_set_out_name(g, buf_create_from_str("fmt"));
......@@ -557,7 +575,11 @@ int main(int argc, char **argv) {
557575 } else if (strcmp(arg, "--release-small") == 0) {
558576 build_mode = BuildModeSmallRelease;
559577 } else if (strcmp(arg, "--help") == 0) {
560 return print_full_usage(arg0, stderr, EXIT_FAILURE);
578 if (cmd == CmdLibC) {
579 return print_libc_usage(arg0, stderr, EXIT_FAILURE);
580 } else {
581 return print_full_usage(arg0, stderr, EXIT_FAILURE);
582 }
561583 } else if (strcmp(arg, "--strip") == 0) {
562584 strip = true;
563585 } else if (strcmp(arg, "--static") == 0) {
......@@ -658,18 +680,8 @@ int main(int argc, char **argv) {
658680 }
659681 } else if (strcmp(arg, "--name") == 0) {
660682 out_name = argv[i];
661 } else if (strcmp(arg, "--libc-lib-dir") == 0) {
662 libc_lib_dir = argv[i];
663 } else if (strcmp(arg, "--libc-static-lib-dir") == 0) {
664 libc_static_lib_dir = argv[i];
665 } else if (strcmp(arg, "--libc-include-dir") == 0) {
666 libc_include_dir = argv[i];
667 } else if (strcmp(arg, "--msvc-lib-dir") == 0) {
668 msvc_lib_dir = argv[i];
669 } else if (strcmp(arg, "--kernel32-lib-dir") == 0) {
670 kernel32_lib_dir = argv[i];
671 } else if (strcmp(arg, "--dynamic-linker") == 0) {
672 dynamic_linker = argv[i];
683 } else if (strcmp(arg, "--libc") == 0) {
684 libc_txt = argv[i];
673685 } else if (strcmp(arg, "-isystem") == 0) {
674686 clang_argv.append("-isystem");
675687 clang_argv.append(argv[i]);
......@@ -778,6 +790,8 @@ int main(int argc, char **argv) {
778790 cmd = CmdVersion;
779791 } else if (strcmp(arg, "zen") == 0) {
780792 cmd = CmdZen;
793 } else if (strcmp(arg, "libc") == 0) {
794 cmd = CmdLibC;
781795 } else if (strcmp(arg, "translate-c") == 0) {
782796 cmd = CmdTranslateC;
783797 } else if (strcmp(arg, "test") == 0) {
......@@ -797,6 +811,7 @@ int main(int argc, char **argv) {
797811 case CmdRun:
798812 case CmdTranslateC:
799813 case CmdTest:
814 case CmdLibC:
800815 if (!in_file) {
801816 in_file = arg;
802817 if (cmd == CmdRun) {
......@@ -828,27 +843,25 @@ int main(int argc, char **argv) {
828843
829844 init_all_targets();
830845
831 ZigTarget alloc_target;
832 ZigTarget *target;
846 ZigTarget target;
833847 if (!target_arch && !target_os && !target_environ) {
834 target = nullptr;
848 get_native_target(&target);
835849 } else {
836 target = &alloc_target;
837 get_unknown_target(target);
850 get_unknown_target(&target);
838851 if (target_arch) {
839 if (parse_target_arch(target_arch, &target->arch)) {
852 if (parse_target_arch(target_arch, &target.arch)) {
840853 fprintf(stderr, "invalid --target-arch argument\n");
841854 return print_error_usage(arg0);
842855 }
843856 }
844857 if (target_os) {
845 if (parse_target_os(target_os, &target->os)) {
858 if (parse_target_os(target_os, &target.os)) {
846859 fprintf(stderr, "invalid --target-os argument\n");
847860 return print_error_usage(arg0);
848861 }
849862 }
850863 if (target_environ) {
851 if (parse_target_environ(target_environ, &target->env_type)) {
864 if (parse_target_environ(target_environ, &target.env_type)) {
852865 fprintf(stderr, "invalid --target-environ argument\n");
853866 return print_error_usage(arg0);
854867 }
......@@ -856,8 +869,22 @@ int main(int argc, char **argv) {
856869 }
857870
858871 switch (cmd) {
872 case CmdLibC: {
873 if (in_file) {
874 ZigLibCInstallation libc;
875 if ((err = zig_libc_parse(&libc, buf_create_from_str(in_file), &target, true)))
876 return EXIT_FAILURE;
877 return EXIT_SUCCESS;
878 }
879 ZigLibCInstallation libc;
880 if ((err = zig_libc_find_native(&libc, true)))
881 return EXIT_FAILURE;
882 zig_libc_render(&libc, stdout);
883 return EXIT_SUCCESS;
884 }
859885 case CmdBuiltin: {
860 CodeGen *g = codegen_create(nullptr, target, out_type, build_mode, get_zig_lib_dir(), override_std_dir);
886 CodeGen *g = codegen_create(nullptr, &target, out_type, build_mode, get_zig_lib_dir(), override_std_dir,
887 nullptr);
861888 g->valgrind_support = valgrind_support;
862889 g->is_single_threaded = is_single_threaded;
863890 Buf *builtin_source = codegen_generate_builtin_source(g);
......@@ -917,8 +944,16 @@ int main(int argc, char **argv) {
917944 if (cmd == CmdRun && buf_out_name == nullptr) {
918945 buf_out_name = buf_create_from_str("run");
919946 }
920 CodeGen *g = codegen_create(zig_root_source_file, target, out_type, build_mode, get_zig_lib_dir(),
921 override_std_dir);
947 ZigLibCInstallation *libc = nullptr;
948 if (libc_txt != nullptr) {
949 libc = allocate<ZigLibCInstallation>(1);
950 if ((err = zig_libc_parse(libc, buf_create_from_str(libc_txt), &target, true))) {
951 fprintf(stderr, "Unable to parse --libc text file: %s\n", err_str(err));
952 return EXIT_FAILURE;
953 }
954 }
955 CodeGen *g = codegen_create(zig_root_source_file, &target, out_type, build_mode, get_zig_lib_dir(),
956 override_std_dir, libc);
922957 g->valgrind_support = valgrind_support;
923958 g->subsystem = subsystem;
924959
......@@ -944,18 +979,6 @@ int main(int argc, char **argv) {
944979 codegen_set_llvm_argv(g, llvm_argv.items, llvm_argv.length);
945980 codegen_set_strip(g, strip);
946981 codegen_set_is_static(g, is_static);
947 if (libc_lib_dir)
948 codegen_set_libc_lib_dir(g, buf_create_from_str(libc_lib_dir));
949 if (libc_static_lib_dir)
950 codegen_set_libc_static_lib_dir(g, buf_create_from_str(libc_static_lib_dir));
951 if (libc_include_dir)
952 codegen_set_libc_include_dir(g, buf_create_from_str(libc_include_dir));
953 if (msvc_lib_dir)
954 codegen_set_msvc_lib_dir(g, buf_create_from_str(msvc_lib_dir));
955 if (kernel32_lib_dir)
956 codegen_set_kernel32_lib_dir(g, buf_create_from_str(kernel32_lib_dir));
957 if (dynamic_linker)
958 codegen_set_dynamic_linker(g, buf_create_from_str(dynamic_linker));
959982 g->verbose_tokenize = verbose_tokenize;
960983 g->verbose_ast = verbose_ast;
961984 g->verbose_link = verbose_link;
......@@ -1086,7 +1109,7 @@ int main(int argc, char **argv) {
10861109 }
10871110 }
10881111
1089 if (!target_can_exec(&native, target)) {
1112 if (!target_can_exec(&native, &target)) {
10901113 fprintf(stderr, "Created %s but skipping execution because it is non-native.\n",
10911114 buf_ptr(test_exe_path));
10921115 return 0;
src/os.cpp+7-7
......@@ -1550,7 +1550,7 @@ void os_stderr_set_color(TermColor color) {
15501550#endif
15511551}
15521552
1553int os_get_win32_ucrt_lib_path(ZigWindowsSDK *sdk, Buf* output_buf, ZigLLVM_ArchType platform_type) {
1553Error os_get_win32_ucrt_lib_path(ZigWindowsSDK *sdk, Buf* output_buf, ZigLLVM_ArchType platform_type) {
15541554#if defined(ZIG_OS_WINDOWS)
15551555 buf_resize(output_buf, 0);
15561556 buf_appendf(output_buf, "%s\\Lib\\%s\\ucrt\\", sdk->path10_ptr, sdk->version10_ptr);
......@@ -1571,7 +1571,7 @@ int os_get_win32_ucrt_lib_path(ZigWindowsSDK *sdk, Buf* output_buf, ZigLLVM_Arch
15711571 buf_init_from_buf(tmp_buf, output_buf);
15721572 buf_append_str(tmp_buf, "ucrt.lib");
15731573 if (GetFileAttributesA(buf_ptr(tmp_buf)) != INVALID_FILE_ATTRIBUTES) {
1574 return 0;
1574 return ErrorNone;
15751575 }
15761576 else {
15771577 buf_resize(output_buf, 0);
......@@ -1582,12 +1582,12 @@ int os_get_win32_ucrt_lib_path(ZigWindowsSDK *sdk, Buf* output_buf, ZigLLVM_Arch
15821582#endif
15831583}
15841584
1585int os_get_win32_ucrt_include_path(ZigWindowsSDK *sdk, Buf* output_buf) {
1585Error os_get_win32_ucrt_include_path(ZigWindowsSDK *sdk, Buf* output_buf) {
15861586#if defined(ZIG_OS_WINDOWS)
15871587 buf_resize(output_buf, 0);
15881588 buf_appendf(output_buf, "%s\\Include\\%s\\ucrt", sdk->path10_ptr, sdk->version10_ptr);
15891589 if (GetFileAttributesA(buf_ptr(output_buf)) != INVALID_FILE_ATTRIBUTES) {
1590 return 0;
1590 return ErrorNone;
15911591 }
15921592 else {
15931593 buf_resize(output_buf, 0);
......@@ -1598,7 +1598,7 @@ int os_get_win32_ucrt_include_path(ZigWindowsSDK *sdk, Buf* output_buf) {
15981598#endif
15991599}
16001600
1601int os_get_win32_kern32_path(ZigWindowsSDK *sdk, Buf* output_buf, ZigLLVM_ArchType platform_type) {
1601Error os_get_win32_kern32_path(ZigWindowsSDK *sdk, Buf* output_buf, ZigLLVM_ArchType platform_type) {
16021602#if defined(ZIG_OS_WINDOWS)
16031603 {
16041604 buf_resize(output_buf, 0);
......@@ -1620,7 +1620,7 @@ int os_get_win32_kern32_path(ZigWindowsSDK *sdk, Buf* output_buf, ZigLLVM_ArchTy
16201620 buf_init_from_buf(tmp_buf, output_buf);
16211621 buf_append_str(tmp_buf, "kernel32.lib");
16221622 if (GetFileAttributesA(buf_ptr(tmp_buf)) != INVALID_FILE_ATTRIBUTES) {
1623 return 0;
1623 return ErrorNone;
16241624 }
16251625 }
16261626 {
......@@ -1643,7 +1643,7 @@ int os_get_win32_kern32_path(ZigWindowsSDK *sdk, Buf* output_buf, ZigLLVM_ArchTy
16431643 buf_init_from_buf(tmp_buf, output_buf);
16441644 buf_append_str(tmp_buf, "kernel32.lib");
16451645 if (GetFileAttributesA(buf_ptr(tmp_buf)) != INVALID_FILE_ATTRIBUTES) {
1646 return 0;
1646 return ErrorNone;
16471647 }
16481648 }
16491649 return ErrorFileNotFound;
src/os.hpp+3-3
......@@ -135,9 +135,9 @@ Error ATTRIBUTE_MUST_USE os_self_exe_path(Buf *out_path);
135135
136136Error ATTRIBUTE_MUST_USE os_get_app_data_dir(Buf *out_path, const char *appname);
137137
138int os_get_win32_ucrt_include_path(ZigWindowsSDK *sdk, Buf *output_buf);
139int os_get_win32_ucrt_lib_path(ZigWindowsSDK *sdk, Buf *output_buf, ZigLLVM_ArchType platform_type);
140int os_get_win32_kern32_path(ZigWindowsSDK *sdk, Buf *output_buf, ZigLLVM_ArchType platform_type);
138Error ATTRIBUTE_MUST_USE os_get_win32_ucrt_include_path(ZigWindowsSDK *sdk, Buf *output_buf);
139Error ATTRIBUTE_MUST_USE os_get_win32_ucrt_lib_path(ZigWindowsSDK *sdk, Buf *output_buf, ZigLLVM_ArchType platform_type);
140Error ATTRIBUTE_MUST_USE os_get_win32_kern32_path(ZigWindowsSDK *sdk, Buf *output_buf, ZigLLVM_ArchType platform_type);
141141
142142Error ATTRIBUTE_MUST_USE os_self_exe_shared_libs(ZigList<Buf *> &paths);
143143
src/target.cpp+38-87
......@@ -214,7 +214,7 @@ size_t target_oformat_count(void) {
214214 return array_length(oformat_list);
215215}
216216
217const ZigLLVM_ObjectFormatType get_target_oformat(size_t index) {
217ZigLLVM_ObjectFormatType get_target_oformat(size_t index) {
218218 return oformat_list[index];
219219}
220220
......@@ -443,14 +443,16 @@ ZigLLVM_EnvironmentType get_target_environ(size_t index) {
443443
444444void get_native_target(ZigTarget *target) {
445445 ZigLLVM_OSType os_type;
446 ZigLLVM_ObjectFormatType oformat; // ignored; based on arch/os
446447 ZigLLVMGetNativeTarget(
447448 &target->arch.arch,
448449 &target->arch.sub_arch,
449450 &target->vendor,
450451 &os_type,
451452 &target->env_type,
452 &target->oformat);
453 &oformat);
453454 target->os = get_zig_os_type(os_type);
455 target->is_native = true;
454456}
455457
456458void get_unknown_target(ZigTarget *target) {
......@@ -459,7 +461,7 @@ void get_unknown_target(ZigTarget *target) {
459461 target->vendor = ZigLLVM_UnknownVendor;
460462 target->os = OsFreestanding;
461463 target->env_type = ZigLLVM_UnknownEnvironment;
462 target->oformat = ZigLLVM_UnknownObjectFormat;
464 target->is_native = false;
463465}
464466
465467static void get_arch_name_raw(char *out_str, ZigLLVM_ArchType arch, ZigLLVM_SubArchType sub_arch) {
......@@ -554,85 +556,18 @@ bool target_is_darwin(const ZigTarget *target) {
554556 }
555557}
556558
557void resolve_target_object_format(ZigTarget *target) {
558 if (target->oformat != ZigLLVM_UnknownObjectFormat) {
559 return;
559ZigLLVM_ObjectFormatType target_object_format(const ZigTarget *target) {
560 if (target->os == OsUefi || target->os == OsWindows) {
561 return ZigLLVM_COFF;
562 } else if (target_is_darwin(target)) {
563 return ZigLLVM_MachO;
560564 }
561
562 switch (target->arch.arch) {
563 case ZigLLVM_UnknownArch:
564 case ZigLLVM_aarch64:
565 case ZigLLVM_arm:
566 case ZigLLVM_thumb:
567 case ZigLLVM_x86:
568 case ZigLLVM_x86_64:
569 if (target_is_darwin(target)) {
570 target->oformat = ZigLLVM_MachO;
571 } else if (target->os == OsWindows) {
572 target->oformat = ZigLLVM_COFF;
573 } else {
574 target->oformat = ZigLLVM_ELF;
575 }
576 return;
577
578 case ZigLLVM_aarch64_be:
579 case ZigLLVM_amdgcn:
580 case ZigLLVM_amdil:
581 case ZigLLVM_amdil64:
582 case ZigLLVM_armeb:
583 case ZigLLVM_arc:
584 case ZigLLVM_avr:
585 case ZigLLVM_bpfeb:
586 case ZigLLVM_bpfel:
587 case ZigLLVM_hexagon:
588 case ZigLLVM_lanai:
589 case ZigLLVM_hsail:
590 case ZigLLVM_hsail64:
591 case ZigLLVM_kalimba:
592 case ZigLLVM_le32:
593 case ZigLLVM_le64:
594 case ZigLLVM_mips:
595 case ZigLLVM_mips64:
596 case ZigLLVM_mips64el:
597 case ZigLLVM_mipsel:
598 case ZigLLVM_msp430:
599 case ZigLLVM_nios2:
600 case ZigLLVM_nvptx:
601 case ZigLLVM_nvptx64:
602 case ZigLLVM_ppc64le:
603 case ZigLLVM_r600:
604 case ZigLLVM_renderscript32:
605 case ZigLLVM_renderscript64:
606 case ZigLLVM_riscv32:
607 case ZigLLVM_riscv64:
608 case ZigLLVM_shave:
609 case ZigLLVM_sparc:
610 case ZigLLVM_sparcel:
611 case ZigLLVM_sparcv9:
612 case ZigLLVM_spir:
613 case ZigLLVM_spir64:
614 case ZigLLVM_systemz:
615 case ZigLLVM_tce:
616 case ZigLLVM_tcele:
617 case ZigLLVM_thumbeb:
618 case ZigLLVM_xcore:
619 target->oformat= ZigLLVM_ELF;
620 return;
621
622 case ZigLLVM_wasm32:
623 case ZigLLVM_wasm64:
624 target->oformat = ZigLLVM_Wasm;
625 return;
626
627 case ZigLLVM_ppc:
628 case ZigLLVM_ppc64:
629 if (target_is_darwin(target)) {
630 target->oformat = ZigLLVM_MachO;
631 } else {
632 target->oformat= ZigLLVM_ELF;
633 }
634 return;
565 if (target->arch.arch == ZigLLVM_wasm32 ||
566 target->arch.arch == ZigLLVM_wasm64)
567 {
568 return ZigLLVM_Wasm;
635569 }
570 return ZigLLVM_ELF;
636571}
637572
638573// See lib/Support/Triple.cpp in LLVM for the source of this data.
......@@ -812,7 +747,7 @@ bool target_allows_addr_zero(const ZigTarget *target) {
812747 return target->os == OsFreestanding;
813748}
814749
815const char *target_o_file_ext(ZigTarget *target) {
750const char *target_o_file_ext(const ZigTarget *target) {
816751 if (target->env_type == ZigLLVM_MSVC || target->os == OsWindows || target->os == OsUefi) {
817752 return ".obj";
818753 } else {
......@@ -820,15 +755,15 @@ const char *target_o_file_ext(ZigTarget *target) {
820755 }
821756}
822757
823const char *target_asm_file_ext(ZigTarget *target) {
758const char *target_asm_file_ext(const ZigTarget *target) {
824759 return ".s";
825760}
826761
827const char *target_llvm_ir_file_ext(ZigTarget *target) {
762const char *target_llvm_ir_file_ext(const ZigTarget *target) {
828763 return ".ll";
829764}
830765
831const char *target_exe_file_ext(ZigTarget *target) {
766const char *target_exe_file_ext(const ZigTarget *target) {
832767 if (target->os == OsWindows) {
833768 return ".exe";
834769 } else if (target->os == OsUefi) {
......@@ -838,7 +773,9 @@ const char *target_exe_file_ext(ZigTarget *target) {
838773 }
839774}
840775
841const char *target_lib_file_ext(ZigTarget *target, bool is_static, size_t version_major, size_t version_minor, size_t version_patch) {
776const char *target_lib_file_ext(const ZigTarget *target, bool is_static,
777 size_t version_major, size_t version_minor, size_t version_patch)
778{
842779 if (target->os == OsWindows || target->os == OsUefi) {
843780 if (is_static) {
844781 return ".lib";
......@@ -860,7 +797,7 @@ enum FloatAbi {
860797 FloatAbiSoftFp,
861798};
862799
863static FloatAbi get_float_abi(ZigTarget *target) {
800static FloatAbi get_float_abi(const ZigTarget *target) {
864801 const ZigLLVM_EnvironmentType env = target->env_type;
865802 if (env == ZigLLVM_GNUEABIHF ||
866803 env == ZigLLVM_EABIHF ||
......@@ -876,7 +813,14 @@ static bool is_64_bit(ZigLLVM_ArchType arch) {
876813 return get_arch_pointer_bit_width(arch) == 64;
877814}
878815
879Buf *target_dynamic_linker(ZigTarget *target) {
816Buf *target_dynamic_linker(const ZigTarget *target) {
817 if (target->os == OsFreeBSD) {
818 return buf_create_from_str("/libexec/ld-elf.so.1");
819 }
820 if (target->os == OsNetBSD) {
821 return buf_create_from_str("/libexec/ld.elf_so");
822 }
823
880824 const ZigLLVM_ArchType arch = target->arch.arch;
881825 const ZigLLVM_EnvironmentType env = target->env_type;
882826
......@@ -1098,3 +1042,10 @@ bool target_has_valgrind_support(const ZigTarget *target) {
10981042 }
10991043 zig_unreachable();
11001044}
1045
1046bool target_requires_libc(const ZigTarget *target) {
1047 // On Darwin, we always link libSystem which contains libc.
1048 // Similarly on FreeBSD and NetBSD we always link system libc
1049 // since this is the stable syscall interface.
1050 return (target_is_darwin(target) || target->os == OsFreeBSD || target->os == OsNetBSD);
1051}
src/target.hpp+11-8
......@@ -71,7 +71,7 @@ struct ZigTarget {
7171 ZigLLVM_VendorType vendor;
7272 Os os;
7373 ZigLLVM_EnvironmentType env_type;
74 ZigLLVM_ObjectFormatType oformat;
74 bool is_native;
7575};
7676
7777enum CIntType {
......@@ -105,8 +105,9 @@ ZigLLVM_EnvironmentType get_target_environ(size_t index);
105105
106106
107107size_t target_oformat_count(void);
108const ZigLLVM_ObjectFormatType get_target_oformat(size_t index);
108ZigLLVM_ObjectFormatType get_target_oformat(size_t index);
109109const char *get_target_oformat_name(ZigLLVM_ObjectFormatType oformat);
110ZigLLVM_ObjectFormatType target_object_format(const ZigTarget *target);
110111
111112void get_native_target(ZigTarget *target);
112113void get_unknown_target(ZigTarget *target);
......@@ -123,13 +124,14 @@ void resolve_target_object_format(ZigTarget *target);
123124
124125uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id);
125126
126const char *target_o_file_ext(ZigTarget *target);
127const char *target_asm_file_ext(ZigTarget *target);
128const char *target_llvm_ir_file_ext(ZigTarget *target);
129const char *target_exe_file_ext(ZigTarget *target);
130const char *target_lib_file_ext(ZigTarget *target, bool is_static, size_t version_major, size_t version_minor, size_t version_patch);
127const char *target_o_file_ext(const ZigTarget *target);
128const char *target_asm_file_ext(const ZigTarget *target);
129const char *target_llvm_ir_file_ext(const ZigTarget *target);
130const char *target_exe_file_ext(const ZigTarget *target);
131const char *target_lib_file_ext(const ZigTarget *target, bool is_static,
132 size_t version_major, size_t version_minor, size_t version_patch);
131133
132Buf *target_dynamic_linker(ZigTarget *target);
134Buf *target_dynamic_linker(const ZigTarget *target);
133135
134136bool target_can_exec(const ZigTarget *host_target, const ZigTarget *guest_target);
135137ZigLLVM_OSType get_llvm_os_type(Os os_type);
......@@ -138,5 +140,6 @@ bool target_is_arm(const ZigTarget *target);
138140bool target_allows_addr_zero(const ZigTarget *target);
139141bool target_has_valgrind_support(const ZigTarget *target);
140142bool target_is_darwin(const ZigTarget *target);
143bool target_requires_libc(const ZigTarget *target);
141144
142145#endif
src/translate_c.cpp+4-4
......@@ -4776,7 +4776,7 @@ Error parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const
47764776 clang_argv.append("-x");
47774777 clang_argv.append("c");
47784778
4779 if (c->codegen->is_native_target) {
4779 if (c->codegen->zig_target->is_native) {
47804780 char *ZIG_PARSEC_CFLAGS = getenv("ZIG_NATIVE_PARSEC_CFLAGS");
47814781 if (ZIG_PARSEC_CFLAGS) {
47824782 Buf tmp_buf = BUF_INIT;
......@@ -4798,9 +4798,9 @@ Error parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const
47984798 clang_argv.append("-isystem");
47994799 clang_argv.append(buf_ptr(codegen->zig_c_headers_dir));
48004800
4801 if (codegen->libc_include_dir != nullptr) {
4801 if (codegen->libc != nullptr) {
48024802 clang_argv.append("-isystem");
4803 clang_argv.append(buf_ptr(codegen->libc_include_dir));
4803 clang_argv.append(buf_ptr(&codegen->libc->include_dir));
48044804 }
48054805
48064806 // windows c runtime requires -D_DEBUG if using debug libraries
......@@ -4820,7 +4820,7 @@ Error parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const
48204820 clang_argv.append("-Xclang");
48214821 clang_argv.append("-detailed-preprocessing-record");
48224822
4823 if (!c->codegen->is_native_target) {
4823 if (!c->codegen->zig_target->is_native) {
48244824 clang_argv.append("-target");
48254825 clang_argv.append(buf_ptr(&c->codegen->triple_str));
48264826 }