Since support for WebAssembly 1.0 was just introduced in the nightly builds of Firefox and Chromium, I gave it a try and things look good, at least with firefox-nightly. The following nim.cfg
@if emscripten:
cc = clang
clang.exe = "emcc"
clang.linkerexe = "emcc"
clang.options.linker = ""
cpu = "i386"
passC = "-s WASM=1 -s 'BINARYEN_METHOD=\"native-wasm\"' -Iemscripten"
passL = "-s WASM=1 -Lemscripten -s TOTAL_MEMORY=335544320"
# use ALLOW_MEMORY_GROWTH=1 instead of TOTAL_MEMORY if performance isn't top priority
@end
lets one compile Nim to native wasm by setting -d:emscripten on the command line.
Trying something crazy first, I took Araqs version of JohnS's GC test and it compiled successfully with
nim c -d:useRealtimeGC -d:release -d:emscripten --out=index.html GCBench.nim
The result actually seems to work in the broswer, the HTML page has an output text area showing this:
Worst push time: 1000000 nano seconds
[GC] total memory: 275017728
[GC] occupied memory: 274141184
[GC] stack scans: 4092
[GC] stack cells: 1
[GC] cycle collections: 0
[GC] max threshold: 0
[GC] zct capacity: 1024
[GC] max cycle table size: 0
[GC] max pause time [ms]: 1
[GC] max stack size: 64
The GC claims it is actually doing something and I am inclined to believe it :-)
Sub-ms timing doesn't work in the browser, but the fact that the push time is in the single digit ms ballpark looks good too.
P.S.: the wasm file has 92kB, so in terms of runtime overhead we are on par with jQuery minified.
Yeah, honestly didn't expect that. We need some heavier benchmarking to be sure that it's viable though, I'm working on that.
As soon as the browser wasm VMs offer access to the HTML page DOM and some globals (as planned), we could actually bury and forget JavaScript. For me, personally, this would be a thing to celebrate :-)
Also, for Nim as a language, wasm offers a big chance to shine. As of now, the easy and proven way to compile to wasm is emscripten, which needs C/C++ as input. Plus, wasm VMs do not yet have their own garbage collectors (planned for the future). So AFAIU people who want to write code in a modern language with garbage collection and compile to wasm now do not have much of a choice apart from Nim.
tryed to repeate after you, but got
C:\Nim\dev\guitest>nim c -d:useRealtimeGC -d:release -d:emscripten --out=index.html test.nim
Hint: used config file 'C:\Nim\nim160-32\nim-0.16.0\config\nim.cfg' [Conf]
Hint: used config file 'C:\Nim\dev\guitest\nim.cfg' [Conf]
Hint: system [Processing]
Hint: test [Processing]
CC: test
Error: unhandled exception: The system cannot find the file specified.
Additional info: Requested command not found: 'emcc.exe -c -w -s WASM=1 -s 'BINARYEN_METHOD="native-wasm"' -Iemscripten
-O3 -IC:\Nim\nim160-32\nim-0.16.0\lib -o C:\Nim\dev\guitest\nimcache\test.o C:\Nim\dev\guitest\nimcache\test.c'. OS e
rror: [OSError]
seems i need change my nim.cfg, but i haven't ideas how to. Problem is next, somewhy nim runs 'emcc.exe', but correct command surely is 'emcc', how can i change this@vic1107, I changed from emcc to emcc.bat because I have portable emscripten instead of installed one.
I changed the cpu to amd64, and I got this error:
D:\Installer\nim\lib\nimbase.h:443:64: error:
'Nim_and_C_compiler_disagree_on_target_architecture' declared as an array
with a negative size
...sizeof(NI) == sizeof(void*) && NIM_INTBITS == sizeof(NI)*8 ? 1 : -1];
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1 error generated.
In file included from d:\College\Nim\zmisc\nimcache\stdlib_parseutils.c:9:
D:\Installer\nim\lib\nimbase.h:443:64: In file included from d:\dev\Nim\zmisc\nimcache\stdlib_system.c:9:
error: D:\Installer\nim\lib\nimbase.h:443:64:
'Nim_and_C_compiler_disagree_on_target_architecture' declared as an array
with aERROR:root:compiler frontend failed to generate LLVM bitcode, halting
error: negative size
'Nim_and_C_compiler_disagree_on_target_architecture' declared as an array
with a
negative size
...sizeof(NI) == sizeof(void*) && NIM_INTBITS == sizeof(NI)*8 ? 1 : -1]; ...sizeof(NI) == sizeof(void*) && NIM_INTBITS == sizeof(NI)*8 ? 1 : -1];
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1 error generated.
d:\dev\Nim\zmisc\nimcache\stdlib_system.c:11:10: fatal error: 'io.h' file
not found
#include <io.h>
^~~~~~
In file included from d:\dev\Nim\zmisc\nimcache\stdlib_strutils.c:9:
D:\Installer\nim\lib\nimbase.h:443:64: error:
E RROR:root:compiler frontend failed to generate LLVM bitcode, halting
'Nim_and_C_compiler_disagree_on_target_architecture' declared as an array
with a negative size
...sizeof(NI) == sizeof(void*) && NIM_INTBITS == sizeof(NI)*8 ? 1 : -1];
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1 error generated.
ERROR:root:compiler frontend failed to generate LLVM bitcode, halting
CC: stdlib_math
CC: stdlib_algorithm
2 errors generated.
ERROR:root:compiler frontend failed to generate LLVM bitcode, halting
In file included from d:\College\Nim\zmisc\nimcache\stdlib_math.c:9:
D:\Installer\nim\lib\nimbase.h:443:64: error:
'Nim_and_C_compiler_disagree_on_target_architecture' declared as an array
with a negative size
...sizeof(NI) == sizeof(void*) && NIM_INTBITS == sizeof(NI)*8 ? 1 : -1];
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1 error generated.
In file included from d:\College\Nim\zmisc\nimcache\stdlib_algorithm.c:9:
D:\Installer\nim\lib\nimbase.h:443:64: error:
'Nim_and_C_compiler_disagree_on_target_architecture' declared as an array
with a negative size
...sizeof(NI) == sizeof(void*) && NIM_INTBITS == sizeof(NI)*8 ? 1 : -1];
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1 error generated.
ERROR:root:compiler frontend failed to generate LLVM bitcode, halting
ERROR:root:compiler frontend failed to generate LLVM bitcode, halting
Hint: [Link]
ERROR:root:d:\dev\Nim\zmisc\nimcache\stdlib_algorithm.o: No such file or directory ("d:\dev\Nim\zmisc\nimcache\stdlib_algorithm.o" was expected to be an input file, based on the commandline arguments provided)
Error: execution of an external program failed: 'emcc.bat -o d:\dev\Nim\zmisc\araqgc.html d:\dev\Nim\zmisc\nimcache\stdlib_algorithm.o d:\dev\Nim\zmisc\nimcache\stdlib_math.o d:\dev\Nim\zmisc\nimcache\stdlib_parseutils.o d:\dev\Nim\zmisc\nimcache\stdlib_strutils.o d:\dev\Nim\zmisc\nimcache\stdlib_system.o d:\dev\Nim\zmisc\nimcache\araqgc.o -s WASM=1 -Lemscripten TOTAL_MEMORY=335544320 '
Is it the error because I defined it using cpu=amd64?
I'm sure I'm using 64bit toolchain though.
Ouch, thank for the info.
I don't think I'll be able to test it for awhile, too lazy to setup 32bit tooling right now :P
Hi all,
Did any of you try to build the rosseta code opengl example for webasm?
nim c -d:useRealtimeGC -d:release -d:emscripten --out=index.html src/test.nim
Hint: used config file '/home/xyz/personal/devel/nim/Nim/config/nim.cfg' [Conf]
Hint: used config file '/home/xyz/projects/test/nim.cfg' [Conf]
Hint: used config file '/home/xyz/projects/test/src/test.nim.cfg' [Conf]
Hint: system [Processing]
Hint: test [Processing]
Hint: opengl [Processing]
Hint: macros [Processing]
Hint: sequtils [Processing]
Hint: glut [Processing]
test.nim(36, 3) Error: undeclared identifier: 'loadExtensions'
This is the code I am talking about.
#? braces
import opengl, glut
proc paint() {.cdecl.} {
glClearColor(0.3,0.3,0.3,0.0);
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
glShadeModel(GL_SMOOTH);
glLoadIdentity();
glTranslatef(-15.0, -15.0, 0.0);
glBegin(GL_TRIANGLES);
glColor3f(1.0, 0.0, 0.0);
glVertex2f(0.0, 0.0);
glColor3f(0.0, 1.0, 0.0);
glVertex2f(30.0, 0.0);
glColor3f(0.0, 0.0, 1.0);
glVertex2f(0.0, 30.0);
glEnd();
glFlush();
}
proc reshape(width, height: GLint) {.cdecl.} {
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-30.0, 30.0, -30.0, 30.0, -30.0, 30.0);
glMatrixMode(GL_MODELVIEW);
}
when (isMainModule) {
enableAutoGlErrorCheck(false);
loadExtensions();
glutInit();
glutInitWindowSize(640, 480);
discard glutCreateWindow("Triangle");
glutDisplayFunc(paint);
glutReshapeFunc(reshape);
glutMainLoop();
}
Thanks.
Hi,
Did any of you try to build the rosseta code opengl example for webasm?
No, I didn't. If I ever try, I will first read the chapter about OpenGL support in the Emscripten manual. That would tell me something about the various OpenGL APIs Emscripten offers, how to select one and what functions they define. ;-)