From 1cb7a01b25349c42dbe207b68f9e19b92890b3d2 Mon Sep 17 00:00:00 2001 From: Luuk de Gram Date: Wed, 30 Aug 2023 16:59:48 +0200 Subject: [PATCH 1/5] wasm-linker: implement `-fno-entry` flag This adds support for the `-fno-entry` and `-fentry` flags respectively, for zig build-{exe/lib} and the build system. For `zig cc` we use the `--no-entry` flag to be compatible with clang and existing tooling. In `start.zig` we now make the main function optional when the target is WebAssembly, as to allow for the build-exe command in combination with `-fno-entry`. When the execution model is set, and is set to 'reactor', we now verify when an entry name is given it matches what is expected. When no entry point is given, we set it to `_initialize` by default. This means the user will also be met with an error when they use the reactor model, but did not provide the correct function. --- lib/std/Build/Step/Compile.zig | 3 +++ lib/std/start.zig | 8 ++++++-- src/Compilation.zig | 3 +++ src/link.zig | 1 + src/link/Wasm.zig | 24 +++++------------------- src/main.zig | 29 +++++++++++++++++++++++++++++ 6 files changed, 47 insertions(+), 21 deletions(-) diff --git a/lib/std/Build/Step/Compile.zig b/lib/std/Build/Step/Compile.zig index 9ede31c9172b05baf6aad9181f21d39b2b70e544..18977ac472a6d15169828b1b05ff0ddf0b8b8736 100644 --- a/lib/std/Build/Step/Compile.zig +++ b/lib/std/Build/Step/Compile.zig @@ -64,6 +64,8 @@ initial_memory: ?u64 = null, max_memory: ?u64 = null, shared_memory: bool = false, global_base: ?u64 = null, +/// For WebAssembly only. Tells the linker to not output an entry point. +no_entry: ?bool = null, c_std: std.Build.CStd, /// Set via options; intended to be read-only after that. zig_lib_dir: ?LazyPath, @@ -1851,6 +1853,7 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { if (self.global_base) |global_base| { try zig_args.append(b.fmt("--global-base={d}", .{global_base})); } + try addFlag(&zig_args, "entry", self.no_entry); if (self.code_model != .default) { try zig_args.append("-mcmodel"); diff --git a/lib/std/start.zig b/lib/std/start.zig index 7ed59a467590feb15994bd44b9421e3eec52acf4..29fdb3b031260dfc484a2a9267ee34dfd1614c97 100644 --- a/lib/std/start.zig +++ b/lib/std/start.zig @@ -82,11 +82,15 @@ comptime { .reactor => "_initialize", .command => "_start", }; - if (!@hasDecl(root, wasm_start_sym)) { + if (!@hasDecl(root, wasm_start_sym) and @hasDecl(root, "main")) { + // Only call main when defined. For WebAssembly it's allowed to pass `-fno-entry` in which + // case it's not required to provide an entrypoint such as main. @export(wasi_start, .{ .name = wasm_start_sym }); } } else if (native_arch.isWasm() and native_os == .freestanding) { - if (!@hasDecl(root, start_sym_name)) @export(wasm_freestanding_start, .{ .name = start_sym_name }); + // Only call main when defined. For WebAssembly it's allowed to pass `-fno-entry` in which + // case it's not required to provide an entrypoint such as main. + if (!@hasDecl(root, start_sym_name) and @hasDecl(root, "main")) @export(wasm_freestanding_start, .{ .name = start_sym_name }); } else if (native_os != .other and native_os != .freestanding) { if (!@hasDecl(root, start_sym_name)) @export(_start, .{ .name = start_sym_name }); } diff --git a/src/Compilation.zig b/src/Compilation.zig index 954acd44b76b3b0d6373ef941aa1c55c8b40cf4b..1d60be20a5a31c88a397c5b5097d8e9612e6c8ea 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -643,6 +643,7 @@ pub const InitOptions = struct { linker_import_symbols: bool = false, linker_import_table: bool = false, linker_export_table: bool = false, + linker_no_entry: bool = false, linker_initial_memory: ?u64 = null, linker_max_memory: ?u64 = null, linker_shared_memory: bool = false, @@ -1614,6 +1615,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { .import_symbols = options.linker_import_symbols, .import_table = options.linker_import_table, .export_table = options.linker_export_table, + .no_entry = options.linker_no_entry, .initial_memory = options.linker_initial_memory, .max_memory = options.linker_max_memory, .shared_memory = options.linker_shared_memory, @@ -2577,6 +2579,7 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes man.hash.addOptional(comp.bin_file.options.max_memory); man.hash.add(comp.bin_file.options.shared_memory); man.hash.addOptional(comp.bin_file.options.global_base); + man.hash.add(comp.bin_file.options.no_entry); // Mach-O specific stuff man.hash.addListOfBytes(comp.bin_file.options.framework_dirs); diff --git a/src/link.zig b/src/link.zig index 1648d6a63efa340f27fe003246eb369ccfbe0eeb..a49582aac9b1a100a565316dcb0654a70faf9cd2 100644 --- a/src/link.zig +++ b/src/link.zig @@ -166,6 +166,7 @@ pub const Options = struct { export_table: bool, initial_memory: ?u64, max_memory: ?u64, + no_entry: bool, shared_memory: bool, export_symbol_names: []const []const u8, global_base: ?u64, diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig index fdac89f8373e7d7df6084b845bdaddd6feb8dab3..135803007aadfd4e4343f81fb7a7628e2ce17fe7 100644 --- a/src/link/Wasm.zig +++ b/src/link/Wasm.zig @@ -2817,14 +2817,10 @@ fn setupExports(wasm: *Wasm) !void { } fn setupStart(wasm: *Wasm) !void { + if (wasm.base.options.no_entry) return; const entry_name = wasm.base.options.entry orelse "_start"; const symbol_loc = wasm.findGlobalSymbol(entry_name) orelse { - if (wasm.base.options.output_mode == .Exe) { - if (wasm.base.options.wasi_exec_model == .reactor) return; // Not required for reactors - } else { - return; // No entry point needed for non-executable wasm files - } log.err("Entry symbol '{s}' missing", .{entry_name}); return error.MissingSymbol; }; @@ -4544,24 +4540,14 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) ! const arg = try std.fmt.allocPrint(arena, "stack-size={d}", .{stack_size}); try argv.append(arg); - if (wasm.base.options.output_mode == .Exe) { - if (wasm.base.options.wasi_exec_model == .reactor) { - // Reactor execution model does not have _start so lld doesn't look for it. - try argv.append("--no-entry"); - // Make sure "_initialize" and other used-defined functions are exported if this is WASI reactor. - // If rdynamic is true, it will already be appended, so only verify if the user did not specify - // the flag in which case, we ensure `--export-dynamic` is called. - if (!wasm.base.options.rdynamic) { - try argv.append("--export-dynamic"); - } - } - } else if (wasm.base.options.entry == null) { - try argv.append("--no-entry"); // So lld doesn't look for _start. - } if (wasm.base.options.import_symbols) { try argv.append("--allow-undefined"); } + if (wasm.base.options.no_entry) { + try argv.append("--no-entry"); + } + // XXX - TODO: add when wasm-ld supports --build-id. // if (wasm.base.options.build_id) { // try argv.append("--build-id=tree"); diff --git a/src/main.zig b/src/main.zig index cbc7283eefb991430cfc8fe01611e5b40e34798d..fc7e43b16f7f33788e3bbba171d1407cfad80e8a 100644 --- a/src/main.zig +++ b/src/main.zig @@ -577,6 +577,8 @@ const usage_build_generic = \\ --shared-memory (WebAssembly) use shared linear memory \\ --global-base=[addr] (WebAssembly) where to start to place global data \\ --export=[value] (WebAssembly) Force a symbol to be exported + \\ -fentry (WebAssembly) Force output an entry point + \\ -fno-entry (WebAssembly) Do not output any entry point \\ \\Test Options: \\ --test-filter [text] Skip tests that do not match filter @@ -835,6 +837,7 @@ fn buildOutputType( var linker_import_symbols: bool = false; var linker_import_table: bool = false; var linker_export_table: bool = false; + var linker_no_entry: ?bool = null; var linker_initial_memory: ?u64 = null; var linker_max_memory: ?u64 = null; var linker_shared_memory: bool = false; @@ -1503,6 +1506,10 @@ fn buildOutputType( } } else if (mem.eql(u8, arg, "--import-memory")) { linker_import_memory = true; + } else if (mem.eql(u8, arg, "-fentry")) { + linker_no_entry = false; + } else if (mem.eql(u8, arg, "-fno-entry")) { + linker_no_entry = true; } else if (mem.eql(u8, arg, "--export-memory")) { linker_export_memory = true; } else if (mem.eql(u8, arg, "--import-symbols")) { @@ -2134,6 +2141,8 @@ fn buildOutputType( linker_import_table = true; } else if (mem.eql(u8, arg, "--export-table")) { linker_export_table = true; + } else if (mem.eql(u8, arg, "--no-entry")) { + linker_no_entry = true; } else if (mem.eql(u8, arg, "--initial-memory")) { const next_arg = linker_args_it.nextOrFatal(); linker_initial_memory = std.fmt.parseUnsigned(u32, eatIntPrefix(next_arg, 16), 16) catch |err| { @@ -2618,6 +2627,25 @@ fn buildOutputType( if (single_threaded == null) { single_threaded = true; } + if (wasi_exec_model) |model| { + if (model == .reactor) { + if (linker_no_entry != null and !linker_no_entry.?) { + fatal("WASI exucution model 'reactor' incompatible with flag '-fentry'. Reactor execution model has no entry point", .{}); + } + if (entry) |entry_name| { + if (!mem.eql(u8, "_initialize", entry_name)) { + fatal("the entry symbol of the reactor model must be '_initialize', but found '{s}'", .{entry_name}); + } + } else { + entry = "_initialize"; + } + } + } + if (linker_no_entry) |no_entry| { + if (no_entry and entry != null) { + fatal("combination of '--entry' and `-fno-entry` are incompatible", .{}); + } + } if (linker_shared_memory) { if (output_mode == .Obj) { fatal("shared memory is not allowed in object files", .{}); @@ -3465,6 +3493,7 @@ fn buildOutputType( .linker_import_symbols = linker_import_symbols, .linker_import_table = linker_import_table, .linker_export_table = linker_export_table, + .linker_no_entry = linker_no_entry orelse false, .linker_initial_memory = linker_initial_memory, .linker_max_memory = linker_max_memory, .linker_shared_memory = linker_shared_memory, -- 2.54.0 From 58618afaee7c14feedad4f115e9a4468bac4c529 Mon Sep 17 00:00:00 2001 From: Luuk de Gram Date: Thu, 31 Aug 2023 17:12:12 +0200 Subject: [PATCH 2/5] wasm-linker: correctly pass --shared and --pie When linking a WebAssembly binary using wasm-ld, we will now correctly pass --shared when building a dynamic library and --pie when `-fpic` is given. This is a breaking change and users who currently build dynamic libraries for WebAssembly but wish to have an executable without a main, should use build-exe instead while supplying `-fno-entry`. We also verify the user does not supply --export-memory when -dynamic is enabled. By default we set this flag now to 'false' when `-dynamic` is used to ensure we do not enable it as it's enabled by default for regular WebAssembly binaries. --- src/link/Wasm.zig | 7 +++++++ src/main.zig | 10 ++++++++++ 2 files changed, 17 insertions(+) diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig index 135803007aadfd4e4343f81fb7a7628e2ce17fe7..ad9f8266f069ba14b7023ad5fa0e15b5fb8ae4e2 100644 --- a/src/link/Wasm.zig +++ b/src/link/Wasm.zig @@ -4548,6 +4548,13 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) ! try argv.append("--no-entry"); } + if (wasm.base.options.output_mode == .Lib and wasm.base.options.link_mode == .Dynamic) { + try argv.append("--shared"); + } + if (wasm.base.options.pie) { + try argv.append("--pie"); + } + // XXX - TODO: add when wasm-ld supports --build-id. // if (wasm.base.options.build_id) { // try argv.append("--build-id=tree"); diff --git a/src/main.zig b/src/main.zig index fc7e43b16f7f33788e3bbba171d1407cfad80e8a..95174ae34466eb9014ec6867716e7246866cf996 100644 --- a/src/main.zig +++ b/src/main.zig @@ -2627,6 +2627,16 @@ fn buildOutputType( if (single_threaded == null) { single_threaded = true; } + if (link_mode) |mode| { + if (mode == .Dynamic) { + if (linker_export_memory != null and linker_export_memory.?) { + fatal("flags '-dynamic' and '--export-memory' are incompatible", .{}); + } + // User did not supply `--export-memory` which is incompatible with -dynamic, therefore + // set the flag to false to ensure it does not get enabled by default. + linker_export_memory = false; + } + } if (wasi_exec_model) |model| { if (model == .reactor) { if (linker_no_entry != null and !linker_no_entry.?) { -- 2.54.0 From 938f9dea374193972be05b19b58dced54d79b1cb Mon Sep 17 00:00:00 2001 From: Luuk de Gram Date: Fri, 1 Sep 2023 16:37:07 +0200 Subject: [PATCH 3/5] update linker tests This updates all linker tests to include `no_entry` as well as changes all tests to executable so they do not need to be updated later when the in-house WebAssembly linker supports dynamic libraries. --- lib/std/Build/Step/Compile.zig | 6 +- test/link/wasm/archive/build.zig | 3 +- test/link/wasm/basic-features/build.zig | 3 +- test/link/wasm/bss/build.zig | 6 +- test/link/wasm/export-data/build.zig | 3 +- test/link/wasm/export/build.zig | 9 +- test/link/wasm/extern-mangle/build.zig | 3 +- test/link/wasm/function-table/build.zig | 9 +- test/link/wasm/infer-features/build.zig | 3 +- test/link/wasm/producers/build.zig | 3 +- test/link/wasm/segments/build.zig | 3 +- test/link/wasm/shared-memory/build.zig | 149 ++++++++++++------------ test/link/wasm/stack_pointer/build.zig | 3 +- test/link/wasm/type/build.zig | 3 +- 14 files changed, 113 insertions(+), 93 deletions(-) diff --git a/lib/std/Build/Step/Compile.zig b/lib/std/Build/Step/Compile.zig index 18977ac472a6d15169828b1b05ff0ddf0b8b8736..f59de11deb4978a5a53a84666c1d2c31bb7873fa 100644 --- a/lib/std/Build/Step/Compile.zig +++ b/lib/std/Build/Step/Compile.zig @@ -1853,7 +1853,11 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { if (self.global_base) |global_base| { try zig_args.append(b.fmt("--global-base={d}", .{global_base})); } - try addFlag(&zig_args, "entry", self.no_entry); + // invert the value due to naming so when `no_entry` is set to 'true' + // we actually emit the flag `-fno_entry`. + if (self.no_entry) |no_entry| { + try addFlag(&zig_args, "entry", !no_entry); + } if (self.code_model != .default) { try zig_args.append("-mcmodel"); diff --git a/test/link/wasm/archive/build.zig b/test/link/wasm/archive/build.zig index d87b8e973e7feb4008ac5327c6fe536ec180f542..c238e1647b3e1a257f07fc8d304bbc5cd3d11aea 100644 --- a/test/link/wasm/archive/build.zig +++ b/test/link/wasm/archive/build.zig @@ -15,12 +15,13 @@ pub fn build(b: *std.Build) void { fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.OptimizeMode) void { // The code in question will pull-in compiler-rt, // and therefore link with its archive file. - const lib = b.addSharedLibrary(.{ + const lib = b.addExecutable(.{ .name = "main", .root_source_file = .{ .path = "main.zig" }, .optimize = optimize, .target = .{ .cpu_arch = .wasm32, .os_tag = .freestanding }, }); + lib.no_entry = true; lib.use_llvm = false; lib.use_lld = false; lib.strip = false; diff --git a/test/link/wasm/basic-features/build.zig b/test/link/wasm/basic-features/build.zig index 703bd13febca3e1bc484aca0783523d3aec470d4..689527b52bb0b3e83704daa952959276d4faf756 100644 --- a/test/link/wasm/basic-features/build.zig +++ b/test/link/wasm/basic-features/build.zig @@ -4,7 +4,7 @@ pub const requires_stage2 = true; pub fn build(b: *std.Build) void { // Library with explicitly set cpu features - const lib = b.addSharedLibrary(.{ + const lib = b.addExecutable(.{ .name = "lib", .root_source_file = .{ .path = "main.zig" }, .optimize = .Debug, @@ -15,6 +15,7 @@ pub fn build(b: *std.Build) void { .os_tag = .freestanding, }, }); + lib.no_entry = true; lib.use_llvm = false; lib.use_lld = false; diff --git a/test/link/wasm/bss/build.zig b/test/link/wasm/bss/build.zig index e6cb9d4f3dcbe4494ac2fc8681d80826584b123e..9435c7848563e1f1316ccc7e80e0f8c4a7aae8dd 100644 --- a/test/link/wasm/bss/build.zig +++ b/test/link/wasm/bss/build.zig @@ -14,12 +14,13 @@ pub fn build(b: *std.Build) void { fn add(b: *std.Build, test_step: *std.Build.Step, optimize_mode: std.builtin.OptimizeMode, is_safe: bool) void { { - const lib = b.addSharedLibrary(.{ + const lib = b.addExecutable(.{ .name = "lib", .root_source_file = .{ .path = "lib.zig" }, .target = .{ .cpu_arch = .wasm32, .os_tag = .freestanding }, .optimize = optimize_mode, }); + lib.no_entry = true; lib.use_llvm = false; lib.use_lld = false; lib.strip = false; @@ -60,12 +61,13 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize_mode: std.builtin.Opt // verify zero'd declaration is stored in bss for all optimization modes. { - const lib = b.addSharedLibrary(.{ + const lib = b.addExecutable(.{ .name = "lib", .root_source_file = .{ .path = "lib2.zig" }, .target = .{ .cpu_arch = .wasm32, .os_tag = .freestanding }, .optimize = optimize_mode, }); + lib.no_entry = true; lib.use_llvm = false; lib.use_lld = false; lib.strip = false; diff --git a/test/link/wasm/export-data/build.zig b/test/link/wasm/export-data/build.zig index 7e3128aa769264dece9b532308fee134e7e38937..5c2fbac7ced7ba5fad71948181f7dea8547ff8de 100644 --- a/test/link/wasm/export-data/build.zig +++ b/test/link/wasm/export-data/build.zig @@ -9,12 +9,13 @@ pub fn build(b: *std.Build) void { return; } - const lib = b.addSharedLibrary(.{ + const lib = b.addExecutable(.{ .name = "lib", .root_source_file = .{ .path = "lib.zig" }, .optimize = .ReleaseSafe, // to make the output deterministic in address positions .target = .{ .cpu_arch = .wasm32, .os_tag = .freestanding }, }); + lib.no_entry = true; lib.use_lld = false; lib.export_symbol_names = &.{ "foo", "bar" }; lib.global_base = 0; // put data section at address 0 to make data symbols easier to parse diff --git a/test/link/wasm/export/build.zig b/test/link/wasm/export/build.zig index 5afe2df768e4b9b8621632d3ff112c056e562752..0ad9f380d24d4795e0057671cee5c2872547de56 100644 --- a/test/link/wasm/export/build.zig +++ b/test/link/wasm/export/build.zig @@ -13,31 +13,34 @@ pub fn build(b: *std.Build) void { } fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.OptimizeMode) void { - const no_export = b.addSharedLibrary(.{ + const no_export = b.addExecutable(.{ .name = "no-export", .root_source_file = .{ .path = "main.zig" }, .optimize = optimize, .target = .{ .cpu_arch = .wasm32, .os_tag = .freestanding }, }); + no_export.no_entry = true; no_export.use_llvm = false; no_export.use_lld = false; - const dynamic_export = b.addSharedLibrary(.{ + const dynamic_export = b.addExecutable(.{ .name = "dynamic", .root_source_file = .{ .path = "main.zig" }, .optimize = optimize, .target = .{ .cpu_arch = .wasm32, .os_tag = .freestanding }, }); + dynamic_export.no_entry = true; dynamic_export.rdynamic = true; dynamic_export.use_llvm = false; dynamic_export.use_lld = false; - const force_export = b.addSharedLibrary(.{ + const force_export = b.addExecutable(.{ .name = "force", .root_source_file = .{ .path = "main.zig" }, .optimize = optimize, .target = .{ .cpu_arch = .wasm32, .os_tag = .freestanding }, }); + force_export.no_entry = true; force_export.export_symbol_names = &.{"foo"}; force_export.use_llvm = false; force_export.use_lld = false; diff --git a/test/link/wasm/extern-mangle/build.zig b/test/link/wasm/extern-mangle/build.zig index 841d118efdc9e490b352b6949d67c18690a0d6c0..13446fec0da44740058deb97f2371c2859944dfd 100644 --- a/test/link/wasm/extern-mangle/build.zig +++ b/test/link/wasm/extern-mangle/build.zig @@ -11,12 +11,13 @@ pub fn build(b: *std.Build) void { } fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.OptimizeMode) void { - const lib = b.addSharedLibrary(.{ + const lib = b.addExecutable(.{ .name = "lib", .root_source_file = .{ .path = "lib.zig" }, .target = .{ .cpu_arch = .wasm32, .os_tag = .freestanding }, .optimize = optimize, }); + lib.no_entry = true; lib.import_symbols = true; // import `a` and `b` lib.rdynamic = true; // export `foo` diff --git a/test/link/wasm/function-table/build.zig b/test/link/wasm/function-table/build.zig index 796ba670ad7a5378533eb441aa4e10c99e54dc3e..c8c5f4c3f91794d027cde2ff810801b7f51ce873 100644 --- a/test/link/wasm/function-table/build.zig +++ b/test/link/wasm/function-table/build.zig @@ -13,32 +13,35 @@ pub fn build(b: *std.Build) void { } fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.OptimizeMode) void { - const import_table = b.addSharedLibrary(.{ + const import_table = b.addExecutable(.{ .name = "import_table", .root_source_file = .{ .path = "lib.zig" }, .target = .{ .cpu_arch = .wasm32, .os_tag = .freestanding }, .optimize = optimize, }); + import_table.no_entry = true; import_table.use_llvm = false; import_table.use_lld = false; import_table.import_table = true; - const export_table = b.addSharedLibrary(.{ + const export_table = b.addExecutable(.{ .name = "export_table", .root_source_file = .{ .path = "lib.zig" }, .target = .{ .cpu_arch = .wasm32, .os_tag = .freestanding }, .optimize = optimize, }); + export_table.no_entry = true; export_table.use_llvm = false; export_table.use_lld = false; export_table.export_table = true; - const regular_table = b.addSharedLibrary(.{ + const regular_table = b.addExecutable(.{ .name = "regular_table", .root_source_file = .{ .path = "lib.zig" }, .target = .{ .cpu_arch = .wasm32, .os_tag = .freestanding }, .optimize = optimize, }); + regular_table.no_entry = true; regular_table.use_llvm = false; regular_table.use_lld = false; diff --git a/test/link/wasm/infer-features/build.zig b/test/link/wasm/infer-features/build.zig index 6264edfba912c64e2ad5c365ae366e64a63d130a..d92f5865ecef275d42a6cb6fe2a511edb1dc0041 100644 --- a/test/link/wasm/infer-features/build.zig +++ b/test/link/wasm/infer-features/build.zig @@ -17,7 +17,7 @@ pub fn build(b: *std.Build) void { // Wasm library that doesn't have any features specified. This will // infer its featureset from other linked object files. - const lib = b.addSharedLibrary(.{ + const lib = b.addExecutable(.{ .name = "lib", .root_source_file = .{ .path = "main.zig" }, .optimize = .Debug, @@ -27,6 +27,7 @@ pub fn build(b: *std.Build) void { .os_tag = .freestanding, }, }); + lib.no_entry = true; lib.use_llvm = false; lib.use_lld = false; lib.addObject(c_obj); diff --git a/test/link/wasm/producers/build.zig b/test/link/wasm/producers/build.zig index f541a1c8ec145519cfdc03d258c46ce1b92dd9d0..dd9dcdf45acedea7ab010fdde07f1fba729065cd 100644 --- a/test/link/wasm/producers/build.zig +++ b/test/link/wasm/producers/build.zig @@ -14,12 +14,13 @@ pub fn build(b: *std.Build) void { } fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.OptimizeMode) void { - const lib = b.addSharedLibrary(.{ + const lib = b.addExecutable(.{ .name = "lib", .root_source_file = .{ .path = "lib.zig" }, .target = .{ .cpu_arch = .wasm32, .os_tag = .freestanding }, .optimize = optimize, }); + lib.no_entry = true; lib.use_llvm = false; lib.use_lld = false; lib.strip = false; diff --git a/test/link/wasm/segments/build.zig b/test/link/wasm/segments/build.zig index d01c34f90d39cd74731ab94d47d60a3bd696c4fe..fa95c20c61d5956fd094129c67f27737d1bc25c8 100644 --- a/test/link/wasm/segments/build.zig +++ b/test/link/wasm/segments/build.zig @@ -13,12 +13,13 @@ pub fn build(b: *std.Build) void { } fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.OptimizeMode) void { - const lib = b.addSharedLibrary(.{ + const lib = b.addExecutable(.{ .name = "lib", .root_source_file = .{ .path = "lib.zig" }, .target = .{ .cpu_arch = .wasm32, .os_tag = .freestanding }, .optimize = optimize, }); + lib.no_entry = true; lib.use_llvm = false; lib.use_lld = false; lib.strip = false; diff --git a/test/link/wasm/shared-memory/build.zig b/test/link/wasm/shared-memory/build.zig index cf84ad7528c2772c9a6fe46ce3bec25d99635dd7..a113ac7bcd8ad081e8d3fa11bbb8e47c4fd832d3 100644 --- a/test/link/wasm/shared-memory/build.zig +++ b/test/link/wasm/shared-memory/build.zig @@ -11,88 +11,87 @@ pub fn build(b: *std.Build) void { } fn add(b: *std.Build, test_step: *std.Build.Step, optimize_mode: std.builtin.OptimizeMode) void { - { - const lib = b.addSharedLibrary(.{ - .name = "lib", - .root_source_file = .{ .path = "lib.zig" }, - .target = .{ - .cpu_arch = .wasm32, - .cpu_model = .{ .explicit = &std.Target.wasm.cpu.mvp }, - .cpu_features_add = std.Target.wasm.featureSet(&.{ .atomics, .bulk_memory }), - .os_tag = .freestanding, - }, - .optimize = optimize_mode, - }); - lib.use_lld = false; - lib.strip = false; - lib.import_memory = true; - lib.export_memory = true; - lib.shared_memory = true; - lib.max_memory = 67108864; - lib.single_threaded = false; - lib.export_symbol_names = &.{"foo"}; + const lib = b.addExecutable(.{ + .name = "lib", + .root_source_file = .{ .path = "lib.zig" }, + .target = .{ + .cpu_arch = .wasm32, + .cpu_model = .{ .explicit = &std.Target.wasm.cpu.mvp }, + .cpu_features_add = std.Target.wasm.featureSet(&.{ .atomics, .bulk_memory }), + .os_tag = .freestanding, + }, + .optimize = optimize_mode, + }); + lib.no_entry = true; + lib.use_lld = false; + lib.strip = false; + lib.import_memory = true; + lib.export_memory = true; + lib.shared_memory = true; + lib.max_memory = 67108864; + lib.single_threaded = false; + lib.export_symbol_names = &.{"foo"}; - const check_lib = lib.checkObject(); + const check_lib = lib.checkObject(); - check_lib.checkStart("Section import"); - check_lib.checkNext("entries 1"); - check_lib.checkNext("module env"); - check_lib.checkNext("name memory"); // ensure we are importing memory + check_lib.checkStart("Section import"); + check_lib.checkNext("entries 1"); + check_lib.checkNext("module env"); + check_lib.checkNext("name memory"); // ensure we are importing memory - check_lib.checkStart("Section export"); - check_lib.checkNext("entries 2"); - check_lib.checkNext("name memory"); // ensure we also export memory again + check_lib.checkStart("Section export"); + check_lib.checkNext("entries 2"); + check_lib.checkNext("name memory"); // ensure we also export memory again - // This section *must* be emit as the start function is set to the index - // of __wasm_init_memory - // release modes will have the TLS segment optimized out in our test-case. - // This means we won't have __wasm_init_memory in such case, and therefore - // should also not have a section "start" - if (optimize_mode == .Debug) { - check_lib.checkStart("Section start"); - } - - // This section is only and *must* be emit when shared-memory is enabled - // release modes will have the TLS segment optimized out in our test-case. - if (optimize_mode == .Debug) { - check_lib.checkStart("Section data_count"); - check_lib.checkNext("count 3"); - } + // This section *must* be emit as the start function is set to the index + // of __wasm_init_memory + // release modes will have the TLS segment optimized out in our test-case. + // This means we won't have __wasm_init_memory in such case, and therefore + // should also not have a section "start" + if (optimize_mode == .Debug) { + check_lib.checkStart("Section start"); + } - check_lib.checkStart("Section custom"); - check_lib.checkNext("name name"); - check_lib.checkNext("type function"); - if (optimize_mode == .Debug) { - check_lib.checkNext("name __wasm_init_memory"); - } - check_lib.checkNext("name __wasm_init_tls"); - check_lib.checkNext("type global"); + // This section is only and *must* be emit when shared-memory is enabled + // release modes will have the TLS segment optimized out in our test-case. + if (optimize_mode == .Debug) { + check_lib.checkStart("Section data_count"); + check_lib.checkNext("count 3"); + } - // In debug mode the symbol __tls_base is resolved to an undefined symbol - // from the object file, hence its placement differs than in release modes - // where the entire tls segment is optimized away, and tls_base will have - // its original position. - if (optimize_mode == .Debug) { - check_lib.checkNext("name __tls_size"); - check_lib.checkNext("name __tls_align"); - check_lib.checkNext("name __tls_base"); - } else { - check_lib.checkNext("name __tls_base"); - check_lib.checkNext("name __tls_size"); - check_lib.checkNext("name __tls_align"); - } + check_lib.checkStart("Section custom"); + check_lib.checkNext("name name"); + check_lib.checkNext("type function"); + if (optimize_mode == .Debug) { + check_lib.checkNext("name __wasm_init_memory"); + } + check_lib.checkNext("name __wasm_init_tls"); + check_lib.checkNext("type global"); - check_lib.checkNext("type data_segment"); - if (optimize_mode == .Debug) { - check_lib.checkNext("names 3"); - check_lib.checkNext("index 0"); - check_lib.checkNext("name .rodata"); - check_lib.checkNext("index 1"); - check_lib.checkNext("name .bss"); - check_lib.checkNext("index 2"); - check_lib.checkNext("name .tdata"); - } + // In debug mode the symbol __tls_base is resolved to an undefined symbol + // from the object file, hence its placement differs than in release modes + // where the entire tls segment is optimized away, and tls_base will have + // its original position. + if (optimize_mode == .Debug) { + check_lib.checkNext("name __tls_size"); + check_lib.checkNext("name __tls_align"); + check_lib.checkNext("name __tls_base"); + } else { + check_lib.checkNext("name __tls_base"); + check_lib.checkNext("name __tls_size"); + check_lib.checkNext("name __tls_align"); + } - test_step.dependOn(&check_lib.step); + check_lib.checkNext("type data_segment"); + if (optimize_mode == .Debug) { + check_lib.checkNext("names 3"); + check_lib.checkNext("index 0"); + check_lib.checkNext("name .rodata"); + check_lib.checkNext("index 1"); + check_lib.checkNext("name .bss"); + check_lib.checkNext("index 2"); + check_lib.checkNext("name .tdata"); } + + test_step.dependOn(&check_lib.step); } diff --git a/test/link/wasm/stack_pointer/build.zig b/test/link/wasm/stack_pointer/build.zig index ce724e5736398c5957cd03d5207f845d44d929a0..b004583cf3dcb0c87dd0787028664a5d247fdb99 100644 --- a/test/link/wasm/stack_pointer/build.zig +++ b/test/link/wasm/stack_pointer/build.zig @@ -13,12 +13,13 @@ pub fn build(b: *std.Build) void { } fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.OptimizeMode) void { - const lib = b.addSharedLibrary(.{ + const lib = b.addExecutable(.{ .name = "lib", .root_source_file = .{ .path = "lib.zig" }, .target = .{ .cpu_arch = .wasm32, .os_tag = .freestanding }, .optimize = optimize, }); + lib.no_entry = true; lib.use_llvm = false; lib.use_lld = false; lib.strip = false; diff --git a/test/link/wasm/type/build.zig b/test/link/wasm/type/build.zig index 7110f465f480180b770fea47339ae2a2dd4b9251..98e12eb4dc17c1a7dccd38cb6b83b768a90b6f5c 100644 --- a/test/link/wasm/type/build.zig +++ b/test/link/wasm/type/build.zig @@ -13,12 +13,13 @@ pub fn build(b: *std.Build) void { } fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.OptimizeMode) void { - const lib = b.addSharedLibrary(.{ + const lib = b.addExecutable(.{ .name = "lib", .root_source_file = .{ .path = "lib.zig" }, .target = .{ .cpu_arch = .wasm32, .os_tag = .freestanding }, .optimize = optimize, }); + lib.no_entry = true; lib.use_llvm = false; lib.use_lld = false; lib.strip = false; -- 2.54.0 From 5b2ee5eacc177873ce674a307a1bebdfffeeae10 Mon Sep 17 00:00:00 2001 From: Luuk de Gram Date: Wed, 1 Nov 2023 15:56:30 +0100 Subject: [PATCH 4/5] docs: update WebAssembly freestanding example --- doc/langref.html.in | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/langref.html.in b/doc/langref.html.in index b3ae609a7542b957b781abc4c45b6b91a053e38f..7e4d25a2fa12010995463676f8e418b03b587123 100644 --- a/doc/langref.html.in +++ b/doc/langref.html.in @@ -11336,12 +11336,12 @@ all your base are belong to us{#end_shell_samp#} {#header_open|WebAssembly#}

