Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 31 additions & 12 deletions src/Compilation.zig
Original file line number Diff line number Diff line change
Expand Up @@ -203,8 +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,
/// one of WASI libc static objects
wasi_libc_crt_file: wasi_libc.CRTFile,

/// Use stage1 C++ code to compile zig code into an object file.
stage1_module: void,
Expand Down Expand Up @@ -279,7 +279,7 @@ pub const MiscTask = enum {
libcxx,
libcxxabi,
libtsan,
wasi_libc_sysroot,
wasi_libc_crt_file,
compiler_rt,
libssp,
zig_libc,
Expand Down Expand Up @@ -646,6 +646,12 @@ pub const InitOptions = struct {
framework_dirs: []const []const u8 = &[0][]const u8{},
frameworks: []const []const u8 = &[0][]const u8{},
system_libs: []const []const u8 = &[0][]const u8{},
/// These correspond to the WASI libc emulated subcomponents including:
/// * process clocks
/// * getpid
/// * mman
/// * signal
wasi_emulated_libs: []const wasi_libc.CRTFile = &[0]wasi_libc.CRTFile{},
link_libc: bool = false,
link_libcpp: bool = false,
link_libunwind: bool = false,
Expand Down Expand Up @@ -1286,6 +1292,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
.framework_dirs = options.framework_dirs,
.system_libs = system_libs,
.syslibroot = darwin_options.syslibroot,
.wasi_emulated_libs = options.wasi_emulated_libs,
.lib_dirs = options.lib_dirs,
.rpath_list = options.rpath_list,
.strip = strip,
Expand Down Expand Up @@ -1426,8 +1433,19 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
},
});
}
if (comp.wantBuildWasiLibcSysrootFromSource()) {
try comp.work_queue.write(&[_]Job{.{ .wasi_libc_sysroot = {} }});
if (comp.wantBuildWasiLibcFromSource()) {
const wasi_emulated_libs = comp.bin_file.options.wasi_emulated_libs;
try comp.work_queue.ensureUnusedCapacity(wasi_emulated_libs.len + 2); // worst-case we need all components
for (wasi_emulated_libs) |crt_file| {
comp.work_queue.writeItemAssumeCapacity(.{
.wasi_libc_crt_file = crt_file,
});
}
// TODO add logic deciding which crt1 we want here.
comp.work_queue.writeAssumeCapacity(&[_]Job{
.{ .wasi_libc_crt_file = .crt1_o },
.{ .wasi_libc_crt_file = .libc_a },
});
}
if (comp.wantBuildMinGWFromSource()) {
const static_lib_jobs = [_]Job{
Expand Down Expand Up @@ -2169,12 +2187,12 @@ pub fn performAllTheWork(self: *Compilation) error{ TimerUnsupported, OutOfMemor
);
};
},
.wasi_libc_sysroot => {
wasi_libc.buildWasiLibcSysroot(self) catch |err| {
.wasi_libc_crt_file => |crt_file| {
wasi_libc.buildCRTFile(self, crt_file) catch |err| {
// TODO Surface more error details.
try self.setMiscFailure(
.wasi_libc_sysroot,
"unable to build WASI libc sysroot: {s}",
.wasi_libc_crt_file,
"unable to build WASI libc CRT file: {s}",
.{@errorName(err)},
);
};
Expand Down Expand Up @@ -3303,7 +3321,7 @@ pub fn get_libc_crt_file(comp: *Compilation, arena: *Allocator, basename: []cons
if (comp.wantBuildGLibCFromSource() or
comp.wantBuildMuslFromSource() or
comp.wantBuildMinGWFromSource() or
comp.wantBuildWasiLibcSysrootFromSource())
comp.wantBuildWasiLibcFromSource())
{
return comp.crt_files.get(basename).?.full_object_path;
}
Expand Down Expand Up @@ -3343,8 +3361,9 @@ fn wantBuildMuslFromSource(comp: Compilation) bool {
!comp.getTarget().isWasm();
}

fn wantBuildWasiLibcSysrootFromSource(comp: Compilation) bool {
return comp.wantBuildLibCFromSource() and comp.getTarget().isWasm();
fn wantBuildWasiLibcFromSource(comp: Compilation) bool {
return comp.wantBuildLibCFromSource() and comp.getTarget().isWasm() and
comp.getTarget().os.tag == .wasi;
}

fn wantBuildMinGWFromSource(comp: Compilation) bool {
Expand Down
2 changes: 2 additions & 0 deletions src/link.zig
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ const Type = @import("type.zig").Type;
const Cache = @import("Cache.zig");
const build_options = @import("build_options");
const LibCInstallation = @import("libc_installation.zig").LibCInstallation;
const wasi_libc = @import("wasi_libc.zig");

pub const producer_string = if (std.builtin.is_test) "zig test" else "zig " ++ build_options.version;

Expand Down Expand Up @@ -110,6 +111,7 @@ pub const Options = struct {
framework_dirs: []const []const u8,
frameworks: []const []const u8,
system_libs: std.StringArrayHashMapUnmanaged(void),
wasi_emulated_libs: []const wasi_libc.CRTFile,
lib_dirs: []const []const u8,
rpath_list: []const []const u8,

Expand Down
48 changes: 32 additions & 16 deletions src/link/Wasm.zig
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const codegen = @import("../codegen/wasm.zig");
const link = @import("../link.zig");
const trace = @import("../tracy.zig").trace;
const build_options = @import("build_options");
const wasi_libc = @import("../wasi_libc.zig");
const Cache = @import("../Cache.zig");
const TypedValue = @import("../TypedValue.zig");

Expand Down Expand Up @@ -574,7 +575,6 @@ 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";

Expand Down Expand Up @@ -653,19 +653,13 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation) !void {
try fs.cwd().copyFile(the_object_path, fs.cwd(), full_out_path, .{});
}
} else {
const is_obj = self.base.options.output_mode == .Obj;

// Create an LLD command line and invoke it.
var argv = std.ArrayList([]const u8).init(self.base.allocator);
defer argv.deinit();
// We will invoke ourselves as a child process to gain access to LLD.
// This is necessary because LLD does not behave properly as a library -
// it calls exit() and does not reset all global data between invocations.
try argv.appendSlice(&[_][]const u8{ comp.self_exe_path.?, "wasm-ld" });
if (is_obj) {
try argv.append("-r");
}

try argv.append("-error-limit=0");

if (self.base.options.lto) {
Expand Down Expand Up @@ -697,16 +691,38 @@ 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"));
}
if (target.os.tag == .wasi) {
if (self.base.options.link_libc and self.base.options.output_mode == .Exe) {
// TODO work out if we want standard crt, a reactor or a command
try argv.append(try comp.get_libc_crt_file(arena, "crt1.o"));
}

const is_exe_or_dyn_lib = self.base.options.output_mode == .Exe or
(self.base.options.output_mode == .Lib and self.base.options.link_mode == .Dynamic);
if (is_exe_or_dyn_lib) {
const system_libs = self.base.options.system_libs.keys();

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,
}));
for (system_libs) |link_lib| {
if (mem.eql(u8, "wasi_snapshot_preview1", link_lib)) {
// Any referenced symbol from this lib, will be undefined until
// runtime as this lib is provided directly by the runtime.
continue;
}
try argv.append(try std.fmt.allocPrint(arena, "-l{s}", .{link_lib}));
}

const wasi_emulated_libs = self.base.options.wasi_emulated_libs;
for (wasi_emulated_libs) |crt_file| {
try argv.append(try comp.get_libc_crt_file(
arena,
wasi_libc.emulatedLibCRFileLibName(crt_file),
));
}

if (self.base.options.link_libc) {
try argv.append(try comp.get_libc_crt_file(arena, "libc.a"));
}
}
}

// Positional arguments to the linker such as object files.
Expand Down
12 changes: 12 additions & 0 deletions src/main.zig
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const Package = @import("Package.zig");
const build_options = @import("build_options");
const introspect = @import("introspect.zig");
const LibCInstallation = @import("libc_installation.zig").LibCInstallation;
const wasi_libc = @import("wasi_libc.zig");
const translate_c = @import("translate_c.zig");
const Cache = @import("Cache.zig");
const target_util = @import("target.zig");
Expand Down Expand Up @@ -616,6 +617,9 @@ fn buildOutputType(
var system_libs = std.ArrayList([]const u8).init(gpa);
defer system_libs.deinit();

var wasi_emulated_libs = std.ArrayList(wasi_libc.CRTFile).init(gpa);
defer wasi_emulated_libs.deinit();

var clang_argv = std.ArrayList([]const u8).init(gpa);
defer clang_argv.deinit();

Expand Down Expand Up @@ -1586,6 +1590,13 @@ fn buildOutputType(
if (std.fs.path.isAbsolute(lib_name)) {
fatal("cannot use absolute path as a system library: {s}", .{lib_name});
}
if (target_info.target.os.tag == .wasi) {
if (wasi_libc.getEmulatedLibCRTFile(lib_name)) |crt_file| {
try wasi_emulated_libs.append(crt_file);
_ = system_libs.orderedRemove(i);
continue;
}
}
i += 1;
}
}
Expand Down Expand Up @@ -1895,6 +1906,7 @@ fn buildOutputType(
.framework_dirs = framework_dirs.items,
.frameworks = frameworks.items,
.system_libs = system_libs.items,
.wasi_emulated_libs = wasi_emulated_libs.items,
.link_libc = link_libc,
.link_libcpp = link_libcpp,
.link_libunwind = link_libunwind,
Expand Down
Loading