better libc detection (#1996)

* better libc detection

This introduces a new command `zig libc` which prints
the various paths of libc files. It outputs them to stdout
in a simple text file format that it is capable of parsing.
You can use `zig libc libc.txt` to validate a file.

These arguments are gone:
--libc-lib-dir [path]        directory where libc crt1.o resides
--libc-static-lib-dir [path] directory where libc crtbegin.o resides
--msvc-lib-dir [path]        (windows) directory where vcruntime.lib resides
--kernel32-lib-dir [path]    (windows) directory where kernel32.lib resides

Instead we have this argument:
--libc [file]                Provide a file which specifies libc paths

This is used to pass a libc text file (which can be generated with
`zig libc`). So it is easier to manage multiple cross compilation
environments.

`--cache on` now works when linking against libc.

`ZigTarget` now has a bool field `is_native`

Better error messaging when you try to link against libc or use
`@cImport` but the various paths cannot be found. It should also be
faster.

* save native_libc.txt in zig-cache

This avoids having to detect libc at runtime on every invocation.
master
Andrew Kelley 2019-02-23 09:35:56 -05:00 committed by GitHub
parent 52bb71867d
commit 6fd8d455bc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 774 additions and 592 deletions

View File

@ -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"

View File

@ -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 {

View File

@ -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)) {

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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)";
}

View File

@ -36,6 +36,8 @@ enum Error {
ErrorPipeBusy,
ErrorPrimitiveTypeNotFound,
ErrorCacheUnavailable,
ErrorPathTooLong,
ErrorCCompilerCannotFindFile,
};
const char *err_str(Error err);

View File

@ -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;

408
src/libc_installation.cpp Normal file
View File

@ -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
}

33
src/libc_installation.hpp Normal file
View File

@ -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

View File

@ -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);
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<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);
}

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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);
}

View File

@ -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

View File

@ -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));
}