From 1962c8588f03f510c100d318472505315acaf3b2 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sun, 1 Oct 2017 18:29:50 -0400 Subject: [PATCH] implement standard library path search closes #463 See #302 --- CMakeLists.txt | 5 +- src/all_types.hpp | 2 + src/codegen.cpp | 11 ++++- src/codegen.hpp | 2 +- src/config.h.in | 3 +- src/link.cpp | 2 +- src/main.cpp | 117 +++++++++++++++++++++++++++++++++++++++------- src/os.cpp | 30 ++++++++++-- src/os.hpp | 2 + src/parsec.cpp | 5 +- 10 files changed, 147 insertions(+), 32 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f8a45af9dd..74540f81df 100644 --- a/CMakeLists.txt +++ b/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" diff --git a/src/all_types.hpp b/src/all_types.hpp index aefaa736cf..05df479beb 100644 --- a/src/all_types.hpp +++ b/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; diff --git a/src/codegen.cpp b/src/codegen.cpp index e31b318dcc..f0826e3c49 100644 --- a/src/codegen.cpp +++ b/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(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); diff --git a/src/codegen.hpp b/src/codegen.hpp index 91418b1fc9..824b82feb9 100644 --- a/src/codegen.hpp +++ b/src/codegen.hpp @@ -15,7 +15,7 @@ #include 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); diff --git a/src/config.h.in b/src/config.h.in index 6aa3312d7f..36bd66098b 100644 --- a/src/config.h.in +++ b/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@" diff --git a/src/link.cpp b/src/link.cpp index 90862bde8d..4327b5f8cf 100644 --- a/src/link.cpp +++ b/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; diff --git a/src/main.cpp b/src/main.cpp index 962a2e6b30..65ca7deadf 100644 --- a/src/main.cpp +++ b/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 clang_argv = {0}; ZigList 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); diff --git a/src/os.cpp b/src/os.cpp index f7d055b6ce..5f884485db 100644 --- a/src/os.cpp +++ b/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; +} diff --git a/src/os.hpp b/src/os.hpp index 44dd361d17..da106c4377 100644 --- a/src/os.hpp +++ b/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) diff --git a/src/parsec.cpp b/src/parsec.cpp index b389400f58..9ebd99c712 100644 --- a/src/parsec.cpp +++ b/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 *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 *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 err_unit; std::unique_ptr ast_unit(ASTUnit::LoadFromCommandLine( &clang_argv.at(0), &clang_argv.last(),