Web builds? #24
Replies: 11 comments 5 replies
|
Hey, SDL2 web builds are possible with Emscripten. However, I really do not know what the current state of compiling C# for the web is. You'd need to both build the native C Platform library with Emscripten and then also compile the C# code with Blazor or something, and have them link up nicely. |
|
Theoretically, it may be possible. Something similar was done with Raylib-cs. Keep in mind, it is uncharted territory so documentation/examples are likely to be sparse. I'd be extremely interested in any attempts to make it work, though. |
|
I did a quick experiment based on the Raylib-cs example. I got the C# running, but for whatever reason I could not get it to P/Invoke into the native DLL I built with emscripten - it always resulted in an error Definitely seems possible though! But would likely require some fixes / changes. |
|
I got a little further with this today, but there's definitely a lot of weird issues. I may create a branch to experiment in. Things I've found so far:
|
|
I tried it too, but with no luck. However, you guys may interested in some things I found during the discovery. #ifdef __EMSCRIPTEN__
#include <emscripten.h>
#endifAnd should use mkdir build
cd build
emcmake cmake ..
emmake make -j4Also in Second, according to ASP.NET Core Doc
Which I find is 3.1.34 in dotnet-8.0. NOTE: emscripten 3.1.34 use it's own version of SDL2 (which is 2.24) to build the library, and that version of SDL don't support |
|
I'm finding that the net 5 guide (that uses Uno Wasm Bootstrap instead of the newer NativeAOT) for fna is actually addressing a lot of these issues:
So hypothetically you could also try shipping your own SDL2 which is implied to work? The library lib prefix removing thing is also mentioned so I guess it's not actually new with nativeaot. I believe Uno actually logs the full emscripten cli in debug, so I may potentially see if I have any old screenshots of the expected emcc flags, I'm not sure if |
|
Not sure if these are doing anything different, but here are two more recently updated .NET 7/8 C# raylib wasm repos: |
I've also just refactored this today, so besides logging functions this should be much more straightforward now. |
|
Alright I got this working but it took a fair amount of wrangling: Brief list of things I had to do to get it working: Getting SDL2 to work:
Getting Foster to work:
[UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvCdecl) })]
private static void HandleLog(IntPtr msg, int type)
{
switch (type)
{
case 0: Log.Info(msg); break;
case 1: Log.Warning(msg); break;
case 2: Log.Error(msg); break;
default: Log.Info(msg); break;
}
}
static unsafe Platform()
{
delegate* unmanaged[Cdecl]<IntPtr, int, void> fn = &HandleLog;
FosterSetLogCallback((IntPtr)fn, 0);
}
[DllImport(DLL)]
public static extern void FosterSetLogCallback(IntPtr logFn, int level);The main loop doesn't work nicely in // in Platform.cs, link to `emscripten_set_main_loop`:
[DllImport(DLL)]
public static extern void emscripten_set_main_loop(IntPtr action, int fps, bool simulateInfiniteLoop);
// in App.cs, comment out `while (!Exiting)` and everything after, and replace with this:
unsafe
{
delegate* unmanaged[Cdecl]<void> fn = &Tick;
Platform.emscripten_set_main_loop(new IntPtr(fn), 60, true);
}
// this does mean the app will never shutdown, but that can be resolved more
// gracefully with a way to end the emscripten main loop, but I didn't do it for this test.
// the Tick() method also needs this attribute added:
[UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvCdecl) })]
private static void Tick()GLSL shaders had to be slightly adjusted to work with v300, which just meant changing the first line in the vertex/fragment shaders to: #version 300 es
precision mediump float;Finally, the resulting dll must be named Creating a Wrapper ApplicationThis project linked above is a really good example of how to set up the project. I changed a few things but mostly it's the same as what they did. I changed the main game to a <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<RuntimeIdentifier>browser-wasm</RuntimeIdentifier>
<WasmMainJSPath>main.js</WasmMainJSPath>
<OutputType>Exe</OutputType>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<RunAOTCompilation>true</RunAOTCompilation>
<WasmBuildNative>true</WasmBuildNative>
<RootNamespace>FosterWasm</RootNamespace>
<WasmNativeStrip>true</WasmNativeStrip>
<EnableAggressiveTrimming>true</EnableAggressiveTrimming>
<PublishTrimmed>true</PublishTrimmed>
<TrimMode>full</TrimMode>
<!-- This is to basically disable globalization to exclude icudt.dat (1.5MB) and reduce size of dotnet.wasm -->
<InvariantGlobalization>true</InvariantGlobalization>
<ValidateExecutableReferencesMatchSelfContained>false</ValidateExecutableReferencesMatchSelfContained>
</PropertyGroup>
<Choose>
<When Condition=" $(Configuration) == 'Debug' ">
<PropertyGroup>
<WasmEmitSymbolMap>true</WasmEmitSymbolMap>
<EmccFlags>-sVERBOSE=1 -sMIN_WEBGL_VERSION=2 -Wbad-function-cast -Wcast-function-type -O2 -g3 -sINITIAL_MEMORY=128MB -sMAXIMUM_MEMORY=2048MB -sALLOW_MEMORY_GROWTH=1 -sASYNCIFY_STACK_SIZE=10000000</EmccFlags>
</PropertyGroup>
</When>
<When Condition=" $(Configuration) == 'Release' ">
<PropertyGroup>
<EmccFlags>-sMIN_WEBGL_VERSION=2 -Wbad-function-cast -Wcast-function-type -O3 -g3 -sINITIAL_MEMORY=128MB -sMAXIMUM_MEMORY=2048MB -sALLOW_MEMORY_GROWTH=1 -sASYNCIFY_STACK_SIZE=10000000</EmccFlags>
</PropertyGroup>
</When>
</Choose>
<ItemGroup>
<WasmExtraFilesToDeploy Include="index.html" />
<WasmExtraFilesToDeploy Include="main.js" />
<NativeFileReference Include="FosterPlatform.a" />
<NativeFileReference Include="SDL2.a" />
<WasmFilesToIncludeInFileSystem Include="$(ProjectDir)..\Assets\**\*.*" TargetPath="Assets\%(RecursiveDir)\%(Filename)%(Extension)" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Source\Source.csproj" />
</ItemGroup>
</Project>ThoughtsAll told this wasn't too bad, and I think we could support it, likely with a separate example project that has a custom wrapper like I described above and pre-build SDL2 and FosterFramework libraries. I don't have much time this month to iterate on this but as a proof of concept it's cool! |
|
So |
|
Is it possible to compile to wasm? |
Uh oh!
There was an error while loading. Please reload this page.
Are web builds supported by SDL2, or easy to compile to? Coming from Unity, I’d like to tinker with Foster for a game jam and publish on itch.io.
All reactions