authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-03-13 13:11:55-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-03-13 13:11:55-04:00
log7efa2cd81cef69d071982cfaa6953d6b9d4a1c95
tree36bb2eca682dffbd285e1eda0a63f6e673a061f0
parentd10bbd28e9576d000f04ac6d06c2a8493ffc72ef

add --each-lib-rpath option and corresponding config option

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
18set(ZIG_LIBC_STATIC_LIB_DIR "" CACHE STRING "Default native target libc directory where crtbeginT.o can be found")18set(ZIG_LIBC_STATIC_LIB_DIR "" CACHE STRING "Default native target libc directory where crtbeginT.o can be found")
19set(ZIG_LIBC_INCLUDE_DIR "/usr/include" CACHE STRING "Default native target libc include directory")19set(ZIG_LIBC_INCLUDE_DIR "/usr/include" CACHE STRING "Default native target libc include directory")
20set(ZIG_DYNAMIC_LINKER "" CACHE STRING "Override dynamic linker for native target")20set(ZIG_DYNAMIC_LINKER "" CACHE STRING "Override dynamic linker for native target")
21set(ZIG_EACH_LIB_RPATH off CACHE BOOL "Add each dynamic library to rpath for native target")
2122
22option(ZIG_TEST_COVERAGE "Build Zig with test coverage instrumentation" OFF)23option(ZIG_TEST_COVERAGE "Build Zig with test coverage instrumentation" OFF)
2324
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;
14141414
1415 bool check_unused;1415 bool check_unused;
1416 bool each_lib_rpath;
14161417
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 stuff95 // 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
103107
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}
140144
145void codegen_set_each_lib_rpath(CodeGen *g, bool each_lib_rpath) {
146 g->each_lib_rpath = each_lib_rpath;
147}
148
141void codegen_set_errmsg_color(CodeGen *g, ErrColor err_color) {149void 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);
20void codegen_set_is_release(CodeGen *codegen, bool is_release);20void codegen_set_is_release(CodeGen *codegen, bool is_release);
21void codegen_set_is_test(CodeGen *codegen, bool is_test);21void codegen_set_is_test(CodeGen *codegen, bool is_test);
22void codegen_set_check_unused(CodeGen *codegen, bool check_unused);22void codegen_set_check_unused(CodeGen *codegen, bool check_unused);
23void codegen_set_each_lib_rpath(CodeGen *codegen, bool each_lib_rpath);
2324
24void codegen_set_is_static(CodeGen *codegen, bool is_static);25void codegen_set_is_static(CodeGen *codegen, bool is_static);
25void codegen_set_strip(CodeGen *codegen, bool strip);26void 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@"
2323
24#cmakedefine ZIG_EACH_LIB_RPATH
24#cmakedefine ZIG_LLVM_OLD_CXX_ABI25#cmakedefine ZIG_LLVM_OLD_CXX_ABI
2526
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};
2122
22static const char *get_libc_file(CodeGen *g, const char *file) {23static 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}
150151
152static 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
151static void construct_linker_job_elf(LinkJob *lj) {162static void construct_linker_job_elf(LinkJob *lj) {
152 CodeGen *g = lj->codegen;163 CodeGen *g = lj->codegen;
153164
...@@ -205,8 +216,24 @@ static void construct_linker_job_elf(LinkJob *lj) {...@@ -205,8 +216,24 @@ static void construct_linker_job_elf(LinkJob *lj) {
205216
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 }
211238
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) {
708735
709void codegen_link(CodeGen *g, const char *out_file) {736void 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;
146148
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-path174 // 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);
354360
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}
220220
221int 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)
222static int os_exec_process_posix(const char *exe, ZigList<const char *> &args,231static 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 @@
1010
11#include "list.hpp"11#include "list.hpp"
12#include "buffer.hpp"12#include "buffer.hpp"
13#include "error.hpp"
1314
14#include <stdio.h>15#include <stdio.h>
1516
...@@ -40,7 +41,6 @@ bool os_path_is_absolute(Buf *path);...@@ -40,7 +41,6 @@ bool os_path_is_absolute(Buf *path);
4041
41void os_write_file(Buf *full_path, Buf *contents);42void os_write_file(Buf *full_path, Buf *contents);
4243
43
44int os_fetch_file(FILE *file, Buf *out_contents);44int os_fetch_file(FILE *file, Buf *out_contents);
45int os_fetch_file_path(Buf *full_path, Buf *out_contents);45int os_fetch_file_path(Buf *full_path, Buf *out_contents);
4646
...@@ -51,4 +51,6 @@ bool os_stderr_tty(void);...@@ -51,4 +51,6 @@ bool os_stderr_tty(void);
51int os_buf_to_tmp_file(Buf *contents, Buf *suffix, Buf *out_tmp_path);51int os_buf_to_tmp_file(Buf *contents, Buf *suffix, Buf *out_tmp_path);
52int os_delete_file(Buf *path);52int os_delete_file(Buf *path);
5353
54int os_file_exists(Buf *full_path, bool *result);
55
54#endif56#endif