authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-09-21 22:38:45-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-09-21 22:38:45-07:00
log877e4248fc1e8e28b1f43282411aa9868d6d1d9c
treea5036516ce1b54ed5a4934e6da01bfda6a90e487
parent974333faaf70eb67b78d3fa83bdc92e91379631a

stage2: implement building & linking against libcxx and libcxxabi


5 files changed, 273 insertions(+), 12 deletions(-)

BRANCH_TODO-1
...@@ -1,4 +1,3 @@...@@ -1,4 +1,3 @@
1 * build & link against libcxx and libcxxabi
2 * `zig build`1 * `zig build`
3 * repair @cImport2 * repair @cImport
4 * make sure zig cc works3 * make sure zig cc works
src/Compilation.zig+32-3
...@@ -16,6 +16,7 @@ const build_options = @import("build_options");...@@ -16,6 +16,7 @@ const build_options = @import("build_options");
16const LibCInstallation = @import("libc_installation.zig").LibCInstallation;16const LibCInstallation = @import("libc_installation.zig").LibCInstallation;
17const glibc = @import("glibc.zig");17const glibc = @import("glibc.zig");
18const libunwind = @import("libunwind.zig");18const libunwind = @import("libunwind.zig");
19const libcxx = @import("libcxx.zig");
19const fatal = @import("main.zig").fatal;20const fatal = @import("main.zig").fatal;
20const Module = @import("Module.zig");21const Module = @import("Module.zig");
21const Cache = @import("Cache.zig");22const Cache = @import("Cache.zig");
...@@ -69,10 +70,10 @@ rand: *std.rand.Random,...@@ -69,10 +70,10 @@ rand: *std.rand.Random,
6970
70/// Populated when we build the libc++ static library. A Job to build this is placed in the queue71/// Populated when we build the libc++ static library. A Job to build this is placed in the queue
71/// and resolved before calling linker.flush().72/// and resolved before calling linker.flush().
72libcxx_static_lib: ?[]const u8 = null,73libcxx_static_lib: ?CRTFile = null,
73/// Populated when we build the libc++abi static library. A Job to build this is placed in the queue74/// Populated when we build the libc++abi static library. A Job to build this is placed in the queue
74/// and resolved before calling linker.flush().75/// and resolved before calling linker.flush().
75libcxxabi_static_lib: ?[]const u8 = null,76libcxxabi_static_lib: ?CRTFile = null,
76/// Populated when we build the libunwind static library. A Job to build this is placed in the queue77/// Populated when we build the libunwind static library. A Job to build this is placed in the queue
77/// and resolved before calling linker.flush().78/// and resolved before calling linker.flush().
78libunwind_static_lib: ?CRTFile = null,79libunwind_static_lib: ?CRTFile = null,
...@@ -140,6 +141,8 @@ const Job = union(enum) {...@@ -140,6 +141,8 @@ const Job = union(enum) {
140 glibc_shared_objects,141 glibc_shared_objects,
141 /// libunwind.a, usually needed when linking libc142 /// libunwind.a, usually needed when linking libc
142 libunwind: void,143 libunwind: void,
144 libcxx: void,
145 libcxxabi: void,
143 /// needed when producing a dynamic library or executable146 /// needed when producing a dynamic library or executable
144 libcompiler_rt: void,147 libcompiler_rt: void,
145 /// needed when not linking libc and using LLVM for code generation because it generates148 /// needed when not linking libc and using LLVM for code generation because it generates
...@@ -770,10 +773,18 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {...@@ -770,10 +773,18 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
770 if (comp.wantBuildLibUnwindFromSource()) {773 if (comp.wantBuildLibUnwindFromSource()) {
771 try comp.work_queue.writeItem(.{ .libunwind = {} });774 try comp.work_queue.writeItem(.{ .libunwind = {} });
772 }775 }
776 if (build_options.have_llvm and comp.bin_file.options.output_mode != .Obj and
777 comp.bin_file.options.link_libcpp)
778 {
779 try comp.work_queue.writeItem(.libcxx);
780 try comp.work_queue.writeItem(.libcxxabi);
781 }
773 if (build_options.is_stage1 and comp.bin_file.options.use_llvm) {782 if (build_options.is_stage1 and comp.bin_file.options.use_llvm) {
774 try comp.work_queue.writeItem(.{ .stage1_module = {} });783 try comp.work_queue.writeItem(.{ .stage1_module = {} });
775 }784 }
776 if (is_exe_or_dyn_lib and comp.bin_file.options.use_llvm) {785 if (is_exe_or_dyn_lib and !comp.bin_file.options.is_compiler_rt_or_libc and
786 build_options.is_stage1)
787 {
777 try comp.work_queue.writeItem(.{ .libcompiler_rt = {} });788 try comp.work_queue.writeItem(.{ .libcompiler_rt = {} });
778 if (!comp.bin_file.options.link_libc) {789 if (!comp.bin_file.options.link_libc) {
779 try comp.work_queue.writeItem(.{ .zig_libc = {} });790 try comp.work_queue.writeItem(.{ .zig_libc = {} });
...@@ -811,6 +822,12 @@ pub fn destroy(self: *Compilation) void {...@@ -811,6 +822,12 @@ pub fn destroy(self: *Compilation) void {
811 if (self.libunwind_static_lib) |*crt_file| {822 if (self.libunwind_static_lib) |*crt_file| {
812 crt_file.deinit(gpa);823 crt_file.deinit(gpa);
813 }824 }
825 if (self.libcxx_static_lib) |*crt_file| {
826 crt_file.deinit(gpa);
827 }
828 if (self.libcxxabi_static_lib) |*crt_file| {
829 crt_file.deinit(gpa);
830 }
814 if (self.compiler_rt_static_lib) |*crt_file| {831 if (self.compiler_rt_static_lib) |*crt_file| {
815 crt_file.deinit(gpa);832 crt_file.deinit(gpa);
816 }833 }
...@@ -1109,6 +1126,18 @@ pub fn performAllTheWork(self: *Compilation) error{OutOfMemory}!void {...@@ -1109,6 +1126,18 @@ pub fn performAllTheWork(self: *Compilation) error{OutOfMemory}!void {
1109 fatal("unable to build libunwind: {}", .{@errorName(err)});1126 fatal("unable to build libunwind: {}", .{@errorName(err)});
1110 };1127 };
1111 },1128 },
1129 .libcxx => {
1130 libcxx.buildLibCXX(self) catch |err| {
1131 // TODO Expose this as a normal compile error rather than crashing here.
1132 fatal("unable to build libcxx: {}", .{@errorName(err)});
1133 };
1134 },
1135 .libcxxabi => {
1136 libcxx.buildLibCXXABI(self) catch |err| {
1137 // TODO Expose this as a normal compile error rather than crashing here.
1138 fatal("unable to build libcxxabi: {}", .{@errorName(err)});
1139 };
1140 },
1112 .libcompiler_rt => {1141 .libcompiler_rt => {
1113 self.buildStaticLibFromZig("compiler_rt.zig", &self.compiler_rt_static_lib) catch |err| {1142 self.buildStaticLibFromZig("compiler_rt.zig", &self.compiler_rt_static_lib) catch |err| {
1114 // TODO Expose this as a normal compile error rather than crashing here.1143 // TODO Expose this as a normal compile error rather than crashing here.
src/libcxx.zig+236-3
...@@ -1,6 +1,13 @@...@@ -1,6 +1,13 @@
1//! TODO build libcxx and libcxxabi from source1const std = @import("std");
2const path = std.fs.path;
3const assert = std.debug.assert;
24
3pub const libcxxabi_files = [_][]const u8{5const target_util = @import("target.zig");
6const Compilation = @import("Compilation.zig");
7const build_options = @import("build_options");
8const trace = @import("tracy.zig").trace;
9
10const libcxxabi_files = [_][]const u8{
4 "src/abort_message.cpp",11 "src/abort_message.cpp",
5 "src/cxa_aux_runtime.cpp",12 "src/cxa_aux_runtime.cpp",
6 "src/cxa_default_handlers.cpp",13 "src/cxa_default_handlers.cpp",
...@@ -22,7 +29,7 @@ pub const libcxxabi_files = [_][]const u8{...@@ -22,7 +29,7 @@ pub const libcxxabi_files = [_][]const u8{
22 "src/stdlib_typeinfo.cpp",29 "src/stdlib_typeinfo.cpp",
23};30};
2431
25pub const libcxx_files = [_][]const u8{32const libcxx_files = [_][]const u8{
26 "src/algorithm.cpp",33 "src/algorithm.cpp",
27 "src/any.cpp",34 "src/any.cpp",
28 "src/bind.cpp",35 "src/bind.cpp",
...@@ -64,3 +71,229 @@ pub const libcxx_files = [_][]const u8{...@@ -64,3 +71,229 @@ pub const libcxx_files = [_][]const u8{
64 "src/variant.cpp",71 "src/variant.cpp",
65 "src/vector.cpp",72 "src/vector.cpp",
66};73};
74
75pub fn buildLibCXX(comp: *Compilation) !void {
76 if (!build_options.have_llvm) {
77 return error.ZigCompilerNotBuiltWithLLVMExtensions;
78 }
79
80 const tracy = trace(@src());
81 defer tracy.end();
82
83 var arena_allocator = std.heap.ArenaAllocator.init(comp.gpa);
84 defer arena_allocator.deinit();
85 const arena = &arena_allocator.allocator;
86
87 const root_name = "c++";
88 const output_mode = .Lib;
89 const link_mode = .Static;
90 const target = comp.getTarget();
91 const basename = try std.zig.binNameAlloc(arena, root_name, target, output_mode, link_mode, null);
92
93 const emit_bin = Compilation.EmitLoc{
94 .directory = null, // Put it in the cache directory.
95 .basename = basename,
96 };
97
98 const cxxabi_include_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libcxxabi", "include" });
99 const cxx_include_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libcxx", "include" });
100 var c_source_files = std.ArrayList(Compilation.CSourceFile).init(arena);
101 try c_source_files.ensureCapacity(libcxx_files.len);
102
103 for (libcxx_files) |cxx_src| {
104 var cflags = std.ArrayList([]const u8).init(arena);
105
106 if (target.os.tag == .windows) {
107 // Filesystem stuff isn't supported on Windows.
108 if (std.mem.startsWith(u8, cxx_src, "src/filesystem/"))
109 continue;
110 } else {
111 if (std.mem.startsWith(u8, cxx_src, "src/support/win32/"))
112 continue;
113 }
114
115 try cflags.append("-DNDEBUG");
116 try cflags.append("-D_LIBCPP_BUILDING_LIBRARY");
117 try cflags.append("-D_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER");
118 try cflags.append("-DLIBCXX_BUILDING_LIBCXXABI");
119 try cflags.append("-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS");
120 try cflags.append("-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS");
121
122 if (target.abi.isMusl()) {
123 try cflags.append("-D_LIBCPP_HAS_MUSL_LIBC");
124 }
125
126 try cflags.append("-I");
127 try cflags.append(cxx_include_path);
128
129 try cflags.append("-I");
130 try cflags.append(cxxabi_include_path);
131
132 try cflags.append("-O3");
133 try cflags.append("-DNDEBUG");
134 if (target_util.supports_fpic(target)) {
135 try cflags.append("-fPIC");
136 }
137 try cflags.append("-nostdinc++");
138 try cflags.append("-fvisibility-inlines-hidden");
139 try cflags.append("-std=c++14");
140 try cflags.append("-Wno-user-defined-literals");
141
142 c_source_files.appendAssumeCapacity(.{
143 .src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libcxx", cxx_src }),
144 .extra_flags = cflags.items,
145 });
146 }
147
148 const sub_compilation = try Compilation.create(comp.gpa, .{
149 // TODO use the global cache directory here
150 .zig_cache_directory = comp.zig_cache_directory,
151 .zig_lib_directory = comp.zig_lib_directory,
152 .target = target,
153 .root_name = root_name,
154 .root_pkg = null,
155 .output_mode = output_mode,
156 .rand = comp.rand,
157 .libc_installation = comp.bin_file.options.libc_installation,
158 .emit_bin = emit_bin,
159 .optimize_mode = comp.bin_file.options.optimize_mode,
160 .link_mode = link_mode,
161 .want_sanitize_c = false,
162 .want_stack_check = false,
163 .want_valgrind = false,
164 .want_pic = comp.bin_file.options.pic,
165 .emit_h = null,
166 .strip = comp.bin_file.options.strip,
167 .is_native_os = comp.bin_file.options.is_native_os,
168 .self_exe_path = comp.self_exe_path,
169 .c_source_files = c_source_files.items,
170 .verbose_cc = comp.verbose_cc,
171 .verbose_link = comp.bin_file.options.verbose_link,
172 .verbose_tokenize = comp.verbose_tokenize,
173 .verbose_ast = comp.verbose_ast,
174 .verbose_ir = comp.verbose_ir,
175 .verbose_llvm_ir = comp.verbose_llvm_ir,
176 .verbose_cimport = comp.verbose_cimport,
177 .verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features,
178 .clang_passthrough_mode = comp.clang_passthrough_mode,
179 .link_libc = true,
180 });
181 defer sub_compilation.destroy();
182
183 try sub_compilation.updateSubCompilation();
184
185 assert(comp.libcxx_static_lib == null);
186 comp.libcxx_static_lib = Compilation.CRTFile{
187 .full_object_path = try sub_compilation.bin_file.options.directory.join(comp.gpa, &[_][]const u8{basename}),
188 .lock = sub_compilation.bin_file.toOwnedLock(),
189 };
190}
191
192pub fn buildLibCXXABI(comp: *Compilation) !void {
193 if (!build_options.have_llvm) {
194 return error.ZigCompilerNotBuiltWithLLVMExtensions;
195 }
196
197 const tracy = trace(@src());
198 defer tracy.end();
199
200 var arena_allocator = std.heap.ArenaAllocator.init(comp.gpa);
201 defer arena_allocator.deinit();
202 const arena = &arena_allocator.allocator;
203
204 const root_name = "c++abi";
205 const output_mode = .Lib;
206 const link_mode = .Static;
207 const target = comp.getTarget();
208 const basename = try std.zig.binNameAlloc(arena, root_name, target, output_mode, link_mode, null);
209
210 const emit_bin = Compilation.EmitLoc{
211 .directory = null, // Put it in the cache directory.
212 .basename = basename,
213 };
214
215 const cxxabi_include_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libcxxabi", "include" });
216 const cxx_include_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libcxx", "include" });
217
218 var c_source_files: [libcxxabi_files.len]Compilation.CSourceFile = undefined;
219 for (libcxxabi_files) |cxxabi_src, i| {
220 var cflags = std.ArrayList([]const u8).init(arena);
221
222 try cflags.append("-DHAVE___CXA_THREAD_ATEXIT_IMPL");
223 try cflags.append("-D_LIBCPP_DISABLE_EXTERN_TEMPLATE");
224 try cflags.append("-D_LIBCPP_ENABLE_CXX17_REMOVED_UNEXPECTED_FUNCTIONS");
225 try cflags.append("-D_LIBCXXABI_BUILDING_LIBRARY");
226 try cflags.append("-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS");
227 try cflags.append("-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS");
228
229 if (target.abi.isMusl()) {
230 try cflags.append("-D_LIBCPP_HAS_MUSL_LIBC");
231 }
232
233 try cflags.append("-I");
234 try cflags.append(cxxabi_include_path);
235
236 try cflags.append("-I");
237 try cflags.append(cxx_include_path);
238
239 try cflags.append("-O3");
240 try cflags.append("-DNDEBUG");
241 if (target_util.supports_fpic(target)) {
242 try cflags.append("-fPIC");
243 }
244 try cflags.append("-nostdinc++");
245 try cflags.append("-fstrict-aliasing");
246 try cflags.append("-funwind-tables");
247 try cflags.append("-D_DEBUG");
248 try cflags.append("-UNDEBUG");
249 try cflags.append("-std=c++11");
250
251 c_source_files[i] = .{
252 .src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libcxxabi", cxxabi_src }),
253 .extra_flags = cflags.items,
254 };
255 }
256
257 const sub_compilation = try Compilation.create(comp.gpa, .{
258 // TODO use the global cache directory here
259 .zig_cache_directory = comp.zig_cache_directory,
260 .zig_lib_directory = comp.zig_lib_directory,
261 .target = target,
262 .root_name = root_name,
263 .root_pkg = null,
264 .output_mode = output_mode,
265 .rand = comp.rand,
266 .libc_installation = comp.bin_file.options.libc_installation,
267 .emit_bin = emit_bin,
268 .optimize_mode = comp.bin_file.options.optimize_mode,
269 .link_mode = link_mode,
270 .want_sanitize_c = false,
271 .want_stack_check = false,
272 .want_valgrind = false,
273 .want_pic = comp.bin_file.options.pic,
274 .emit_h = null,
275 .strip = comp.bin_file.options.strip,
276 .is_native_os = comp.bin_file.options.is_native_os,
277 .self_exe_path = comp.self_exe_path,
278 .c_source_files = &c_source_files,
279 .verbose_cc = comp.verbose_cc,
280 .verbose_link = comp.bin_file.options.verbose_link,
281 .verbose_tokenize = comp.verbose_tokenize,
282 .verbose_ast = comp.verbose_ast,
283 .verbose_ir = comp.verbose_ir,
284 .verbose_llvm_ir = comp.verbose_llvm_ir,
285 .verbose_cimport = comp.verbose_cimport,
286 .verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features,
287 .clang_passthrough_mode = comp.clang_passthrough_mode,
288 .link_libc = true,
289 });
290 defer sub_compilation.destroy();
291
292 try sub_compilation.updateSubCompilation();
293
294 assert(comp.libcxxabi_static_lib == null);
295 comp.libcxxabi_static_lib = Compilation.CRTFile{
296 .full_object_path = try sub_compilation.bin_file.options.directory.join(comp.gpa, &[_][]const u8{basename}),
297 .lock = sub_compilation.bin_file.toOwnedLock(),
298 };
299}
src/libunwind.zig+3-3
...@@ -8,13 +8,13 @@ const build_options = @import("build_options");...@@ -8,13 +8,13 @@ const build_options = @import("build_options");
8const trace = @import("tracy.zig").trace;8const trace = @import("tracy.zig").trace;
99
10pub fn buildStaticLib(comp: *Compilation) !void {10pub fn buildStaticLib(comp: *Compilation) !void {
11 const tracy = trace(@src());
12 defer tracy.end();
13
14 if (!build_options.have_llvm) {11 if (!build_options.have_llvm) {
15 return error.ZigCompilerNotBuiltWithLLVMExtensions;12 return error.ZigCompilerNotBuiltWithLLVMExtensions;
16 }13 }
1714
15 const tracy = trace(@src());
16 defer tracy.end();
17
18 var arena_allocator = std.heap.ArenaAllocator.init(comp.gpa);18 var arena_allocator = std.heap.ArenaAllocator.init(comp.gpa);
19 defer arena_allocator.deinit();19 defer arena_allocator.deinit();
20 const arena = &arena_allocator.allocator;20 const arena = &arena_allocator.allocator;
src/link/Elf.zig+2-2
...@@ -1513,8 +1513,8 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {...@@ -1513,8 +1513,8 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
1513 if (!is_obj) {1513 if (!is_obj) {
1514 // libc++ dep1514 // libc++ dep
1515 if (self.base.options.link_libcpp) {1515 if (self.base.options.link_libcpp) {
1516 try argv.append(comp.libcxxabi_static_lib.?);1516 try argv.append(comp.libcxxabi_static_lib.?.full_object_path);
1517 try argv.append(comp.libcxx_static_lib.?);1517 try argv.append(comp.libcxx_static_lib.?.full_object_path);
1518 }1518 }
15191519
1520 // libc dep1520 // libc dep