aboutsummaryrefslogtreecommitdiff
path: root/src/Compilation.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2020-11-30 16:40:25 -0700
committerAndrew Kelley <andrew@ziglang.org>2020-11-30 16:40:25 -0700
commit205af5b14828d64c10f5c67e05cebf32b882c646 (patch)
treea76c48fca7b7458f41c4dca14f9ec9eb30325818 /src/Compilation.zig
parent51d7c14ce1bdadc4405474cfb3945581c198c741 (diff)
parentff9798eb265b02d572ecbced675efcd7c763aea9 (diff)
downloadzig-205af5b14828d64c10f5c67e05cebf32b882c646.tar.gz
zig-205af5b14828d64c10f5c67e05cebf32b882c646.zip
Merge branch 'alexnask-bundle_compiler_rt' into master
Closes #7013 Closes #6817
Diffstat (limited to 'src/Compilation.zig')
-rw-r--r--src/Compilation.zig77
1 files changed, 57 insertions, 20 deletions
diff --git a/src/Compilation.zig b/src/Compilation.zig
index a66df1db7b..b7660718de 100644
--- a/src/Compilation.zig
+++ b/src/Compilation.zig
@@ -93,6 +93,9 @@ libc_static_lib: ?CRTFile = null,
/// Populated when we build the libcompiler_rt static library. A Job to build this is placed in the queue
/// and resolved before calling linker.flush().
compiler_rt_static_lib: ?CRTFile = null,
+/// Populated when we build the compiler_rt_obj object. A Job to build this is placed in the queue
+/// and resolved before calling linker.flush().
+compiler_rt_obj: ?CRTFile = null,
glibc_so_files: ?glibc.BuiltSharedObjects = null,
@@ -164,8 +167,8 @@ const Job = union(enum) {
libcxx: void,
libcxxabi: void,
libssp: void,
- /// needed when producing a dynamic library or executable
- libcompiler_rt: void,
+ compiler_rt_lib: void,
+ compiler_rt_obj: void,
/// needed when not linking libc and using LLVM for code generation because it generates
/// calls to, for example, memcpy and memset.
zig_libc: void,
@@ -350,6 +353,7 @@ pub const InitOptions = struct {
want_sanitize_c: ?bool = null,
want_stack_check: ?bool = null,
want_valgrind: ?bool = null,
+ want_compiler_rt: ?bool = null,
use_llvm: ?bool = null,
use_lld: ?bool = null,
use_clang: ?bool = null,
@@ -409,6 +413,9 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
.Lib => is_dyn_lib,
.Exe => true,
};
+ const needs_c_symbols = !options.is_compiler_rt_or_libc and
+ (is_exe_or_dyn_lib or (options.target.isWasm() and options.output_mode != .Obj));
+
const comp: *Compilation = comp: {
// For allocations that have the same lifetime as Compilation. This arena is used only during this
// initialization and then is freed in deinit().
@@ -585,6 +592,8 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
break :b options.want_valgrind orelse (options.optimize_mode == .Debug);
};
+ const include_compiler_rt = options.want_compiler_rt orelse needs_c_symbols;
+
const single_threaded = options.single_threaded or target_util.isSingleThreaded(options.target);
const llvm_cpu_features: ?[*:0]const u8 = if (build_options.have_llvm and use_llvm) blk: {
@@ -821,6 +830,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
.z_defs = options.linker_z_defs,
.stack_size_override = options.stack_size_override,
.image_base_override = options.image_base_override,
+ .include_compiler_rt = include_compiler_rt,
.linker_script = options.linker_script,
.version_script = options.version_script,
.gc_sections = options.linker_gc_sections,
@@ -967,16 +977,31 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
try comp.work_queue.writeItem(.libcxxabi);
}
- const needs_compiler_rt_and_c = is_exe_or_dyn_lib or
- (comp.getTarget().isWasm() and comp.bin_file.options.output_mode != .Obj);
- if (needs_compiler_rt_and_c and build_options.is_stage1) {
- try comp.work_queue.writeItem(.{ .libcompiler_rt = {} });
- // MinGW provides no libssp, use our own implementation.
- if (comp.getTarget().isMinGW()) {
- try comp.work_queue.writeItem(.{ .libssp = {} });
+ // The `is_stage1` condition is here only because stage2 cannot yet build compiler-rt.
+ // Once it is capable this condition should be removed.
+ if (build_options.is_stage1) {
+ if (comp.bin_file.options.include_compiler_rt) {
+ if (is_exe_or_dyn_lib) {
+ try comp.work_queue.writeItem(.{ .compiler_rt_lib = {} });
+ } else {
+ try comp.work_queue.writeItem(.{ .compiler_rt_obj = {} });
+ if (comp.bin_file.options.object_format != .elf) {
+ // For ELF we can rely on using -r to link multiple objects together into one,
+ // but to truly support `build-obj -fcompiler-rt` will require virtually
+ // injecting `_ = @import("compiler_rt.zig")` into the root source file of
+ // the compilation.
+ fatal("Embedding compiler-rt into non-ELF objects is not yet implemented.", .{});
+ }
+ }
}
- if (!comp.bin_file.options.link_libc) {
- try comp.work_queue.writeItem(.{ .zig_libc = {} });
+ if (needs_c_symbols) {
+ // MinGW provides no libssp, use our own implementation.
+ if (comp.getTarget().isMinGW()) {
+ try comp.work_queue.writeItem(.{ .libssp = {} });
+ }
+ if (!comp.bin_file.options.link_libc) {
+ try comp.work_queue.writeItem(.{ .zig_libc = {} });
+ }
}
}
}
@@ -1374,20 +1399,26 @@ pub fn performAllTheWork(self: *Compilation) error{ TimerUnsupported, OutOfMemor
fatal("unable to build libcxxabi: {}", .{@errorName(err)});
};
},
- .libcompiler_rt => {
- self.buildStaticLibFromZig("compiler_rt.zig", &self.compiler_rt_static_lib) catch |err| {
+ .compiler_rt_lib => {
+ self.buildOutputFromZig("compiler_rt.zig", .Lib, &self.compiler_rt_static_lib) catch |err| {
// TODO Expose this as a normal compile error rather than crashing here.
- fatal("unable to build compiler_rt: {}", .{@errorName(err)});
+ fatal("unable to build compiler_rt: {s}", .{@errorName(err)});
+ };
+ },
+ .compiler_rt_obj => {
+ self.buildOutputFromZig("compiler_rt.zig", .Obj, &self.compiler_rt_obj) catch |err| {
+ // TODO Expose this as a normal compile error rather than crashing here.
+ fatal("unable to build compiler_rt: {s}", .{@errorName(err)});
};
},
.libssp => {
- self.buildStaticLibFromZig("ssp.zig", &self.libssp_static_lib) catch |err| {
+ self.buildOutputFromZig("ssp.zig", .Lib, &self.libssp_static_lib) catch |err| {
// TODO Expose this as a normal compile error rather than crashing here.
fatal("unable to build libssp: {}", .{@errorName(err)});
};
},
.zig_libc => {
- self.buildStaticLibFromZig("c.zig", &self.libc_static_lib) catch |err| {
+ self.buildOutputFromZig("c.zig", .Lib, &self.libc_static_lib) catch |err| {
// TODO Expose this as a normal compile error rather than crashing here.
fatal("unable to build zig's multitarget libc: {}", .{@errorName(err)});
};
@@ -2551,10 +2582,16 @@ pub fn updateSubCompilation(sub_compilation: *Compilation) !void {
}
}
-fn buildStaticLibFromZig(comp: *Compilation, src_basename: []const u8, out: *?CRTFile) !void {
+fn buildOutputFromZig(
+ comp: *Compilation,
+ src_basename: []const u8,
+ output_mode: std.builtin.OutputMode,
+ out: *?CRTFile,
+) !void {
const tracy = trace(@src());
defer tracy.end();
+ std.debug.assert(output_mode != .Exe);
const special_sub = "std" ++ std.fs.path.sep_str ++ "special";
const special_path = try comp.zig_lib_directory.join(comp.gpa, &[_][]const u8{special_sub});
defer comp.gpa.free(special_path);
@@ -2571,11 +2608,11 @@ fn buildStaticLibFromZig(comp: *Compilation, src_basename: []const u8, out: *?CR
};
const root_name = mem.split(src_basename, ".").next().?;
const target = comp.getTarget();
- const output_mode: std.builtin.OutputMode = if (target.cpu.arch.isWasm()) .Obj else .Lib;
+ const fixed_output_mode = if (target.cpu.arch.isWasm()) .Obj else output_mode;
const bin_basename = try std.zig.binNameAlloc(comp.gpa, .{
.root_name = root_name,
.target = target,
- .output_mode = output_mode,
+ .output_mode = fixed_output_mode,
});
defer comp.gpa.free(bin_basename);
@@ -2598,7 +2635,7 @@ fn buildStaticLibFromZig(comp: *Compilation, src_basename: []const u8, out: *?CR
.target = target,
.root_name = root_name,
.root_pkg = &root_pkg,
- .output_mode = output_mode,
+ .output_mode = fixed_output_mode,
.rand = comp.rand,
.libc_installation = comp.bin_file.options.libc_installation,
.emit_bin = emit_bin,