Commit b01c50d6fa
Changed files (9)
src/analyze.cpp
@@ -4285,24 +4285,117 @@ static ZigWindowsSDK *get_windows_sdk(CodeGen *g) {
return g->win_sdk;
}
+
+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();
+ int 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;
+}
+
+Buf *get_linux_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();
+ int 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 = {};
+ bool found_search_paths = false;
+ for (;;) {
+ char *newline = strchr(prev_newline, '\n');
+ if (newline == nullptr) {
+ zig_panic("unable to determine libc include path: bad output from C compiler command");
+ }
+ *newline = 0;
+ if (found_search_paths) {
+ if (strcmp(prev_newline, "End of search list.") == 0) {
+ break;
+ }
+ search_paths.append(prev_newline);
+ } else {
+ if (strcmp(prev_newline, "#include <...> search starts here:") == 0) {
+ found_search_paths = true;
+ }
+ }
+ 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 || buf_len(g->libc_include_dir) == 0) {
+ if (g->libc_include_dir == nullptr) {
if (g->zig_target.os == OsWindows) {
ZigWindowsSDK *sdk = get_windows_sdk(g);
if (os_get_win32_ucrt_include_path(sdk, g->libc_include_dir)) {
zig_panic("Unable to determine libc include path.");
}
+ } else if (g->zig_target.os == OsLinux) {
+ g->libc_include_dir = get_linux_libc_include_path();
+ } else if (g->zig_target.os == OsMacOSX) {
+ g->libc_include_dir = buf_create_from_str("/usr/include");
+ } else {
+ // TODO find libc at runtime for other operating systems
+ zig_panic("Unable to determine libc include path.");
}
-
- // TODO find libc at runtime for other operating systems
- zig_panic("Unable to determine libc include path.");
}
+ 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 || buf_len(g->libc_lib_dir) == 0 ||
+ 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) {
@@ -4326,18 +4419,25 @@ void find_libc_lib_path(CodeGen *g) {
g->msvc_lib_dir = vc_lib_dir;
g->libc_lib_dir = ucrt_lib_path;
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 {
zig_panic("Unable to determine libc lib path.");
}
+ } else {
+ assert(buf_len(g->libc_lib_dir) != 0);
}
- if (!g->libc_static_lib_dir || buf_len(g->libc_static_lib_dir) == 0) {
+ if (g->libc_static_lib_dir == nullptr) {
if ((g->zig_target.os == OsWindows) && (g->msvc_lib_dir != NULL)) {
return;
- }
- else {
+ } else if (g->zig_target.os == OsLinux) {
+ g->libc_static_lib_dir = get_linux_libc_lib_path("crtbegin.o");
+ } else {
zig_panic("Unable to determine libc static lib path.");
}
+ } else {
+ assert(buf_len(g->libc_static_lib_dir) != 0);
}
}
src/codegen.cpp
@@ -112,10 +112,10 @@ CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out
// that's for native compilation
g->zig_target = *target;
resolve_target_object_format(&g->zig_target);
- g->dynamic_linker = buf_create_from_str("");
- g->libc_lib_dir = buf_create_from_str("");
- g->libc_static_lib_dir = buf_create_from_str("");
- g->libc_include_dir = buf_create_from_str("");
+ 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;
g->each_lib_rpath = false;
@@ -123,16 +123,13 @@ CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out
// native compilation, we can rely on the configuration stuff
g->is_native_target = true;
get_native_target(&g->zig_target);
- g->dynamic_linker = buf_create_from_str(ZIG_DYNAMIC_LINKER);
- g->libc_lib_dir = buf_create_from_str(ZIG_LIBC_LIB_DIR);
- g->libc_static_lib_dir = buf_create_from_str(ZIG_LIBC_STATIC_LIB_DIR);
- g->libc_include_dir = buf_create_from_str(ZIG_LIBC_INCLUDE_DIR);
+ 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
-
-#ifdef ZIG_EACH_LIB_RPATH
g->each_lib_rpath = true;
-#endif
if (g->zig_target.os == OsMacOSX ||
g->zig_target.os == OsIOS)
src/config.h.in
@@ -13,14 +13,6 @@
#define ZIG_VERSION_PATCH @ZIG_VERSION_PATCH@
#define ZIG_VERSION_STRING "@ZIG_VERSION@"
-#define ZIG_INSTALL_PREFIX "@CMAKE_INSTALL_PREFIX@"
-#define ZIG_LIBC_INCLUDE_DIR "@ZIG_LIBC_INCLUDE_DIR_ESCAPED@"
-#define ZIG_LIBC_LIB_DIR "@ZIG_LIBC_LIB_DIR_ESCAPED@"
-#define ZIG_LIBC_STATIC_LIB_DIR "@ZIG_LIBC_STATIC_LIB_DIR_ESCAPED@"
-#define ZIG_DYNAMIC_LINKER "@ZIG_DYNAMIC_LINKER@"
-
-#cmakedefine ZIG_EACH_LIB_RPATH
-
// Only used for running tests before installing.
#define ZIG_TEST_DIR "@CMAKE_SOURCE_DIR@/test"
src/link.cpp
@@ -164,6 +164,34 @@ static void add_rpath(LinkJob *lj, Buf *rpath) {
lj->rpath_table.put(rpath, true);
}
+static Buf *get_dynamic_linker_path(CodeGen *g) {
+ if (g->is_native_target && g->zig_target.arch.arch == ZigLLVM_x86_64) {
+ const char *cc_exe = getenv("CC");
+ cc_exe = (cc_exe == nullptr) ? "cc" : cc_exe;
+ ZigList<const char *> args = {};
+ args.append("-print-file-name=ld-linux-x86-64.so.2");
+ 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 target_dynamic_linker(&g->zig_target);
+ }
+ if (term.how != TerminationIdClean || term.code != 0) {
+ return target_dynamic_linker(&g->zig_target);
+ }
+ 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-linux-x86-64.so.2")) {
+ return target_dynamic_linker(&g->zig_target);
+ }
+ return out_stdout;
+ } else {
+ return target_dynamic_linker(&g->zig_target);
+ }
+}
+
static void construct_linker_job_elf(LinkJob *lj) {
CodeGen *g = lj->codegen;
@@ -259,12 +287,16 @@ static void construct_linker_job_elf(LinkJob *lj) {
lj->args.append(buf_ptr(g->libc_static_lib_dir));
}
- if (g->dynamic_linker && buf_len(g->dynamic_linker) > 0) {
- lj->args.append("-dynamic-linker");
- lj->args.append(buf_ptr(g->dynamic_linker));
- } else {
- lj->args.append("-dynamic-linker");
- lj->args.append(buf_ptr(target_dynamic_linker(&g->zig_target)));
+ if (!g->is_static) {
+ if (g->dynamic_linker != nullptr) {
+ assert(buf_len(g->dynamic_linker) != 0);
+ lj->args.append("-dynamic-linker");
+ lj->args.append(buf_ptr(g->dynamic_linker));
+ } else {
+ Buf *resolved_dynamic_linker = get_dynamic_linker_path(g);
+ lj->args.append("-dynamic-linker");
+ lj->args.append(buf_ptr(resolved_dynamic_linker));
+ }
}
if (shared) {
src/main.cpp
@@ -195,13 +195,6 @@ static int find_zig_lib_dir(Buf *out_path) {
}
}
- if (ZIG_INSTALL_PREFIX != nullptr) {
- if (test_zig_install_prefix(buf_create_from_str(ZIG_INSTALL_PREFIX), out_path)) {
- return 0;
- }
- }
-
-
return ErrorFileNotFound;
}
src/os.cpp
@@ -57,10 +57,6 @@ static clock_serv_t cclock;
#include <errno.h>
#include <time.h>
-// these implementations are lazy. But who cares, we'll make a robust
-// implementation in the zig standard library and then this code all gets
-// deleted when we self-host. it works for now.
-
#if defined(ZIG_OS_POSIX)
static void populate_termination(Termination *term, int status) {
if (WIFEXITED(status)) {
@@ -929,7 +925,18 @@ int os_self_exe_path(Buf *out_path) {
#elif defined(ZIG_OS_DARWIN)
return ErrorFileNotFound;
#elif defined(ZIG_OS_LINUX)
- return ErrorFileNotFound;
+ buf_resize(out_path, 256);
+ for (;;) {
+ ssize_t amt = readlink("/proc/self/exe", buf_ptr(out_path), buf_len(out_path));
+ if (amt == -1) {
+ return ErrorUnexpected;
+ }
+ if (amt == (ssize_t)buf_len(out_path)) {
+ buf_resize(out_path, buf_len(out_path) * 2);
+ continue;
+ }
+ return 0;
+ }
#endif
return ErrorFileNotFound;
}
src/target.cpp
@@ -863,6 +863,10 @@ Buf *target_dynamic_linker(ZigTarget *target) {
env == ZigLLVM_GNUX32)
{
return buf_create_from_str("/libx32/ld-linux-x32.so.2");
+ } else if (arch == ZigLLVM_x86_64 &&
+ (env == ZigLLVM_Musl || env == ZigLLVM_MuslEABI || env == ZigLLVM_MuslEABIHF))
+ {
+ return buf_create_from_str("/lib/ld-musl-x86_64.so.1");
} else {
return buf_create_from_str("/lib64/ld-linux-x86-64.so.2");
}
CMakeLists.txt
@@ -30,11 +30,6 @@ if(GIT_EXE)
endif()
message("Configuring zig version ${ZIG_VERSION}")
-set(ZIG_LIBC_LIB_DIR "" CACHE STRING "Default native target libc directory where crt1.o can be found")
-set(ZIG_LIBC_STATIC_LIB_DIR "" CACHE STRING "Default native target libc directory where crtbeginT.o can be found")
-set(ZIG_LIBC_INCLUDE_DIR "/usr/include" CACHE STRING "Default native target libc include directory")
-set(ZIG_DYNAMIC_LINKER "" CACHE STRING "Override dynamic linker for native target")
-set(ZIG_EACH_LIB_RPATH off CACHE BOOL "Add each dynamic library to rpath for native target")
set(ZIG_STATIC off CACHE BOOL "Attempt to build a static zig executable (not compatible with glibc)")
string(REGEX REPLACE "\\\\" "\\\\\\\\" ZIG_LIBC_LIB_DIR_ESCAPED "${ZIG_LIBC_LIB_DIR}")
README.md
@@ -138,14 +138,10 @@ libc. Create demo games using Zig.
##### POSIX
-If you have gcc or clang installed, you can find out what `ZIG_LIBC_LIB_DIR`,
-`ZIG_LIBC_STATIC_LIB_DIR`, and `ZIG_LIBC_INCLUDE_DIR` should be set to
-(example below).
-
```
mkdir build
cd build
-cmake .. -DCMAKE_INSTALL_PREFIX=$(pwd) -DZIG_LIBC_LIB_DIR=$(dirname $(cc -print-file-name=crt1.o)) -DZIG_LIBC_INCLUDE_DIR=$(echo -n | cc -E -x c - -v 2>&1 | grep -B1 "End of search list." | head -n1 | cut -c 2- | sed "s/ .*//") -DZIG_LIBC_STATIC_LIB_DIR=$(dirname $(cc -print-file-name=crtbegin.o))
+cmake .. -DCMAKE_INSTALL_PREFIX=$(pwd)
make
make install
./zig build --build-file ../build.zig test
@@ -153,8 +149,6 @@ make install
##### MacOS
-`ZIG_LIBC_LIB_DIR` and `ZIG_LIBC_STATIC_LIB_DIR` are unused.
-
```
brew install cmake llvm@6
brew outdated llvm@6 || brew upgrade llvm@6