authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-02-08 00:50:51-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-02-08 00:50:51-07:00
log430d0dfcb24178fd079be5d6988298bffec8beab
tree9212d6e5b43bc590cc5c436f092b3298a3e066b2
parentea3bd585634fa648cce7b597e611e9db35f5f929

support static linking against libc


7 files changed, 127 insertions(+), 56 deletions(-)

README.md+5-4
...@@ -70,13 +70,14 @@ compromises backward compatibility....@@ -70,13 +70,14 @@ compromises backward compatibility.
7070
71### Debug / Development Build71### Debug / Development Build
7272
73If you have gcc or clang installed, you can find out what `ZIG_LIBC_LIB_DIR` should73If you have gcc or clang installed, you can find out what `ZIG_LIBC_LIB_DIR`
74be set to (example below). `ZIG_LIBC_INCLUDE_DIR` likely can be set to `/usr/include`.74and `ZIG_LIBC_STATIC_LIB_DIR` should be set to (example below).
75`ZIG_LIBC_INCLUDE_DIR` likely can be set to `/usr/include`.
7576
76```77```
77mkdir build78mkdir build
78cd build79cd build
79cmake .. -DCMAKE_INSTALL_PREFIX=$(pwd) -DZIG_LIBC_LIB_DIR=$(dirname $(cc -print-file-name=crt1.o)) -DZIG_LIBC_INCLUDE_DIR=/usr/include80cmake .. -DCMAKE_INSTALL_PREFIX=$(pwd) -DZIG_LIBC_LIB_DIR=$(dirname $(cc -print-file-name=crt1.o)) -DZIG_LIBC_INCLUDE_DIR=/usr/include -DZIG_LIBC_STATIC_LIB_DIR=$(dirname $(cc -print-file-name=crtbeginT.o))
80make81make
81make install82make install
82./run_tests83./run_tests
...@@ -90,7 +91,7 @@ by the `--libc-lib-dir` and `--libc-include-dir` parameters to the zig binary....@@ -90,7 +91,7 @@ by the `--libc-lib-dir` and `--libc-include-dir` parameters to the zig binary.
90```91```
91mkdir build92mkdir build
92cd build93cd build
93cmake .. -DCMAKE_BUILD_TYPE=Release -DZIG_LIBC_LIB_DIR=/some/path -DZIG_LIBC_INCLUDE_DIR=/some/path94cmake .. -DCMAKE_BUILD_TYPE=Release -DZIG_LIBC_LIB_DIR=/some/path -DZIG_LIBC_INCLUDE_DIR=/some/path -DZIG_LIBC_STATIC_INCLUDE_DIR=/some/path
94make95make
95sudo make install96sudo make install
96```97```
src/all_types.hpp+1
...@@ -1104,6 +1104,7 @@ struct CodeGen {...@@ -1104,6 +1104,7 @@ struct CodeGen {
1104 bool have_exported_main;1104 bool have_exported_main;
1105 bool link_libc;1105 bool link_libc;
1106 Buf *libc_lib_dir;1106 Buf *libc_lib_dir;
1107 Buf *libc_static_lib_dir;
1107 Buf *libc_include_dir;1108 Buf *libc_include_dir;
1108 bool is_release_build;1109 bool is_release_build;
1109 bool is_test_build;1110 bool is_test_build;
src/analyze.cpp+3
...@@ -5852,6 +5852,9 @@ void find_libc_path(CodeGen *g) {...@@ -5852,6 +5852,9 @@ void find_libc_path(CodeGen *g) {
5852 if (!g->libc_lib_dir || buf_len(g->libc_lib_dir) == 0) {5852 if (!g->libc_lib_dir || buf_len(g->libc_lib_dir) == 0) {
5853 zig_panic("Unable to determine libc lib path. probably need to reconfigure");5853 zig_panic("Unable to determine libc lib path. probably need to reconfigure");
5854 }5854 }
5855 if (!g->libc_static_lib_dir || buf_len(g->libc_static_lib_dir) == 0) {
5856 zig_panic("Unable to determine libc static lib path. probably need to reconfigure");
5857 }
5855 if (!g->libc_include_dir || buf_len(g->libc_include_dir) == 0) {5858 if (!g->libc_include_dir || buf_len(g->libc_include_dir) == 0) {
5856 zig_panic("Unable to determine libc include path. probably need to reconfigure");5859 zig_panic("Unable to determine libc include path. probably need to reconfigure");
5857 }5860 }
src/codegen.cpp+92-35
...@@ -35,6 +35,7 @@ CodeGen *codegen_create(Buf *root_source_dir) {...@@ -35,6 +35,7 @@ CodeGen *codegen_create(Buf *root_source_dir) {
35 g->error_value_count = 1;35 g->error_value_count = 1;
3636
37 g->libc_lib_dir = buf_create_from_str(ZIG_LIBC_LIB_DIR);37 g->libc_lib_dir = buf_create_from_str(ZIG_LIBC_LIB_DIR);
38 g->libc_static_lib_dir = buf_create_from_str(ZIG_LIBC_STATIC_LIB_DIR);
38 g->libc_include_dir = buf_create_from_str(ZIG_LIBC_INCLUDE_DIR);39 g->libc_include_dir = buf_create_from_str(ZIG_LIBC_INCLUDE_DIR);
3940
40 return g;41 return g;
...@@ -81,6 +82,10 @@ void codegen_set_libc_lib_dir(CodeGen *g, Buf *libc_lib_dir) {...@@ -81,6 +82,10 @@ void codegen_set_libc_lib_dir(CodeGen *g, Buf *libc_lib_dir) {
81 g->libc_lib_dir = libc_lib_dir;82 g->libc_lib_dir = libc_lib_dir;
82}83}
8384
85void codegen_set_libc_static_lib_dir(CodeGen *g, Buf *libc_static_lib_dir) {
86 g->libc_static_lib_dir = libc_static_lib_dir;
87}
88
84void codegen_set_libc_include_dir(CodeGen *g, Buf *libc_include_dir) {89void codegen_set_libc_include_dir(CodeGen *g, Buf *libc_include_dir) {
85 g->libc_include_dir = libc_include_dir;90 g->libc_include_dir = libc_include_dir;
86}91}
...@@ -4010,6 +4015,12 @@ static const char *get_libc_file(CodeGen *g, const char *file) {...@@ -4010,6 +4015,12 @@ static const char *get_libc_file(CodeGen *g, const char *file) {
4010 return buf_ptr(out_buf);4015 return buf_ptr(out_buf);
4011}4016}
40124017
4018static const char *get_libc_static_file(CodeGen *g, const char *file) {
4019 Buf *out_buf = buf_alloc();
4020 os_path_join(g->libc_static_lib_dir, buf_create_from_str(file), out_buf);
4021 return buf_ptr(out_buf);
4022}
4023
4013static Buf *build_o(CodeGen *parent_gen, const char *oname) {4024static Buf *build_o(CodeGen *parent_gen, const char *oname) {
4014 Buf *source_basename = buf_sprintf("%s.zig", oname);4025 Buf *source_basename = buf_sprintf("%s.zig", oname);
4015 Buf *std_dir_path = buf_create_from_str(ZIG_STD_DIR);4026 Buf *std_dir_path = buf_create_from_str(ZIG_STD_DIR);
...@@ -4096,27 +4107,63 @@ void codegen_link(CodeGen *g, const char *out_file) {...@@ -4096,27 +4107,63 @@ void codegen_link(CodeGen *g, const char *out_file) {
4096 return;4107 return;
4097 }4108 }
40984109
4110 bool link_in_crt = (g->link_libc && g->out_type == OutTypeExe);
4111 if (link_in_crt) {
4112 find_libc_path(g);
4113 }
4114
4115
40994116
4100 // invoke `ld`4117 // invoke `ld`
4101 ZigList<const char *> args = {0};4118 ZigList<const char *> args = {0};
4102 const char *crt1o;4119
4120 // TODO make this target dependent
4121 args.append("-m");
4122 args.append("elf_x86_64");
4123
4103 if (g->is_static) {4124 if (g->is_static) {
4104 args.append("-static");4125 args.append("-static");
4105 crt1o = "crt1.o";
4106 } else {
4107 crt1o = "Scrt1.o";
4108 }4126 }
41094127
4110 // TODO don't pass this parameter unless linking with libc4128 args.append("-o");
4111 char *ZIG_NATIVE_DYNAMIC_LINKER = getenv("ZIG_NATIVE_DYNAMIC_LINKER");4129 args.append(out_file);
4112 if (g->is_native_target && ZIG_NATIVE_DYNAMIC_LINKER) {4130
4113 if (ZIG_NATIVE_DYNAMIC_LINKER[0] != 0) {4131 if (link_in_crt) {
4114 args.append("-dynamic-linker");4132 const char *crt1o;
4115 args.append(ZIG_NATIVE_DYNAMIC_LINKER);4133 const char *crtbegino;
4134 if (g->is_static) {
4135 crt1o = "crt1.o";
4136 crtbegino = "crtbeginT.o";
4137 } else {
4138 crt1o = "Scrt1.o";
4139 crtbegino = "crtbegin.o";
4116 }4140 }
4117 } else {4141 args.append(get_libc_file(g, crt1o));
4142 args.append(get_libc_file(g, "crti.o"));
4143 args.append(get_libc_static_file(g, crtbegino));
4144 }
4145
4146 for (int i = 0; i < g->lib_dirs.length; i += 1) {
4147 const char *lib_dir = g->lib_dirs.at(i);
4148 args.append("-L");
4149 args.append(lib_dir);
4150 }
4151
4152 if (g->link_libc) {
4153 args.append("-L");
4154 args.append(buf_ptr(g->libc_lib_dir));
4155
4156 args.append("-L");
4157 args.append(buf_ptr(g->libc_static_lib_dir));
4158 }
4159
4160 // TODO don't pass this parameter unless linking with libc
4161 if (ZIG_DYNAMIC_LINKER[0] == 0) {
4118 args.append("-dynamic-linker");4162 args.append("-dynamic-linker");
4119 args.append(buf_ptr(get_dynamic_linker(g->target_machine)));4163 args.append(buf_ptr(get_dynamic_linker(g->target_machine)));
4164 } else {
4165 args.append("-dynamic-linker");
4166 args.append(ZIG_DYNAMIC_LINKER);
4120 }4167 }
41214168
4122 if (g->out_type == OutTypeLib) {4169 if (g->out_type == OutTypeLib) {
...@@ -4129,24 +4176,9 @@ void codegen_link(CodeGen *g, const char *out_file) {...@@ -4129,24 +4176,9 @@ void codegen_link(CodeGen *g, const char *out_file) {
4129 out_file = buf_ptr(out_lib_so);4176 out_file = buf_ptr(out_lib_so);
4130 }4177 }
41314178
4132 args.append("-o");4179 // .o files
4133 args.append(out_file);
4134
4135 bool link_in_crt = (g->link_libc && g->out_type == OutTypeExe);
4136
4137 if (link_in_crt) {
4138 find_libc_path(g);
4139
4140 args.append(get_libc_file(g, crt1o));
4141 args.append(get_libc_file(g, "crti.o"));
4142 }
4143
4144 args.append((const char *)buf_ptr(&out_file_o));4180 args.append((const char *)buf_ptr(&out_file_o));
41454181
4146 if (link_in_crt) {
4147 args.append(get_libc_file(g, "crtn.o"));
4148 }
4149
4150 if (g->is_test_build) {4182 if (g->is_test_build) {
4151 const char *test_runner_name = g->link_libc ? "test_runner_libc" : "test_runner_nolibc";4183 const char *test_runner_name = g->link_libc ? "test_runner_libc" : "test_runner_nolibc";
4152 Buf *test_runner_o_path = build_o(g, test_runner_name);4184 Buf *test_runner_o_path = build_o(g, test_runner_name);
...@@ -4158,20 +4190,45 @@ void codegen_link(CodeGen *g, const char *out_file) {...@@ -4158,20 +4190,45 @@ void codegen_link(CodeGen *g, const char *out_file) {
4158 args.append(buf_ptr(builtin_o_path));4190 args.append(buf_ptr(builtin_o_path));
4159 }4191 }
41604192
4161 for (int i = 0; i < g->lib_dirs.length; i += 1) {
4162 const char *lib_dir = g->lib_dirs.at(i);
4163 args.append("-L");
4164 args.append(lib_dir);
4165 }
4166
4167 auto it = g->link_table.entry_iterator();4193 auto it = g->link_table.entry_iterator();
4168 for (;;) {4194 for (;;) {
4169 auto *entry = it.next();4195 auto *entry = it.next();
4170 if (!entry)4196 if (!entry)
4171 break;4197 break;
41724198
4173 Buf *arg = buf_sprintf("-l%s", buf_ptr(entry->key));4199 // we handle libc explicitly, don't do it here
4174 args.append(buf_ptr(arg));4200 if (!buf_eql_str(entry->key, "c")) {
4201 Buf *arg = buf_sprintf("-l%s", buf_ptr(entry->key));
4202 args.append(buf_ptr(arg));
4203 }
4204 }
4205
4206
4207 // libc dep
4208 if (g->link_libc) {
4209 if (g->is_static) {
4210 args.append("--start-group");
4211 args.append("-lgcc");
4212 args.append("-lgcc_eh");
4213 args.append("-lc");
4214 args.append("--end-group");
4215 } else {
4216 args.append("-lgcc");
4217 args.append("--as-needed");
4218 args.append("-lgcc_s");
4219 args.append("--no-as-needed");
4220 args.append("-lc");
4221 args.append("-lgcc");
4222 args.append("--as-needed");
4223 args.append("-lgcc_s");
4224 args.append("--no-as-needed");
4225 }
4226 }
4227
4228 // crt end
4229 if (link_in_crt) {
4230 args.append(get_libc_static_file(g, "crtend.o"));
4231 args.append(get_libc_file(g, "crtn.o"));
4175 }4232 }
41764233
4177 if (g->verbose) {4234 if (g->verbose) {
src/codegen.hpp+1
...@@ -26,6 +26,7 @@ void codegen_set_errmsg_color(CodeGen *codegen, ErrColor err_color);...@@ -26,6 +26,7 @@ void codegen_set_errmsg_color(CodeGen *codegen, ErrColor err_color);
26void codegen_set_out_type(CodeGen *codegen, OutType out_type);26void codegen_set_out_type(CodeGen *codegen, OutType out_type);
27void codegen_set_out_name(CodeGen *codegen, Buf *out_name);27void codegen_set_out_name(CodeGen *codegen, Buf *out_name);
28void codegen_set_libc_lib_dir(CodeGen *codegen, Buf *libc_lib_dir);28void codegen_set_libc_lib_dir(CodeGen *codegen, Buf *libc_lib_dir);
29void codegen_set_libc_static_lib_dir(CodeGen *g, Buf *libc_static_lib_dir);
29void codegen_set_libc_include_dir(CodeGen *codegen, Buf *libc_include_dir);30void codegen_set_libc_include_dir(CodeGen *codegen, Buf *libc_include_dir);
30void codegen_add_lib_dir(CodeGen *codegen, const char *dir);31void codegen_add_lib_dir(CodeGen *codegen, const char *dir);
3132
src/config.h.in+2
...@@ -10,6 +10,8 @@...@@ -10,6 +10,8 @@
10#define ZIG_STD_DIR "@CMAKE_INSTALL_PREFIX@/@ZIG_STD_DEST@"10#define ZIG_STD_DIR "@CMAKE_INSTALL_PREFIX@/@ZIG_STD_DEST@"
11#define ZIG_LIBC_INCLUDE_DIR "@ZIG_LIBC_INCLUDE_DIR@"11#define ZIG_LIBC_INCLUDE_DIR "@ZIG_LIBC_INCLUDE_DIR@"
12#define ZIG_LIBC_LIB_DIR "@ZIG_LIBC_LIB_DIR@"12#define ZIG_LIBC_LIB_DIR "@ZIG_LIBC_LIB_DIR@"
13#define ZIG_LIBC_STATIC_LIB_DIR "@ZIG_LIBC_STATIC_LIB_DIR@"
14#define ZIG_DYNAMIC_LINKER "@ZIG_DYNAMIC_LINKER@"
1315
14#cmakedefine ZIG_LLVM_OLD_CXX_ABI16#cmakedefine ZIG_LLVM_OLD_CXX_ABI
1517
src/main.cpp+23-17
...@@ -16,24 +16,25 @@...@@ -16,24 +16,25 @@
16static int usage(const char *arg0) {16static int usage(const char *arg0) {
17 fprintf(stderr, "Usage: %s [command] [options]\n"17 fprintf(stderr, "Usage: %s [command] [options]\n"
18 "Commands:\n"18 "Commands:\n"
19 " build create executable, object, or library from target\n"19 " build create executable, object, or library from target\n"
20 " test create and run a test build\n"20 " test create and run a test build\n"
21 " version print version number and exit\n"21 " version print version number and exit\n"
22 " parseh convert a c header file to zig extern declarations\n"22 " parseh convert a c header file to zig extern declarations\n"
23 "Options:\n"23 "Options:\n"
24 " --release build with optimizations on and debug protection off\n"24 " --release build with optimizations on and debug protection off\n"
25 " --static output will be statically linked\n"25 " --static output will be statically linked\n"
26 " --strip exclude debug symbols\n"26 " --strip exclude debug symbols\n"
27 " --export [exe|lib|obj] override output type\n"27 " --export [exe|lib|obj] override output type\n"
28 " --name [name] override output name\n"28 " --name [name] override output name\n"
29 " --output [file] override destination path\n"29 " --output [file] override destination path\n"
30 " --verbose turn on compiler debug output\n"30 " --verbose turn on compiler debug output\n"
31 " --color [auto|off|on] enable or disable colored error messages\n"31 " --color [auto|off|on] enable or disable colored error messages\n"
32 " --libc-lib-dir [path] set the C compiler data path\n"32 " --libc-lib-dir [path] set the C compiler data path\n"
33 " --libc-include-dir [path] set the C compiler data path\n"33 " --libc-static-lib-dir [path] set the C compiler data path\n"
34 " -isystem [dir] add additional search path for other .h files\n"34 " --libc-include-dir [path] set the C compiler data path\n"
35 " -dirafter [dir] same as -isystem but do it last\n"35 " -isystem [dir] add additional search path for other .h files\n"
36 " --library-path [dir] add a directory to the library search path\n"36 " -dirafter [dir] same as -isystem but do it last\n"
37 " --library-path [dir] add a directory to the library search path\n"
37 , arg0);38 , arg0);
38 return EXIT_FAILURE;39 return EXIT_FAILURE;
39}40}
...@@ -59,6 +60,7 @@ int main(int argc, char **argv) {...@@ -59,6 +60,7 @@ int main(int argc, char **argv) {
59 bool verbose = false;60 bool verbose = false;
60 ErrColor color = ErrColorAuto;61 ErrColor color = ErrColorAuto;
61 const char *libc_lib_dir = nullptr;62 const char *libc_lib_dir = nullptr;
63 const char *libc_static_lib_dir = nullptr;
62 const char *libc_include_dir = nullptr;64 const char *libc_include_dir = nullptr;
63 ZigList<const char *> clang_argv = {0};65 ZigList<const char *> clang_argv = {0};
64 ZigList<const char *> lib_dirs = {0};66 ZigList<const char *> lib_dirs = {0};
...@@ -108,6 +110,8 @@ int main(int argc, char **argv) {...@@ -108,6 +110,8 @@ int main(int argc, char **argv) {
108 out_name = argv[i];110 out_name = argv[i];
109 } else if (strcmp(arg, "--libc-lib-dir") == 0) {111 } else if (strcmp(arg, "--libc-lib-dir") == 0) {
110 libc_lib_dir = argv[i];112 libc_lib_dir = argv[i];
113 } else if (strcmp(arg, "--libc-static-lib-dir") == 0) {
114 libc_static_lib_dir = argv[i];
111 } else if (strcmp(arg, "--libc-include-dir") == 0) {115 } else if (strcmp(arg, "--libc-include-dir") == 0) {
112 libc_include_dir = argv[i];116 libc_include_dir = argv[i];
113 } else if (strcmp(arg, "-isystem") == 0) {117 } else if (strcmp(arg, "-isystem") == 0) {
...@@ -202,6 +206,8 @@ int main(int argc, char **argv) {...@@ -202,6 +206,8 @@ int main(int argc, char **argv) {
202 }206 }
203 if (libc_lib_dir)207 if (libc_lib_dir)
204 codegen_set_libc_lib_dir(g, buf_create_from_str(libc_lib_dir));208 codegen_set_libc_lib_dir(g, buf_create_from_str(libc_lib_dir));
209 if (libc_static_lib_dir)
210 codegen_set_libc_static_lib_dir(g, buf_create_from_str(libc_static_lib_dir));
205 if (libc_include_dir)211 if (libc_include_dir)
206 codegen_set_libc_include_dir(g, buf_create_from_str(libc_include_dir));212 codegen_set_libc_include_dir(g, buf_create_from_str(libc_include_dir));
207 codegen_set_verbose(g, verbose);213 codegen_set_verbose(g, verbose);