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

building emscripten: "No emscripten cache. Generate it!" #134

Closed
pancelor opened this issue Aug 15, 2024 · 8 comments
Closed

building emscripten: "No emscripten cache. Generate it!" #134

pancelor opened this issue Aug 15, 2024 · 8 comments

Comments

@pancelor
Copy link
Contributor

pancelor commented Aug 15, 2024

This is going to be a bit of a rambling issue; sorry about that. I'm confused about what exactly the problem is here, there's too many things going on that I'm unfamiliar with.

tl;dr

I don't have emsdk but I do have the manjaro emscripten package; I think raylib is hard-coded to assume I have emsdk, and it's causing problems when try to build for web. But I'm not really certain about anything and don't know the best way to fix it.

emsdk

I'm running Manjaro Linux, and I have the emscripten package installed:

> pacman -Qi emscripten | head -n2
Name            : emscripten
Version         : 3.1.61-1

This installed emcc etc for me:

> emcc -v
emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) 3.1.61-git (67fa4c16496b157a7fc3377afd69ee0445e8a6e3)
clang version 19.0.0git (/startdir/llvm-project 7cfffe74eeb68fbb3fb9706ac7071f8caeeb6520)
Target: wasm32-unknown-emscripten
Thread model: posix
InstalledDir: /opt/emscripten-llvm/bin

When I run > ls $(dirname $(which emcc)) I see various other executables, like em++, emrun, emstrip. But I don't have emsdk (> which emsdk says "emsdk not found")

My best guess about what's going on here is that emsdk is "a small package manager for controlling which tools are installed" , and Manjaro doesn't want another package manager around, so the manjaro emscripten package is meant to replace any need for having emsdk.

zig build ... emscripten

