authorgravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2025-07-07 03:42:51+02:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2025-07-07 03:42:51+02:00
logc96c913bab00bcae42991244381ddcc8b2377552
treec41c3bcd901a1626afa922ab665488a2d80fb572
parentef8db03d52e4eeeafa0cc4697703bd711ffda6c3
parent2bf9ff1b42ada9808aa5e78c758b3475baf8d60b
signaturebadge-check Signed by PGP key B5690EEEBB952194

Merge pull request #24352 from alexrp/wasi-emulated-libs

`wasi`: Build emulated libraries into `libc.a`

4 files changed, 75 insertions(+), 142 deletions(-)

src/Compilation.zig-13
...@@ -234,7 +234,6 @@ fuzzer_lib: ?CrtFile = null,...@@ -234,7 +234,6 @@ fuzzer_lib: ?CrtFile = null,
234glibc_so_files: ?glibc.BuiltSharedObjects = null,234glibc_so_files: ?glibc.BuiltSharedObjects = null,
235freebsd_so_files: ?freebsd.BuiltSharedObjects = null,235freebsd_so_files: ?freebsd.BuiltSharedObjects = null,
236netbsd_so_files: ?netbsd.BuiltSharedObjects = null,236netbsd_so_files: ?netbsd.BuiltSharedObjects = null,
237wasi_emulated_libs: []const wasi_libc.CrtFile,
238237
239/// For example `Scrt1.o` and `libc_nonshared.a`. These are populated after building libc from source,238/// For example `Scrt1.o` and `libc_nonshared.a`. These are populated after building libc from source,
240/// The set of needed CRT (C runtime) files differs depending on the target and compilation settings.239/// The set of needed CRT (C runtime) files differs depending on the target and compilation settings.
...@@ -1567,12 +1566,6 @@ pub const CreateOptions = struct {...@@ -1567,12 +1566,6 @@ pub const CreateOptions = struct {
1567 framework_dirs: []const []const u8 = &[0][]const u8{},1566 framework_dirs: []const []const u8 = &[0][]const u8{},
1568 frameworks: []const Framework = &.{},1567 frameworks: []const Framework = &.{},
1569 windows_lib_names: []const []const u8 = &.{},1568 windows_lib_names: []const []const u8 = &.{},
1570 /// These correspond to the WASI libc emulated subcomponents including:
1571 /// * process clocks
1572 /// * getpid
1573 /// * mman
1574 /// * signal
1575 wasi_emulated_libs: []const wasi_libc.CrtFile = &.{},
1576 /// This means that if the output mode is an executable it will be a1569 /// This means that if the output mode is an executable it will be a
1577 /// Position Independent Executable. If the output mode is not an1570 /// Position Independent Executable. If the output mode is not an
1578 /// executable this field is ignored.1571 /// executable this field is ignored.
...@@ -2055,7 +2048,6 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil...@@ -2055,7 +2048,6 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
2055 .function_sections = options.function_sections,2048 .function_sections = options.function_sections,
2056 .data_sections = options.data_sections,2049 .data_sections = options.data_sections,
2057 .native_system_include_paths = options.native_system_include_paths,2050 .native_system_include_paths = options.native_system_include_paths,
2058 .wasi_emulated_libs = options.wasi_emulated_libs,
2059 .force_undefined_symbols = options.force_undefined_symbols,2051 .force_undefined_symbols = options.force_undefined_symbols,
2060 .link_eh_frame_hdr = link_eh_frame_hdr,2052 .link_eh_frame_hdr = link_eh_frame_hdr,
2061 .global_cc_argv = options.global_cc_argv,2053 .global_cc_argv = options.global_cc_argv,
...@@ -2384,11 +2376,6 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil...@@ -2384,11 +2376,6 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
2384 } else if (target.isWasiLibC()) {2376 } else if (target.isWasiLibC()) {
2385 if (!std.zig.target.canBuildLibC(target)) return error.LibCUnavailable;2377 if (!std.zig.target.canBuildLibC(target)) return error.LibCUnavailable;
23862378
2387 for (comp.wasi_emulated_libs) |crt_file| {
2388 comp.queued_jobs.wasi_libc_crt_file[@intFromEnum(crt_file)] = true;
2389 }
2390 comp.link_task_queue.pending_prelink_tasks += @intCast(comp.wasi_emulated_libs.len);
2391
2392 comp.queued_jobs.wasi_libc_crt_file[@intFromEnum(wasi_libc.execModelCrtFile(comp.config.wasi_exec_model))] = true;2379 comp.queued_jobs.wasi_libc_crt_file[@intFromEnum(wasi_libc.execModelCrtFile(comp.config.wasi_exec_model))] = true;
2393 comp.queued_jobs.wasi_libc_crt_file[@intFromEnum(wasi_libc.CrtFile.libc_a)] = true;2380 comp.queued_jobs.wasi_libc_crt_file[@intFromEnum(wasi_libc.CrtFile.libc_a)] = true;
2394 comp.link_task_queue.pending_prelink_tasks += 2;2381 comp.link_task_queue.pending_prelink_tasks += 2;
src/libs/wasi_libc.zig+75-109
...@@ -10,43 +10,8 @@ pub const CrtFile = enum {...@@ -10,43 +10,8 @@ pub const CrtFile = enum {
10 crt1_reactor_o,10 crt1_reactor_o,
11 crt1_command_o,11 crt1_command_o,
12 libc_a,12 libc_a,
13 libdl_a,
14 libwasi_emulated_process_clocks_a,
15 libwasi_emulated_getpid_a,
16 libwasi_emulated_mman_a,
17 libwasi_emulated_signal_a,
18};13};
1914
20pub fn getEmulatedLibCrtFile(lib_name: []const u8) ?CrtFile {
21 if (mem.eql(u8, lib_name, "dl")) {
22 return .libdl_a;
23 }
24 if (mem.eql(u8, lib_name, "wasi-emulated-process-clocks")) {
25 return .libwasi_emulated_process_clocks_a;
26 }
27 if (mem.eql(u8, lib_name, "wasi-emulated-getpid")) {
28 return .libwasi_emulated_getpid_a;
29 }
30 if (mem.eql(u8, lib_name, "wasi-emulated-mman")) {
31 return .libwasi_emulated_mman_a;
32 }
33 if (mem.eql(u8, lib_name, "wasi-emulated-signal")) {
34 return .libwasi_emulated_signal_a;
35 }
36 return null;
37}
38
39pub fn emulatedLibCRFileLibName(crt_file: CrtFile) []const u8 {
40 return switch (crt_file) {
41 .libdl_a => "libdl.a",
42 .libwasi_emulated_process_clocks_a => "libwasi-emulated-process-clocks.a",
43 .libwasi_emulated_getpid_a => "libwasi-emulated-getpid.a",
44 .libwasi_emulated_mman_a => "libwasi-emulated-mman.a",
45 .libwasi_emulated_signal_a => "libwasi-emulated-signal.a",
46 else => unreachable,
47 };
48}
49
50pub fn execModelCrtFile(wasi_exec_model: std.builtin.WasiExecModel) CrtFile {15pub fn execModelCrtFile(wasi_exec_model: std.builtin.WasiExecModel) CrtFile {
51 return switch (wasi_exec_model) {16 return switch (wasi_exec_model) {
52 .reactor => CrtFile.crt1_reactor_o,17 .reactor => CrtFile.crt1_reactor_o,
...@@ -157,87 +122,57 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre...@@ -157,87 +122,57 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre
157 }122 }
158 }123 }
159124
160 try comp.build_crt_file("c", .Lib, .@"wasi libc.a", prog_node, libc_sources.items, .{});125 {
161 },126 // Compile libdl.
162127 var args = std.ArrayList([]const u8).init(arena);
163 .libdl_a => {128 try addCCArgs(comp, arena, &args, .{ .want_O3 = true });
164 var args = std.ArrayList([]const u8).init(arena);129 try addLibcBottomHalfIncludes(comp, arena, &args);
165 try addCCArgs(comp, arena, &args, .{ .want_O3 = true });
166 try addLibcBottomHalfIncludes(comp, arena, &args);
167130
168 var emu_dl_sources = std.ArrayList(Compilation.CSourceFile).init(arena);131 for (emulated_dl_src_files) |file_path| {
169 for (emulated_dl_src_files) |file_path| {132 try libc_sources.append(.{
170 try emu_dl_sources.append(.{133 .src_path = try comp.dirs.zig_lib.join(arena, &.{
171 .src_path = try comp.dirs.zig_lib.join(arena, &.{134 "libc", try sanitize(arena, file_path),
172 "libc", try sanitize(arena, file_path),135 }),
173 }),136 .extra_flags = args.items,
174 .extra_flags = args.items,137 .owner = undefined,
175 .owner = undefined,138 });
176 });139 }
177 }140 }
178 try comp.build_crt_file("dl", .Lib, .@"wasi libdl.a", prog_node, emu_dl_sources.items, .{});
179 },
180
181 .libwasi_emulated_process_clocks_a => {
182 var args = std.ArrayList([]const u8).init(arena);
183 try addCCArgs(comp, arena, &args, .{ .want_O3 = true });
184 try addLibcBottomHalfIncludes(comp, arena, &args);
185141
186 var emu_clocks_sources = std.ArrayList(Compilation.CSourceFile).init(arena);142 {
187 for (emulated_process_clocks_src_files) |file_path| {143 // Compile libwasi-emulated-process-clocks.
188 try emu_clocks_sources.append(.{144 var args = std.ArrayList([]const u8).init(arena);
189 .src_path = try comp.dirs.zig_lib.join(arena, &.{145 try addCCArgs(comp, arena, &args, .{ .want_O3 = true });
190 "libc", try sanitize(arena, file_path),146 try args.appendSlice(&.{
147 "-I",
148 try comp.dirs.zig_lib.join(arena, &.{
149 "libc",
150 "wasi",
151 "libc-bottom-half",
152 "cloudlibc",
153 "src",
191 }),154 }),
192 .extra_flags = args.items,
193 .owner = undefined,
194 });155 });
195 }
196 try comp.build_crt_file("wasi-emulated-process-clocks", .Lib, .@"libwasi-emulated-process-clocks.a", prog_node, emu_clocks_sources.items, .{});
197 },
198 .libwasi_emulated_getpid_a => {
199 var args = std.ArrayList([]const u8).init(arena);
200 try addCCArgs(comp, arena, &args, .{ .want_O3 = true });
201 try addLibcBottomHalfIncludes(comp, arena, &args);
202156
203 var emu_getpid_sources = std.ArrayList(Compilation.CSourceFile).init(arena);157 for (emulated_process_clocks_src_files) |file_path| {
204 for (emulated_getpid_src_files) |file_path| {158 try libc_sources.append(.{
205 try emu_getpid_sources.append(.{159 .src_path = try comp.dirs.zig_lib.join(arena, &.{
206 .src_path = try comp.dirs.zig_lib.join(arena, &.{160 "libc", try sanitize(arena, file_path),
207 "libc", try sanitize(arena, file_path),161 }),
208 }),162 .extra_flags = args.items,
209 .extra_flags = args.items,163 .owner = undefined,
210 .owner = undefined,164 });
211 });165 }
212 }
213 try comp.build_crt_file("wasi-emulated-getpid", .Lib, .@"libwasi-emulated-getpid.a", prog_node, emu_getpid_sources.items, .{});
214 },
215 .libwasi_emulated_mman_a => {
216 var args = std.ArrayList([]const u8).init(arena);
217 try addCCArgs(comp, arena, &args, .{ .want_O3 = true });
218 try addLibcBottomHalfIncludes(comp, arena, &args);
219
220 var emu_mman_sources = std.ArrayList(Compilation.CSourceFile).init(arena);
221 for (emulated_mman_src_files) |file_path| {
222 try emu_mman_sources.append(.{
223 .src_path = try comp.dirs.zig_lib.join(arena, &.{
224 "libc", try sanitize(arena, file_path),
225 }),
226 .extra_flags = args.items,
227 .owner = undefined,
228 });
229 }166 }
230 try comp.build_crt_file("wasi-emulated-mman", .Lib, .@"libwasi-emulated-mman.a", prog_node, emu_mman_sources.items, .{});
231 },
232 .libwasi_emulated_signal_a => {
233 var emu_signal_sources = std.ArrayList(Compilation.CSourceFile).init(arena);
234167
235 {168 {
169 // Compile libwasi-emulated-getpid.
236 var args = std.ArrayList([]const u8).init(arena);170 var args = std.ArrayList([]const u8).init(arena);
237 try addCCArgs(comp, arena, &args, .{ .want_O3 = true });171 try addCCArgs(comp, arena, &args, .{ .want_O3 = true });
172 try addLibcBottomHalfIncludes(comp, arena, &args);
238173
239 for (emulated_signal_bottom_half_src_files) |file_path| {174 for (emulated_getpid_src_files) |file_path| {
240 try emu_signal_sources.append(.{175 try libc_sources.append(.{
241 .src_path = try comp.dirs.zig_lib.join(arena, &.{176 .src_path = try comp.dirs.zig_lib.join(arena, &.{
242 "libc", try sanitize(arena, file_path),177 "libc", try sanitize(arena, file_path),
243 }),178 }),
...@@ -248,13 +183,13 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre...@@ -248,13 +183,13 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre
248 }183 }
249184
250 {185 {
186 // Compile libwasi-emulated-mman.
251 var args = std.ArrayList([]const u8).init(arena);187 var args = std.ArrayList([]const u8).init(arena);
252 try addCCArgs(comp, arena, &args, .{ .want_O3 = true });188 try addCCArgs(comp, arena, &args, .{ .want_O3 = true });
253 try addLibcTopHalfIncludes(comp, arena, &args);189 try addLibcBottomHalfIncludes(comp, arena, &args);
254 try args.append("-D_WASI_EMULATED_SIGNAL");
255190
256 for (emulated_signal_top_half_src_files) |file_path| {191 for (emulated_mman_src_files) |file_path| {
257 try emu_signal_sources.append(.{192 try libc_sources.append(.{
258 .src_path = try comp.dirs.zig_lib.join(arena, &.{193 .src_path = try comp.dirs.zig_lib.join(arena, &.{
259 "libc", try sanitize(arena, file_path),194 "libc", try sanitize(arena, file_path),
260 }),195 }),
...@@ -264,7 +199,38 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre...@@ -264,7 +199,38 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre
264 }199 }
265 }200 }
266201
267 try comp.build_crt_file("wasi-emulated-signal", .Lib, .@"libwasi-emulated-signal.a", prog_node, emu_signal_sources.items, .{});202 {
203 // Compile libwasi-emulated-signal.
204 var bottom_args = std.ArrayList([]const u8).init(arena);
205 try addCCArgs(comp, arena, &bottom_args, .{ .want_O3 = true });
206
207 for (emulated_signal_bottom_half_src_files) |file_path| {
208 try libc_sources.append(.{
209 .src_path = try comp.dirs.zig_lib.join(arena, &.{
210 "libc", try sanitize(arena, file_path),
211 }),
212 .extra_flags = bottom_args.items,
213 .owner = undefined,
214 });
215 }
216
217 var top_args = std.ArrayList([]const u8).init(arena);
218 try addCCArgs(comp, arena, &top_args, .{ .want_O3 = true });
219 try addLibcTopHalfIncludes(comp, arena, &top_args);
220 try top_args.append("-D_WASI_EMULATED_SIGNAL");
221
222 for (emulated_signal_top_half_src_files) |file_path| {
223 try libc_sources.append(.{
224 .src_path = try comp.dirs.zig_lib.join(arena, &.{
225 "libc", try sanitize(arena, file_path),
226 }),
227 .extra_flags = top_args.items,
228 .owner = undefined,
229 });
230 }
231 }
232
233 try comp.build_crt_file("c", .Lib, .@"wasi libc.a", prog_node, libc_sources.items, .{});
268 },234 },
269 }235 }
270}236}
src/link/Lld.zig-7
...@@ -1539,13 +1539,6 @@ fn wasmLink(lld: *Lld, arena: Allocator) !void {...@@ -1539,13 +1539,6 @@ fn wasmLink(lld: *Lld, arena: Allocator) !void {
15391539
1540 if (comp.config.link_libc and is_exe_or_dyn_lib) {1540 if (comp.config.link_libc and is_exe_or_dyn_lib) {
1541 if (target.os.tag == .wasi) {1541 if (target.os.tag == .wasi) {
1542 for (comp.wasi_emulated_libs) |crt_file| {
1543 try argv.append(try comp.crtFileAsString(
1544 arena,
1545 wasi_libc.emulatedLibCRFileLibName(crt_file),
1546 ));
1547 }
1548
1549 try argv.append(try comp.crtFileAsString(1542 try argv.append(try comp.crtFileAsString(
1550 arena,1543 arena,
1551 wasi_libc.execModelCrtFileFullName(comp.config.wasi_exec_model),1544 wasi_libc.execModelCrtFileFullName(comp.config.wasi_exec_model),
src/main.zig-13
...@@ -972,8 +972,6 @@ fn buildOutputType(...@@ -972,8 +972,6 @@ fn buildOutputType(
972 .windows_libs = .empty,972 .windows_libs = .empty,
973 .link_inputs = .empty,973 .link_inputs = .empty,
974974
975 .wasi_emulated_libs = .{},
976
977 .c_source_files = .{},975 .c_source_files = .{},
978 .rc_source_files = .{},976 .rc_source_files = .{},
979977
...@@ -3406,7 +3404,6 @@ fn buildOutputType(...@@ -3406,7 +3404,6 @@ fn buildOutputType(
3406 .framework_dirs = create_module.framework_dirs.items,3404 .framework_dirs = create_module.framework_dirs.items,
3407 .frameworks = resolved_frameworks.items,3405 .frameworks = resolved_frameworks.items,
3408 .windows_lib_names = create_module.windows_libs.keys(),3406 .windows_lib_names = create_module.windows_libs.keys(),
3409 .wasi_emulated_libs = create_module.wasi_emulated_libs.items,
3410 .want_compiler_rt = want_compiler_rt,3407 .want_compiler_rt = want_compiler_rt,
3411 .want_ubsan_rt = want_ubsan_rt,3408 .want_ubsan_rt = want_ubsan_rt,
3412 .hash_style = hash_style,3409 .hash_style = hash_style,
...@@ -3687,8 +3684,6 @@ const CreateModule = struct {...@@ -3687,8 +3684,6 @@ const CreateModule = struct {
3687 /// output. Allocated with gpa.3684 /// output. Allocated with gpa.
3688 link_inputs: std.ArrayListUnmanaged(link.Input),3685 link_inputs: std.ArrayListUnmanaged(link.Input),
36893686
3690 wasi_emulated_libs: std.ArrayListUnmanaged(wasi_libc.CrtFile),
3691
3692 c_source_files: std.ArrayListUnmanaged(Compilation.CSourceFile),3687 c_source_files: std.ArrayListUnmanaged(Compilation.CSourceFile),
3693 rc_source_files: std.ArrayListUnmanaged(Compilation.RcSourceFile),3688 rc_source_files: std.ArrayListUnmanaged(Compilation.RcSourceFile),
36943689
...@@ -3819,14 +3814,6 @@ fn createModule(...@@ -3819,14 +3814,6 @@ fn createModule(
3819 .name_query => |nq| {3814 .name_query => |nq| {
3820 const lib_name = nq.name;3815 const lib_name = nq.name;
38213816
3822 if (target.os.tag == .wasi) {
3823 if (wasi_libc.getEmulatedLibCrtFile(lib_name)) |crt_file| {
3824 try create_module.wasi_emulated_libs.append(arena, crt_file);
3825 create_module.opts.link_libc = true;
3826 continue;
3827 }
3828 }
3829
3830 if (std.zig.target.isLibCLibName(target, lib_name)) {3817 if (std.zig.target.isLibCLibName(target, lib_name)) {
3831 create_module.opts.link_libc = true;3818 create_module.opts.link_libc = true;
3832 continue;3819 continue;