Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Compiling Zig compiler to wasm32-wasi target #20665

Open
eliot-akira opened this issue Jul 17, 2024 · 3 comments
Open

Compiling Zig compiler to wasm32-wasi target #20665

eliot-akira opened this issue Jul 17, 2024 · 3 comments
Labels
bug Observed behavior contradicts documented or intended behavior
Milestone

Comments

@eliot-akira
Copy link

eliot-akira commented Jul 17, 2024

Zig Version

0.13.0

Steps to Reproduce and Observed Behavior

Clone Zig and compile the compiler to wasm32-wasi target.

git clone --recursive --depth 1 --single-branch --branch master https://github.com/ziglang/zig
cd zig
zig build -Dtarget=wasm32-wasi -Doptimize=ReleaseSmall -Dno-langref -Dno-lib

It results in errors.

~/zig/build.zig:600:25: error: no field or member function named 'addUpdateSourceFiles' in 'Build'
    const copy_zig_h = b.addUpdateSourceFiles();
                       ~^~~~~~~~~~~~~~~~~~~~~
~/.local/lib/zig/lib/std/Build.zig:1:1: note: struct declared here
const std = @import("std.zig");
^~~~~
referenced by:
    build: ~/zig/build.zig:537:9
    runBuild__anon_8848: ~/.local/lib/zig/lib/std/Build.zig:2117:37
    remaining reference traces hidden; use '-freference-trace' to see all reference traces
~/zig/build.zig:1289:64: error: no field named 'zig_lib_directory' in struct 'Build.Graph'
        cmd.addArgs(&.{ "--zig-lib-dir", b.fmt("{}", .{b.graph.zig_lib_directory}) });
                                                               ^~~~~~~~~~~~~~~~~
