Commit 93a4403271

Jakub Konka <kubkon@jakubkonka.com>
2021-06-07 08:37:04
cc,wasi: package emulations as static archives
This replicates the expected behavior when using `clang` with upstream `wasi-libc` sysroot: linking emulated subcomponents such as process clocks or signals requires an explicit link flag in the compiler invocation, for example: ``` zig cc -target wasm32-wasi -lwasi-emulated-process-clocks main.c -o main.wasm ```
1 parent 6f6182a
Changed files (2)
src/link/Wasm.zig
@@ -702,11 +702,20 @@ fn linkWithLLD(self: *Wasm, comp: *Compilation) !void {
             try argv.append(try comp.get_libc_crt_file(arena, "crt.o"));
         }
 
-        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,
-            }));
+        if (!is_obj) {
+            const system_libs = self.base.options.system_libs.keys();
+            for (system_libs) |link_lib| {
+                const full_name = try std.fmt.allocPrint(arena, "lib{s}.a", .{link_lib});
+                if (comp.crt_files.get(full_name)) |crt| {
+                    try argv.append(crt.full_object_path);
+                } else {
+                    try argv.append(try std.fmt.allocPrint(arena, "-l{s}", .{link_lib}));
+                }
+            }
+
+            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.
src/wasi_libc.zig
@@ -23,21 +23,21 @@ pub fn buildWasiLibcSysroot(comp: *Compilation) !void {
         try addCCArgs(comp, arena, &args, false);
         try addLibcBottomHalfIncludes(comp, arena, &args);
 
-        var comp_sources = std.ArrayList(Compilation.CSourceFile).init(arena);
+        var crt_sources = std.ArrayList(Compilation.CSourceFile).init(arena);
         for (crt_src_files) |file_path| {
-            try comp_sources.append(.{
+            try crt_sources.append(.{
                 .src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{
                     "libc", try sanitize(arena, file_path),
                 }),
                 .extra_flags = args.items,
             });
         }
-        try comp.build_crt_file("crt", .Obj, comp_sources.items);
+        try comp.build_crt_file("crt", .Obj, crt_sources.items);
     }
 
     {
         // Compile WASI libc (sysroot).
-        var comp_sources = std.ArrayList(Compilation.CSourceFile).init(arena);
+        var libc_sources = std.ArrayList(Compilation.CSourceFile).init(arena);
 
         {
             // Compile dlmalloc.
@@ -54,7 +54,7 @@ pub fn buildWasiLibcSysroot(comp: *Compilation) !void {
             });
 
             for (dlmalloc_src_files) |file_path| {
-                try comp_sources.append(.{
+                try libc_sources.append(.{
                     .src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{
                         "libc", try sanitize(arena, file_path),
                     }),
@@ -70,7 +70,7 @@ pub fn buildWasiLibcSysroot(comp: *Compilation) !void {
             try addLibcBottomHalfIncludes(comp, arena, &args);
 
             for (libc_bottom_half_src_files) |file_path| {
-                try comp_sources.append(.{
+                try libc_sources.append(.{
                     .src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{
                         "libc", try sanitize(arena, file_path),
                     }),
@@ -80,63 +80,88 @@ pub fn buildWasiLibcSysroot(comp: *Compilation) !void {
         }
 
         {
-            // Compile emulated sources depending only on libc-bottom-half.
+            // Compile libc-top-half.
             var args = std.ArrayList([]const u8).init(arena);
             try addCCArgs(comp, arena, &args, true);
-            try addLibcBottomHalfIncludes(comp, arena, &args);
+            try addLibcTopHalfIncludes(comp, arena, &args);
 
-            for (emulated_process_clocks_src_files) |file_path| {
-                try comp_sources.append(.{
+            for (libc_top_half_src_files) |file_path| {
+                try libc_sources.append(.{
                     .src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{
                         "libc", try sanitize(arena, file_path),
                     }),
                     .extra_flags = args.items,
                 });
             }
+        }
 
-            for (emulated_getpid_src_files) |file_path| {
-                try comp_sources.append(.{
-                    .src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{
-                        "libc", try sanitize(arena, file_path),
-                    }),
-                    .extra_flags = args.items,
-                });
-            }
+        try comp.build_crt_file("c", .Lib, libc_sources.items);
+    }
 
-            for (emulated_mman_src_files) |file_path| {
-                try comp_sources.append(.{
-                    .src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{
-                        "libc", try sanitize(arena, file_path),
-                    }),
-                    .extra_flags = args.items,
-                });
-            }
+    {
+        // Compile emulated process clocks.
+        var args = std.ArrayList([]const u8).init(arena);
+        try addCCArgs(comp, arena, &args, true);
+        try addLibcBottomHalfIncludes(comp, arena, &args);
+
+        var emu_clocks_sources = std.ArrayList(Compilation.CSourceFile).init(arena);
+        for (emulated_process_clocks_src_files) |file_path| {
+            try emu_clocks_sources.append(.{
+                .src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{
+                    "libc", try sanitize(arena, file_path),
+                }),
+                .extra_flags = args.items,
+            });
         }
+        try comp.build_crt_file("wasi-emulated-process-clocks", .Lib, emu_clocks_sources.items);
+    }
 
-        {
-            // Compile emulated signals (bottom-half).
-            var args = std.ArrayList([]const u8).init(arena);
-            try addCCArgs(comp, arena, &args, true);
+    {
+        // Compile emulated getpid.
+        var args = std.ArrayList([]const u8).init(arena);
+        try addCCArgs(comp, arena, &args, true);
+        try addLibcBottomHalfIncludes(comp, arena, &args);
 
-            for (emulated_signal_bottom_half_src_files) |file_path| {
-                try comp_sources.append(.{
-                    .src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{
-                        "libc", try sanitize(arena, file_path),
-                    }),
-                    .extra_flags = args.items,
-                });
-            }
+        var emu_getpid_sources = std.ArrayList(Compilation.CSourceFile).init(arena);
+        for (emulated_getpid_src_files) |file_path| {
+            try emu_getpid_sources.append(.{
+                .src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{
+                    "libc", try sanitize(arena, file_path),
+                }),
+                .extra_flags = args.items,
+            });
+        }
+        try comp.build_crt_file("wasi-emulated-getpid", .Lib, emu_getpid_sources.items);
+    }
+
+    {
+        // Compile emulated mman.
+        var args = std.ArrayList([]const u8).init(arena);
+        try addCCArgs(comp, arena, &args, true);
+        try addLibcBottomHalfIncludes(comp, arena, &args);
+
+        var emu_mman_sources = std.ArrayList(Compilation.CSourceFile).init(arena);
+        for (emulated_mman_src_files) |file_path| {
+            try emu_mman_sources.append(.{
+                .src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{
+                    "libc", try sanitize(arena, file_path),
+                }),
+                .extra_flags = args.items,
+            });
         }
+        try comp.build_crt_file("wasi-emulated-mman", .Lib, emu_mman_sources.items);
+    }
+
+    {
+        // Compile emulated signals.
+        var emu_signal_sources = std.ArrayList(Compilation.CSourceFile).init(arena);
 
         {
-            // Compile emulated signals (top-half).
             var args = std.ArrayList([]const u8).init(arena);
             try addCCArgs(comp, arena, &args, true);
-            try addLibcTopHalfIncludes(comp, arena, &args);
-            try args.append("-D_WASI_EMULATED_SIGNAL");
 
-            for (emulated_signal_top_half_src_files) |file_path| {
-                try comp_sources.append(.{
+            for (emulated_signal_bottom_half_src_files) |file_path| {
+                try emu_signal_sources.append(.{
                     .src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{
                         "libc", try sanitize(arena, file_path),
                     }),
@@ -146,13 +171,13 @@ 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 addLibcTopHalfIncludes(comp, arena, &args);
+            try args.append("-D_WASI_EMULATED_SIGNAL");
 
-            for (libc_top_half_src_files) |file_path| {
-                try comp_sources.append(.{
+            for (emulated_signal_top_half_src_files) |file_path| {
+                try emu_signal_sources.append(.{
                     .src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{
                         "libc", try sanitize(arena, file_path),
                     }),
@@ -161,7 +186,7 @@ pub fn buildWasiLibcSysroot(comp: *Compilation) !void {
             }
         }
 
-        try comp.build_crt_file("c", .Lib, comp_sources.items);
+        try comp.build_crt_file("wasi-emulated-signal", .Lib, emu_signal_sources.items);
     }
 }