Zig supports building for WebAssembly out of the box.

{#header_open|Freestanding#} -

For host environments like the web browser and nodejs, build as a dynamic library using the freestanding +

For host environments like the web browser and nodejs, build as an executable using the freestanding OS target. Here's an example of running Zig code compiled to WebAssembly with nodejs.

- {#code_begin|lib|math#} + {#code_begin|exe|math#} {#target_wasm#} - {#link_mode_dynamic#} - {#additonal_option|-rdynamic#} + {#additonal_option|-fno-entry#} + {#additonal_option|--export=add#} extern fn print(i32) void; export fn add(a: i32, b: i32) void { -- 2.54.0 From c893f837151d4764fd34911376836a01192b4d75 Mon Sep 17 00:00:00 2001 From: Luuk de Gram Date: Thu, 2 Nov 2023 19:06:19 +0100 Subject: [PATCH 5/5] cli: consolidate entry point flags --- lib/std/Build/Step/Compile.zig | 32 ++++++++---- src/Compilation.zig | 3 -- src/link.zig | 1 - src/link/Wasm.zig | 12 ++--- src/main.zig | 64 ++++++++++++++---------- test/link/elf.zig | 4 +- test/link/macho/entry/build.zig | 2 +- test/link/macho/entry_in_dylib/build.zig | 2 +- test/link/wasm/archive/build.zig | 2 +- test/link/wasm/basic-features/build.zig | 2 +- test/link/wasm/bss/build.zig | 4 +- test/link/wasm/export-data/build.zig | 2 +- test/link/wasm/export/build.zig | 6 +-- test/link/wasm/extern-mangle/build.zig | 2 +- test/link/wasm/function-table/build.zig | 6 +-- test/link/wasm/infer-features/build.zig | 2 +- test/link/wasm/producers/build.zig | 2 +- test/link/wasm/segments/build.zig | 2 +- test/link/wasm/shared-memory/build.zig | 2 +- test/link/wasm/stack_pointer/build.zig | 2 +- test/link/wasm/type/build.zig | 2 +- 21 files changed, 86 insertions(+), 70 deletions(-) diff --git a/lib/std/Build/Step/Compile.zig b/lib/std/Build/Step/Compile.zig index f59de11deb4978a5a53a84666c1d2c31bb7873fa..2d08541545b64f0889e469bf539836af73563166 100644 --- a/lib/std/Build/Step/Compile.zig +++ b/lib/std/Build/Step/Compile.zig @@ -64,8 +64,6 @@ initial_memory: ?u64 = null, max_memory: ?u64 = null, shared_memory: bool = false, global_base: ?u64 = null, -/// For WebAssembly only. Tells the linker to not output an entry point. -no_entry: ?bool = null, c_std: std.Build.CStd, /// Set via options; intended to be read-only after that. zig_lib_dir: ?LazyPath, @@ -191,7 +189,8 @@ dll_export_fns: ?bool = null, subsystem: ?std.Target.SubSystem = null, -entry_symbol_name: ?[]const u8 = null, +/// How the linker must handle the entry point of the executable. +entry: Entry = .default, /// List of symbols forced as undefined in the symbol table /// thus forcing their resolution by the linker. @@ -306,6 +305,18 @@ const FrameworkLinkInfo = struct { weak: bool = false, }; +const Entry = union(enum) { + /// Let the compiler decide whether to make an entry point and what to name + /// it. + default, + /// The executable will have no entry point. + disabled, + /// The executable will have an entry point with the default symbol name. + enabled, + /// The executable will have an entry point with the specified symbol name. + symbol_name: []const u8, +}; + pub const IncludeDir = union(enum) { path: LazyPath, path_system: LazyPath, @@ -1420,9 +1431,13 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { try zig_args.append(try std.fmt.allocPrint(b.allocator, "-ofmt={s}", .{@tagName(ofmt)})); } - if (self.entry_symbol_name) |entry| { - try zig_args.append("--entry"); - try zig_args.append(entry); + switch (self.entry) { + .default => {}, + .disabled => try zig_args.append("-fno-entry"), + .enabled => try zig_args.append("-fentry"), + .symbol_name => |entry_name| { + try zig_args.append(try std.fmt.allocPrint(b.allocator, "-fentry={s}", .{entry_name})); + }, } { @@ -1853,11 +1868,6 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { if (self.global_base) |global_base| { try zig_args.append(b.fmt("--global-base={d}", .{global_base})); } - // invert the value due to naming so when `no_entry` is set to 'true' - // we actually emit the flag `-fno_entry`. - if (self.no_entry) |no_entry| { - try addFlag(&zig_args, "entry", !no_entry); - } if (self.code_model != .default) { try zig_args.append("-mcmodel"); diff --git a/src/Compilation.zig b/src/Compilation.zig index 1d60be20a5a31c88a397c5b5097d8e9612e6c8ea..954acd44b76b3b0d6373ef941aa1c55c8b40cf4b 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -643,7 +643,6 @@ pub const InitOptions = struct { linker_import_symbols: bool = false, linker_import_table: bool = false, linker_export_table: bool = false, - linker_no_entry: bool = false, linker_initial_memory: ?u64 = null, linker_max_memory: ?u64 = null, linker_shared_memory: bool = false, @@ -1615,7 +1614,6 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { .import_symbols = options.linker_import_symbols, .import_table = options.linker_import_table, .export_table = options.linker_export_table, - .no_entry = options.linker_no_entry, .initial_memory = options.linker_initial_memory, .max_memory = options.linker_max_memory, .shared_memory = options.linker_shared_memory, @@ -2579,7 +2577,6 @@ fn addNonIncrementalStuffToCacheManifest(comp: *Compilation, man: *Cache.Manifes man.hash.addOptional(comp.bin_file.options.max_memory); man.hash.add(comp.bin_file.options.shared_memory); man.hash.addOptional(comp.bin_file.options.global_base); - man.hash.add(comp.bin_file.options.no_entry); // Mach-O specific stuff man.hash.addListOfBytes(comp.bin_file.options.framework_dirs); diff --git a/src/link.zig b/src/link.zig index a49582aac9b1a100a565316dcb0654a70faf9cd2..1648d6a63efa340f27fe003246eb369ccfbe0eeb 100644 --- a/src/link.zig +++ b/src/link.zig @@ -166,7 +166,6 @@ pub const Options = struct { export_table: bool, initial_memory: ?u64, max_memory: ?u64, - no_entry: bool, shared_memory: bool, export_symbol_names: []const []const u8, global_base: ?u64, diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig index ad9f8266f069ba14b7023ad5fa0e15b5fb8ae4e2..baa10be60394a26374ad53db1ecaf6e6912df64a 100644 --- a/src/link/Wasm.zig +++ b/src/link/Wasm.zig @@ -2817,11 +2817,11 @@ fn setupExports(wasm: *Wasm) !void { } fn setupStart(wasm: *Wasm) !void { - if (wasm.base.options.no_entry) return; - const entry_name = wasm.base.options.entry orelse "_start"; + // do not export entry point if user set none or no default was set. + const entry_name = wasm.base.options.entry orelse return; const symbol_loc = wasm.findGlobalSymbol(entry_name) orelse { - log.err("Entry symbol '{s}' missing", .{entry_name}); + log.err("Entry symbol '{s}' missing, use '-fno-entry' to suppress", .{entry_name}); return error.MissingSymbol; }; @@ -4531,6 +4531,8 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) ! if (wasm.base.options.entry) |entry| { try argv.append("--entry"); try argv.append(entry); + } else { + try argv.append("--no-entry"); } // Increase the default stack size to a more reasonable value of 1MB instead of @@ -4544,10 +4546,6 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) ! try argv.append("--allow-undefined"); } - if (wasm.base.options.no_entry) { - try argv.append("--no-entry"); - } - if (wasm.base.options.output_mode == .Lib and wasm.base.options.link_mode == .Dynamic) { try argv.append("--shared"); } diff --git a/src/main.zig b/src/main.zig index 95174ae34466eb9014ec6867716e7246866cf996..51c5397c101724d296d2b69ef6f942e9f4d59e88 100644 --- a/src/main.zig +++ b/src/main.zig @@ -509,7 +509,9 @@ const usage_build_generic = \\ --dynamic-linker [path] Set the dynamic interpreter path (usually ld.so) \\ --sysroot [path] Set the system root directory (usually /) \\ --version [ver] Dynamic library semver - \\ --entry [name] Set the entrypoint symbol name + \\ -fentry Enable entry point with default symbol name + \\ -fentry=[name] Override the entry point symbol name + \\ -fno-entry Do not output any entry point \\ --force_undefined [name] Specify the symbol must be defined for the link to succeed \\ -fsoname[=name] Override the default SONAME value \\ -fno-soname Disable emitting a SONAME @@ -577,8 +579,6 @@ const usage_build_generic = \\ --shared-memory (WebAssembly) use shared linear memory \\ --global-base=[addr] (WebAssembly) where to start to place global data \\ --export=[value] (WebAssembly) Force a symbol to be exported - \\ -fentry (WebAssembly) Force output an entry point - \\ -fno-entry (WebAssembly) Do not output any entry point \\ \\Test Options: \\ --test-filter [text] Skip tests that do not match filter @@ -837,7 +837,7 @@ fn buildOutputType( var linker_import_symbols: bool = false; var linker_import_table: bool = false; var linker_export_table: bool = false; - var linker_no_entry: ?bool = null; + var linker_force_entry: ?bool = null; var linker_initial_memory: ?u64 = null; var linker_max_memory: ?u64 = null; var linker_shared_memory: bool = false; @@ -1074,8 +1074,8 @@ fn buildOutputType( subsystem = try parseSubSystem(args_iter.nextOrFatal()); } else if (mem.eql(u8, arg, "-O")) { optimize_mode_string = args_iter.nextOrFatal(); - } else if (mem.eql(u8, arg, "--entry")) { - entry = args_iter.nextOrFatal(); + } else if (mem.startsWith(u8, arg, "-fentry=")) { + entry = arg["-fentry=".len..]; } else if (mem.eql(u8, arg, "--force_undefined")) { try force_undefined_symbols.put(gpa, args_iter.nextOrFatal(), {}); } else if (mem.eql(u8, arg, "--stack")) { @@ -1507,9 +1507,9 @@ fn buildOutputType( } else if (mem.eql(u8, arg, "--import-memory")) { linker_import_memory = true; } else if (mem.eql(u8, arg, "-fentry")) { - linker_no_entry = false; + linker_force_entry = true; } else if (mem.eql(u8, arg, "-fno-entry")) { - linker_no_entry = true; + linker_force_entry = false; } else if (mem.eql(u8, arg, "--export-memory")) { linker_export_memory = true; } else if (mem.eql(u8, arg, "--import-symbols")) { @@ -2142,7 +2142,7 @@ fn buildOutputType( } else if (mem.eql(u8, arg, "--export-table")) { linker_export_table = true; } else if (mem.eql(u8, arg, "--no-entry")) { - linker_no_entry = true; + linker_force_entry = false; } else if (mem.eql(u8, arg, "--initial-memory")) { const next_arg = linker_args_it.nextOrFatal(); linker_initial_memory = std.fmt.parseUnsigned(u32, eatIntPrefix(next_arg, 16), 16) catch |err| { @@ -2605,6 +2605,23 @@ fn buildOutputType( link_libcpp = true; } + if (linker_force_entry) |force| { + if (!force) { + entry = null; + } else if (entry == null and output_mode == .Exe) { + entry = switch (target_info.target.ofmt) { + .coff => "wWinMainCRTStartup", + .macho => "_main", + .elf, .plan9 => "_start", + .wasm => defaultWasmEntryName(wasi_exec_model), + else => |tag| fatal("No default entry point available for output format {s}", .{@tagName(tag)}), + }; + } + } else if (entry == null and target_info.target.isWasm() and output_mode == .Exe) { + // For WebAssembly the compiler defaults to setting the entry name when no flags are set. + entry = defaultWasmEntryName(wasi_exec_model); + } + if (target_info.target.ofmt == .coff) { // Now that we know the target supports resources, // we can add the res files as link objects. @@ -2637,23 +2654,11 @@ fn buildOutputType( linker_export_memory = false; } } - if (wasi_exec_model) |model| { - if (model == .reactor) { - if (linker_no_entry != null and !linker_no_entry.?) { - fatal("WASI exucution model 'reactor' incompatible with flag '-fentry'. Reactor execution model has no entry point", .{}); + if (wasi_exec_model != null and wasi_exec_model.? == .reactor) { + if (entry) |entry_name| { + if (!mem.eql(u8, "_initialize", entry_name)) { + fatal("the entry symbol of the reactor model must be '_initialize', but found '{s}'", .{entry_name}); } - if (entry) |entry_name| { - if (!mem.eql(u8, "_initialize", entry_name)) { - fatal("the entry symbol of the reactor model must be '_initialize', but found '{s}'", .{entry_name}); - } - } else { - entry = "_initialize"; - } - } - } - if (linker_no_entry) |no_entry| { - if (no_entry and entry != null) { - fatal("combination of '--entry' and `-fno-entry` are incompatible", .{}); } } if (linker_shared_memory) { @@ -3503,7 +3508,6 @@ fn buildOutputType( .linker_import_symbols = linker_import_symbols, .linker_import_table = linker_import_table, .linker_export_table = linker_export_table, - .linker_no_entry = linker_no_entry orelse false, .linker_initial_memory = linker_initial_memory, .linker_max_memory = linker_max_memory, .linker_shared_memory = linker_shared_memory, @@ -7253,3 +7257,11 @@ fn createDependenciesModule( try main_mod.deps.put(arena, "@dependencies", deps_mod); return deps_mod; } + +fn defaultWasmEntryName(exec_model: ?std.builtin.WasiExecModel) []const u8 { + const model = exec_model orelse .command; + if (model == .reactor) { + return "_initialize"; + } + return "_start"; +} diff --git a/test/link/elf.zig b/test/link/elf.zig index dad3604c31ae98683f27a68554d507a50102a833..d7fe7562763c9c9c5f6abc558b13e37b5802a3bc 100644 --- a/test/link/elf.zig +++ b/test/link/elf.zig @@ -651,7 +651,7 @@ fn testEntryPoint(b: *Build, opts: Options) *Step { const exe = addExecutable(b, "main", opts); exe.addObject(a_o); exe.addObject(b_o); - exe.entry_symbol_name = "foo"; + exe.entry = .{ .symbol_name = "foo" }; const check = exe.checkObject(); check.checkStart(); @@ -667,7 +667,7 @@ fn testEntryPoint(b: *Build, opts: Options) *Step { const exe = addExecutable(b, "other", opts); exe.addObject(a_o); exe.addObject(b_o); - exe.entry_symbol_name = "bar"; + exe.entry = .{ .symbol_name = "bar" }; const check = exe.checkObject(); check.checkStart(); diff --git a/test/link/macho/entry/build.zig b/test/link/macho/entry/build.zig index fcba02cd9a8832b03a1c2f5dadfe0261aa46b2b4..9f493d2715d2aa44fa60ac01af871ca2a71f010e 100644 --- a/test/link/macho/entry/build.zig +++ b/test/link/macho/entry/build.zig @@ -20,7 +20,7 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.Optimize }); exe.addCSourceFile(.{ .file = .{ .path = "main.c" }, .flags = &.{} }); exe.linkLibC(); - exe.entry_symbol_name = "_non_main"; + exe.entry = .{ .symbol_name = "_non_main" }; const check_exe = exe.checkObject(); diff --git a/test/link/macho/entry_in_dylib/build.zig b/test/link/macho/entry_in_dylib/build.zig index 97ffa917b451488b6fe083cca3b6a994b9ce71b7..eb036abe6a5f75ecebde819108a2ef47b835c23a 100644 --- a/test/link/macho/entry_in_dylib/build.zig +++ b/test/link/macho/entry_in_dylib/build.zig @@ -30,7 +30,7 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.Optimize exe.addCSourceFile(.{ .file = .{ .path = "main.c" }, .flags = &.{} }); exe.linkLibrary(lib); exe.linkLibC(); - exe.entry_symbol_name = "_bootstrap"; + exe.entry = .{ .symbol_name = "_bootstrap" }; exe.forceUndefinedSymbol("_my_main"); const check_exe = exe.checkObject(); diff --git a/test/link/wasm/archive/build.zig b/test/link/wasm/archive/build.zig index c238e1647b3e1a257f07fc8d304bbc5cd3d11aea..3da284ac8ff505a165e3751c20339f7712e0fa94 100644 --- a/test/link/wasm/archive/build.zig +++ b/test/link/wasm/archive/build.zig @@ -21,7 +21,7 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.Optimize .optimize = optimize, .target = .{ .cpu_arch = .wasm32, .os_tag = .freestanding }, }); - lib.no_entry = true; + lib.entry = .disabled; lib.use_llvm = false; lib.use_lld = false; lib.strip = false; diff --git a/test/link/wasm/basic-features/build.zig b/test/link/wasm/basic-features/build.zig index 689527b52bb0b3e83704daa952959276d4faf756..0566fbe2c1771954b2b43aa3f0d6fc9c1be3d66b 100644 --- a/test/link/wasm/basic-features/build.zig +++ b/test/link/wasm/basic-features/build.zig @@ -15,7 +15,7 @@ pub fn build(b: *std.Build) void { .os_tag = .freestanding, }, }); - lib.no_entry = true; + lib.entry = .disabled; lib.use_llvm = false; lib.use_lld = false; diff --git a/test/link/wasm/bss/build.zig b/test/link/wasm/bss/build.zig index 9435c7848563e1f1316ccc7e80e0f8c4a7aae8dd..1bc059acdeca52a3100491f825998d562039c3df 100644 --- a/test/link/wasm/bss/build.zig +++ b/test/link/wasm/bss/build.zig @@ -20,7 +20,7 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize_mode: std.builtin.Opt .target = .{ .cpu_arch = .wasm32, .os_tag = .freestanding }, .optimize = optimize_mode, }); - lib.no_entry = true; + lib.entry = .disabled; lib.use_llvm = false; lib.use_lld = false; lib.strip = false; @@ -67,7 +67,7 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize_mode: std.builtin.Opt .target = .{ .cpu_arch = .wasm32, .os_tag = .freestanding }, .optimize = optimize_mode, }); - lib.no_entry = true; + lib.entry = .disabled; lib.use_llvm = false; lib.use_lld = false; lib.strip = false; diff --git a/test/link/wasm/export-data/build.zig b/test/link/wasm/export-data/build.zig index 5c2fbac7ced7ba5fad71948181f7dea8547ff8de..58a8795390e70030c025ad6d007dbb7819bd10b0 100644 --- a/test/link/wasm/export-data/build.zig +++ b/test/link/wasm/export-data/build.zig @@ -15,7 +15,7 @@ pub fn build(b: *std.Build) void { .optimize = .ReleaseSafe, // to make the output deterministic in address positions .target = .{ .cpu_arch = .wasm32, .os_tag = .freestanding }, }); - lib.no_entry = true; + lib.entry = .disabled; lib.use_lld = false; lib.export_symbol_names = &.{ "foo", "bar" }; lib.global_base = 0; // put data section at address 0 to make data symbols easier to parse diff --git a/test/link/wasm/export/build.zig b/test/link/wasm/export/build.zig index 0ad9f380d24d4795e0057671cee5c2872547de56..5c0306335dd53349e29907b43665e7f36cf960ca 100644 --- a/test/link/wasm/export/build.zig +++ b/test/link/wasm/export/build.zig @@ -19,7 +19,7 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.Optimize .optimize = optimize, .target = .{ .cpu_arch = .wasm32, .os_tag = .freestanding }, }); - no_export.no_entry = true; + no_export.entry = .disabled; no_export.use_llvm = false; no_export.use_lld = false; @@ -29,7 +29,7 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.Optimize .optimize = optimize, .target = .{ .cpu_arch = .wasm32, .os_tag = .freestanding }, }); - dynamic_export.no_entry = true; + dynamic_export.entry = .disabled; dynamic_export.rdynamic = true; dynamic_export.use_llvm = false; dynamic_export.use_lld = false; @@ -40,7 +40,7 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.Optimize .optimize = optimize, .target = .{ .cpu_arch = .wasm32, .os_tag = .freestanding }, }); - force_export.no_entry = true; + force_export.entry = .disabled; force_export.export_symbol_names = &.{"foo"}; force_export.use_llvm = false; force_export.use_lld = false; diff --git a/test/link/wasm/extern-mangle/build.zig b/test/link/wasm/extern-mangle/build.zig index 13446fec0da44740058deb97f2371c2859944dfd..9f450c2dcc0e33afa8dbb21319e986f008ea0c70 100644 --- a/test/link/wasm/extern-mangle/build.zig +++ b/test/link/wasm/extern-mangle/build.zig @@ -17,7 +17,7 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.Optimize .target = .{ .cpu_arch = .wasm32, .os_tag = .freestanding }, .optimize = optimize, }); - lib.no_entry = true; + lib.entry = .disabled; lib.import_symbols = true; // import `a` and `b` lib.rdynamic = true; // export `foo` diff --git a/test/link/wasm/function-table/build.zig b/test/link/wasm/function-table/build.zig index c8c5f4c3f91794d027cde2ff810801b7f51ce873..906a2556423bc07f662ec4eda95be150ffd9accd 100644 --- a/test/link/wasm/function-table/build.zig +++ b/test/link/wasm/function-table/build.zig @@ -19,7 +19,7 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.Optimize .target = .{ .cpu_arch = .wasm32, .os_tag = .freestanding }, .optimize = optimize, }); - import_table.no_entry = true; + import_table.entry = .disabled; import_table.use_llvm = false; import_table.use_lld = false; import_table.import_table = true; @@ -30,7 +30,7 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.Optimize .target = .{ .cpu_arch = .wasm32, .os_tag = .freestanding }, .optimize = optimize, }); - export_table.no_entry = true; + export_table.entry = .disabled; export_table.use_llvm = false; export_table.use_lld = false; export_table.export_table = true; @@ -41,7 +41,7 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.Optimize .target = .{ .cpu_arch = .wasm32, .os_tag = .freestanding }, .optimize = optimize, }); - regular_table.no_entry = true; + regular_table.entry = .disabled; regular_table.use_llvm = false; regular_table.use_lld = false; diff --git a/test/link/wasm/infer-features/build.zig b/test/link/wasm/infer-features/build.zig index d92f5865ecef275d42a6cb6fe2a511edb1dc0041..5c7fa574472ac8a2b4ce7a3b87387587f60c07ae 100644 --- a/test/link/wasm/infer-features/build.zig +++ b/test/link/wasm/infer-features/build.zig @@ -27,7 +27,7 @@ pub fn build(b: *std.Build) void { .os_tag = .freestanding, }, }); - lib.no_entry = true; + lib.entry = .disabled; lib.use_llvm = false; lib.use_lld = false; lib.addObject(c_obj); diff --git a/test/link/wasm/producers/build.zig b/test/link/wasm/producers/build.zig index dd9dcdf45acedea7ab010fdde07f1fba729065cd..e2bd95f45065f53d6bb32f5e92578aabbde2f7e8 100644 --- a/test/link/wasm/producers/build.zig +++ b/test/link/wasm/producers/build.zig @@ -20,7 +20,7 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.Optimize .target = .{ .cpu_arch = .wasm32, .os_tag = .freestanding }, .optimize = optimize, }); - lib.no_entry = true; + lib.entry = .disabled; lib.use_llvm = false; lib.use_lld = false; lib.strip = false; diff --git a/test/link/wasm/segments/build.zig b/test/link/wasm/segments/build.zig index fa95c20c61d5956fd094129c67f27737d1bc25c8..21b954a9022a582318718bfea933d652753d8871 100644 --- a/test/link/wasm/segments/build.zig +++ b/test/link/wasm/segments/build.zig @@ -19,7 +19,7 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.Optimize .target = .{ .cpu_arch = .wasm32, .os_tag = .freestanding }, .optimize = optimize, }); - lib.no_entry = true; + lib.entry = .disabled; lib.use_llvm = false; lib.use_lld = false; lib.strip = false; diff --git a/test/link/wasm/shared-memory/build.zig b/test/link/wasm/shared-memory/build.zig index a113ac7bcd8ad081e8d3fa11bbb8e47c4fd832d3..a1d660d13582e21895f355bff503a3adcddc4fd5 100644 --- a/test/link/wasm/shared-memory/build.zig +++ b/test/link/wasm/shared-memory/build.zig @@ -22,7 +22,7 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize_mode: std.builtin.Opt }, .optimize = optimize_mode, }); - lib.no_entry = true; + lib.entry = .disabled; lib.use_lld = false; lib.strip = false; lib.import_memory = true; diff --git a/test/link/wasm/stack_pointer/build.zig b/test/link/wasm/stack_pointer/build.zig index b004583cf3dcb0c87dd0787028664a5d247fdb99..00ef54c0528e45fa0c8067d003767d033afba9a2 100644 --- a/test/link/wasm/stack_pointer/build.zig +++ b/test/link/wasm/stack_pointer/build.zig @@ -19,7 +19,7 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.Optimize .target = .{ .cpu_arch = .wasm32, .os_tag = .freestanding }, .optimize = optimize, }); - lib.no_entry = true; + lib.entry = .disabled; lib.use_llvm = false; lib.use_lld = false; lib.strip = false; diff --git a/test/link/wasm/type/build.zig b/test/link/wasm/type/build.zig index 98e12eb4dc17c1a7dccd38cb6b83b768a90b6f5c..de574e36e4cba50ef21683b6bab21a8a786f2134 100644 --- a/test/link/wasm/type/build.zig +++ b/test/link/wasm/type/build.zig @@ -19,7 +19,7 @@ fn add(b: *std.Build, test_step: *std.Build.Step, optimize: std.builtin.Optimize .target = .{ .cpu_arch = .wasm32, .os_tag = .freestanding }, .optimize = optimize, }); - lib.no_entry = true; + lib.entry = .disabled; lib.use_llvm = false; lib.use_lld = false; lib.strip = false; -- 2.54.0