├── .gitignore ├── mylib ├── v.mod ├── .gitignore ├── mylib.v └── mylib_wrapper.c ├── Dockerfile ├── README.md ├── Makefile └── index.html /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode/ 2 | *.wasm 3 | *.js 4 | *.c 5 | *.h 6 | !mylib/*.c 7 | !mylib/*.h -------------------------------------------------------------------------------- /mylib/v.mod: -------------------------------------------------------------------------------- 1 | Module { 2 | name: 'mylib' 3 | description: '' 4 | version: '' 5 | license: '' 6 | dependencies: [] 7 | } 8 | -------------------------------------------------------------------------------- /mylib/.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | main 3 | mylib 4 | *.exe 5 | *.exe~ 6 | *.so 7 | *.dylib 8 | *.dll 9 | vls.log 10 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM emscripten/emsdk:latest 2 | 3 | # Add vlang layer 4 | ENV VVV /opt/vlang 5 | ENV PATH "/opt/vlang::${PATH}" 6 | RUN git clone https://github.com/vlang/v /opt/vlang && cd /opt/vlang && make && ./v symlink 7 | -------------------------------------------------------------------------------- /mylib/mylib.v: -------------------------------------------------------------------------------- 1 | module mylib 2 | 3 | [export: 'mylib_add'] 4 | pub fn add(a int, b int) int { 5 | return a + b 6 | } 7 | 8 | [export: 'mylib_hello_world'] 9 | pub fn hello_world() { 10 | println("Hello, world!") 11 | } 12 | 13 | [export: 'mylib_version'] 14 | pub fn version() int { 15 | return 42 16 | } 17 | 18 | [export: 'mylib_v_hash'] 19 | pub fn v_hash() string { 20 | return @VHASH 21 | } 22 | 23 | [export: 'mylib_string_custom_reverse'] 24 | pub fn string_custom_reverse(input string) string { 25 | return input.reverse() 26 | } 27 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # V WebAssembly demo 2 | 3 | Compile a simple V library into WebAssembly! 4 | Require Emscripten or Docker. 5 | 6 | ## Build 7 | ### Docker-less 8 | You need to install Emscriptem, make and V. 9 | ``` 10 | make 11 | ``` 12 | ### docker emcc 13 | ``` 14 | docker build -t emscripten-v . 15 | docker run --rm -v $(pwd):/src emscripten-v:latest make 16 | ``` 17 | 18 | ## Test 19 | To see the output from the console, you need to run a simple web server. 20 | You can use python: 21 | ``` 22 | python -m http.server 8080 23 | ``` 24 | 25 | ## License 26 | No credit required but appreciated - CC0 27 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Get compilers 2 | EMSCRIPTEM_CC = $(shell which emcc) 3 | V_CC = $(shell which v) 4 | 5 | # Library c file 6 | LIB = mylib.c 7 | 8 | # Wrapper used for V => C 9 | WRAPPER_FILE = mylib_wrapper.c 10 | WRAPPER = mylib/$(WRAPPER_FILE) 11 | 12 | # Tell Emscripten to treat the code as a library (no main function) 13 | EMCC_FLAGS = --no-entry 14 | # Export the functions that interface JS <=> Wasm 15 | EMCC_FLAGS += -s "EXPORTED_RUNTIME_METHODS=['ccall','cwrap']" 16 | # Tell Emscriptem to make add,hello_world, vhash and version functions visible 17 | EMCC_FLAGS += -s EXPORTED_FUNCTIONS=_add,_hello_world,_version,_v_hash 18 | # Force set linux macro 19 | EMCC_FLAGS += -D__linux__ 20 | 21 | # Misc - Enable optimizations 22 | EMCC_OPT = -O2 23 | 24 | # Flags to the V Compiler 25 | V_FLAGS = -prod -shared -gc none -d no_backtrace 26 | 27 | all: lib emscripten 28 | 29 | # Build the library using V, then inject emscripten wrapper into the C generated 30 | # file 31 | lib: 32 | $(V_CC) mylib $(V_FLAGS) -o $(LIB) 33 | cat $(WRAPPER) >> $(LIB) 34 | 35 | # Generate a JS and a wasm file 36 | emscripten: 37 | $(EMSCRIPTEM_CC) $(LIB) -o mylib.js $(EMCC_FLAGS) $(EMCC_OPT) 38 | 39 | clean: 40 | $(RM) *.wasm *.js *.c *.h -------------------------------------------------------------------------------- /mylib/mylib_wrapper.c: -------------------------------------------------------------------------------- 1 | #include 2 | // Should be already included 3 | #include 4 | 5 | // ----------------------------------------------------------------------------- 6 | // Declarations 7 | // ----------------------------------------------------------------------------- 8 | 9 | // ----------------------------------------------------------------------------- 10 | // Wrapper 11 | // ----------------------------------------------------------------------------- 12 | 13 | 14 | #ifdef __cplusplus 15 | extern "C" { 16 | #endif 17 | 18 | EMSCRIPTEN_KEEPALIVE void hello_world() { 19 | mylib_hello_world(); 20 | } 21 | 22 | EMSCRIPTEN_KEEPALIVE int add(int a, int b) { 23 | return mylib_add(a, b); 24 | } 25 | 26 | EMSCRIPTEN_KEEPALIVE int version() { 27 | return mylib_version(); 28 | } 29 | 30 | EMSCRIPTEN_KEEPALIVE char* v_hash() { 31 | string hsh = mylib_v_hash(); 32 | return (char *)hsh.str; 33 | } 34 | 35 | EMSCRIPTEN_KEEPALIVE char* string_custom_reverse(char* input) { 36 | string tmp; 37 | tmp.str = (byte *)input; 38 | tmp.len = strlen(input); 39 | tmp.is_lit = 1; 40 | 41 | string hsh = mylib_string_custom_reverse(tmp); 42 | return (char *)hsh.str; 43 | } 44 | 45 | #ifdef __cplusplus 46 | } 47 | #endif -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | V WASM demo! 5 | 6 | 7 | 8 | 28 | 29 | 30 |

Check out the console!

31 | 32 | 33 | --------------------------------------------------------------------------------