Commit 1962c8588f

Andrew Kelley <superjoe30@gmail.com>
2017-10-02 00:29:50
implement standard library path search
closes #463 See #302
1 parent 9636603
src/all_types.hpp
@@ -1456,7 +1456,9 @@ struct CodeGen {
     Buf *libc_lib_dir;
     Buf *libc_static_lib_dir;
     Buf *libc_include_dir;
+    Buf *zig_lib_dir;
     Buf *zig_std_dir;
+    Buf *zig_c_headers_dir;
     Buf *zig_std_special_dir;
     Buf *dynamic_linker;
     Buf *ar_path;
src/codegen.cpp
@@ -56,13 +56,20 @@ static PackageTableEntry *new_package(const char *root_src_dir, const char *root
 }
 
 CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out_type, BuildMode build_mode,
-    Buf *zig_std_dir)
+    Buf *zig_lib_dir)
 {
     CodeGen *g = allocate<CodeGen>(1);
 
     codegen_add_time_event(g, "Initialize");
 
-    g->zig_std_dir = zig_std_dir;
+    g->zig_lib_dir = zig_lib_dir;
+
+    g->zig_std_dir = buf_alloc();
+    os_path_join(zig_lib_dir, buf_create_from_str("std"), g->zig_std_dir);
+
+    g->zig_c_headers_dir = buf_alloc();
+    os_path_join(zig_lib_dir, buf_create_from_str("include"), g->zig_c_headers_dir);
+
     g->build_mode = build_mode;
     g->out_type = out_type;
     g->import_table.init(32);
src/codegen.hpp
@@ -15,7 +15,7 @@
 #include <stdio.h>
 
 CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out_type, BuildMode build_mode,
-    Buf *zig_std_dir);
+    Buf *zig_lib_dir);
 
 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);
src/config.h.in
@@ -13,8 +13,7 @@
 #define ZIG_VERSION_PATCH @ZIG_VERSION_PATCH@
 #define ZIG_VERSION_STRING "@ZIG_VERSION@"
 