My project uses zig 0.13.0 and a recent version of this library (raylib-zig). My build file is minimally modified from the example project, and includes these lines:

    if (target.query.os_tag == .emscripten) {
        const exe_lib = rlz.emcc.compileForEmscripten(b, name, "src/main.zig", target, optimize);
        // ...

I tried to build it with > zig build run -Dtarget=wasm32-emscripten but got panic: Pass '--sysroot "$EMSDK/upstream/emscripten"'. But, I don't have EMSDK! > echo $EMSDK prints nothing.

I figured out where my emscripten cache is by running > emcc main.c on a simple Hello World program:

> emcc main.c
shared:INFO: old sanity: 3.1.55-git|/opt/emscripten-llvm/bin
shared:INFO: new sanity: 3.1.61-git|/opt/emscripten-llvm/bin
shared:INFO: (Emscripten: config changed, clearing cache)
shared:INFO: (Emscripten: Running sanity checks)
cache:INFO: generating system headers: sysroot_install.stamp... (this will be cached in "/home/pancelor/.emscripten_cache/sysroot_install.stamp" for subsequent builds)
cache:INFO:  - ok
cache:INFO: generating system library: sysroot/lib/wasm32-emscripten/libGL-getprocaddr.a... (this will be cached in "/home/pancelor/.emscripten_cache/sysroot/lib/wasm32-emscripten/libGL-getprocaddr.a" for subsequent builds)
system_libs:INFO: compiled 4 inputs in 0.42s
cache:INFO:  - ok
...

Alright, so then I tried > zig build run -Dtarget=wasm32-emscripten --sysroot ~/.emscripten_cache/sysroot but this fails with "panic: No emscripten cache. Generate it!"

This is coming from raylib/src/build.zig, which seems to be assuming that my cache is managed by emsdk? This line: const cache_include = std.fs.path.join(b.allocator, &.{ b.sysroot.?, "cache", "sysroot", "include" }) catch @panic("Out of memory").

I think this means it's looking for ~/.emscripten_cache/sysroot/cache/sysroot/include on my machine and not finding it, because it doesn't exist. I think it should be looking for ~/.emscripten_cache/sysroot/include instead, but it's hard-coded to assume I have emsdk, which I don't.

editing raylib/src/build.zig

I tried hacking at raylib/src/build.zig and using this:

                var dir = std.fs.openDirAbsolute(b.sysroot.?, std.fs.Dir.OpenDirOptions{ .access_sub_paths = true, .no_follow = true }) catch @panic("No emscripten cache. Generate it!");
                dir.close();
                raylib.addIncludePath(std.Build.LazyPath{ .cwd_relative = b.sysroot.? });

which worked(?) but is now giving me error: 'stdlib.h' file not found, error: 'math.h' file not found, etc. pretty similar to #108. Maybe I didn't "fully" generate the emscripten cache somehow, and I need to flesh it out somehow? But, > ls ~/.emscripten_cache/sysroot/include/stdlib.h finds the file -- it exists.

edit: ah! my bad, I needed b.sysroot.? ++ "/include". well, not that exact syntax; see my comment below

questions

  • Have I misunderstood anything here?
  • Do I need emsdk?
  • Do I just need to edit raylib/src/build.zig? I did that above but I feel like I'm probably making this way harder somehow
    • why do I get error: 'stdlib.h' file not found, when then file exists? (edit: resolved, see below)
@pancelor
Copy link
Contributor Author

oh! I made a mistake with "editing raylib/src/build.zig" -- now that I've changed it to this:

            const cache_include = std.fs.path.join(b.allocator, &.{ b.sysroot.?, "include" }) catch @panic("Out of memory");
            defer b.allocator.free(cache_include);

            var dir = std.fs.cwd().openDir(cache_include, std.fs.Dir.OpenDirOptions{ .access_sub_paths = true, .no_follow = true }) catch @panic("No emscripten cache. Generate it!");
            dir.close();
            raylib.addIncludePath(.{ .cwd_relative = cache_include });

my new error is this:

> zig build run -Dtarget=wasm32-emscripten --sysroot ~/.emscripten_cache/sysroot
run
└─ run /home/pancelor/.emscripten_cache/sysroot/emrun
   └─ run /home/pancelor/.emscripten_cache/sysroot/emcc failure
error: unable to spawn /home/pancelor/.emscripten_cache/sysroot/emcc: FileNotFound
Build Summary: 6/9 steps succeeded; 1 failed (disable with --summary none)

This makes sense, emcc isn't located there. My original questions remain tho -- have I misunderstood anything / is this the best way to go about doing this?

@pancelor
Copy link
Contributor Author

more progress!

  • edited raylib/src/build.zig to change the sysroot include path
  • edited emcc.zig to not use hard-coded paths for emcc and emrun
  • the emscripten webpage opened! and crashed; I added "-sUSE_OFFSET_CONVERTER" as recommended by unable to build for web with zig 0.13.0 #108
  • I added link_step.addArg("--embed-file"); link_step.addArg("res/"); to my personal build.zig to include my game's sprites
  • the game draws in a web browser! but just for one frame I think. the error is unhelpful: "panic: reached unreachable code"

@Not-Nik
Copy link
Owner

Not-Nik commented Aug 17, 2024

Ok, so far this doesn't look like a raylib-zig issue. Could you try adding raylib as a dependency directly and building without raylib-zig in between? If the error persists, please take this to the raylib repo (you can reference this issue there, I'm also looking into main raylib issues occasionally)

@yanfrimmel
Copy link

yanfrimmel commented Aug 29, 2024

For me it was:

  1. Adding to my build.zig: exe.entry = .disabled; , to fix the entry point issue.
  2. Replacing the line in raylib's build.zig in cache folder: raylib.addIncludePath(b.path(cache_include)); with: raylib.addIncludePath(.{ .cwd_relative = cache_include });
  3. Then running: zig build -Dtarget=wasm32-emscripten --sysroot ../emsdk/upstream/emscripten

@Not-Nik
Copy link
Owner

Not-Nik commented Aug 31, 2024

