commit
d3c88a8949
|
@ -14,6 +14,7 @@ static const char *zig_libc_keys[] = {
|
|||
"include_dir",
|
||||
"sys_include_dir",
|
||||
"crt_dir",
|
||||
"static_crt_dir",
|
||||
"msvc_lib_dir",
|
||||
"kernel32_lib_dir",
|
||||
};
|
||||
|
@ -34,6 +35,7 @@ static void zig_libc_init_empty(ZigLibCInstallation *libc) {
|
|||
buf_init_from_str(&libc->include_dir, "");
|
||||
buf_init_from_str(&libc->sys_include_dir, "");
|
||||
buf_init_from_str(&libc->crt_dir, "");
|
||||
buf_init_from_str(&libc->static_crt_dir, "");
|
||||
buf_init_from_str(&libc->msvc_lib_dir, "");
|
||||
buf_init_from_str(&libc->kernel32_lib_dir, "");
|
||||
}
|
||||
|
@ -74,8 +76,9 @@ Error zig_libc_parse(ZigLibCInstallation *libc, Buf *libc_file, const ZigTarget
|
|||
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->sys_include_dir);
|
||||
match = match || zig_libc_match_key(name, value, found_keys, 2, &libc->crt_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, 3, &libc->static_crt_dir);
|
||||
match = match || zig_libc_match_key(name, value, found_keys, 4, &libc->msvc_lib_dir);
|
||||
match = match || zig_libc_match_key(name, value, found_keys, 5, &libc->kernel32_lib_dir);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < zig_libc_keys_len; i += 1) {
|
||||
|
@ -110,6 +113,15 @@ Error zig_libc_parse(ZigLibCInstallation *libc, Buf *libc_file, const ZigTarget
|
|||
}
|
||||
}
|
||||
|
||||
if (buf_len(&libc->static_crt_dir) == 0) {
|
||||
if (target->os == OsWindows && target_abi_is_gnu(target->abi)) {
|
||||
if (verbose) {
|
||||
fprintf(stderr, "static_crt_dir may not be empty for %s\n", target_os_name(target->os));
|
||||
}
|
||||
return ErrorSemanticAnalyzeFail;
|
||||
}
|
||||
}
|
||||
|
||||
if (buf_len(&libc->msvc_lib_dir) == 0) {
|
||||
if (target->os == OsWindows && !target_abi_is_gnu(target->abi)) {
|
||||
if (verbose) {
|
||||
|
@ -310,6 +322,10 @@ static Error zig_libc_find_native_crt_dir_posix(ZigLibCInstallation *self, bool
|
|||
}
|
||||
#endif
|
||||
|
||||
static Error zig_libc_find_native_static_crt_dir_posix(ZigLibCInstallation *self, bool verbose) {
|
||||
return zig_libc_cc_print_file_name("crtbegin.o", &self->static_crt_dir, true, verbose);
|
||||
}
|
||||
|
||||
#if defined(ZIG_OS_WINDOWS)
|
||||
static Error zig_libc_find_native_include_dir_windows(ZigLibCInstallation *self, ZigWindowsSDK *sdk, bool verbose) {
|
||||
Error err;
|
||||
|
@ -322,7 +338,7 @@ static Error zig_libc_find_native_include_dir_windows(ZigLibCInstallation *self,
|
|||
return ErrorNone;
|
||||
}
|
||||
|
||||
static Error zig_libc_find_crt_dir_windows(ZigLibCInstallation *self, ZigWindowsSDK *sdk, ZigTarget *target,
|
||||
static Error zig_libc_find_native_crt_dir_windows(ZigLibCInstallation *self, ZigWindowsSDK *sdk, ZigTarget *target,
|
||||
bool verbose)
|
||||
{
|
||||
Error err;
|
||||
|
@ -398,11 +414,16 @@ void zig_libc_render(ZigLibCInstallation *self, FILE *file) {
|
|||
"# On POSIX it's the directory that includes `sys/errno.h`.\n"
|
||||
"sys_include_dir=%s\n"
|
||||
"\n"
|
||||
"# The directory that contains `crt1.o`.\n"
|
||||
"# The directory that contains `crt1.o` or `crt2.o`.\n"
|
||||
"# On POSIX, can be found with `cc -print-file-name=crt1.o`.\n"
|
||||
"# Not needed when targeting MacOS.\n"
|
||||
"crt_dir=%s\n"
|
||||
"\n"
|
||||
"# The directory that contains `crtbegin.o`.\n"
|
||||
"# On POSIX, can be found with `cc -print-file-name=crtbegin.o`.\n"
|
||||
"# Not needed when targeting MacOS.\n"
|
||||
"static_crt_dir=%s\n"
|
||||
"\n"
|
||||
"# The directory that contains `vcruntime.lib`.\n"
|
||||
"# Only needed when targeting MSVC on Windows.\n"
|
||||
"msvc_lib_dir=%s\n"
|
||||
|
@ -415,6 +436,7 @@ void zig_libc_render(ZigLibCInstallation *self, FILE *file) {
|
|||
buf_ptr(&self->include_dir),
|
||||
buf_ptr(&self->sys_include_dir),
|
||||
buf_ptr(&self->crt_dir),
|
||||
buf_ptr(&self->static_crt_dir),
|
||||
buf_ptr(&self->msvc_lib_dir),
|
||||
buf_ptr(&self->kernel32_lib_dir)
|
||||
);
|
||||
|
@ -431,6 +453,8 @@ Error zig_libc_find_native(ZigLibCInstallation *self, bool verbose) {
|
|||
return err;
|
||||
if ((err = zig_libc_find_native_crt_dir_posix(self, verbose)))
|
||||
return err;
|
||||
if ((err = zig_libc_find_native_static_crt_dir_posix(self, verbose)))
|
||||
return err;
|
||||
return ErrorNone;
|
||||
} else {
|
||||
ZigWindowsSDK *sdk;
|
||||
|
@ -444,7 +468,7 @@ Error zig_libc_find_native(ZigLibCInstallation *self, bool verbose) {
|
|||
return err;
|
||||
if ((err = zig_libc_find_native_include_dir_windows(self, sdk, verbose)))
|
||||
return err;
|
||||
if ((err = zig_libc_find_crt_dir_windows(self, sdk, &native_target, verbose)))
|
||||
if ((err = zig_libc_find_native_crt_dir_windows(self, sdk, &native_target, verbose)))
|
||||
return err;
|
||||
return ErrorNone;
|
||||
case ZigFindWindowsSdkErrorOutOfMemory:
|
||||
|
|
|
@ -19,6 +19,7 @@ struct ZigLibCInstallation {
|
|||
Buf include_dir;
|
||||
Buf sys_include_dir;
|
||||
Buf crt_dir;
|
||||
Buf static_crt_dir;
|
||||
Buf msvc_lib_dir;
|
||||
Buf kernel32_lib_dir;
|
||||
};
|
||||
|
@ -29,8 +30,6 @@ void zig_libc_render(ZigLibCInstallation *self, FILE *file);
|
|||
|
||||
Error ATTRIBUTE_MUST_USE zig_libc_find_native(ZigLibCInstallation *self, bool verbose);
|
||||
|
||||
#if defined(ZIG_OS_LINUX) || defined(ZIG_OS_WINDOWS)
|
||||
Error zig_libc_cc_print_file_name(const char *o_file, Buf *out, bool want_dirname, bool verbose);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
259
src/link.cpp
259
src/link.cpp
|
@ -1137,53 +1137,121 @@ static bool zig_lld_link(ZigLLVM_ObjectFormatType oformat, const char **args, si
|
|||
}
|
||||
|
||||
static void add_uefi_link_args(LinkJob *lj) {
|
||||
lj->args.append("/BASE:0");
|
||||
lj->args.append("/ENTRY:EfiMain");
|
||||
lj->args.append("/OPT:REF");
|
||||
lj->args.append("/SAFESEH:NO");
|
||||
lj->args.append("/MERGE:.rdata=.data");
|
||||
lj->args.append("/ALIGN:32");
|
||||
lj->args.append("/NODEFAULTLIB");
|
||||
lj->args.append("/SECTION:.xdata,D");
|
||||
lj->args.append("-BASE:0");
|
||||
lj->args.append("-ENTRY:EfiMain");
|
||||
lj->args.append("-OPT:REF");
|
||||
lj->args.append("-SAFESEH:NO");
|
||||
lj->args.append("-MERGE:.rdata=.data");
|
||||
lj->args.append("-ALIGN:32");
|
||||
lj->args.append("-NODEFAULTLIB");
|
||||
lj->args.append("-SECTION:.xdata,D");
|
||||
}
|
||||
|
||||
static void add_nt_link_args(LinkJob *lj, bool is_library) {
|
||||
static void add_msvc_link_args(LinkJob *lj, bool is_library) {
|
||||
CodeGen *g = lj->codegen;
|
||||
|
||||
if (lj->link_in_crt) {
|
||||
// TODO: https://github.com/ziglang/zig/issues/2064
|
||||
bool is_dynamic = true; // g->is_dynamic;
|
||||
const char *lib_str = is_dynamic ? "" : "lib";
|
||||
const char *d_str = (g->build_mode == BuildModeDebug) ? "d" : "";
|
||||
// TODO: https://github.com/ziglang/zig/issues/2064
|
||||
bool is_dynamic = true; // g->is_dynamic;
|
||||
const char *lib_str = is_dynamic ? "" : "lib";
|
||||
const char *d_str = (g->build_mode == BuildModeDebug) ? "d" : "";
|
||||
|
||||
if (!is_dynamic) {
|
||||
Buf *cmt_lib_name = buf_sprintf("libcmt%s.lib", d_str);
|
||||
lj->args.append(buf_ptr(cmt_lib_name));
|
||||
} else {
|
||||
Buf *msvcrt_lib_name = buf_sprintf("msvcrt%s.lib", d_str);
|
||||
lj->args.append(buf_ptr(msvcrt_lib_name));
|
||||
}
|
||||
|
||||
Buf *vcruntime_lib_name = buf_sprintf("%svcruntime%s.lib", lib_str, d_str);
|
||||
lj->args.append(buf_ptr(vcruntime_lib_name));
|
||||
|
||||
Buf *crt_lib_name = buf_sprintf("%sucrt%s.lib", lib_str, d_str);
|
||||
lj->args.append(buf_ptr(crt_lib_name));
|
||||
|
||||
//Visual C++ 2015 Conformance Changes
|
||||
//https://msdn.microsoft.com/en-us/library/bb531344.aspx
|
||||
lj->args.append("legacy_stdio_definitions.lib");
|
||||
|
||||
// msvcrt depends on kernel32 and ntdll
|
||||
lj->args.append("kernel32.lib");
|
||||
lj->args.append("ntdll.lib");
|
||||
if (!is_dynamic) {
|
||||
Buf *cmt_lib_name = buf_sprintf("libcmt%s.lib", d_str);
|
||||
lj->args.append(buf_ptr(cmt_lib_name));
|
||||
} else {
|
||||
lj->args.append("/NODEFAULTLIB");
|
||||
Buf *msvcrt_lib_name = buf_sprintf("msvcrt%s.lib", d_str);
|
||||
lj->args.append(buf_ptr(msvcrt_lib_name));
|
||||
}
|
||||
|
||||
Buf *vcruntime_lib_name = buf_sprintf("%svcruntime%s.lib", lib_str, d_str);
|
||||
lj->args.append(buf_ptr(vcruntime_lib_name));
|
||||
|
||||
Buf *crt_lib_name = buf_sprintf("%sucrt%s.lib", lib_str, d_str);
|
||||
lj->args.append(buf_ptr(crt_lib_name));
|
||||
|
||||
//Visual C++ 2015 Conformance Changes
|
||||
//https://msdn.microsoft.com/en-us/library/bb531344.aspx
|
||||
lj->args.append("legacy_stdio_definitions.lib");
|
||||
|
||||
// msvcrt depends on kernel32 and ntdll
|
||||
lj->args.append("kernel32.lib");
|
||||
lj->args.append("ntdll.lib");
|
||||
}
|
||||
|
||||
static const char *get_libc_file(ZigLibCInstallation *lib, const char *file) {
|
||||
Buf *out_buf = buf_alloc();
|
||||
os_path_join(&lib->crt_dir, buf_create_from_str(file), out_buf);
|
||||
return buf_ptr(out_buf);
|
||||
}
|
||||
|
||||
static const char *get_libc_static_file(ZigLibCInstallation *lib, const char *file) {
|
||||
Buf *out_buf = buf_alloc();
|
||||
os_path_join(&lib->static_crt_dir, buf_create_from_str(file), out_buf);
|
||||
return buf_ptr(out_buf);
|
||||
}
|
||||
|
||||
static void add_mingw_link_args(LinkJob *lj, bool is_library) {
|
||||
CodeGen *g = lj->codegen;
|
||||
|
||||
bool is_dll = g->out_type == OutTypeLib && g->is_dynamic;
|
||||
|
||||
if (g->zig_target->arch == ZigLLVM_x86) {
|
||||
lj->args.append("-ALTERNATENAME:__image_base__=___ImageBase");
|
||||
} else {
|
||||
lj->args.append("-ALTERNATENAME:__image_base__=__ImageBase");
|
||||
}
|
||||
|
||||
if (is_dll) {
|
||||
lj->args.append(get_libc_file(g->libc, "dllcrt2.o"));
|
||||
} else {
|
||||
lj->args.append(get_libc_file(g->libc, "crt2.o"));
|
||||
}
|
||||
|
||||
lj->args.append(get_libc_static_file(g->libc, "crtbegin.o"));
|
||||
|
||||
lj->args.append(get_libc_file(g->libc, "libmingw32.a"));
|
||||
|
||||
if (is_dll) {
|
||||
lj->args.append(get_libc_static_file(g->libc, "libgcc_s.a"));
|
||||
lj->args.append(get_libc_static_file(g->libc, "libgcc.a"));
|
||||
} else {
|
||||
lj->args.append(get_libc_static_file(g->libc, "libgcc.a"));
|
||||
lj->args.append(get_libc_static_file(g->libc, "libgcc_eh.a"));
|
||||
}
|
||||
|
||||
lj->args.append(get_libc_static_file(g->libc, "libssp.a"));
|
||||
lj->args.append(get_libc_file(g->libc, "libmoldname.a"));
|
||||
lj->args.append(get_libc_file(g->libc, "libmingwex.a"));
|
||||
lj->args.append(get_libc_file(g->libc, "libmsvcrt.a"));
|
||||
|
||||
if (g->subsystem == TargetSubsystemWindows) {
|
||||
lj->args.append(get_libc_file(g->libc, "libgdi32.a"));
|
||||
lj->args.append(get_libc_file(g->libc, "libcomdlg32.a"));
|
||||
}
|
||||
|
||||
lj->args.append(get_libc_file(g->libc, "libadvapi32.a"));
|
||||
lj->args.append(get_libc_file(g->libc, "libadvapi32.a"));
|
||||
lj->args.append(get_libc_file(g->libc, "libshell32.a"));
|
||||
lj->args.append(get_libc_file(g->libc, "libuser32.a"));
|
||||
lj->args.append(get_libc_file(g->libc, "libkernel32.a"));
|
||||
|
||||
lj->args.append(get_libc_static_file(g->libc, "crtend.o"));
|
||||
}
|
||||
|
||||
static void add_win_link_args(LinkJob *lj, bool is_library) {
|
||||
if (lj->link_in_crt) {
|
||||
if (target_abi_is_gnu(lj->codegen->zig_target->abi)) {
|
||||
add_mingw_link_args(lj, is_library);
|
||||
} else {
|
||||
add_msvc_link_args(lj, is_library);
|
||||
}
|
||||
} else {
|
||||
lj->args.append("-NODEFAULTLIB");
|
||||
if (!is_library) {
|
||||
if (g->have_winmain) {
|
||||
lj->args.append("/ENTRY:WinMain");
|
||||
if (lj->codegen->have_winmain) {
|
||||
lj->args.append("-ENTRY:WinMain");
|
||||
} else {
|
||||
lj->args.append("/ENTRY:WinMainCRTStartup");
|
||||
lj->args.append("-ENTRY:WinMainCRTStartup");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1193,62 +1261,24 @@ static void construct_linker_job_coff(LinkJob *lj) {
|
|||
Error err;
|
||||
CodeGen *g = lj->codegen;
|
||||
|
||||
lj->args.append("/ERRORLIMIT:0");
|
||||
lj->args.append("-ERRORLIMIT:0");
|
||||
|
||||
lj->args.append("/NOLOGO");
|
||||
lj->args.append("-NOLOGO");
|
||||
|
||||
if (!g->strip_debug_symbols) {
|
||||
lj->args.append("/DEBUG");
|
||||
lj->args.append("-DEBUG");
|
||||
}
|
||||
|
||||
if (g->out_type == OutTypeExe) {
|
||||
// TODO compile time stack upper bound detection
|
||||
lj->args.append("/STACK:16777216");
|
||||
lj->args.append("-STACK:16777216");
|
||||
}
|
||||
|
||||
coff_append_machine_arg(g, &lj->args);
|
||||
|
||||
bool is_library = g->out_type == OutTypeLib;
|
||||
switch (g->subsystem) {
|
||||
case TargetSubsystemAuto:
|
||||
if (g->zig_target->os == OsUefi) {
|
||||
add_uefi_link_args(lj);
|
||||
} else {
|
||||
add_nt_link_args(lj, is_library);
|
||||
}
|
||||
break;
|
||||
case TargetSubsystemConsole:
|
||||
lj->args.append("/SUBSYSTEM:console");
|
||||
add_nt_link_args(lj, is_library);
|
||||
break;
|
||||
case TargetSubsystemEfiApplication:
|
||||
lj->args.append("/SUBSYSTEM:efi_application");
|
||||
add_uefi_link_args(lj);
|
||||
break;
|
||||
case TargetSubsystemEfiBootServiceDriver:
|
||||
lj->args.append("/SUBSYSTEM:efi_boot_service_driver");
|
||||
add_uefi_link_args(lj);
|
||||
break;
|
||||
case TargetSubsystemEfiRom:
|
||||
lj->args.append("/SUBSYSTEM:efi_rom");
|
||||
add_uefi_link_args(lj);
|
||||
break;
|
||||
case TargetSubsystemEfiRuntimeDriver:
|
||||
lj->args.append("/SUBSYSTEM:efi_runtime_driver");
|
||||
add_uefi_link_args(lj);
|
||||
break;
|
||||
case TargetSubsystemNative:
|
||||
lj->args.append("/SUBSYSTEM:native");
|
||||
add_nt_link_args(lj, is_library);
|
||||
break;
|
||||
case TargetSubsystemPosix:
|
||||
lj->args.append("/SUBSYSTEM:posix");
|
||||
add_nt_link_args(lj, is_library);
|
||||
break;
|
||||
case TargetSubsystemWindows:
|
||||
lj->args.append("/SUBSYSTEM:windows");
|
||||
add_nt_link_args(lj, is_library);
|
||||
break;
|
||||
if (is_library && g->is_dynamic) {
|
||||
lj->args.append("-DLL");
|
||||
}
|
||||
|
||||
lj->args.append(buf_ptr(buf_sprintf("-OUT:%s", buf_ptr(&g->output_file_path))));
|
||||
|
@ -1256,13 +1286,15 @@ static void construct_linker_job_coff(LinkJob *lj) {
|
|||
if (g->libc_link_lib != nullptr) {
|
||||
assert(g->libc != nullptr);
|
||||
|
||||
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->crt_dir))));
|
||||
}
|
||||
|
||||
if (is_library && g->is_dynamic) {
|
||||
lj->args.append("-DLL");
|
||||
if (target_abi_is_gnu(g->zig_target->abi)) {
|
||||
lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(&g->libc->sys_include_dir))));
|
||||
lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(&g->libc->include_dir))));
|
||||
} else {
|
||||
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))));
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < g->lib_dirs.length; i += 1) {
|
||||
|
@ -1274,6 +1306,48 @@ static void construct_linker_job_coff(LinkJob *lj) {
|
|||
lj->args.append((const char *)buf_ptr(g->link_objects.at(i)));
|
||||
}
|
||||
|
||||
switch (g->subsystem) {
|
||||
case TargetSubsystemAuto:
|
||||
if (g->zig_target->os == OsUefi) {
|
||||
add_uefi_link_args(lj);
|
||||
} else {
|
||||
add_win_link_args(lj, is_library);
|
||||
}
|
||||
break;
|
||||
case TargetSubsystemConsole:
|
||||
lj->args.append("-SUBSYSTEM:console");
|
||||
add_win_link_args(lj, is_library);
|
||||
break;
|
||||
case TargetSubsystemEfiApplication:
|
||||
lj->args.append("-SUBSYSTEM:efi_application");
|
||||
add_uefi_link_args(lj);
|
||||
break;
|
||||
case TargetSubsystemEfiBootServiceDriver:
|
||||
lj->args.append("-SUBSYSTEM:efi_boot_service_driver");
|
||||
add_uefi_link_args(lj);
|
||||
break;
|
||||
case TargetSubsystemEfiRom:
|
||||
lj->args.append("-SUBSYSTEM:efi_rom");
|
||||
add_uefi_link_args(lj);
|
||||
break;
|
||||
case TargetSubsystemEfiRuntimeDriver:
|
||||
lj->args.append("-SUBSYSTEM:efi_runtime_driver");
|
||||
add_uefi_link_args(lj);
|
||||
break;
|
||||
case TargetSubsystemNative:
|
||||
lj->args.append("-SUBSYSTEM:native");
|
||||
add_win_link_args(lj, is_library);
|
||||
break;
|
||||
case TargetSubsystemPosix:
|
||||
lj->args.append("-SUBSYSTEM:posix");
|
||||
add_win_link_args(lj, is_library);
|
||||
break;
|
||||
case TargetSubsystemWindows:
|
||||
lj->args.append("-SUBSYSTEM:windows");
|
||||
add_win_link_args(lj, is_library);
|
||||
break;
|
||||
}
|
||||
|
||||
if (g->out_type == OutTypeExe || (g->out_type == OutTypeLib && g->is_dynamic)) {
|
||||
if (g->libc_link_lib == nullptr && !g->is_dummy_so) {
|
||||
Buf *builtin_a_path = build_a(g, "builtin");
|
||||
|
@ -1293,11 +1367,10 @@ static void construct_linker_job_coff(LinkJob *lj) {
|
|||
continue;
|
||||
}
|
||||
if (link_lib->provided_explicitly) {
|
||||
if (lj->codegen->zig_target->abi == ZigLLVM_GNU) {
|
||||
Buf *arg = buf_sprintf("-l%s", buf_ptr(link_lib->name));
|
||||
lj->args.append(buf_ptr(arg));
|
||||
}
|
||||
else {
|
||||
if (target_abi_is_gnu(lj->codegen->zig_target->abi)) {
|
||||
Buf *lib_name = buf_sprintf("lib%s.a", buf_ptr(link_lib->name));
|
||||
lj->args.append(buf_ptr(lib_name));
|
||||
} else {
|
||||
lj->args.append(buf_ptr(link_lib->name));
|
||||
}
|
||||
} else {
|
||||
|
|
Loading…
Reference in New Issue