| 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,6 +18,7 @@ set(ZIG_LIBC_LIB_DIR "" CACHE STRING "Default native target libc directory where |
| 18 | set(ZIG_LIBC_STATIC_LIB_DIR "" CACHE STRING "Default native target libc directory where crtbeginT.o can be found") | 18 | set(ZIG_LIBC_STATIC_LIB_DIR "" CACHE STRING "Default native target libc directory where crtbeginT.o can be found") |
| 19 | set(ZIG_LIBC_INCLUDE_DIR "/usr/include" CACHE STRING "Default native target libc include directory") | 19 | set(ZIG_LIBC_INCLUDE_DIR "/usr/include" CACHE STRING "Default native target libc include directory") |
| 20 | set(ZIG_DYNAMIC_LINKER "" CACHE STRING "Override dynamic linker for native target") | 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 | option(ZIG_TEST_COVERAGE "Build Zig with test coverage instrumentation" OFF) | 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,6 +1413,7 @@ struct CodeGen { |
| 1413 | uint32_t test_fn_count; | 1413 | uint32_t test_fn_count; |
| 1414 | 1414 | ||
| 1415 | bool check_unused; | 1415 | bool check_unused; |
| 1416 | bool each_lib_rpath; | ||
| 1416 | 1417 | ||
| 1417 | ZigList<AstNode *> error_decls; | 1418 | ZigList<AstNode *> error_decls; |
| 1418 | bool generate_error_name_table; | 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,6 +90,7 @@ CodeGen *codegen_create(Buf *root_source_dir, const ZigTarget *target) { |
| 90 | g->libc_static_lib_dir = buf_create_from_str(""); | 90 | g->libc_static_lib_dir = buf_create_from_str(""); |
| 91 | g->libc_include_dir = buf_create_from_str(""); | 91 | g->libc_include_dir = buf_create_from_str(""); |
| 92 | g->darwin_linker_version = buf_create_from_str(""); | 92 | g->darwin_linker_version = buf_create_from_str(""); |
| 93 | g->each_lib_rpath = false; | ||
| 93 | } else { | 94 | } else { |
| 94 | // native compilation, we can rely on the configuration stuff | 95 | // native compilation, we can rely on the configuration stuff |
| 95 | g->is_native_target = true; | 96 | g->is_native_target = true; |
| ... | @@ -100,6 +101,9 @@ CodeGen *codegen_create(Buf *root_source_dir, const ZigTarget *target) { | ... | @@ -100,6 +101,9 @@ CodeGen *codegen_create(Buf *root_source_dir, const ZigTarget *target) { |
| 100 | g->libc_static_lib_dir = buf_create_from_str(ZIG_LIBC_STATIC_LIB_DIR); | 101 | g->libc_static_lib_dir = buf_create_from_str(ZIG_LIBC_STATIC_LIB_DIR); |
| 101 | g->libc_include_dir = buf_create_from_str(ZIG_LIBC_INCLUDE_DIR); | 102 | g->libc_include_dir = buf_create_from_str(ZIG_LIBC_INCLUDE_DIR); |
| 102 | g->darwin_linker_version = buf_create_from_str(ZIG_HOST_LINK_VERSION); | 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 | if (g->zig_target.os == ZigLLVM_Darwin || | 108 | if (g->zig_target.os == ZigLLVM_Darwin || |
| 105 | g->zig_target.os == ZigLLVM_MacOSX || | 109 | g->zig_target.os == ZigLLVM_MacOSX || |
| ... | @@ -138,6 +142,10 @@ void codegen_set_check_unused(CodeGen *g, bool check_unused) { | ... | @@ -138,6 +142,10 @@ void codegen_set_check_unused(CodeGen *g, bool check_unused) { |
| 138 | g->check_unused = check_unused; | 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 | void codegen_set_errmsg_color(CodeGen *g, ErrColor err_color) { | 149 | void codegen_set_errmsg_color(CodeGen *g, ErrColor err_color) { |
| 142 | g->err_color = err_color; | 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,6 +20,7 @@ void codegen_set_clang_argv(CodeGen *codegen, const char **args, size_t len); |
| 20 | void codegen_set_is_release(CodeGen *codegen, bool is_release); | 20 | void codegen_set_is_release(CodeGen *codegen, bool is_release); |
| 21 | void codegen_set_is_test(CodeGen *codegen, bool is_test); | 21 | void codegen_set_is_test(CodeGen *codegen, bool is_test); |
| 22 | void codegen_set_check_unused(CodeGen *codegen, bool check_unused); | 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 | void codegen_set_is_static(CodeGen *codegen, bool is_static); | 25 | void codegen_set_is_static(CodeGen *codegen, bool is_static); |
| 25 | void codegen_set_strip(CodeGen *codegen, bool strip); | 26 | void codegen_set_strip(CodeGen *codegen, bool strip); |
src/config.h.in+1| ... | @@ -21,6 +21,7 @@ | ... | @@ -21,6 +21,7 @@ |
| 21 | #define ZIG_DYNAMIC_LINKER "@ZIG_DYNAMIC_LINKER@" | 21 | #define ZIG_DYNAMIC_LINKER "@ZIG_DYNAMIC_LINKER@" |
| 22 | #define ZIG_HOST_LINK_VERSION "@ZIG_HOST_LINK_VERSION@" | 22 | #define ZIG_HOST_LINK_VERSION "@ZIG_HOST_LINK_VERSION@" |
| 23 | 23 | ||
| 24 | #cmakedefine ZIG_EACH_LIB_RPATH | ||
| 24 | #cmakedefine ZIG_LLVM_OLD_CXX_ABI | 25 | #cmakedefine ZIG_LLVM_OLD_CXX_ABI |
| 25 | 26 | ||
| 26 | // Only used for running tests before installing. | 27 | // Only used for running tests before installing. |
src/link.cpp+30-2| ... | @@ -17,6 +17,7 @@ struct LinkJob { | ... | @@ -17,6 +17,7 @@ struct LinkJob { |
| 17 | ZigList<const char *> args; | 17 | ZigList<const char *> args; |
| 18 | bool link_in_crt; | 18 | bool link_in_crt; |
| 19 | Buf out_file_o; | 19 | Buf out_file_o; |
| 20 | HashMap<Buf *, bool, buf_hash, buf_eql_buf> rpath_table; | ||
| 20 | }; | 21 | }; |
| 21 | 22 | ||
| 22 | static const char *get_libc_file(CodeGen *g, const char *file) { | 23 | static const char *get_libc_file(CodeGen *g, const char *file) { |
| ... | @@ -148,6 +149,16 @@ static const char *getLDMOption(const ZigTarget *t) { | ... | @@ -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 | static void construct_linker_job_elf(LinkJob *lj) { | 162 | static void construct_linker_job_elf(LinkJob *lj) { |
| 152 | CodeGen *g = lj->codegen; | 163 | CodeGen *g = lj->codegen; |
| 153 | 164 | ||
| ... | @@ -205,8 +216,24 @@ static void construct_linker_job_elf(LinkJob *lj) { | ... | @@ -205,8 +216,24 @@ static void construct_linker_job_elf(LinkJob *lj) { |
| 205 | 216 | ||
| 206 | for (size_t i = 0; i < g->rpath_list.length; i += 1) { | 217 | for (size_t i = 0; i < g->rpath_list.length; i += 1) { |
| 207 | Buf *rpath = g->rpath_list.at(i); | 218 | Buf *rpath = g->rpath_list.at(i); |
| 208 | lj->args.append("-rpath"); | 219 | add_rpath(lj, rpath); |
| 209 | lj->args.append(buf_ptr(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 | for (size_t i = 0; i < g->lib_dirs.length; i += 1) { | 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,6 +735,7 @@ static void construct_linker_job(LinkJob *lj) { |
| 708 | 735 | ||
| 709 | void codegen_link(CodeGen *g, const char *out_file) { | 736 | void codegen_link(CodeGen *g, const char *out_file) { |
| 710 | LinkJob lj = {0}; | 737 | LinkJob lj = {0}; |
| 738 | lj.rpath_table.init(4); | ||
| 711 | lj.codegen = g; | 739 | lj.codegen = g; |
| 712 | if (out_file) { | 740 | if (out_file) { |
| 713 | buf_init_from_str(&lj.out_file, out_file); | 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,7 +58,8 @@ static int usage(const char *arg0) { |
| 58 | " -framework [name] (darwin only) link against framework\n" | 58 | " -framework [name] (darwin only) link against framework\n" |
| 59 | " --check-unused perform semantic analysis on unused declarations\n" | 59 | " --check-unused perform semantic analysis on unused declarations\n" |
| 60 | " --linker-script [path] use a custom linker script\n" | 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 | , arg0); | 63 | , arg0); |
| 63 | return EXIT_FAILURE; | 64 | return EXIT_FAILURE; |
| 64 | } | 65 | } |
| ... | @@ -143,6 +144,7 @@ int main(int argc, char **argv) { | ... | @@ -143,6 +144,7 @@ int main(int argc, char **argv) { |
| 143 | bool check_unused = false; | 144 | bool check_unused = false; |
| 144 | const char *linker_script = nullptr; | 145 | const char *linker_script = nullptr; |
| 145 | ZigList<const char *> rpath_list = {0}; | 146 | ZigList<const char *> rpath_list = {0}; |
| 147 | bool each_lib_rpath = false; | ||
| 146 | 148 | ||
| 147 | for (int i = 1; i < argc; i += 1) { | 149 | for (int i = 1; i < argc; i += 1) { |
| 148 | char *arg = argv[i]; | 150 | char *arg = argv[i]; |
| ... | @@ -166,6 +168,8 @@ int main(int argc, char **argv) { | ... | @@ -166,6 +168,8 @@ int main(int argc, char **argv) { |
| 166 | rdynamic = true; | 168 | rdynamic = true; |
| 167 | } else if (strcmp(arg, "--check-unused") == 0) { | 169 | } else if (strcmp(arg, "--check-unused") == 0) { |
| 168 | check_unused = true; | 170 | check_unused = true; |
| 171 | } else if (strcmp(arg, "--each-lib-rpath") == 0) { | ||
| 172 | each_lib_rpath = true; | ||
| 169 | } else if (arg[1] == 'L' && arg[2] != 0) { | 173 | } else if (arg[1] == 'L' && arg[2] != 0) { |
| 170 | // alias for --library-path | 174 | // alias for --library-path |
| 171 | lib_dirs.append(&arg[2]); | 175 | lib_dirs.append(&arg[2]); |
| ... | @@ -351,6 +355,8 @@ int main(int argc, char **argv) { | ... | @@ -351,6 +355,8 @@ int main(int argc, char **argv) { |
| 351 | codegen_set_is_test(g, cmd == CmdTest); | 355 | codegen_set_is_test(g, cmd == CmdTest); |
| 352 | codegen_set_linker_script(g, linker_script); | 356 | codegen_set_linker_script(g, linker_script); |
| 353 | codegen_set_check_unused(g, check_unused); | 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 | codegen_set_clang_argv(g, clang_argv.items, clang_argv.length); | 361 | codegen_set_clang_argv(g, clang_argv.items, clang_argv.length); |
| 356 | codegen_set_strip(g, strip); | 362 | codegen_set_strip(g, strip); |
src/os.cpp+9| ... | @@ -218,6 +218,15 @@ int os_fetch_file(FILE *f, Buf *out_buf) { | ... | @@ -218,6 +218,15 @@ int os_fetch_file(FILE *f, Buf *out_buf) { |
| 218 | zig_unreachable(); | 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 | #if defined(ZIG_OS_POSIX) | 230 | #if defined(ZIG_OS_POSIX) |
| 222 | static int os_exec_process_posix(const char *exe, ZigList<const char *> &args, | 231 | static int os_exec_process_posix(const char *exe, ZigList<const char *> &args, |
| 223 | Termination *term, Buf *out_stderr, Buf *out_stdout) | 232 | Termination *term, Buf *out_stderr, Buf *out_stdout) |
src/os.hpp+3-1| ... | @@ -10,6 +10,7 @@ | ... | @@ -10,6 +10,7 @@ |
| 10 | 10 | ||
| 11 | #include "list.hpp" | 11 | #include "list.hpp" |
| 12 | #include "buffer.hpp" | 12 | #include "buffer.hpp" |
| 13 | #include "error.hpp" | ||
| 13 | 14 | ||
| 14 | #include <stdio.h> | 15 | #include <stdio.h> |
| 15 | 16 | ||
| ... | @@ -40,7 +41,6 @@ bool os_path_is_absolute(Buf *path); | ... | @@ -40,7 +41,6 @@ bool os_path_is_absolute(Buf *path); |
| 40 | 41 | ||
| 41 | void os_write_file(Buf *full_path, Buf *contents); | 42 | void os_write_file(Buf *full_path, Buf *contents); |
| 42 | 43 | ||
| 43 | |||
| 44 | int os_fetch_file(FILE *file, Buf *out_contents); | 44 | int os_fetch_file(FILE *file, Buf *out_contents); |
| 45 | int os_fetch_file_path(Buf *full_path, Buf *out_contents); | 45 | int os_fetch_file_path(Buf *full_path, Buf *out_contents); |
| 46 | 46 | ||
| ... | @@ -51,4 +51,6 @@ bool os_stderr_tty(void); | ... | @@ -51,4 +51,6 @@ bool os_stderr_tty(void); |
| 51 | int os_buf_to_tmp_file(Buf *contents, Buf *suffix, Buf *out_tmp_path); | 51 | int os_buf_to_tmp_file(Buf *contents, Buf *suffix, Buf *out_tmp_path); |
| 52 | int os_delete_file(Buf *path); | 52 | int os_delete_file(Buf *path); |
| 53 | 53 | ||
| 54 | int os_file_exists(Buf *full_path, bool *result); | ||
| 55 | |||
| 54 | #endif | 56 | #endif |