@pancelor could you check if these steps work for you, and if so open an issue on the raylib repo?

@pancelor
Copy link
Contributor Author

I tried adding exe.entry = .disabled; I don't know how this would help (I don't think I have an "entry point issue") and my game still fails in the same way (it runs in the browser but crashes with an unhelpful panic message when I try to move the player)

I don't think the --sysroot ../emsdk/upstream/emscripten will help me, because my local emscripten is not laid out in the normal way, as discussed in my initial post.

@pancelor
Copy link
Contributor Author

pancelor commented Sep 15, 2024

I think I'm done trying to make this work for now; here's my thoughts on what I think should happen. I realize that just writing them here doesn't do much, but it seems best to write them somewhere, and I don't have the social energy right now to start an additional issue in the raylib repo, so I'll write my thoughts here and then close this.

  • I think my current bug (the game runs until I move the player, and the JS console says "panic: reached unreachable code") is mostly my fault somehow. Maybe I've misconfigured the emcc args and I wish the error were more helpful, but I think emscripten is mostly working -- I'm just doing something wrong somehow.
  • I think raylib and raylib-zig should both include emsdk directly as a dependency in build.zig.zon, the way sokol-zig does it. By including the files instead of depending on my system to have emsdk installed, the build is more portable, which is one of the main goals of the zig build system (sources: andrewrk talk, eliminate absolute paths from the build system ziglang/zig#18450, found via [build] Zig emscripten build broken? raysan5/raylib#4010)
    • note: pacman.zig (which depends on sokol-zig) works great for me: just run zig build run -Dtarget=wasm32-emscripten and it builds emsdk, sokol, and everything else needed to make things work
  • If either project (raylib or raylib-zig) would rather depend on system-installed libraries like emsdk (this goes against the zig build system philosophy as far as I understand it, but I can imagine reasons you might want to), then both projects should remove/deprecate the --sysroot arg and add a --sysroot_cache arg which points to the cache directory instead. i.e. make this change:
    - const cache_include = std.fs.path.join(b.allocator, &.{ b.sysroot.?, "cache", "sysroot", "include" }) catch @panic("Out of memory");
    + const cache_include = std.fs.path.join(b.allocator, &.{ b.sysroot_cache.?, "include" }) catch @panic("Out of memory");
    (and various other small changes to support this new path)
    This would let things work on my machine; I would pass --sysroot_cache ~/.emscripten_cache/sysroot, people with emsdk would pass --sysroot_cache "$EMSDK/upstream/emscripten/cache/sysroot", and things would work on either system

pancelor added a commit to pancelor/raylib-zig that referenced this issue Sep 15, 2024
I am unsure what the point of this file is, so maybe I should not be
removing it. But the comment says to try removing it to see if things
work fine, and things work fine on my machine when I remove it.

I tested 3 or 4 of the builtin examples using commands like this:
zig build raw_stream -Dtarget=wasm32-emscripten --sysroot ~/.emscripten_cache/sysroot

(see also Not-Nik#134; my sysroot setup is a bit weird. but I don't think
that would affect this at all)
@Not-Nik
Copy link
Owner

Not-Nik commented Sep 28, 2024

I think I like the "emcc as a dependency" thing, but this has to start at a raylib level. I can add a small patch that just attempts to find emcc in the PATH, but that won't fix your cache issue. In the meantime I can't even get an emscripten build going WITH emsdk, so I can't work on this too much.

Not-Nik pushed a commit that referenced this issue Sep 28, 2024
I am unsure what the point of this file is, so maybe I should not be
removing it. But the comment says to try removing it to see if things
work fine, and things work fine on my machine when I remove it.

I tested 3 or 4 of the builtin examples using commands like this:
zig build raw_stream -Dtarget=wasm32-emscripten --sysroot ~/.emscripten_cache/sysroot

(see also #134; my sysroot setup is a bit weird. but I don't think
that would affect this at all)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants