diff --git a/CMakeLists.txt b/CMakeLists.txt index 814a05c49f..5eb35d2281 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -414,6 +414,7 @@ set(ZIG_SOURCES "${CMAKE_SOURCE_DIR}/src/error.cpp" "${CMAKE_SOURCE_DIR}/src/ir.cpp" "${CMAKE_SOURCE_DIR}/src/ir_print.cpp" + "${CMAKE_SOURCE_DIR}/src/libc_installation.cpp" "${CMAKE_SOURCE_DIR}/src/link.cpp" "${CMAKE_SOURCE_DIR}/src/main.cpp" "${CMAKE_SOURCE_DIR}/src/os.cpp" diff --git a/src/all_types.hpp b/src/all_types.hpp index 29598672cd..f29411476e 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -18,6 +18,7 @@ #include "bigfloat.hpp" #include "target.hpp" #include "tokenizer.hpp" +#include "libc_installation.hpp" struct AstNode; struct ImportTableEntry; @@ -1743,6 +1744,9 @@ struct CodeGen { Buf *wanted_output_file_path; Buf cache_dir; + Buf *zig_c_headers_dir; // Cannot be overridden; derived from zig_lib_dir. + Buf *zig_std_special_dir; // Cannot be overridden; derived from zig_lib_dir. + IrInstruction *invalid_instruction; IrInstruction *unreach_instruction; @@ -1791,6 +1795,8 @@ struct CodeGen { bool system_linker_hack; //////////////////////////// Participates in Input Parameter Cache Hash + /////// Note: there is a separate cache hash for builtin.zig, when adding fields, + /////// consider if they need to go into both. ZigList link_libs_list; // add -framework [name] args to linker ZigList darwin_frameworks; @@ -1801,6 +1807,8 @@ struct CodeGen { ZigList assembly_files; ZigList lib_dirs; + ZigLibCInstallation *libc; + size_t version_major; size_t version_minor; size_t version_patch; @@ -1809,14 +1817,13 @@ struct CodeGen { EmitFileType emit_file_type; BuildMode build_mode; OutType out_type; - ZigTarget zig_target; + const ZigTarget *zig_target; TargetSubsystem subsystem; ValgrindSupport valgrind_support; bool is_static; bool strip_debug_symbols; bool is_test_build; bool is_single_threaded; - bool is_native_target; bool linker_rdynamic; bool each_lib_rpath; bool disable_pic; @@ -1827,26 +1834,14 @@ struct CodeGen { Buf *test_filter; Buf *test_name_prefix; PackageTableEntry *root_package; + Buf *zig_lib_dir; + Buf *zig_std_dir; const char **llvm_argv; size_t llvm_argv_len; const char **clang_argv; size_t clang_argv_len; - - //////////////////////////// Unsorted - - Buf *libc_lib_dir; - Buf *libc_static_lib_dir; - Buf *libc_include_dir; - Buf *msvc_lib_dir; - Buf *kernel32_lib_dir; - Buf *zig_lib_dir; - Buf *zig_std_dir; - Buf *zig_c_headers_dir; - Buf *zig_std_special_dir; - Buf *dynamic_linker; - ZigWindowsSDK *win_sdk; }; enum VarLinkage { diff --git a/src/analyze.cpp b/src/analyze.cpp index 020446eb44..0ecff11142 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -1102,10 +1102,10 @@ bool want_first_arg_sret(CodeGen *g, FnTypeId *fn_type_id) { if (type_is_c_abi_int(g, fn_type_id->return_type)) { return false; } - if (g->zig_target.arch.arch == ZigLLVM_x86_64) { + if (g->zig_target->arch.arch == ZigLLVM_x86_64) { X64CABIClass abi_class = type_c_abi_x86_64_class(g, fn_type_id->return_type); return abi_class == X64CABIClass_MEMORY; - } else if (target_is_arm(&g->zig_target)) { + } else if (target_is_arm(g->zig_target)) { return type_size(g, fn_type_id->return_type) > 16; } 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 g->have_c_main = true; g->subsystem = TargetSubsystemConsole; } else if (buf_eql_str(symbol_name, "WinMain") && - g->zig_target.os == OsWindows) + g->zig_target->os == OsWindows) { g->have_winmain = true; g->subsystem = TargetSubsystemWindows; } else if (buf_eql_str(symbol_name, "WinMainCRTStartup") && - g->zig_target.os == OsWindows) + g->zig_target->os == OsWindows) { g->have_winmain_crt_startup = true; } else if (buf_eql_str(symbol_name, "DllMainCRTStartup") && - g->zig_target.os == OsWindows) + g->zig_target->os == OsWindows) { g->have_dllmain_crt_startup = true; } @@ -4651,186 +4651,6 @@ bool handle_is_ptr(ZigType *type_entry) { zig_unreachable(); } -static ZigWindowsSDK *get_windows_sdk(CodeGen *g) { - if (g->win_sdk == nullptr) { - if (zig_find_windows_sdk(&g->win_sdk)) { - fprintf(stderr, "unable to determine windows sdk path\n"); - exit(1); - } - } - assert(g->win_sdk != nullptr); - return g->win_sdk; -} - - -static Buf *get_linux_libc_lib_path(const char *o_file) { - const char *cc_exe = getenv("CC"); - cc_exe = (cc_exe == nullptr) ? "cc" : cc_exe; - ZigList args = {}; - args.append(buf_ptr(buf_sprintf("-print-file-name=%s", o_file))); - Termination term; - Buf *out_stderr = buf_alloc(); - Buf *out_stdout = buf_alloc(); - Error err; - if ((err = os_exec_process(cc_exe, args, &term, out_stderr, out_stdout))) { - zig_panic("unable to determine libc lib path: executing C compiler: %s", err_str(err)); - } - if (term.how != TerminationIdClean || term.code != 0) { - zig_panic("unable to determine libc lib path: executing C compiler command failed"); - } - if (buf_ends_with_str(out_stdout, "\n")) { - buf_resize(out_stdout, buf_len(out_stdout) - 1); - } - if (buf_len(out_stdout) == 0 || buf_eql_str(out_stdout, o_file)) { - zig_panic("unable to determine libc lib path: C compiler could not find %s", o_file); - } - Buf *result = buf_alloc(); - os_path_dirname(out_stdout, result); - return result; -} - -static Buf *get_posix_libc_include_path(void) { - const char *cc_exe = getenv("CC"); - cc_exe = (cc_exe == nullptr) ? "cc" : cc_exe; - ZigList args = {}; - args.append("-E"); - args.append("-Wp,-v"); - args.append("-xc"); - args.append("/dev/null"); - Termination term; - Buf *out_stderr = buf_alloc(); - Buf *out_stdout = buf_alloc(); - Error err; - if ((err = os_exec_process(cc_exe, args, &term, out_stderr, out_stdout))) { - zig_panic("unable to determine libc include path: executing C compiler: %s", err_str(err)); - } - if (term.how != TerminationIdClean || term.code != 0) { - zig_panic("unable to determine libc include path: executing C compiler command failed"); - } - char *prev_newline = buf_ptr(out_stderr); - ZigList search_paths = {}; - for (;;) { - char *newline = strchr(prev_newline, '\n'); - if (newline == nullptr) { - break; - } - *newline = 0; - if (prev_newline[0] == ' ') { - search_paths.append(prev_newline); - } - prev_newline = newline + 1; - } - if (search_paths.length == 0) { - zig_panic("unable to determine libc include path: even C compiler does not know where libc headers are"); - } - for (size_t i = 0; i < search_paths.length; i += 1) { - // search in reverse order - const char *search_path = search_paths.items[search_paths.length - i - 1]; - // cut off spaces - while (*search_path == ' ') { - search_path += 1; - } - Buf *stdlib_path = buf_sprintf("%s/stdlib.h", search_path); - bool exists; - if ((err = os_file_exists(stdlib_path, &exists))) { - exists = false; - } - if (exists) { - return buf_create_from_str(search_path); - } - } - zig_panic("unable to determine libc include path: stdlib.h not found in C compiler search paths"); -} - -void find_libc_include_path(CodeGen *g) { - if (g->libc_include_dir == nullptr) { - if (!g->is_native_target) { - return; - } - - if (g->zig_target.os == OsWindows) { - ZigWindowsSDK *sdk = get_windows_sdk(g); - g->libc_include_dir = buf_alloc(); - if (os_get_win32_ucrt_include_path(sdk, g->libc_include_dir)) { - fprintf(stderr, "Unable to determine libc include path. --libc-include-dir"); - exit(1); - } - } else if (g->zig_target.os == OsLinux || - g->zig_target.os == OsMacOSX || - g->zig_target.os == OsFreeBSD || - g->zig_target.os == OsNetBSD) - { - g->libc_include_dir = get_posix_libc_include_path(); - } else { - fprintf(stderr, "Unable to determine libc include path.\n" - "TODO: implement finding libc at runtime for other operating systems.\n" - "in the meantime, you can use as a workaround: --libc-include-dir\n"); - exit(1); - } - } - assert(buf_len(g->libc_include_dir) != 0); -} - -void find_libc_lib_path(CodeGen *g) { - // later we can handle this better by reporting an error via the normal mechanism - if (g->libc_lib_dir == nullptr || - (g->zig_target.os == OsWindows && (g->msvc_lib_dir == nullptr || g->kernel32_lib_dir == nullptr))) - { - if (g->zig_target.os == OsWindows) { - ZigWindowsSDK *sdk = get_windows_sdk(g); - - if (g->msvc_lib_dir == nullptr) { - if (sdk->msvc_lib_dir_ptr == nullptr) { - fprintf(stderr, "Unable to determine vcruntime path. --msvc-lib-dir"); - exit(1); - } - g->msvc_lib_dir = buf_create_from_mem(sdk->msvc_lib_dir_ptr, sdk->msvc_lib_dir_len); - } - - if (g->libc_lib_dir == nullptr) { - Buf* ucrt_lib_path = buf_alloc(); - if (os_get_win32_ucrt_lib_path(sdk, ucrt_lib_path, g->zig_target.arch.arch)) { - fprintf(stderr, "Unable to determine ucrt path. --libc-lib-dir"); - exit(1); - } - g->libc_lib_dir = ucrt_lib_path; - } - - if (g->kernel32_lib_dir == nullptr) { - Buf* kern_lib_path = buf_alloc(); - if (os_get_win32_kern32_path(sdk, kern_lib_path, g->zig_target.arch.arch)) { - fprintf(stderr, "Unable to determine kernel32 path. --kernel32-lib-dir"); - exit(1); - } - g->kernel32_lib_dir = kern_lib_path; - } - - } else if (g->zig_target.os == OsLinux) { - g->libc_lib_dir = get_linux_libc_lib_path("crt1.o"); - } else if ((g->zig_target.os == OsFreeBSD) || (g->zig_target.os == OsNetBSD)) { - g->libc_lib_dir = buf_create_from_str("/usr/lib"); - } else { - zig_panic("Unable to determine libc lib path."); - } - } else { - assert(buf_len(g->libc_lib_dir) != 0); - } - - if (g->libc_static_lib_dir == nullptr) { - if ((g->zig_target.os == OsWindows) && (g->msvc_lib_dir != NULL)) { - return; - } else if (g->zig_target.os == OsLinux) { - g->libc_static_lib_dir = get_linux_libc_lib_path("crtbegin.o"); - } else if ((g->zig_target.os == OsFreeBSD) || (g->zig_target.os == OsNetBSD)) { - g->libc_static_lib_dir = buf_create_from_str("/usr/lib"); - } else { - zig_panic("Unable to determine libc static lib path."); - } - } else { - assert(buf_len(g->libc_static_lib_dir) != 0); - } -} - static uint32_t hash_ptr(void *ptr) { return (uint32_t)(((uintptr_t)ptr) % UINT32_MAX); } @@ -6736,14 +6556,6 @@ LinkLib *add_link_lib(CodeGen *g, Buf *name) { if (is_libc && g->libc_link_lib != nullptr) return g->libc_link_lib; - if (g->enable_cache && is_libc && g->zig_target.os != OsMacOSX && - g->zig_target.os != OsIOS && g->zig_target.os != OsFreeBSD && - g->zig_target.os != OsNetBSD) { - fprintf(stderr, "TODO linking against libc is currently incompatible with `--cache on`.\n" - "Zig is not yet capable of determining whether the libc installation has changed on subsequent builds.\n"); - exit(1); - } - for (size_t i = 0; i < g->link_libs_list.length; i += 1) { LinkLib *existing_lib = g->link_libs_list.at(i); if (buf_eql_buf(existing_lib->name, name)) { diff --git a/src/analyze.hpp b/src/analyze.hpp index 39c1450678..de4785fb27 100644 --- a/src/analyze.hpp +++ b/src/analyze.hpp @@ -40,8 +40,6 @@ ZigType *get_promise_type(CodeGen *g, ZigType *result_type); ZigType *get_promise_frame_type(CodeGen *g, ZigType *return_type); ZigType *get_test_fn_type(CodeGen *g); bool handle_is_ptr(ZigType *type_entry); -void find_libc_include_path(CodeGen *g); -void find_libc_lib_path(CodeGen *g); bool type_has_bits(ZigType *type_entry); bool type_allowed_in_extern(CodeGen *g, ZigType *type_entry); diff --git a/src/codegen.cpp b/src/codegen.cpp index 0cb1e93211..54da63e9f9 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -29,9 +29,9 @@ static void init_darwin_native(CodeGen *g) { // Allow conflicts among OSX and iOS, but choose the default platform. if (osx_target && ios_target) { - if (g->zig_target.arch.arch == ZigLLVM_arm || - g->zig_target.arch.arch == ZigLLVM_aarch64 || - g->zig_target.arch.arch == ZigLLVM_thumb) + if (g->zig_target->arch.arch == ZigLLVM_arm || + g->zig_target->arch.arch == ZigLLVM_aarch64 || + g->zig_target->arch.arch == ZigLLVM_thumb) { osx_target = nullptr; } else { @@ -43,7 +43,7 @@ static void init_darwin_native(CodeGen *g) { g->mmacosx_version_min = buf_create_from_str(osx_target); } else if (ios_target) { g->mios_version_min = buf_create_from_str(ios_target); - } else if (g->zig_target.os != OsIOS) { + } else if (g->zig_target->os != OsIOS) { g->mmacosx_version_min = buf_create_from_str("10.10"); } } @@ -88,13 +88,15 @@ static const char *symbols_that_llvm_depends_on[] = { }; CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out_type, BuildMode build_mode, - Buf *zig_lib_dir, Buf *override_std_dir) + Buf *zig_lib_dir, Buf *override_std_dir, ZigLibCInstallation *libc) { CodeGen *g = allocate(1); codegen_add_time_event(g, "Initialize"); + g->libc = libc; g->zig_lib_dir = zig_lib_dir; + g->zig_target = target; if (override_std_dir == nullptr) { g->zig_std_dir = buf_alloc(); @@ -149,44 +151,19 @@ CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out g->zig_std_special_dir = buf_alloc(); os_path_join(g->zig_std_dir, buf_sprintf("special"), g->zig_std_special_dir); - if (target) { - // cross compiling, so we can't rely on all the configured stuff since - // that's for native compilation - g->zig_target = *target; - resolve_target_object_format(&g->zig_target); - g->dynamic_linker = nullptr; - g->libc_lib_dir = nullptr; - g->libc_static_lib_dir = nullptr; - g->libc_include_dir = nullptr; - g->msvc_lib_dir = nullptr; - g->kernel32_lib_dir = nullptr; + assert(target != nullptr); + if (!target->is_native) { g->each_lib_rpath = false; } else { - // native compilation, we can rely on the configuration stuff - g->is_native_target = true; - get_native_target(&g->zig_target); - g->dynamic_linker = nullptr; // find it at runtime - g->libc_lib_dir = nullptr; // find it at runtime - g->libc_static_lib_dir = nullptr; // find it at runtime - g->libc_include_dir = nullptr; // find it at runtime - g->msvc_lib_dir = nullptr; // find it at runtime - g->kernel32_lib_dir = nullptr; // find it at runtime g->each_lib_rpath = true; - if (g->zig_target.os == OsMacOSX || - g->zig_target.os == OsIOS) - { + if (target_is_darwin(g->zig_target)) { init_darwin_native(g); } } - // On Darwin/MacOS/iOS, we always link libSystem which contains libc. - if (g->zig_target.os == OsMacOSX || - g->zig_target.os == OsIOS || - g->zig_target.os == OsFreeBSD || - g->zig_target.os == OsNetBSD) - { + if (target_requires_libc(g->zig_target)) { g->libc_link_lib = create_link_lib(buf_create_from_str("c")); g->link_libs_list.append(g->libc_link_lib); } @@ -254,30 +231,6 @@ void codegen_set_out_name(CodeGen *g, Buf *out_name) { g->root_out_name = out_name; } -void codegen_set_libc_lib_dir(CodeGen *g, Buf *libc_lib_dir) { - g->libc_lib_dir = libc_lib_dir; -} - -void codegen_set_libc_static_lib_dir(CodeGen *g, Buf *libc_static_lib_dir) { - g->libc_static_lib_dir = libc_static_lib_dir; -} - -void codegen_set_libc_include_dir(CodeGen *g, Buf *libc_include_dir) { - g->libc_include_dir = libc_include_dir; -} - -void codegen_set_msvc_lib_dir(CodeGen *g, Buf *msvc_lib_dir) { - g->msvc_lib_dir = msvc_lib_dir; -} - -void codegen_set_kernel32_lib_dir(CodeGen *g, Buf *kernel32_lib_dir) { - g->kernel32_lib_dir = kernel32_lib_dir; -} - -void codegen_set_dynamic_linker(CodeGen *g, Buf *dynamic_linker) { - g->dynamic_linker = dynamic_linker; -} - void codegen_add_lib_dir(CodeGen *g, const char *dir) { g->lib_dirs.append(dir); } @@ -390,11 +343,11 @@ static LLVMCallConv get_llvm_cc(CodeGen *g, CallingConvention cc) { case CallingConventionC: return LLVMCCallConv; case CallingConventionCold: // cold calling convention only works on x86. - if (g->zig_target.arch.arch == ZigLLVM_x86 || - g->zig_target.arch.arch == ZigLLVM_x86_64) + if (g->zig_target->arch.arch == ZigLLVM_x86 || + g->zig_target->arch.arch == ZigLLVM_x86_64) { // cold calling convention is not supported on windows - if (g->zig_target.os == OsWindows) { + if (g->zig_target->os == OsWindows) { return LLVMCCallConv; } else { return LLVMColdCallConv; @@ -407,7 +360,7 @@ static LLVMCallConv get_llvm_cc(CodeGen *g, CallingConvention cc) { zig_unreachable(); case CallingConventionStdcall: // stdcall calling convention only works on x86. - if (g->zig_target.arch.arch == ZigLLVM_x86) { + if (g->zig_target->arch.arch == ZigLLVM_x86) { return LLVMX86StdcallCallConv; } else { return LLVMCCallConv; @@ -419,7 +372,7 @@ static LLVMCallConv get_llvm_cc(CodeGen *g, CallingConvention cc) { } static void add_uwtable_attr(CodeGen *g, LLVMValueRef fn_val) { - if (g->zig_target.os == OsWindows) { + if (g->zig_target->os == OsWindows) { addLLVMFnAttr(fn_val, "uwtable"); } } @@ -455,13 +408,13 @@ static uint32_t get_err_ret_trace_arg_index(CodeGen *g, ZigFn *fn_table_entry) { } static void maybe_export_dll(CodeGen *g, LLVMValueRef global_value, GlobalLinkageId linkage) { - if (linkage != GlobalLinkageIdInternal && g->zig_target.os == OsWindows) { + if (linkage != GlobalLinkageIdInternal && g->zig_target->os == OsWindows) { LLVMSetDLLStorageClass(global_value, LLVMDLLExportStorageClass); } } static void maybe_import_dll(CodeGen *g, LLVMValueRef global_value, GlobalLinkageId linkage) { - if (linkage != GlobalLinkageIdInternal && g->zig_target.os == OsWindows) { + if (linkage != GlobalLinkageIdInternal && g->zig_target->os == OsWindows) { // TODO come up with a good explanation/understanding for why we never do // DLLImportStorageClass. Empirically it only causes problems. But let's have // this documented and then clean up the code accordingly. @@ -506,7 +459,7 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) { bool external_linkage = linkage != GlobalLinkageIdInternal; CallingConvention cc = fn_table_entry->type_entry->data.fn.fn_type_id.cc; if (cc == CallingConventionStdcall && external_linkage && - g->zig_target.arch.arch == ZigLLVM_x86) + g->zig_target->arch.arch == ZigLLVM_x86) { // prevent llvm name mangling 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_ return true; } - if (g->zig_target.arch.arch == ZigLLVM_x86_64) { + if (g->zig_target->arch.arch == ZigLLVM_x86_64) { X64CABIClass abi_class = type_c_abi_x86_64_class(g, ty); size_t ty_size = type_size(g, ty); if (abi_class == X64CABIClass_MEMORY) { @@ -3381,15 +3334,15 @@ static bool value_is_all_undef(ConstExprValue *const_val) { static LLVMValueRef gen_valgrind_client_request(CodeGen *g, LLVMValueRef default_value, LLVMValueRef request, LLVMValueRef a1, LLVMValueRef a2, LLVMValueRef a3, LLVMValueRef a4, LLVMValueRef a5) { - if (!target_has_valgrind_support(&g->zig_target)) { + if (!target_has_valgrind_support(g->zig_target)) { return default_value; } LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->type_ref; bool asm_has_side_effects = true; bool asm_is_alignstack = false; - if (g->zig_target.arch.arch == ZigLLVM_x86_64) { - if (g->zig_target.os == OsLinux || target_is_darwin(&g->zig_target) || g->zig_target.os == OsSolaris || - (g->zig_target.os == OsWindows && g->zig_target.env_type != ZigLLVM_MSVC)) + if (g->zig_target->arch.arch == ZigLLVM_x86_64) { + if (g->zig_target->os == OsLinux || target_is_darwin(g->zig_target) || g->zig_target->os == OsSolaris || + (g->zig_target->os == OsWindows && g->zig_target->env_type != ZigLLVM_MSVC)) { if (g->cur_fn->valgrind_client_request_array == nullptr) { LLVMBasicBlockRef prev_block = LLVMGetInsertBlock(g->builder); @@ -3436,7 +3389,7 @@ static LLVMValueRef gen_valgrind_client_request(CodeGen *g, LLVMValueRef default } static bool want_valgrind_support(CodeGen *g) { - if (!target_has_valgrind_support(&g->zig_target)) + if (!target_has_valgrind_support(g->zig_target)) return false; switch (g->valgrind_support) { case ValgrindSupportDisabled: @@ -3629,7 +3582,7 @@ static void gen_set_stack_pointer(CodeGen *g, LLVMValueRef aligned_end_addr) { LLVMValueRef write_register_fn_val = get_write_register_fn_val(g); if (g->sp_md_node == nullptr) { - Buf *sp_reg_name = buf_create_from_str(arch_stack_pointer_register_name(&g->zig_target.arch)); + Buf *sp_reg_name = buf_create_from_str(arch_stack_pointer_register_name(&g->zig_target->arch)); LLVMValueRef str_node = LLVMMDString(buf_ptr(sp_reg_name), buf_len(sp_reg_name) + 1); g->sp_md_node = LLVMMDNode(&str_node, 1); } @@ -7042,7 +6995,7 @@ static void define_builtin_types(CodeGen *g) { for (size_t i = 0; i < array_length(c_int_type_infos); i += 1) { const CIntTypeInfo *info = &c_int_type_infos[i]; - uint32_t size_in_bits = target_c_type_size_in_bits(&g->zig_target, info->id); + uint32_t size_in_bits = target_c_type_size_in_bits(g->zig_target, info->id); bool is_signed = info->is_signed; ZigType *entry = new_type_table_entry(ZigTypeIdInt); @@ -7309,6 +7262,9 @@ static const char *build_mode_to_str(BuildMode build_mode) { Buf *codegen_generate_builtin_source(CodeGen *g) { Buf *contents = buf_alloc(); + // NOTE: when editing this file, you may need to make modifications to the + // cache input parameters in define_builtin_compile_vars + // Modifications to this struct must be coordinated with code that does anything with // g->stack_trace_type. There are hard-coded references to the field indexes. buf_append_str(contents, @@ -7328,7 +7284,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) { const char *name = get_target_os_name(os_type); buf_appendf(contents, " %s,\n", name); - if (os_type == g->zig_target.os) { + if (os_type == g->zig_target->os) { g->target_os_index = i; cur_os = name; } @@ -7350,8 +7306,8 @@ Buf *codegen_generate_builtin_source(CodeGen *g) { buf_appendf(contents, " %s,\n", buf_ptr(arch_name)); - if (arch_type->arch == g->zig_target.arch.arch && - arch_type->sub_arch == g->zig_target.arch.sub_arch) + if (arch_type->arch == g->zig_target->arch.arch && + arch_type->sub_arch == g->zig_target->arch.sub_arch) { g->target_arch_index = i; cur_arch = buf_ptr(arch_name); @@ -7370,7 +7326,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) { const char *name = ZigLLVMGetEnvironmentTypeName(environ_type); buf_appendf(contents, " %s,\n", name); - if (environ_type == g->zig_target.env_type) { + if (environ_type == g->zig_target->env_type) { g->target_environ_index = i; cur_environ = name; } @@ -7388,7 +7344,8 @@ Buf *codegen_generate_builtin_source(CodeGen *g) { const char *name = get_target_oformat_name(oformat); buf_appendf(contents, " %s,\n", name); - if (oformat == g->zig_target.oformat) { + ZigLLVM_ObjectFormatType target_oformat = target_object_format(g->zig_target); + if (oformat == target_oformat) { g->target_oformat_index = i; cur_obj_fmt = name; } @@ -7707,14 +7664,15 @@ static Error define_builtin_compile_vars(CodeGen *g) { cache_int(&cache_hash, g->build_mode); cache_bool(&cache_hash, g->is_test_build); cache_bool(&cache_hash, g->is_single_threaded); - cache_int(&cache_hash, g->zig_target.arch.arch); - cache_int(&cache_hash, g->zig_target.arch.sub_arch); - cache_int(&cache_hash, g->zig_target.vendor); - cache_int(&cache_hash, g->zig_target.os); - cache_int(&cache_hash, g->zig_target.env_type); - cache_int(&cache_hash, g->zig_target.oformat); + cache_int(&cache_hash, g->zig_target->is_native); + cache_int(&cache_hash, g->zig_target->arch.arch); + cache_int(&cache_hash, g->zig_target->arch.sub_arch); + cache_int(&cache_hash, g->zig_target->vendor); + cache_int(&cache_hash, g->zig_target->os); + cache_int(&cache_hash, g->zig_target->env_type); cache_bool(&cache_hash, g->have_err_ret_tracing); cache_bool(&cache_hash, g->libc_link_lib != nullptr); + cache_bool(&cache_hash, g->valgrind_support); Buf digest = BUF_INIT; buf_resize(&digest, 0); @@ -7783,11 +7741,11 @@ static void init(CodeGen *g) { assert(g->root_out_name); g->module = LLVMModuleCreateWithName(buf_ptr(g->root_out_name)); - get_target_triple(&g->triple_str, &g->zig_target); + get_target_triple(&g->triple_str, g->zig_target); LLVMSetTarget(g->module, buf_ptr(&g->triple_str)); - if (g->zig_target.oformat == ZigLLVM_COFF) { + if (target_object_format(g->zig_target) == ZigLLVM_COFF) { ZigLLVMAddModuleCodeViewFlag(g->module); } else { ZigLLVMAddModuleDebugInfoFlag(g->module); @@ -7815,11 +7773,11 @@ static void init(CodeGen *g) { const char *target_specific_cpu_args; const char *target_specific_features; - if (g->is_native_target) { + if (g->zig_target->is_native) { // LLVM creates invalid binaries on Windows sometimes. // See https://github.com/ziglang/zig/issues/508 // As a workaround we do not use target native features on Windows. - if (g->zig_target.os == OsWindows || g->zig_target.os == OsUefi) { + if (g->zig_target->os == OsWindows || g->zig_target->os == OsUefi) { target_specific_cpu_args = ""; target_specific_features = ""; } else { @@ -7892,9 +7850,59 @@ static void init(CodeGen *g) { } } -void codegen_translate_c(CodeGen *g, Buf *full_path) { - find_libc_include_path(g); +static void detect_libc(CodeGen *g) { + Error err; + if (g->libc != nullptr || g->libc_link_lib == nullptr) + return; + + if (g->zig_target->is_native) { + g->libc = allocate(1); + + // Look for zig-cache/native_libc.txt + Buf *native_libc_txt = buf_alloc(); + os_path_join(&g->cache_dir, buf_create_from_str("native_libc.txt"), native_libc_txt); + if ((err = zig_libc_parse(g->libc, native_libc_txt, g->zig_target, false))) { + if ((err = zig_libc_find_native(g->libc, true))) { + fprintf(stderr, + "Unable to link against libc: Unable to find libc installation: %s\n" + "See `zig libc --help` for more details.\n", err_str(err)); + exit(1); + } + if ((err = os_make_path(&g->cache_dir))) { + fprintf(stderr, "Unable to create %s directory: %s\n", + buf_ptr(&g->cache_dir), err_str(err)); + exit(1); + } + Buf *native_libc_tmp = buf_sprintf("%s.tmp", buf_ptr(native_libc_txt)); + FILE *file = fopen(buf_ptr(native_libc_tmp), "wb"); + if (file == nullptr) { + fprintf(stderr, "Unable to open %s: %s\n", buf_ptr(native_libc_tmp), strerror(errno)); + exit(1); + } + zig_libc_render(g->libc, file); + if (fclose(file) != 0) { + fprintf(stderr, "Unable to save %s: %s\n", buf_ptr(native_libc_tmp), strerror(errno)); + exit(1); + } + if (rename(buf_ptr(native_libc_tmp), buf_ptr(native_libc_txt)) == -1) { + fprintf(stderr, "Unable to create %s: %s\n", buf_ptr(native_libc_txt), strerror(errno)); + exit(1); + } + } + } else if ((g->out_type == OutTypeExe || (g->out_type == OutTypeLib && !g->is_static)) && + !target_is_darwin(g->zig_target)) + { + // Currently darwin is the only platform that we can link libc on when not compiling natively, + // without a cross compiling libc kit. + fprintf(stderr, + "Cannot link against libc for non-native OS '%s' without providing a libc installation file.\n" + "See `zig libc --help` for more details.\n", get_target_os_name(g->zig_target->os)); + exit(1); + } +} + +void codegen_translate_c(CodeGen *g, Buf *full_path) { Buf *src_basename = buf_alloc(); Buf *src_dirname = buf_alloc(); os_path_split(full_path, src_dirname, src_basename); @@ -7905,6 +7913,8 @@ void codegen_translate_c(CodeGen *g, Buf *full_path) { g->root_import = import; import->decls_scope = create_decls_scope(g, nullptr, nullptr, nullptr, import); + detect_libc(g); + init(g); 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) { } report_errors_and_maybe_exit(g); - if (!g->is_test_build && g->zig_target.os != OsFreestanding && - g->zig_target.os != OsUefi && + if (!g->is_test_build && g->zig_target->os != OsFreestanding && + g->zig_target->os != OsUefi && !g->have_c_main && !g->have_winmain && !g->have_winmain_crt_startup && ((g->have_pub_main && g->out_type == OutTypeObj) || g->out_type == OutTypeExe)) { g->bootstrap_import = add_special_code(g, create_bootstrap_pkg(g, g->root_package), "bootstrap.zig"); } - if (g->zig_target.os == OsWindows && !g->have_dllmain_crt_startup && + if (g->zig_target->os == OsWindows && !g->have_dllmain_crt_startup && g->out_type == OutTypeLib && !g->is_static) { g->bootstrap_import = add_special_code(g, create_bootstrap_pkg(g, g->root_package), "bootstrap_lib.zig"); @@ -8619,6 +8629,8 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) { } cache_buf(ch, compiler_id); cache_buf(ch, g->root_out_name); + cache_buf(ch, g->zig_lib_dir); + cache_buf(ch, g->zig_std_dir); cache_list_of_link_lib(ch, g->link_libs_list.items, g->link_libs_list.length); cache_list_of_buf(ch, g->darwin_frameworks.items, g->darwin_frameworks.length); 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) { cache_int(ch, g->emit_file_type); cache_int(ch, g->build_mode); cache_int(ch, g->out_type); - cache_int(ch, g->zig_target.arch.arch); - cache_int(ch, g->zig_target.arch.sub_arch); - cache_int(ch, g->zig_target.vendor); - cache_int(ch, g->zig_target.os); - cache_int(ch, g->zig_target.env_type); - cache_int(ch, g->zig_target.oformat); + cache_bool(ch, g->zig_target->is_native); + cache_int(ch, g->zig_target->arch.arch); + cache_int(ch, g->zig_target->arch.sub_arch); + cache_int(ch, g->zig_target->vendor); + cache_int(ch, g->zig_target->os); + cache_int(ch, g->zig_target->env_type); cache_int(ch, g->subsystem); cache_bool(ch, g->is_static); cache_bool(ch, g->strip_debug_symbols); cache_bool(ch, g->is_test_build); cache_bool(ch, g->is_single_threaded); - cache_bool(ch, g->is_native_target); cache_bool(ch, g->linker_rdynamic); cache_bool(ch, g->each_lib_rpath); cache_bool(ch, g->disable_pic); @@ -8654,6 +8665,14 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) { cache_list_of_str(ch, g->llvm_argv, g->llvm_argv_len); cache_list_of_str(ch, g->clang_argv, g->clang_argv_len); cache_list_of_str(ch, g->lib_dirs.items, g->lib_dirs.length); + if (g->libc) { + cache_buf(ch, &g->libc->include_dir); + cache_buf(ch, &g->libc->lib_dir); + cache_buf(ch, &g->libc->static_lib_dir); + cache_buf(ch, &g->libc->msvc_lib_dir); + cache_buf(ch, &g->libc->kernel32_lib_dir); + cache_buf(ch, &g->libc->dynamic_linker_path); + } buf_resize(digest, 0); if ((err = cache_hit(ch, digest))) @@ -8668,19 +8687,19 @@ static void resolve_out_paths(CodeGen *g) { switch (g->emit_file_type) { case EmitFileTypeBinary: { - const char *o_ext = target_o_file_ext(&g->zig_target); + const char *o_ext = target_o_file_ext(g->zig_target); buf_append_str(o_basename, o_ext); break; } case EmitFileTypeAssembly: { - const char *asm_ext = target_asm_file_ext(&g->zig_target); + const char *asm_ext = target_asm_file_ext(g->zig_target); buf_append_str(o_basename, asm_ext); break; } case EmitFileTypeLLVMIr: { - const char *llvm_ir_ext = target_llvm_ir_file_ext(&g->zig_target); + const char *llvm_ir_ext = target_llvm_ir_file_ext(g->zig_target); buf_append_str(o_basename, llvm_ir_ext); break; } @@ -8706,7 +8725,7 @@ static void resolve_out_paths(CodeGen *g) { Buf basename = BUF_INIT; buf_init_from_buf(&basename, g->root_out_name); - buf_append_str(&basename, target_exe_file_ext(&g->zig_target)); + buf_append_str(&basename, target_exe_file_ext(g->zig_target)); if (g->enable_cache || g->is_test_build) { os_path_join(&g->artifact_dir, &basename, &g->output_file_path); } else { @@ -8719,7 +8738,7 @@ static void resolve_out_paths(CodeGen *g) { } else { Buf basename = BUF_INIT; buf_init_from_buf(&basename, g->root_out_name); - buf_append_str(&basename, target_lib_file_ext(&g->zig_target, g->is_static, + buf_append_str(&basename, target_lib_file_ext(g->zig_target, g->is_static, g->version_major, g->version_minor, g->version_patch)); if (g->enable_cache) { os_path_join(&g->artifact_dir, &basename, &g->output_file_path); @@ -8732,11 +8751,12 @@ static void resolve_out_paths(CodeGen *g) { } } - void codegen_build_and_link(CodeGen *g) { Error err; assert(g->out_type != OutTypeUnknown); + detect_libc(g); + Buf *stage1_dir = get_stage1_cache_path(); Buf *artifact_dir = buf_alloc(); Buf digest = BUF_INIT; diff --git a/src/codegen.hpp b/src/codegen.hpp index 4bd8f2dcca..035b759ec5 100644 --- a/src/codegen.hpp +++ b/src/codegen.hpp @@ -11,11 +11,12 @@ #include "parser.hpp" #include "errmsg.hpp" #include "target.hpp" +#include "libc_installation.hpp" #include CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out_type, BuildMode build_mode, - Buf *zig_lib_dir, Buf *override_std_dir); + Buf *zig_lib_dir, Buf *override_std_dir, ZigLibCInstallation *libc); void codegen_set_clang_argv(CodeGen *codegen, const char **args, size_t len); void 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); void codegen_set_strip(CodeGen *codegen, bool strip); void codegen_set_errmsg_color(CodeGen *codegen, ErrColor err_color); void codegen_set_out_name(CodeGen *codegen, Buf *out_name); -void codegen_set_libc_lib_dir(CodeGen *codegen, Buf *libc_lib_dir); -void codegen_set_libc_static_lib_dir(CodeGen *g, Buf *libc_static_lib_dir); -void codegen_set_libc_include_dir(CodeGen *codegen, Buf *libc_include_dir); -void codegen_set_msvc_lib_dir(CodeGen *g, Buf *msvc_lib_dir); -void codegen_set_kernel32_lib_dir(CodeGen *codegen, Buf *kernel32_lib_dir); -void codegen_set_dynamic_linker(CodeGen *g, Buf *dynamic_linker); void codegen_add_lib_dir(CodeGen *codegen, const char *dir); void codegen_add_forbidden_lib(CodeGen *codegen, Buf *lib); LinkLib *codegen_add_link_lib(CodeGen *codegen, Buf *lib); diff --git a/src/error.cpp b/src/error.cpp index 10186fbde5..9e01a86d8c 100644 --- a/src/error.cpp +++ b/src/error.cpp @@ -34,6 +34,8 @@ const char *err_str(Error err) { case ErrorPipeBusy: return "pipe busy"; case ErrorPrimitiveTypeNotFound: return "primitive type not found"; case ErrorCacheUnavailable: return "cache unavailable"; + case ErrorPathTooLong: return "path too long"; + case ErrorCCompilerCannotFindFile: return "C compiler cannot find file"; } return "(invalid error)"; } diff --git a/src/error.hpp b/src/error.hpp index b60cb8517e..0e14f37a69 100644 --- a/src/error.hpp +++ b/src/error.hpp @@ -36,6 +36,8 @@ enum Error { ErrorPipeBusy, ErrorPrimitiveTypeNotFound, ErrorCacheUnavailable, + ErrorPathTooLong, + ErrorCCompilerCannotFindFile, }; const char *err_str(Error err); diff --git a/src/ir.cpp b/src/ir.cpp index a3c15dbd0f..ea2fcb289f 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -18690,8 +18690,6 @@ static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruct if (type_is_invalid(cimport_result->type)) return ira->codegen->invalid_instruction; - find_libc_include_path(ira->codegen); - ImportTableEntry *child_import = allocate(1); child_import->decls_scope = create_decls_scope(ira->codegen, node, nullptr, nullptr, child_import); child_import->c_import_node = node; diff --git a/src/libc_installation.cpp b/src/libc_installation.cpp new file mode 100644 index 0000000000..9228ea95b6 --- /dev/null +++ b/src/libc_installation.cpp @@ -0,0 +1,408 @@ +/* + * Copyright (c) 2019 Andrew Kelley + * + * This file is part of zig, which is MIT licensed. + * See http://opensource.org/licenses/MIT + */ + +#include "libc_installation.hpp" +#include "os.hpp" +#include "windows_sdk.h" +#include "target.hpp" + +static const size_t zig_libc_keys_len = 6; + +static const char *zig_libc_keys[] = { + "include_dir", + "lib_dir", + "static_lib_dir", + "msvc_lib_dir", + "kernel32_lib_dir", + "dynamic_linker_path", +}; + +static bool zig_libc_match_key(Slice name, Slice value, bool *found_keys, + size_t index, Buf *field_ptr) +{ + if (!memEql(name, str(zig_libc_keys[index]))) return false; + buf_init_from_mem(field_ptr, (const char*)value.ptr, value.len); + found_keys[index] = true; + return true; +} + +static void zig_libc_init_empty(ZigLibCInstallation *libc) { + *libc = {}; + buf_init_from_str(&libc->include_dir, ""); + buf_init_from_str(&libc->lib_dir, ""); + buf_init_from_str(&libc->static_lib_dir, ""); + buf_init_from_str(&libc->msvc_lib_dir, ""); + buf_init_from_str(&libc->kernel32_lib_dir, ""); + buf_init_from_str(&libc->dynamic_linker_path, ""); +} + +Error zig_libc_parse(ZigLibCInstallation *libc, Buf *libc_file, const ZigTarget *target, bool verbose) { + Error err; + zig_libc_init_empty(libc); + + bool found_keys[6] = {}; // zig_libc_keys_len + + Buf *contents = buf_alloc(); + if ((err = os_fetch_file_path(libc_file, contents, false))) { + if (err != ErrorFileNotFound && verbose) { + fprintf(stderr, "Unable to read '%s': %s\n", buf_ptr(libc_file), err_str(err)); + } + return err; + } + + SplitIterator it = memSplit(buf_to_slice(contents), str("\n")); + for (;;) { + Optional> opt_line = SplitIterator_next(&it); + if (!opt_line.is_some) + break; + + if (opt_line.value.len == 0 || opt_line.value.ptr[0] == '#') + continue; + + SplitIterator line_it = memSplit(opt_line.value, str("=")); + Slice name; + if (!SplitIterator_next(&line_it).unwrap(&name)) { + if (verbose) { + fprintf(stderr, "missing equal sign after field name\n"); + } + return ErrorSemanticAnalyzeFail; + } + Slice value = SplitIterator_rest(&line_it); + bool match = false; + match = match || zig_libc_match_key(name, value, found_keys, 0, &libc->include_dir); + match = match || zig_libc_match_key(name, value, found_keys, 1, &libc->lib_dir); + match = match || zig_libc_match_key(name, value, found_keys, 2, &libc->static_lib_dir); + match = match || zig_libc_match_key(name, value, found_keys, 3, &libc->msvc_lib_dir); + match = match || zig_libc_match_key(name, value, found_keys, 4, &libc->kernel32_lib_dir); + match = match || zig_libc_match_key(name, value, found_keys, 5, &libc->dynamic_linker_path); + } + + for (size_t i = 0; i < zig_libc_keys_len; i += 1) { + if (!found_keys[i]) { + if (verbose) { + fprintf(stderr, "missing field: %s\n", zig_libc_keys[i]); + } + return ErrorSemanticAnalyzeFail; + } + } + + if (buf_len(&libc->include_dir) == 0) { + if (verbose) { + fprintf(stderr, "include_dir may not be empty\n"); + } + return ErrorSemanticAnalyzeFail; + } + + if (buf_len(&libc->lib_dir) == 0) { + if (!target_is_darwin(target)) { + if (verbose) { + fprintf(stderr, "lib_dir may not be empty for %s\n", get_target_os_name(target->os)); + } + return ErrorSemanticAnalyzeFail; + } + } + + if (buf_len(&libc->static_lib_dir) == 0) { + if (!target_is_darwin(target) && target->os != OsWindows) { + if (verbose) { + fprintf(stderr, "static_lib_dir may not be empty for %s\n", get_target_os_name(target->os)); + } + return ErrorSemanticAnalyzeFail; + } + } + + if (buf_len(&libc->msvc_lib_dir) == 0) { + if (target->os == OsWindows) { + if (verbose) { + fprintf(stderr, "msvc_lib_dir may not be empty for %s\n", get_target_os_name(target->os)); + } + return ErrorSemanticAnalyzeFail; + } + } + + if (buf_len(&libc->kernel32_lib_dir) == 0) { + if (target->os == OsWindows) { + if (verbose) { + fprintf(stderr, "kernel32_lib_dir may not be empty for %s\n", get_target_os_name(target->os)); + } + return ErrorSemanticAnalyzeFail; + } + } + + if (buf_len(&libc->dynamic_linker_path) == 0) { + if (target->os == OsLinux) { + if (verbose) { + fprintf(stderr, "dynamic_linker_path may not be empty for %s\n", get_target_os_name(target->os)); + } + return ErrorSemanticAnalyzeFail; + } + } + + return ErrorNone; +} + +#if defined(ZIG_OS_WINDOWS) +static Error zig_libc_find_native_include_dir_windows(ZigLibCInstallation *self, ZigWindowsSDK *sdk, bool verbose) { + Error err; + if ((err = os_get_win32_ucrt_include_path(sdk, &self->include_dir))) { + if (verbose) { + fprintf(stderr, "Unable to determine libc include path: %s\n", err_str(err)); + } + return err; + } + return ErrorNone; +} +static Error zig_libc_find_lib_dir_windows(ZigLibCInstallation *self, ZigWindowsSDK *sdk, ZigTarget *target, + bool verbose) +{ + Error err; + if ((err = os_get_win32_ucrt_lib_path(sdk, &self->lib_dir, target->arch.arch))) { + if (verbose) { + fprintf(stderr, "Unable to determine ucrt path: %s\n", err_str(err)); + } + return err; + } + return ErrorNone; +} +static Error zig_libc_find_kernel32_lib_dir(ZigLibCInstallation *self, ZigWindowsSDK *sdk, ZigTarget *target, + bool verbose) +{ + Error err; + if ((err = os_get_win32_kern32_path(sdk, &self->kernel32_lib_dir, target->arch.arch))) { + if (verbose) { + fprintf(stderr, "Unable to determine kernel32 path: %s\n", err_str(err)); + } + return err; + } + return ErrorNone; +} +static Error zig_libc_find_native_msvc_lib_dir(ZigLibCInstallation *self, ZigWindowsSDK *sdk, bool verbose) { + if (sdk->msvc_lib_dir_ptr == nullptr) { + if (verbose) { + fprintf(stderr, "Unable to determine vcruntime path\n"); + } + return ErrorFileNotFound; + } + buf_init_from_mem(&self->msvc_lib_dir, sdk->msvc_lib_dir_ptr, sdk->msvc_lib_dir_len); + return ErrorNone; +} +#else +static Error zig_libc_find_native_include_dir_posix(ZigLibCInstallation *self, bool verbose) { + const char *cc_exe = getenv("CC"); + cc_exe = (cc_exe == nullptr) ? "cc" : cc_exe; + ZigList args = {}; + args.append("-E"); + args.append("-Wp,-v"); + args.append("-xc"); + args.append("/dev/null"); + Termination term; + Buf *out_stderr = buf_alloc(); + Buf *out_stdout = buf_alloc(); + Error err; + if ((err = os_exec_process(cc_exe, args, &term, out_stderr, out_stdout))) { + if (verbose) { + fprintf(stderr, "unable to determine libc include path: executing '%s': %s\n", cc_exe, err_str(err)); + } + return err; + } + if (term.how != TerminationIdClean || term.code != 0) { + if (verbose) { + fprintf(stderr, "unable to determine libc include path: executing '%s' failed\n", cc_exe); + } + return ErrorCCompileErrors; + } + char *prev_newline = buf_ptr(out_stderr); + ZigList search_paths = {}; + for (;;) { + char *newline = strchr(prev_newline, '\n'); + if (newline == nullptr) { + break; + } + *newline = 0; + if (prev_newline[0] == ' ') { + search_paths.append(prev_newline); + } + prev_newline = newline + 1; + } + if (search_paths.length == 0) { + if (verbose) { + fprintf(stderr, "unable to determine libc include path: '%s' cannot find libc headers\n", cc_exe); + } + return ErrorCCompileErrors; + } + for (size_t i = 0; i < search_paths.length; i += 1) { + // search in reverse order + const char *search_path = search_paths.items[search_paths.length - i - 1]; + // cut off spaces + while (*search_path == ' ') { + search_path += 1; + } + Buf *stdlib_path = buf_sprintf("%s/stdlib.h", search_path); + bool exists; + if ((err = os_file_exists(stdlib_path, &exists))) { + exists = false; + } + if (exists) { + buf_init_from_str(&self->include_dir, search_path); + return ErrorNone; + } + } + if (verbose) { + fprintf(stderr, "unable to determine libc include path: stdlib.h not found in '%s' search paths\n", cc_exe); + } + return ErrorFileNotFound; +} +#if !defined(ZIG_OS_DARWIN) +static Error zig_libc_cc_print_file_name(const char *o_file, Buf *out, bool want_dirname, bool verbose) { + const char *cc_exe = getenv("CC"); + cc_exe = (cc_exe == nullptr) ? "cc" : cc_exe; + ZigList args = {}; + args.append(buf_ptr(buf_sprintf("-print-file-name=%s", o_file))); + Termination term; + Buf *out_stderr = buf_alloc(); + Buf *out_stdout = buf_alloc(); + Error err; + if ((err = os_exec_process(cc_exe, args, &term, out_stderr, out_stdout))) { + if (verbose) { + fprintf(stderr, "unable to determine libc include path: executing '%s': %s\n", cc_exe, err_str(err)); + } + return err; + } + if (term.how != TerminationIdClean || term.code != 0) { + if (verbose) { + fprintf(stderr, "unable to determine libc include path: executing '%s' failed\n", cc_exe); + } + return ErrorCCompileErrors; + } + if (buf_ends_with_str(out_stdout, "\n")) { + buf_resize(out_stdout, buf_len(out_stdout) - 1); + } + if (buf_len(out_stdout) == 0 || buf_eql_str(out_stdout, o_file)) { + return ErrorCCompilerCannotFindFile; + } + if (want_dirname) { + os_path_dirname(out_stdout, out); + } else { + buf_init_from_buf(out, out_stdout); + } + return ErrorNone; +} +static Error zig_libc_find_native_lib_dir_posix(ZigLibCInstallation *self, bool verbose) { + return zig_libc_cc_print_file_name("crt1.o", &self->lib_dir, true, verbose); +} + +static Error zig_libc_find_native_static_lib_dir_posix(ZigLibCInstallation *self, bool verbose) { + return zig_libc_cc_print_file_name("crtbegin.o", &self->static_lib_dir, true, verbose); +} +#endif + +static Error zig_libc_find_native_dynamic_linker_posix(ZigLibCInstallation *self, bool verbose) { +#if defined(ZIG_OS_LINUX) + Error err; + static const char *dyn_tests[] = { + "ld-linux-x86-64.so.2", + "ld-musl-x86_64.so.1", + }; + for (size_t i = 0; i < array_length(dyn_tests); i += 1) { + const char *lib_name = dyn_tests[i]; + if ((err = zig_libc_cc_print_file_name(lib_name, &self->dynamic_linker_path, false, true))) { + if (err != ErrorCCompilerCannotFindFile) + return err; + continue; + } + return ErrorNone; + } +#endif + ZigTarget native_target; + get_native_target(&native_target); + Buf *dynamic_linker_path = target_dynamic_linker(&native_target); + buf_init_from_buf(&self->dynamic_linker_path, dynamic_linker_path); + return ErrorNone; +} +#endif + +void zig_libc_render(ZigLibCInstallation *self, FILE *file) { + fprintf(file, + "# The directory that contains `stdlib.h`.\n" + "# On Linux, can be found with: `cc -E -Wp,-v -xc /dev/null`\n" + "include_dir=%s\n" + "\n" + "# The directory that contains `crt1.o`.\n" + "# On Linux, can be found with `cc -print-file-name=crt1.o`.\n" + "# Not needed when targeting MacOS.\n" + "lib_dir=%s\n" + "\n" + "# The directory that contains `crtbegin.o`.\n" + "# On Linux, can be found with `cc -print-file-name=crtbegin.o`.\n" + "# Not needed when targeting MacOS or Windows.\n" + "static_lib_dir=%s\n" + "\n" + "# The directory that contains `vcruntime.lib`.\n" + "# Only needed when targeting Windows.\n" + "msvc_lib_dir=%s\n" + "\n" + "# The directory that contains `kernel32.lib`.\n" + "# Only needed when targeting Windows.\n" + "kernel32_lib_dir=%s\n" + "\n" + "# The full path to the dynamic linker, on the target system.\n" + "# Only needed when targeting Linux.\n" + "dynamic_linker_path=%s\n" + "\n" + , + buf_ptr(&self->include_dir), + buf_ptr(&self->lib_dir), + buf_ptr(&self->static_lib_dir), + buf_ptr(&self->msvc_lib_dir), + buf_ptr(&self->kernel32_lib_dir), + buf_ptr(&self->dynamic_linker_path) + ); +} + +Error zig_libc_find_native(ZigLibCInstallation *self, bool verbose) { + Error err; + zig_libc_init_empty(self); +#if defined(ZIG_OS_WINDOWS) + ZigTarget native_target; + get_native_target(&native_target); + ZigWindowsSDK *sdk; + switch (zig_find_windows_sdk(&sdk)) { + case ZigFindWindowsSdkErrorNone: + if ((err = zig_libc_find_native_msvc_lib_dir(self, sdk, verbose))) + return err; + if ((err = zig_libc_find_kernel32_lib_dir(self, sdk, &native_target, verbose))) + return err; + if ((err = zig_libc_find_native_include_dir_windows(self, sdk, verbose))) + return err; + if ((err = zig_libc_find_lib_dir_windows(self, sdk, &native_target, verbose))) + return err; + return ErrorNone; + case ZigFindWindowsSdkErrorOutOfMemory: + return ErrorNoMem; + case ZigFindWindowsSdkErrorNotFound: + return ErrorFileNotFound; + case ZigFindWindowsSdkErrorPathTooLong: + return ErrorPathTooLong; + } + zig_unreachable(); +#else + if ((err = zig_libc_find_native_include_dir_posix(self, verbose))) + return err; +#if defined(ZIG_OS_FREEBSD) || defined(ZIG_OS_NETBSD) + buf_init_from_str(&self->lib_dir, "/usr/lib"); + buf_init_from_str(&self->static_lib_dir, "/usr/lib"); +#elif !defined(ZIG_OS_DARWIN) + if ((err = zig_libc_find_native_lib_dir_posix(self, verbose))) + return err; + if ((err = zig_libc_find_native_static_lib_dir_posix(self, verbose))) + return err; +#endif + if ((err = zig_libc_find_native_dynamic_linker_posix(self, verbose))) + return err; + return ErrorNone; +#endif +} diff --git a/src/libc_installation.hpp b/src/libc_installation.hpp new file mode 100644 index 0000000000..4cb77f1451 --- /dev/null +++ b/src/libc_installation.hpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2019 Andrew Kelley + * + * This file is part of zig, which is MIT licensed. + * See http://opensource.org/licenses/MIT + */ + +#ifndef ZIG_LIBC_INSTALLATION_HPP +#define ZIG_LIBC_INSTALLATION_HPP + +#include + +#include "buffer.hpp" +#include "error.hpp" +#include "target.hpp" + +// Must be synchronized with zig_libc_keys +struct ZigLibCInstallation { + Buf include_dir; + Buf lib_dir; + Buf static_lib_dir; + Buf msvc_lib_dir; + Buf kernel32_lib_dir; + Buf dynamic_linker_path; +}; + +Error ATTRIBUTE_MUST_USE zig_libc_parse(ZigLibCInstallation *libc, Buf *libc_file, + const ZigTarget *target, bool verbose); +void zig_libc_render(ZigLibCInstallation *self, FILE *file); + +Error ATTRIBUTE_MUST_USE zig_libc_find_native(ZigLibCInstallation *self, bool verbose); + +#endif diff --git a/src/link.cpp b/src/link.cpp index 2878a00358..2068b8efb0 100644 --- a/src/link.cpp +++ b/src/link.cpp @@ -18,31 +18,32 @@ struct LinkJob { }; static const char *get_libc_file(CodeGen *g, const char *file) { + assert(g->libc != nullptr); Buf *out_buf = buf_alloc(); - os_path_join(g->libc_lib_dir, buf_create_from_str(file), out_buf); + os_path_join(&g->libc->lib_dir, buf_create_from_str(file), out_buf); return buf_ptr(out_buf); } static const char *get_libc_static_file(CodeGen *g, const char *file) { + assert(g->libc != nullptr); Buf *out_buf = buf_alloc(); - os_path_join(g->libc_static_lib_dir, buf_create_from_str(file), out_buf); + os_path_join(&g->libc->static_lib_dir, buf_create_from_str(file), out_buf); return buf_ptr(out_buf); } static Buf *build_a_raw(CodeGen *parent_gen, const char *aname, Buf *full_path) { - ZigTarget *child_target = parent_gen->is_native_target ? nullptr : &parent_gen->zig_target; - // The Mach-O LLD code is not well maintained, and trips an assertion // when we link compiler_rt and builtin as libraries rather than objects. // Here we workaround this by having compiler_rt and builtin be objects. // TODO write our own linker. https://github.com/ziglang/zig/issues/1535 OutType child_out_type = OutTypeLib; - if (parent_gen->zig_target.os == OsMacOSX) { + if (parent_gen->zig_target->os == OsMacOSX) { child_out_type = OutTypeObj; } - CodeGen *child_gen = codegen_create(full_path, child_target, child_out_type, - parent_gen->build_mode, parent_gen->zig_lib_dir, parent_gen->zig_std_dir); + CodeGen *child_gen = codegen_create(full_path, parent_gen->zig_target, child_out_type, + parent_gen->build_mode, parent_gen->zig_lib_dir, parent_gen->zig_std_dir, + parent_gen->libc); child_gen->out_h_path = nullptr; child_gen->verbose_tokenize = parent_gen->verbose_tokenize; @@ -171,62 +172,11 @@ static void add_rpath(LinkJob *lj, Buf *rpath) { lj->rpath_table.put(rpath, true); } -static Buf *try_dynamic_linker_path(const char *ld_name) { - const char *cc_exe = getenv("CC"); - cc_exe = (cc_exe == nullptr) ? "cc" : cc_exe; - ZigList args = {}; - args.append(buf_ptr(buf_sprintf("-print-file-name=%s", ld_name))); - Termination term; - Buf *out_stderr = buf_alloc(); - Buf *out_stdout = buf_alloc(); - int err; - if ((err = os_exec_process(cc_exe, args, &term, out_stderr, out_stdout))) { - return nullptr; - } - if (term.how != TerminationIdClean || term.code != 0) { - return nullptr; - } - if (buf_ends_with_str(out_stdout, "\n")) { - buf_resize(out_stdout, buf_len(out_stdout) - 1); - } - if (buf_len(out_stdout) == 0 || buf_eql_str(out_stdout, ld_name)) { - return nullptr; - } - return out_stdout; -} - -static Buf *get_dynamic_linker_path(CodeGen *g) { - if (g->zig_target.os == OsFreeBSD) { - return buf_create_from_str("/libexec/ld-elf.so.1"); - } - if (g->zig_target.os == OsNetBSD) { - return buf_create_from_str("/libexec/ld.elf_so"); - } - if (g->is_native_target && g->zig_target.arch.arch == ZigLLVM_x86_64) { - static const char *ld_names[] = { - "ld-linux-x86-64.so.2", - "ld-musl-x86_64.so.1", - }; - for (size_t i = 0; i < array_length(ld_names); i += 1) { - const char *ld_name = ld_names[i]; - Buf *result = try_dynamic_linker_path(ld_name); - if (result != nullptr) { - return result; - } - } - } - return target_dynamic_linker(&g->zig_target); -} - static void construct_linker_job_elf(LinkJob *lj) { CodeGen *g = lj->codegen; lj->args.append("-error-limit=0"); - if (g->libc_link_lib != nullptr) { - find_libc_lib_path(g); - } - if (g->linker_script) { lj->args.append("-T"); lj->args.append(g->linker_script); @@ -235,14 +185,14 @@ static void construct_linker_job_elf(LinkJob *lj) { lj->args.append("--gc-sections"); lj->args.append("-m"); - lj->args.append(getLDMOption(&g->zig_target)); + lj->args.append(getLDMOption(g->zig_target)); bool is_lib = g->out_type == OutTypeLib; bool shared = !g->is_static && is_lib; Buf *soname = nullptr; if (g->is_static) { - if (g->zig_target.arch.arch == ZigLLVM_arm || g->zig_target.arch.arch == ZigLLVM_armeb || - g->zig_target.arch.arch == ZigLLVM_thumb || g->zig_target.arch.arch == ZigLLVM_thumbeb) + if (g->zig_target->arch.arch == ZigLLVM_arm || g->zig_target->arch.arch == ZigLLVM_armeb || + g->zig_target->arch.arch == ZigLLVM_thumb || g->zig_target->arch.arch == ZigLLVM_thumbeb) { lj->args.append("-Bstatic"); } else { @@ -264,13 +214,13 @@ static void construct_linker_job_elf(LinkJob *lj) { if (lj->link_in_crt) { const char *crt1o; const char *crtbegino; - if (g->zig_target.os == OsNetBSD) { - crt1o = "crt0.o"; - crtbegino = "crtbegin.o"; - } else if (g->is_static) { + if (g->zig_target->os == OsNetBSD) { + crt1o = "crt0.o"; + crtbegino = "crtbegin.o"; + } else if (g->is_static) { crt1o = "crt1.o"; crtbegino = "crtbeginT.o"; - } else { + } else { crt1o = "Scrt1.o"; crtbegino = "crtbegin.o"; } @@ -311,23 +261,19 @@ static void construct_linker_job_elf(LinkJob *lj) { } if (g->libc_link_lib != nullptr) { + assert(g->libc != nullptr); lj->args.append("-L"); - lj->args.append(buf_ptr(g->libc_lib_dir)); + lj->args.append(buf_ptr(&g->libc->lib_dir)); lj->args.append("-L"); - lj->args.append(buf_ptr(g->libc_static_lib_dir)); - } + lj->args.append(buf_ptr(&g->libc->static_lib_dir)); - if (!g->is_static) { - if (g->dynamic_linker != nullptr) { - assert(buf_len(g->dynamic_linker) != 0); + if (!g->is_static) { + assert(buf_len(&g->libc->dynamic_linker_path) != 0); lj->args.append("-dynamic-linker"); - lj->args.append(buf_ptr(g->dynamic_linker)); - } else { - Buf *resolved_dynamic_linker = get_dynamic_linker_path(g); - lj->args.append("-dynamic-linker"); - lj->args.append(buf_ptr(resolved_dynamic_linker)); + lj->args.append(buf_ptr(&g->libc->dynamic_linker_path)); } + } if (shared) { @@ -397,11 +343,11 @@ static void construct_linker_job_elf(LinkJob *lj) { lj->args.append(get_libc_file(g, "crtn.o")); } - if (!g->is_native_target) { + if (!g->zig_target->is_native) { lj->args.append("--allow-shlib-undefined"); } - if (g->zig_target.os == OsZen) { + if (g->zig_target->os == OsZen) { lj->args.append("-e"); lj->args.append("_start"); @@ -429,11 +375,11 @@ static void construct_linker_job_wasm(LinkJob *lj) { //} static void coff_append_machine_arg(CodeGen *g, ZigList *list) { - if (g->zig_target.arch.arch == ZigLLVM_x86) { + if (g->zig_target->arch.arch == ZigLLVM_x86) { list->append("-MACHINE:X86"); - } else if (g->zig_target.arch.arch == ZigLLVM_x86_64) { + } else if (g->zig_target->arch.arch == ZigLLVM_x86_64) { list->append("-MACHINE:X64"); - } else if (g->zig_target.arch.arch == ZigLLVM_arm) { + } else if (g->zig_target->arch.arch == ZigLLVM_arm) { list->append("-MACHINE:ARM"); } } @@ -592,10 +538,6 @@ static void construct_linker_job_coff(LinkJob *lj) { lj->args.append("/ERRORLIMIT:0"); - if (g->libc_link_lib != nullptr) { - find_libc_lib_path(g); - } - lj->args.append("/NOLOGO"); if (!g->strip_debug_symbols) { @@ -650,13 +592,11 @@ static void construct_linker_job_coff(LinkJob *lj) { lj->args.append(buf_ptr(buf_sprintf("-OUT:%s", buf_ptr(&g->output_file_path)))); if (g->libc_link_lib != nullptr) { - lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(g->msvc_lib_dir)))); - lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(g->kernel32_lib_dir)))); + assert(g->libc != nullptr); - lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(g->libc_lib_dir)))); - if (g->libc_static_lib_dir != nullptr) { - lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(g->libc_static_lib_dir)))); - } + lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(&g->libc->msvc_lib_dir)))); + lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(&g->libc->kernel32_lib_dir)))); + lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(&g->libc->lib_dir)))); } if (is_library && !g->is_static) { @@ -691,7 +631,7 @@ static void construct_linker_job_coff(LinkJob *lj) { continue; } if (link_lib->provided_explicitly) { - if (lj->codegen->zig_target.env_type == ZigLLVM_GNU) { + if (lj->codegen->zig_target->env_type == ZigLLVM_GNU) { Buf *arg = buf_sprintf("-l%s", buf_ptr(link_lib->name)); lj->args.append(buf_ptr(arg)); } @@ -721,7 +661,8 @@ static void construct_linker_job_coff(LinkJob *lj) { gen_lib_args.append(buf_ptr(buf_sprintf("-DEF:%s", buf_ptr(def_path)))); gen_lib_args.append(buf_ptr(buf_sprintf("-OUT:%s", buf_ptr(generated_lib_path)))); Buf diag = BUF_INIT; - if (!zig_lld_link(g->zig_target.oformat, gen_lib_args.items, gen_lib_args.length, &diag)) { + ZigLLVM_ObjectFormatType target_ofmt = target_object_format(g->zig_target); + if (!zig_lld_link(target_ofmt, gen_lib_args.items, gen_lib_args.length, &diag)) { fprintf(stderr, "%s\n", buf_ptr(&diag)); exit(1); } @@ -790,7 +731,7 @@ static void get_darwin_platform(LinkJob *lj, DarwinPlatform *platform) { platform->kind = MacOS; } else if (g->mios_version_min) { platform->kind = IPhoneOS; - } else if (g->zig_target.os == OsMacOSX) { + } else if (g->zig_target->os == OsMacOSX) { platform->kind = MacOS; g->mmacosx_version_min = buf_create_from_str("10.10"); } else { @@ -817,8 +758,8 @@ static void get_darwin_platform(LinkJob *lj, DarwinPlatform *platform) { } if (platform->kind == IPhoneOS && - (g->zig_target.arch.arch == ZigLLVM_x86 || - g->zig_target.arch.arch == ZigLLVM_x86_64)) + (g->zig_target->arch.arch == ZigLLVM_x86 || + g->zig_target->arch.arch == ZigLLVM_x86_64)) { platform->kind = IPhoneOSSimulator; } @@ -882,7 +823,7 @@ static void construct_linker_job_macho(LinkJob *lj) { } lj->args.append("-arch"); - lj->args.append(get_darwin_arch_string(&g->zig_target)); + lj->args.append(get_darwin_arch_string(g->zig_target)); DarwinPlatform platform; get_darwin_platform(lj, &platform); @@ -939,7 +880,7 @@ static void construct_linker_job_macho(LinkJob *lj) { } break; case IPhoneOS: - if (g->zig_target.arch.arch == ZigLLVM_aarch64) { + if (g->zig_target->arch.arch == ZigLLVM_aarch64) { // iOS does not need any crt1 files for arm64 } else if (darwin_version_lt(&platform, 3, 1)) { lj->args.append("-lcrt1.o"); @@ -969,7 +910,7 @@ static void construct_linker_job_macho(LinkJob *lj) { lj->args.append(buf_ptr(compiler_rt_o_path)); } - if (g->is_native_target) { + if (g->zig_target->is_native) { for (size_t lib_i = 0; lib_i < g->link_libs_list.length; lib_i += 1) { LinkLib *link_lib = g->link_libs_list.at(lib_i); if (buf_eql_str(link_lib->name, "c")) { @@ -1010,7 +951,7 @@ static void construct_linker_job_macho(LinkJob *lj) { } static void construct_linker_job(LinkJob *lj) { - switch (lj->codegen->zig_target.oformat) { + switch (target_object_format(lj->codegen->zig_target)) { case ZigLLVM_UnknownObjectFormat: zig_unreachable(); @@ -1050,7 +991,7 @@ void codegen_link(CodeGen *g) { for (size_t i = 0; i < g->link_objects.length; i += 1) { file_names.append((const char *)buf_ptr(g->link_objects.at(i))); } - ZigLLVM_OSType os_type = get_llvm_os_type(g->zig_target.os); + ZigLLVM_OSType os_type = get_llvm_os_type(g->zig_target->os); codegen_add_time_event(g, "LLVM Link"); if (ZigLLVMWriteArchive(buf_ptr(&g->output_file_path), file_names.items, file_names.length, os_type)) { fprintf(stderr, "Unable to write archive '%s'\n", buf_ptr(&g->output_file_path)); @@ -1075,7 +1016,7 @@ void codegen_link(CodeGen *g) { Buf diag = BUF_INIT; codegen_add_time_event(g, "LLVM Link"); - if (g->system_linker_hack && g->zig_target.os == OsMacOSX) { + if (g->system_linker_hack && g->zig_target->os == OsMacOSX) { Termination term; ZigList args = {}; for (size_t i = 1; i < lj.args.length; i += 1) { @@ -1085,7 +1026,7 @@ void codegen_link(CodeGen *g) { if (term.how != TerminationIdClean || term.code != 0) { exit(1); } - } else if (!zig_lld_link(g->zig_target.oformat, lj.args.items, lj.args.length, &diag)) { + } else if (!zig_lld_link(target_object_format(g->zig_target), lj.args.items, lj.args.length, &diag)) { fprintf(stderr, "%s\n", buf_ptr(&diag)); exit(1); } diff --git a/src/main.cpp b/src/main.cpp index dd35cee5a5..681cd6e8ac 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -13,6 +13,7 @@ #include "error.hpp" #include "os.hpp" #include "target.hpp" +#include "libc_installation.hpp" #include @@ -36,6 +37,7 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) { " id print the base64-encoded compiler id\n" " init-exe initialize a `zig build` application in the cwd\n" " init-lib initialize a `zig build` library in the cwd\n" + " libc [paths_file] Display native libc paths file or validate one\n" " run [source] create executable and run immediately\n" " translate-c [source] convert c code to zig code\n" " targets list available compilation targets\n" @@ -53,7 +55,7 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) { " --enable-valgrind include valgrind client requests release builds\n" " --emit [asm|bin|llvm-ir] emit a specific file format as compilation output\n" " -ftime-report print timing diagnostics\n" - " --libc-include-dir [path] directory where libc stdlib.h resides\n" + " --libc [file] Provide a file which specifies libc paths\n" " --name [name] override output name\n" " --output [file] override destination path\n" " --output-h [file] generate header file\n" @@ -82,10 +84,6 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) { "Link Options:\n" " --dynamic-linker [path] set the path to ld.so\n" " --each-lib-rpath add rpath for each used dynamic library\n" - " --libc-lib-dir [path] directory where libc crt1.o resides\n" - " --libc-static-lib-dir [path] directory where libc crtbegin.o resides\n" - " --msvc-lib-dir [path] (windows) directory where vcruntime.lib resides\n" - " --kernel32-lib-dir [path] (windows) directory where kernel32.lib resides\n" " --library [lib] link against lib\n" " --forbid-library [lib] make it an error to link against lib\n" " --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) { return return_code; } +static int print_libc_usage(const char *arg0, FILE *file, int return_code) { + fprintf(file, + "Usage: %s libc\n" + "\n" + "Detect the native libc installation and print the resulting paths to stdout.\n" + "You can save this into a file and then edit the paths to create a cross\n" + "compilation libc kit. Then you can pass `--libc [file]` for Zig to use it.\n" + "\n" + "When compiling natively and no `--libc` argument provided, Zig automatically\n" + "creates zig-cache/native_libc.txt so that it does not have to detect libc\n" + "on every invocation. You can remove this file to have Zig re-detect the\n" + "native libc.\n" + "\n\n" + "Usage: %s libc [file]\n" + "\n" + "Parse a libc installation text file and validate it.\n" + , arg0, arg0); + return return_code; +} + static const char *ZIG_ZEN = "\n" " * Communicate intent precisely.\n" " * Edge cases matter.\n" @@ -169,6 +187,7 @@ enum Cmd { CmdTranslateC, CmdVersion, CmdZen, + CmdLibC, }; static const char *default_zig_cache_name = "zig-cache"; @@ -359,12 +378,7 @@ int main(int argc, char **argv) { bool verbose_cimport = false; ErrColor color = ErrColorAuto; CacheOpt enable_cache = CacheOptAuto; - const char *libc_lib_dir = nullptr; - const char *libc_static_lib_dir = nullptr; - const char *libc_include_dir = nullptr; - const char *msvc_lib_dir = nullptr; - const char *kernel32_lib_dir = nullptr; - const char *dynamic_linker = nullptr; + const char *libc_txt = nullptr; ZigList clang_argv = {0}; ZigList llvm_argv = {0}; ZigList lib_dirs = {0}; @@ -434,8 +448,10 @@ int main(int argc, char **argv) { Buf *build_runner_path = buf_alloc(); os_path_join(get_zig_special_dir(), buf_create_from_str("build_runner.zig"), build_runner_path); - CodeGen *g = codegen_create(build_runner_path, nullptr, OutTypeExe, BuildModeDebug, get_zig_lib_dir(), - override_std_dir); + ZigTarget target; + get_native_target(&target); + CodeGen *g = codegen_create(build_runner_path, &target, OutTypeExe, BuildModeDebug, get_zig_lib_dir(), + override_std_dir, nullptr); g->valgrind_support = valgrind_support; g->enable_time_report = timing_info; 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) { return (term.how == TerminationIdClean) ? term.code : -1; } else if (argc >= 2 && strcmp(argv[1], "fmt") == 0) { init_all_targets(); + ZigTarget target; + get_native_target(&target); Buf *fmt_runner_path = buf_alloc(); os_path_join(get_zig_special_dir(), buf_create_from_str("fmt_runner.zig"), fmt_runner_path); - CodeGen *g = codegen_create(fmt_runner_path, nullptr, OutTypeExe, BuildModeDebug, get_zig_lib_dir(), - nullptr); + CodeGen *g = codegen_create(fmt_runner_path, &target, OutTypeExe, BuildModeDebug, get_zig_lib_dir(), + nullptr, nullptr); g->valgrind_support = valgrind_support; g->is_single_threaded = true; codegen_set_out_name(g, buf_create_from_str("fmt")); @@ -557,7 +575,11 @@ int main(int argc, char **argv) { } else if (strcmp(arg, "--release-small") == 0) { build_mode = BuildModeSmallRelease; } else if (strcmp(arg, "--help") == 0) { - return print_full_usage(arg0, stderr, EXIT_FAILURE); + if (cmd == CmdLibC) { + return print_libc_usage(arg0, stderr, EXIT_FAILURE); + } else { + return print_full_usage(arg0, stderr, EXIT_FAILURE); + } } else if (strcmp(arg, "--strip") == 0) { strip = true; } else if (strcmp(arg, "--static") == 0) { @@ -658,18 +680,8 @@ int main(int argc, char **argv) { } } else if (strcmp(arg, "--name") == 0) { out_name = argv[i]; - } else if (strcmp(arg, "--libc-lib-dir") == 0) { - libc_lib_dir = argv[i]; - } else if (strcmp(arg, "--libc-static-lib-dir") == 0) { - libc_static_lib_dir = argv[i]; - } else if (strcmp(arg, "--libc-include-dir") == 0) { - libc_include_dir = argv[i]; - } else if (strcmp(arg, "--msvc-lib-dir") == 0) { - msvc_lib_dir = argv[i]; - } else if (strcmp(arg, "--kernel32-lib-dir") == 0) { - kernel32_lib_dir = argv[i]; - } else if (strcmp(arg, "--dynamic-linker") == 0) { - dynamic_linker = argv[i]; + } else if (strcmp(arg, "--libc") == 0) { + libc_txt = argv[i]; } else if (strcmp(arg, "-isystem") == 0) { clang_argv.append("-isystem"); clang_argv.append(argv[i]); @@ -778,6 +790,8 @@ int main(int argc, char **argv) { cmd = CmdVersion; } else if (strcmp(arg, "zen") == 0) { cmd = CmdZen; + } else if (strcmp(arg, "libc") == 0) { + cmd = CmdLibC; } else if (strcmp(arg, "translate-c") == 0) { cmd = CmdTranslateC; } else if (strcmp(arg, "test") == 0) { @@ -797,6 +811,7 @@ int main(int argc, char **argv) { case CmdRun: case CmdTranslateC: case CmdTest: + case CmdLibC: if (!in_file) { in_file = arg; if (cmd == CmdRun) { @@ -828,27 +843,25 @@ int main(int argc, char **argv) { init_all_targets(); - ZigTarget alloc_target; - ZigTarget *target; + ZigTarget target; if (!target_arch && !target_os && !target_environ) { - target = nullptr; + get_native_target(&target); } else { - target = &alloc_target; - get_unknown_target(target); + get_unknown_target(&target); if (target_arch) { - if (parse_target_arch(target_arch, &target->arch)) { + if (parse_target_arch(target_arch, &target.arch)) { fprintf(stderr, "invalid --target-arch argument\n"); return print_error_usage(arg0); } } if (target_os) { - if (parse_target_os(target_os, &target->os)) { + if (parse_target_os(target_os, &target.os)) { fprintf(stderr, "invalid --target-os argument\n"); return print_error_usage(arg0); } } if (target_environ) { - if (parse_target_environ(target_environ, &target->env_type)) { + if (parse_target_environ(target_environ, &target.env_type)) { fprintf(stderr, "invalid --target-environ argument\n"); return print_error_usage(arg0); } @@ -856,8 +869,22 @@ int main(int argc, char **argv) { } switch (cmd) { + case CmdLibC: { + if (in_file) { + ZigLibCInstallation libc; + if ((err = zig_libc_parse(&libc, buf_create_from_str(in_file), &target, true))) + return EXIT_FAILURE; + return EXIT_SUCCESS; + } + ZigLibCInstallation libc; + if ((err = zig_libc_find_native(&libc, true))) + return EXIT_FAILURE; + zig_libc_render(&libc, stdout); + return EXIT_SUCCESS; + } case CmdBuiltin: { - CodeGen *g = codegen_create(nullptr, target, out_type, build_mode, get_zig_lib_dir(), override_std_dir); + CodeGen *g = codegen_create(nullptr, &target, out_type, build_mode, get_zig_lib_dir(), override_std_dir, + nullptr); g->valgrind_support = valgrind_support; g->is_single_threaded = is_single_threaded; Buf *builtin_source = codegen_generate_builtin_source(g); @@ -917,8 +944,16 @@ int main(int argc, char **argv) { if (cmd == CmdRun && buf_out_name == nullptr) { buf_out_name = buf_create_from_str("run"); } - CodeGen *g = codegen_create(zig_root_source_file, target, out_type, build_mode, get_zig_lib_dir(), - override_std_dir); + ZigLibCInstallation *libc = nullptr; + if (libc_txt != nullptr) { + libc = allocate(1); + if ((err = zig_libc_parse(libc, buf_create_from_str(libc_txt), &target, true))) { + fprintf(stderr, "Unable to parse --libc text file: %s\n", err_str(err)); + return EXIT_FAILURE; + } + } + CodeGen *g = codegen_create(zig_root_source_file, &target, out_type, build_mode, get_zig_lib_dir(), + override_std_dir, libc); g->valgrind_support = valgrind_support; g->subsystem = subsystem; @@ -944,18 +979,6 @@ int main(int argc, char **argv) { codegen_set_llvm_argv(g, llvm_argv.items, llvm_argv.length); codegen_set_strip(g, strip); codegen_set_is_static(g, is_static); - if (libc_lib_dir) - codegen_set_libc_lib_dir(g, buf_create_from_str(libc_lib_dir)); - if (libc_static_lib_dir) - codegen_set_libc_static_lib_dir(g, buf_create_from_str(libc_static_lib_dir)); - if (libc_include_dir) - codegen_set_libc_include_dir(g, buf_create_from_str(libc_include_dir)); - if (msvc_lib_dir) - codegen_set_msvc_lib_dir(g, buf_create_from_str(msvc_lib_dir)); - if (kernel32_lib_dir) - codegen_set_kernel32_lib_dir(g, buf_create_from_str(kernel32_lib_dir)); - if (dynamic_linker) - codegen_set_dynamic_linker(g, buf_create_from_str(dynamic_linker)); g->verbose_tokenize = verbose_tokenize; g->verbose_ast = verbose_ast; g->verbose_link = verbose_link; @@ -1086,7 +1109,7 @@ int main(int argc, char **argv) { } } - if (!target_can_exec(&native, target)) { + if (!target_can_exec(&native, &target)) { fprintf(stderr, "Created %s but skipping execution because it is non-native.\n", buf_ptr(test_exe_path)); return 0; diff --git a/src/os.cpp b/src/os.cpp index c11840b1cf..95febca9bc 100644 --- a/src/os.cpp +++ b/src/os.cpp @@ -1550,7 +1550,7 @@ void os_stderr_set_color(TermColor color) { #endif } -int os_get_win32_ucrt_lib_path(ZigWindowsSDK *sdk, Buf* output_buf, ZigLLVM_ArchType platform_type) { +Error os_get_win32_ucrt_lib_path(ZigWindowsSDK *sdk, Buf* output_buf, ZigLLVM_ArchType platform_type) { #if defined(ZIG_OS_WINDOWS) buf_resize(output_buf, 0); 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 buf_init_from_buf(tmp_buf, output_buf); buf_append_str(tmp_buf, "ucrt.lib"); if (GetFileAttributesA(buf_ptr(tmp_buf)) != INVALID_FILE_ATTRIBUTES) { - return 0; + return ErrorNone; } else { buf_resize(output_buf, 0); @@ -1582,12 +1582,12 @@ int os_get_win32_ucrt_lib_path(ZigWindowsSDK *sdk, Buf* output_buf, ZigLLVM_Arch #endif } -int os_get_win32_ucrt_include_path(ZigWindowsSDK *sdk, Buf* output_buf) { +Error os_get_win32_ucrt_include_path(ZigWindowsSDK *sdk, Buf* output_buf) { #if defined(ZIG_OS_WINDOWS) buf_resize(output_buf, 0); buf_appendf(output_buf, "%s\\Include\\%s\\ucrt", sdk->path10_ptr, sdk->version10_ptr); if (GetFileAttributesA(buf_ptr(output_buf)) != INVALID_FILE_ATTRIBUTES) { - return 0; + return ErrorNone; } else { buf_resize(output_buf, 0); @@ -1598,7 +1598,7 @@ int os_get_win32_ucrt_include_path(ZigWindowsSDK *sdk, Buf* output_buf) { #endif } -int os_get_win32_kern32_path(ZigWindowsSDK *sdk, Buf* output_buf, ZigLLVM_ArchType platform_type) { +Error os_get_win32_kern32_path(ZigWindowsSDK *sdk, Buf* output_buf, ZigLLVM_ArchType platform_type) { #if defined(ZIG_OS_WINDOWS) { buf_resize(output_buf, 0); @@ -1620,7 +1620,7 @@ int os_get_win32_kern32_path(ZigWindowsSDK *sdk, Buf* output_buf, ZigLLVM_ArchTy buf_init_from_buf(tmp_buf, output_buf); buf_append_str(tmp_buf, "kernel32.lib"); if (GetFileAttributesA(buf_ptr(tmp_buf)) != INVALID_FILE_ATTRIBUTES) { - return 0; + return ErrorNone; } } { @@ -1643,7 +1643,7 @@ int os_get_win32_kern32_path(ZigWindowsSDK *sdk, Buf* output_buf, ZigLLVM_ArchTy buf_init_from_buf(tmp_buf, output_buf); buf_append_str(tmp_buf, "kernel32.lib"); if (GetFileAttributesA(buf_ptr(tmp_buf)) != INVALID_FILE_ATTRIBUTES) { - return 0; + return ErrorNone; } } return ErrorFileNotFound; diff --git a/src/os.hpp b/src/os.hpp index dab7b84896..db357c22a2 100644 --- a/src/os.hpp +++ b/src/os.hpp @@ -135,9 +135,9 @@ Error ATTRIBUTE_MUST_USE os_self_exe_path(Buf *out_path); Error ATTRIBUTE_MUST_USE os_get_app_data_dir(Buf *out_path, const char *appname); -int os_get_win32_ucrt_include_path(ZigWindowsSDK *sdk, Buf *output_buf); -int os_get_win32_ucrt_lib_path(ZigWindowsSDK *sdk, Buf *output_buf, ZigLLVM_ArchType platform_type); -int os_get_win32_kern32_path(ZigWindowsSDK *sdk, Buf *output_buf, ZigLLVM_ArchType platform_type); +Error ATTRIBUTE_MUST_USE os_get_win32_ucrt_include_path(ZigWindowsSDK *sdk, Buf *output_buf); +Error ATTRIBUTE_MUST_USE os_get_win32_ucrt_lib_path(ZigWindowsSDK *sdk, Buf *output_buf, ZigLLVM_ArchType platform_type); +Error ATTRIBUTE_MUST_USE os_get_win32_kern32_path(ZigWindowsSDK *sdk, Buf *output_buf, ZigLLVM_ArchType platform_type); Error ATTRIBUTE_MUST_USE os_self_exe_shared_libs(ZigList &paths); diff --git a/src/target.cpp b/src/target.cpp index 3e733da0e7..01e8b90cea 100644 --- a/src/target.cpp +++ b/src/target.cpp @@ -214,7 +214,7 @@ size_t target_oformat_count(void) { return array_length(oformat_list); } -const ZigLLVM_ObjectFormatType get_target_oformat(size_t index) { +ZigLLVM_ObjectFormatType get_target_oformat(size_t index) { return oformat_list[index]; } @@ -443,14 +443,16 @@ ZigLLVM_EnvironmentType get_target_environ(size_t index) { void get_native_target(ZigTarget *target) { ZigLLVM_OSType os_type; + ZigLLVM_ObjectFormatType oformat; // ignored; based on arch/os ZigLLVMGetNativeTarget( &target->arch.arch, &target->arch.sub_arch, &target->vendor, &os_type, &target->env_type, - &target->oformat); + &oformat); target->os = get_zig_os_type(os_type); + target->is_native = true; } void get_unknown_target(ZigTarget *target) { @@ -459,7 +461,7 @@ void get_unknown_target(ZigTarget *target) { target->vendor = ZigLLVM_UnknownVendor; target->os = OsFreestanding; target->env_type = ZigLLVM_UnknownEnvironment; - target->oformat = ZigLLVM_UnknownObjectFormat; + target->is_native = false; } static 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) { } } -void resolve_target_object_format(ZigTarget *target) { - if (target->oformat != ZigLLVM_UnknownObjectFormat) { - return; +ZigLLVM_ObjectFormatType target_object_format(const ZigTarget *target) { + if (target->os == OsUefi || target->os == OsWindows) { + return ZigLLVM_COFF; + } else if (target_is_darwin(target)) { + return ZigLLVM_MachO; } - - switch (target->arch.arch) { - case ZigLLVM_UnknownArch: - case ZigLLVM_aarch64: - case ZigLLVM_arm: - case ZigLLVM_thumb: - case ZigLLVM_x86: - case ZigLLVM_x86_64: - if (target_is_darwin(target)) { - target->oformat = ZigLLVM_MachO; - } else if (target->os == OsWindows) { - target->oformat = ZigLLVM_COFF; - } else { - target->oformat = ZigLLVM_ELF; - } - return; - - case ZigLLVM_aarch64_be: - case ZigLLVM_amdgcn: - case ZigLLVM_amdil: - case ZigLLVM_amdil64: - case ZigLLVM_armeb: - case ZigLLVM_arc: - case ZigLLVM_avr: - case ZigLLVM_bpfeb: - case ZigLLVM_bpfel: - case ZigLLVM_hexagon: - case ZigLLVM_lanai: - case ZigLLVM_hsail: - case ZigLLVM_hsail64: - case ZigLLVM_kalimba: - case ZigLLVM_le32: - case ZigLLVM_le64: - case ZigLLVM_mips: - case ZigLLVM_mips64: - case ZigLLVM_mips64el: - case ZigLLVM_mipsel: - case ZigLLVM_msp430: - case ZigLLVM_nios2: - case ZigLLVM_nvptx: - case ZigLLVM_nvptx64: - case ZigLLVM_ppc64le: - case ZigLLVM_r600: - case ZigLLVM_renderscript32: - case ZigLLVM_renderscript64: - case ZigLLVM_riscv32: - case ZigLLVM_riscv64: - case ZigLLVM_shave: - case ZigLLVM_sparc: - case ZigLLVM_sparcel: - case ZigLLVM_sparcv9: - case ZigLLVM_spir: - case ZigLLVM_spir64: - case ZigLLVM_systemz: - case ZigLLVM_tce: - case ZigLLVM_tcele: - case ZigLLVM_thumbeb: - case ZigLLVM_xcore: - target->oformat= ZigLLVM_ELF; - return; - - case ZigLLVM_wasm32: - case ZigLLVM_wasm64: - target->oformat = ZigLLVM_Wasm; - return; - - case ZigLLVM_ppc: - case ZigLLVM_ppc64: - if (target_is_darwin(target)) { - target->oformat = ZigLLVM_MachO; - } else { - target->oformat= ZigLLVM_ELF; - } - return; + if (target->arch.arch == ZigLLVM_wasm32 || + target->arch.arch == ZigLLVM_wasm64) + { + return ZigLLVM_Wasm; } + return ZigLLVM_ELF; } // 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) { return target->os == OsFreestanding; } -const char *target_o_file_ext(ZigTarget *target) { +const char *target_o_file_ext(const ZigTarget *target) { if (target->env_type == ZigLLVM_MSVC || target->os == OsWindows || target->os == OsUefi) { return ".obj"; } else { @@ -820,15 +755,15 @@ const char *target_o_file_ext(ZigTarget *target) { } } -const char *target_asm_file_ext(ZigTarget *target) { +const char *target_asm_file_ext(const ZigTarget *target) { return ".s"; } -const char *target_llvm_ir_file_ext(ZigTarget *target) { +const char *target_llvm_ir_file_ext(const ZigTarget *target) { return ".ll"; } -const char *target_exe_file_ext(ZigTarget *target) { +const char *target_exe_file_ext(const ZigTarget *target) { if (target->os == OsWindows) { return ".exe"; } else if (target->os == OsUefi) { @@ -838,7 +773,9 @@ const char *target_exe_file_ext(ZigTarget *target) { } } -const char *target_lib_file_ext(ZigTarget *target, bool is_static, size_t version_major, size_t version_minor, size_t version_patch) { +const char *target_lib_file_ext(const ZigTarget *target, bool is_static, + size_t version_major, size_t version_minor, size_t version_patch) +{ if (target->os == OsWindows || target->os == OsUefi) { if (is_static) { return ".lib"; @@ -860,7 +797,7 @@ enum FloatAbi { FloatAbiSoftFp, }; -static FloatAbi get_float_abi(ZigTarget *target) { +static FloatAbi get_float_abi(const ZigTarget *target) { const ZigLLVM_EnvironmentType env = target->env_type; if (env == ZigLLVM_GNUEABIHF || env == ZigLLVM_EABIHF || @@ -876,7 +813,14 @@ static bool is_64_bit(ZigLLVM_ArchType arch) { return get_arch_pointer_bit_width(arch) == 64; } -Buf *target_dynamic_linker(ZigTarget *target) { +Buf *target_dynamic_linker(const ZigTarget *target) { + if (target->os == OsFreeBSD) { + return buf_create_from_str("/libexec/ld-elf.so.1"); + } + if (target->os == OsNetBSD) { + return buf_create_from_str("/libexec/ld.elf_so"); + } + const ZigLLVM_ArchType arch = target->arch.arch; const ZigLLVM_EnvironmentType env = target->env_type; @@ -1098,3 +1042,10 @@ bool target_has_valgrind_support(const ZigTarget *target) { } zig_unreachable(); } + +bool target_requires_libc(const ZigTarget *target) { + // On Darwin, we always link libSystem which contains libc. + // Similarly on FreeBSD and NetBSD we always link system libc + // since this is the stable syscall interface. + return (target_is_darwin(target) || target->os == OsFreeBSD || target->os == OsNetBSD); +} diff --git a/src/target.hpp b/src/target.hpp index 292ea8f94f..620c9b2664 100644 --- a/src/target.hpp +++ b/src/target.hpp @@ -71,7 +71,7 @@ struct ZigTarget { ZigLLVM_VendorType vendor; Os os; ZigLLVM_EnvironmentType env_type; - ZigLLVM_ObjectFormatType oformat; + bool is_native; }; enum CIntType { @@ -105,8 +105,9 @@ ZigLLVM_EnvironmentType get_target_environ(size_t index); size_t target_oformat_count(void); -const ZigLLVM_ObjectFormatType get_target_oformat(size_t index); +ZigLLVM_ObjectFormatType get_target_oformat(size_t index); const char *get_target_oformat_name(ZigLLVM_ObjectFormatType oformat); +ZigLLVM_ObjectFormatType target_object_format(const ZigTarget *target); void get_native_target(ZigTarget *target); void get_unknown_target(ZigTarget *target); @@ -123,13 +124,14 @@ void resolve_target_object_format(ZigTarget *target); uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id); -const char *target_o_file_ext(ZigTarget *target); -const char *target_asm_file_ext(ZigTarget *target); -const char *target_llvm_ir_file_ext(ZigTarget *target); -const char *target_exe_file_ext(ZigTarget *target); -const char *target_lib_file_ext(ZigTarget *target, bool is_static, size_t version_major, size_t version_minor, size_t version_patch); +const char *target_o_file_ext(const ZigTarget *target); +const char *target_asm_file_ext(const ZigTarget *target); +const char *target_llvm_ir_file_ext(const ZigTarget *target); +const char *target_exe_file_ext(const ZigTarget *target); +const char *target_lib_file_ext(const ZigTarget *target, bool is_static, + size_t version_major, size_t version_minor, size_t version_patch); -Buf *target_dynamic_linker(ZigTarget *target); +Buf *target_dynamic_linker(const ZigTarget *target); bool target_can_exec(const ZigTarget *host_target, const ZigTarget *guest_target); ZigLLVM_OSType get_llvm_os_type(Os os_type); @@ -138,5 +140,6 @@ bool target_is_arm(const ZigTarget *target); bool target_allows_addr_zero(const ZigTarget *target); bool target_has_valgrind_support(const ZigTarget *target); bool target_is_darwin(const ZigTarget *target); +bool target_requires_libc(const ZigTarget *target); #endif diff --git a/src/translate_c.cpp b/src/translate_c.cpp index 1600fa9bf7..3fcdf139f6 100644 --- a/src/translate_c.cpp +++ b/src/translate_c.cpp @@ -4776,7 +4776,7 @@ Error parse_h_file(ImportTableEntry *import, ZigList *errors, const clang_argv.append("-x"); clang_argv.append("c"); - if (c->codegen->is_native_target) { + if (c->codegen->zig_target->is_native) { char *ZIG_PARSEC_CFLAGS = getenv("ZIG_NATIVE_PARSEC_CFLAGS"); if (ZIG_PARSEC_CFLAGS) { Buf tmp_buf = BUF_INIT; @@ -4798,9 +4798,9 @@ Error parse_h_file(ImportTableEntry *import, ZigList *errors, const clang_argv.append("-isystem"); clang_argv.append(buf_ptr(codegen->zig_c_headers_dir)); - if (codegen->libc_include_dir != nullptr) { + if (codegen->libc != nullptr) { clang_argv.append("-isystem"); - clang_argv.append(buf_ptr(codegen->libc_include_dir)); + clang_argv.append(buf_ptr(&codegen->libc->include_dir)); } // windows c runtime requires -D_DEBUG if using debug libraries @@ -4820,7 +4820,7 @@ Error parse_h_file(ImportTableEntry *import, ZigList *errors, const clang_argv.append("-Xclang"); clang_argv.append("-detailed-preprocessing-record"); - if (!c->codegen->is_native_target) { + if (!c->codegen->zig_target->is_native) { clang_argv.append("-target"); clang_argv.append(buf_ptr(&c->codegen->triple_str)); }