Commit 6fd8d455bc
Changed files (18)
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<LinkLib *> link_libs_list;
// add -framework [name] args to linker
ZigList<Buf *> darwin_frameworks;
@@ -1801,6 +1807,8 @@ struct CodeGen {
ZigList<Buf *> assembly_files;
ZigList<const char *> 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 {
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<const char *> 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<const char *> 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<const char *> 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)) {
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);
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<CodeGen>(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<ZigLibCInstallation>(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;
src/codegen.hpp
@@ -11,11 +11,12 @@
#include "parser.hpp"
#include "errmsg.hpp"
#include "target.hpp"
+#include "libc_installation.hpp"
#include <stdio.h>
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);
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)";
}
src/error.hpp
@@ -36,6 +36,8 @@ enum Error {
ErrorPipeBusy,
ErrorPrimitiveTypeNotFound,
ErrorCacheUnavailable,
+ ErrorPathTooLong,
+ ErrorCCompilerCannotFindFile,
};
const char *err_str(Error err);
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<ImportTableEntry>(1);
child_import->decls_scope = create_decls_scope(ira->codegen, node, nullptr, nullptr, child_import);
child_import->c_import_node = node;
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<uint8_t> name, Slice<uint8_t> 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<Slice<uint8_t>> 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<uint8_t> name;
+ if (!SplitIterator_next(&line_it).unwrap(&name)) {
+ if (verbose) {
+ fprintf(stderr, "missing equal sign after field name\n");
+ }
+ return ErrorSemanticAnalyzeFail;
+ }
+ Slice<uint8_t> 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<const char *> 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<const char *> 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<const char *> 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
+}
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 <stdio.h>
+
+#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
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<const char *> 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);
- lj->args.append("-dynamic-linker");
- lj->args.append(buf_ptr(g->dynamic_linker));
- } else {
- Buf *resolved_dynamic_linker = get_dynamic_linker_path(g);
+ if (!g->is_static) {
+ assert(buf_len(&g->libc->dynamic_linker_path) != 0);
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<const char *> *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<const char *> 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);
}
src/main.cpp
@@ -13,6 +13,7 @@
#include "error.hpp"
#include "os.hpp"
#include "target.hpp"
+#include "libc_installation.hpp"
#include <stdio.h>
@@ -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<const char *> clang_argv = {0};
ZigList<const char *> llvm_argv = {0};
ZigList<const char *> 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<ZigLibCInstallation>(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;
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;
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<Buf *> &paths);
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);
+}
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
src/translate_c.cpp
@@ -4776,7 +4776,7 @@ Error parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *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<ErrorMsg *> *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<ErrorMsg *> *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));
}
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"