From 4e4722a65e3bc3d6bb4518df3082ffea7c2a7c5d Mon Sep 17 00:00:00 2001 From: Jakub Konka Date: Mon, 7 Jun 2021 11:02:11 +0200 Subject: cc,wasi: build referenced-only emulated components Move parsing of system libs into `main.zig` next to where we decide if we should link libC, and, if targeting WASI, if the specified libname equals one of the emulated components, save it on the side and remove it from the system libs. Then, build *only* those parts of WASI libc that were preserved in the previous step. This also fixes building of different crt1 bits needed to support reactors and commands. --- src/Compilation.zig | 43 +++++++++++++++++++++++++++++++------------ 1 file changed, 31 insertions(+), 12 deletions(-) (limited to 'src/Compilation.zig') diff --git a/src/Compilation.zig b/src/Compilation.zig index 4c015cb58f..444e69c557 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -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, @@ -279,7 +279,7 @@ pub const MiscTask = enum { libcxx, libcxxabi, libtsan, - wasi_libc_sysroot, + wasi_libc_crt_file, compiler_rt, libssp, zig_libc, @@ -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 []const u8 = &[0][]const u8{}, link_libc: bool = false, link_libcpp: bool = false, link_libunwind: bool = false, @@ -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, @@ -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()) { + try comp.work_queue.ensureUnusedCapacity(6); // worst-case we need all components + const wasi_emulated_libs = comp.bin_file.options.wasi_emulated_libs; + for (wasi_emulated_libs) |lib_name| { + comp.work_queue.writeItemAssumeCapacity(.{ + .wasi_libc_crt_file = wasi_libc.getEmulatedLibCRTFile(lib_name).?, + }); + } + // 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{ @@ -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)}, ); }; @@ -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; } @@ -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 { -- cgit v1.2.3 From 95745f77da6cd3ca30aea6aa47253c1e0a4f5a75 Mon Sep 17 00:00:00 2001 From: Jakub Konka Date: Mon, 7 Jun 2021 16:08:43 +0200 Subject: wasi: skip adding wasi_snapshot_preview1 as lib dep in stage1 --- src/Compilation.zig | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src/Compilation.zig') diff --git a/src/Compilation.zig b/src/Compilation.zig index 444e69c557..1d85182f06 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -4157,6 +4157,12 @@ pub fn stage1AddLinkLib(comp: *Compilation, lib_name: []const u8) !void { if (comp.bin_file.options.skip_linker_dependencies) return; // This happens when an `extern "foo"` function is referenced by the stage1 backend. + if (comp.getTarget().os.tag == .wasi and mem.eql(u8, "wasi_snapshot_preview1", lib_name)) { + // Any referenced symbol from this lib, will be undefined until + // runtime as this lib is provided directly by the runtime. + return; + } + // If we haven't seen this library yet and we're targeting Windows, we need to queue up // a work item to produce the DLL import library for this. const gop = try comp.bin_file.options.system_libs.getOrPut(comp.gpa, lib_name); -- cgit v1.2.3 From 2ee1f7898b27447bb9b21d284842415c7459db4b Mon Sep 17 00:00:00 2001 From: Jakub Konka Date: Wed, 9 Jun 2021 01:23:05 +0200 Subject: cc,wasi: store CRTFile enum in wasi_emulated_libs * then, in `link/Wasm.zig` map `CRTFile` to full emulated libs name * move logic for removing any mention of WASI snapshot `wasi_snapshot_preview1` from `Compilation.zig` into `link/Wasm.zig` --- src/Compilation.zig | 14 ++++---------- src/link.zig | 3 ++- src/link/Wasm.zig | 15 ++++++++++++--- src/main.zig | 6 +++--- src/wasi_libc.zig | 10 ++++++++++ 5 files changed, 31 insertions(+), 17 deletions(-) (limited to 'src/Compilation.zig') diff --git a/src/Compilation.zig b/src/Compilation.zig index 1d85182f06..371bcdaf18 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -651,7 +651,7 @@ pub const InitOptions = struct { /// * getpid /// * mman /// * signal - wasi_emulated_libs: []const []const u8 = &[0][]const u8{}, + wasi_emulated_libs: []const wasi_libc.CRTFile = &[0]wasi_libc.CRTFile{}, link_libc: bool = false, link_libcpp: bool = false, link_libunwind: bool = false, @@ -1434,11 +1434,11 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { }); } if (comp.wantBuildWasiLibcFromSource()) { - try comp.work_queue.ensureUnusedCapacity(6); // worst-case we need all components const wasi_emulated_libs = comp.bin_file.options.wasi_emulated_libs; - for (wasi_emulated_libs) |lib_name| { + 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 = wasi_libc.getEmulatedLibCRTFile(lib_name).?, + .wasi_libc_crt_file = crt_file, }); } // TODO add logic deciding which crt1 we want here. @@ -4157,12 +4157,6 @@ pub fn stage1AddLinkLib(comp: *Compilation, lib_name: []const u8) !void { if (comp.bin_file.options.skip_linker_dependencies) return; // This happens when an `extern "foo"` function is referenced by the stage1 backend. - if (comp.getTarget().os.tag == .wasi and mem.eql(u8, "wasi_snapshot_preview1", lib_name)) { - // Any referenced symbol from this lib, will be undefined until - // runtime as this lib is provided directly by the runtime. - return; - } - // If we haven't seen this library yet and we're targeting Windows, we need to queue up // a work item to produce the DLL import library for this. const gop = try comp.bin_file.options.system_libs.getOrPut(comp.gpa, lib_name); diff --git a/src/link.zig b/src/link.zig index c013db4947..4072e90ca3 100644 --- a/src/link.zig +++ b/src/link.zig @@ -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; @@ -110,7 +111,7 @@ pub const Options = struct { framework_dirs: []const []const u8, frameworks: []const []const u8, system_libs: std.StringArrayHashMapUnmanaged(void), - wasi_emulated_libs: []const []const u8, + wasi_emulated_libs: []const wasi_libc.CRTFile, lib_dirs: []const []const u8, rpath_list: []const []const u8, diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig index 39f1f13e60..21bb9d826c 100644 --- a/src/link/Wasm.zig +++ b/src/link/Wasm.zig @@ -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"); @@ -700,14 +701,22 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation) !void { (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(); + 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) |lib_name| { - const full_lib_name = try std.fmt.allocPrint(arena, "lib{s}.a", .{lib_name}); - try argv.append(try comp.get_libc_crt_file(arena, full_lib_name)); + 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) { diff --git a/src/main.zig b/src/main.zig index 1e4ec0183f..0b93f97726 100644 --- a/src/main.zig +++ b/src/main.zig @@ -617,7 +617,7 @@ fn buildOutputType( var system_libs = std.ArrayList([]const u8).init(gpa); defer system_libs.deinit(); - var wasi_emulated_libs = std.ArrayList([]const u8).init(gpa); + 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); @@ -1591,8 +1591,8 @@ fn buildOutputType( 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)) |_| { - try wasi_emulated_libs.append(lib_name); + if (wasi_libc.getEmulatedLibCRTFile(lib_name)) |crt_file| { + try wasi_emulated_libs.append(crt_file); _ = system_libs.orderedRemove(i); continue; } diff --git a/src/wasi_libc.zig b/src/wasi_libc.zig index 0c178891c7..b61ba5091c 100644 --- a/src/wasi_libc.zig +++ b/src/wasi_libc.zig @@ -35,6 +35,16 @@ pub fn getEmulatedLibCRTFile(lib_name: []const u8) ?CRTFile { return null; } +pub fn emulatedLibCRFileLibName(crt_file: CRTFile) []const u8 { + return switch (crt_file) { + .libwasi_emulated_process_clocks_a => "libwasi-emulated-process-clocks.a", + .libwasi_emulated_getpid_a => "libwasi-emulated-getpid.a", + .libwasi_emulated_mman_a => "libwasi-emulated-mman.a", + .libwasi_emulated_signal_a => "libwasi-emulated-signal.a", + else => unreachable, + }; +} + pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void { if (!build_options.have_llvm) { return error.ZigCompilerNotBuiltWithLLVMExtensions; -- cgit v1.2.3