Commit 877e4248fc
Changed files (5)
src/link/Elf.zig
@@ -1513,8 +1513,8 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
if (!is_obj) {
// libc++ dep
if (self.base.options.link_libcpp) {
- try argv.append(comp.libcxxabi_static_lib.?);
- try argv.append(comp.libcxx_static_lib.?);
+ try argv.append(comp.libcxxabi_static_lib.?.full_object_path);
+ try argv.append(comp.libcxx_static_lib.?.full_object_path);
}
// libc dep
src/Compilation.zig
@@ -16,6 +16,7 @@ const build_options = @import("build_options");
const LibCInstallation = @import("libc_installation.zig").LibCInstallation;
const glibc = @import("glibc.zig");
const libunwind = @import("libunwind.zig");
+const libcxx = @import("libcxx.zig");
const fatal = @import("main.zig").fatal;
const Module = @import("Module.zig");
const Cache = @import("Cache.zig");
@@ -69,10 +70,10 @@ rand: *std.rand.Random,
/// Populated when we build the libc++ static library. A Job to build this is placed in the queue
/// and resolved before calling linker.flush().
-libcxx_static_lib: ?[]const u8 = null,
+libcxx_static_lib: ?CRTFile = null,
/// Populated when we build the libc++abi static library. A Job to build this is placed in the queue
/// and resolved before calling linker.flush().
-libcxxabi_static_lib: ?[]const u8 = null,
+libcxxabi_static_lib: ?CRTFile = null,
/// Populated when we build the libunwind static library. A Job to build this is placed in the queue
/// and resolved before calling linker.flush().
libunwind_static_lib: ?CRTFile = null,
@@ -140,6 +141,8 @@ const Job = union(enum) {
glibc_shared_objects,
/// libunwind.a, usually needed when linking libc
libunwind: void,
+ libcxx: void,
+ libcxxabi: void,
/// needed when producing a dynamic library or executable
libcompiler_rt: void,
/// 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 {
if (comp.wantBuildLibUnwindFromSource()) {
try comp.work_queue.writeItem(.{ .libunwind = {} });
}
+ if (build_options.have_llvm and comp.bin_file.options.output_mode != .Obj and
+ comp.bin_file.options.link_libcpp)
+ {
+ try comp.work_queue.writeItem(.libcxx);
+ try comp.work_queue.writeItem(.libcxxabi);
+ }
if (build_options.is_stage1 and comp.bin_file.options.use_llvm) {
try comp.work_queue.writeItem(.{ .stage1_module = {} });
}
- if (is_exe_or_dyn_lib and comp.bin_file.options.use_llvm) {
+ if (is_exe_or_dyn_lib and !comp.bin_file.options.is_compiler_rt_or_libc and
+ build_options.is_stage1)
+ {
try comp.work_queue.writeItem(.{ .libcompiler_rt = {} });
if (!comp.bin_file.options.link_libc) {
try comp.work_queue.writeItem(.{ .zig_libc = {} });
@@ -811,6 +822,12 @@ pub fn destroy(self: *Compilation) void {
if (self.libunwind_static_lib) |*crt_file| {
crt_file.deinit(gpa);
}
+ if (self.libcxx_static_lib) |*crt_file| {
+ crt_file.deinit(gpa);
+ }
+ if (self.libcxxabi_static_lib) |*crt_file| {
+ crt_file.deinit(gpa);
+ }
if (self.compiler_rt_static_lib) |*crt_file| {
crt_file.deinit(gpa);
}
@@ -1109,6 +1126,18 @@ pub fn performAllTheWork(self: *Compilation) error{OutOfMemory}!void {
fatal("unable to build libunwind: {}", .{@errorName(err)});
};
},
+ .libcxx => {
+ libcxx.buildLibCXX(self) catch |err| {
+ // TODO Expose this as a normal compile error rather than crashing here.
+ fatal("unable to build libcxx: {}", .{@errorName(err)});
+ };
+ },
+ .libcxxabi => {
+ libcxx.buildLibCXXABI(self) catch |err| {
+ // TODO Expose this as a normal compile error rather than crashing here.
+ fatal("unable to build libcxxabi: {}", .{@errorName(err)});
+ };
+ },
.libcompiler_rt => {
self.buildStaticLibFromZig("compiler_rt.zig", &self.compiler_rt_static_lib) catch |err| {
// TODO Expose this as a normal compile error rather than crashing here.
src/libcxx.zig
@@ -1,6 +1,13 @@
-//! TODO build libcxx and libcxxabi from source
+const std = @import("std");
+const path = std.fs.path;
+const assert = std.debug.assert;
-pub const libcxxabi_files = [_][]const u8{
+const target_util = @import("target.zig");
+const Compilation = @import("Compilation.zig");
+const build_options = @import("build_options");
+const trace = @import("tracy.zig").trace;
+
+const libcxxabi_files = [_][]const u8{
"src/abort_message.cpp",
"src/cxa_aux_runtime.cpp",
"src/cxa_default_handlers.cpp",
@@ -22,7 +29,7 @@ pub const libcxxabi_files = [_][]const u8{
"src/stdlib_typeinfo.cpp",
};
-pub const libcxx_files = [_][]const u8{
+const libcxx_files = [_][]const u8{
"src/algorithm.cpp",
"src/any.cpp",
"src/bind.cpp",
@@ -64,3 +71,229 @@ pub const libcxx_files = [_][]const u8{
"src/variant.cpp",
"src/vector.cpp",
};
+
+pub fn buildLibCXX(comp: *Compilation) !void {
+ if (!build_options.have_llvm) {
+ return error.ZigCompilerNotBuiltWithLLVMExtensions;
+ }
+
+ const tracy = trace(@src());
+ defer tracy.end();
+
+ var arena_allocator = std.heap.ArenaAllocator.init(comp.gpa);
+ defer arena_allocator.deinit();
+ const arena = &arena_allocator.allocator;
+
+ const root_name = "c++";
+ const output_mode = .Lib;
+ const link_mode = .Static;
+ const target = comp.getTarget();
+ const basename = try std.zig.binNameAlloc(arena, root_name, target, output_mode, link_mode, null);
+
+ const emit_bin = Compilation.EmitLoc{
+ .directory = null, // Put it in the cache directory.
+ .basename = basename,
+ };
+
+ const cxxabi_include_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libcxxabi", "include" });
+ const cxx_include_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libcxx", "include" });
+ var c_source_files = std.ArrayList(Compilation.CSourceFile).init(arena);
+ try c_source_files.ensureCapacity(libcxx_files.len);
+
+ for (libcxx_files) |cxx_src| {
+ var cflags = std.ArrayList([]const u8).init(arena);
+
+ if (target.os.tag == .windows) {
+ // Filesystem stuff isn't supported on Windows.
+ if (std.mem.startsWith(u8, cxx_src, "src/filesystem/"))
+ continue;
+ } else {
+ if (std.mem.startsWith(u8, cxx_src, "src/support/win32/"))
+ continue;
+ }
+
+ try cflags.append("-DNDEBUG");
+ try cflags.append("-D_LIBCPP_BUILDING_LIBRARY");
+ try cflags.append("-D_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER");
+ try cflags.append("-DLIBCXX_BUILDING_LIBCXXABI");
+ try cflags.append("-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS");
+ try cflags.append("-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS");
+
+ if (target.abi.isMusl()) {
+ try cflags.append("-D_LIBCPP_HAS_MUSL_LIBC");
+ }
+
+ try cflags.append("-I");
+ try cflags.append(cxx_include_path);
+
+ try cflags.append("-I");
+ try cflags.append(cxxabi_include_path);
+
+ try cflags.append("-O3");
+ try cflags.append("-DNDEBUG");
+ if (target_util.supports_fpic(target)) {
+ try cflags.append("-fPIC");
+ }
+ try cflags.append("-nostdinc++");
+ try cflags.append("-fvisibility-inlines-hidden");
+ try cflags.append("-std=c++14");
+ try cflags.append("-Wno-user-defined-literals");
+
+ c_source_files.appendAssumeCapacity(.{
+ .src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libcxx", cxx_src }),
+ .extra_flags = cflags.items,
+ });
+ }
+
+ const sub_compilation = try Compilation.create(comp.gpa, .{
+ // TODO use the global cache directory here
+ .zig_cache_directory = comp.zig_cache_directory,
+ .zig_lib_directory = comp.zig_lib_directory,
+ .target = target,
+ .root_name = root_name,
+ .root_pkg = null,
+ .output_mode = output_mode,
+ .rand = comp.rand,
+ .libc_installation = comp.bin_file.options.libc_installation,
+ .emit_bin = emit_bin,
+ .optimize_mode = comp.bin_file.options.optimize_mode,
+ .link_mode = link_mode,
+ .want_sanitize_c = false,
+ .want_stack_check = false,
+ .want_valgrind = false,
+ .want_pic = comp.bin_file.options.pic,
+ .emit_h = null,
+ .strip = comp.bin_file.options.strip,
+ .is_native_os = comp.bin_file.options.is_native_os,
+ .self_exe_path = comp.self_exe_path,
+ .c_source_files = c_source_files.items,
+ .verbose_cc = comp.verbose_cc,
+ .verbose_link = comp.bin_file.options.verbose_link,
+ .verbose_tokenize = comp.verbose_tokenize,
+ .verbose_ast = comp.verbose_ast,
+ .verbose_ir = comp.verbose_ir,
+ .verbose_llvm_ir = comp.verbose_llvm_ir,
+ .verbose_cimport = comp.verbose_cimport,
+ .verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features,
+ .clang_passthrough_mode = comp.clang_passthrough_mode,
+ .link_libc = true,
+ });
+ defer sub_compilation.destroy();
+
+ try sub_compilation.updateSubCompilation();
+
+ assert(comp.libcxx_static_lib == null);
+ comp.libcxx_static_lib = Compilation.CRTFile{
+ .full_object_path = try sub_compilation.bin_file.options.directory.join(comp.gpa, &[_][]const u8{basename}),
+ .lock = sub_compilation.bin_file.toOwnedLock(),
+ };
+}
+
+pub fn buildLibCXXABI(comp: *Compilation) !void {
+ if (!build_options.have_llvm) {
+ return error.ZigCompilerNotBuiltWithLLVMExtensions;
+ }
+
+ const tracy = trace(@src());
+ defer tracy.end();
+
+ var arena_allocator = std.heap.ArenaAllocator.init(comp.gpa);
+ defer arena_allocator.deinit();
+ const arena = &arena_allocator.allocator;
+
+ const root_name = "c++abi";
+ const output_mode = .Lib;
+ const link_mode = .Static;
+ const target = comp.getTarget();
+ const basename = try std.zig.binNameAlloc(arena, root_name, target, output_mode, link_mode, null);
+
+ const emit_bin = Compilation.EmitLoc{
+ .directory = null, // Put it in the cache directory.
+ .basename = basename,
+ };
+
+ const cxxabi_include_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libcxxabi", "include" });
+ const cxx_include_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libcxx", "include" });
+
+ var c_source_files: [libcxxabi_files.len]Compilation.CSourceFile = undefined;
+ for (libcxxabi_files) |cxxabi_src, i| {
+ var cflags = std.ArrayList([]const u8).init(arena);
+
+ try cflags.append("-DHAVE___CXA_THREAD_ATEXIT_IMPL");
+ try cflags.append("-D_LIBCPP_DISABLE_EXTERN_TEMPLATE");
+ try cflags.append("-D_LIBCPP_ENABLE_CXX17_REMOVED_UNEXPECTED_FUNCTIONS");
+ try cflags.append("-D_LIBCXXABI_BUILDING_LIBRARY");
+ try cflags.append("-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS");
+ try cflags.append("-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS");
+
+ if (target.abi.isMusl()) {
+ try cflags.append("-D_LIBCPP_HAS_MUSL_LIBC");
+ }
+
+ try cflags.append("-I");
+ try cflags.append(cxxabi_include_path);
+
+ try cflags.append("-I");
+ try cflags.append(cxx_include_path);
+
+ try cflags.append("-O3");
+ try cflags.append("-DNDEBUG");
+ if (target_util.supports_fpic(target)) {
+ try cflags.append("-fPIC");
+ }
+ try cflags.append("-nostdinc++");
+ try cflags.append("-fstrict-aliasing");
+ try cflags.append("-funwind-tables");
+ try cflags.append("-D_DEBUG");
+ try cflags.append("-UNDEBUG");
+ try cflags.append("-std=c++11");
+
+ c_source_files[i] = .{
+ .src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libcxxabi", cxxabi_src }),
+ .extra_flags = cflags.items,
+ };
+ }
+
+ const sub_compilation = try Compilation.create(comp.gpa, .{
+ // TODO use the global cache directory here
+ .zig_cache_directory = comp.zig_cache_directory,
+ .zig_lib_directory = comp.zig_lib_directory,
+ .target = target,
+ .root_name = root_name,
+ .root_pkg = null,
+ .output_mode = output_mode,
+ .rand = comp.rand,
+ .libc_installation = comp.bin_file.options.libc_installation,
+ .emit_bin = emit_bin,
+ .optimize_mode = comp.bin_file.options.optimize_mode,
+ .link_mode = link_mode,
+ .want_sanitize_c = false,
+ .want_stack_check = false,
+ .want_valgrind = false,
+ .want_pic = comp.bin_file.options.pic,
+ .emit_h = null,
+ .strip = comp.bin_file.options.strip,
+ .is_native_os = comp.bin_file.options.is_native_os,
+ .self_exe_path = comp.self_exe_path,
+ .c_source_files = &c_source_files,
+ .verbose_cc = comp.verbose_cc,
+ .verbose_link = comp.bin_file.options.verbose_link,
+ .verbose_tokenize = comp.verbose_tokenize,
+ .verbose_ast = comp.verbose_ast,
+ .verbose_ir = comp.verbose_ir,
+ .verbose_llvm_ir = comp.verbose_llvm_ir,
+ .verbose_cimport = comp.verbose_cimport,
+ .verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features,
+ .clang_passthrough_mode = comp.clang_passthrough_mode,
+ .link_libc = true,
+ });
+ defer sub_compilation.destroy();
+
+ try sub_compilation.updateSubCompilation();
+
+ assert(comp.libcxxabi_static_lib == null);
+ comp.libcxxabi_static_lib = Compilation.CRTFile{
+ .full_object_path = try sub_compilation.bin_file.options.directory.join(comp.gpa, &[_][]const u8{basename}),
+ .lock = sub_compilation.bin_file.toOwnedLock(),
+ };
+}
src/libunwind.zig
@@ -8,13 +8,13 @@ const build_options = @import("build_options");
const trace = @import("tracy.zig").trace;
pub fn buildStaticLib(comp: *Compilation) !void {
- const tracy = trace(@src());
- defer tracy.end();
-
if (!build_options.have_llvm) {
return error.ZigCompilerNotBuiltWithLLVMExtensions;
}
+ const tracy = trace(@src());
+ defer tracy.end();
+
var arena_allocator = std.heap.ArenaAllocator.init(comp.gpa);
defer arena_allocator.deinit();
const arena = &arena_allocator.allocator;
BRANCH_TODO
@@ -1,4 +1,3 @@
- * build & link against libcxx and libcxxabi
* `zig build`
* repair @cImport
* make sure zig cc works