From 7b74de7d717e2167337ba8a23e73baf99239529f Mon Sep 17 00:00:00 2001 From: Jakub Konka Date: Tue, 18 May 2021 16:00:06 +0200 Subject: wasi,cc: fix naming and add stubs for building Rename include dir to match the convention: from `wasm32-wasi` to `wasm-wasi-musl` Add building stubs which will be used to build and cache WASI libc sysroot. --- src/Compilation.zig | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'src/Compilation.zig') diff --git a/src/Compilation.zig b/src/Compilation.zig index ff36df198a..5c856b6217 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -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, @@ -1414,6 +1418,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 }, @@ -2139,6 +2146,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", @@ -3285,6 +3302,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(); } -- cgit v1.2.3 From 6d5002028a2fe71b67d8106b30c6602bc8e44121 Mon Sep 17 00:00:00 2001 From: Jakub Konka Date: Wed, 19 May 2021 21:59:21 +0200 Subject: cc,wasi: link compiled WASI libc with wasm-ld --- lib/std/target.zig | 3 --- lib/std/zig.zig | 11 ++++++++++- src/Compilation.zig | 3 ++- src/link.zig | 4 +--- src/link/Wasm.zig | 13 +++++++++++++ src/wasi_libc.zig | 5 +++++ 6 files changed, 31 insertions(+), 8 deletions(-) (limited to 'src/Compilation.zig') diff --git a/lib/std/target.zig b/lib/std/target.zig index fb54d2e18f..aa65ca669e 100644 --- a/lib/std/target.zig +++ b/lib/std/target.zig @@ -1307,9 +1307,6 @@ pub const Target = struct { } pub fn libPrefix_cpu_arch_abi(cpu_arch: Cpu.Arch, abi: Abi) [:0]const u8 { - if (cpu_arch.isWasm()) { - return ""; - } switch (abi) { .msvc => return "", else => return "lib", diff --git a/lib/std/zig.zig b/lib/std/zig.zig index 911edbd21c..61e7ca5545 100644 --- a/lib/std/zig.zig +++ b/lib/std/zig.zig @@ -160,8 +160,17 @@ pub fn binNameAlloc(allocator: *std.mem.Allocator, options: BinNameOptions) erro }, .wasm => switch (options.output_mode) { .Exe => return std.fmt.allocPrint(allocator, "{s}{s}", .{ root_name, target.exeFileExt() }), + .Lib => { + switch (options.link_mode orelse .Static) { + .Static => return std.fmt.allocPrint(allocator, "{s}{s}.a", .{ + target.libPrefix(), root_name, + }), + .Dynamic => return std.fmt.allocPrint(allocator, "{s}{s}.wasm", .{ + target.libPrefix(), root_name, + }), + } + }, .Obj => return std.fmt.allocPrint(allocator, "{s}{s}", .{ root_name, target.oFileExt() }), - .Lib => return std.fmt.allocPrint(allocator, "{s}.wasm", .{root_name}), }, .c => return std.fmt.allocPrint(allocator, "{s}.c", .{root_name}), .spirv => return std.fmt.allocPrint(allocator, "{s}.spv", .{root_name}), diff --git a/src/Compilation.zig b/src/Compilation.zig index 5c856b6217..1d1f2f01b8 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -3262,7 +3262,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; } diff --git a/src/link.zig b/src/link.zig index 33b73a3360..7338593a0e 100644 --- a/src/link.zig +++ b/src/link.zig @@ -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) { diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig index 41b08b09d6..8e296b2b6a 100644 --- a/src/link/Wasm.zig +++ b/src/link/Wasm.zig @@ -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); diff --git a/src/wasi_libc.zig b/src/wasi_libc.zig index 5b7738204b..e2d3652928 100644 --- a/src/wasi_libc.zig +++ b/src/wasi_libc.zig @@ -17,6 +17,7 @@ pub fn buildWASILibcSysroot(comp: *Compilation) !void { const arena = &arena_allocator.allocator; { + // Compile crt sources. var args = std.ArrayList([]const u8).init(arena); try addCCArgs(comp, arena, &args, false); try args.appendSlice(&[_][]const u8{ @@ -62,9 +63,11 @@ pub fn buildWASILibcSysroot(comp: *Compilation) !void { } { + // Compile WASI libc (sysroot). var comp_sources = std.ArrayList(Compilation.CSourceFile).init(arena); { + // Compile dlmalloc. var args = std.ArrayList([]const u8).init(arena); try addCCArgs(comp, arena, &args, true); try args.appendSlice(&[_][]const u8{ @@ -88,6 +91,7 @@ pub fn buildWASILibcSysroot(comp: *Compilation) !void { } { + // Compile libc-bottom-half. var args = std.ArrayList([]const u8).init(arena); try addCCArgs(comp, arena, &args, true); try args.appendSlice(&[_][]const u8{ @@ -131,6 +135,7 @@ pub fn buildWASILibcSysroot(comp: *Compilation) !void { } { + // Compile libc-top-half. var args = std.ArrayList([]const u8).init(arena); try addCCArgs(comp, arena, &args, true); try args.appendSlice(&[_][]const u8{ -- cgit v1.2.3 From 3a5d0f7700dc28b523e17ba461874b807786b939 Mon Sep 17 00:00:00 2001 From: Jakub Konka Date: Thu, 20 May 2021 10:27:35 +0200 Subject: wasm: link dynamically by default when targeting wasm This matches the behaviour of other languages and leaves us the ability to create actual static Wasm archives with ``` zig build-lib -static some.zig ``` which can then be combined with other Wasm object files and linked into either a Wasm lib or executable using `wasm-ld`. Update langref to reflect the fact we now ship WASI libc. --- doc/langref.html.in | 2 ++ lib/std/zig.zig | 4 +--- src/Compilation.zig | 19 +++++++++---------- src/main.zig | 6 ++++++ src/target.zig | 1 + src/wasi_libc.zig | 2 +- 6 files changed, 20 insertions(+), 14 deletions(-) (limited to 'src/Compilation.zig') diff --git a/doc/langref.html.in b/doc/langref.html.in index 618cd953f1..d67f97f4c6 100644 --- a/doc/langref.html.in +++ b/doc/langref.html.in @@ -10280,6 +10280,7 @@ Operating Systems: ps4 elfiamcu tvos + wasi watchos mesa3d contiki @@ -10348,6 +10349,7 @@ Available libcs: sparc-linux-gnu sparcv9-linux-gnu wasm32-freestanding-musl + wasm32-wasi-musl x86_64-linux-gnu x86_64-linux-gnux32 x86_64-linux-musl diff --git a/lib/std/zig.zig b/lib/std/zig.zig index 61e7ca5545..083803e0c8 100644 --- a/lib/std/zig.zig +++ b/lib/std/zig.zig @@ -165,9 +165,7 @@ pub fn binNameAlloc(allocator: *std.mem.Allocator, options: BinNameOptions) erro .Static => return std.fmt.allocPrint(allocator, "{s}{s}.a", .{ target.libPrefix(), root_name, }), - .Dynamic => return std.fmt.allocPrint(allocator, "{s}{s}.wasm", .{ - target.libPrefix(), root_name, - }), + .Dynamic => return std.fmt.allocPrint(allocator, "{s}.wasm", .{root_name}), } }, .Obj => return std.fmt.allocPrint(allocator, "{s}{s}", .{ root_name, target.oFileExt() }), diff --git a/src/Compilation.zig b/src/Compilation.zig index 1d1f2f01b8..2af35b7d66 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -770,8 +770,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 @@ -1418,7 +1418,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { }, }); } - if (comp.wantBuildWASILibcSysrootFromSource()) { + if (comp.wantBuildWasiLibcSysrootFromSource()) { try comp.work_queue.write(&[_]Job{.{ .wasi_libc_sysroot = {} }}); } if (comp.wantBuildMinGWFromSource()) { @@ -1462,7 +1462,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 = {} }); @@ -2147,7 +2147,7 @@ pub fn performAllTheWork(self: *Compilation) error{ TimerUnsupported, OutOfMemor }; }, .wasi_libc_sysroot => { - wasi_libc.buildWASILibcSysroot(self) catch |err| { + wasi_libc.buildWasiLibcSysroot(self) catch |err| { // TODO Surface more error details. try self.setMiscFailure( .wasi_libc_sysroot, @@ -3263,7 +3263,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.wantBuildWasiLibcSysrootFromSource()) { return comp.crt_files.get(basename).?.full_object_path; } @@ -3303,7 +3303,7 @@ fn wantBuildMuslFromSource(comp: Compilation) bool { !comp.getTarget().isWasm(); } -fn wantBuildWASILibcSysrootFromSource(comp: Compilation) bool { +fn wantBuildWasiLibcSysrootFromSource(comp: Compilation) bool { return comp.wantBuildLibCFromSource() and comp.getTarget().isWasm(); } @@ -3610,11 +3610,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); @@ -3629,7 +3628,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, diff --git a/src/main.zig b/src/main.zig index b388329508..86d017b3b7 100644 --- a/src/main.zig +++ b/src/main.zig @@ -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. diff --git a/src/target.zig b/src/target.zig index cb6aecf645..2a3b1d858c 100644 --- a/src/target.zig +++ b/src/target.zig @@ -146,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, diff --git a/src/wasi_libc.zig b/src/wasi_libc.zig index e2d3652928..1fba312265 100644 --- a/src/wasi_libc.zig +++ b/src/wasi_libc.zig @@ -6,7 +6,7 @@ const Compilation = @import("Compilation.zig"); const build_options = @import("build_options"); const target_util = @import("target.zig"); -pub fn buildWASILibcSysroot(comp: *Compilation) !void { +pub fn buildWasiLibcSysroot(comp: *Compilation) !void { if (!build_options.have_llvm) { return error.ZigCompilerNotBuiltWithLLVMExtensions; } -- cgit v1.2.3 From b63c92f0b9ce7b3876c5f51e12a6ae249dfa4bac Mon Sep 17 00:00:00 2001 From: Jakub Konka Date: Thu, 20 May 2021 14:08:28 +0200 Subject: cc,wasi: do not add stack protector --- src/Compilation.zig | 4 ++-- src/wasi_libc.zig | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'src/Compilation.zig') diff --git a/src/Compilation.zig b/src/Compilation.zig index 2af35b7d66..6fd1a2f874 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -2896,7 +2896,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"); @@ -2908,7 +2908,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"); diff --git a/src/wasi_libc.zig b/src/wasi_libc.zig index 1fba312265..0885f4c5be 100644 --- a/src/wasi_libc.zig +++ b/src/wasi_libc.zig @@ -234,6 +234,7 @@ fn addCCArgs( try args.appendSlice(&[_][]const u8{ "-std=gnu17", "-fno-trapping-math", + "-fno-stack-protector", "-w", // ignore all warnings o_arg, -- cgit v1.2.3