ialex32x / unity-jsb

It brings Javascript runtime capability to Unity3D by integrating QuickJS.
MIT License
337 stars 43 forks source link

How to build QuickJS within UnityJsb? #29

Open etiennepinchon opened 3 years ago

etiennepinchon commented 3 years ago

Hi! I would like to know how to build QuickJs within UnityJsb on Windows. I went into jsb_build/quickjs and run . make_jsb_win.sh unfortunately I am getting errors:

CMake Error: 
CMake was unable to find a build program corresponding to "Unix Makefiles".  
CMAKE_MAKE_PROGRAM is not set.  You probably need to select a different build tool.
building...
The parameter is incorrect
CMake Error: Generator: execution of make failed. Make command was:  -f Makefile

Any idea how to make this work? Kind regards, Etienne

ialex32x commented 3 years ago

Hi etinnepinchon, what platform and toolset are you using? The original quickjs source can not be compiled on windows. It should be cross-compiled on the Linux system (or Linux subsystem in windows).

Or, you can use github actions to compile it remotely, just like what in this project (in .github/workflows).

etiennepinchon commented 3 years ago

Hey! Ohh I didn't see the .github/workflow folder! Thank you very much that is exactly what I needed!

Btw I was doing some benchmarking with the quickJS.dll in your project (mainly a for loop iterating over simple instructions) and then swapped it with the latest dll from the original project (https://github.com/bellard/quickjs) and saw a ~4x speed boost compared to the one in UnityJSB which I found very surprising. Are you aware of this speed difference?

The code used:

var a = 0; for (let i = 0; i < 10000000; i++) { a++; a *= 2; a /= 3; }

quickJS.dll from bellard/quickjs: ~1.4 seconds quickJS.dll from UnityJSB: ~4 seconds

I ran this code in the exampleunity script from the sample scene

ialex32x commented 3 years ago

I haven't do any benchmark yet. It's strange, I didn't modify quickjs source, so the plain js like that should have same performance. I'll check it soon.

etiennepinchon commented 3 years ago

Awesome thank you very much! I rerun the github action on my end with the lastest from bellard and the speed went back to 1.4secs.

Oh one more thing if that's okay: does the project support WebGL? I have seen the webgl folder but I am getting errors when building the web player:

Failed running "C:/Program Files/Unity/Hub/Editor/2020.2.1f1/Editor/Data/PlaybackEngines/WebGLSupport\BuildTools\Emscripten_Win\python\2.7.5.3_64bit\python.exe" -E "C:/Program Files/Unity/Hub/Editor/2020.2.1f1/Editor/Data/PlaybackEngines/WebGLSupport\BuildTools\Emscripten\emcc"

stdout:
stderr:In file included from
quickjs/quickjs-latest/libunicode.c:283:12: error: implicit declaration of function 'realloc_is_forbidden' is invalid in C99 [-Werror,-Wimplicit-function-declaration]    return realloc(ptr, size);          
quickjs/quickjs-latest/quickjs.c:1786:22: note: expanded from macro 'realloc'#define realloc(p,s) realloc_is_forbidden(p,s)                    
quickjs/quickjs-latest/quickjs.c:6198:13: error: expected ')'            CONFIG_VERSION " version, %d-bit, malloc limit: %"PRId64"\n\n",           
quickjs/quickjs-latest/cutils.c:86:12: warning: incompatible integer to pointer conversion returning 'int' from a function with result type 'void *' [-Wint-conversion]    return realloc(ptr, size);       
quickjs/quickjs-latest/quickjs.c:10005:19: note: previous definition is herestatic inline int to_digit(int c) 
quickjs/quickjs-latest/quickjs.c:47864:16: note: previous definition is herestatic int64_t floor_div(int64_t a, int64_t b) {             
...

Have you seen those before?

ialex32x commented 3 years ago

Yes, it's just can not build for WebGL, because I haven't finished this part, and have no specific plan yet on this part of the work.

BTW, I'll check the performance issue today.

ialex32x commented 3 years ago

The performance issue has been fixed now. It's because of some missing compiler flags in the make file.

etiennepinchon commented 3 years ago

Awesome! Glad you could fix it! Do you know what is preventing QuickJs from being built for WebGL? It must be possible, some people did build for emscripten: https://github.com/justjake/quickjs-emscripten I removed the big number header which was causing those redefinition errors and was able to build correctly for webGL in Unity. However I am still getting a crash went launching the app: "the dll for quickJs cannot be found", could be some linker issue?

ialex32x commented 3 years ago

Yes, it's possible. I'll have a try to build it. But as I see, the WebGL build is not so reasonable and valuable because of the performance issue and many limitations. The script coding experience will be different from the common H5 dev. And it still doesn't make really sense to create H5 games by Unity at present.

For the issue you've encountered, did you set the DllImport attribute to "__Internal" for the external functions from quickjs?

etiennepinchon commented 3 years ago

Hey! My use case is for a 3d tool that I would like use on the web and quickjs seems to be the best candidate for what I need. I can build the core library just fine however as soon as I try to call one of the quickJs functions I get wasm errors.

I tried with both [DllImport("__Internal" and [DllImport("quickjs" but no luck so far :/

Wasm errors for [DllImport("__Internal":

build.loader.js:1 LinkError: WebAssembly.instantiate(): Import #6 module="env" function="_lre_id_continue_table_ascii" error: global import must be a number, valid Wasm reference, or WebAssembly.Global object

Wasm errors for [DllImport("quickjs":

DllNotFoundException: Unable to load DLL 'quickjs': The specified module could not be found.

C# api call

using System.Runtime.InteropServices;
using System.Runtime.CompilerServices;
using System.Security;

namespace QuickJS.Native
{
    public static class QuickJSNativeApi
    {
        [DllImport("__Internal", CallingConvention = CallingConvention.Cdecl)]
        public static extern JSContext JS_NewContext(JSRuntime rt);

        [DllImport("__Internal", CallingConvention = CallingConvention.Cdecl)]
        public static extern JSRuntime JS_NewRuntime();

        // ...
    }
}

the libquickjs.c that I compile in Unity


//#include "../quickjs/quickjs-latest/libregexp.c"
#include "../quickjs/quickjs-latest/libunicode.c"
#include "../quickjs/quickjs-latest/cutils.c"
#include "../quickjs/quickjs-latest/quickjs.c"
//#include "../quickjs/quickjs-latest/libbf.c"
//#include "../quickjs/quickjs-latest/quickjs-libc.c"
#include "../quickjs/quickjs-latest/unity_qjs.c"

Any idea what could go wrong here?

etiennepinchon commented 3 years ago

Update:

I added back #include "../quickjs/quickjs-latest/libregexp.c" and patched a few duplicated functions errors and got it running. I am now able to create a JSRuntime in wasm however the context always return null and stop the process or throw: build.loader.js:1 exception thrown: RuntimeError: memory access out of bounds,RuntimeError: memory access out of bounds

// .. runtime setup
JSContext ctx = JS_NewContext(_runtime); 
if (ctx == JSContext.Null)
{
// true => null
}
ialex32x commented 3 years ago

I've fixed the build error. But got the same memory access runtime error issue. And have no idea about why at present. It seems the memory allocated in NewRuntime has something wrong. It will enter an infinite loop if directly call FreeRuntime after NewRuntime.