-#define ZIG_HEADERS_DIR "@CMAKE_INSTALL_PREFIX@/@C_HEADERS_DEST@"
-#define ZIG_STD_DIR "@CMAKE_INSTALL_PREFIX@/@ZIG_STD_DEST@"
+#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@"
src/link.cpp
@@ -34,7 +34,7 @@ static const char *get_libc_static_file(CodeGen *g, const char *file) {
 static Buf *build_o_raw(CodeGen *parent_gen, const char *oname, Buf *full_path) {
     ZigTarget *child_target = parent_gen->is_native_target ? nullptr : &parent_gen->zig_target;
     CodeGen *child_gen = codegen_create(full_path, child_target, OutTypeObj, parent_gen->build_mode,
-        parent_gen->zig_std_dir);
+        parent_gen->zig_lib_dir);
 
     child_gen->want_h_file = false;
     child_gen->verbose_link = parent_gen->verbose_link;
src/main.cpp
@@ -49,7 +49,7 @@ static int usage(const char *arg0) {
         "  --verbose                    turn on compiler debug output\n"
         "  --verbose-link               turn on compiler debug output for linking only\n"
         "  --verbose-ir                 turn on compiler debug output for IR only\n"
-        "  --zig-std-dir [path]         directory where zig standard library resides\n"
+        "  --zig-install-prefix [path]  override directory where zig thinks it is installed\n"
         "  -dirafter [dir]              same as -isystem but do it last\n"
         "  -isystem [dir]               add additional search path for other .h files\n"
         "  -mllvm [arg]                 additional arguments to forward to LLVM's option processing\n"
@@ -131,6 +131,93 @@ static int print_target_list(FILE *f) {
     return EXIT_SUCCESS;
 }
 
+static bool test_zig_install_prefix(Buf *test_path, Buf *out_zig_lib_dir) {
+    Buf lib_buf = BUF_INIT;
+    buf_init_from_str(&lib_buf, "lib");
+
+    Buf zig_buf = BUF_INIT;
+    buf_init_from_str(&zig_buf, "zig");
+
+    Buf std_buf = BUF_INIT;
+    buf_init_from_str(&std_buf, "std");
+
+    Buf index_zig_buf = BUF_INIT;
+    buf_init_from_str(&index_zig_buf, "index.zig");
+
+    Buf test_lib_dir = BUF_INIT;
+    Buf test_zig_dir = BUF_INIT;
+    Buf test_std_dir = BUF_INIT;
+    Buf test_index_file = BUF_INIT;
+
+    os_path_join(test_path, &lib_buf, &test_lib_dir);
+    os_path_join(&test_lib_dir, &zig_buf, &test_zig_dir);
+    os_path_join(&test_zig_dir, &std_buf, &test_std_dir);
+    os_path_join(&test_std_dir, &index_zig_buf, &test_index_file);
+
+    int err;
+    bool exists;
+    if ((err = os_file_exists(&test_index_file, &exists))) {
+        exists = false;
+    }
+    if (exists) {
+        buf_init_from_buf(out_zig_lib_dir, &test_zig_dir);
+        return true;
+    }
+    return false;
+}
+
+static int find_zig_lib_dir(Buf *out_path) {
+    int err;
+
+    Buf self_exe_path = BUF_INIT;
+    if (!(err = os_self_exe_path(&self_exe_path))) {
+        Buf *cur_path = &self_exe_path;
+
+        for (;;) {
+            Buf *test_dir = buf_alloc();
+            os_path_dirname(cur_path, test_dir);
+
+            if (buf_eql_buf(test_dir, cur_path)) {
+                break;
+            }
+
+            if (test_zig_install_prefix(test_dir, out_path)) {
+                return 0;
+            }
+
+            cur_path = test_dir;
+        }
+    }
+
+    if (ZIG_INSTALL_PREFIX != nullptr) {
+        if (test_zig_install_prefix(buf_create_from_str(ZIG_INSTALL_PREFIX), out_path)) {
+            return 0;
+        }
+    }
+
+
+    return ErrorFileNotFound;
+}
+
+static Buf *resolve_zig_lib_dir(const char *zig_install_prefix_arg) {
+    int err;
+    Buf *result = buf_alloc();
+    if (zig_install_prefix_arg == nullptr) {
+        if ((err = find_zig_lib_dir(result))) {
+            fprintf(stderr, "Unable to find zig lib directory. Reinstall Zig or use --zig-install-prefix.\n");
+            exit(EXIT_FAILURE);
+        }
+        return result;
+    }
+    Buf *zig_lib_dir_buf = buf_create_from_str(zig_install_prefix_arg);
+    if (test_zig_install_prefix(zig_lib_dir_buf, result)) {
+        return result;
+    }
+
+    fprintf(stderr, "No Zig installation found at prefix: %s\n", zig_install_prefix_arg);
+    exit(EXIT_FAILURE);
+}
+
 enum Cmd {
     CmdInvalid,
     CmdBuild,
@@ -192,7 +279,7 @@ int main(int argc, char **argv) {
     const char *libc_lib_dir = nullptr;
     const char *libc_static_lib_dir = nullptr;
     const char *libc_include_dir = nullptr;
-    const char *zig_std_dir = nullptr;
+    const char *zig_install_prefix = nullptr;
     const char *dynamic_linker = nullptr;
     ZigList<const char *> clang_argv = {0};
     ZigList<const char *> llvm_argv = {0};
@@ -248,29 +335,26 @@ int main(int argc, char **argv) {
             } else if (i + 1 < argc && strcmp(argv[i], "--cache-dir") == 0) {
                 cache_dir = argv[i + 1];
                 i += 1;
-            } else if (i + 1 < argc && strcmp(argv[i], "--zig-std-dir") == 0) {
+            } else if (i + 1 < argc && strcmp(argv[i], "--zig-install-prefix") == 0) {
                 args.append(argv[i]);
                 i += 1;
-                zig_std_dir = argv[i];
-                args.append(zig_std_dir);
+                zig_install_prefix = argv[i];
+                args.append(zig_install_prefix);
             } else {
                 args.append(argv[i]);
             }
         }
 
-        if (zig_std_dir == nullptr) {
-            zig_std_dir = ZIG_STD_DIR;
-        }
-        Buf *zig_std_dir_buf = buf_create_from_str(zig_std_dir);
+        Buf *zig_lib_dir_buf = resolve_zig_lib_dir(zig_install_prefix);
 
         Buf *special_dir = buf_alloc();
-        os_path_join(zig_std_dir_buf, buf_sprintf("special"), special_dir);
+        os_path_join(zig_lib_dir_buf, buf_sprintf("special"), special_dir);
 
         Buf *build_runner_path = buf_alloc();
         os_path_join(special_dir, buf_create_from_str("build_runner.zig"), build_runner_path);
 
 
-        CodeGen *g = codegen_create(build_runner_path, nullptr, OutTypeExe, BuildModeDebug, zig_std_dir_buf);
+        CodeGen *g = codegen_create(build_runner_path, nullptr, OutTypeExe, BuildModeDebug, zig_lib_dir_buf);
         codegen_set_out_name(g, buf_create_from_str("build"));
         codegen_set_verbose(g, verbose);
 
@@ -430,8 +514,8 @@ int main(int argc, char **argv) {
                     libc_static_lib_dir = argv[i];
                 } else if (strcmp(arg, "--libc-include-dir") == 0) {
                     libc_include_dir = argv[i];
-                } else if (strcmp(arg, "--zig-std-dir") == 0) {
-                    zig_std_dir = argv[i];
+                } else if (strcmp(arg, "--zig-install-prefix") == 0) {
+                    zig_install_prefix = argv[i];
                 } else if (strcmp(arg, "--dynamic-linker") == 0) {
                     dynamic_linker = argv[i];
                 } else if (strcmp(arg, "-isystem") == 0) {
@@ -619,12 +703,9 @@ int main(int argc, char **argv) {
                     buf_create_from_str((cache_dir == nullptr) ? default_zig_cache_name : cache_dir),
                     full_cache_dir);
 
-            if (zig_std_dir == nullptr) {
-                zig_std_dir = ZIG_STD_DIR;
-            }
+            Buf *zig_lib_dir_buf = resolve_zig_lib_dir(zig_install_prefix);
 
-            CodeGen *g = codegen_create(zig_root_source_file, target, out_type, build_mode,
-                buf_create_from_str(zig_std_dir));
+            CodeGen *g = codegen_create(zig_root_source_file, target, out_type, build_mode, zig_lib_dir_buf);
             codegen_set_out_name(g, buf_out_name);
             codegen_set_lib_version(g, ver_major, ver_minor, ver_patch);
             codegen_set_is_test(g, cmd == CmdTest);
src/os.cpp
@@ -312,11 +312,12 @@ int os_fetch_file(FILE *f, Buf *out_buf) {
 }
 
 int os_file_exists(Buf *full_path, bool *result) {
-#if defined(ZIG_OS_POSIX)
-    *result = access(buf_ptr(full_path), F_OK) != -1;
+#if defined(ZIG_OS_WINDOWS)
+    *result = GetFileAttributes(buf_ptr(full_path)) != INVALID_FILE_ATTRIBUTES;
     return 0;
 #else
-    return GetFileAttributes(buf_ptr(full_path)) != INVALID_FILE_ATTRIBUTES;
+    *result = access(buf_ptr(full_path), F_OK) != -1;
+    return 0;
 #endif
 }
 
@@ -835,3 +836,26 @@ int os_init(void) {
 #endif
     return 0;
 }
+
+int os_self_exe_path(Buf *out_path) {
+#if defined(ZIG_OS_WINDOWS)
+    buf_resize(out_path, 256);
+    for (;;) {
+        DWORD copied_amt = GetModuleFileName(nullptr, buf_ptr(out_path), buf_len(out_path));
+        if (copied_amt <= 0) {
+            return ErrorFileNotFound;
+        }
+        if (copied_amt < buf_len(out_path)) {
+            buf_resize(out_path, copied_amt);
+            return 0;
+        }
+        buf_resize(out_path, buf_len(out_path) * 2);
+    }
+
+#elif defined(ZIG_OS_DARWIN)
+    return ErrorFileNotFound;
+#elif defined(ZIG_OS_LINUX)
+    return ErrorFileNotFound;
+#endif
+    return ErrorFileNotFound;
+}
src/os.hpp
@@ -64,6 +64,8 @@ double os_get_time(void);
 
 bool os_is_sep(uint8_t c);
 
+int os_self_exe_path(Buf *out_path);
+
 #if defined(__APPLE__)
 #define ZIG_OS_DARWIN
 #elif defined(_WIN32)
src/parsec.cpp
@@ -8,7 +8,6 @@
 #include "all_types.hpp"
 #include "analyze.hpp"
 #include "c_tokenizer.hpp"
-#include "config.h"
 #include "error.hpp"
 #include "ir.hpp"
 #include "os.hpp"
@@ -3206,7 +3205,7 @@ int parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const ch
     }
 
     clang_argv.append("-isystem");
-    clang_argv.append(ZIG_HEADERS_DIR);
+    clang_argv.append(buf_ptr(codegen->zig_c_headers_dir));
 
     clang_argv.append("-isystem");
     clang_argv.append(buf_ptr(codegen->libc_include_dir));
@@ -3244,7 +3243,7 @@ int parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const ch
     bool allow_pch_with_compiler_errors = false;
     bool single_file_parse = false;
     bool for_serialization = false;
-    const char *resources_path = ZIG_HEADERS_DIR;
+    const char *resources_path = buf_ptr(codegen->zig_c_headers_dir);
     std::unique_ptr<ASTUnit> err_unit;
     std::unique_ptr<ASTUnit> ast_unit(ASTUnit::LoadFromCommandLine(
             &clang_argv.at(0), &clang_argv.last(),
CMakeLists.txt
@@ -327,8 +327,9 @@ set(ZIG_SOURCES
     "${CMAKE_SOURCE_DIR}/src/zig_llvm.cpp"
 )
 
-set(C_HEADERS_DEST "lib/zig/include")
-set(ZIG_STD_DEST "lib/zig/std")
+set(ZIG_LIB_DIR "lib/zig")
+set(C_HEADERS_DEST "${ZIG_LIB_DIR}/include")
+set(ZIG_STD_DEST "${ZIG_LIB_DIR}/std")
 set(CONFIGURE_OUT_FILE "${CMAKE_BINARY_DIR}/config.h")
 configure_file (
     "${CMAKE_SOURCE_DIR}/src/config.h.in"