~/.local/lib/zig/lib/std/Build.zig:112:19: note: struct declared here
pub const Graph = struct {
                  ^~~~~~
~/zig/test/tests.zig:775:45: error: type '[]const u8' does not support struct initialization syntax
        const cleanup = b.addRemoveDirTree(.{ .cwd_relative = tmp_path });
                                           ~^~~~~~~~~~~~~~~~~~~~~~~~~~~~
~/zig/test/standalone/cmakedefine/build.zig:83:66: error: root struct of file 'Build.Step' has no member named 'MakeOptions'
fn compare_headers(step: *std.Build.Step, options: std.Build.Step.MakeOptions) !void {
                                                   ~~~~~~~~~~~~~~^~~~~~~~~~~~
~/.local/lib/zig/lib/std/Build/Step.zig:1:1: note: struct declared here
id: Id,
^~

Expected Behavior

The Zig compiler can be compiled to wasm32-wasi target for running in the browser.

Attempts toward a solution

The closest solution I found is in the Zig Playground repo, specifically ZIG_WASM.md.

It's a patch that allows the compilation to succeed. I'll include it below for reference.

diff --git a/build.zig b/build.zig
index 9e6e86386..ec8b6b9bd 100644
--- a/build.zig
+++ b/build.zig
@@ -237,7 +237,7 @@ pub fn build(b: *std.Build) !void {
     exe_options.addOption(bool, "llvm_has_xtensa", llvm_has_xtensa);
     exe_options.addOption(bool, "force_gpa", force_gpa);
     exe_options.addOption(bool, "only_c", only_c);
-    exe_options.addOption(bool, "only_core_functionality", only_c);
+    exe_options.addOption(bool, "only_core_functionality", true);

     if (link_libc) {
         exe.linkLibC();
diff --git a/src/link.zig b/src/link.zig
index 703dfb873..3bc4039e7 100644
--- a/src/link.zig
+++ b/src/link.zig
@@ -765,9 +765,9 @@ pub const File = struct {
     /// Commit pending changes and write headers. Takes into account final output mode
     /// and `use_lld`, not only `effectiveOutputMode`.
     pub fn flush(base: *File, comp: *Compilation, prog_node: *std.Progress.Node) FlushError!void {
-        if (build_options.only_c) {
-            assert(base.tag == .c);
-            return @fieldParentPtr(C, "base", base).flush(comp, prog_node);
+        if (true) {
+            assert(base.tag == .wasm);
+            return @fieldParentPtr(Wasm, "base", base).flush(comp, prog_node);
         }
         if (comp.clang_preprocessor_mode == .yes) {
             const emit = base.options.emit orelse return; // -fno-emit-bin
diff --git a/src/link/Wasm/Archive.zig b/src/link/Wasm/Archive.zig
index c4fb9b829..7fdc018ab 100644
--- a/src/link/Wasm/Archive.zig
+++ b/src/link/Wasm/Archive.zig
@@ -208,9 +208,9 @@ pub fn parseObject(archive: Archive, allocator: Allocator, file_offset: u32) !Ob

     const object_name = try archive.parseName(header);
     const name = name: {
-        var buffer: [std.fs.MAX_PATH_BYTES]u8 = undefined;
-        const path = try std.os.realpath(archive.name, &buffer);
-        break :name try std.fmt.allocPrint(allocator, "{s}({s})", .{ path, object_name });
+        // var buffer: [std.fs.MAX_PATH_BYTES]u8 = undefined;
+        // const path = try std.os.realpath(archive.name, &buffer);
+        break :name try std.fmt.allocPrint(allocator, "{s}({s})", .{ archive.name, object_name });
     };
     defer allocator.free(name);

diff --git a/src/main.zig b/src/main.zig
index 39a7adc42..616518d15 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -200,7 +200,7 @@ pub fn main() anyerror!void {
     }

     // Short circuit some of the other logic for bootstrapping.
-    if (build_options.only_c) {
+    if (true) {
         if (mem.eql(u8, args[1], "build-exe")) {
             return buildOutputType(gpa, arena, args, .{ .build = .Exe });
         } else if (mem.eql(u8, args[1], "build-obj")) {
@@ -1544,7 +1544,7 @@ fn buildOutputType(
             }
         },
         .cc, .cpp => {
-            if (build_options.only_c) unreachable;
+            if (true) unreachable;

             emit_h = .no;
             soname = .no;
@@ -3238,7 +3238,7 @@ fn buildOutputType(
     switch (listen) {
         .none => {},
         .stdio => {
-            if (build_options.only_c) unreachable;
+            if (true) unreachable;
             try serve(
                 comp,
                 std.io.getStdIn(),
@@ -3286,7 +3286,7 @@ fn buildOutputType(
         error.SemanticAnalyzeFail => if (listen == .none) process.exit(1),
         else => |e| return e,
     };
-    if (build_options.only_c) return cleanExit();
+    if (true) return cleanExit();
     try comp.makeBinFileExecutable();

     if (test_exec_args.items.len == 0 and object_format == .c) default_exec_args: {

Notably, I found the patch only works for Zig version 0.11.


Versions above 0.11 result in compile errors related to os.realpath(). I think the following issue is related:

On version 0.13, for example, after applying the patch and running below (removed deprecated option -Dno-autodocs and added option -freference-trace recommended by the error message).

zig build -Dtarget=wasm32-wasi -Doptimize=ReleaseSmall -Dno-langref -Dno-lib -freference-trace

The error:

~/.local/lib/zig/lib/std/posix.zig:5340:9: error: WASI does not support os.realpath
        @compileError("WASI does not support os.realpath");
        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
referenced by:
    realpathAlloc: ~/.local/lib/zig/lib/std/fs.zig:726:40
    create: src/codegen/llvm.zig:913:38
    create: src/Compilation.zig:1649:64
    buildOutputType: src/main.zig:3213:29
    main: src/main.zig:203:20
    callMain: ~/.local/lib/zig/lib/std/start.zig:524:32
    wasi_start: ~/.local/lib/zig/lib/std/start.zig:207:65
@eliot-akira eliot-akira added the bug Observed behavior contradicts documented or intended behavior label Jul 17, 2024
@gooncreeper
Copy link
Contributor

Actual errors if you build it correctly:

src/introspect.zig:41:9: error: this function is unsupported on WASI
        @compileError("this function is unsupported on WASI");
        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/introspect.zig:85:9: error: on WASI the global cache dir must be resolved with preopens
        @compileError("on WASI the global cache dir must be resolved with preopens");
        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
lib/std/posix.zig:145:28: error: root struct of file 'c' has no member named 'sockaddr'
pub const sockaddr = system.sockaddr;
                     ~~~~~~^~~~~~~~~
lib/std/c.zig:1:1: note: struct declared here
const std = @import("std");

Command (change your paths to whatever matches your system):
~/release.z/zig-linux-x86_64-0.14.0-dev.311+c50f30038/zig build -Dtarget=wasm32-wasi -Doptimize=ReleaseSmall --zig-lib-dir ~/git/ziglang/zig/lib

@eliot-akira
Copy link
Author

eliot-akira commented Jul 17, 2024

Thank you for the response.

OK, so I'll set the options as suggested, especially --zig-lib-dir to point to lib in the source directory. I did make sure to use the same version of the compiler as the source to compile itself.

Maybe this should have been posted as a question in the forums, or a feature request for an additional target in ziglang/zig-bootstrap.

@eliot-akira eliot-akira changed the title Support compiling Zig compiler to wasm32-wasi target Compiling Zig compiler to wasm32-wasi target Jul 17, 2024
@andrewrk andrewrk added this to the 0.16.0 milestone Jul 19, 2024
@gooncreeper
Copy link
Contributor

#10716
Seems to be a regression

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Observed behavior contradicts documented or intended behavior
Projects
None yet
Development

No branches or pull requests

3 participants