Merge pull request #8837 from ziglang/cc-wasm32-wasi

cc,wasi: ship WASI libc and autobuild it when needed
This commit is contained in:
Jakub Konka
2021-05-21 09:04:16 +02:00
committed by GitHub
2439 changed files with 125821 additions and 16 deletions

View File

@@ -21,6 +21,7 @@ const musl = @import("musl.zig");
const mingw = @import("mingw.zig");
const libunwind = @import("libunwind.zig");
const libcxx = @import("libcxx.zig");
const wasi_libc = @import("wasi_libc.zig");
const fatal = @import("main.zig").fatal;
const Module = @import("Module.zig");
const Cache = @import("Cache.zig");
@@ -202,6 +203,8 @@ const Job = union(enum) {
/// needed when not linking libc and using LLVM for code generation because it generates
/// calls to, for example, memcpy and memset.
zig_libc: void,
/// WASI libc sysroot
wasi_libc_sysroot: void,
/// Use stage1 C++ code to compile zig code into an object file.
stage1_module: void,
@@ -276,6 +279,7 @@ pub const MiscTask = enum {
libcxx,
libcxxabi,
libtsan,
wasi_libc_sysroot,
compiler_rt,
libssp,
zig_libc,
@@ -769,8 +773,8 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
.Lib => is_dyn_lib,
.Exe => true,
};
const needs_c_symbols = !options.skip_linker_dependencies and
(is_exe_or_dyn_lib or (options.target.isWasm() and options.output_mode != .Obj));
const needs_c_symbols = !options.skip_linker_dependencies and is_exe_or_dyn_lib;
const comp: *Compilation = comp: {
// For allocations that have the same lifetime as Compilation. This arena is used only during this
@@ -1417,6 +1421,9 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
},
});
}
if (comp.wantBuildWasiLibcSysrootFromSource()) {
try comp.work_queue.write(&[_]Job{.{ .wasi_libc_sysroot = {} }});
}
if (comp.wantBuildMinGWFromSource()) {
const static_lib_jobs = [_]Job{
.{ .mingw_crt_file = .mingw32_lib },
@@ -1458,7 +1465,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
// 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 or comp.getTarget().isWasm()) {
if (is_exe_or_dyn_lib) {
try comp.work_queue.writeItem(.{ .compiler_rt_lib = {} });
} else {
try comp.work_queue.writeItem(.{ .compiler_rt_obj = {} });
@@ -2142,6 +2149,16 @@ pub fn performAllTheWork(self: *Compilation) error{ TimerUnsupported, OutOfMemor
);
};
},
.wasi_libc_sysroot => {
wasi_libc.buildWasiLibcSysroot(self) catch |err| {
// TODO Surface more error details.
try self.setMiscFailure(
.wasi_libc_sysroot,
"unable to build WASI libc sysroot: {s}",
.{@errorName(err)},
);
};
},
.compiler_rt_lib => {
self.buildOutputFromZig(
"compiler_rt.zig",
@@ -2882,7 +2899,7 @@ pub fn addCCArgs(
try argv.append("-D_DEBUG");
try argv.append("-Og");
if (comp.bin_file.options.link_libc) {
if (comp.bin_file.options.link_libc and target.os.tag != .wasi) {
try argv.append("-fstack-protector-strong");
try argv.append("--param");
try argv.append("ssp-buffer-size=4");
@@ -2894,7 +2911,7 @@ pub fn addCCArgs(
// See the comment in the BuildModeFastRelease case for why we pass -O2 rather
// than -O3 here.
try argv.append("-O2");
if (comp.bin_file.options.link_libc) {
if (comp.bin_file.options.link_libc and target.os.tag != .wasi) {
try argv.append("-D_FORTIFY_SOURCE=2");
try argv.append("-fstack-protector-strong");
try argv.append("--param");
@@ -3248,7 +3265,8 @@ fn detectLibCFromLibCInstallation(arena: *Allocator, target: Target, lci: *const
pub fn get_libc_crt_file(comp: *Compilation, arena: *Allocator, basename: []const u8) ![]const u8 {
if (comp.wantBuildGLibCFromSource() or
comp.wantBuildMuslFromSource() or
comp.wantBuildMinGWFromSource())
comp.wantBuildMinGWFromSource() or
comp.wantBuildWasiLibcSysrootFromSource())
{
return comp.crt_files.get(basename).?.full_object_path;
}
@@ -3288,6 +3306,10 @@ fn wantBuildMuslFromSource(comp: Compilation) bool {
!comp.getTarget().isWasm();
}
fn wantBuildWasiLibcSysrootFromSource(comp: Compilation) bool {
return comp.wantBuildLibCFromSource() and comp.getTarget().isWasm();
}
fn wantBuildMinGWFromSource(comp: Compilation) bool {
return comp.wantBuildLibCFromSource() and comp.getTarget().isMinGW();
}
@@ -3591,11 +3613,10 @@ fn buildOutputFromZig(
};
const root_name = src_basename[0 .. src_basename.len - std.fs.path.extension(src_basename).len];
const target = comp.getTarget();
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 = fixed_output_mode,
.output_mode = output_mode,
});
defer comp.gpa.free(bin_basename);
@@ -3610,7 +3631,7 @@ fn buildOutputFromZig(
.target = target,
.root_name = root_name,
.root_pkg = &root_pkg,
.output_mode = fixed_output_mode,
.output_mode = output_mode,
.thread_pool = comp.thread_pool,
.libc_installation = comp.bin_file.options.libc_installation,
.emit_bin = emit_bin,

View File

@@ -412,9 +412,7 @@ pub const File = struct {
return;
}
const use_lld = build_options.have_llvm and base.options.use_lld;
if (use_lld and base.options.output_mode == .Lib and base.options.link_mode == .Static and
!base.options.target.isWasm())
{
if (use_lld and base.options.output_mode == .Lib and base.options.link_mode == .Static) {
return base.linkAsArchive(comp);
}
switch (base.tag) {

View File

@@ -573,6 +573,7 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation) !void {
null;
const target = self.base.options.target;
const link_in_crt = self.base.options.link_libc and self.base.options.output_mode == .Exe;
const id_symlink_basename = "lld.id";
@@ -695,6 +696,18 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation) !void {
full_out_path,
});
if (link_in_crt) {
// TODO work out if we want standard crt, a reactor or a command
try argv.append(try comp.get_libc_crt_file(arena, "crt.o.wasm"));
}
if (!is_obj and self.base.options.link_libc) {
try argv.append(try comp.get_libc_crt_file(arena, switch (self.base.options.link_mode) {
.Static => "libc.a",
.Dynamic => unreachable,
}));
}
// Positional arguments to the linker such as object files.
try argv.appendSlice(self.base.options.objects);

View File

@@ -1548,6 +1548,12 @@ fn buildOutputType(
link_libcpp = true;
}
if (cross_target.getCpuArch().isWasm() and output_mode == .Lib and link_mode == null) {
// If link_mode is unspecified, always link as dynamic library when targeting Wasm,
// so that wasm-ld is invoked rather than standard archiver.
link_mode = .Dynamic;
}
// Now that we have target info, we can find out if any of the system libraries
// are part of libc or libc++. We remove them from the list and communicate their
// existence via flags instead.

View File

@@ -57,6 +57,7 @@ pub const available_libcs = [_]ArchOsAbi{
.{ .arch = .sparc, .os = .linux, .abi = .gnu },
.{ .arch = .sparcv9, .os = .linux, .abi = .gnu },
.{ .arch = .wasm32, .os = .freestanding, .abi = .musl },
.{ .arch = .wasm32, .os = .wasi, .abi = .musl },
.{ .arch = .x86_64, .os = .linux, .abi = .gnu },
.{ .arch = .x86_64, .os = .linux, .abi = .gnux32 },
.{ .arch = .x86_64, .os = .linux, .abi = .musl },
@@ -145,6 +146,7 @@ pub fn libcNeedsLibUnwind(target: std.Target) bool {
.watchos,
.tvos,
.freestanding,
.wasi, // Wasm/WASI currently doesn't offer support for libunwind, so don't link it.
=> false,
.windows => target.abi != .msvc,

1026
src/wasi_libc.zig Normal file

File diff suppressed because it is too large Load Diff