| author | |
| committer | |
| log | 7efa2cd81cef69d071982cfaa6953d6b9d4a1c95 |
| tree | 36bb2eca682dffbd285e1eda0a63f6e673a061f0 |
| parent | d10bbd28e9576d000f04ac6d06c2a8493ffc72ef |
This adds an rpath entry for each used dynamic library directory.
This is necessary on some systems such as NixOS.9 files changed, 61 insertions(+), 4 deletions(-)
CMakeLists.txt+1| ... | ... | @@ -18,6 +18,7 @@ set(ZIG_LIBC_LIB_DIR "" CACHE STRING "Default native target libc directory where |
| 18 | 18 | set(ZIG_LIBC_STATIC_LIB_DIR "" CACHE STRING "Default native target libc directory where crtbeginT.o can be found") |
| 19 | 19 | set(ZIG_LIBC_INCLUDE_DIR "/usr/include" CACHE STRING "Default native target libc include directory") |
| 20 | 20 | set(ZIG_DYNAMIC_LINKER "" CACHE STRING "Override dynamic linker for native target") |
| 21 | set(ZIG_EACH_LIB_RPATH off CACHE BOOL "Add each dynamic library to rpath for native target") | |
| 21 | 22 | |
| 22 | 23 | option(ZIG_TEST_COVERAGE "Build Zig with test coverage instrumentation" OFF) |
| 23 | 24 |
src/all_types.hpp+1| ... | ... | @@ -1413,6 +1413,7 @@ struct CodeGen { |
| 1413 | 1413 | uint32_t test_fn_count; |
| 1414 | 1414 | |
| 1415 | 1415 | bool check_unused; |
| 1416 | bool each_lib_rpath; | |
| 1416 | 1417 | |
| 1417 | 1418 | ZigList<AstNode *> error_decls; |
| 1418 | 1419 | bool generate_error_name_table; |
src/codegen.cpp+8| ... | ... | @@ -90,6 +90,7 @@ CodeGen *codegen_create(Buf *root_source_dir, const ZigTarget *target) { |
| 90 | 90 | g->libc_static_lib_dir = buf_create_from_str(""); |
| 91 | 91 | g->libc_include_dir = buf_create_from_str(""); |
| 92 | 92 | g->darwin_linker_version = buf_create_from_str(""); |
| 93 | g->each_lib_rpath = false; | |
| 93 | 94 | } else { |
| 94 | 95 | // native compilation, we can rely on the configuration stuff |
| 95 | 96 | g->is_native_target = true; |
| ... | ... | @@ -100,6 +101,9 @@ CodeGen *codegen_create(Buf *root_source_dir, const ZigTarget *target) { |
| 100 | 101 | g->libc_static_lib_dir = buf_create_from_str(ZIG_LIBC_STATIC_LIB_DIR); |
| 101 | 102 | g->libc_include_dir = buf_create_from_str(ZIG_LIBC_INCLUDE_DIR); |
| 102 | 103 | g->darwin_linker_version = buf_create_from_str(ZIG_HOST_LINK_VERSION); |
| 104 | #ifdef ZIG_EACH_LIB_RPATH | |
| 105 | g->each_lib_rpath = true; | |
| 106 | #endif | |
| 103 | 107 | |
| 104 | 108 | if (g->zig_target.os == ZigLLVM_Darwin || |
| 105 | 109 | g->zig_target.os == ZigLLVM_MacOSX || |
| ... | ... | @@ -138,6 +142,10 @@ void codegen_set_check_unused(CodeGen *g, bool check_unused) { |
| 138 | 142 | g->check_unused = check_unused; |
| 139 | 143 | } |
| 140 | 144 | |
| 145 | void codegen_set_each_lib_rpath(CodeGen *g, bool each_lib_rpath) { | |
| 146 | g->each_lib_rpath = each_lib_rpath; | |
| 147 | } | |
| 148 | ||
| 141 | 149 | void codegen_set_errmsg_color(CodeGen *g, ErrColor err_color) { |
| 142 | 150 | g->err_color = err_color; |
| 143 | 151 | } |
src/codegen.hpp+1| ... | ... | @@ -20,6 +20,7 @@ void codegen_set_clang_argv(CodeGen *codegen, const char **args, size_t len); |
| 20 | 20 | void codegen_set_is_release(CodeGen *codegen, bool is_release); |
| 21 | 21 | void codegen_set_is_test(CodeGen *codegen, bool is_test); |
| 22 | 22 | void codegen_set_check_unused(CodeGen *codegen, bool check_unused); |
| 23 | void codegen_set_each_lib_rpath(CodeGen *codegen, bool each_lib_rpath); | |
| 23 | 24 | |
| 24 | 25 | void codegen_set_is_static(CodeGen *codegen, bool is_static); |
| 25 | 26 | void codegen_set_strip(CodeGen *codegen, bool strip); |
src/config.h.in+1| ... | ... | @@ -21,6 +21,7 @@ |
| 21 | 21 | #define ZIG_DYNAMIC_LINKER "@ZIG_DYNAMIC_LINKER@" |
| 22 | 22 | #define ZIG_HOST_LINK_VERSION "@ZIG_HOST_LINK_VERSION@" |
| 23 | 23 | |
| 24 | #cmakedefine ZIG_EACH_LIB_RPATH | |
| 24 | 25 | #cmakedefine ZIG_LLVM_OLD_CXX_ABI |
| 25 | 26 | |
| 26 | 27 | // Only used for running tests before installing. |
src/link.cpp+30-2| ... | ... | @@ -17,6 +17,7 @@ struct LinkJob { |
| 17 | 17 | ZigList<const char *> args; |
| 18 | 18 | bool link_in_crt; |
| 19 | 19 | Buf out_file_o; |
| 20 | HashMap<Buf *, bool, buf_hash, buf_eql_buf> rpath_table; | |
| 20 | 21 | }; |
| 21 | 22 | |
| 22 | 23 | static const char *get_libc_file(CodeGen *g, const char *file) { |
| ... | ... | @@ -148,6 +149,16 @@ static const char *getLDMOption(const ZigTarget *t) { |
| 148 | 149 | } |
| 149 | 150 | } |
| 150 | 151 | |
| 152 | static void add_rpath(LinkJob *lj, Buf *rpath) { | |
| 153 | if (lj->rpath_table.maybe_get(rpath) != nullptr) | |
| 154 | return; | |
| 155 | ||
| 156 | lj->args.append("-rpath"); | |
| 157 | lj->args.append(buf_ptr(rpath)); | |
| 158 | ||
| 159 | lj->rpath_table.put(rpath, true); | |
| 160 | } | |
| 161 | ||
| 151 | 162 | static void construct_linker_job_elf(LinkJob *lj) { |
| 152 | 163 | CodeGen *g = lj->codegen; |
| 153 | 164 | |
| ... | ... | @@ -205,8 +216,24 @@ static void construct_linker_job_elf(LinkJob *lj) { |
| 205 | 216 | |
| 206 | 217 | for (size_t i = 0; i < g->rpath_list.length; i += 1) { |
| 207 | 218 | Buf *rpath = g->rpath_list.at(i); |
| 208 | lj->args.append("-rpath"); | |
| 209 | lj->args.append(buf_ptr(rpath)); | |
| 219 | add_rpath(lj, rpath); | |
| 220 | } | |
| 221 | if (g->each_lib_rpath) { | |
| 222 | for (size_t i = 0; i < g->lib_dirs.length; i += 1) { | |
| 223 | const char *lib_dir = g->lib_dirs.at(i); | |
| 224 | for (size_t i = 0; i < g->link_libs.length; i += 1) { | |
| 225 | Buf *link_lib = g->link_libs.at(i); | |
| 226 | bool does_exist; | |
| 227 | Buf *test_path = buf_sprintf("%s/lib%s.so", lib_dir, buf_ptr(link_lib)); | |
| 228 | if (os_file_exists(test_path, &does_exist) != ErrorNone) { | |
| 229 | zig_panic("link: unable to check if file exists: %s", buf_ptr(test_path)); | |
| 230 | } | |
| 231 | if (does_exist) { | |
| 232 | add_rpath(lj, buf_create_from_str(lib_dir)); | |
| 233 | break; | |
| 234 | } | |
| 235 | } | |
| 236 | } | |
| 210 | 237 | } |
| 211 | 238 | |
| 212 | 239 | for (size_t i = 0; i < g->lib_dirs.length; i += 1) { |
| ... | ... | @@ -708,6 +735,7 @@ static void construct_linker_job(LinkJob *lj) { |
| 708 | 735 | |
| 709 | 736 | void codegen_link(CodeGen *g, const char *out_file) { |
| 710 | 737 | LinkJob lj = {0}; |
| 738 | lj.rpath_table.init(4); | |
| 711 | 739 | lj.codegen = g; |
| 712 | 740 | if (out_file) { |
| 713 | 741 | buf_init_from_str(&lj.out_file, out_file); |
src/main.cpp+7-1| ... | ... | @@ -58,7 +58,8 @@ static int usage(const char *arg0) { |
| 58 | 58 | " -framework [name] (darwin only) link against framework\n" |
| 59 | 59 | " --check-unused perform semantic analysis on unused declarations\n" |
| 60 | 60 | " --linker-script [path] use a custom linker script\n" |
| 61 | " -rpath [path] add a directory to the runtime library search path\n" | |
| 61 | " -rpath [path] add directory to the runtime library search path\n" | |
| 62 | " --each-lib-rpath add rpath for each used dynamic library\n" | |
| 62 | 63 | , arg0); |
| 63 | 64 | return EXIT_FAILURE; |
| 64 | 65 | } |
| ... | ... | @@ -143,6 +144,7 @@ int main(int argc, char **argv) { |
| 143 | 144 | bool check_unused = false; |
| 144 | 145 | const char *linker_script = nullptr; |
| 145 | 146 | ZigList<const char *> rpath_list = {0}; |
| 147 | bool each_lib_rpath = false; | |
| 146 | 148 | |
| 147 | 149 | for (int i = 1; i < argc; i += 1) { |
| 148 | 150 | char *arg = argv[i]; |
| ... | ... | @@ -166,6 +168,8 @@ int main(int argc, char **argv) { |
| 166 | 168 | rdynamic = true; |
| 167 | 169 | } else if (strcmp(arg, "--check-unused") == 0) { |
| 168 | 170 | check_unused = true; |
| 171 | } else if (strcmp(arg, "--each-lib-rpath") == 0) { | |
| 172 | each_lib_rpath = true; | |
| 169 | 173 | } else if (arg[1] == 'L' && arg[2] != 0) { |
| 170 | 174 | // alias for --library-path |
| 171 | 175 | lib_dirs.append(&arg[2]); |
| ... | ... | @@ -351,6 +355,8 @@ int main(int argc, char **argv) { |
| 351 | 355 | codegen_set_is_test(g, cmd == CmdTest); |
| 352 | 356 | codegen_set_linker_script(g, linker_script); |
| 353 | 357 | codegen_set_check_unused(g, check_unused); |
| 358 | if (each_lib_rpath) | |
| 359 | codegen_set_each_lib_rpath(g, each_lib_rpath); | |
| 354 | 360 | |
| 355 | 361 | codegen_set_clang_argv(g, clang_argv.items, clang_argv.length); |
| 356 | 362 | codegen_set_strip(g, strip); |
src/os.cpp+9| ... | ... | @@ -218,6 +218,15 @@ int os_fetch_file(FILE *f, Buf *out_buf) { |
| 218 | 218 | zig_unreachable(); |
| 219 | 219 | } |
| 220 | 220 | |
| 221 | int os_file_exists(Buf *full_path, bool *result) { | |
| 222 | #if defined(ZIG_OS_POSIX) | |
| 223 | *result = access(buf_ptr(full_path), F_OK) != -1; | |
| 224 | return 0; | |
| 225 | #else | |
| 226 | zig_panic("TODO implement os_file_exists for non-posix"); | |
| 227 | #endif | |
| 228 | } | |
| 229 | ||
| 221 | 230 | #if defined(ZIG_OS_POSIX) |
| 222 | 231 | static int os_exec_process_posix(const char *exe, ZigList<const char *> &args, |
| 223 | 232 | Termination *term, Buf *out_stderr, Buf *out_stdout) |
src/os.hpp+3-1| ... | ... | @@ -10,6 +10,7 @@ |
| 10 | 10 | |
| 11 | 11 | #include "list.hpp" |
| 12 | 12 | #include "buffer.hpp" |
| 13 | #include "error.hpp" | |
| 13 | 14 | |
| 14 | 15 | #include <stdio.h> |
| 15 | 16 | |
| ... | ... | @@ -40,7 +41,6 @@ bool os_path_is_absolute(Buf *path); |
| 40 | 41 | |
| 41 | 42 | void os_write_file(Buf *full_path, Buf *contents); |
| 42 | 43 | |
| 43 | ||
| 44 | 44 | int os_fetch_file(FILE *file, Buf *out_contents); |
| 45 | 45 | int os_fetch_file_path(Buf *full_path, Buf *out_contents); |
| 46 | 46 | |
| ... | ... | @@ -51,4 +51,6 @@ bool os_stderr_tty(void); |
| 51 | 51 | int os_buf_to_tmp_file(Buf *contents, Buf *suffix, Buf *out_tmp_path); |
| 52 | 52 | int os_delete_file(Buf *path); |
| 53 | 53 | |
| 54 | int os_file_exists(Buf *full_path, bool *result); | |
| 55 | ||
| 54 | 56 | #endif |