From 416c21da598c1efe19855fca1265078b38875041 Mon Sep 17 00:00:00 2001 From: Boris Tsarev Date: Thu, 7 Aug 2014 11:28:03 +0400 Subject: [PATCH 01/91] Fixed wget2 tests by adding ST_ABORTED request status --- tests/http.cpp | 8 +++++--- tests/http.h | 3 ++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/tests/http.cpp b/tests/http.cpp index deb3eec25cd80..3becbe7ecbf8f 100644 --- a/tests/http.cpp +++ b/tests/http.cpp @@ -131,6 +131,7 @@ void http::runRequest(const char* page, int assync) { */ void http::abortRequest() { emscripten_async_wget2_abort(_handle); + _status = ST_ABORTED; } /** @@ -249,7 +250,8 @@ void wait_http(void* request) { } else { if (req->getStatus() == http::ST_OK) { printf("Success Request n°%d : %s\n",req->getId(),req->getContent()); - + } else if (req->getStatus() == http::ST_ABORTED) { + printf("Aborted Request n°%d", req->getId()); } else { printf("Error Request n°%d : %s\n",req->getId(), req->getError()); } @@ -265,8 +267,8 @@ void wait_http(void* request) { int main() { time_elapsed = emscripten_get_now(); - http* http1 = new http("http://localhost/~boristsarev",http::REQUEST_GET,"Demo1.js"); - http1->runRequest("/download.php?url=Demo1.js",http::ASSYNC_THREAD); + http* http1 = new http("https://github.com",http::REQUEST_GET,"emscripten_master.zip"); + http1->runRequest("/kripken/emscripten/archive/master.zip",http::ASSYNC_THREAD); http* http2 = new http("https://github.com",http::REQUEST_GET,"wolfviking_master.zip"); http2->runRequest("/wolfviking0/image.js/archive/master.zip",http::ASSYNC_THREAD); diff --git a/tests/http.h b/tests/http.h index 19b52802d8b4d..f89396d46a33d 100644 --- a/tests/http.h +++ b/tests/http.h @@ -21,7 +21,8 @@ class http { enum Status { ST_PENDING = 0, ST_FAILED, - ST_OK + ST_OK, + ST_ABORTED, }; enum RequestType { From 4264dab9895df3c8a45cbc984341176274c7f6d6 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 7 Aug 2014 16:15:54 -0700 Subject: [PATCH 02/91] add fastcomp stack overflow checks and testing --- emscripten.py | 3 ++- tests/core/stack_overflow.cpp | 29 +++++++++++++++++++++++++++++ tests/test_core.py | 5 +++++ 3 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 tests/core/stack_overflow.cpp diff --git a/emscripten.py b/emscripten.py index 216a741055654..1dc021eb43eb7 100755 --- a/emscripten.py +++ b/emscripten.py @@ -1207,7 +1207,8 @@ def math_fix(g): var ret = 0; ret = STACKTOP; STACKTOP = (STACKTOP + size)|0; - ''' + ('STACKTOP = (STACKTOP + 3)&-4;' if settings['TARGET_X86'] else 'STACKTOP = (STACKTOP + 7)&-8;') + ''' + ''' + ('STACKTOP = (STACKTOP + 3)&-4;' if settings['TARGET_X86'] else 'STACKTOP = (STACKTOP + 7)&-8;\n') + + ('if ((STACKTOP|0) >= (STACK_MAX|0)) abort();\n' if settings['ASSERTIONS'] else '') + ''' return ret|0; } function stackSave() { diff --git a/tests/core/stack_overflow.cpp b/tests/core/stack_overflow.cpp new file mode 100644 index 0000000000000..67dba43e11a72 --- /dev/null +++ b/tests/core/stack_overflow.cpp @@ -0,0 +1,29 @@ +#include +#include +#include + +void recurse(int x); + +void act(volatile int *a) { + printf("act %d\n", *a); + int b = (int)(intptr_t)(alloca(*a)); + if (b < *a) *a--; + recurse(*a); +} + +void recurse(int x) { + printf("recurse %d\n", x); + volatile int a = x; + if (x*x < x) { + act(&a); + if (a < x) x = a; + x--; + return; + } + if (x > 0) recurse(x-1); +} + +int main() { + recurse(1000*1000); +} + diff --git a/tests/test_core.py b/tests/test_core.py index ded164a741a2f..cf0e2b0201cf8 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -2825,6 +2825,11 @@ def test_bsearch(self): self.do_run_from_file(src, output) + def test_stack_overflow(self): + if os.environ.get('EMCC_FAST_COMPILER') == '0': return self.skip('needs fastcomp') + Settings.ASSERTIONS = 1 + self.do_run(open(path_from_root('tests', 'core', 'stack_overflow.cpp')).read(), 'abort()') + def test_nestedstructs(self): src = ''' #include From de2583876c3c340a68e458e3baffa1379d4e5d26 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 7 Aug 2014 16:50:01 -0700 Subject: [PATCH 03/91] explicitly provide Module to EM_ASM scripts, so that they work even if Module was removed by closure; #2639 --- src/runtime.js | 3 +- tests/test_core.py | 6 +- tests/webidl/post.js | 128 +++++++++++++++++++++---------------------- 3 files changed, 70 insertions(+), 67 deletions(-) diff --git a/src/runtime.js b/src/runtime.js index 84ee4255f4f69..bfbd9c320062d 100644 --- a/src/runtime.js +++ b/src/runtime.js @@ -420,7 +420,8 @@ var Runtime = { } #if NO_DYNAMIC_EXECUTION == 0 try { - var evalled = eval('(function(' + args.join(',') + '){ ' + source + ' })'); // new Function does not allow upvars in node + // Module is the only 'upvar', which we provide directly. We also provide FS for legacy support. + var evalled = eval('(function(Module, FS) { return function(' + args.join(',') + '){ ' + source + ' } })')(Module, typeof FS !== 'undefined' ? FS : null); } catch(e) { Module.printErr('error in executing inline EM_ASM code: ' + e + ' on: \n\n' + source + '\n\nwith args |' + args + '| (make sure to use the right one out of EM_ASM, EM_ASM_ARGS, etc.)'); throw e; diff --git a/tests/test_core.py b/tests/test_core.py index cf0e2b0201cf8..cb7ba9f1c463e 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -6293,7 +6293,9 @@ def test_webidl(self): assert os.path.exists('glue.cpp') assert os.path.exists('glue.js') - open('export.js', 'w').write('''this['Module'] = Module;\n''') + # Export things on "TheModule". This matches the typical use pattern of the bound library + # being used as Box2D.* or Ammo.*, and we cannot rely on "Module" being always present (closure may remove it). + open('export.js', 'w').write('''this['TheModule'] = Module;\n''') self.emcc_args += ['--post-js', 'glue.js', '--post-js', 'export.js'] shutil.copyfile(path_from_root('tests', 'webidl', 'test.h'), self.in_dir('test.h')) shutil.copyfile(path_from_root('tests', 'webidl', 'test.cpp'), self.in_dir('test.cpp')) @@ -6301,7 +6303,7 @@ def test_webidl(self): def post(filename): src = open(filename, 'a') src.write('\n\n') - src.write('var Module = this.Module;\n') + src.write('var TheModule = this.TheModule;\n') src.write('\n\n') src.write(open(path_from_root('tests', 'webidl', 'post.js')).read()) src.write('\n\n') diff --git a/tests/webidl/post.js b/tests/webidl/post.js index 831e2c02ba7de..712f4e58db6c9 100644 --- a/tests/webidl/post.js +++ b/tests/webidl/post.js @@ -1,157 +1,157 @@ // Part 1 -var sme = new Module.Parent(42); +var sme = new TheModule.Parent(42); sme.mulVal(2); -Module.print('*') -Module.print(sme.getVal()); +TheModule.print('*') +TheModule.print(sme.getVal()); sme.parentFunc(90); -Module.print(typeof sme.getAsConst()); +TheModule.print(typeof sme.getAsConst()); -Module.print('c1'); +TheModule.print('c1'); -var c1 = new Module.Child1(); -Module.print(c1.getVal()); +var c1 = new TheModule.Child1(); +TheModule.print(c1.getVal()); c1.mulVal(2); -Module.print(c1.getVal()); -Module.print(c1.getValSqr()); -Module.print(c1.getValSqr(3)); -Module.print(c1.getValTimes()); // default argument should be 1 -Module.print(c1.getValTimes(2)); +TheModule.print(c1.getVal()); +TheModule.print(c1.getValSqr()); +TheModule.print(c1.getValSqr(3)); +TheModule.print(c1.getValTimes()); // default argument should be 1 +TheModule.print(c1.getValTimes(2)); c1.parentFunc(90); -Module.print('c1 v2'); +TheModule.print('c1 v2'); -c1 = new Module.Child1(8); // now with a parameter, we should handle the overloading automatically and properly and use constructor #2 -Module.print(c1.getVal()); +c1 = new TheModule.Child1(8); // now with a parameter, we should handle the overloading automatically and properly and use constructor #2 +TheModule.print(c1.getVal()); c1.mulVal(2); -Module.print(c1.getVal()); -Module.print(c1.getValSqr()); -Module.print(c1.getValSqr(3)); +TheModule.print(c1.getVal()); +TheModule.print(c1.getValSqr()); +TheModule.print(c1.getValSqr(3)); -Module.print('c2') +TheModule.print('c2') -var c2 = new Module.Child2(); -Module.print(c2.getVal()); +var c2 = new TheModule.Child2(); +TheModule.print(c2.getVal()); c2.mulVal(2); -Module.print(c2.getVal()); -Module.print(c2.getValCube()); +TheModule.print(c2.getVal()); +TheModule.print(c2.getValCube()); var succeeded; try { succeeded = 0; - Module.print(c2.doSomethingSecret()); // should fail since private + TheModule.print(c2.doSomethingSecret()); // should fail since private succeeded = 1; } catch(e) {} -Module.print(succeeded); +TheModule.print(succeeded); try { succeeded = 0; - Module.print(c2.getValSqr()); // function from the other class + TheModule.print(c2.getValSqr()); // function from the other class succeeded = 1; } catch(e) {} -Module.print(succeeded); +TheModule.print(succeeded); try { succeeded = 0; c2.getValCube(); // sanity succeeded = 1; } catch(e) {} -Module.print(succeeded); +TheModule.print(succeeded); -Module.Child2.prototype.printStatic(); // static calls go through the prototype +TheModule.Child2.prototype.printStatic(); // static calls go through the prototype // virtual function c2.virtualFunc(); -Module.Child2.prototype.runVirtualFunc(c2); +TheModule.Child2.prototype.runVirtualFunc(c2); c2.virtualFunc2(); // extend a class from JS -var c3 = new Module.Child2JS; +var c3 = new TheModule.Child2JS; c3.virtualFunc = function() { - Module.print('*js virtualf replacement*'); + TheModule.print('*js virtualf replacement*'); }; c3.virtualFunc2 = function() { - Module.print('*js virtualf2 replacement*'); + TheModule.print('*js virtualf2 replacement*'); }; c3.virtualFunc3 = function(x) { - Module.print('*js virtualf3 replacement ' + x + '*'); + TheModule.print('*js virtualf3 replacement ' + x + '*'); }; c3.virtualFunc(); -Module.Child2.prototype.runVirtualFunc(c3); +TheModule.Child2.prototype.runVirtualFunc(c3); c3.virtualFunc2(); c3.virtualFunc3(123); // this one is not replaced! try { c3.virtualFunc4(123); } catch(e) { - Module.print('caught: ' + e); + TheModule.print('caught: ' + e); } // Test virtual method dispatch from c++ -Module.Child2.prototype.runVirtualFunc3(c3, 43); +TheModule.Child2.prototype.runVirtualFunc3(c3, 43); c2.virtualFunc(); // original should remain the same -Module.Child2.prototype.runVirtualFunc(c2); +TheModule.Child2.prototype.runVirtualFunc(c2); c2.virtualFunc2(); -Module.print('*ok*'); +TheModule.print('*ok*'); // Part 2 -var suser = new Module.StringUser("hello", 43); +var suser = new TheModule.StringUser("hello", 43); suser.Print(41, "world"); suser.PrintFloat(12.3456); -var bv = new Module.RefUser(10); -var bv2 = new Module.RefUser(11); -Module.print(bv2.getValue(bv)); +var bv = new TheModule.RefUser(10); +var bv2 = new TheModule.RefUser(11); +TheModule.print(bv2.getValue(bv)); -Module.print(typeof bv2.getMe()); -Module.print(bv2.getMe().getValue(bv)); -Module.print(bv2.getMe().getValue(bv2)); +TheModule.print(typeof bv2.getMe()); +TheModule.print(bv2.getMe().getValue(bv)); +TheModule.print(bv2.getMe().getValue(bv2)); -Module.print(typeof bv2.getCopy()); -Module.print(bv2.getCopy().getValue(bv)); -Module.print(bv2.getCopy().getValue(bv2)); +TheModule.print(typeof bv2.getCopy()); +TheModule.print(bv2.getCopy().getValue(bv)); +TheModule.print(bv2.getCopy().getValue(bv2)); bv2.getAnother().PrintFloat(21.12); -Module.print(new Module.Inner().get()); -new Module.Inner().mul(2); +TheModule.print(new TheModule.Inner().get()); +new TheModule.Inner().mul(2); -Module.print(Module.enum_value1); -Module.print(Module.enum_value2); +TheModule.print(TheModule.enum_value1); +TheModule.print(TheModule.enum_value2); // Enums from classes are accessed via the class. -enumClassInstance = new Module.EnumClass(); -Module.print([enumClassInstance.GetEnum(), Module.EnumClass.e_val].join(',')); +enumClassInstance = new TheModule.EnumClass(); +TheModule.print([enumClassInstance.GetEnum(), TheModule.EnumClass.e_val].join(',')); // Enums from namespaces are accessed via the top-level module, as with classes defined // in namespaces, see `Inner` above. -Module.print(Module.e_namespace_val); +TheModule.print(TheModule.e_namespace_val); -typeTester = new Module.TypeTestClass(); +typeTester = new TheModule.TypeTestClass(); -Module.print('return char ' + typeTester.ReturnCharMethod()); +TheModule.print('return char ' + typeTester.ReturnCharMethod()); typeTester.AcceptCharMethod((2<<6)-1); // Prints -1 because the c++ code accepts unsigned char. typeTester.AcceptCharMethod((2<<7)-1); // Prints -1 because all integers are signed in javascript. -Module.print('return unsigned char ' + typeTester.ReturnUnsignedCharMethod()); +TheModule.print('return unsigned char ' + typeTester.ReturnUnsignedCharMethod()); typeTester.AcceptUnsignedCharMethod((2<<7)-1); // Prints -1 because all integers are signed in javascript. -Module.print('return unsigned short ' + typeTester.ReturnUnsignedShortMethod()); +TheModule.print('return unsigned short ' + typeTester.ReturnUnsignedShortMethod()); typeTester.AcceptUnsignedShortMethod((2<<15)-1); // Prints -1 because all integers are signed in javascript. -Module.print('return unsigned long ' + typeTester.ReturnUnsignedLongMethod()); +TheModule.print('return unsigned long ' + typeTester.ReturnUnsignedLongMethod()); typeTester.AcceptUnsignedLongMethod((2<<31)-1); -var voidPointerUser = new Module.VoidPointerUser(); +var voidPointerUser = new TheModule.VoidPointerUser(); voidPointerUser.SetVoidPointer(3); -Module.print('void * ' + voidPointerUser.GetVoidPointer()); +TheModule.print('void * ' + voidPointerUser.GetVoidPointer()); // -Module.print('\ndone.') +TheModule.print('\ndone.') From 1dc3d1ee3855a7e8a99951ccada13b3f61dd1341 Mon Sep 17 00:00:00 2001 From: hamishwillee Date: Fri, 8 Aug 2014 10:04:41 +1000 Subject: [PATCH 04/91] Update emscripten.h, html5.h docs to match the source files --- .../docs/api_reference/emscripten.h.rst | 192 +++++++++++++++++- site/source/docs/api_reference/html5.h.rst | 144 ++++++++++++- site/source/docs/getting_started/Tutorial.rst | 2 +- site/source/docs/tools_reference/emcc.rst | 5 +- 4 files changed, 330 insertions(+), 13 deletions(-) diff --git a/site/source/docs/api_reference/emscripten.h.rst b/site/source/docs/api_reference/emscripten.h.rst index 0ad328672ef0a..18a7db5878968 100644 --- a/site/source/docs/api_reference/emscripten.h.rst +++ b/site/source/docs/api_reference/emscripten.h.rst @@ -175,7 +175,9 @@ Functions The JavaScript environment will call that function at a specified number of frames per second. Setting 0 or a negative value as the ``fps`` will instead use the browser’s ``requestAnimationFrame`` mechanism to call the main loop function. This is **HIGHLY** recommended if you are doing rendering, as the browser’s ``requestAnimationFrame`` will make sure you render at a proper smooth rate that lines up with the the browser and monitor in a proper way. (If you do not render at all in your application, then you should pick a specific frame rate that makes sense for your code.) - If ``simulate_infinite_loop`` is true, the function will throw an exception in order to stop execution of the caller. This will lead to the main loop being entered instead of code after the call to :c:func:`emscripten_set_main_loop` being run, which is the closest we can get to simulating an infinite loop (we do something similar in ``glutMainLoop`` in GLUT). If this parameter is false, then the behavior is the same as it was before this parameter was added to the API, which is that execution continues normally. Note that in both cases we do not run global destructors, ``atexit``, etc., since we know the main loop will still be running, but if we do not simulate an infinite loop then the stack will be unwound. That means that if ``simulate_infinite_loop`` is false, and you created an object on the stack, it will be cleaned up before the main loop is called for the first time. + If ``simulate_infinite_loop`` is true, the function will throw an exception in order to stop execution of the caller. This will lead to the main loop being entered instead of code after the call to :c:func:`emscripten_set_main_loop` being run, which is the closest we can get to simulating an infinite loop (we do something similar in ``glutMainLoop`` in GLUT). If this parameter is ``false``, then the behavior is the same as it was before this parameter was added to the API, which is that execution continues normally. Note that in both cases we do not run global destructors, ``atexit``, etc., since we know the main loop will still be running, but if we do not simulate an infinite loop then the stack will be unwound. That means that if ``simulate_infinite_loop`` is ``false``, and you created an object on the stack, it will be cleaned up before the main loop is called for the first time. + + .. tip:: There can be only *one* main loop function at a time. To change the main loop function, first :c:func:`cancel ` the current loop, and then call this function to set another. .. note:: See :c:func:`emscripten_set_main_loop_expected_blockers`, :c:func:`emscripten_pause_main_loop`, :c:func:`emscripten_resume_main_loop` and :c:func:`emscripten_cancel_main_loop` for information about blocking, pausing, and resuming the main loop. @@ -267,7 +269,16 @@ Functions .. c:function:: void emscripten_exit_with_live_runtime(void) - Exits the program immediately, but leaves the runtime alive so that you can continue to run code later (so global destructors etc., are not run). This is implicitly performed when you do an asynchronous operation like :c:func:`emscripten_async_call`. + Exits the program immediately, but leaves the runtime alive so that you can continue to run code later (so global destructors etc., are not run). Note that the runtime is kept alive automatically when you do an asynchronous operation like :c:func:`emscripten_async_call`, so you don't need to call this function for those cases. + + +.. c:function:: void emscripten_force_exit(int status) + + Shuts down the runtime and exits (terminates) the program, as if you called ``exit()``. + + The difference is that ``emscripten_force_exit`` will shut down the runtime even if you previously called :c:func:`emscripten_exit_with_live_runtime` or otherwise kept the runtime alive. In other words, this method gives you the option to completely shut down the runtime after it was kept alive beyond the completion of ``main()``. + + :param int status: The same as for the *libc* function `exit() `_. .. c:function::void emscripten_hide_mouse(void) @@ -389,12 +400,26 @@ Typedefs Functions --------- + +.. c:function:: void emscripten_wget(const char* url, const char* file) + + Load file from url in *synchronously*. For the asynchronous version, see the :c:func:`emscripten_async_wget`. + + In addition to fetching the URL from the network, the contents are prepared so that the data is usable in ``IMG_Load`` and so forth (we synchronously do the work to make the browser decode the image or audio etc.). + + This function is blocking; it won't return until all operations are finished. You can then open and read the file if it succeeded. + + To use this function, you will need to compile your application with the linker flag ``-s ASYNCIFY=1`` + + :param const char* url: The URL to load. + :param const char* file: The name of the file created and loaded from the URL. If the file already exists it will be overwritten. + .. c:function:: void emscripten_async_wget(const char* url, const char* file, em_str_callback_func onload, em_str_callback_func onerror) Loads a file from a URL asynchronously. - In addition to fetching the URL from the network, the contents are prepared so that the data is usable in ``IMG_Load`` and so forth (we asynchronously do the work to make the browser decode the image or audio and so forth). + In addition to fetching the URL from the network, the contents are prepared so that the data is usable in ``IMG_Load`` and so forth (we asynchronously do the work to make the browser decode the image or audio etc.). When file is ready the ``onload`` callback will be called. If any error occurs ``onerror`` will be called. The callbacks are called with the file as their argument. @@ -434,7 +459,7 @@ Functions - *(void*)* : A pointer to ``arg`` (user defined data). -.. c:function:: void emscripten_async_wget2(const char* url, const char* file, const char* requesttype, const char* param, void *arg, em_async_wget2_onload_func onload, em_async_wget2_onstatus_func onerror, em_async_wget2_onstatus_func onprogress) +.. c:function:: int emscripten_async_wget2(const char* url, const char* file, const char* requesttype, const char* param, void *arg, em_async_wget2_onload_func onload, em_async_wget2_onstatus_func onerror, em_async_wget2_onstatus_func onprogress) Loads a file from a URL asynchronously. @@ -468,8 +493,10 @@ Functions - *(void*)* : A pointer to ``arg`` (user defined data). - *(int)* : The progress (percentage completed). + :returns: A handle to request (``int``) that can be used to :c:func:`abort ` the request. -.. c:function:: void emscripten_async_wget2_data(const char* url, const char* requesttype, const char* param, void *arg, int free, em_async_wget2_data_onload_func onload, em_async_wget2_data_onerror_func onerror, em_async_wget2_data_onprogress_func onprogress) + +.. c:function:: int emscripten_async_wget2_data(const char* url, const char* requesttype, const char* param, void *arg, int free, em_async_wget2_data_onload_func onload, em_async_wget2_data_onerror_func onerror, em_async_wget2_data_onprogress_func onprogress) Loads a buffer from a URL asynchronously. @@ -507,7 +534,16 @@ Functions - *(void*)* : A pointer to ``arg`` (user defined data). - *(int)* : The number of bytes loaded. - *(int)* : The total size of the data in bytes, or zero if the size is unavailable. + + :returns: A handle to request (``int``) that can be used to :c:func:`abort ` the request. + + +.. c:function:: emscripten_async_wget2_abort(int handle) + + Abort an asynchronous request raised using :c:func:`emscripten_async_wget2` or :c:func:`emscripten_async_wget2_data`. + :param int handle: A handle to request to be aborted. + .. c:function:: int emscripten_async_prepare(const char* file, em_str_callback_func onload, em_str_callback_func onerror) @@ -786,8 +822,8 @@ Functions -Networking -========== +Networking backend +================== Defines ------- @@ -815,5 +851,147 @@ Functions :param int backend: The backend to use. One of :c:macro:`EMSCRIPTEN_NETWORK_WEBSOCKETS` and :c:macro:`EMSCRIPTEN_NETWORK_WEBRTC` + + +.. _emscripten-api-reference-sockets: + +Socket event registration +============================ + +The functions in this section register callback functions for receiving socket events. These events are analogous to `WebSocket `_ events but are emitted *after* the internal Emscripten socket processing has occurred. This means, for example, that the message callback will be triggered after the data has been added to the *recv_queue*, so that an application receiving this callback can simply read the data using the file descriptor passed as a parameter to the callback. All of the callbacks are passed a file descriptor (``fd``) representing the socket that the notified activity took place on. The error callback also takes an ``int`` representing the socket error number (``errno``) and a ``char*`` that represents the error message (``msg``). + +Only a single callback function may be registered to handle any given event, so calling a given registration function more than once will cause the first callback to be replaced. Similarly, passing a ``NULL`` callback function to any ``emscripten_set_socket_*_callback`` call will de-register the callback registered for that event. + +The ``userData`` pointer allows arbitrary data specified during event registration to be passed to the callback, this is particularly useful for passing ``this`` pointers around in Object Oriented code. + +In addition to being able to register network callbacks from C it is also possible for native JavaScript code to directly use the underlying mechanism used to implement the callback registration. For example, the following code shows simple logging callbacks that are registered by default when ``SOCKET_DEBUG`` is enabled: + +.. code-block:: javascript + + Module['websocket']['on']('error', function(error) {console.log('Socket error ' + error);}); + Module['websocket']['on']('open', function(fd) {console.log('Socket open fd = ' + fd);}); + Module['websocket']['on']('listen', function(fd) {console.log('Socket listen fd = ' + fd);}); + Module['websocket']['on']('connection', function(fd) {console.log('Socket connection fd = ' + fd);}); + Module['websocket']['on']('message', function(fd) {console.log('Socket message fd = ' + fd);}); + Module['websocket']['on']('close', function(fd) {console.log('Socket close fd = ' + fd);}); + +Most of the JavaScript callback functions above get passed the file descriptor of the socket that triggered the callback, the on error callback however gets passed an *array* that contains the file descriptor, the error code and an error message. + +.. note:: The underlying JavaScript implementation doesn't pass ``userData``. This is mostly of use to C/C++ code and the ``emscripten_set_socket_*_callback`` calls simply create a closure containing the ``userData`` and pass that as the callback to the underlying JavaScript event registration mechanism. + + +Callback functions +------------------ + +.. c:type:: em_socket_callback + + Function pointer for :c:func:`emscripten_set_socket_open_callback`, and the other socket functions (except :c:func:`emscripten_set_socket_error_callback`). This is defined as: + + .. code-block:: cpp + + typedef void (*em_socket_callback)(int fd, void *userData); + + :param int fd: The file descriptor of the socket that triggered the callback. + :param void* userData: The ``userData`` originally passed to the event registration function. + + +.. c:type:: em_socket_error_callback + + Function pointer for the :c:func:`emscripten_set_socket_error_callback`, defined as: + + .. code-block:: cpp + + typedef void (*em_socket_error_callback)(int fd, int err, const char* msg, void *userData); + :param int fd: The file descriptor of the socket that triggered the callback. + :param int err: The code for the error that occurred. + :param int msg: The message for the error that occurred. + :param void* userData: The ``userData`` originally passed to the event registration function. + + +Functions +--------- + +.. c:function:: void emscripten_set_socket_error_callback(void *userData, em_socket_error_callback *callback) + + Triggered by a ``WebSocket`` error. + + See :ref:`emscripten-api-reference-sockets` for more information. + + :param void* userData: Arbitrary user data to be passed to the callback. + :param em_socket_error_callback* callback: Pointer to a callback function. The callback returns a file descriptor, error code and message, and the arbitrary ``userData`` passed to this function. + + +.. c:function:: void emscripten_set_socket_open_callback(void *userData, em_socket_callback callback) + + Triggered when the ``WebSocket`` has opened. + + See :ref:`emscripten-api-reference-sockets` for more information. + + :param void* userData: Arbitrary user data to be passed to the callback. + :param em_socket_callback callback: Pointer to a callback function. The callback returns a file descriptor and the arbitrary ``userData`` passed to this function. + + +.. c:function:: void emscripten_set_socket_listen_callback(void *userData, em_socket_callback callback) + + Triggered when ``listen`` has been called (synthetic event). + + See :ref:`emscripten-api-reference-sockets` for more information. + + :param void* userData: Arbitrary user data to be passed to the callback. + :param em_socket_callback callback: Pointer to a callback function. The callback returns a file descriptor and the arbitrary ``userData`` passed to this function. + + +.. c:function:: void emscripten_set_socket_connection_callback(void *userData, em_socket_callback callback) + + Triggered when the connection has been established. + + See :ref:`emscripten-api-reference-sockets` for more information. + + :param void* userData: Arbitrary user data to be passed to the callback. + :param em_socket_callback callback: Pointer to a callback function. The callback returns a file descriptor and the arbitrary ``userData`` passed to this function. + + + +.. c:function:: void emscripten_set_socket_message_callback(void *userData, em_socket_callback callback) + + Triggered when data is available to be read from the socket. + + See :ref:`emscripten-api-reference-sockets` for more information. + + :param void* userData: Arbitrary user data to be passed to the callback. + :param em_socket_callback callback: Pointer to a callback function. The callback returns a file descriptor and the arbitrary ``userData`` passed to this function. + + + +.. c:function:: void emscripten_set_socket_close_callback(void *userData, em_socket_callback callback) + + Triggered when the ``WebSocket`` has closed. + + See :ref:`emscripten-api-reference-sockets` for more information. + + :param void* userData: Arbitrary user data to be passed to the callback. + :param em_socket_callback callback: Pointer to a callback function. The callback returns a file descriptor and the arbitrary ``userData`` passed to this function. + + +Unaligned types +=============== + +Typedefs +--------- + +.. c:type:: emscripten_align1_short + emscripten_align2_int + emscripten_align1_int + emscripten_align2_float + emscripten_align1_float + emscripten_align4_double + emscripten_align2_double + emscripten_align1_double + + Unaligned types. These may be used to force LLVM to emit unaligned loads/stores in places in your code where ``SAFE_HEAP`` found an unaligned operation. + + .. note:: It is better to avoid unaligned operations, but if you are reading from a packed stream of bytes or such, these types may be useful! + + diff --git a/site/source/docs/api_reference/html5.h.rst b/site/source/docs/api_reference/html5.h.rst index 6d4d37c26eb4b..e8aebd20ee7d4 100644 --- a/site/source/docs/api_reference/html5.h.rst +++ b/site/source/docs/api_reference/html5.h.rst @@ -1,6 +1,8 @@ -======= +.. _html5-h: + +======== html5.h -======= +======== The C++ APIs in `html5.h `_ define the Emscripten low-level glue bindings to interact with HTML5 events from native code. @@ -605,6 +607,11 @@ Functions EMSCRIPTEN_RESULT emscripten_set_scroll_callback(const char *target, void *userData, EM_BOOL useCapture, em_ui_callback_func callback) Registers a callback function for receiving DOM element `resize `_ and `scroll `_ events. + + .. note:: + + - For the ``resize`` callback, pass in target = 0 to get ``resize`` events from the ``Window`` object. + - The DOM3 Events specification only requires that the ``Window`` object sends resize events. It is valid to register a ``resize`` callback on other DOM elements, but the browser is not required to fire ``resize`` events for these. :param target: |target-parameter-doc| :type target: const char* @@ -1713,6 +1720,69 @@ Defines Emscripten `WebGL context `_ events. +.. c:type:: EMSCRIPTEN_WEBGL_CONTEXT_HANDLE + + Represents a handle to an Emscripten WebGL context object. The value 0 denotes an invalid/no context (this is a typedef to an ``int``). + + +Struct +------ + +.. c:type:: EmscriptenWebGLContextAttributes + + Specifies `WebGL context creation parameters `_. + + .. c:member:: EM_BOOL alpha + + If ``true``, request an alpha channel for the context. If you create an alpha channel, you can blend the canvas rendering with the underlying web page contents. Default value: ``true``. + + .. c:member:: EM_BOOL depth + + If ``true``, request a depth buffer of at least 16 bits. If ``false``, no depth buffer will be initialized. Default value: ``true``. + + .. c:member:: EM_BOOL stencil + + If ``true``, request a stencil buffer of at least 8 bits. If ``false``, no stencil buffer will be initialized. Default value: ``false``. + + .. c:member:: EM_BOOL antialias + + If ``true``, antialiasing will be initialized with a browser-specified algorithm and quality level. If ``false``, antialiasing is disabled. Default value: ``true``. + + + .. c:member:: EM_BOOL premultipliedAlpha + + If ``true``, the alpha channel of the rendering context will be treated as representing premultiplied alpha values. If ``false``, the alpha channel represents non-premultiplied alpha. Default value: ``true``. + + + .. c:member:: EM_BOOL preserveDrawingBuffer + + If ``true``, the contents of the drawing buffer are preserved between consecutive ``requestAnimationFrame()`` calls. If ``false``, color, depth and stencil are cleared at the beginning of each ``requestAnimationFrame()``. Generally setting this to ``false`` gives better performance. Default value: ``false``. + + + .. c:member:: EM_BOOL preferLowPowerToHighPerformance + + If ``true``, hints the browser to initialize a low-power GPU rendering context. If ``false``, prefers to initialize a high-performance rendering context. Default value: ``false``. + + .. c:member:: EM_BOOL failIfMajorPerformanceCaveat + + If ``true``, requests context creation to abort if the browser is only able to create a context that does not give good hardware-accelerated performance. Default value: ``false``. + + + .. c:member:: int majorVersion + int minorVersion + + Emscripten-specific extensions which specify the WebGL context version to initialize. + + For example, pass in ``majorVersion=1``, ``minorVersion=0`` to request a WebGL 1.0 context, and ``majorVersion=2``, ``minorVersion=0`` to request a WebGL 2.0 context. + + Default value: ``majorVersion=1``, ``minorVersion=0`` + + + .. c:member:: EM_BOOL enableExtensionsByDefault + + If ``true``, all GLES2-compatible non-performance-impacting WebGL extensions will automatically be enabled for you after the context has been created. If ``false``, no extensions are enabled by default, and you need to manually call :c:func:`emscripten_webgl_enable_extension` to enable each extension that you want to use. Default value: ``true``. + + Callback functions ------------------ @@ -1753,7 +1823,6 @@ Functions :rtype: |EMSCRIPTEN_RESULT| - .. c:function:: EM_BOOL emscripten_is_webgl_context_lost(const char *target) Queries the given canvas element for whether its WebGL context is in a lost state. @@ -1764,6 +1833,73 @@ Functions :rtype: |EM_BOOL| +.. c:function:: void emscripten_webgl_init_context_attributes(EmscriptenWebGLContextAttributes *attributes) + + Populates all fields of the given :c:type:`EmscriptenWebGLContextAttributes` structure to their default values for use with WebGL 1.0. + + Call this function as a forward-compatible way to ensure that if there are new fields added to the ``EmscriptenWebGLContextAttributes`` structure in the future, that they also will get default-initialized without having to change any code. + + :param attributes: The structure to be populated. + :type attributes: EmscriptenWebGLContextAttributes* + + + +.. c:function:: EMSCRIPTEN_WEBGL_CONTEXT_HANDLE emscripten_webgl_create_context(const char *target, const EmscriptenWebGLContextAttributes *attributes) + + Creates and returns a new `WebGL context `_. + + .. note:: + + - A successful call to this function will not immediately make that rendering context active. Call :c:func:`emscripten_webgl_make_context_current` after creating a context to activate it. + - This function will try to initialize the context version that was *exactly* requested. It will not e.g. initialize a newer backwards-compatible version or similar. + + :param target: The DOM canvas element in which to initialize the WebGL context. If 0 is passed, the element specified by ``Module.canvas`` will be used. + :type target: const char* + :param attributes: The attributes of the requested context version. + :type attributes: EmscriptenWebGLContextAttributes* + :returns: On success, a strictly positive value that represents a handle to the created context. On failure, a negative number that can be cast to an |EMSCRIPTEN_RESULT| field to get the reason why the context creation failed. + :rtype: |EMSCRIPTEN_WEBGL_CONTEXT_HANDLE| + + +.. c:function:: EMSCRIPTEN_RESULT emscripten_webgl_make_context_current(EMSCRIPTEN_WEBGL_CONTEXT_HANDLE context) + + Activates the given WebGL context for rendering. After calling this function, all OpenGL functions (``glBindBuffer()``, ``glDrawArrays()``, etc.) can be applied to the given GL context. + + :param EMSCRIPTEN_WEBGL_CONTEXT_HANDLE context: The WebGL context to activate. + :returns: :c:data:`EMSCRIPTEN_RESULT_SUCCESS`, or one of the other result values. + :rtype: |EMSCRIPTEN_RESULT| + + +.. c:function:: EMSCRIPTEN_WEBGL_CONTEXT_HANDLE emscripten_webgl_get_current_context() + + Returns the currently active WebGL rendering context, or 0 if no context is active. Calling any WebGL functions when there is no active rendering context is undefined and may throw a JavaScript exception. + + :returns: The currently active WebGL rendering context, or 0 if no context is active. + :rtype: |EMSCRIPTEN_WEBGL_CONTEXT_HANDLE| + + +.. c:function:: EMSCRIPTEN_RESULT emscripten_webgl_destroy_context(EMSCRIPTEN_WEBGL_CONTEXT_HANDLE context) + + Deletes the given WebGL context. If that context was active, then the no context is set to active. + + :param EMSCRIPTEN_WEBGL_CONTEXT_HANDLE context: The WebGL context to delete. + :returns: :c:data:`EMSCRIPTEN_RESULT_SUCCESS`, or one of the other result values. + :rtype: |EMSCRIPTEN_RESULT| + + +.. c:function:: EM_BOOL emscripten_webgl_enable_extension(EMSCRIPTEN_WEBGL_CONTEXT_HANDLE context, const char *extension) + + Enables the given extension on the given context. + + :param EMSCRIPTEN_WEBGL_CONTEXT_HANDLE context: The WebGL context on which the extension is to be enabled. + :param extension: A string identifyingthea `WebGL extension `_. For example "OES_texture_float". + :type extension: const char* + :returns: EM_TRUE if the given extension is supported by the context, and EM_FALSE if the extension was not available. + :rtype: |EM_BOOL| + + .. comment : **HamishW** Are EM_TRUE, EM_FALSE defined? + + .. COMMENT (not rendered): Section below is automated copy and replace text. @@ -1771,6 +1907,8 @@ Functions .. |EMSCRIPTEN_RESULT| replace:: :c:type:`EMSCRIPTEN_RESULT` .. |EM_BOOL| replace:: :c:type:`EM_BOOL` +.. |EMSCRIPTEN_WEBGL_CONTEXT_HANDLE| replace:: :c:type:`EMSCRIPTEN_WEBGL_CONTEXT_HANDLE` + .. COMMENT (not rendered): Following values are common to many functions, and currently only updated in one place (here). .. COMMENT (not rendered): These can be properly replaced if required either wholesale or on an individual basis. diff --git a/site/source/docs/getting_started/Tutorial.rst b/site/source/docs/getting_started/Tutorial.rst index 11a6e7384fd15..1677cdcaa658d 100644 --- a/site/source/docs/getting_started/Tutorial.rst +++ b/site/source/docs/getting_started/Tutorial.rst @@ -15,7 +15,7 @@ First things first Make sure you have :ref:`downloaded and installed ` Emscripten (the exact approach for doing this will depend your operating system: Windows, Mac or Linux). -Emscripten is accessed using the :ref:`emcc`. This script invokes all the other tools needed to build your code, and can act as a drop-in replacement for a standard compiler like *gcc*. It is called on the command line using ``emcc`` or ``em++`` +Emscripten is accessed using the :ref:`emcc `. This script invokes all the other tools needed to build your code, and can act as a drop-in replacement for a standard compiler like *gcc*. It is called on the command line using ``emcc`` or ``em++`` .. note:: On Mac OS X the tool is called using the slightly different syntax: ``./emcc`` or ``./em++`` (or even directly via Python: ``python emcc``). The remainder of this tutorial uses the Windows syntax (``emcc``). diff --git a/site/source/docs/tools_reference/emcc.rst b/site/source/docs/tools_reference/emcc.rst index 92233d9088383..a67de986592b7 100644 --- a/site/source/docs/tools_reference/emcc.rst +++ b/site/source/docs/tools_reference/emcc.rst @@ -1,8 +1,9 @@ + .. _emcc: -======================================================== +========================================================= Emscripten Compiler Frontend (emcc) (under-construction) -======================================================== +========================================================= **This document provides the command syntax for the Emscription Compiler Frontend.** From 9451eae87c2393d9a9bb9284950c47e7f84fcbeb Mon Sep 17 00:00:00 2001 From: hamishwillee Date: Fri, 8 Aug 2014 10:44:41 +1000 Subject: [PATCH 05/91] Remove comments from preamble.js. Add link to doc file and built version --- src/preamble.js | 68 ++++++++++++------------------------------------- 1 file changed, 16 insertions(+), 52 deletions(-) diff --git a/src/preamble.js b/src/preamble.js index 34ffd0c016433..76eca122d7925 100644 --- a/src/preamble.js +++ b/src/preamble.js @@ -1,5 +1,12 @@ // === Auto-generated preamble library stuff === +// Documentation for the public APIs defined in this file must be updated in: +// /emscripten/site/source/docs/api_reference/preamble.js.rst +// A prebuilt version of the documentation is available at: +// /emscripten/site/build/html/docs/api_reference/preamble.js.html +// +// The code can be used permissively under the MIT license. + //======================================== // Runtime code shared with compiler //======================================== @@ -358,30 +365,7 @@ var cwrap, ccall; // For fast lookup of conversion functions var toC = {'string' : JSfuncs['stringToC'], 'array' : JSfuncs['arrayToC']}; - // C calling interface. A convenient way to call C functions (in C files, or - // defined with extern "C"). - // - // Note: ccall/cwrap use the C stack for temporary values. If you pass a string - // then it is only alive until the call is complete. If the code being - // called saves the pointer to be used later, it may point to invalid - // data. If you need a string to live forever, you can create it (and - // must later delete it manually!) using malloc and writeStringToMemory, - // for example. - // - // Note: LLVM optimizations can inline and remove functions, after which you will not be - // able to call them. Closure can also do so. To avoid that, add your function to - // the exports using something like - // - // -s EXPORTED_FUNCTIONS='["_main", "_myfunc"]' - // - // @param ident The name of the C function (note that C++ functions will be name-mangled - use extern "C") - // @param returnType The return type of the function, one of the JS types 'number', 'string' or 'array' (use 'number' for any C pointer, and - // 'array' for JavaScript arrays and typed arrays; note that arrays are 8-bit). - // @param argTypes An array of the types of arguments for the function (if there are no arguments, this can be ommitted). Types are as in returnType, - // except that 'array' is not possible (there is no way for us to know the length of the array) - // @param args An array of the arguments to the function, as native JS values (as in returnType) - // Note that string arguments will be stored on the stack (the JS string will become a C string on the stack). - // @return The return value, as a native JS value (as in returnType) + // C calling interface. ccall = function ccallFunc(ident, returnType, argTypes, args) { var func = getCFunc(ident); var cArgs = []; @@ -419,13 +403,8 @@ var cwrap, ccall; JSsource[fun] = parseJSFunc(JSfuncs[fun]); } } - // Returns a native JS wrapper for a C function. This is similar to ccall, but - // returns a function you can call repeatedly in a normal way. For example: - // - // var my_function = cwrap('my_c_function', 'number', ['number', 'number']); - // alert(my_function(5, 22)); - // alert(my_function(99, 12)); - // + + cwrap = function cwrap(ident, returnType, argTypes) { argTypes = argTypes || []; var cfunc = getCFunc(ident); @@ -478,14 +457,7 @@ var cwrap, ccall; Module["cwrap"] = cwrap; Module["ccall"] = ccall; -// Sets a value in memory in a dynamic way at run-time. Uses the -// type data. This is the same as makeSetValue, except that -// makeSetValue is done at compile-time and generates the needed -// code then, whereas this function picks the right code at -// run-time. -// Note that setValue and getValue only do *aligned* writes and reads! -// Note that ccall uses JS types as for defining types, while setValue and -// getValue need LLVM types ('i8', 'i32') - this is a lower-level operation + function setValue(ptr, value, type, noSafe) { type = type || 'i8'; if (type.charAt(type.length-1) === '*') type = 'i32'; // pointers are 32-bit @@ -519,7 +491,7 @@ function setValue(ptr, value, type, noSafe) { } Module['setValue'] = setValue; -// Parallel to setValue. + function getValue(ptr, type, noSafe) { type = type || 'i8'; if (type.charAt(type.length-1) === '*') type = 'i32'; // pointers are 32-bit @@ -705,8 +677,6 @@ function Pointer_stringify(ptr, /* optional */ length) { } Module['Pointer_stringify'] = Pointer_stringify; -// Given a pointer 'ptr' to a null-terminated UTF16LE-encoded string in the emscripten HEAP, returns -// a copy of that string as a Javascript String object. function UTF16ToString(ptr) { var i = 0; @@ -722,8 +692,7 @@ function UTF16ToString(ptr) { } Module['UTF16ToString'] = UTF16ToString; -// Copies the given Javascript String object 'str' to the emscripten HEAP at address 'outPtr', -// null-terminated and encoded in UTF16LE form. The copy will require at most (str.length*2+1)*2 bytes of space in the HEAP. + function stringToUTF16(str, outPtr) { for(var i = 0; i < str.length; ++i) { // charCodeAt returns a UTF-16 encoded code unit, so it can be directly written to the HEAP. @@ -735,8 +704,7 @@ function stringToUTF16(str, outPtr) { } Module['stringToUTF16'] = stringToUTF16; -// Given a pointer 'ptr' to a null-terminated UTF32LE-encoded string in the emscripten HEAP, returns -// a copy of that string as a Javascript String object. + function UTF32ToString(ptr) { var i = 0; @@ -757,9 +725,7 @@ function UTF32ToString(ptr) { } Module['UTF32ToString'] = UTF32ToString; -// Copies the given Javascript String object 'str' to the emscripten HEAP at address 'outPtr', -// null-terminated and encoded in UTF32LE form. The copy will require at most (str.length+1)*4 bytes of space in the HEAP, -// but can use less, since str.length does not return the number of characters in the string, but the number of UTF-16 code units in the string. + function stringToUTF32(str, outPtr) { var iChar = 0; for(var iCodeUnit = 0; iCodeUnit < str.length; ++iCodeUnit) { @@ -1209,8 +1175,7 @@ Module['addOnPostRun'] = Module.addOnPostRun = addOnPostRun; // Tools -// This processes a JS string into a C-line array of numbers, 0-terminated. -// For LLVM-originating strings, see parser.js:parseLLVMString function + function intArrayFromString(stringy, dontAddNull, length /* optional */) { var ret = (new Runtime.UTF8Processor()).processJSString(stringy); if (length) { @@ -1239,7 +1204,6 @@ function intArrayToString(array) { } Module['intArrayToString'] = intArrayToString; -// Write a Javascript array to somewhere in the heap function writeStringToMemory(string, buffer, dontAddNull) { var array = intArrayFromString(string, dontAddNull); var i = 0; From 45eb0be55147fb577f331fed91387a627fc23f53 Mon Sep 17 00:00:00 2001 From: hamishwillee Date: Fri, 8 Aug 2014 10:45:07 +1000 Subject: [PATCH 06/91] Remove comments from emscripten.h. Add link to doc file and built version --- system/include/emscripten/emscripten.h | 553 +------------------------ 1 file changed, 12 insertions(+), 541 deletions(-) diff --git a/system/include/emscripten/emscripten.h b/system/include/emscripten/emscripten.h index 5d7157ec5d921..c62dbd7d1beaf 100644 --- a/system/include/emscripten/emscripten.h +++ b/system/include/emscripten/emscripten.h @@ -5,6 +5,11 @@ * This file contains a few useful things for compiling C/C++ code * with Emscripten, an LLVM-to-JavaScript compiler. * + * Documentation for the public APIs defined in this file must be updated in + * /emscripten/site/source/docs/api_reference/emscripten.h.rst + * A prebuilt version of the documentation is available at: + * /emscripten/site/build/html/docs/api_reference/emscripten.h.html + * * The code can be used permissively under the MIT license. * * http://emscripten.org @@ -23,14 +28,6 @@ extern "C" { /* Typedefs */ -/* - * Unaligned types, helpful to force LLVM to emit unaligned - * loads/stores in places in your code where SAFE_HEAP found - * an unaligned operation. (It's better to avoid unaligned - * operations, but if you are reading from a packed stream of - * bytes or such, these types may be useful.) - */ - typedef short __attribute__((aligned(1))) emscripten_align1_short; typedef int __attribute__((aligned(2))) emscripten_align2_int; @@ -43,57 +40,12 @@ typedef double __attribute__((aligned(4))) emscripten_align4_double; typedef double __attribute__((aligned(2))) emscripten_align2_double; typedef double __attribute__((aligned(1))) emscripten_align1_double; -/* - * Function pointer types - */ - typedef void (*em_callback_func)(void); typedef void (*em_arg_callback_func)(void*); typedef void (*em_str_callback_func)(const char *); -/* Functions */ -/* - * Convenient syntax for inline assembly/js. Allows stuff like - * - * EM_ASM(window.alert('hai')); - * - * This also works with asm.js, as it outlines the code (it - * does a function call to reach it). It supports newlines, - * - * EM_ASM( - * window.alert('hai'); - * window.alert('bai'); - * ) - * - * Notes: Double-quotes (") are not supported, but you can use - * single-quotes (') in js anyhow. - * - * You can't access C variables with EM_ASM, nor receive - * a value back. use EM_ASM_INT or EM_ASM_DOUBLE for that - */ #define EM_ASM(...) emscripten_asm_const(#__VA_ARGS__) - -/* - * Input-output versions of EM_ASM. - * - * EM_ASM_ (an extra _ is added) or EM_ASM_ARGS allow sending values - * (ints or doubles) into the code. If you also want a return value, - * EM_ASM_INT receives arguments (of int or double type) - * and returns an int; EM_ASM_DOUBLE does the same and returns - * a double. - * - * Arguments arrive as $0, $1 etc. The output value should be returned: - * - * int x = EM_ASM_INT({ - * console.log('I received: ' + [$0, $1]); - * return $0 + $1; - * }, calc(), otherCalc()); - * - * Note the { and }. If you just want to receive an output value - * (int or double) but *not* to pass any values, you can use - * EM_ASM_INT_V and EM_ASM_DOUBLE_V respectively. - */ #define EM_ASM_(code, ...) emscripten_asm_const_int(#code, __VA_ARGS__) #define EM_ASM_ARGS(code, ...) emscripten_asm_const_int(#code, __VA_ARGS__) #define EM_ASM_INT(code, ...) emscripten_asm_const_int(#code, __VA_ARGS__) @@ -101,82 +53,15 @@ typedef void (*em_str_callback_func)(const char *); #define EM_ASM_INT_V(code) emscripten_asm_const_int(#code) #define EM_ASM_DOUBLE_V(code) emscripten_asm_const_double(#code) -/* - * Forces LLVM to not dead-code-eliminate a function. This also - * exports the function, as if you added it to EXPORTED_FUNCTIONS. - */ + #define EMSCRIPTEN_KEEPALIVE __attribute__((used)) -/* - * Interface to the underlying JS engine. This function will - * eval() the given script. - */ extern void emscripten_run_script(const char *script); extern int emscripten_run_script_int(const char *script); -extern char *emscripten_run_script_string(const char *script); // uses a single buffer - shared between calls! - -/* - * Asynchronously run a script, after a specified amount of - * time. - */ +extern char *emscripten_run_script_string(const char *script); extern void emscripten_async_run_script(const char *script, int millis); - -/* - * Asynchronously loads a script from a URL. - * - * This integrates with the run dependencies system, so your - * script can call addRunDependency multiple times, prepare - * various asynchronous tasks, and call removeRunDependency - * on them; when all are complete (or there were no run - * dependencies to begin with), onload is called. An example use - * for this is to load an asset module, that is, the output of the - * file packager. - */ extern void emscripten_async_load_script(const char *script, em_callback_func onload, em_callback_func onerror); -/* - * Set a C function as the main event loop. The JS environment - * will call that function at a specified number of frames per - * second. Setting 0 or a negative value as the fps will use - * the browser's requestAnimationFrame mechanism. This is - * *HIGHLY* recommended if you are doing rendering, as - * the browser's requestAnimationFrame will make sure you - * render at a proper smooth rate that lines up with the - * the browser and monitor in a proper way. (If you do not - * render at all in your application, then you should pick a - * specific frame rate that makes sense for your code.) - * - * Pausing and resuming the main loop is useful if your app - * needs to perform some synchronous operation, for example - * to load a file from the network. It might be wrong to - * run the main loop before that finishes (the original - * code assumes that), so you can break the code up into - * asynchronous callbacks, but you must pause the main - * loop until they complete. - * - * If you want your main loop function to receive a void* - * argument, use emscripten_set_main_loop_arg. - * - * There can be only *one* main loop function at a time. You - * can cancel the current one and set another, if you want to - * change it. - * - * @simulate_infinite_loop If true, this function will throw an - * exception in order to stop execution of the caller. This - * will lead to the main loop being entered instead of code - * after the call to emscripten_set_main_loop being run, which - * is the closest we can get to simulating an infinite loop - * (we do something similar in glutMainLoop in GLUT). If this - * parameter is false, then the behavior is the same as it - * was before this parameter was added to the API, which is - * that execution continues normally. Note that in both cases - * we do not run global destructors, atexit, etc., since we - * know the main loop will still be running, but if we do - * not simulate an infinite loop then the stack will be unwound. - * That means that if simulate_infinite_loop is false, and - * you created an object on the stack, it will be cleaned up - * before the main loop will be called the first time. - */ #if __EMSCRIPTEN__ extern void emscripten_set_main_loop(em_callback_func func, int fps, int simulate_infinite_loop); extern void emscripten_set_main_loop_arg(em_arg_callback_func func, void *arg, int fps, int simulate_infinite_loop); @@ -189,81 +74,18 @@ extern void emscripten_cancel_main_loop(void); #define emscripten_cancel_main_loop() exit(1); #endif -/* - * Registers callback functions for receiving socket events. - * These events are analogous to WebSocket events but are emitted - * *after* the internal emscripten socket processing has occurred - * so, for example, the message callback will be triggered after - * the data has been added to the recv_queue. This means that an - * application receiving this callback can simply read/recv the data - * using the file descriptor passed as a parameter to the callback. - * All of the callbacks are passed a file descriptor representing - * the fd that the notified activity took place on. The error - * callback also takes an int representing errno and a char* that - * represents the error message. - * - * Only a single callback function may be registered to handle any - * given Event, so calling a given registration function more than - * once will cause the first callback to be replaced by the second. - * Similarly passing a NULL callback function to any - * emscripten_set_socket_*_callback call will deregister the callback - * registered for that Event. - * - * The userData pointer allows arbitrary data specified during Event - * registration to be passed to the callback, this is particularly - * useful for passing "this" pointers around in Object Oriented code. - * - * In addition to being able to register network callbacks from C - * it is also possible for native JavaScript code to directly use the - * underlying mechanism used to implement the callback registration. - * For example, the following are the simple logging callbacks that - * are registered by default when SOCKET_DEBUG is enabled - * Module['websocket']['on']('error', function(error) {console.log('Socket error ' + error);}); - * Module['websocket']['on']('open', function(fd) {console.log('Socket open fd = ' + fd);}); - * Module['websocket']['on']('listen', function(fd) {console.log('Socket listen fd = ' + fd);}); - * Module['websocket']['on']('connection', function(fd) {console.log('Socket connection fd = ' + fd);}); - * Module['websocket']['on']('message', function(fd) {console.log('Socket message fd = ' + fd);}); - * Module['websocket']['on']('close', function(fd) {console.log('Socket close fd = ' + fd);}); - * - * Most of the JavaScript callback functions above get passed the - * file descriptor of the socket that triggered the callback, the - * on error callback however gets passed an *array* that contains - * the file descriptor, the error code and an error message. - * - * Note that the underlying JavaScript implementation doesn't pass - * userData, this is actually mostly of use to C/C++ code and the - * emscripten_set_socket_*_callback calls actually create a closure - * containing the userData and pass that as the callback to the - * underlying JavaScript Event registration mechanism. - */ + typedef void (*em_socket_callback)(int fd, void *userData); typedef void (*em_socket_error_callback)(int fd, int err, const char* msg, void *userData); -// Triggered by a WebSocket error. + extern void emscripten_set_socket_error_callback(void *userData, em_socket_error_callback *callback); -// Triggered when the WebSocket has actually opened. extern void emscripten_set_socket_open_callback(void *userData, em_socket_callback callback); -// Triggered when listen has been called (synthetic event). extern void emscripten_set_socket_listen_callback(void *userData, em_socket_callback callback); -// Triggered when the connection has actually been established. extern void emscripten_set_socket_connection_callback(void *userData, em_socket_callback callback); -// Triggered when data is available to be read from the socket. extern void emscripten_set_socket_message_callback(void *userData, em_socket_callback callback); -// Triggered when the WebSocket has actually closed. extern void emscripten_set_socket_close_callback(void *userData, em_socket_callback callback); -/* - * Add a function to a queue of events that will execute - * before the main loop will continue. The event is pushed - * into the back of the queue. (Note that in the native version - * of this we simply execute the function, so to keep semantics - * identical be careful to not push while the queue is being - * used.) - * - * Main loop blockers block the main loop from running, and - * can be counted to show progress. In contrast, emscripten_async_calls - * are not counted, do not block the main loop, and can fire - * at specific time in the future. - */ + #if __EMSCRIPTEN__ extern void _emscripten_push_main_loop_blocker(em_arg_callback_func func, void *arg, const char *name); extern void _emscripten_push_uncounted_main_loop_blocker(em_arg_callback_func func, void *arg, const char *name); @@ -280,27 +102,13 @@ inline void _emscripten_push_uncounted_main_loop_blocker(em_arg_callback_func fu #define emscripten_push_uncounted_main_loop_blocker(func, arg) \ _emscripten_push_uncounted_main_loop_blocker(func, arg, #func) -/* - * Sets the number of blockers remaining until some user-relevant - * event. This affects how we show progress. So if you set this - * to 10, then push 10 blockers, as they complete the user will - * see x/10 and so forth. - */ #if __EMSCRIPTEN__ extern void emscripten_set_main_loop_expected_blockers(int num); #else inline void emscripten_set_main_loop_expected_blockers(int num) {} #endif -/* - * Call a C function asynchronously, that is, after returning - * control to the JS event loop. This is done by a setTimeout. - * When building natively this becomes a simple direct call, - * after SDL_Delay (you must include SDL.h for that). - * - * If millis is negative, the browser's requestAnimationFrame - * mechanism is used. - */ + #if __EMSCRIPTEN__ extern void emscripten_async_call(em_arg_callback_func func, void *arg, int millis); #else @@ -310,53 +118,14 @@ inline void emscripten_async_call(em_arg_callback_func func, void *arg, int mill } #endif -/* - * Exits the program immediately, but leaves the runtime alive - * so that you can continue to run code later (so global destructors - * etc. are not run). Note that the runtime is kept alive automatically - * when you do an asynchronous operation like emscripten_async_call, - * so you don't need to call this function in that case. - */ -extern void emscripten_exit_with_live_runtime(void); -/* - * Shuts down the runtime and exits (terminates) the program, as if - * you called exit(). The difference is that emscripten_force_exit - * will shut down the runtime even if you previously called - * emscripten_exit_with_live_runtime or otherwise kept the - * runtime alive. In other words, this method gives you the - * option to completely shut down the runtime after it was - * kept alive beyond the completion of main(). - */ +extern void emscripten_exit_with_live_runtime(void); extern void emscripten_force_exit(int status); -/* - * Hide the OS mouse cursor over the canvas. Note that SDL's - * SDL_ShowCursor command shows and hides the SDL cursor, not - * the OS one. This command is useful to hide the OS cursor - * if your app draws its own cursor. - */ void emscripten_hide_mouse(void); - -/* - * Resizes the pixel width and height of the element - * on the Emscripten web page. - */ void emscripten_set_canvas_size(int width, int height); - -/* - * Get the current pixel width and height of the element - * as well as whether the canvas is fullscreen or not. - */ void emscripten_get_canvas_size(int *width, int *height, int *isFullscreen); -/* - * Returns the highest-precision representation of the - * current time that the browser provides. This uses either - * Date.now or performance.now. The result is *not* an - * absolute time, and is only meaningful in comparison to - * other calls to this function. The unit is ms. - */ #if __EMSCRIPTEN__ double emscripten_get_now(void); #else @@ -366,366 +135,68 @@ static inline double emscripten_get_now(void) { } #endif -/* - * Simple random number generation in [0, 1), maps to Math.random(). - */ float emscripten_random(void); -/* - * This macro-looking function will cause Emscripten to - * generate a comment in the generated code. - * XXX This is deprecated for now, because it requires us to - * hold all global vars in memory. We need a better solution. - */ -//extern void EMSCRIPTEN_COMMENT(const char *text); -/* - * Emscripten file system api - */ -/* - * Load file from url in *synchronous* way, for the asynchronous - * version, see the emscripten_async_wget function below. - * - * In addition to fetching the URL from the network, - * the contents are prepared so that the data is usable - * in IMG_Load and * so forth. - * - * This function is blocking, it won't return until all - * operations are finished. You can then open and read - * the file if it succeeded. - * - * To use this function, you will need to compile your - * application with the linker flag `-s ASYNCIFY=1` - */ void emscripten_wget(const char* url, const char* file); - -/* - * Asynchronous version of emscripten_wget. - * When file is ready then 'onload' callback will called. - * If any error occurred 'onerror' will called. - * The callbacks are called with the file as their argument. - */ void emscripten_async_wget(const char* url, const char* file, em_str_callback_func onload, em_str_callback_func onerror); -/* - * Data version of emscripten_async_wget. Instead of writing - * to a file, it writes to a buffer directly in memory. - * This avoids the overhead of using the emulated - * filesystem, note however that since files are not used, - * It cannot do the 'prepare' stage to set things up for - * IMG_Load and so forth (IMG_Load etc. work on files). - * - * @param arg User-defined data that is passed to the callbacks, - * - * @param onload Callback on success, with the @arg that - * was provided to this function, a pointer - * to a buffer with the data, and the size - * of the buffer. As in the worker API, the - * data buffer only lives during the - * callback, so you should use it or copy - * it during that time and not later. - * - * @param onerror An optional callback on failure, with the - * @arg that was provided to this function. - * - */ typedef void (*em_async_wget_onload_func)(void*, void*, int); - void emscripten_async_wget_data(const char* url, void *arg, em_async_wget_onload_func onload, em_arg_callback_func onerror); -/* - * More feature-complete version of emscripten_async_wget. Note: - * this version is experimental. - * - * @param url Requested url - * @param file File to load - * @param requesttype 'GET' or 'POST' - * @param param If is post request, param is the post parameter - * like key=value&key2=value2. - * @param arg It is a pointer will be pass to the callback - * @param onload When file is ready then 'onload' callback will called. - * @param onprogress During the download 'onprogress' callback will called. - * @param onerror If any error occurred 'onerror' will called. - * - * The callbacks are called with a request handle, - * an object pointer give in parameter - * and file if is a success, the progress value during progress - * and http status code if is an error. - * - * @return Handle to request. It can be used to abort request - */ typedef void (*em_async_wget2_onload_func)(unsigned, void*, const char*); typedef void (*em_async_wget2_onstatus_func)(unsigned, void*, int); int emscripten_async_wget2(const char* url, const char* file, const char* requesttype, const char* param, void *arg, em_async_wget2_onload_func onload, em_async_wget2_onstatus_func onerror, em_async_wget2_onstatus_func onprogress); -/* - * More feature-complete version of emscripten_async_wget_data. Note: - * this version is experimental. - * - * @param url Requested url - * @param requesttype 'GET' or 'POST' - * @param param If is post request, param is the post parameter - * like key=value&key2=value2. - * @param arg It is a pointer will be pass to the callback - * @param free Tells the runtime whether to free the returned buffer - after onload is complete. If false freeing the buffer is the receiver's - responsibility. - * @param onload When data is ready then 'onload' callback will called. - * @param onprogress During the download 'onprogress' callback will called. - * @param onerror If any error occurred 'onerror' will called. - * - * The callbacks are called with a request handle and an object pointer give in parameter - * When data is ready then 'onload' callback will called with a pointer to - the buffer in memory and the size in bytes. - * During the download 'onprogress' callback will called. The first argument is - the number of bytes loaded. The second argument is the total size in bytes, - or zero if the size is unavailable. - * If any error occurred 'onerror' will called with the HTTP status code - and a string with the status description. - * - * @return Handle to request. It can be used to abort request - */ typedef void (*em_async_wget2_data_onload_func)(unsigned, void*, void*, unsigned); typedef void (*em_async_wget2_data_onerror_func)(unsigned, void*, int, const char*); typedef void (*em_async_wget2_data_onprogress_func)(unsigned, void*, int, int); int emscripten_async_wget2_data(const char* url, const char* requesttype, const char* param, void *arg, int free, em_async_wget2_data_onload_func onload, em_async_wget2_data_onerror_func onerror, em_async_wget2_data_onprogress_func onprogress); -/* - * Abort async request - * - * @param handle Request handle - */ void emscripten_async_wget2_abort(int handle); -/* - * Prepare a file in asynchronous way. This does just the - * preparation part of emscripten_async_wget, that is, it - * works on file data already present, and asynchronously - * prepares it for use in IMG_Load, Mix_LoadWAV, etc. - * When file is loaded then 'onload' callback will called. - * If any error occurred 'onerror' will called. - * The callbacks are called with the file as their argument. - * @return 0 if successful, -1 if the file does not exist - */ int emscripten_async_prepare(const char* file, em_str_callback_func onload, em_str_callback_func onerror); -/* - * Data version of emscripten_async_prepare, which receives - * raw data as input instead of a filename (this can prevent - * the need to write data to a file first). onload and - * onerror are called back with the given arg pointer as the - * first parameter. onload also receives a second - * parameter, which is a 'fake' filename which you can - * then pass into IMG_Load (it is not an actual file, - * but it identifies this image for IMG_Load to be able - * to process it). Note that the user of this API is - * responsible for free()ing the memory allocated for - * the fake filename. - * @suffix The file suffix, e.g. 'png' or 'jpg'. - */ typedef void (*em_async_prepare_data_onload_func)(void*, const char*); - void emscripten_async_prepare_data(char* data, int size, const char *suffix, void *arg, em_async_prepare_data_onload_func onload, em_arg_callback_func onerror); -/* - * Worker API. Basically a wrapper around web workers, lets - * you create workers and communicate with them. - - * Note that the current API is mainly focused on a main thread that - * sends jobs to workers and waits for responses, i.e., in an - * asymmetrical manner, there is no current API to send a message - * without being asked for it from a worker to the main thread. - * - */ - typedef int worker_handle; -/* - * Create and destroy workers. A worker must be compiled separately - * from the main program, and with the BUILD_AS_WORKER flag set to 1. - */ worker_handle emscripten_create_worker(const char *url); void emscripten_destroy_worker(worker_handle worker); -/* - * Asynchronously call a worker. - * - * The worker function will be called with two parameters: a - * data pointer, and a size. The data block defined by the - * pointer and size exists only during the callback and - * _cannot_ be relied upon afterwards - if you need to keep some - * of that information around, you need to copy it to a safe - * location. - * - * The called worker function can return data, by calling - * emscripten_worker_respond(). If called, and if a callback was - * given, then the callback will be called with three arguments: - * a data pointer, a size, and * an argument that was provided - * when calling emscripten_call_worker (to more easily associate - * callbacks to calls). The data block defined by the data pointer - * and size behave like the data block in the worker function - - * it exists only during the callback. - * - * @funcname the name of the function in the worker. The function - * must be a C function (so no C++ name mangling), and - * must be exported (EXPORTED_FUNCTIONS). - * @data the address of a block of memory to copy over - * @size the size of the block of memory - * @callback the callback with the response (can be null) - * @arg an argument to be passed to the callback - */ typedef void (*em_worker_callback_func)(char*, int, void*); - void emscripten_call_worker(worker_handle worker, const char *funcname, char *data, int size, em_worker_callback_func callback, void *arg); - -/* - * Sends a response when in a worker call. Both functions post a message - * back to the thread which called the worker. The _respond_provisionally - * variant can be invoked multiple times, which will queue up messages to - * be posted to the worker's creator. Eventually, the _respond variant must - * be invoked, which will disallow further messages and free framework - * resources previously allocated for this worker call. (Calling the - * provisional version is optional, but you must call the non-provisional - * one to avoid leaks.) - */ void emscripten_worker_respond(char *data, int size); void emscripten_worker_respond_provisionally(char *data, int size); -/* - * Checks how many responses are being waited for from a worker. This - * only counts calls to emscripten_call_worker that had a non-null - * callback (if it's null, we do not have any tracking of a response), - * and that the response was not yet received. It is a simple way to - * check on the status of the worker to see how busy it is, and do - * basic decisions about throttling. - */ int emscripten_get_worker_queue_size(worker_handle worker); -/* - * Select the networking backend to use. By default emscripten's - * socket/networking implementation will use websockets, with this - * function you can change that to WebRTC. - * This function must be called before any network functions are - * called. - */ #define EMSCRIPTEN_NETWORK_WEBSOCKETS 0 #define EMSCRIPTEN_NETWORK_WEBRTC 1 void emscripten_set_network_backend(int backend); -/* - * Returns the value of a compiler setting. For example - * - * emscripten_get_compiler_setting("PRECISE_F32") - * - * will return an integer representing the value of - * PRECISE_F32 during compilation. For values containing - * anything other than an integer, a string is returned - * (you will need to cast the int return value to a char*). - * - * Some useful things this can do is provide the - * version of emscripten ("EMSCRIPTEN_VERSION"), the optimization - * level ("OPT_LEVEL"), debug level ("DEBUG_LEVEL"), etc. - * - * For this command to work, you must build with - * -s RETAIN_COMPILER_SETTINGS=1 - * as otherwise we do not want to increase the build size - * with this metadata. - */ int emscripten_get_compiler_setting(const char *name); -/* - * Emits - * debugger; - * inline in the code, which tells the JS engine to invoke - * the debugger if it gets there. - */ void emscripten_debugger(); -/* - * Get preloaded image data and the size of the image. - * - * Returns pointer to loaded image or NULL. - * width/height of image are written to w/h if data is valid. - * Pointer should be free()'d - */ char *emscripten_get_preloaded_image_data(const char *path, int *w, int *h); - -/* - * Get preloaded image data from a c FILE *. - * - * Returns pointer to loaded image or NULL. - * width/height of image are written to w/h if data is valid. - * Pointer should be free()'d - */ char *emscripten_get_preloaded_image_data_from_FILE(FILE *file, int *w, int *h); -/* Logging utilities */ - -/* If specified, logs directly to the browser console/inspector - * window. If not specified, logs via the application Module. */ #define EM_LOG_CONSOLE 1 -/* If specified, prints a warning message. */ #define EM_LOG_WARN 2 -/* If specified, prints an error message. If neither EM_LOG_WARN - * or EM_LOG_ERROR is specified, an info message is printed. - * EM_LOG_WARN and EM_LOG_ERROR are mutually exclusive. */ #define EM_LOG_ERROR 4 -/* If specified, prints a callstack that contains filenames referring - * to original C sources using source map information. */ #define EM_LOG_C_STACK 8 -/* If specified, prints a callstack that contains filenames referring - * to lines to the built .js/.html file along with the message. The - * flags EM_LOG_C_STACK and EM_LOG_JS_STACK can be combined to output - * both untranslated and translated file+line information. */ #define EM_LOG_JS_STACK 16 -/* If specified, C/C++ function names are demangled before printing. - * Otherwise, the mangled post-compilation JS function names are - * displayed. */ #define EM_LOG_DEMANGLE 32 -/* If specified, the pathnames of the file information in the call - * stack will be omitted. */ #define EM_LOG_NO_PATHS 64 -/* If specified, prints out the actual values of the parameters the - * functions were invoked with. */ #define EM_LOG_FUNC_PARAMS 128 -/* - * Prints out a message to the console, optionally with the - * callstack information. - * @param flags A binary OR of items from the list of EM_LOG_xxx - * flags that specify printing options. - * @param '...' A printf-style "format, ..." parameter list that - * is parsed according to the printf formatting rules. - */ void emscripten_log(int flags, ...); -/* - * Programmatically obtains the current callstack. - * @param flags A binary OR of items from the list of EM_LOG_xxx - * flags that specify printing options. The - * items EM_LOG_CONSOLE, EM_LOG_WARN and - * EM_LOG_ERROR do not apply in this function and - * are ignored. - * @param out A pointer to a memory region where the callstack - * string will be written to. The string outputted - * by this function will always be null-terminated. - * @param maxbytes The maximum number of bytes that this function can - * write to the memory pointed to by 'out'. If - * there is no enough space, the output will be - * truncated (but always null-terminated). - * @return Returns the number of bytes written. (not number of - * characters, so this will also include the terminating zero) - - * To query the amount of bytes needed for a callstack without writing - * it, pass 0 to 'out' and 'maxbytes', in which case the function will - * return the number of bytes (including the terminating zero) that - * will be needed to hold the full callstack. Note that this might be - * fully accurate since subsequent calls will carry different line - * numbers, so it is best to allocate a few bytes extra to be safe. - */ int emscripten_get_callstack(int flags, char *out, int maxbytes); From fbd59d6ccb42e7c2539e2ee6560a991c5c8c17d8 Mon Sep 17 00:00:00 2001 From: hamishwillee Date: Fri, 8 Aug 2014 10:45:41 +1000 Subject: [PATCH 07/91] Remove comments from html5.h. Add link to doc file and built version --- system/include/emscripten/html5.h | 439 +++--------------------------- 1 file changed, 35 insertions(+), 404 deletions(-) diff --git a/system/include/emscripten/html5.h b/system/include/emscripten/html5.h index 98192e289e543..bd72f21f177d0 100644 --- a/system/include/emscripten/html5.h +++ b/system/include/emscripten/html5.h @@ -5,48 +5,15 @@ extern "C" { #endif -/* This file defines Emscripten low-level glue bindings for interfacing with the following HTML5 APIs: - * - DOM Level 3 Events: Keyboard, Mouse, Mouse Wheel, Resize, Scroll, Focus. See https://dvcs.w3.org/hg/dom3events/raw-file/tip/html/DOM3-Events.html - * - DeviceOrientation Events for gyro and accelerometer. See http://www.w3.org/TR/orientation-event/ - * - Screen Orientation Events for portrait/landscape handling. See https://dvcs.w3.org/hg/screen-orientation/raw-file/tip/Overview.html - * - Fullscreen Events for browser canvas fullscreen modes transitioning. See https://dvcs.w3.org/hg/fullscreen/raw-file/tip/Overview.html - * - Pointer Lock Events for relative-mode mouse motion control. See http://www.w3.org/TR/pointerlock/ - * - Vibration API for mobile device haptic vibration feedback control. See http://dev.w3.org/2009/dap/vibration/ - * - Page Visibility Events for power management control. See http://www.w3.org/TR/page-visibility/ - * - Touch Events. See http://www.w3.org/TR/touch-events/ - * - Gamepad API. See http://www.w3.org/TR/gamepad/ - * - Beforeunload event. See http://www.whatwg.org/specs/web-apps/current-work/multipage/history.html#beforeunloadevent - * - WebGL context events. See http://www.khronos.org/registry/webgl/specs/latest/1.0/#5.15.2 +/* This file defines Emscripten low-level glue bindings for interfacing with HTML5 APIs + * + * Documentation for the public APIs defined in this file must be updated in: + * /emscripten/site/source/docs/api_reference/html5.h.rst + * A prebuilt version of the documentation is available at: + * /emscripten/site/build/html/docs/api_reference/html5.h.html + * + * The code can be used permissively under the MIT license. * - * Most web APIs are event-based, which means that the functionality is accessed by registering a callback function to be called when the event occurs. The - * Gamepad API is currently an exception, for which only a polling API is available. For some APIs, both an event-based and a polling-based API is exposed. - * - * Calling a callback registration function with a null pointer function causes an unregistration of that callback from the given target element. All event - * handlers are also automatically unregistered when the C exit() function is invoked during the atexit handler pass. Use either the function - * emscripten_set_main_loop() or set Module.noExitRuntime = true; to make sure that leaving main() will not immediately cause an exit() and clean up the - * event handlers. - * - * Throughout this file, the function signatures have a 'target' parameter. This parameter allows specifying the HTML Element ID to which the callback - * registration is to be applied to. This field has the following special meanings: - * - 0 or NULL: A default element is chosen automatically based on the event type, which should be reasonable most of the time. - * - "#window": The event listener is applied to the JS 'window' object. - * - "#document": The event listener is applied to the JS 'document' object. - * - "#screen": The event listener is applied to the JS 'window.screen' object. - * - "#canvas": The event listener is applied to the Emscripten default WebGL canvas element. - * - Any other string without a leading hash "#" sign: The event listener is applied to the element by the given ID on the page. - * - * The callback hook functions also take in a 'userData' parameter. This is a custom user-defineable value that will be carried through unchanged to all - * invocations of the registered event callback. Use this e.g. to pass a pointer to a C++ class or similar to enclose the C API in a clean object-oriented manner. - * - * Callback handlers that return an EM_BOOL may return nonzero to signal that the default action for that event is to be suppressed. This will call - * the .preventDefault(); member on the event. Returning zero will cause the default browser event action to be carried out. - * - * Most functions return the result using the type EMSCRIPTEN_RESULT. Nonzero and positive values denote success. Negative values - * signal failure. None of the functions fail or abort by throwing a JS or C++ exception. If a particular browser does not support the given feature, - * the value EMSCRIPTEN_RESULT_NOT_SUPPORTED will be returned at the time the callback is registered. - * - * Due to web security purposes, the pointer lock and fullscreen requests can only be invoked from inside an user-originated event handler. Such requests - * are automatically deferred until the user presses a keyboard or mouse button the next time. */ #define EMSCRIPTEN_EVENT_KEYPRESS 1 @@ -84,31 +51,15 @@ extern "C" { #define EMSCRIPTEN_RESULT int -// The operation succeeded -#define EMSCRIPTEN_RESULT_SUCCESS 0 -// For web security reasons, the requested operation cannot be completed now, but was deferred for completion in the next event handler. +#define EMSCRIPTEN_RESULT_SUCCESS 0 #define EMSCRIPTEN_RESULT_DEFERRED 1 - -// The given operation is not supported by this browser or the target element. #define EMSCRIPTEN_RESULT_NOT_SUPPORTED -1 - -// For web security reasons, the requested operation could not be completed now, and it failed since the user requested the operation to not be deferred. #define EMSCRIPTEN_RESULT_FAILED_NOT_DEFERRED -2 - -// The given target element for the operation is invalid. #define EMSCRIPTEN_RESULT_INVALID_TARGET -3 - -// The given target element for the operation was not found. #define EMSCRIPTEN_RESULT_UNKNOWN_TARGET -4 - -// An invalid parameter was passed to the function. #define EMSCRIPTEN_RESULT_INVALID_PARAM -5 - -// The operation failed due to some generic reason. #define EMSCRIPTEN_RESULT_FAILED -6 - -// Operation failed since no data is currently available. #define EMSCRIPTEN_RESULT_NO_DATA -7 #define EM_BOOL int @@ -120,245 +71,133 @@ extern "C" { #define DOM_KEY_LOCATION_RIGHT 0x02 #define DOM_KEY_LOCATION_NUMPAD 0x03 -/* - * The event structure passed in keyboard events keypress, keydown and keyup. - * https://dvcs.w3.org/hg/dom3events/raw-file/tip/html/DOM3-Events.html#keys - * - * Note that since the DOM Level 3 Events spec is very recent at the time of writing (2014-03), uniform - * support for the different fields in the spec is still in flux. Be sure to check the results in multiple - * browsers. See the unmerged pull request #2222 for an example way on how to interpret the legacy key events. - */ + typedef struct EmscriptenKeyboardEvent { - // The printed representation of the pressed key. EM_UTF8 key[32]; - // A string that identifies the physical key being pressed. The value is not affected by the current keyboard - // layout or modifier state, so a particular key will always return the same value. EM_UTF8 code[32]; - // Indicates the location of the key on the keyboard. One of the DOM_KEY_LOCATION_ values. unsigned long location; - // Specifies which modifiers were active during the key event. EM_BOOL ctrlKey; EM_BOOL shiftKey; EM_BOOL altKey; EM_BOOL metaKey; - // Specifies if this keyboard event represents a repeated press. EM_BOOL repeat; - // A locale string indicating the locale the keyboard is configured for. This may be the empty string if the - // browser or device doesn't know the keyboard's locale. EM_UTF8 locale[32]; - // The following fields are values from previous versions of the DOM key events specifications. - // See https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent?redirectlocale=en-US&redirectslug=DOM%2FKeyboardEvent - // The character representation of the key. This is the field 'char' from the docs, but renamed to charValue to avoid a C reserved word. - // Warning: This attribute has been dropped from DOM Level 3 events. EM_UTF8 charValue[32]; - // The Unicode reference number of the key; this attribute is used only by the keypress event. For keys whose char attribute - // contains multiple characters, this is the Unicode value of the first character in that attribute. - // Warning: This attribute is deprecated, you should use the field 'key' instead, if available. unsigned long charCode; - // A system and implementation dependent numerical code identifying the unmodified value of the pressed key. - // Warning: This attribute is deprecated, you should use the field 'key' instead, if available. unsigned long keyCode; - // A system and implementation dependent numeric code identifying the unmodified value of the pressed key; this is usually the same as keyCode. - // Warning: This attribute is deprecated, you should use the field 'key' instead, if available. unsigned long which; } EmscriptenKeyboardEvent; -/* - * Registers a callback function for receiving browser-generated keyboard input events. - * See https://developer.mozilla.org/en/DOM/Event/UIEvent/KeyEvent - * and http://www.javascriptkit.com/jsref/eventkeyboardmouse.shtml - */ + typedef EM_BOOL (*em_key_callback_func)(int eventType, const EmscriptenKeyboardEvent *keyEvent, void *userData); extern EMSCRIPTEN_RESULT emscripten_set_keypress_callback(const char *target, void *userData, EM_BOOL useCapture, em_key_callback_func callback); extern EMSCRIPTEN_RESULT emscripten_set_keydown_callback(const char *target, void *userData, EM_BOOL useCapture, em_key_callback_func callback); extern EMSCRIPTEN_RESULT emscripten_set_keyup_callback(const char *target, void *userData, EM_BOOL useCapture, em_key_callback_func callback); -/* - * The event structure passed in mouse events click, mousedown, mouseup, dblclick and mousemove. - * https://dvcs.w3.org/hg/dom3events/raw-file/tip/html/DOM3-Events.html#interface-MouseEvent - */ + typedef struct EmscriptenMouseEvent { - // A timestamp of when this data was generated by the browser. This is an absolute wallclock time in milliseconds. double timestamp; - // The coordinate relative to the browser screen coordinate system. long screenX; long screenY; - // The coordinate relative to the viewport associate with the event. long clientX; long clientY; - // Specifies which modifiers were active during the mouse event. EM_BOOL ctrlKey; EM_BOOL shiftKey; EM_BOOL altKey; EM_BOOL metaKey; - // Which pointer device button changed state. unsigned short button; - // A bitmask that indicates which combinations of mouse buttons were being held down at the time of the event. unsigned short buttons; - // If pointer lock is active, these two extra fields give relative mouse movement since the last event. long movementX; long movementY; - // Emscripten-specific extension: These fields give the mouse coordinates mapped to the Emscripten canvas client area. - // If the Emscripten canvas does not exist (Module.canvas element is null), then these fields will contain a value (0, 0). long canvasX; long canvasY; - // Pad this struct to multiple of 8 bytes to make WheelEvent unambiguously align to 8 bytes. long padding; } EmscriptenMouseEvent; -/* - * Registers a callback function for receiving browser-generated mouse input events. - * See https://developer.mozilla.org/en/DOM/MouseEvent - */ + typedef EM_BOOL (*em_mouse_callback_func)(int eventType, const EmscriptenMouseEvent *keyEvent, void *userData); extern EMSCRIPTEN_RESULT emscripten_set_click_callback(const char *target, void *userData, EM_BOOL useCapture, em_mouse_callback_func callback); extern EMSCRIPTEN_RESULT emscripten_set_mousedown_callback(const char *target, void *userData, EM_BOOL useCapture, em_mouse_callback_func callback); extern EMSCRIPTEN_RESULT emscripten_set_mouseup_callback(const char *target, void *userData, EM_BOOL useCapture, em_mouse_callback_func callback); extern EMSCRIPTEN_RESULT emscripten_set_dblclick_callback(const char *target, void *userData, EM_BOOL useCapture, em_mouse_callback_func callback); extern EMSCRIPTEN_RESULT emscripten_set_mousemove_callback(const char *target, void *userData, EM_BOOL useCapture, em_mouse_callback_func callback); -/* - * Returns the most recently received mouse event state. Note that for this function call to succeed, emscripten_set_xx_callback must have first - * been called with one of the mouse event types and a non-zero callback function pointer to enable the Mouse state capture. - */ + extern EMSCRIPTEN_RESULT emscripten_get_mouse_status(EmscriptenMouseEvent *mouseState); #define DOM_DELTA_PIXEL 0x00 #define DOM_DELTA_LINE 0x01 #define DOM_DELTA_PAGE 0x02 -/* - * The event structure passed in mouse wheelevent. - * https://dvcs.w3.org/hg/dom3events/raw-file/tip/html/DOM3-Events.html#interface-WheelEvent - */ typedef struct EmscriptenWheelEvent { - // Specifies general mouse information related to this event. EmscriptenMouseEvent mouse; - // Measures along different axes the movement of the wheel. double deltaX; double deltaY; double deltaZ; - // One of the DOM_DELTA_ values that indicates the units of measurement for the delta values. unsigned long deltaMode; } EmscriptenWheelEvent; -/* - * Registers a callback function for receiving browser-generated mouse wheel events. - * See http://www.w3.org/TR/DOM-Level-3-Events/#event-type-wheel - */ + typedef EM_BOOL (*em_wheel_callback_func)(int eventType, const EmscriptenWheelEvent *keyEvent, void *userData); extern EMSCRIPTEN_RESULT emscripten_set_wheel_callback(const char *target, void *userData, EM_BOOL useCapture, em_wheel_callback_func callback); -/* - * The event structure passed in DOM element resize and scroll events. - * https://dvcs.w3.org/hg/dom3events/raw-file/tip/html/DOM3-Events.html#interface-UIEvent - */ typedef struct EmscriptenUiEvent { - // Specifies detail information about this event. long detail; - // The clientWidth/clientHeight of the document.body element. int documentBodyClientWidth; int documentBodyClientHeight; - // The innerWidth/innerHeight of the window element. int windowInnerWidth; int windowInnerHeight; - // The outerWidth/outerHeight of the window element. int windowOuterWidth; int windowOuterHeight; - // The page scroll position. int scrollTop; int scrollLeft; } EmscriptenUiEvent; -/* - * Registers a callback function for receiving DOM element resize and scroll events. - * See https://dvcs.w3.org/hg/dom3events/raw-file/tip/html/DOM3-Events.html#event-type-resize - * Note: For the resize callback, pass in target = 0 to get resize events from the Window object. The DOM3 Events spec only - * requires that the Window object sends resize events. It is valid to register a resize callback to other DOM elements, - * but the browser is not required to fire resize events on them. - */ + typedef EM_BOOL (*em_ui_callback_func)(int eventType, const EmscriptenUiEvent *keyEvent, void *userData); extern EMSCRIPTEN_RESULT emscripten_set_resize_callback(const char *target, void *userData, EM_BOOL useCapture, em_ui_callback_func callback); extern EMSCRIPTEN_RESULT emscripten_set_scroll_callback(const char *target, void *userData, EM_BOOL useCapture, em_ui_callback_func callback); -/* - * The event structure passed in DOM element blur, focus, focusin and focusout events. - * https://dvcs.w3.org/hg/dom3events/raw-file/tip/html/DOM3-Events.html#interface-FocusEvent - */ typedef struct EmscriptenFocusEvent { - // The nodeName of the target HTML Element. See https://developer.mozilla.org/en-US/docs/Web/API/Node.nodeName EM_UTF8 nodeName[128]; - // The HTML Element ID of the target element. EM_UTF8 id[128]; } EmscriptenFocusEvent; -/* - * Registers a callback function for receiving DOM element blur, focus, focusin and focusout events. - * See https://dvcs.w3.org/hg/dom3events/raw-file/tip/html/DOM3-Events.html#event-type-blur - */ typedef EM_BOOL (*em_focus_callback_func)(int eventType, const EmscriptenFocusEvent *keyEvent, void *userData); extern EMSCRIPTEN_RESULT emscripten_set_blur_callback(const char *target, void *userData, EM_BOOL useCapture, em_focus_callback_func callback); extern EMSCRIPTEN_RESULT emscripten_set_focus_callback(const char *target, void *userData, EM_BOOL useCapture, em_focus_callback_func callback); extern EMSCRIPTEN_RESULT emscripten_set_focusin_callback(const char *target, void *userData, EM_BOOL useCapture, em_focus_callback_func callback); extern EMSCRIPTEN_RESULT emscripten_set_focusout_callback(const char *target, void *userData, EM_BOOL useCapture, em_focus_callback_func callback); -/* - * The event structure passed in the deviceorientation event. - * http://dev.w3.org/geo/api/spec-source-orientation.html#deviceorientation - */ typedef struct EmscriptenDeviceOrientationEvent { - // Absolute wallclock time in msec units of when the event occurred. double timestamp; - // The orientation of the device in terms of the transformation from a coordinate frame fixed on the Earth to a coordinate frame fixed in the device. double alpha; double beta; double gamma; - // If false, the orientation is only relative to some other bas orinetation, not to the fixed coordinate frame. EM_BOOL absolute; } EmscriptenDeviceOrientationEvent; -/* - * Registers a callback function for receiving the deviceorientation event. - * See http://dev.w3.org/geo/api/spec-source-orientation.html - */ + typedef EM_BOOL (*em_deviceorientation_callback_func)(int eventType, const EmscriptenDeviceOrientationEvent *keyEvent, void *userData); extern EMSCRIPTEN_RESULT emscripten_set_deviceorientation_callback(void *userData, EM_BOOL useCapture, em_deviceorientation_callback_func callback); -/* - * Returns the most recently received deviceorientation event state. Note that for this function call to succeed, emscripten_set_deviceorientation_callback - * must have first been called with one of the mouse event types and a non-zero callback function pointer to enable the Device Orientation state capture. - */ extern EMSCRIPTEN_RESULT emscripten_get_deviceorientation_status(EmscriptenDeviceOrientationEvent *orientationState); -/* - * The event structure passed in the devicemotion event. - * http://dev.w3.org/geo/api/spec-source-orientation.html#devicemotion - */ + typedef struct EmscriptenDeviceMotionEvent { - // Absolute wallclock time in msec units of when the event occurred. double timestamp; - // Acceleration of the device excluding gravity. double accelerationX; double accelerationY; double accelerationZ; - // Acceleration of the device including gravity. double accelerationIncludingGravityX; double accelerationIncludingGravityY; double accelerationIncludingGravityZ; - // The rotational delta of the device. double rotationRateAlpha; double rotationRateBeta; double rotationRateGamma; } EmscriptenDeviceMotionEvent; -/* - * Registers a callback function for receiving the devicemotion event. - * See http://dev.w3.org/geo/api/spec-source-orientation.html - */ + typedef EM_BOOL (*em_devicemotion_callback_func)(int eventType, const EmscriptenDeviceMotionEvent *keyEvent, void *userData); extern EMSCRIPTEN_RESULT emscripten_set_devicemotion_callback(void *userData, EM_BOOL useCapture, em_devicemotion_callback_func callback); -/* - * Returns the most recently received deviceomotion event state. Note that for this function call to succeed, emscripten_set_devicemotion_callback - * must have first been called with one of the mouse event types and a non-zero callback function pointer to enable the Device Motion state capture. - */ extern EMSCRIPTEN_RESULT emscripten_get_devicemotion_status(EmscriptenDeviceMotionEvent *motionState); #define EMSCRIPTEN_ORIENTATION_PORTRAIT_PRIMARY 1 @@ -366,118 +205,53 @@ extern EMSCRIPTEN_RESULT emscripten_get_devicemotion_status(EmscriptenDeviceMoti #define EMSCRIPTEN_ORIENTATION_LANDSCAPE_PRIMARY 4 #define EMSCRIPTEN_ORIENTATION_LANDSCAPE_SECONDARY 8 -/* - * The event structure passed in the orientationchange event. - * https://dvcs.w3.org/hg/screen-orientation/raw-file/tip/Overview.html - */ typedef struct EmscriptenOrientationChangeEvent { - // One of EM_ORIENTATION_PORTRAIT_xx fields, or -1 if unknown. int orientationIndex; - // Emscripten-specific extension: Some browsers refer to 'window.orientation', so report that as well. - // Orientation angle in degrees. 0: "default orientation", i.e. default upright orientation to hold the mobile device in. Could be either landscape or portrait. int orientationAngle; } EmscriptenOrientationChangeEvent; -/* - * Registers a callback function for receiving the orientationchange event. - * https://dvcs.w3.org/hg/screen-orientation/raw-file/tip/Overview.html - */ + typedef EM_BOOL (*em_orientationchange_callback_func)(int eventType, const EmscriptenOrientationChangeEvent *keyEvent, void *userData); extern EMSCRIPTEN_RESULT emscripten_set_orientationchange_callback(void *userData, EM_BOOL useCapture, em_orientationchange_callback_func callback); -/* - * Returns the current device orientation state. - */ extern EMSCRIPTEN_RESULT emscripten_get_orientation_status(EmscriptenOrientationChangeEvent *orientationStatus); -/* - * Locks the screen orientation to the given set of allowed orientations. - * allowedOrientations: A bitfield set of EM_ORIENTATION_xx flags. - */ extern EMSCRIPTEN_RESULT emscripten_lock_orientation(int allowedOrientations); -/* - * Allows the screen to turn again into any orientation. - */ extern EMSCRIPTEN_RESULT emscripten_unlock_orientation(void); -/* - * The event structure passed in the fullscreenchange event. - * https://dvcs.w3.org/hg/fullscreen/raw-file/tip/Overview.html - */ typedef struct EmscriptenFullscreenChangeEvent { - // Specifies whether an element on the browser page is currently fullscreen. EM_BOOL isFullscreen; - // Specifies if the current page has the ability to display elements fullscreen. EM_BOOL fullscreenEnabled; - // The nodeName of the target HTML Element that is in full screen mode. See https://developer.mozilla.org/en-US/docs/Web/API/Node.nodeName - // If isFullscreen is false, then nodeName, id and elementWidth/Height specify information about the element that just exited fullscreen mode. EM_UTF8 nodeName[128]; - // The HTML Element ID of the target HTML element that is in full screen mode. EM_UTF8 id[128]; - // The new pixel size of the element that changed fullscreen status. int elementWidth; int elementHeight; - // The size of the whole screen, in pixels. int screenWidth; int screenHeight; } EmscriptenFullscreenChangeEvent; -/* - * Registers a callback function for receiving the fullscreenchange event. - * https://dvcs.w3.org/hg/screen-orientation/raw-file/tip/Overview.html - */ + typedef EM_BOOL (*em_fullscreenchange_callback_func)(int eventType, const EmscriptenFullscreenChangeEvent *keyEvent, void *userData); extern EMSCRIPTEN_RESULT emscripten_set_fullscreenchange_callback(const char *target, void *userData, EM_BOOL useCapture, em_fullscreenchange_callback_func callback); -/* - * Returns the current page fullscreen state. - */ + extern EMSCRIPTEN_RESULT emscripten_get_fullscreen_status(EmscriptenFullscreenChangeEvent *fullscreenStatus); -/* - * Requests the given target element to transition to full screen mode. - * Note: This function can only run inside a user-generated JavaScript event handler. - * deferUntilInEventHandler: If true and you called this function outside an event callback, this request will - * be queued to be executed the next time a JS event handler runs. If false, this - * function will instead fail if not running inside a JS event handler. - */ + extern EMSCRIPTEN_RESULT emscripten_request_fullscreen(const char *target, EM_BOOL deferUntilInEventHandler); -/* - * Returns back to windowed browsing mode. - */ + extern EMSCRIPTEN_RESULT emscripten_exit_fullscreen(void); -/* - * The event structure passed in the pointerlockchange event. - * http://www.w3.org/TR/pointerlock/ - */ typedef struct EmscriptenPointerlockChangeEvent { - // Specifies whether an element on the browser page currently has pointer lock enabled. EM_BOOL isActive; - // The nodeName of the target HTML Element that has the pointer lock active. See https://developer.mozilla.org/en-US/docs/Web/API/Node.nodeName EM_UTF8 nodeName[128]; - // The HTML Element ID of the target HTML element that has the pointer lock active. EM_UTF8 id[128]; } EmscriptenPointerlockChangeEvent; -/* - * Registers a callback function for receiving the pointerlockchange event. - * Pointer lock hides the mouse cursor and exclusively gives the target element relative mouse movement events via the mousemove event. - * http://www.w3.org/TR/pointerlock/ - */ + typedef EM_BOOL (*em_pointerlockchange_callback_func)(int eventType, const EmscriptenPointerlockChangeEvent *keyEvent, void *userData); extern EMSCRIPTEN_RESULT emscripten_set_pointerlockchange_callback(const char *target, void *userData, EM_BOOL useCapture, em_pointerlockchange_callback_func callback); -/* - * Returns the current page pointerlock state. - */ + extern EMSCRIPTEN_RESULT emscripten_get_pointerlock_status(EmscriptenPointerlockChangeEvent *pointerlockStatus); -/* - * Requests the given target element to grab pointerlock. - * Note: This function can only run inside a user-generated JavaScript event handler. - * deferUntilInEventHandler: If true and you called this function outside an event callback, this request will - * be queued to be executed the next time a JS event handler runs. If false, this - * function will instead fail if not running inside a JS event handler. - */ + extern EMSCRIPTEN_RESULT emscripten_request_pointerlock(const char *target, EM_BOOL deferUntilInEventHandler); -/* - * Exits pointer lock state and restores the mouse cursor to be visible again. - */ + extern EMSCRIPTEN_RESULT emscripten_exit_pointerlock(void); #define EMSCRIPTEN_VISIBILITY_HIDDEN 0 @@ -485,129 +259,70 @@ extern EMSCRIPTEN_RESULT emscripten_exit_pointerlock(void); #define EMSCRIPTEN_VISIBILITY_PRERENDER 2 #define EMSCRIPTEN_VISIBILITY_UNLOADED 3 -/* - * The event structure passed in the visibilitychange event. - * http://www.w3.org/TR/page-visibility/ - */ typedef struct EmscriptenVisibilityChangeEvent { - // If true, the current browser page is now hidden. EM_BOOL hidden; - // Specifies a more fine-grained state of the current page visibility status. One of the EMSCRIPTEN_VISIBILITY_ values. int visibilityState; } EmscriptenVisibilityChangeEvent; -/* - * Registers a callback function for receiving the visibilitychange event. - * http://www.w3.org/TR/page-visibility/ - */ typedef EM_BOOL (*em_visibilitychange_callback_func)(int eventType, const EmscriptenVisibilityChangeEvent *keyEvent, void *userData); extern EMSCRIPTEN_RESULT emscripten_set_visibilitychange_callback(void *userData, EM_BOOL useCapture, em_visibilitychange_callback_func callback); -/* - * Returns the current page visibility state. - */ + extern EMSCRIPTEN_RESULT emscripten_get_visibility_status(EmscriptenVisibilityChangeEvent *visibilityStatus); -/* - * Specifies the status of a single touch point on the page. - * See http://www.w3.org/TR/touch-events/#touch-interface - */ + typedef struct EmscriptenTouchPoint { - // An identification number for each touch point. long identifier; - // The touch coordinate relative to the whole screen origin, in pixels. long screenX; long screenY; - // The touch coordinate relative to the viewport, in pixels. long clientX; long clientY; - // The touch coordinate relative to the viewport, in pixels, and including any scroll offset. long pageX; long pageY; - // Specifies whether this touch point changed during this event. EM_BOOL isChanged; - // Specifies whether this touch point is still above the original target on which it was initially pressed against. EM_BOOL onTarget; - // The touch coordinates mapped to the Emscripten canvas client area, in pixels. long canvasX; long canvasY; } EmscriptenTouchPoint; -/* - * Specifies the data of a single touch event. - * See http://www.w3.org/TR/touch-events/#touchevent-interface - */ typedef struct EmscriptenTouchEvent { - // The number of valid elements in the touches array. int numTouches; - // Specifies which modifiers were active during the key event. EM_BOOL ctrlKey; EM_BOOL shiftKey; EM_BOOL altKey; EM_BOOL metaKey; - // An array of currently active touches, one for each finger. EmscriptenTouchPoint touches[32]; } EmscriptenTouchEvent; -/* - * Registers a callback function for receiving the touchstart, touchend, touchmove and touchcancel events. - * http://www.w3.org/TR/touch-events/ - */ + typedef EM_BOOL (*em_touch_callback_func)(int eventType, const EmscriptenTouchEvent *keyEvent, void *userData); extern EMSCRIPTEN_RESULT emscripten_set_touchstart_callback(const char *target, void *userData, EM_BOOL useCapture, em_touch_callback_func callback); extern EMSCRIPTEN_RESULT emscripten_set_touchend_callback(const char *target, void *userData, EM_BOOL useCapture, em_touch_callback_func callback); extern EMSCRIPTEN_RESULT emscripten_set_touchmove_callback(const char *target, void *userData, EM_BOOL useCapture, em_touch_callback_func callback); extern EMSCRIPTEN_RESULT emscripten_set_touchcancel_callback(const char *target, void *userData, EM_BOOL useCapture, em_touch_callback_func callback); -/* - * Represents the current snapshot state of a gamepad. - * http://www.w3.org/TR/gamepad/#gamepad-interface - */ + typedef struct EmscriptenGamepadEvent { - // Absolute wallclock time in msec units of when the data was recorded. double timestamp; - // The number of valid axes entries in the axis array. int numAxes; - // The number of valid button entries in the analogButton and digitalButton arrays. int numButtons; - // The analog state of the gamepad axes, in the range [-1, 1]. double axis[64]; - // The analog state of the gamepad buttons, in the range [0, 1]. double analogButton[64]; - // The digital state of the gamepad buttons, either 0 or 1. EM_BOOL digitalButton[64]; - // Specifies whether this gamepad is connected to the browser page. EM_BOOL connected; - // An ordinal associated with this gamepad, zero-based. long index; - // An ID for the brand or style of the connected gamepad device. Typically, this will include the USB vendor and a product ID. EM_UTF8 id[64]; - // A string that identifies the layout or control mapping of this device. EM_UTF8 mapping[64]; } EmscriptenGamepadEvent; -/* - * Registers a callback function for receiving the gamepadconnected and gamepaddisconnected events. - * http://www.w3.org/TR/gamepad/ - */ + typedef EM_BOOL (*em_gamepad_callback_func)(int eventType, const EmscriptenGamepadEvent *keyEvent, void *userData); extern EMSCRIPTEN_RESULT emscripten_set_gamepadconnected_callback(void *userData, EM_BOOL useCapture, em_gamepad_callback_func callback); extern EMSCRIPTEN_RESULT emscripten_set_gamepaddisconnected_callback(void *userData, EM_BOOL useCapture, em_gamepad_callback_func callback); -/* - * Returns the number of gamepads connected to the system or EMSCRIPTEN_RESULT_NOT_SUPPORTED if the current browser does not support gamepads. - * Note: A gamepad does not show up as connected until a button on it is pressed. - */ extern int emscripten_get_num_gamepads(void); -/* - * Returns a snapshot of the current gamepad state. - */ extern EMSCRIPTEN_RESULT emscripten_get_gamepad_status(int index, EmscriptenGamepadEvent *gamepadState); -/* - * The event structure passed in the battery chargingchange and levelchange event. - * http://www.w3.org/TR/battery-status/#batterymanager-interface - */ typedef struct EmscriptenBatteryEvent { double chargingTime; double dischargingTime; @@ -615,137 +330,53 @@ typedef struct EmscriptenBatteryEvent { EM_BOOL charging; } EmscriptenBatteryEvent; -/* - * Registers a callback function for receiving the battery chargingchange and levelchange events. - * http://www.w3.org/TR/battery-status/ - */ typedef EM_BOOL (*em_battery_callback_func)(int eventType, const EmscriptenBatteryEvent *keyEvent, void *userData); extern EMSCRIPTEN_RESULT emscripten_set_batterychargingchange_callback(void *userData, em_battery_callback_func callback); extern EMSCRIPTEN_RESULT emscripten_set_batterylevelchange_callback(void *userData, em_battery_callback_func callback); -/* - * Returns the current battery status. - */ + extern EMSCRIPTEN_RESULT emscripten_get_battery_status(EmscriptenBatteryEvent *batteryState); -/* - * Produces a vibration feedback for given msecs. - * http://dev.w3.org/2009/dap/vibration/ - */ + extern EMSCRIPTEN_RESULT emscripten_vibrate(int msecs); -/* - * Produces a complex vibration feedback pattern. - * msecsArray: An array of timing entries [on, off, on, off, on, off, ...] where every second one specifies a duration of vibration, and - * every other one specifies a duration of silence. - * numEntries: The number of integers in the array msecsArray. - */ extern EMSCRIPTEN_RESULT emscripten_vibrate_pattern(int *msecsArray, int numEntries); -/* - * Registers a callback function for receiving the page beforeunload event. - * Hook onto this event to perform process right prior to page close, and/or display a confirmation notification asking if the user really wants to leave the page. - * http://www.whatwg.org/specs/web-apps/current-work/multipage/history.html#beforeunloadevent - */ typedef const char *(*em_beforeunload_callback)(int eventType, const void *reserved, void *userData); extern EMSCRIPTEN_RESULT emscripten_set_beforeunload_callback(void *userData, em_beforeunload_callback callback); -// Represents a handle to an Emscripten WebGL context object. The value 0 denotes an invalid/no context. typedef int EMSCRIPTEN_WEBGL_CONTEXT_HANDLE; -/* - * Specifies WebGL context creation parameters, as documented at http://www.khronos.org/registry/webgl/specs/latest/1.0/#5.2 - */ typedef struct EmscriptenWebGLContextAttributes { - // If true, request an alpha channel for the context. If you create an alpha channel, you can blend the canvas rendering with the - // underlying web page contents. Default value: true. EM_BOOL alpha; - // If true, request a depth buffer of at least 16 bits. If false, no depth buffer will be initialized. Default value: true. EM_BOOL depth; - // If true, request a stencil buffer of at least 8 bits. If false, no stencil buffer will be initialized. Default value: false. EM_BOOL stencil; - // If true, antialiasing will be initialized with a browser-specified algorithm and quality level. If false, antialiasing is disabled. Default value: true. EM_BOOL antialias; - // If true, the alpha channel of the rendering context will be treated as representing premultiplied alpha values. If false, the alpha - // channel represents non-premultiplied alpha. Default value: true. EM_BOOL premultipliedAlpha; - // If true, the contents of the drawing buffer are preserved between consecutive requestAnimationFrame() calls. If false, color, depth - // and stencil are cleared at the beginning of each requestAnimationFrame(). Generally setting this to false gives better performance. Default value: false. EM_BOOL preserveDrawingBuffer; - // If true, hints the browser to initialize a low-power GPU rendering context. If false, prefers to initialize a high-performance - // rendering context. Default value: false. EM_BOOL preferLowPowerToHighPerformance; - // If true, requests context creation to abort if the browser is only able to create a context that does not give good - // hardware-accelerated performance. Default value: false. EM_BOOL failIfMajorPerformanceCaveat; - // Emscripten-specific extensions: - // majorVersion x minorVersion: Specifies the WebGL context version to initialize. - // For example, pass in majorVersion=1, minorVersion=0 to request a WebGL 1.0 context, and - // majorVersion=2, minorVersion=0 to request a WebGL 2.0 context. - // Default value: majorVersion=1, minorVersion=0 int majorVersion; int minorVersion; - // If true, all GLES2-compatible non-performance-impacting WebGL extensions will automatically be enabled for you after the context - // has been created. If false, no extensions are enabled by default, and you need to manually call emscripten_webgl_enable_extension() - // to enable each extension that you want to use. Default value: true. EM_BOOL enableExtensionsByDefault; } EmscriptenWebGLContextAttributes; -/* - * Populates all fields of the given EmscriptenWebGLContextAttributes structure to their default values for use with WebGL 1.0. - * Call this function as a forward-compatible way to ensure that if there are new fields added to the EmscriptenWebGLContextAttributes - * structure in the future, that they also will get default-initialized without having to change any code. - */ extern void emscripten_webgl_init_context_attributes(EmscriptenWebGLContextAttributes *attributes); -/* - * Creates a new WebGL context. See http://www.khronos.org/registry/webgl/specs/latest/1.0/#2.1 - * The parameter 'target' specifies the DOM canvas element in which to initialize the WebGL context. If 0 is passed for the target, - * the element specified by Module.canvas will be used. - * On success, this function returns a strictly positive value that represents a handle to the created context. - * On failure, this function returns a negative number that can be casted to a EMSCRIPTEN_RESULT field to get an error reason - * why the context creation failed. - * NOTE: A successful call to emscripten_webgl_create_context() will not immediately make that rendering context active. Call - * emscripten_webgl_make_context_current() after creating a context to activate it. - * NOTE: This function will try to initialize the context version that was *exactly* requested. It will not e.g. initialize a newer - * backwards-compatible version or similar. - */ extern EMSCRIPTEN_WEBGL_CONTEXT_HANDLE emscripten_webgl_create_context(const char *target, const EmscriptenWebGLContextAttributes *attributes); -/* - * Activates the given WebGL context for rendering. After calling this function, all gl***() functions apply to the given GL context. - */ extern EMSCRIPTEN_RESULT emscripten_webgl_make_context_current(EMSCRIPTEN_WEBGL_CONTEXT_HANDLE context); -/* - * Returns the currently active WebGL rendering context, or 0 if no such context is active. Calling any WebGL functions when there is no active - * rendering context is undefined and may throw a JavaScript exception. - */ extern EMSCRIPTEN_WEBGL_CONTEXT_HANDLE emscripten_webgl_get_current_context(); -/* - * Deletes the given WebGL context. If that context was active, then the no context is set to active. - */ extern EMSCRIPTEN_RESULT emscripten_webgl_destroy_context(EMSCRIPTEN_WEBGL_CONTEXT_HANDLE context); -/* - * Enables the given extension on the given context. - * Returns EM_TRUE if the given extension is supported by the context, and EM_FALSE if the extension was not available. - */ extern EM_BOOL emscripten_webgl_enable_extension(EMSCRIPTEN_WEBGL_CONTEXT_HANDLE context, const char *extension); -/* - * Registers a callback function for the canvas webgl context webglcontextlost and webglcontextrestored events. - * See http://www.khronos.org/registry/webgl/specs/latest/1.0/#5.15.2 - */ typedef EM_BOOL (*em_webgl_context_callback)(int eventType, const void *reserved, void *userData); extern EMSCRIPTEN_RESULT emscripten_set_webglcontextlost_callback(const char *target, void *userData, EM_BOOL useCapture, em_webgl_context_callback callback); extern EMSCRIPTEN_RESULT emscripten_set_webglcontextrestored_callback(const char *target, void *userData, EM_BOOL useCapture, em_webgl_context_callback callback); -/* - * Queries the given canvas element for whether its WebGL context is in a lost state. - * target: Reserved for future use, pass in 0. - */ extern EM_BOOL emscripten_is_webgl_context_lost(const char *target); #ifdef __cplusplus From 43a180fb87c864c14cd99aac0d455803b5e1fe73 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 7 Aug 2014 18:01:49 -0700 Subject: [PATCH 08/91] update local docs --- .../html/docs/api_reference/emscripten.h.html | 508 +++++++++--- .../html/docs/api_reference/html5.h.html | 721 ++++++++++++------ 2 files changed, 866 insertions(+), 363 deletions(-) diff --git a/site/build/html/docs/api_reference/emscripten.h.html b/site/build/html/docs/api_reference/emscripten.h.html index 754faba9d4af0..ccb3680ccfd63 100644 --- a/site/build/html/docs/api_reference/emscripten.h.html +++ b/site/build/html/docs/api_reference/emscripten.h.html @@ -302,43 +302,33 @@ -
  • Installing Emscripten from source (under-construction)
      -
    • Installing from Source (under-construction)
        -
      • Things you’ll need
      • -
      • Additional Notes
      • -
      • Windows and OSX: guides for manual building
      • -
      • Linux: guides for manual building
      • -
      • Configuring the basic Emscripten settings file
      • +
      • Building Emscripten from Source (under-construction)
          +
        • Emscripten Toolchain (under-construction)
        • -
        • Manually setting up Emscripten on Linux (under-construction)
            -
          • Installing required tools
          • -
          • Configuring Emscripten
          • -
          • Notes take from existing doc sources
              -
            • Things you’ll need
            • -
            • Additional Notes
            • -
            • Linux: guides for manual building
            • -
            • Configuring the basic Emscripten settings file
            • -
            • Linux - from the portable SDK installation notes
            • -
            • Installing Node.js
            • +
            • Building Emscripten on Linux (under-construction)
            • +
            • Building Emscripten on Windows (wiki-import)
                +
              • Setting up the Emscripten Toolchain on Windows
              • -
              • Using Emscripten on Windows (wiki-import)
                  -
                • Setting up the Emscripten Toolchain on Windows -
                • -
                • Getting started on Mac OS X (wiki-import)
                • +
                • Building Emscripten on Mac OS X (wiki-import)
                • LLVM Backend (wiki-import)
                  • LLVM Backend, aka “fastcomp”
                  • -
                  • Networking
                  • html5.h
                  • -
                  • Installing Emscripten from source (under-construction)
                      -
                    • Installing from Source (under-construction)
                        -
                      • Things you’ll need
                      • -
                      • Additional Notes
                      • -
                      • Windows and OSX: guides for manual building
                      • -
                      • Linux: guides for manual building
                      • -
                      • Configuring the basic Emscripten settings file
                      • +
                      • Building Emscripten from Source (under-construction)
                          +
                        • Emscripten Toolchain (under-construction)
                        • -
                        • Manually setting up Emscripten on Linux (under-construction)
                            -
                          • Installing required tools
                          • -
                          • Configuring Emscripten
                          • -
                          • Notes take from existing doc sources
                              -
                            • Things you’ll need
                            • -
                            • Additional Notes
                            • -
                            • Linux: guides for manual building
                            • -
                            • Configuring the basic Emscripten settings file
                            • -
                            • Linux - from the portable SDK installation notes
                            • -
                            • Installing Node.js
                            • +
                            • Building Emscripten on Linux (under-construction)
                            • +
                            • Building Emscripten on Windows (wiki-import)
                                +
                              • Setting up the Emscripten Toolchain on Windows
                              • -
                              • Using Emscripten on Windows (wiki-import)
                                  -
                                • Setting up the Emscripten Toolchain on Windows -
                                • -
                                • Getting started on Mac OS X (wiki-import)
                                • +
                                • Building Emscripten on Mac OS X (wiki-import)
                                • LLVM Backend (wiki-import)
                                  • LLVM Backend, aka “fastcomp”
                                  • -
                                  • Networking
                                  • html5.h
                                      @@ -436,115 +435,116 @@
                                    • Keys
                                    • Mouse
                                    • Wheel
                                    • UI
                                    • Focus
                                    • Device orientation
                                    • Device motion
                                    • -
                                    • Orientation @@ -725,7 +725,7 @@
                                      -

                                      html5.h

                                      +

                                      html5.h

                                      The C++ APIs in html5.h define the Emscripten low-level glue bindings to interact with HTML5 events from native code.

                                      -

                                      How to use this API

                                      +

                                      How to use this API

                                      Most of these APIs use an event-based architecture; functionality is accessed by registering a callback function that will be called when the event occurs.

                                      Note

                                      @@ -842,7 +842,7 @@

                                      Callback functions -

                                      General types

                                      +

                                      General types

                                      EM_BOOL
                                      @@ -857,7 +857,7 @@

                                      General types
                                      -

                                      Function result values

                                      +

                                      Function result values

                                      Most functions in this API return a result of type EMSCRIPTEN_RESULT. None of the functions fail or abort by throwing a JavaScript or C++ exception. If a particular browser does not support the given feature, the value EMSCRIPTEN_RESULT_NOT_SUPPORTED will be returned at the time the callback is registered.

                                      @@ -921,7 +921,7 @@

                                      Function result values -

                                      Keys

                                      +

                                      Keys

                                      Defines

                                      @@ -1049,8 +1049,8 @@

                                      Struct -

                                      Callback functions

                                      +
                                      +

                                      Callback functions

                                      em_key_callback_func
                                      @@ -1121,9 +1121,9 @@

                                      Functions -

                                      Mouse

                                      -
                                      -

                                      Defines

                                      +

                                      Mouse

                                      +
                                      +

                                      Defines

                                      EMSCRIPTEN_EVENT_CLICK
                                      @@ -1139,8 +1139,8 @@

                                      Defines

                                      -
                                      -

                                      Struct

                                      +
                                      +

                                      Struct

                                      EmscriptenMouseEvent
                                      @@ -1227,8 +1227,8 @@

                                      Struct

                                      -
                                      -

                                      Callback functions

                                      +
                                      +

                                      Callback functions

                                      em_mouse_callback_func
                                      @@ -1258,8 +1258,8 @@

                                      Callback functions -

                                      Functions

                                      +
                                      +

                                      Functions

                                      EMSCRIPTEN_RESULT emscripten_set_click_callback(const char *target, void *userData, EM_BOOL useCapture, em_mouse_callback_func callback)
                                      @@ -1321,9 +1321,9 @@

                                      Functions -

                                      Wheel

                                      -
                                      -

                                      Defines

                                      +

                                      Wheel

                                      +
                                      +

                                      Defines

                                      EMSCRIPTEN_EVENT_WHEEL
                                      @@ -1349,8 +1349,8 @@

                                      Defines

                                      -
                                      -

                                      Struct

                                      +
                                      +

                                      Struct

                                      EmscriptenWheelEvent
                                      @@ -1380,8 +1380,8 @@

                                      Struct

                                      -
                                      -

                                      Callback functions

                                      +
                                      +

                                      Callback functions

                                      em_wheel_callback_func
                                      @@ -1411,8 +1411,8 @@

                                      Callback functions -

                                      Functions

                                      +
                                      +

                                      Functions

                                      EMSCRIPTEN_RESULT EMSCRIPTEN_RESULT emscripten_set_wheel_callback(const char *target, void *userData, EM_BOOL useCapture, em_wheel_callback_func callback)
                                      @@ -1442,9 +1442,9 @@

                                      Functions -

                                      UI

                                      -
                                      -

                                      Defines

                                      +

                                      UI

                                      +
                                      +

                                      Defines

                                      EMSCRIPTEN_EVENT_RESIZE
                                      @@ -1454,8 +1454,8 @@

                                      Defines

                                      -
                                      -

                                      Struct

                                      +
                                      +

                                      Struct

                                      EmscriptenUiEvent
                                      @@ -1501,8 +1501,8 @@

                                      Struct

                                      -
                                      -

                                      Callback functions

                                      +
                                      +

                                      Callback functions

                                      em_ui_callback_func
                                      @@ -1532,14 +1532,21 @@

                                      Callback functions -

                                      Functions

                                      +
                                      +

                                      Functions

                                      EMSCRIPTEN_RESULT emscripten_set_resize_callback(const char *target, void *userData, EM_BOOL useCapture, em_ui_callback_func callback)
                                      EMSCRIPTEN_RESULT emscripten_set_scroll_callback(const char *target, void *userData, EM_BOOL useCapture, em_ui_callback_func callback)

                                      Registers a callback function for receiving DOM element resize and scroll events.

                                      +
                                      +

                                      Note

                                      +
                                        +
                                      • For the resize callback, pass in target = 0 to get resize events from the Window object.
                                      • +
                                      • The DOM3 Events specification only requires that the Window object sends resize events. It is valid to register a resize callback on other DOM elements, but the browser is not required to fire resize events for these.
                                      • +
                                      +
                                      @@ -1565,9 +1572,9 @@

                                      Functions -

                                      Focus

                                      -
                                      -

                                      Defines

                                      +

                                      Focus

                                      +
                                      +

                                      Defines

                                      EMSCRIPTEN_EVENT_BLUR
                                      @@ -1581,8 +1588,8 @@

                                      Defines

                                      -
                                      -

                                      Struct

                                      +
                                      +

                                      Struct

                                      EmscriptenFocusEvent
                                      @@ -1604,8 +1611,8 @@

                                      Struct

                                      -
                                      -

                                      Callback functions

                                      +
                                      +

                                      Callback functions

                                      em_focus_callback_func
                                      @@ -1635,8 +1642,8 @@

                                      Callback functions -

                                      Functions

                                      +
                                      +

                                      Functions

                                      EMSCRIPTEN_RESULT emscripten_set_blur_callback(const char *target, void *userData, EM_BOOL useCapture, em_focus_callback_func callback)
                                      @@ -1672,9 +1679,9 @@

                                      Functions -

                                      Device orientation

                                      -
                                      -

                                      Defines

                                      +

                                      Device orientation

                                      +
                                      +

                                      Defines

                                      EMSCRIPTEN_EVENT_DEVICEORIENTATION
                                      @@ -1682,8 +1689,8 @@

                                      Defines

                                      -
                                      -

                                      Struct

                                      +
                                      +

                                      Struct

                                      EmscriptenDeviceOrientationEvent
                                      @@ -1722,8 +1729,8 @@

                                      Struct

                                      -
                                      -

                                      Callback functions

                                      +
                                      +

                                      Callback functions

                                      em_deviceorientation_callback_func
                                      @@ -1753,8 +1760,8 @@

                                      Callback functions -

                                      Functions

                                      +
                                      +

                                      Functions

                                      EMSCRIPTEN_RESULT emscripten_set_deviceorientation_callback(void *userData, EM_BOOL useCapture, em_deviceorientation_callback_func callback)
                                      @@ -1807,9 +1814,9 @@

                                      Functions -

                                      Device motion

                                      -
                                      -

                                      Defines

                                      +

                                      Device motion

                                      +
                                      +

                                      Defines

                                      EMSCRIPTEN_EVENT_DEVICEMOTION
                                      @@ -1817,8 +1824,8 @@

                                      Defines

                                      -
                                      -

                                      Struct

                                      +
                                      +

                                      Struct

                                      EmscriptenDeviceMotionEvent
                                      @@ -1862,8 +1869,8 @@

                                      Struct

                                      -
                                      -

                                      Callback functions

                                      +
                                      +

                                      Callback functions

                                      em_devicemotion_callback_func
                                      @@ -1893,8 +1900,8 @@

                                      Callback functions -

                                      Functions

                                      +
                                      +

                                      Functions

                                      EMSCRIPTEN_RESULT emscripten_set_devicemotion_callback(void *userData, EM_BOOL useCapture, em_devicemotion_callback_func callback)
                                      @@ -1946,10 +1953,10 @@

                                      Functions -

                                      Orientation

                                      -

                                      Defines

                                      +

                                      Orientation

                                      +
                                      +

                                      Defines

                                      EMSCRIPTEN_EVENT_ORIENTATIONCHANGE
                                      @@ -1981,8 +1988,8 @@

                                      Defines

                                      -
                                      -

                                      Struct

                                      +
                                      +

                                      Struct

                                      EmscriptenOrientationChangeEvent
                                      @@ -2003,8 +2010,8 @@

                                      Struct

                                      -
                                      -

                                      Callback functions

                                      +
                                      +

                                      Callback functions

                                      em_orientationchange_callback_func
                                      @@ -2034,8 +2041,8 @@

                                      Callback functions -

                                      Functions

                                      +
                                      +

                                      Functions

                                      EMSCRIPTEN_RESULT emscripten_set_orientationchange_callback(void *userData, EM_BOOL useCapture, em_orientationchange_callback_func callback)
                                      @@ -2126,9 +2133,9 @@

                                      Functions -

                                      Fullscreen

                                      -
                                      -

                                      Defines

                                      +

                                      Fullscreen

                                      +
                                      +

                                      Defines

                                      EMSCRIPTEN_EVENT_FULLSCREENCHANGE
                                      @@ -2136,8 +2143,8 @@

                                      Defines

                                      -
                                      -

                                      Struct

                                      +
                                      +

                                      Struct

                                      EmscriptenFullscreenChangeEvent
                                      @@ -2188,8 +2195,8 @@

                                      Struct

                                      -
                                      -

                                      Callback functions

                                      +
                                      +

                                      Callback functions

                                      em_fullscreenchange_callback_func
                                      @@ -2219,8 +2226,8 @@

                                      Callback functions -

                                      Functions

                                      +
                                      +

                                      Functions

                                      EMSCRIPTEN_RESULT emscripten_set_fullscreenchange_callback(const char *target, void *userData, EM_BOOL useCapture, em_fullscreenchange_callback_func callback)
                                      @@ -2317,9 +2324,9 @@

                                      Functions -

                                      Pointerlock

                                      -
                                      -

                                      Defines

                                      +

                                      Pointerlock

                                      +
                                      +

                                      Defines

                                      EMSCRIPTEN_EVENT_POINTERLOCKCHANGE
                                      @@ -2327,8 +2334,8 @@

                                      Defines

                                      -
                                      -

                                      Struct

                                      +
                                      +

                                      Struct

                                      EmscriptenPointerlockChangeEvent
                                      @@ -2356,8 +2363,8 @@

                                      Struct

                                      -
                                      -

                                      Callback functions

                                      +
                                      +

                                      Callback functions

                                      em_pointerlockchange_callback_func
                                      @@ -2387,8 +2394,8 @@

                                      Callback functions -

                                      Functions

                                      +
                                      +

                                      Functions

                                      EMSCRIPTEN_RESULT emscripten_set_pointerlockchange_callback(const char *target, void *userData, EM_BOOL useCapture, em_pointerlockchange_callback_func callback)
                                      @@ -2486,9 +2493,9 @@

                                      Functions -

                                      Visibility

                                      -
                                      -

                                      Defines

                                      +

                                      Visibility

                                      +
                                      +

                                      Defines

                                      EMSCRIPTEN_EVENT_VISIBILITYCHANGE
                                      @@ -2520,8 +2527,8 @@

                                      Defines

                                      -
                                      -

                                      Struct

                                      +
                                      +

                                      Struct

                                      EmscriptenVisibilityChangeEvent
                                      @@ -2541,8 +2548,8 @@

                                      Struct

                                      -
                                      -

                                      Callback functions

                                      +
                                      +

                                      Callback functions

                                      em_visibilitychange_callback_func
                                      @@ -2572,8 +2579,8 @@

                                      Callback functions -

                                      Functions

                                      +
                                      +

                                      Functions

                                      EMSCRIPTEN_RESULT emscripten_set_visibilitychange_callback(void *userData, EM_BOOL useCapture, em_visibilitychange_callback_func callback)
                                      @@ -2625,9 +2632,9 @@

                                      Functions -

                                      Touch

                                      -
                                      -

                                      Defines

                                      +

                                      Touch

                                      +
                                      +

                                      Defines

                                      EMSCRIPTEN_EVENT_TOUCHSTART
                                      @@ -2641,8 +2648,8 @@

                                      Defines

                                      -
                                      -

                                      Struct

                                      +
                                      +

                                      Struct

                                      EmscriptenTouchPoint
                                      @@ -2730,8 +2737,8 @@

                                      Struct

                                      -
                                      -

                                      Callback functions

                                      +
                                      +

                                      Callback functions

                                      em_touch_callback_func
                                      @@ -2761,8 +2768,8 @@

                                      Callback functions -

                                      Functions

                                      +
                                      +

                                      Functions

                                      EMSCRIPTEN_RESULT emscripten_set_touchstart_callback(const char *target, void *userData, EM_BOOL useCapture, em_touch_callback_func callback)
                                      @@ -2798,9 +2805,9 @@

                                      Functions -

                                      Gamepad

                                      -
                                      -

                                      Defines

                                      +

                                      Gamepad

                                      +
                                      +

                                      Defines

                                      EMSCRIPTEN_EVENT_GAMEPADCONNECTED
                                      @@ -2810,8 +2817,8 @@

                                      Defines

                                      -
                                      -

                                      Struct

                                      +
                                      +

                                      Struct

                                      EmscriptenGamepadEvent
                                      @@ -2881,8 +2888,8 @@

                                      Struct

                                      -
                                      -

                                      Callback functions

                                      +
                                      +

                                      Callback functions

                                      em_gamepad_callback_func
                                      @@ -2912,8 +2919,8 @@

                                      Callback functions -

                                      Functions

                                      +
                                      +

                                      Functions

                                      EMSCRIPTEN_RESULT emscripten_set_gamepadconnected_callback(void *userData, EM_BOOL useCapture, em_gamepad_callback_func callback)
                                      @@ -2988,9 +2995,9 @@

                                      Functions -

                                      Battery

                                      -
                                      -

                                      Defines

                                      +

                                      Battery

                                      +
                                      +

                                      Defines

                                      EMSCRIPTEN_EVENT_BATTERYCHARGINGCHANGE
                                      @@ -3000,8 +3007,8 @@

                                      Defines

                                      -
                                      -

                                      Struct

                                      +
                                      +

                                      Struct

                                      EmscriptenBatteryEvent
                                      @@ -3033,8 +3040,8 @@

                                      Struct

                                      -
                                      -

                                      Callback functions

                                      +
                                      +

                                      Callback functions

                                      em_battery_callback_func
                                      @@ -3064,8 +3071,8 @@

                                      Callback functions -

                                      Functions

                                      +
                                      +

                                      Functions

                                      EMSCRIPTEN_RESULT emscripten_set_batterychargingchange_callback(void *userData, em_battery_callback_func callback)
                                      @@ -3119,9 +3126,9 @@

                                      Functions -

                                      Vibration

                                      -
                                      -

                                      Functions

                                      +

                                      Vibration

                                      +
                                      +

                                      Functions

                                      EMSCRIPTEN_RESULT emscripten_vibrate(int msecs)
                                      @@ -3172,9 +3179,9 @@

                                      Functions -

                                      Page unload

                                      -
                                      -

                                      Defines

                                      +

                                      Page unload

                                      +
                                      +

                                      Defines

                                      EMSCRIPTEN_EVENT_BEFOREUNLOAD
                                      @@ -3182,8 +3189,8 @@

                                      Defines

                                      -
                                      -

                                      Callback functions

                                      +
                                      +

                                      Callback functions

                                      em_beforeunload_callback
                                      @@ -3213,8 +3220,8 @@

                                      Callback functions -

                                      Functions

                                      +
                                      +

                                      Functions

                                      EMSCRIPTEN_RESULT emscripten_set_beforeunload_callback(void *userData, em_beforeunload_callback callback)
                                      @@ -3243,9 +3250,9 @@

                                      Functions -

                                      WebGL context

                                      -
                                      -

                                      Defines

                                      +

                                      WebGL context

                                      +
                                      +

                                      Defines

                                      EMSCRIPTEN_EVENT_WEBGLCONTEXTLOST
                                      @@ -3254,9 +3261,88 @@

                                      Defines

                                      Emscripten WebGL context events.

                                      +
                                      +
                                      +EMSCRIPTEN_WEBGL_CONTEXT_HANDLE
                                      +

                                      Represents a handle to an Emscripten WebGL context object. The value 0 denotes an invalid/no context (this is a typedef to an int).

                                      +
                                      +
                                      -
                                      -

                                      Callback functions

                                      +
                                      +

                                      Struct

                                      +
                                      +
                                      +EmscriptenWebGLContextAttributes
                                      +

                                      Specifies WebGL context creation parameters.

                                      +
                                      +
                                      +EM_BOOL alpha
                                      +

                                      If true, request an alpha channel for the context. If you create an alpha channel, you can blend the canvas rendering with the underlying web page contents. Default value: true.

                                      +
                                      + +
                                      +
                                      +EM_BOOL depth
                                      +

                                      If true, request a depth buffer of at least 16 bits. If false, no depth buffer will be initialized. Default value: true.

                                      +
                                      + +
                                      +
                                      +EM_BOOL stencil
                                      +

                                      If true, request a stencil buffer of at least 8 bits. If false, no stencil buffer will be initialized. Default value: false.

                                      +
                                      + +
                                      +
                                      +EM_BOOL antialias
                                      +

                                      If true, antialiasing will be initialized with a browser-specified algorithm and quality level. If false, antialiasing is disabled. Default value: true.

                                      +
                                      + +
                                      +
                                      +EM_BOOL premultipliedAlpha
                                      +

                                      If true, the alpha channel of the rendering context will be treated as representing premultiplied alpha values. If false, the alpha channel represents non-premultiplied alpha. Default value: true.

                                      +
                                      + +
                                      +
                                      +EM_BOOL preserveDrawingBuffer
                                      +

                                      If true, the contents of the drawing buffer are preserved between consecutive requestAnimationFrame() calls. If false, color, depth and stencil are cleared at the beginning of each requestAnimationFrame(). Generally setting this to false gives better performance. Default value: false.

                                      +
                                      + +
                                      +
                                      +EM_BOOL preferLowPowerToHighPerformance
                                      +

                                      If true, hints the browser to initialize a low-power GPU rendering context. If false, prefers to initialize a high-performance rendering context. Default value: false.

                                      +
                                      + +
                                      +
                                      +EM_BOOL failIfMajorPerformanceCaveat
                                      +

                                      If true, requests context creation to abort if the browser is only able to create a context that does not give good hardware-accelerated performance. Default value: false.

                                      +
                                      + +
                                      +
                                      +int majorVersion
                                      +
                                      +int minorVersion
                                      +

                                      Emscripten-specific extensions which specify the WebGL context version to initialize.

                                      +

                                      For example, pass in majorVersion=1, minorVersion=0 to request a WebGL 1.0 context, and majorVersion=2, minorVersion=0 to request a WebGL 2.0 context.

                                      +

                                      Default value: majorVersion=1, minorVersion=0

                                      +
                                      + +
                                      +
                                      +EM_BOOL enableExtensionsByDefault
                                      +

                                      If true, all GLES2-compatible non-performance-impacting WebGL extensions will automatically be enabled for you after the context has been created. If false, no extensions are enabled by default, and you need to manually call emscripten_webgl_enable_extension() to enable each extension that you want to use. Default value: true.

                                      +
                                      + +
                                      + +
                                      +
                                      +

                                      Callback functions

                                      em_webgl_context_callback
                                      @@ -3286,8 +3372,8 @@

                                      Callback functions -

                                      Functions

                                      +
                                      +

                                      Functions

                                      EMSCRIPTEN_RESULT emscripten_set_webglcontextlost_callback(const char *target, void *userData, EM_BOOL useCapture, em_webgl_context_callback callback)
                                      @@ -3339,6 +3425,141 @@

                                      Functions +
                                      +void emscripten_webgl_init_context_attributes(EmscriptenWebGLContextAttributes *attributes)
                                      +

                                      Populates all fields of the given EmscriptenWebGLContextAttributes structure to their default values for use with WebGL 1.0.

                                      +

                                      Call this function as a forward-compatible way to ensure that if there are new fields added to the EmscriptenWebGLContextAttributes structure in the future, that they also will get default-initialized without having to change any code.

                                      +

                                      +++ + + + +
                                      Parameters: +
                                      +
                                      + +
                                      +
                                      +EMSCRIPTEN_WEBGL_CONTEXT_HANDLE emscripten_webgl_create_context(const char *target, const EmscriptenWebGLContextAttributes *attributes)
                                      +

                                      Creates and returns a new WebGL context.

                                      +
                                      +

                                      Note

                                      +
                                        +
                                      • A successful call to this function will not immediately make that rendering context active. Call emscripten_webgl_make_context_current() after creating a context to activate it.
                                      • +
                                      • This function will try to initialize the context version that was exactly requested. It will not e.g. initialize a newer backwards-compatible version or similar.
                                      • +
                                      +
                                      + +++ + + + + + + + +
                                      Parameters:
                                        +
                                      • target (const char*) – The DOM canvas element in which to initialize the WebGL context. If 0 is passed, the element specified by Module.canvas will be used.
                                      • +
                                      • attributes (EmscriptenWebGLContextAttributes*) – The attributes of the requested context version.
                                      • +
                                      +
                                      Returns:

                                      On success, a strictly positive value that represents a handle to the created context. On failure, a negative number that can be cast to an EMSCRIPTEN_RESULT field to get the reason why the context creation failed.

                                      +
                                      Return type:

                                      EMSCRIPTEN_WEBGL_CONTEXT_HANDLE

                                      +
                                      +
                                      + +
                                      +
                                      +EMSCRIPTEN_RESULT emscripten_webgl_make_context_current(EMSCRIPTEN_WEBGL_CONTEXT_HANDLE context)
                                      +

                                      Activates the given WebGL context for rendering. After calling this function, all OpenGL functions (glBindBuffer(), glDrawArrays(), etc.) can be applied to the given GL context.

                                      + +++ + + + + + + + +
                                      Parameters: +
                                      Returns:

                                      EMSCRIPTEN_RESULT_SUCCESS, or one of the other result values.

                                      +
                                      Return type:

                                      EMSCRIPTEN_RESULT

                                      +
                                      +
                                      + +
                                      +
                                      +EMSCRIPTEN_WEBGL_CONTEXT_HANDLE emscripten_webgl_get_current_context()
                                      +

                                      Returns the currently active WebGL rendering context, or 0 if no context is active. Calling any WebGL functions when there is no active rendering context is undefined and may throw a JavaScript exception.

                                      + +++ + + + + + +
                                      Returns:The currently active WebGL rendering context, or 0 if no context is active.
                                      Return type:EMSCRIPTEN_WEBGL_CONTEXT_HANDLE
                                      +
                                      + +
                                      +
                                      +EMSCRIPTEN_RESULT emscripten_webgl_destroy_context(EMSCRIPTEN_WEBGL_CONTEXT_HANDLE context)
                                      +

                                      Deletes the given WebGL context. If that context was active, then the no context is set to active.

                                      + +++ + + + + + + + +
                                      Parameters: +
                                      Returns:

                                      EMSCRIPTEN_RESULT_SUCCESS, or one of the other result values.

                                      +
                                      Return type:

                                      EMSCRIPTEN_RESULT

                                      +
                                      +
                                      + +
                                      +
                                      +EM_BOOL emscripten_webgl_enable_extension(EMSCRIPTEN_WEBGL_CONTEXT_HANDLE context, const char *extension)
                                      +

                                      Enables the given extension on the given context.

                                      + +++ + + + + + + + +
                                      Parameters: +
                                      Returns:

                                      EM_TRUE if the given extension is supported by the context, and EM_FALSE if the extension was not available.

                                      +
                                      Return type:

                                      EM_BOOL

                                      +
                                      +
                                      +

                                      From 67b5f4d0dc3d4fc88921b6f3c28c7675477f6d55 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 8 Aug 2014 11:15:44 -0700 Subject: [PATCH 09/91] accept 'POSIX' as a locale; fixes #2636 --- src/library.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/library.js b/src/library.js index 5bde3d1736639..d2124c5a964d9 100644 --- a/src/library.js +++ b/src/library.js @@ -5947,7 +5947,7 @@ LibraryManager.library = { curr: 0, check: function(locale) { if (locale) locale = Pointer_stringify(locale); - return locale === 'C' || !locale; + return locale === 'C' || locale === 'POSIX' || !locale; }, }, From e2ed02b3ec32c8e0534bdf6c316c7fdf39fa5fa5 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 8 Aug 2014 11:27:22 -0700 Subject: [PATCH 10/91] fix test_stack_varargs (musl stack usage is higher than the js libc, but still the test validly checks that stack usage does not explode) --- tests/test_core.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_core.py b/tests/test_core.py index cb7ba9f1c463e..359941c13df27 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -1793,7 +1793,7 @@ def test_stack_varargs(self): def test_stack_varargs2(self): if self.emcc_args is None: return # too slow in other modes - Settings.TOTAL_STACK = 1024 + Settings.TOTAL_STACK = 1536 src = r''' #include #include From 65136b45a5dd29f3426a146e229eba5e0b89d030 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 8 Aug 2014 18:30:15 -0700 Subject: [PATCH 11/91] make test_source_map more robust --- tests/test_core.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/test_core.py b/tests/test_core.py index 359941c13df27..59196d29b6294 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -6557,7 +6557,9 @@ def build_and_check(): def clean(code): code = re.sub(r'\n+[ \n]*\n+', '\n', code) code = code.replace('{\n}', '{}') - return '\n'.join(sorted(code.split('\n'))) + lines = code.split('\n') + lines = filter(lambda line: ': do {' not in line and ' break L' not in line, lines) # ignore labels; they can change in each compile + return '\n'.join(sorted(lines)) self.assertIdentical(clean(no_maps_file), clean(out_file)) map_filename = out_filename + '.map' data = json.load(open(map_filename, 'r')) From 8b1822f142aab0cd3f5056a688bdebf2ef95b86d Mon Sep 17 00:00:00 2001 From: Chad Austin Date: Sat, 9 Aug 2014 19:37:00 -0700 Subject: [PATCH 12/91] fix embind in ie11: ES5 does not provide a 'name' property on functions --- src/embind/embind.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/embind/embind.js b/src/embind/embind.js index b77b684a1202b..b07c189e0d6c6 100644 --- a/src/embind/embind.js +++ b/src/embind/embind.js @@ -2105,6 +2105,9 @@ var LibraryEmbind = { $char_9: '9'.charCodeAt(0), $makeLegalFunctionName__deps: ['$char_0', '$char_9'], $makeLegalFunctionName: function(name) { + if (undefined === name) { + return '_unknown'; + } name = name.replace(/[^a-zA-Z0-9_]/g, '$'); var f = name.charCodeAt(0); if (f >= char_0 && f <= char_9) { From aa4526662fd137cc6a06a56e64fc44315e95f44d Mon Sep 17 00:00:00 2001 From: Anthony Liot Date: Sun, 10 Aug 2014 12:10:45 +0200 Subject: [PATCH 13/91] Add OpenAL function for Unigine Engine --- src/library_openal.js | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/src/library_openal.js b/src/library_openal.js index 2b2e4214dc0b6..71c43aef5fd05 100644 --- a/src/library_openal.js +++ b/src/library_openal.js @@ -282,6 +282,12 @@ var LibraryOpenAL = { } {{{ makeSetValue('data', '0', '0', 'i32') }}}; break; + case 0x20003 /* ALC_MAX_AUXILIARY_SENDS */: + if (!device) { + AL.currentContext.err = 0xA001 /* ALC_INVALID_DEVICE */; + return 0; + } + {{{ makeSetValue('data', '0', '4', 'i32') }}}; default: #if OPENAL_DEBUG console.log("alcGetIntegerv with param " + param + " not implemented yet"); @@ -531,6 +537,11 @@ var LibraryOpenAL = { } }, + alSource3i: ['alSource3f'], + alSource3i: function(source, param, v1, v2, v3) { + _alSource3f(source, param, v1, v2, v3); + }, + alSource3f: function(source, param, v1, v2, v3) { if (!AL.currentContext) { #if OPENAL_DEBUG @@ -1178,6 +1189,31 @@ var LibraryOpenAL = { } }, + alListener3f: function(param, v1, v2, v3) { + if (!AL.currentContext) { +#if OPENAL_DEBUG + console.error("alListenerfv called without a valid context"); +#endif + return; + } + switch (param) { + case 0x1004 /* AL_POSITION */: + AL.currentContext.ctx.listener._position = [v1, v2, v3]; + AL.currentContext.ctx.listener.setPosition(v1, v2, v3); + break; + case 0x1006 /* AL_VELOCITY */: + AL.currentContext.ctx.listener._velocity = [v1, v2, v3]; + AL.currentContext.ctx.listener.setVelocity(v1, v2, v3); + break; + default: +#if OPENAL_DEBUG + console.error("alListener3f with param " + param + " not implemented yet"); +#endif + AL.currentContext.err = 0xA002 /* AL_INVALID_ENUM */; + break; + } + }, + alListenerfv: function(param, values) { if (!AL.currentContext) { #if OPENAL_DEBUG @@ -1344,6 +1380,13 @@ var LibraryOpenAL = { return 0; }, + alGetEnumValue: function(name) { + return 0; + }, + + alSpeedOfSound: function(value) { + }, + alDopplerFactor: function(value) { }, From 7494d3d67aff91de413b6c11feaad974e40f3e0d Mon Sep 17 00:00:00 2001 From: hamishwillee Date: Mon, 11 Aug 2014 19:55:05 +1000 Subject: [PATCH 14/91] Significant updates to the building emscripten from source topiss --- .../building_from_source/LLVM-Backend.rst | 65 ++++-- ...ilding_emscripten_from_source_on_linux.rst | 123 ++--------- ...ing_emscripten_from_source_on_mac_os_x.rst | 146 +++++-------- ...ding_emscripten_from_source_on_windows.rst | 202 +++++------------- .../configuring_emscripten_settings.rst | 104 +++++++++ .../docs/building_from_source/index.rst | 19 +- ...lly_integrating_emscripten_with_vs2010.rst | 72 +++++++ .../toolchain_what_is_needed.rst | 16 +- .../verify_emscripten_environment.rst | 31 ++- site/source/docs/getting_started/Tutorial.rst | 2 +- .../source/docs/getting_started/downloads.rst | 59 ++++- ...ing_started_with_emscripten_and_vs2010.rst | 19 ++ site/source/docs/getting_started/index.rst | 1 + site/source/docs/tools_reference/emcc.rst | 3 +- site/source/docs/tools_reference/emsdk.rst | 56 +++-- 15 files changed, 502 insertions(+), 416 deletions(-) create mode 100644 site/source/docs/building_from_source/configuring_emscripten_settings.rst create mode 100644 site/source/docs/building_from_source/manually_integrating_emscripten_with_vs2010.rst create mode 100644 site/source/docs/getting_started/getting_started_with_emscripten_and_vs2010.rst diff --git a/site/source/docs/building_from_source/LLVM-Backend.rst b/site/source/docs/building_from_source/LLVM-Backend.rst index 87c84f6d2dcf9..defc508b1c11b 100644 --- a/site/source/docs/building_from_source/LLVM-Backend.rst +++ b/site/source/docs/building_from_source/LLVM-Backend.rst @@ -21,24 +21,50 @@ Fastcomp is an **LLVM backend**. It is **not** in upstream LLVM yet, it is far t This means that if you use another build of LLVM - like an older one you built yourself, or one from your linux distro's repos, etc. - it will **not** contain fastcomp. Emscripten will give an error about this (you can manually run those checks with ``emcc -v``), and briefly explain the issue and link to this page (where, later down, you can see how to disable fastcomp). -.. _building-fastcomp-from-source: + Getting Fastcomp ---------------- + +.. _building-fastcomp-from-source: + +Building fastcomp from source +-------------------------------- + To use fastcomp, you need both Emscripten (see the :ref:`Tutorial`) and the Emscripten LLVM code, either from the SDK or from source. Instructions from source are as follows: -- Clone the fastcomp LLVM repository: https://github.com/kripken/emscripten-fastcomp. Note that it doesn't matter where - you do this; you'll point to that directory when you edit ``~/.emscripten``, see later down): :: - +- Clone the fastcomp `LLVM repository `_: + + :: + git clone https://github.com/kripken/emscripten-fastcomp + + .. note:: It doesn't matter where you clone *fastcomp* because Emscripten gets the information from the :ref:`compiler configuration file (~/.emscripten) `. We show how to update this file later in these instructions: + + +- Navigate to the **tools** directory (**emscripten-fastcomp/tools**) and clone the `kripken/emscripten-fastcomp-clang `_ repository into a *clang* subdirectory: + + :: + + cd tools + git clone https://github.com/kripken/emscripten-fastcomp-clang clang + + .. warning:: You **must** clone it into a dir named "clang", so that clang is present in **tools/clang**! + + .. note:: This repo has changed. Early in fastcomp development we used a different directory. + +- Build fastcomp + + - Navigate back to the root of the llvm clone (**/emscripten-fastcomp**), then create and navigate into a new directory "**build**" (we highly recommend creating a separate build directory): + + :: -- Enter ``tools`` and clone the fastcomp Clang repository: https://github.com/kripken/emscripten-fastcomp-clang Note: **you must clone it into a dir named "clang"**, so that clang is present in ``tools/clang``! Use something like ``git clone ..repo.. clang``. (Another note: **this repo has changed**, earlier in fastcomp development we used another one, so make sure you are using this one now.) -- Build it: - - ``cd ..`` to get back to the root of the llvm checkout - - ``mkdir build`` and then ``cd build`` (it is better to build into a - separate build dir) - - Configure the build using the *configure* script or *Cmake*: + cd .. + mkdir build + cd build + + - Configure the build using *either* the *configure* script or *cmake* (configure is located in the parent directory): - Using *configure*: @@ -52,10 +78,23 @@ To use fastcomp, you need both Emscripten (see the :ref:`Tutorial`) and the Emsc cmake .. -DCMAKE_BUILD_TYPE=Release -DLLVM_TARGETS_TO_BUILD="X86;JSBackend" -DLLVM_INCLUDE_EXAMPLES=OFF -DLLVM_INCLUDE_TESTS=OFF -DCLANG_INCLUDE_EXAMPLES=OFF -DCLANG_INCLUDE_TESTS=OFF - replace X86 if you are on something else.. + .. note:: replace X86 if you are on something else.. - - ``make -j 4`` (or whatever number of cores you want to use) -- Set it up in ~/.emscripten (set the path to the llvm checkout + something like ``/build/Release/bin`` as LLVM\_ROOT, look for where the ``clang`` binary shows up under ``build/``) + - Call *make* to build the sources, specifying the number of available cores: + + :: + + make -j 4 + +.. _llvm-update-compiler-configuration-file: + +- Update the :ref:`~/.emscripten `, specifying the location of *fastcomp* in using the ``LLVM_ROOT`` variable. The path should be set to the location of the *clang* binary under the **build** directory. This will be something like **/build/Release/bin** or **/build/bin**: + + :: + + LLVM_ROOT='' **HamishW** + + .. note:: If **~/.emscripten** does not yet exist, you can create it by running ``./emcc --help`` in your **emscripten** directory (assuming Emscripten has already been downloaded). Branches ~~~~~~~~ diff --git a/site/source/docs/building_from_source/building_emscripten_from_source_on_linux.rst b/site/source/docs/building_from_source/building_emscripten_from_source_on_linux.rst index 9b7087cf8f346..583a34fd91e0a 100644 --- a/site/source/docs/building_from_source/building_emscripten_from_source_on_linux.rst +++ b/site/source/docs/building_from_source/building_emscripten_from_source_on_linux.rst @@ -1,12 +1,14 @@ .. _building-emscripten-on-linux: -============================================================ -Building Emscripten on Linux (under-construction) -============================================================ +================================================ +Building Emscripten on Linux (ready-for-review) +================================================ -This page contains basic instructions on how to build and configure Emscripten from source on a clean (Ubuntu 14.04.1 LTS 64bit) Linux box. +.. tip:: The :ref:`Portable SDK for Linux ` (and Mac OS X) provides the **easiest** and **most reliable** method for **building from source**. Just :ref:`download and install the SDK ` and follow the brief instructions :ref:`here `. -.. tip:: The :ref:`Portable SDK for Linux ` (and Mac OS X) also builds the tools from source, and may provide a simpler alternative to the process outlined here. The benefit of the SDK is that it helps automate getting the source and configuring the environment. + These instructions are provided for developers who, for whatever reason, prefer a manual approach. + +This page contains basic instructions on how to manually build and configure Emscripten from source on a clean (Ubuntu 14.04.1 LTS 64bit) Linux box. What you'll need ================= @@ -15,7 +17,7 @@ The previous topic (:ref:`Emscripten Toolchain `) lists Installing required tools -============================================================ +========================== These instructions explain how to install **all** the :ref:`required tools `. You can :ref:`test whether some of these are already installed ` on the platform and skip those steps. @@ -33,7 +35,7 @@ These instructions explain how to install **all** the :ref:`required tools `_ using the *system package manager*: :: @@ -69,115 +71,24 @@ These instructions explain how to install **all** the :ref:`required tools `, a user-specific file located in the user's home directory. +Instructions for creating and manually configuring up this file are given in :ref:`configuring-emscripten-settings`. Validating the environment =============================== -The best way to validate the environment is to build some code. - -There are some basic validation and troubleshooting instructions in the topic: :ref:`verifying-the-emscripten-environment`. - -.. comment: This is a comment that might go in the "verifying" section. - - **HamishW** Also see what can come out of the Downloads validating section. May be some scope for reuse. - - **HamishW** confirm that you can't use paths set up by emscripten - you have to actually specify which emcc you want to run? on Linux. +The best way to validate the environment is to build some code. Open the terminal in your *Emscripten* directory (where *emcc* is located) and enter: :: - You can also validate the individual parts of the toolchain have been installed, as described above: :: - + ./emcc tests/hello_world.cpp - - # Test emcc. This should print out the *emcc* version number as well as run some basic tests - +If this builds **a.out.js** in the current directory, and you don't see any build errors in the terminal, Emscripten is good to go! - +There are additional validation and troubleshooting instructions in the topic: :ref:`verifying-the-emscripten-environment`. diff --git a/site/source/docs/building_from_source/building_emscripten_from_source_on_mac_os_x.rst b/site/source/docs/building_from_source/building_emscripten_from_source_on_mac_os_x.rst index 4b48ded886f63..65e5515201c11 100644 --- a/site/source/docs/building_from_source/building_emscripten_from_source_on_mac_os_x.rst +++ b/site/source/docs/building_from_source/building_emscripten_from_source_on_mac_os_x.rst @@ -1,135 +1,89 @@ -.. _Getting-started-on-Mac-OS-X: +.. _building-emscripten-on-mac-osx-from-source: -================================================ -Building Emscripten on Mac OS X (wiki-import) -================================================ -.. note:: This article was migrated from the wiki (Fri, 25 Jul 2014 04:21) and is now the "master copy" (the version in the wiki will be deleted). It may not be a perfect rendering of the original but we hope to fix that soon! +================================================== +Building Emscripten on Mac OS X (ready-for-review) +================================================== -This guide instructs step-by-step on how to setup emscripten on a clean Mac OS X box. The steps have been tested against OS X version 10.8.2. +.. tip:: The :ref:`Portable SDK for Linux ` (and Mac OS X) provides the **easiest** and **most reliable** method for **building from source**. Just :ref:`download and install the SDK ` and follow the brief instructions :ref:`here `. -Note for `homebrew `__ users: -``brew install emscripten`` does all the steps below for you (including installation of the llvm fastcomp compiler and patching the python interpreter). + These instructions are provided for developers who, for whatever reason, prefer a manual approach. -1. Install svn if you do not have it yet. It is distributed with XCode Command Line Tools in OSX App Store. See http://superuser.com/questions/455214/where-is-svn-on-os-x-mountain-lion +This page contains basic instructions on how to manually build and configure Emscripten from source on a clean (OS X version 10.8.2) clean Mac OS X box. - - Install XCode from OSX App Store. - - In XCode->Preferences->Downloads, install Command Line Tools. - - Test that svn works from command line: type 'svn --version' in terminal. +What you'll need +================= -2. Install git if you do not have it yet: +The topic :ref:`Emscripten Toolchain ` lists the specific versions of tools that are needed. - - Allow installation of unsigned packages, or installing git package won't succeed: https://www.my-private-network.co.uk/knowledge-base/apple-related-questions/osx-unsigned-apps.html - - Download and install git from http://git-scm.com/ - - Test that git works from command line: type 'git --version' in terminal. -3. Install cmake if you do not have it yet: +Installing required tools +========================== - - Download and install cmake-2.8.10.2-Darwin64-universal.dmg or newer from http://www.cmake.org/cmake/resources/software.html - - Test that cmake works from command line: type 'cmake --version' in terminal. +These instructions explain how to install **all** the :ref:`required tools `. You can :ref:`test whether some of these are already installed ` on the platform and skip those steps. -4. Build LLVM+Clang 3.2 from SVN repository: +#. Install the *XCode Command Line Tools*. These include the toolchain to build :term:`Fastcomp`, and also are a precondition for *git*. - :: + - Install XCode from the `Mac OS X App Store `_. + - In **XCode | Preferences | Downloads**, install *Command Line Tools*. - cd ~ - svn co http://llvm.org/svn/llvm-project/llvm/tags/RELEASE\_32/final llvm32 - cd llvm32/tools - svn co http://llvm.org/svn/llvm-project/cfe/tags/RELEASE\_32/final clang - cd ../.. - mkdir llvm32build - cd llvm32build - cmake -DCMAKE\_BUILD\_TYPE=Release -G "Unix Makefiles" ../llvm32 - make +#. Install *git*: - After these steps, Clang 3.2 will be built into ~/llvm32build/bin. The source tree ~/llvm32 is not needed anymore, if you want to conserve disk space. + - Allow installation of unsigned packages, or installing git package `won't succeed `_. + - Install XCode and the XCode Command Line Tools (should already have been done). This will provide *git* to the system PATH (see `this stackoverflow post `_). + - Download and install git directly from http://git-scm.com/. - Note that XCode ships with a custom version of Clang (3.1svn or 3.2svn depending on XCode version). It may be possible to omit this step and just use the version provided by XCode, but the LLVM 3.2 RELEASE version is preferred, since that is the "officially supported version" the Emscripten OSX unit tests are run against. +#. Install *cmake* if you do not have it yet: -5. Set up Clang 3.2 in PATH: + - Download and install `cmake-2.8.10.2-Darwin64-universal.dmg `_ (or newer) - :: - - cd ~ - echo "export PATH=~/llvm32build/bin:$PATH" >> .profile - - The above change is permanent and it persists between system restarts. It only affects the current user. - -6. Close all terminal windows, and open a new one. Check that clang works ok in path: - - :: - - cd ~ - clang --version - - The command should output: clang version 3.2 (tags/RELEASE\_32/final 176107) Target: x86\_64-apple-darwin12.2.1 Thread model: posix - -7. Delete old .emscripten file if it happened to exist: - - :: - - rm ~/.emscripten - rm -rf ~/.emscripten\_cache - -8. Set up node: - - - Download and install node from http://nodejs.org/ - - Test that node works from command line: type 'node --version' in terminal. - -9. Obtain Emscripten: - - :: - - cd ~ - git clone https://github.com/kripken/emscripten.git + +#. Install *node.js* from http://nodejs.org/ - By default, git will clone the emscripten 'incoming' branch, which is the branch where the newest developments of Emscripten occur. If you want to use a more stable branch, switch to the 'master' branch: - cd ~/emscripten - git checkout master -.. _getting-started-on-osx-install-python2: + .. _getting-started-on-osx-install-python2: -10. Setup 'python2': (this step is needed to workaround a bug reported in `#763 `__) +#. Setup *python2* (this step is needed to workaround a bug reported in `#763 `_): - - In terminal, type 'python2 --version'. If you get a "command not found", type the following: :: + - In terminal, type ``python2 --version``. If you get a "command not found", type the following: :: cd /usr/bin sudo ln python python2 sudo ln ../../System/Library/Frameworks/Python.framework/Versions/2.7/bin/python2.7 python22.7 - - Issue 'python2 --version' again. It should now print Python 2.7.2 + - Enter ``python2 --version`` again. It should now print Python 2.7.2 -11. Perform emscripten "first run": - - :: +#. Build :term:`Fastcomp` (LLVM + Clang) from source using :ref:`these instructions `. + +#. Clone the `kripken/emscripten `_ repository from Github. This repository contains the main compiler tool for compiling C/C++ programs to JavaScript: - cd ~/emscripten - /emcc --help + - Create a directory (with no spaces in the name) to contain the clone. + - Enter the following command into the terminal: :: + + git clone https://github.com/kripken/emscripten.git + - - edit the file ~/.emscripten in a text editor to set up any required paths. -12. (Optional) Compile a simple test program to check that everything works: - :: +Configuring Emscripten settings +=============================== - cd ~/emscripten - ./em++ tests/hello\_world.cpp - node a.out.js +Almost all the compiler settings used by Emscripten are defined in the :ref:`compiler configuration file (~/.emscripten) `, a user-specific file located in the user's home directory. - The first run will most likely pop up an automatic prompt that asks to install java. Proceed, and after installation finishes, rerun the above commands. Running node should output: hello, world! +Instructions for creating and manually configuring up this file are given in :ref:`configuring-emscripten-settings`. + -13. (Optional) Compile a simple WebGL program to check that .html output and GLES2/WebGL works: +Validating the environment +=============================== - :: +The best way to validate the environment is to build some code. Open the terminal in your *Emscripten* directory (where *emcc* is located) and enter: :: + + ./emcc tests/hello_world.cpp + +If this builds **a.out.js** in the current directory, and you don't see any build errors in the terminal, Emscripten is good to go! + +There are additional validation and troubleshooting instructions in the topic: :ref:`verifying-the-emscripten-environment`. - cd ~/emscripten - ./emcc tests/hello\_world\_gles.c -o hello\_world\_gles.html - open hello\_world\_gles.html - - .. note:: If the Safari 6 browser pops up with a message "Could not create canvas :(", follow `these instructions `_ to enable WebGL support in Safari -14. (Optional) Run the full battery of tests to check that Emscripten is perfectly operational on the current platform: :: - cd ~/emscripten - python tests/runner.py - python tests/runner.py benchmark - Note that some tests will likely fail. Cross-reference the results with https://github.com/kripken/emscripten/issues?labels=tests to see if you are receiving currently unknown issues. diff --git a/site/source/docs/building_from_source/building_emscripten_from_source_on_windows.rst b/site/source/docs/building_from_source/building_emscripten_from_source_on_windows.rst index 38f90347c9dc9..4147d90a105d8 100644 --- a/site/source/docs/building_from_source/building_emscripten_from_source_on_windows.rst +++ b/site/source/docs/building_from_source/building_emscripten_from_source_on_windows.rst @@ -1,190 +1,86 @@ -.. _Using-Emscripten-on-Windows: +.. _building-emscripten-on-windows-from-source: -============================================== -Building Emscripten on Windows (wiki-import) -============================================== +=================================================== +Building Emscripten on Windows (ready-for-review) +=================================================== -.. note:: This article was migrated from the wiki (Fri, 25 Jul 2014 04:21) and is now the "master copy" (the version in the wiki will be deleted). It may not be a perfect rendering of the original but we hope to fix that soon! +.. tip:: The :ref:`Emscripten Windows SDKs ` provide the **easiest** and **most reliable** method for **building from source**. Just :ref:`download and install the SDK ` and follow the brief instructions :ref:`here `. -This page describes how to use Emscripten on Windows. + These instructions are provided for developers who, for whatever reason, prefer a manual approach. -Setting up the Emscripten Toolchain on Windows ----------------------------------------------- +This page contains basic instructions on how to manually build and configure Emscripten from source on a clean Windows box. -This section contains basic instructions on how to start using Emscripten on a clean Windows box. After these steps, you can invoke emcc from the command line by calling 'python emcc'. 64-bit versions of all needed dependencies are preferred, and may be required if you are building large projects. -Installing required tools -~~~~~~~~~~~~~~~~~~~~~~~~~ - -1. Install Python 2.x (not 3.x) from http://www.python.org/. - - - e.g. `python-2.7.5.amd64.msi `_ for a 64-bit install. - - If you plan to use the Visual Studio integration, do NOT install the 64-bit version. Get the 32-bit version of python from `python-2.7.5.msi `_. - - Add the Python bin directory to your PATH. (Open up System Settings, Advanced system properties, click Environment Variables. Add "C:27" to the PATH, separated by a semicolon.) If on the other hand ``python.exe`` appears in "C:27" and not under bin, just add "C:27". - -2. Install node.js from http://nodejs.org/ - - - e.g. `node-v0.10.17-x64.msi `_ - - If you plan to use the Visual Studio integration, do NOT install the 64-bit version. Get the 32-bit version of node.js from `node-v0.10.17-x86.msi `_. +What you'll need +================= -3. Setup gcc 4.6 and llvm-clang 3.2. +The topic :ref:`Emscripten Toolchain ` lists the specific versions of tools that are needed. - - If you like building the tools yourself or plan to use the Visual Studio integration (for which you need 32-bit versions of the tools) see below for how to build LLVM/Clang from source. - - Otherwise download the following 64-bit builds: +.. note:: 64-bit versions of all needed dependencies are preferred, and may be required if you are building large projects. However, if you plan to use the Visual Studio integration, do NOT install the 64-bit versions of the tools. - - `x86\_64-w64-mingw32-gcc-4.6.3-2-release-win64\_rubenvb.7z `_ - - `x86\_64-w64-mingw32-clang-3.2-release-win64\_rubenvb.7z `_ +Installing required tools +========================== - - Extract both of them using `7zip `__ to the same location, e.g. C:64 +These instructions explain how to install **all** the :ref:`required tools `. You can :ref:`test whether some of these are already installed ` on the platform and skip those steps. -4. If you do not already have a git client, Install `Github for Windows `_. -5. Clone the ``kripken/emscripten`` repository from github. The emscripten repository contains the main compiler tool for compiling C/C++ programs to JavaScript. - - Launch the GitHub for Windows Client. You may click "Skip Setup" if you don't have a github account. - - (optional) Select "Options" from the gear menu, and customize the default storage directory. A path without spaces can save you lots of pain down the line. - - In your web browser, open https://github.com/kripken/emscripten and press the "Clone in Windows" button. - - .. note:: If you already had a different git client, the repository URL is ``https://github.com/kripken/emscripten.git`` (e.g. ``git clone https://github.com/kripken/emscripten.git``) +#. Install `Python 2.x `_ (not 3.x) + - For example `python-2.7.5.amd64.msi `_ (64-bit version) or `python-2.7.5.msi `_ (32-bit version). + - Add the path to the Python directory containing **Python.exe** to your PATH. -Configuring Emscripten -~~~~~~~~~~~~~~~~~~~~~~ - -1. Open up a command prompt, and change to the directory where you cloned the Emscripten repository. By default with the GitHub client, this will be ``C:\Users\username\Documents\GitHub\emscripten``. -2. Run ``python emcc --help`` - - - You should get a ``Welcome to Emscripten!`` message. Behind the scenes, Emscripten generated a file called ``.emscripten`` in your Windows home folder. - - If you do not see this message, make sure that python is properly in your global PATH, and that you are in the Emscripten directory. - -3. Edit ``C:\Users\username\.emscripten``: - - 1. Edit the variable ``EMSCRIPTEN_ROOT`` to point to the Emscripten root folder, e.g. ``EMSCRIPTEN_ROOT = 'C:/Users/username/Documents/GitHub/emscripten'`` (Note: use forward slashes) - 2. Edit the variable ``LLVM_ROOT`` to point directly to the path where you installed clang.exe, e.g. :: - - ``LLVM_ROOT = 'C:/mingw64/bin'`` - - 3. Edit the variable TEMP\_DIR to point to a valid Windows path on your local system, e.g. ``TEMP_DIR = 'C:/tmp'``, and create that folder on the local filesystem if it doesn't exist. - 4. If you are planning on using Cygwin and cygwin make in the future, copy the .emscripten file to your cygwin home folder as well, e.g. - copy C:.emscripten C: (There is a bug in Emscripten that it currently looks for the file .emscripten in two places (Win7 user home folder or cygwin user home folder), depending on the environment it is executed in, so as a current workaround these files must be present and identical on Windows. (see `issue #411 `_)) - - -.. comment: **Hamish** Can we/should we integrate some of the following: - - Configuring the basic Emscripten settings file - ============================================ - - .. COMMENT - HAMISHW from the MDN - and I suspect no longer needed now we have LLVM Backend. Check and delete if needed. - - The first time you run emcc (or any of the other Emscripten tools, for that matter), it will create a settings file at ``~/.emscripten`` (~ is your user's home directory) and exit. This file contains a number of settings that provide Emscripten with the Paths to all its requirements (LLVM, clang, etc.) amongst other things, and looks something like so: :: - - import os - LLVM_ROOT='C:/Program Files/Emscripten/clang/3.2_64bit/bin' - NODE_JS='C:/Program Files/Emscripten/node/0.10.17_64bit/node.exe' - PYTHON='C:/Program Files/Emscripten/python/2.7.5.3_64bit/python.exe' - JAVA='C:/Program Files/Emscripten/java/7.45_64bit/bin/java.exe' - EMSCRIPTEN_ROOT='C:/Program Files/Emscripten/emscripten/1.7.8' - CRUNCH='C:/Program Files/Emscripten/crunch/1.03/crunch.exe' - MINGW_ROOT='C:/Program Files/Emscripten/mingw/4.6.2_32bit' - SPIDERMONKEY_ENGINE = '' - V8_ENGINE = '' - TEMP_DIR = 'c:/users/cmills/appdata/local/temp' - COMPILER_ENGINE = NODE_JS - JS_ENGINES = [NODE_JS] - - If you used an emsdk installer to install Emscripten everything would be set up automatically, but since you probably built everything manually (since you are reading this section) you'll need to set the Emscripten settings yourself. - - 1. If you haven't run Emscripten before, run it now with (assumes you are in ``emsdk`` and haven't set it's location in your PATH): - - :: - - ./Emscripten/1.7.8/emcc + - Paths are set by opening **System Settings | Advanced system properties**, clicking **Environment Variables** and select **PATH**. + - Add the path to python, separated by semicolons: e.g. ``;C:/Python27/;`` or ``;C:/Python27/bin;`` (depending on the location of the exe). - .. note:: This is for Mac/Linux; on Windows you would use emcc instead. - .. note:: If you are having trouble with python versions, you can also explicitly invoke - :: - - python emcc - - especially if python2 is not defined in your system. python2 allows python 2 and 3 to be installed together on one system, which is increasingly common; as an alternative to python emcc, you can also add a symlink to python from python2). In that case you should also update the PYTHON line in the ~/.emscripten settings file. - #. Edit the ``~/.emscripten`` file now using your favourite text editor. - - #. Change the directory locations of ``LLVM_ROOT`` and ``NODE_JS`` to the right places in your setup (specifically, edit ``LLVM_ROOT`` and ``NODE_JS``). If those paths are not right, Emscripten will not find LLVM, Clang or Node.js and return a failure message. Look at the comments in the file that explain what the settings are and which ones you need to change. - - #. After setting those paths, run ``./Emscripten/1.7.8/emcc`` again. It should again perform the sanity checks to test the specified paths. If they don't all pass, you might have a typo somewhere. When everything is set up properly, running ``./Emscripten/1.7.8/emcc`` should return ``emcc: no input files``, and you should be ready to use it. - - - - - -Integrating Emscripten to Visual Studio 2010 --------------------------------------------- +#. Install `node.js `_ -It is possible to integrate the Emscripten compiler directly to Visual Studio. This allows existing VS .sln files to be directly built using *emcc*. The Microsoft compiler property pages are replaced by *Clang* and emcc -specific options. + - For example `node-v0.10.17-x64.msi `_ (64-bit version) or `node-v0.10.17-x86.msi `_. (32-bit version). -1. Install Visual Studio 2010 - .. note:: Express version has not been tested, but should be ok. Please drop a line on Emscripten IRC channel or mailing list to report your experience with VS2010 Express! +#. Install `gcc 4.6 `_ -2. Clone the juj/vs-tool repository from github: +#. Install `Github for Windows `_ (or any other git client). - - git clone https://github.com/juj/vs-tool - - The vs-tool repository contains a plugin to Visual Studio 2010 (or rather, to MSBuild) that instructs Visual Studio how to use the llvm-clang and emscripten toolchain. +#. Install `Java `_ -3. Install vs-tool itself. -4. Navigate to folder vs-tool -5. Copy the folders Clang and Emscripten to C:Files (x86).Cpp.0\\. -6. Set up the required environment variables for vs-tool. -7. Windows 7: Open Control Panel -- System -- Advanced System Settings -- Environment Variables. -8. Create a new environment variable 'CLANG\_BIN' and set it to point to the folder where you built clang to (path to clang.exe) E.g. - - - SETX CLANG\_BIN C:-build - - This is how vs-tool locates the folder to your llvm-clang compiler. Alternatively, this path can be set per-project in Visual Studio project property pages. - -9. Create a new environment variable 'EMSCRIPTEN' and set it to point to the Emscripten git repository root folder (the path where you copied emcc.exe and other exes to). E.g. - - - SETX EMSCRIPTEN C: - - This is how vs-tool locates the Emscripten compiler. This path - can also be overridden per-project in VS property pages. - -10. Create a new environment variable 'EMCC\_WEBBROWSER\_EXE' and set it to point to an executable you want to use to browse Emscripten-generated web pages from Visual Studio. This process is spawned when you tap Start (Ctrl-F5) in Visual Studio for an Emscripten-targeted project. +#. Build :term:`Fastcomp` (LLVM + Clang) from source using :ref:`these instructions `. + +#. Clone the `kripken/emscripten `_ repository from Github. This repository contains the main compiler tool for compiling C/C++ programs to JavaScript: - - SETX EMCC\_WEBBROWSER\_EXE C:Files (x86)Firefox.exe + - Using *Github for Windows*: + - Launch the *GitHub for Windows* Client. Click **Skip Setup** if you don't have a github account. + - (optional) Select **Options** from the gear menu, and customize the default storage directory. Ensure the path has no spaces. + - In your web browser, open https://github.com/kripken/emscripten and press the **Clone in Windows** button. + + - Using the command line: + - Create a directory (with no spaces in the name) to contain the clone. + - Enter the following command into the terminal: :: + + git clone https://github.com/kripken/emscripten.git -11. Now you are all set to start developing Emscripten-based projects from Visual Studio. To test the installation, open the Visual Studio solution file 10\_msvc10.sln. -Tips for using Emscripten from the Visual Studio 2010 IDE -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Configuring Emscripten settings +=============================== -To build a Visual Studio solution using the Emscripten toolchain, select the "Emscripten" configuration from the Configuration Manager dropdown as the active configuration, and choose Build Solution (F7). +Almost all the compiler settings used by Emscripten are defined in the :ref:`compiler configuration file (.emscripten) `, a user-specific file located in the user's home directory. -To launch a project directly to a web browser from Visual Studio, right-click on the project to run, choose "Set as Startup Project", and select Start without Debugging (Ctrl+F5). This should launch the generated .html file to the browser you specified in EMCC\_WEBBROWSER\_EXE. A bug(?) in Visual Studio causes a "Executable for Debug Session" dialog to occasionally open up when you hit Ctrl+F5. This can be ignored by clicking Yes, then No, or simply by hitting Esc and then tapping Ctrl+F5 again. +Instructions for creating and manually configuring this file are given in :ref:`configuring-emscripten-settings`. -llvm-clang and Emscripten compiler settings can be edited for the project in the "usual" Visual Studio fashion: First make sure that the Emscripten platform configuration is active, then right-click on a project, and choose Properties. In the Project properties dialog, two -tree nodes Clang C/C++ and Emcc Linker should exist, which allow you to specify the desired compilation options. + -If you have an existing solution file you want to build using Emscripten, open the Configuration Manager.. dialog for the solution, and in the Active Solution Platform dropdown, choose New.... In the new dialog, choose Emscripten as the platform name, and Copy settings from -Empty. After this, you can switch between building the solution for Win32 and Emscripten from the Configuration Manager dropdown list. +Validating the environment +=============================== -When you want to create a new Visual Studio project for Emscripten, we recommend you start with a Visual C++ Empty Project. This will create a new project for the Win32 platform. Then convert that project for Emscripten as outlined in the previous paragraph. +The best way to validate the environment is to build some code. Open the terminal in your *Emscripten* directory - the directory which contains *emcc* (if you installed using *Github for Windows* this will be **C:/Users/username/Documents/GitHub/emscripten**) and enter: :: -Building LLVM/Clang from Source -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + emcc tests/hello_world.cpp -In case the above-referenced prebuilt binaries do not work for you, you can build LLVM and Clang from source. +If this builds **a.out.js** in the current directory, and you don't see any build errors in the terminal, Emscripten is good to go! -To install and set up ``llvm-clang 3.2``, open a Visual Studio 2010 command prompt and type: +There are additional validation and troubleshooting instructions in the topic: :ref:`verifying-the-emscripten-environment`. -1. ``svn co http://llvm.org/svn/llvm-project/llvm/tags/RELEASE_32/final llvm`` -2. ``cd llvm\tools`` -3. ``svn co http://llvm.org/svn/llvm-project/cfe/tags/RELEASE_32/final clang`` -4. ``cd ..\\..`` -5. ``mkdir build`` -6. ``cd build`` -7. ``cmake -G "Visual Studio 10" ..\llvm`` -8. ``msbuild LLVM.sln /p:Configuration=Release`` -If you have problems with the above, see more help here: http://clang.llvm.org/get\_started.html -.. note:: Instead of checking out the trunk as the guide suggests, check out the latest tagged release of Clang (3.2 at the time of writing). An older version will not most likely work with Emscripten. diff --git a/site/source/docs/building_from_source/configuring_emscripten_settings.rst b/site/source/docs/building_from_source/configuring_emscripten_settings.rst new file mode 100644 index 0000000000000..3dcd2408535f5 --- /dev/null +++ b/site/source/docs/building_from_source/configuring_emscripten_settings.rst @@ -0,0 +1,104 @@ +.. _configuring-emscripten-settings: + +===================================================================================== +Configuring Emscripten Settings when Manually Building from Source (ready-for-review) +===================================================================================== + +.. note:: These instructions are are only useful if you are building Emscripten manually from source! If you're using the :ref:`SDK ` you should never manually update the settings, because the :ref:`emsdk` automatically overwrites the file with the appropriate compiler settings when you :term:`activate ` a tool or SDK. + +The compiler settings used by Emscripten are defined in the :ref:`compiler configuration file (~/.emscripten) `. These settings include paths to the tools (LLVM, Clang, Java etc.) and the compiler's temporary directory for intermediate build files. + +This article explains how to create and update the file when you are building Emscripten :ref:`manually ` from source. + + +Creating the compiler configuration file +======================================== + +The settings file is created the first time a user runs :ref:`emcc ` (or any of the other Emscripten tools): + +1. Navigate to the directory where you cloned the Emscripten repository. +2. Enter the command: + + :: + + ./emcc --help + + You should get a ``Welcome to Emscripten!`` message. Behind the scenes, Emscripten generated a file called ``.emscripten`` in your home folder. + + +Emscripten makes a "best guess" at the correct locations for tools and updates the file appropriately. Where possible it will look for "system" apps (like Python and Java) and infer the location of the ``EMSCRIPTEN_ROOT`` (where :ref:`emcc ` is located) from the location of the command prompt. + +The file will probably not include the link to :term:`Fastcomp` (``LLVM_ROOT``) as a manual source build can create this anywhere. + +Locating the compiler configuration file (.emscripten) +======================================================= + +The settings file is created in the user's home directory: + + - On Linux and Mac OS X this file is named **~/.emscripten**, where ~ is the user's home directory. + + .. note:: On Linux, files with the "." prefix are hidden by default. You may need to change your view settings to find the file. + + + - On Windows the file can be found at a path like: **C:/Users/yourusername_000/.emscripten**. + + +Compiler configuration file-format +================================== + +.. note:: While the syntax is identical, the appearance of the default **.emscripten** file created by *emcc* is quite different than that created by *emsdk* (see :ref:`here `). This is because *emsdk* manages multiple target environments, and where possible hard codes the locations of those tools when a new environment is activated. The default file, by contrast, only needs to manage a single environment, but needs to make it as easy for the user as possible to configure manually. + +The file simply assigns paths to a number of *variables* representing the the main tools used by Emscripten. For example, if the user cloned Emscripten to the **C:/Users/username/Documents/GitHub/emscripten** directory, then the file would have the line: :: + + EMSCRIPTEN_ROOT = 'C:/Users/username/Documents/GitHub/emscripten' + + +The default *emcc* configuration file often gets the paths from environment variables if defined. If no variable is defined the system will also attempt to find "system executables". For example: :: + + PYTHON = os.path.expanduser(os.getenv('PYTHON') or 'C:\\Python27\\python2.exe') + +You can find out the other variable names from the default *.emscripten* file or the :ref:`example here `. + +Editing the compiler configuration file +======================================= + +The compiler configuration file can be edited with the text-editor of your choice. As stated above, most default settings are likely to be correct. If you're building manually from source, you are most likely to have to update the variable ``LLVM_ROOT`` (for :term:`Fastcomp`). + + +#. Edit the variable ``LLVM_ROOT`` to point directly to the path where you :ref:`built Fastcomp `. This path is likely to be something like **/build/Release/bin** or /build/bin**, where ```` is wherever you cloned LVVM: + + :: + + LLVM_ROOT = 'os.path.expanduser(os.getenv('LVVM') or '/home/ubuntu/a-path/emscripten-fastcomp/build/bin')' + + .. note:: Use forward slashes! + +#. Edit the variable ``TEMP_DIR`` to point to a valid path on your local system, e.g. ``TEMP_DIR = '/tmp'`` (``TEMP_DIR = 'c:/tmp'`` on Windows), and create that folder on the local filesystem if it doesn't exist. + +#. You *may* need to edit the variable ``EMSCRIPTEN_ROOT`` to point to the Emscripten root folder, e.g.: + + :: + + EMSCRIPTEN_ROOT = os.path.expanduser(os.getenv('EMSCRIPTEN') or '/home/ubuntu/yourpath/emscripten') # directory + + +.. comment .. The settings are now correct in the configuration file, but the paths and environment variables are not set in the command prompt/terminal. **HamishW** Follow up with Jukka on htis. + +After setting those paths, run ``emcc`` again. It should again perform the sanity checks to test the specified paths. There are further validation tests in: :ref:`verifying-the-emscripten-environment`. + + + + + + + + + + + + + + + + + diff --git a/site/source/docs/building_from_source/index.rst b/site/source/docs/building_from_source/index.rst index cbeb98a5ddae3..7b0453bdd32b0 100644 --- a/site/source/docs/building_from_source/index.rst +++ b/site/source/docs/building_from_source/index.rst @@ -1,12 +1,18 @@ .. _installing-from-source: -====================================================================================== -Building Emscripten from Source (under-construction) -====================================================================================== +================================================== +Building Emscripten from Source (ready-for-review) +================================================== -Instead of using the SDK, you can grab the code and dependencies yourself. This is a little more technical but lets you use the very latest development code. +.. tip:: The *SDK* provides the **easiest** and **most reliable** method for **building from source**. Just :ref:`download the SDK ` and follow the brief instructions :ref:`here `. -The instructions for setting up Emscripten on each platform are given below, followed by guidance on how to validate your environment once it is complete: + This section is provided for developers who, for whatever reason, prefer a manual approach. + +.. note:: A user can't "manually " build from sources and use the SDK at the same time, because the SDK overwrites manual changes made to the user's :ref:`compiler configuration file `. + +This section shows how to get the source and dependencies and build Emscripten from sources. + +The instructions for building Emscripten on the different platforms are given below, followed by guidance on how to update the configuration file and validate your environment once it is complete: .. toctree:: :maxdepth: 1 @@ -14,8 +20,9 @@ The instructions for setting up Emscripten on each platform are given below, fol toolchain_what_is_needed building_emscripten_from_source_on_linux building_emscripten_from_source_on_windows + manually_integrating_emscripten_with_vs2010 building_emscripten_from_source_on_mac_os_x LLVM-Backend + configuring_emscripten_settings verify_emscripten_environment - diff --git a/site/source/docs/building_from_source/manually_integrating_emscripten_with_vs2010.rst b/site/source/docs/building_from_source/manually_integrating_emscripten_with_vs2010.rst new file mode 100644 index 0000000000000..da8a84bafcf79 --- /dev/null +++ b/site/source/docs/building_from_source/manually_integrating_emscripten_with_vs2010.rst @@ -0,0 +1,72 @@ +.. _emscripten-and-vs2010-manual-integration-on-windows: + +========================================================================== +Manually Integrating Emscripten into Visual Studio 2010 (ready-for-review) +========================================================================== + +.. tip:: The :term:`vs-tool` plugin is installed automatically by the :term:`Windows NSIS Installer Emscripten SDK` if *Visual Studio 2010* is present on the target system at install time. These instructions are only needed if you're :ref:`manually building from source `, or for some other reason cannot use the SDK. + +*vs-tool* is a *MSBuild* plugin that tells *Visual Studio* how to use the *Fastcomp* (LVVM + Clang) and Emscripten toolchain. The plugin allows existing Visual Studio **.sln** files to be directly built through the IDE using :ref:`emcc `. The Microsoft compiler property pages are replaced by *Fastcomp*- and *emcc*- specific options. + +The following instructions explain how to manually set up *vs-tool*. + +.. note:: `At time of writing `_ *vs-tool* only supports Visual Studio 2010. + +Install the vs-tool plugin +============================ + +1. Install Visual Studio 2010 + + .. note:: The Express version has not been tested, but should be work. :ref:`contact` if you have any problems integrating with VS2010 Express! + +#. Clone the juj/vs-tool repository from github: + + :: + + git clone https://github.com/juj/vs-tool + +#. Install vs-tool itself: + + #. Navigate to folder **vs-tool** in the repository clone. + #. Copy the folders **Clang** and **Emscripten** to **C:/Program Files (x86)/MSBuild/Microsoft.Cpp/v4.0/Platforms/**. + +#. Set up the required environment variables for *vs-tool*. + + #. Windows 7: Open **Control Panel | System | Advanced System Settings | Environment Variables**. + #. Create a new environment variable ``CLANG_BIN`` and set it to point to the folder where you built *Fastcomp* (path to **clang.exe**) E.g.: + + :: + + SETX CLANG_BIN C:/Projects/llvm-build/bin/Release + + This variable is how *vs-tool* locates the folder to your *Fastcomp* compiler. Alternatively, this path can be set on a per-project basis in the *Visual Studio project property* pages. + + #. Create a new environment variable ``EMSCRIPTEN`` and set it to point to the Emscripten git repository root folder (the path where you copied **emcc.exe** and the other exes). E.g.: + + :: + + SETX EMSCRIPTEN C:/Projects/emscripten + + This variable is how *vs-tool* locates the Emscripten compiler. This path can also be overridden on a per-project basis in the Visual Studio property pages. + + #. Create a new environment variable ``EMCC_WEBBROWSER_EXE`` and set it to point to an executable you want to use to browse in Emscripten-generated web pages from Visual Studio. This process is spawned when you tap **Start** (**Ctrl-F5**) in Visual Studio for an Emscripten-targeted project: + + :: + + SETX EMCC_WEBBROWSER_EXE C:/Program Files (x86)/Mozilla Firefox/firefox.exe + +#. Now you are all set to start developing Emscripten-based projects from *Visual Studio*. + +Test the installation +====================== + +To test the installation, open and build the Visual Studio solution file **/emscripten/tests/msvc10/tests_msvc10.sln**. + +That project builds a few select samples from inside the Emscripten **tests/** folder (for example "hello world", "hello gles", etc.), and is a good verification of the integration. + + +Learn more +========== + +There is a basic guide to using Emscripten from within Visual Studio in the :ref:`Getting Started ` section. + \ No newline at end of file diff --git a/site/source/docs/building_from_source/toolchain_what_is_needed.rst b/site/source/docs/building_from_source/toolchain_what_is_needed.rst index e777b4ab8401b..90a36dbb2e5e3 100644 --- a/site/source/docs/building_from_source/toolchain_what_is_needed.rst +++ b/site/source/docs/building_from_source/toolchain_what_is_needed.rst @@ -1,10 +1,14 @@ .. _emscripten-toolchain-top: -============================================================ -Emscripten Toolchain (under-construction) -============================================================ +======================================= +Emscripten Toolchain (ready-for-review) +======================================= -The :ref:`SDKs ` deliver (or explain how to obtain) everything you need for developing with Emscripten. However if you're building from source you'll need to gather the tools below yourself. +The instructions below list the main tools and dependencies in an Emscripten environment, along with instructions on how to test which dependencies are installed. + +.. tip:: The :ref:`SDK ` provides the **easiest** and **most reliable** method for getting, using, updating and managing Emscripten environments, including **building from source**. If you're using the SDK you won't *need* these instructions, and they are provided for information only. + + The instructions are useful if you're :ref:`manually ` building from source. .. _toolchain-what-you-need: @@ -22,7 +26,7 @@ A complete Emscripten environment includes the following tools: .. note: 64-bit versions of all needed dependencies are preferred, and may be required if you are building large projects. -When building from sources you will also need a compiler environment (to build :ref:`Fastcomp `): +When building manually from sources you will also need a compiler environment (to build :ref:`Fastcomp `): - *gcc* (4.6 or later) @@ -31,7 +35,7 @@ When building from sources you will also need a compiler environment (to build : .. _toolchain-test-which-dependencies-are-installed: Test which tools are installed -==================================== +============================== Some of the tools are pre-installed on the various platforms (for example, Python is always available on Linux builds). diff --git a/site/source/docs/building_from_source/verify_emscripten_environment.rst b/site/source/docs/building_from_source/verify_emscripten_environment.rst index bde44d726fd4f..a15fb2ce74a7b 100644 --- a/site/source/docs/building_from_source/verify_emscripten_environment.rst +++ b/site/source/docs/building_from_source/verify_emscripten_environment.rst @@ -10,9 +10,12 @@ Verifying the Emscripten Development Environment (ready-for-review) Testing the environment ======================= -The first step in verifying the environment is to run Emscripten with the version command (``-v``). +Sanity tests +------------ -Open a terminal in the directory in which you installed Emscripten (on Windows open the :ref:`Emscripten Command Prompt `). Then call the :ref:`Emscripten Compiler Frontend (emcc) ` as shown: +The first step in verifying the environment is to run Emscripten with the version command (``-v``). The command prints out information about the toolchain and runs some basic sanity tests to check that required tools are available. + +Open a terminal in the directory in which you installed Emscripten (on Windows open the :ref:`Emscripten Command Prompt `). Then call the :ref:`Emscripten Compiler Frontend (emcc) ` as shown: :: @@ -20,7 +23,7 @@ Open a terminal in the directory in which you installed Emscripten (on Windows o .. note:: On Windows, invoke the tool with **emsdk** instead of **./emsdk**: -The command prints out information about the toolchain and runs some basic sanity checks. For example, the following output reports an installation where Java is missing: +For example, the following output reports an installation where Java is missing: .. code-block:: javascript :emphasize-lines: 6 @@ -36,15 +39,25 @@ At this point you need to :ref:`Install and activate `, see that link for information on how to obtain all dependencies. Other common problems -+++++++++++++++++++++++++ +--------------------- Other common problems to check for are: @@ -81,7 +94,7 @@ Other common problems to check for are: - Using older versions of LLVM. The correct versions come with the SDK, but if you're building the environment from source see :ref:`LLVM-Backend` for the proper repos for LLVM and Clang. - Not having *python2* defined in your system. For compatibility with systems that install python 2.x alongside 3.x, we look for *python2*. If you only have python 2.x installed, symlink *python2* to *python* and update :ref:`.emscripten `. You can also invoke the python scripts directly: :: - ``python emcc`` + python emcc .. COMMENT:: **HamishW** Need to clarify if this last point on Python2 is Linux/Mac only, and if not, what needs to be done on Windows. diff --git a/site/source/docs/getting_started/Tutorial.rst b/site/source/docs/getting_started/Tutorial.rst index 1677cdcaa658d..0d4637b31ee19 100644 --- a/site/source/docs/getting_started/Tutorial.rst +++ b/site/source/docs/getting_started/Tutorial.rst @@ -15,7 +15,7 @@ First things first Make sure you have :ref:`downloaded and installed ` Emscripten (the exact approach for doing this will depend your operating system: Windows, Mac or Linux). -Emscripten is accessed using the :ref:`emcc `. This script invokes all the other tools needed to build your code, and can act as a drop-in replacement for a standard compiler like *gcc*. It is called on the command line using ``emcc`` or ``em++`` +Emscripten is accessed using the :ref:`emcc `. This script invokes all the other tools needed to build your code, and can act as a drop-in replacement for a standard compiler like *gcc*. It is called on the command line using ``emcc`` or ``em++`` .. note:: On Mac OS X the tool is called using the slightly different syntax: ``./emcc`` or ``./em++`` (or even directly via Python: ``python emcc``). The remainder of this tutorial uses the Windows syntax (``emcc``). diff --git a/site/source/docs/getting_started/downloads.rst b/site/source/docs/getting_started/downloads.rst index 05ab22392e9a1..2851ff24b767c 100644 --- a/site/source/docs/getting_started/downloads.rst +++ b/site/source/docs/getting_started/downloads.rst @@ -6,7 +6,7 @@ Download and install (ready-for-review) .. note:: The *Emscripten SDK* provides the whole Emscripten toolchain (*Clang*, *Python*, *Node.js* and *Visual Studio* integration) in a single easy-to-install package, with integrated support for :ref:`updating to newer SDKs ` as they are released. -.. tip:: If you are :doc:`contributing <../contributing/contributing>` to Emscripten you should :ref:`set up Emscripten from source `. +.. tip:: If you are :ref:`contributing ` to Emscripten you should first install the SDK, and then use it to :ref:`build Emscripten from source `. SDK Downloads @@ -14,6 +14,8 @@ SDK Downloads Download one of the SDK installers below to get started with Emscripten development. The Windows NSIS installers are the easiest to set up, while the portable SDKs can be moved between computers and do not require administration privileges. +.. emscripten-sdk-windows-installers: + Windows ------- @@ -101,8 +103,9 @@ Mac OS X Java is not installed. To open Java, you need a Java SE 6 runtime. Would you like to install one now? -- The *python2* command line tool is not present on OSX by default. To manually work around this issue, follow step 10 in :ref:`Getting started on Mac OS X `. +- The *python2* command line tool is not present on OSX by default. To manually work around this issue, follow the linked step in :ref:`Getting started on Mac OS X `. +.. **HamishW**: I think that Mac OS X has the same issues as Linux - ie you don't get ANYTHING much in the SDK. YOu will need the command line tools, but mostly for GCC - need to confirm this with Jukka Linux ++++++++ @@ -124,6 +127,58 @@ The easiest way to verify the installation is to compile some code using Emscrip You can jump ahead to the :ref:`Tutorial`, but if you have any problems building you should run through the basic tests and troubleshooting instructions in :ref:`verifying-the-emscripten-environment`. +.. _sdk-building-emscripten-from-source: + +Building Emscripten from source +====================================================== + +The SDK can be used to fetch and build the latest version of Emscripten from source. This allows you to obtain new features and the latest fixes as soon as they are pushed to Github (without having to wait for release to be tagged). **No Github account or fork of Emscripten is required!** + +.. note:: The SDK is the recommended method of building Emscripten from source because it makes the process very easy, and allows you to treat the build as "just another SDK". Using the SDK allows you to easily toggle between the current SDK, older SDKs, and source-built environments, and to update to new SDKs and source updates as they become available. + + It is also possible to :ref:`manually build from sources `, but this approach is more difficult, incompatible with the :ref:`SDK manager `, and not really needed! + +You will also need a compiler toolchain to build from source: + + - On Windows install `gcc 4.6 `_ + - On Linux install *gcc* from the **build-essential** package: + + :: + + sudo apt-get install build-essential + + - On Mac OS X install the *XCode Command Line Tools*: + + - Install XCode from the `Mac OS X App Store `_. + - In **XCode | Preferences | Downloads**, install *Command Line Tools*. + +To switch to using the latest upstream git development branch (``incoming``), run the following commands: + +:: + + # Install latest git client. Skip if the system already has it. + ./emsdk install git-1.8.3 + + # Clone+pull the latest kripken/emscripten/incoming. + ./emsdk install sdk-incoming-64bit + + # Set the "incoming SDK" as the active version. + ./emsdk activate sdk-incoming-64bit + +If you want to use the upstream stable branch ``master``, then replace ``-incoming-`` with ``-master-`` in the commands above. + +.. note:: On Windows, *git* may fail with the error message: + + :: + + Unable to find remote helper for 'https' when cloning a repository with https:// url. + + The workaround is to uninstall git from *emsdk* (``emsdk uninstall git-1.8.3``) and install `Git for Windows `_. This issue is reported `here `_. + +.. todo:: **HamishW** Check whether the bug (https://github.com/juj/emsdk/issues/13) is fixed and remove the above note if it is. + +It is also possible to build your :ref:`own fork of the Emscripten using the SDK `. + .. _updating-the-emscripten-sdk: Updating the SDK diff --git a/site/source/docs/getting_started/getting_started_with_emscripten_and_vs2010.rst b/site/source/docs/getting_started/getting_started_with_emscripten_and_vs2010.rst new file mode 100644 index 0000000000000..249ba6ebeb206 --- /dev/null +++ b/site/source/docs/getting_started/getting_started_with_emscripten_and_vs2010.rst @@ -0,0 +1,19 @@ +.. getting-started-emscripten-from-vs2010: + +=========================================================================================== +Getting started using Emscripten from the Visual Studio 2010 IDE (under-construction) +=========================================================================================== + + +To build a Visual Studio solution using the Emscripten toolchain, select the "Emscripten" configuration from the Configuration Manager dropdown as the active configuration, and choose Build Solution (F7). + +To launch a project directly to a web browser from Visual Studio, right-click on the project to run, choose "Set as Startup Project", and select Start without Debugging (Ctrl+F5). This should launch the generated .html file to the browser you specified in EMCC\_WEBBROWSER\_EXE. A bug(?) in Visual Studio causes a "Executable for Debug Session" dialog to occasionally open up when you hit Ctrl+F5. This can be ignored by clicking Yes, then No, or simply by hitting Esc and then tapping Ctrl+F5 again. + +llvm-clang and Emscripten compiler settings can be edited for the project in the "usual" Visual Studio fashion: First make sure that the Emscripten platform configuration is active, then right-click on a project, and choose Properties. In the Project properties dialog, two +tree nodes Clang C/C++ and Emcc Linker should exist, which allow you to specify the desired compilation options. + +If you have an existing solution file you want to build using Emscripten, open the Configuration Manager.. dialog for the solution, and in the Active Solution Platform dropdown, choose New.... In the new dialog, choose Emscripten as the platform name, and Copy settings from +Empty. After this, you can switch between building the solution for Win32 and Emscripten from the Configuration Manager dropdown list. + +When you want to create a new Visual Studio project for Emscripten, we recommend you start with a Visual C++ Empty Project. This will create a new project for the Win32 platform. Then convert that project for Emscripten as outlined in the previous paragraph. + diff --git a/site/source/docs/getting_started/index.rst b/site/source/docs/getting_started/index.rst index 799cbfe1470f1..0fb93dd37c683 100644 --- a/site/source/docs/getting_started/index.rst +++ b/site/source/docs/getting_started/index.rst @@ -8,3 +8,4 @@ Getting Started (under-construction) downloads Tutorial + getting_started_with_emscripten_and_vs2010 diff --git a/site/source/docs/tools_reference/emcc.rst b/site/source/docs/tools_reference/emcc.rst index a67de986592b7..5ad94ed3ed0bc 100644 --- a/site/source/docs/tools_reference/emcc.rst +++ b/site/source/docs/tools_reference/emcc.rst @@ -1,5 +1,4 @@ - -.. _emcc: +.. _emccdoc: ========================================================= Emscripten Compiler Frontend (emcc) (under-construction) diff --git a/site/source/docs/tools_reference/emsdk.rst b/site/source/docs/tools_reference/emsdk.rst index e0af1cf4e28a7..1137f18f9605f 100644 --- a/site/source/docs/tools_reference/emsdk.rst +++ b/site/source/docs/tools_reference/emsdk.rst @@ -11,14 +11,14 @@ This document provides the command syntax, and a :ref:`set of guides ` in development on Github. To access the *emsdk*, first launch the :ref:`Emscripten Command Prompt `. Most operations are of the form ``emsdk command``. +With *emsdk* you can download, install or remove *any* :term:`SDK` or :term:`Tool`, and even use the :ref:`bleeding edge versions ` in development on Github. To access the *emsdk*, first launch the :ref:`Emscripten Command Prompt `. Most operations are of the form ``./emsdk command``. Command line syntax ============================================ -**emsdk** [**help** [**--old**] | **list** | **update** | **install** ** | **uninstall** ** | **activate** **] +**./emsdk** [**help** [**--old**] | **list** | **update** | **install** ** | **uninstall** ** | **activate** **] Arguments @@ -41,13 +41,13 @@ Arguments * - ``uninstall `` - Removes the :ref:`specified tool or SDK ` from the disk. * - ``activate `` - - Sets the :ref:`specified tool or SDK ` as the default tool in the system environment. + - Sets the :ref:`specified tool or SDK ` as the default tool in the system environment. On Linux you additionally have to enable the environment settings using ``source ./emsdk_env.sh``, as described in ":ref:`emsdk-set-active-tools`". * - ``help`` - Lists all supported commands. The same list is output if no command is specified. .. note:: - - For Mac OSX the commands are called with **./emsdk**. + - For Mac OSX the commands are called with **./emsdk**. On Windows use **emsdk**. - **emcmdprompt.bat** is also displayed as an option in the ``emsdk help``. This is :ref:`not intended ` to be called through the command line. @@ -82,11 +82,11 @@ The *Compiler Configuration File* stores the :term:`active ` co The configuration file is named **.emscripten**. It is user-specific, and is located in the user's home directory (**~/.emscripten** on Linux). -The file should not be updated directly. Instead use the *emsdk* to activate specific SDKs and tools as needed (``emsdk activate ``). +The file should generally not be updated directly unless you're :ref:`building Emscripten from source `. Instead use the *emsdk* to activate specific SDKs and tools as needed (``emsdk activate ``). -Below is a typical **.emscripten** file, taken from a user's root directory on Windows: +Below is a typical **.emscripten** file (created by *emsdk*), taken from a user's root directory on Windows. Note the variable names used to point to the different tools: -.. todo:: **HamishW** When I've fully tested on ubuntu perhaps include the file from there (since Linux is the most used platform. +.. todo:: **HamishW** When I've fully tested on ubuntu perhaps include the file from there (since Linux is the most used platform). :: @@ -122,20 +122,20 @@ How do I just get the latest SDK? Use the ``update`` argument to fetch the current registry of available tools, and then specify the ``latest`` install target to get the most recent SDK: :: # Fetch the latest registry of available tools. - emsdk update + ./emsdk update # Download and install the latest SDK tools. - emsdk install latest + ./emsdk install latest # Set up the compiler configuration to point to the "latest" SDK. - emsdk activate latest + ./emsdk activate latest How do I use emsdk? -------------------------------- -Use ``emsdk help`` or just ``emsdk`` to get information about all available commands. +Use ``./emsdk help`` or just ``./emsdk`` to get information about all available commands. How do I check which versions of the SDK and tools are installed? @@ -143,7 +143,7 @@ How do I check which versions of the SDK and tools are installed? To get a list of all currently installed tools and SDK versions (and all available tools) run: :: - emsdk list + ./emsdk list A line will be printed for each tool and SDK that is available for installation. The text ``INSTALLED`` will be shown for each tool that has already been installed. If a tool/SDK is currently active, a star (\*) will be shown next to it. @@ -153,7 +153,9 @@ How do I install a tool/SDK version? Use the ``install`` argument to download and install a new tool or SDK version: :: - emsdk install + ./emsdk install + +.. note:: An installed tool is present on the local machine, but not necessarily the active environment. To make an installed SDK active, use the ``activate`` command. .. _emsdk-remove-tool-sdk: @@ -163,7 +165,7 @@ How do I remove a tool or an SDK? Use the ``uninstall`` argument to delete a given tool or SDK from the local computer: :: - emsdk uninstall + ./emsdk uninstall If you want to completely remove Emscripten from your system, follow the guide at :ref:`downloads-uninstall-the-sdk`. @@ -175,18 +177,27 @@ How do I check for updates to the Emscripten SDK? First use the ``update`` command to fetch package information for all new tools and SDK versions. Then use ``install `` to install a new version: :: # Fetch the latest registry of available tools. - emsdk update + ./emsdk update # Download and install the specified new version. - emsdk install + ./emsdk install + +.. _emsdk-set-active-tools: How do I change the currently active SDK version? ---------------------------------------------------------------- Toggle between different tools and SDK versions using the :term:`activate ` command. This will set up ``~/.emscripten`` to point to that particular tool: :: - emsdk activate + ./emsdk activate + + # On Linux and OSX, also set the environment variables. + source ./emsdk_env.sh + +.. note:: On Linux and Mac OS X, ``activate`` writes the required information to the configuration file, but cannot automatically set up the environment variables in the current terminal. To do this you need to call **/emsdk_env.sh** with the source prefix after calling ``activate``. The use of ``source`` is a security feature of Unix shells. + + On Windows, calling ``activate`` automatically sets up the required paths and environment variables. How do I install an old Emscripten compiler version? @@ -194,8 +205,8 @@ How do I install an old Emscripten compiler version? *Emsdk* contains a history of old compiler versions that you can use to maintain your migration path. Use the ``list --old`` argument to get a list of archived tool and SDK versions, and ``install `` to install it: :: - emsdk list --old - emsdk install + ./emsdk list --old + ./emsdk install On Windows, you can directly install an old SDK version by using one of :ref:`these archived NSIS installers `. @@ -213,13 +224,13 @@ To switch to using the latest upstream git development branch (``incoming``), ru :: # Install git. Skip if the system already has it. - emsdk install git-1.8.3 + ./emsdk install git-1.8.3 # Clone+pull the latest kripken/emscripten/incoming. - emsdk install sdk-incoming-64bit + ./emsdk install sdk-incoming-64bit # Set the "incoming SDK" as the active version. - emsdk activate sdk-incoming-64bit + ./emsdk activate sdk-incoming-64bit If you want to use the upstream stable branch ``master``, then replace ``-incoming-`` with ``-master-`` in the commands above. @@ -233,6 +244,7 @@ If you want to use the upstream stable branch ``master``, then replace ``-incomi .. todo:: **HamishW** Check whether the bug (https://github.com/juj/emsdk/issues/13) is fixed and remove the above note if it is. +.. _emsdk-howto-use-own-fork: How do I use my own Emscripten Github fork with the SDK? ---------------------------------------------------------------- From 44087597f74e75580312cc933b18e0e4caa643a6 Mon Sep 17 00:00:00 2001 From: hamishwillee Date: Mon, 11 Aug 2014 20:38:08 +1000 Subject: [PATCH 15/91] fix horrible sentence on index page --- site/source/docs/building_from_source/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/source/docs/building_from_source/index.rst b/site/source/docs/building_from_source/index.rst index 7b0453bdd32b0..e22e71b48c20d 100644 --- a/site/source/docs/building_from_source/index.rst +++ b/site/source/docs/building_from_source/index.rst @@ -10,7 +10,7 @@ Building Emscripten from Source (ready-for-review) .. note:: A user can't "manually " build from sources and use the SDK at the same time, because the SDK overwrites manual changes made to the user's :ref:`compiler configuration file `. -This section shows how to get the source and dependencies and build Emscripten from sources. +This section shows how to get the source and dependencies and manually build the Emscripten toolchain. The instructions for building Emscripten on the different platforms are given below, followed by guidance on how to update the configuration file and validate your environment once it is complete: From 64d37910b817680762997b24c4f8d7435609e092 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jukka=20Jyl=C3=A4nki?= Date: Mon, 11 Aug 2014 15:48:30 +0300 Subject: [PATCH 16/91] Updated ChangeLog up to v1.22.1 --- ChangeLog | 163 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 160 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index a3a2bfded24da..8824e813bc8a6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -10,9 +10,166 @@ Not all changes are documented here. In particular, new features, user-oriented Current trunk code ------------------ - To see a list of commits in the active development branch 'incoming', which have not yet been packaged in a release, see - - Emscripten: https://github.com/kripken/emscripten/compare/1.21.1...incoming - - Emscripten-LLVM: https://github.com/kripken/emscripten-fastcomp/compare/1.21.1...incoming - - Emscripten-Clang: https://github.com/kripken/emscripten-fastcomp-clang/compare/1.21.1...incoming + - Emscripten: https://github.com/kripken/emscripten/compare/1.22.1...incoming + - Emscripten-LLVM: https://github.com/kripken/emscripten-fastcomp/compare/1.22.1...incoming + - Emscripten-Clang: https://github.com/kripken/emscripten-fastcomp-clang/compare/1.22.1...incoming + +v1.22.1: 8/7/2014 +------------------ + - Added support for prefixing functions with '$' in JS libraries, in order to cause them not be prefixed with '_' when compiling. + - Improved WebIDL compiler to support enums. + - Fixed a bug with emscripten_force_exit() that would throw an exception (#2629). + - Fixed setlocale() when setting a bad locale. (#2630) + - Fixed a compiler miscompilation bug when optimizing loops. (#2626) + - Fixed an issue with rethrowing an exception (#2627) + - Fixed a bug where malloc()ing from JS code would leak memory if the C/C++ side does not use malloc() (#2621) + - Removed an unnecessary assert() in glReadPixels, and improved it to support more texture pixel types. + - Fixed a bug with std::locale accepting unknown locale names (#2636) + - Added support for WebIDL binder to work with Closure (#2620) + - Added no-op SDL IMG_Quit() and TTF_Quit() symbols. + - Migrated to building libcxx and libcxxapi with -Oz optimization flags. + - Full list of changes: + - Emscripten: https://github.com/kripken/emscripten/compare/1.22.0...1.22.1 + - Emscripten-LLVM: no changes. + - Emscripten-Clang: no changes. + +v1.22.0: 8/5/2014 +------------------ + - Added support to emrun to dump files to the local filesystem for debugging purposes. + - Implemented emscripten_wget in ASYNCIFY mode. + - Improved extension catching support (#2616) + - Fixed .a link groups to also work when linking to bitcode. (#2568) + - Full list of changes: + - Emscripten: https://github.com/kripken/emscripten/compare/1.21.10...1.22.0 + - Emscripten-LLVM: https://github.com/kripken/emscripten-fastcomp/compare/1.21.10...1.22.0 + - Emscripten-Clang: no changes. + +v1.21.10: 7/29/2014 +------------------- + - Fixed a Windows-specific issue where the generated output files might contain line endings of form \r\r\n. This caused browser debuggers to get confused with line numbers. (#2133) + - Improved the node.js workaround introduced in v1.21.8. + - Implemented new HTML5 API for direct WebGL context creation, emscripten_webgl_*(). + - Fixed a bug when loading in node.js and loaded by another module (#2586) + - Full list of changes: + - Emscripten: https://github.com/kripken/emscripten/compare/1.21.9...1.21.10 + - Emscripten-LLVM: no changes. + - Emscripten-Clang: no changes. + +v1.21.9: 7/28/2014 +------------------ + - Fixed issues with exception catching. (#2531) + - Full list of changes: + - Emscripten: https://github.com/kripken/emscripten/compare/1.21.8...1.21.9 + - Emscripten-LLVM: no changes. + - Emscripten-Clang: no changes. + +v1.21.8: 7/28/2014 +------------------ + - Fixed an issue when using --embed-file to embed very large files. + - Worked around a Windows node.js bug where the compiler output might get cut off when the compilation ends in an error. (https://github.com/joyent/node/issues/1669) + - Full list of changes: + - Emscripten: https://github.com/kripken/emscripten/compare/1.21.7...1.21.8 + - Emscripten-LLVM: https://github.com/kripken/emscripten-fastcomp/compare/1.21.7...1.21.8 + - Emscripten-Clang: no changes. + +v1.21.7: 7/25/2014 +------------------ + - Added new link option -s EMCC_ONLY_FORCED_STDLIBS which can be used to restrict to only linking to the chosen set of Emscripten-provided libraries. (See also -s EMCC_FORCE_STDLIBS) + - Adjusted argv[0] and environment variables USER, HOME, LANG and _ to report a more convenient set of default values. (#2565) + - Fixed an issue where the application could not use environ without also referring to getenv() (#2557) + - Fixed an issue with IDBFS running in web workers. + - Print out an error if IDBFS is used without IDB support. + - Fixed calling Runtime.getFuncWrapper() when -s ALIASING_FUNCTION_POINTERS=1 (#2010) + - Fixed an issue where deleting files during directory iteration would produce incorrect iteration results (#2528) + - Fixed support for strftime with %z and %Z (#2570) + - Fixed a bug with truncate() throwing an exception (#2572) + - Improved the linker to generate warning messages if user specifies -s X=Y linker flags that do not exist (#2579) + - Fixed an issue with creating read-only files (#2573) + - Added first implementation for the ASYNCIFY option, which splits up synchronous blocking loops to asynchronous execution. For more information on this approach, see https://github.com/kripken/emscripten/wiki/Asyncify + - Full list of changes: + - Emscripten: https://github.com/kripken/emscripten/compare/1.21.6...1.21.7 + - Emscripten-LLVM: https://github.com/kripken/emscripten-fastcomp/compare/1.21.6...1.21.7 + - Emscripten-Clang: no changes. + +v1.21.6: 7/22/2014 +------------------ + - Separated OpenAL AL and ALC errors to properly separate fields. + - When using EGL to initialize a GL context, initialize a stencil buffer to the context as well, since proper EGL context choosing is not yet implemented. + - Added new linker flag -s DEMANGLE_SUPPORT to choose whether to compile the application with libcxxabi-provided demangling support ___cxa_demangle(). + - Fixed a problem where calling stat() on a nonexisting file in the runtime VFS would result in an exception being thrown. (#2552) + - When using the -v flag, no longer retain intermediate compilation files. To preserve the intermediate files, set the EMCC_DEBUG=1 environment variable. (#2538) + - Added a new HTML setting Module.memoryInitializerPrefixURL which specifies a prefix for where the memory initializer file .mem.js should be loaded from (#2542) + - Implemented eglReleaseThread to work according to spec. + - Implemented a new function emscripten_force_exit() which immediately shuts down the C runtime. + - Fixed a bug with exception handling that resulted in an error unresolved symbol: _ZTISt13bad_exception (#2560) + - Full list of changes: + - Emscripten: https://github.com/kripken/emscripten/compare/1.21.5...1.21.6 + - Emscripten-LLVM: no changes. + - Emscripten-Clang: no changes. + +v1.21.5: 7/21/2014 +------------------ + - Added support for glDrawBuffers with the WEBGL_draw_buffers extension. + - Added stub implementation for eglReleaseThread. + - Fixed a bug where passing -E to emcc used the system include headers instead of the built-in ones. (#2534) + - Fixed the stacktrace() function to work on MSIE as well. + - Removed the zlib.h header file from system include directory, since Emscripten does not provide an implementation of zlib built-in. + - Added support for __cxa_bad_typeid (#2547) + - Fixed an internal compiler crash with a certain pattern involving optimized builds and int64_t (#2539) + - Fixed an issue with -s EXCEPTION_CATCHING_WHITELIST handling where an extension that was a substring of another might get erroneously handled. + - Full list of changes: + - Emscripten: https://github.com/kripken/emscripten/compare/1.21.4...1.21.5 + - Emscripten-LLVM: https://github.com/kripken/emscripten-fastcomp/compare/1.21.4...1.21.5 + - Emscripten-Clang: no changes. + +v1.21.4: 7/17/2014 +------------------ + - Implemented the getsockopt() function. + - Added new event callback functions emscripten_set_socket_xx_callback() that allow listening to WebSocket events in an asynchronous manner. + - Greatly improved CMake support, now various forms of configure-time test builds are supported, and the default extension is set to ".js" + - Prohibit the virtual filesystem from creating files with name '.' or '..' at runtime. + - Have runtime mkdir() function call normalize the path to be created before creation. + - Fixed an issue with omitting the third paramter in cwrap() call (#2511). + - Fixed an issue where mouse event handling would throw an exception if the page did not contain a canvas object. + - Fixed a GL initialization problem when user has extended Array with custom functions (#2514) + - Added new compiler defines __EMSCRIPTEN_major__, __EMSCRIPTEN_minor__ and __EMSCRIPTEN_tiny__ which communicate the compiler version major.minor.tiny to compiled applications (#2343) + - Fixed a bug where emrun did not properly capture the exit code when exit runtime via not calling exit(). + - Fixed an error message when symlinkin invalid filenams at runtime. + - Fixed a bug in EGL context creation that parsed the input context creation parameters with wrong terminator. + - Improved ffdb.py to be smarter when to attempt port forwarding to connect to a FFOS device DevTools port. + - Implemented strsignal() function (#2532) + - Full list of changes: + - Emscripten: https://github.com/kripken/emscripten/compare/1.21.3...1.21.4 + - Emscripten-LLVM: no changes. + - Emscripten-Clang: no changes. + +v1.21.3: 7/10/2014 +------------------ + - Added implementations for SDL function SDL_AudioQuit and SDL_VideoQuit. + - Fix an issue with the optimizeShifts optimization enabled in previous version. + - Fixed the -s RELOOPER command line parameter to work. + - Fixed a bug where building the system libc migt result in a compiler deadlock on Windows. + - Removed emcc from trying to link in .dll files as static libraries on Windows. + - Added support for GL_HALF_FLOAT_OES. + - Fixed a bug where emcmake did not work on Windows. + - Use multithreaded compilation to build libc. + - Fixed an issue where the GL interop library could throw an exception in an error condition, instead of raising a GL error. + - Full list of changes: + - Emscripten: https://github.com/kripken/emscripten/compare/1.21.2...1.21.3 + - Emscripten-LLVM: no changes. + - Emscripten-Clang: no changes. + +v1.21.2: 7/5/2014 +------------------ + - Improved the checks that detect that code is run only while the runtime is initialized. + - The memory initializer file (.mem.js) is now emitted by default when compiling with at least -O2 optimization level. + - Fixed a performance issue where built-in math functions (Math.sqrt, etc.) took a slightly slower path (#2484). + - Added support for the ffs libc function. + - Re-enabled optimizeShifts optimization when not compiling for asm.js (#2481) + - Full list of changes: + - Emscripten: https://github.com/kripken/emscripten/compare/1.21.1...1.21.2 + - Emscripten-LLVM: no changes. + - Emscripten-Clang: no changes. v1.21.1: 7/3/2014 ------------------ From bff7dd6cb6b77396afff54002baba91ceb6b6cae Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 11 Aug 2014 11:15:57 -0700 Subject: [PATCH 17/91] docs updates following #2650 --- .../source/docs/building_from_source/LLVM-Backend.rst | 11 +++++++---- site/source/docs/building_from_source/index.rst | 2 +- .../building_from_source/toolchain_what_is_needed.rst | 4 ++-- site/source/docs/getting_started/downloads.rst | 2 +- 4 files changed, 11 insertions(+), 8 deletions(-) diff --git a/site/source/docs/building_from_source/LLVM-Backend.rst b/site/source/docs/building_from_source/LLVM-Backend.rst index defc508b1c11b..743dc2b93800b 100644 --- a/site/source/docs/building_from_source/LLVM-Backend.rst +++ b/site/source/docs/building_from_source/LLVM-Backend.rst @@ -50,7 +50,7 @@ To use fastcomp, you need both Emscripten (see the :ref:`Tutorial`) and the Emsc cd tools git clone https://github.com/kripken/emscripten-fastcomp-clang clang - .. warning:: You **must** clone it into a dir named "clang", so that clang is present in **tools/clang**! + .. warning:: You **must** clone it into a dir named "clang" (as is done by that command), so that clang is present in **tools/clang**! .. note:: This repo has changed. Early in fastcomp development we used a different directory. @@ -88,7 +88,7 @@ To use fastcomp, you need both Emscripten (see the :ref:`Tutorial`) and the Emsc .. _llvm-update-compiler-configuration-file: -- Update the :ref:`~/.emscripten `, specifying the location of *fastcomp* in using the ``LLVM_ROOT`` variable. The path should be set to the location of the *clang* binary under the **build** directory. This will be something like **/build/Release/bin** or **/build/bin**: +- Update the :ref:`~/.emscripten ` file, specifying the location of *fastcomp* in using the ``LLVM_ROOT`` variable. The path should be set to the location of the *clang* binary under the **build** directory. This will be something like **/build/Release/bin** or **/build/bin**: :: @@ -113,8 +113,11 @@ to synchronize points between them, which helps. - emscripten-version.txt in fastcomp (llvm) - emscripten-version.txt in fastcomp-clang (clang) -Version numbers are typically X.Y.Z where X is a major number (changes very rarely), Y is a release number (changes each time we merge incoming to master, so these numbers indicate points where all tests passed) and Z is minor update that is just a sync point between the repos, or is needed when libc changes in emscripten (version changes clear the -cache). +Version numbers are typically X.Y.Z where + +- X is a major number (changes very rarely) +- Y is a release number (changes each time we merge incoming to master, so these numbers indicate points where all tests passed), and +- Z is minor update that is just a sync point between the repos, or is needed when libc changes in emscripten (version changes clear the cache). Compilation Notes ~~~~~~~~~~~~~~~~~ diff --git a/site/source/docs/building_from_source/index.rst b/site/source/docs/building_from_source/index.rst index e22e71b48c20d..374fc3077542c 100644 --- a/site/source/docs/building_from_source/index.rst +++ b/site/source/docs/building_from_source/index.rst @@ -6,7 +6,7 @@ Building Emscripten from Source (ready-for-review) .. tip:: The *SDK* provides the **easiest** and **most reliable** method for **building from source**. Just :ref:`download the SDK ` and follow the brief instructions :ref:`here `. - This section is provided for developers who, for whatever reason, prefer a manual approach. + This section is provided for developers who prefer a manual approach and/or are contributing to Emscripten development. .. note:: A user can't "manually " build from sources and use the SDK at the same time, because the SDK overwrites manual changes made to the user's :ref:`compiler configuration file `. diff --git a/site/source/docs/building_from_source/toolchain_what_is_needed.rst b/site/source/docs/building_from_source/toolchain_what_is_needed.rst index 90a36dbb2e5e3..aff71252eac2c 100644 --- a/site/source/docs/building_from_source/toolchain_what_is_needed.rst +++ b/site/source/docs/building_from_source/toolchain_what_is_needed.rst @@ -21,7 +21,7 @@ A complete Emscripten environment includes the following tools: - :term:`Python` 2.x (2.7.3 or above preferred) - :term:`Java` (1.6.0_31 or later). Java is optional. It is required to use the :term:`Closure Compiler` (in order to minify your code). - :term:`Git` client. Git required if building tools from source. - - :term:`Fastcomp` (Emscripten's LLVM and Clang) + - :term:`Fastcomp` (Emscripten's fork of LLVM and Clang) - The `Emscripten code `_, from GitHub .. note: 64-bit versions of all needed dependencies are preferred, and may be required if you are building large projects. @@ -30,7 +30,7 @@ When building manually from sources you will also need a compiler environment (t - *gcc* (4.6 or later) -.. note:: The *Spidermonkey* shell is also required if you want to run **all** the test code. Most developers will not need this, and should use *node.js*. +.. note:: The *Spidermonkey* shell is also required if you want to run **100%** of the tests in the test suite. Most developers will not need this, and need only *node.js*. .. _toolchain-test-which-dependencies-are-installed: diff --git a/site/source/docs/getting_started/downloads.rst b/site/source/docs/getting_started/downloads.rst index 2851ff24b767c..9de09838c99de 100644 --- a/site/source/docs/getting_started/downloads.rst +++ b/site/source/docs/getting_started/downloads.rst @@ -136,7 +136,7 @@ The SDK can be used to fetch and build the latest version of Emscripten from sou .. note:: The SDK is the recommended method of building Emscripten from source because it makes the process very easy, and allows you to treat the build as "just another SDK". Using the SDK allows you to easily toggle between the current SDK, older SDKs, and source-built environments, and to update to new SDKs and source updates as they become available. - It is also possible to :ref:`manually build from sources `, but this approach is more difficult, incompatible with the :ref:`SDK manager `, and not really needed! + It is also possible to :ref:`manually build from source `, but this approach is more difficult, incompatible with the :ref:`SDK manager `, and in general not really needed, unless you are contributing to Emscripten development itself (as opposed to just using it). You will also need a compiler toolchain to build from source: From 1ffeb801d879ca3f65d480d7d758f9822b307983 Mon Sep 17 00:00:00 2001 From: Anthony Liot Date: Mon, 11 Aug 2014 20:50:04 +0200 Subject: [PATCH 18/91] Add Runtime.warnOnce --- src/library_openal.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/library_openal.js b/src/library_openal.js index 71c43aef5fd05..4091cddeae6f2 100644 --- a/src/library_openal.js +++ b/src/library_openal.js @@ -446,7 +446,7 @@ var LibraryOpenAL = { if (value === 1 /* AL_TRUE */) { if (src.panner) { src.panner = null; - + // Disconnect from the panner. src.gain.disconnect(); @@ -1385,12 +1385,15 @@ var LibraryOpenAL = { }, alSpeedOfSound: function(value) { + Runtime.warnOnce('alSpeedOfSound() is not yet implemented! Ignoring all calls to it.' }, alDopplerFactor: function(value) { + Runtime.warnOnce('alDopplerFactor() is not yet implemented! Ignoring all calls to it.' }, alDopplerVelocity: function(value) { + Runtime.warnOnce('alDopplerVelocity() is not yet implemented! Ignoring all calls to it.' } }; From 343b4892812babbad1ac6d6119a3ea493c4f1326 Mon Sep 17 00:00:00 2001 From: Anthony Liot Date: Mon, 11 Aug 2014 21:01:23 +0200 Subject: [PATCH 19/91] Sorry, add missing ');' --- src/library_openal.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/library_openal.js b/src/library_openal.js index 4091cddeae6f2..26f24e5e26385 100644 --- a/src/library_openal.js +++ b/src/library_openal.js @@ -1385,15 +1385,15 @@ var LibraryOpenAL = { }, alSpeedOfSound: function(value) { - Runtime.warnOnce('alSpeedOfSound() is not yet implemented! Ignoring all calls to it.' + Runtime.warnOnce('alSpeedOfSound() is not yet implemented! Ignoring all calls to it.'); }, alDopplerFactor: function(value) { - Runtime.warnOnce('alDopplerFactor() is not yet implemented! Ignoring all calls to it.' + Runtime.warnOnce('alDopplerFactor() is not yet implemented! Ignoring all calls to it.'); }, alDopplerVelocity: function(value) { - Runtime.warnOnce('alDopplerVelocity() is not yet implemented! Ignoring all calls to it.' + Runtime.warnOnce('alDopplerVelocity() is not yet implemented! Ignoring all calls to it.'); } }; From c2d449216cc48b2980d6e75897b1fa32d0b3c0fb Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 11 Aug 2014 12:34:15 -0700 Subject: [PATCH 20/91] do not emit temp .o files to curr dir, if target is not them; fixes #2644 --- emcc | 3 ++- tests/test_other.py | 17 +++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/emcc b/emcc index ff79d87528e38..af26964cc3d22 100755 --- a/emcc +++ b/emcc @@ -1447,7 +1447,8 @@ try: return os.path.join(specified_target, os.path.basename(unsuffixed(input_file))) + default_object_extension return specified_target return unsuffixed(input_file) + final_ending - return unsuffixed(input_file) + default_object_extension + else: + if has_dash_c: return unsuffixed(input_file) + default_object_extension return in_temp(unsuffixed(uniquename(input_file)) + default_object_extension) # First, generate LLVM bitcode. For each input file, we get base.o with bitcode diff --git a/tests/test_other.py b/tests/test_other.py index 224570abcae8b..45570a09a4adf 100644 --- a/tests/test_other.py +++ b/tests/test_other.py @@ -1,4 +1,5 @@ import multiprocessing, os, re, shutil, subprocess, sys +import glob import tools.shared from tools.shared import * from runner import RunnerCore, path_from_root, get_bullet_library, nonfastcomp @@ -3911,3 +3912,19 @@ def test_locale_wrong(self): self.assertContained('Constructed locale "C"\nThis locale is the global locale.\nThis locale is the C locale.', run_js('a.out.js', args=['C'])) self.assertContained('''Can't construct locale "waka": collate_byname::collate_byname failed to construct for waka''', run_js('a.out.js', args=['waka'], assert_returncode=1)) + def test_cleanup_os(self): + # issue 2644 + def test(args, be_clean): + print args + self.clear() + shutil.copyfile(path_from_root('tests', 'hello_world.c'), 'a.c') + open('b.c', 'w').write(' ') + Popen([PYTHON, EMCC, 'a.c', 'b.c'] + args).communicate() + clutter = glob.glob('*.o') + if be_clean: assert len(clutter) == 0, 'should not leave clutter ' + str(clutter) + else: assert len(clutter) == 2, 'should leave .o files' + test(['-o', 'c.bc'], True) + test(['-o', 'c.js'], True) + test(['-o', 'c.html'], True) + test(['-c'], False) + From e9d4fac26a998aef4eee7ef06409790c31f2b811 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9A=D0=BE=D1=80=D0=B5=D0=BD=D0=B1=D0=B5=D1=80=D0=B3=20?= =?UTF-8?q?=D0=9C=D0=B0=D1=80=D0=BA=20=28imac=29?= Date: Tue, 12 Aug 2014 00:57:30 +0600 Subject: [PATCH 21/91] Code reformat: split library names into separate lines make git life a bit easy --- src/modules.js | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/src/modules.js b/src/modules.js index 0554498fd10da..622873e5e8b6b 100644 --- a/src/modules.js +++ b/src/modules.js @@ -425,7 +425,31 @@ var LibraryManager = { load: function() { if (this.library) return; - var libraries = ['library.js', 'library_path.js', 'library_fs.js', 'library_idbfs.js', 'library_memfs.js', 'library_nodefs.js', 'library_sockfs.js', 'library_tty.js', 'library_browser.js', 'library_sdl.js', 'library_gl.js', 'library_glut.js', 'library_xlib.js', 'library_egl.js', 'library_gc.js', 'library_jansson.js', 'library_openal.js', 'library_glfw.js', 'library_uuid.js', 'library_glew.js', 'library_html5.js', 'library_async.js'].concat(additionalLibraries); + var libraries = [ + 'library.js', + 'library_path.js', + 'library_fs.js', + 'library_idbfs.js', + 'library_memfs.js', + 'library_nodefs.js', + 'library_sockfs.js', + 'library_tty.js', + 'library_browser.js', + 'library_sdl.js', + 'library_gl.js', + 'library_glut.js', + 'library_xlib.js', + 'library_egl.js', + 'library_gc.js', + 'library_jansson.js', + 'library_openal.js', + 'library_glfw.js', + 'library_uuid.js', + 'library_glew.js', + 'library_html5.js', + 'library_async.js' + ].concat(additionalLibraries); + for (var i = 0; i < libraries.length; i++) { var filename = libraries[i]; var src = read(filename); From be044933759150227c8c58587504a28e5ce5e8cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jukka=20Jyl=C3=A4nki?= Date: Mon, 11 Aug 2014 23:43:20 +0300 Subject: [PATCH 22/91] Update download links for Emscripten SDK 1.22.0. --- site/source/docs/getting_started/downloads.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/site/source/docs/getting_started/downloads.rst b/site/source/docs/getting_started/downloads.rst index 9de09838c99de..9073ec6e032af 100644 --- a/site/source/docs/getting_started/downloads.rst +++ b/site/source/docs/getting_started/downloads.rst @@ -19,13 +19,13 @@ Download one of the SDK installers below to get started with Emscripten developm Windows ------- -- `Emscripten SDK Web Installer `_ (emsdk-1.21.0-web-64bit.exe) +- `Emscripten SDK Web Installer `_ (emsdk-1.22.0-web-64bit.exe) An NSIS installer that fetches and installs the latest Emscripten SDK from the web. To :ref:`install `, download and open the file, then follow the installer prompts. -- `Emscripten SDK Offline Installer `_ (emsdk-1.21.0-full-64bit.exe) +- `Emscripten SDK Offline Installer `_ (emsdk-1.22.0-full-64bit.exe) An NSIS installer that bundles together the current Emscripten toolchain as an offline-installable package. To :ref:`install `, download and open the file, then follow the installer prompts. -- `Portable Emscripten SDK for Windows `_ (emsdk-1.21.0-portable-64bit.zip) +- `Portable Emscripten SDK for Windows `_ (emsdk-1.22.0-portable-64bit.zip) A zipped package of the SDK that does not require system installation privileges. To install, follow :ref:`these ` instructions. Linux and Mac OS X From d2831b680135c8631f96be46f14bbdfd230a6523 Mon Sep 17 00:00:00 2001 From: Anthony Liot Date: Mon, 11 Aug 2014 22:52:21 +0200 Subject: [PATCH 23/91] Add AL_INVALID_VALUE Set ALC_MAX_AUXILIARY_SENDS to 1 --- src/library_openal.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/library_openal.js b/src/library_openal.js index 26f24e5e26385..e74d860f120e3 100644 --- a/src/library_openal.js +++ b/src/library_openal.js @@ -287,7 +287,7 @@ var LibraryOpenAL = { AL.currentContext.err = 0xA001 /* ALC_INVALID_DEVICE */; return 0; } - {{{ makeSetValue('data', '0', '4', 'i32') }}}; + {{{ makeSetValue('data', '0', '1', 'i32') }}}; default: #if OPENAL_DEBUG console.log("alcGetIntegerv with param " + param + " not implemented yet"); @@ -1381,6 +1381,7 @@ var LibraryOpenAL = { }, alGetEnumValue: function(name) { + AL.currentContext.err = 0xA003 /* AL_INVALID_VALUE */; return 0; }, From c2295c7b3d8c73e12ca3e2c4f0801446af384791 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 11 Aug 2014 13:47:38 -0700 Subject: [PATCH 24/91] allow proxy-to-worker builds to run on the main thread, when noProxy is part of the url's search portion --- emcc | 15 ++++++++++++++- src/jsifier.js | 2 ++ tests/runner.py | 6 ++++-- tests/test_browser.py | 19 +++++++++++++++++++ 4 files changed, 39 insertions(+), 3 deletions(-) diff --git a/emcc b/emcc index af26964cc3d22..812b5f646ccfd 100755 --- a/emcc +++ b/emcc @@ -1859,7 +1859,20 @@ try: js_target = unsuffixed(target) + '.js' base_js_target = os.path.basename(js_target) if proxy_to_worker: - html.write(shell.replace('{{{ SCRIPT }}}', '')) + child_js = shared.Settings.PROXY_TO_WORKER_FILENAME or target_basename + html.write(shell.replace('{{{ SCRIPT }}}', ''' +''' % child_js)) shutil.move(final, js_target) elif not Compression.on: # Normal code generation path diff --git a/src/jsifier.js b/src/jsifier.js index 358791f198ac1..0842d32cbee15 100644 --- a/src/jsifier.js +++ b/src/jsifier.js @@ -1906,8 +1906,10 @@ function JSify(data, functionsOnly) { print('}'); } if (PROXY_TO_WORKER) { + print('if (ENVIRONMENT_IS_WORKER) {\n'); print(read('webGLWorker.js')); print(read('proxyWorker.js')); + print('}'); } if (DETERMINISTIC) { print(read('deterministic.js')); diff --git a/tests/runner.py b/tests/runner.py index 629047dfe5ea6..fae27a09cd7fb 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -526,6 +526,7 @@ def server_func(dir, q): class TestServerHandler(SimpleHTTPServer.SimpleHTTPRequestHandler): def do_GET(self): if 'report_' in self.path: + print '[server response:', self.path, ']' q.put(self.path) else: # Use SimpleHTTPServer default file serving operation for GET. @@ -561,6 +562,7 @@ def tearDownClass(self): time.sleep(0.1) def run_browser(self, html_file, message, expectedResult=None): + print '[browser launch:', html_file, ']' if expectedResult is not None: try: queue = multiprocessing.Queue() @@ -690,7 +692,7 @@ def reftest(self, expected): ''' % basename) def btest(self, filename, expected=None, reference=None, force_c=False, reference_slack=0, manual_reference=False, post_build=None, - args=[], outfile='test.html', message='.', also_proxied=False): # TODO: use in all other tests + args=[], outfile='test.html', message='.', also_proxied=False, url_suffix=''): # TODO: use in all other tests # if we are provided the source and not a path, use that filename_is_src = '\n' in filename src = filename if filename_is_src else '' @@ -716,7 +718,7 @@ def btest(self, filename, expected=None, reference=None, force_c=False, referenc assert os.path.exists(outfile) if post_build: post_build() if type(expected) is str: expected = [expected] - self.run_browser(outfile, message, ['/report_result?' + e for e in expected]) + self.run_browser(outfile + url_suffix, message, ['/report_result?' + e for e in expected]) if also_proxied: print 'proxied...' # save non-proxied diff --git a/tests/test_browser.py b/tests/test_browser.py index 65cec3e504f9d..4cdca6e5e311f 100644 --- a/tests/test_browser.py +++ b/tests/test_browser.py @@ -748,6 +748,25 @@ def test_sdl_canvas_proxy(self): def test_glgears_proxy(self): self.btest('hello_world_gles_proxy.c', reference='gears.png', args=['--proxy-to-worker', '-s', 'GL_TESTING=1'], manual_reference=True, post_build=self.post_manual_reftest) + # test noProxy option applied at runtime + + # run normally (duplicates above test, but verifies we can run outside of the btest harness + self.run_browser('test.html', None, ['/report_result?0']) + + # run with noProxy + self.run_browser('test.html?noProxy', None, ['/report_result?0']) + + # run with noProxy, but make main thread fail + original = open('test.js').read() + open('test.js', 'w').write(original.replace('function _main($argc,$argv) {', 'function _main($argc,$argv) { if (ENVIRONMENT_IS_WEB) { var xhr = new XMLHttpRequest(); xhr.open("GET", "http://localhost:8888/report_result?999");xhr.send(); }')) + self.run_browser('test.html?noProxy', None, ['/report_result?999']) + self.run_browser('test.html', None, ['/report_result?0']) # this is still cool + + # run without noProxy, so proxy, but make worker fail + open('test.js', 'w').write(original.replace('function _main($argc,$argv) {', 'function _main($argc,$argv) { if (ENVIRONMENT_IS_WORKER) { var xhr = new XMLHttpRequest(); xhr.open("GET", "http://localhost:8888/report_result?999");xhr.send(); }')) + self.run_browser('test.html', None, ['/report_result?999']) + self.run_browser('test.html?noProxy', None, ['/report_result?0']) # this is still cool + def test_glgears_proxy_jstarget(self): # test .js target with --proxy-worker; emits 2 js files, client and worker Popen([PYTHON, EMCC, path_from_root('tests', 'hello_world_gles_proxy.c'), '-o', 'test.js', '--proxy-to-worker', '-s', 'GL_TESTING=1']).communicate() From 8bd02e7b7fc7b79bf20b3167cd73a17bb1fbb66d Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 11 Aug 2014 15:37:26 -0700 Subject: [PATCH 25/91] enable emptyasm testcase in fastcomp --- tests/test_core.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/test_core.py b/tests/test_core.py index 59196d29b6294..597d4e8296eca 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -5486,7 +5486,6 @@ def test_cases(self): '2xi40', # pnacl limitations in ExpandGetElementPtr 'quoted', # current fastcomp limitations FIXME 'atomicrmw_unaligned', # TODO XXX - 'emptyasm_aue' # we don't support inline asm ]: continue if os.path.basename(shortname) in need_no_leave_inputs_raw: From 045157e7c00ac91d3cff886a9a02c70515bf3036 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9A=D0=BE=D1=80=D0=B5=D0=BD=D0=B1=D0=B5=D1=80=D0=B3=20?= =?UTF-8?q?=D0=9C=D0=B0=D1=80=D0=BA=20=28imac=29?= Date: Tue, 12 Aug 2014 00:54:49 +0600 Subject: [PATCH 26/91] Signal-related function implementations moved to separate file When stubs are used, message will be printed using console.error() alarm() and ualarm() throws exception now instead of stub. Using stubs may significantly break applications. siginterrupt() calls stub instead of exception. Since syscalls are never interrupted in emscripten, it is better not to raise exception here. --- AUTHORS | 1 + src/library.js | 79 ------------------------ src/library_signals.js | 135 +++++++++++++++++++++++++++++++++++++++++ src/modules.js | 1 + 4 files changed, 137 insertions(+), 79 deletions(-) create mode 100644 src/library_signals.js diff --git a/AUTHORS b/AUTHORS index 2979ffd95efb0..e45d89f155ffc 100644 --- a/AUTHORS +++ b/AUTHORS @@ -152,3 +152,4 @@ a license to everyone to use it as detailed in LICENSE.) * Hamish Willee (copyright owned by Mozilla Foundation) * Sylvain Chevalier * Nathan Ross +* Коренберг Марк diff --git a/src/library.js b/src/library.js index 40d7e0648b003..754ff032273ff 100644 --- a/src/library.js +++ b/src/library.js @@ -1148,14 +1148,6 @@ LibraryManager.library = { return -1; } }, - alarm: function(seconds) { - // unsigned alarm(unsigned seconds); - // http://pubs.opengroup.org/onlinepubs/000095399/functions/alarm.html - // We don't support signals, and there's no way to indicate failure, so just - // fail silently. - return 0; - }, - ualarm: 'alarm', confstr__deps: ['__setErrNo', '$ERRNO_CODES', '$ENV'], confstr: function(name, buf, len) { // size_t confstr(int name, char *buf, size_t len); @@ -1354,14 +1346,6 @@ LibraryManager.library = { ___setErrNo(ERRNO_CODES.EPERM); return 0; }, - pause__deps: ['__setErrNo', '$ERRNO_CODES'], - pause: function() { - // int pause(void); - // http://pubs.opengroup.org/onlinepubs/000095399/functions/pause.html - // We don't support signals, so we return immediately. - ___setErrNo(ERRNO_CODES.EINTR); - return -1; - }, setgid__deps: ['__setErrNo', '$ERRNO_CODES'], setgid: function(gid) { // int setgid(gid_t gid); @@ -5667,9 +5651,6 @@ LibraryManager.library = { return 0; }, - setitimer: function() { throw 'setitimer not implemented yet' }, - getitimer: function() { throw 'getitimer not implemented yet' }, - // ========================================================================== // sys/time.h // ========================================================================== @@ -5858,66 +5839,6 @@ LibraryManager.library = { _longjmp(env, value); }, - // ========================================================================== - // signal.h - // ========================================================================== - - signal: function(sig, func) { - // TODO - return 0; - }, - sigemptyset: function(set) { - // int sigemptyset(sigset_t *set); - {{{ makeSetValue('set', '0', '0', 'i32') }}}; - return 0; - }, - sigfillset: function(set) { - {{{ makeSetValue('set', '0', '-1>>>0', 'i32') }}}; - return 0; - }, - sigaddset: function(set, signum) { - {{{ makeSetValue('set', '0', makeGetValue('set', '0', 'i32') + '| (1 << (signum-1))', 'i32') }}}; - return 0; - }, - sigdelset: function(set, signum) { - {{{ makeSetValue('set', '0', makeGetValue('set', '0', 'i32') + '& (~(1 << (signum-1)))', 'i32') }}}; - return 0; - }, - sigismember: function(set, signum) { - return {{{ makeGetValue('set', '0', 'i32') }}} & (1 << (signum-1)); - }, - sigaction: function(set) { - // TODO: - return 0; - }, - sigprocmask: 'sigaction', - __libc_current_sigrtmin: function() { - return 0; - }, - __libc_current_sigrtmax: function() { - return 0; - }, - kill__deps: ['$ERRNO_CODES', '__setErrNo'], - kill: function(pid, sig) { - // int kill(pid_t pid, int sig); - // http://pubs.opengroup.org/onlinepubs/000095399/functions/kill.html - // Makes no sense in a single-process environment. - ___setErrNo(ERRNO_CODES.EPERM); - return -1; - }, - killpg: 'kill', - - siginterrupt: function() { throw 'siginterrupt not implemented' }, - - raise__deps: ['$ERRNO_CODES', '__setErrNo'], - raise: function(sig) { - ___setErrNo(ERRNO_CODES.ENOSYS); -#if ASSERTIONS - Runtime.warnOnce('raise() returning an error as we do not support it'); -#endif - return -1; - }, - // ========================================================================== // sys/wait.h // ========================================================================== diff --git a/src/library_signals.js b/src/library_signals.js new file mode 100644 index 0000000000000..773618c592c28 --- /dev/null +++ b/src/library_signals.js @@ -0,0 +1,135 @@ +// 'use strict' +var funs = { + signal: function(sig, func) { + console.error('Calling stub instead of signal()'); + return 0; + }, + sigemptyset: function(set) { + {{{ makeSetValue('set', '0', '0', 'i32') }}}; + return 0; + }, + sigfillset: function(set) { + {{{ makeSetValue('set', '0', '-1>>>0', 'i32') }}}; + return 0; + }, + sigaddset: function(set, signum) { + {{{ makeSetValue('set', '0', makeGetValue('set', '0', 'i32') + '| (1 << (signum-1))', 'i32') }}}; + return 0; + }, + sigdelset: function(set, signum) { + {{{ makeSetValue('set', '0', makeGetValue('set', '0', 'i32') + '& (~(1 << (signum-1)))', 'i32') }}}; + return 0; + }, + sigismember: function(set, signum) { + return {{{ makeGetValue('set', '0', 'i32') }}} & (1 << (signum-1)); + }, + sigaction: function(signum, act, oldact) { + //int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact); + console.error('Calling stub instead of sigaction()'); + return 0; + }, + sigprocmask: function() { + console.error('Calling stub instead of sigprocmask()'); + return 0; + }, + __libc_current_sigrtmin: function() { + console.error('Calling stub instead of __libc_current_sigrtmin'); + return 0; + }, + __libc_current_sigrtmax: function() { + console.error('Calling stub instead of __libc_current_sigrtmax'); + return 0; + }, + kill__deps: ['$ERRNO_CODES', '__setErrNo'], + kill: function(pid, sig) { + // http://pubs.opengroup.org/onlinepubs/000095399/functions/kill.html + // Makes no sense in a single-process environment. + // Should kill itself somtimes depending on `pid` + console.error('Calling stub instead of kill()'); + ___setErrNo(ERRNO_CODES.EPERM); + return -1; + }, + + killpg__deps: ['$ERRNO_CODES', '__setErrNo'], + killpg: function() { + console.error('Calling stub instead of killpg()'); + ___setErrNo(ERRNO_CODES.EPERM); + return -1; + }, + siginterrupt: function() { + console.error('Calling stub instead of siginterrupt()'); + return 0; + }, + + raise__deps: ['$ERRNO_CODES', '__setErrNo'], + raise: function(sig) { + console.error('Calling stub instead of raise()'); + ___setErrNo(ERRNO_CODES.ENOSYS); +#if ASSERTIONS + Runtime.warnOnce('raise() returning an error as we do not support it'); +#endif + return -1; + }, + + alarm: function(seconds) { + // unsigned alarm(unsigned seconds); + // http://pubs.opengroup.org/onlinepubs/000095399/functions/alarm.html + // We don't support signals, and there's no way to indicate failure, so just + // fail silently. + throw 'alarm() is not implemented yet'; + }, + ualarm: function() { + throw 'ualarm() is not implemented yet'; + }, + setitimer: function() { + throw 'setitimer() is not implemented yet'; + }, + getitimer: function() { + throw 'getitimer() is not implemented yet'; + }, + + pause__deps: ['__setErrNo', '$ERRNO_CODES'], + pause: function() { + // int pause(void); + // http://pubs.opengroup.org/onlinepubs/000095399/functions/pause.html + // We don't support signals, so we return immediately. + console.error('Calling stub instead of pause()'); + ___setErrNo(ERRNO_CODES.EINTR); + return -1; + } + //signalfd + //ppoll + //epoll_pwait + //pselect + //sigvec + //sigmask + //sigblock + //sigsetmask + //siggetmask + //sigpending + //sigsuspend + //bsd_signal + //siginterrupt + //sigqueue + //sysv_signal + //signal + //pthread_kill + //gsignal + //ssignal + //psignal + //psiginfo + //sigpause + //sigisemptyset + //sigtimedwait + //sigwaitinfo + //sigreturn + //sigstack + //sigaltstack(2) + //sigsetops(3), + //sighold + //sigrelse + //sigignore + //sigset +}; + +mergeInto(LibraryManager.library, funs); diff --git a/src/modules.js b/src/modules.js index 622873e5e8b6b..b340e5bee9caf 100644 --- a/src/modules.js +++ b/src/modules.js @@ -447,6 +447,7 @@ var LibraryManager = { 'library_uuid.js', 'library_glew.js', 'library_html5.js', + 'library_signals.js', 'library_async.js' ].concat(additionalLibraries); From 78b2fc50e7c6bf699cd592f9cfb9bed66057cc48 Mon Sep 17 00:00:00 2001 From: hamishwillee Date: Tue, 12 Aug 2014 21:52:16 +1000 Subject: [PATCH 27/91] changes to building from articles as a result of feedback from ChrisM. Significant fixes to LLVM-Backend doc --- .../building_from_source/LLVM-Backend.rst | 285 +++++++++++++----- ...ilding_emscripten_from_source_on_linux.rst | 8 +- ...ing_emscripten_from_source_on_mac_os_x.rst | 10 +- ...ding_emscripten_from_source_on_windows.rst | 22 +- .../configuring_emscripten_settings.rst | 4 +- ...lly_integrating_emscripten_with_vs2010.rst | 21 +- .../toolchain_what_is_needed.rst | 48 ++- .../verify_emscripten_environment.rst | 2 +- site/source/docs/getting_started/Tutorial.rst | 8 +- .../source/docs/getting_started/downloads.rst | 20 +- ...ing_started_with_emscripten_and_vs2010.rst | 2 +- site/source/docs/site/glossary.rst | 8 + 12 files changed, 296 insertions(+), 142 deletions(-) diff --git a/site/source/docs/building_from_source/LLVM-Backend.rst b/site/source/docs/building_from_source/LLVM-Backend.rst index 743dc2b93800b..d48da501a6021 100644 --- a/site/source/docs/building_from_source/LLVM-Backend.rst +++ b/site/source/docs/building_from_source/LLVM-Backend.rst @@ -1,40 +1,127 @@ .. _LLVM-Backend: -========================== -LLVM Backend (wiki-import) -========================== -.. note:: This article was migrated from the wiki (Fri, 25 Jul 2014 04:21) and is now the "master copy" (the version in the wiki will be deleted). It may not be a perfect rendering of the original but we hope to fix that soon! +==================================================== +LLVM Backend ("Fastcomp") (under-construction) +==================================================== -LLVM Backend, aka "fastcomp" -============================ +*Fastcomp* is the default compiler core for Emscripten. It is a new :term:`LLVM backend` that converts the LLVM Intermediate Representation (IR) created by *Clang* (from C/C++) into JavaScript. -*Fastcomp* is a new compiler core for emscripten, replacing much of the original compiler core in ``src/*.js``. This replaces **only** the JS compiler itself, not the toolchain code nor library code (``src/library*.js``) nor JS optimizer code. (For context, the core compiler is a few thousand lines of code, to be replaced with a few other thousand lines of code, whereas all the other stuff not being replaced is far larger.) +The backend is still too new to be in the upstream LLVM repository. As such, builds from Linux distributions will **not** contain *Fastcomp*, and Emscripten will report an error if you try to use them. Instead you will need to use the Emscripten fork of LLVM, which you can either build from source or get as part of the :ref:`Emscripten SDK `. -**Fastcomp was turned on by default in version 1.12.1.** If you are using that version or later, you are using fastcomp unless you manually disable it (which is highly unrecommended). +This article explains how to get *Fastcomp* — either from the SDK or by building it from source. There is also a :ref:`fastcomp-faq` at the very end for troubleshooting *Fastcomp* problems. -See the FAQ at the bottom of this page if you are having problems. -Overview of Fastcomp --------------------- +.. note:: *Fastcomp* was turned on by default in version 1.12.1. It replaces the :ref:`original compiler core `, which is now "deprecated". While it is possible to manually disable Fastcomp and build the original compiler from source (binaries are no longer provided), this is discouraged. -Fastcomp is an **LLVM backend**. It is **not** in upstream LLVM yet, it is far too new for that (but hopefully eventually will be). So you need to use the emscripten fork of LLVM. You can either build it from source, or get it as part of the emscripten SDK. - -This means that if you use another build of LLVM - like an older one you built yourself, or one from your linux distro's repos, etc. - it will **not** contain fastcomp. Emscripten will give an error about this (you can manually run those checks with ``emcc -v``), and briefly explain the issue and link to this page (where, later down, you can see how to disable fastcomp). + The article also explains the reasons for changing to *Fastcomp*, and how you can use the old compiler if needed. +.. todo:: Emscripten tool (emcc) links to original wiki page when you use the wrong clang. Should point to here instead. Getting Fastcomp ----------------- +================ + +*Fastcomp* (Clang) is part of the SDK, and the binaries are automatically installed during installation (except on Linux, where pre-built binaries are not supplied so the SDK builds them for you). + +It is also possible to build Fastcomp from source as a :ref:`fully manual process ` or :ref:`using the SDK ` (recommended). + +.. _building-fastcomp-from-source-using-the-sdk: + +Building Fastcomp from source using the SDK +============================================ + +The SDK (:term:`emsdk`) supports building *Fastcomp* from :ref:`the master or incoming branches `, or from :ref:`your own fork ` of these branches. The former allows you to get the latest and greatest code, while the later lets you additionally make and contribute your own modifications. + +.. tip:: This approach is recommended over :ref:`building-fastcomp-from-source` because the SDK does all the work of getting the correct sources and tools for each branch, and guides you through the build process. + +You can see the *Clang* SDK targets for this using ``./emsdk list``: :: + + clang-incoming-32bit + clang-incoming-64bit + clang-master-32bit + clang-master-64bit + +.. note:: + + - To build from source you first need to install a :ref:`compiler-toolchain` (see link for installation instructions). + - If you are building a large project, you will need a 64-bit build of LLVM and Clang. Compiling and optimizing can take more memory than is available to the 32-bit build. + +To get and build the latest upstream git development branch (``incoming``), run the following: + +:: + + # Install git. Skip if git is already installed. + ./emsdk install git-1.8.3 + + # Clone+pull the latest **/kripken/emscripten-fastcomp-clang** and **/kripken/emscripten-fastcomp** + ./emsdk install clang-incoming-64bit + + # Set the "incoming SDK" as the active version. + ./emsdk activate clang-incoming-64bit + +If you want to use the upstream stable branch ``master``, then replace ``-incoming-`` with ``-master-`` in the commands above. This is all you need to do to get the latest version of *Fastcomp*. + +.. note:: On Windows, *git* may fail with the error message: + + :: + + Unable to find remote helper for 'https' when cloning a repository with https:// url. + + The workaround is to uninstall git from *emsdk* (``emsdk uninstall git-1.8.3``) and install `Git for Windows `_. This issue is reported `here `_. + +.. todo:: **HamishW** Check whether the bug (https://github.com/juj/emsdk/issues/13) is fixed and remove the above note if it is. + +If you're :ref:`contributing` to Emscripten you will instead want to use a fork of the *incoming* branch on Github (so that you can make pull requests back to the project). + +The way this works is that you first install the ``clang-incoming-64bit`` SDK target (as explained above). Then you use familiar *git* commands to replace this branch with the information from your own fork. These commands are the same that are used when :ref:`building-fastcomp-from-source`: + +:: + + cd clang/fastcomp/src + + ## Get your fork of LLVM + + # Add a git remote link to your LLVM repository fork. + git remote add myllvmremote https://github.com/mygituseraccount/emscripten-fastcomp.git + + # Obtain the changes in the remote. + git fetch myllvmremote + + # Checkout the code in your LLVM fork to replace the original repository code + git checkout -b myllvmremote --track myremote/incoming + + + ## Get your fork of Clang + + # Add a git remote link to your Clang repository fork. + git remote add myclangremote https://github.com/mygituseraccount/emscripten-fastcomp-clang.git + + # Obtain the changes in the remote. + git fetch myclangremote + + # Checkout the code in your Clang fork to replace the original repository code + git checkout -b myclangremote --track myclangremote/incoming + + # At this point the clang-incoming-64bit target now points to your fork. + +You can switch back and forth between remotes (the original sources and your fork, or the incoming and master branches) using the ``git checkout`` command as usual. + .. _building-fastcomp-from-source: -Building fastcomp from source --------------------------------- +Manually building Fastcomp from source +====================================== + +.. note:: + + - To build from source you first need to install a :ref:`compiler-toolchain` (see link for installation instructions). + - If you are building a large project, you will need a 64-bit build of LLVM and Clang. Compiling and optimizing can take more memory than is available to the 32-bit build. -To use fastcomp, you need both Emscripten (see the :ref:`Tutorial`) and the Emscripten LLVM code, either from the SDK or from source. Instructions from source are as follows: -- Clone the fastcomp `LLVM repository `_: +To build the Fastcomp code from source "manually" (without the benefit of the SDK environment): + +- Clone the fastcomp LLVM repository (https://github.com/kripken/emscripten-fastcomp>): :: @@ -43,20 +130,21 @@ To use fastcomp, you need both Emscripten (see the :ref:`Tutorial`) and the Emsc .. note:: It doesn't matter where you clone *fastcomp* because Emscripten gets the information from the :ref:`compiler configuration file (~/.emscripten) `. We show how to update this file later in these instructions: -- Navigate to the **tools** directory (**emscripten-fastcomp/tools**) and clone the `kripken/emscripten-fastcomp-clang `_ repository into a *clang* subdirectory: +- Navigate to the **tools** directory (**emscripten-fastcomp/tools**) and clone the `kripken/emscripten-fastcomp-clang `_ repository into a **clang** subdirectory: :: cd tools git clone https://github.com/kripken/emscripten-fastcomp-clang clang - .. warning:: You **must** clone it into a dir named "clang" (as is done by that command), so that clang is present in **tools/clang**! + .. warning:: You **must** clone it into a directory named **clang** as shown, so that :term:`Clang` is present in **tools/clang**! - .. note:: This repo has changed. Early in fastcomp development we used a different directory. + .. note:: This repository has changed. Early in fastcomp development we used a different directory. -- Build fastcomp +- Create a *build* directory (we highly recommend creating a separate build directory): - - Navigate back to the root of the llvm clone (**/emscripten-fastcomp**), then create and navigate into a new directory "**build**" (we highly recommend creating a separate build directory): + - Navigate back to the root of the llvm clone (**/emscripten-fastcomp**) + - Create a new directory "**build**", and then navigate into it: :: @@ -64,27 +152,36 @@ To use fastcomp, you need both Emscripten (see the :ref:`Tutorial`) and the Emsc mkdir build cd build - - Configure the build using *either* the *configure* script or *cmake* (configure is located in the parent directory): +- Configure the build using *either* the *configure* script or *cmake* (configure is located in the parent directory): - - Using *configure*: - - :: + - Using *configure*: - ../configure --enable-optimized --disable-assertions --enable-targets=host,js + :: + + ../configure --enable-optimized --disable-assertions --enable-targets=host,js - - Using *CMake*: + - Using *CMake*: - :: + :: - cmake .. -DCMAKE_BUILD_TYPE=Release -DLLVM_TARGETS_TO_BUILD="X86;JSBackend" -DLLVM_INCLUDE_EXAMPLES=OFF -DLLVM_INCLUDE_TESTS=OFF -DCLANG_INCLUDE_EXAMPLES=OFF -DCLANG_INCLUDE_TESTS=OFF + cmake .. -DCMAKE_BUILD_TYPE=Release -DLLVM_TARGETS_TO_BUILD="X86;JSBackend" -DLLVM_INCLUDE_EXAMPLES=OFF -DLLVM_INCLUDE_TESTS=OFF -DCLANG_INCLUDE_EXAMPLES=OFF -DCLANG_INCLUDE_TESTS=OFF - .. note:: replace X86 if you are on something else.. + .. note:: replace X86 if you are on something else.. - - Call *make* to build the sources, specifying the number of available cores: +- Determine the number of available cores on your system (Emscripten can run many operations in parallel, so using more cores may have a significant impact on compilation time): - :: + - On Mac OS X you can get the number of cores using: **Apple menu | About this mac | System report**. The **Hardware overview** on the resulting dialog includes a *Total number of cores* entry. + - On Linux you can find the number of cores by entering the following command on the terminal: ``cat /proc/cpuinfo | grep "^cpu cores" | uniq``. + - On Windows the number of cores is listed on the **Task Manager | Performance Tab**. YOu can open the *Task Manager* by entering **Ctrl + Shift + Esc** from the Desktop. + +- Call *make* to build the sources, specifying the number of available cores: + + :: + + make -j 4 + + - make -j 4 .. _llvm-update-compiler-configuration-file: @@ -92,91 +189,124 @@ To use fastcomp, you need both Emscripten (see the :ref:`Tutorial`) and the Emsc :: - LLVM_ROOT='' **HamishW** + LLVM_ROOT='/home/ubuntu/yourpath/emscripten-fastcomp/build/bin' .. note:: If **~/.emscripten** does not yet exist, you can create it by running ``./emcc --help`` in your **emscripten** directory (assuming Emscripten has already been downloaded). Branches -~~~~~~~~ +--------- + +You should use the **same** branch (*incoming*, or *master*) for building all three repositories: -You should use the **same** branch in all 3 repos: emscripten, emscripten-fastcomp and emscripten-fastcomp-clang (that is, in emscripten, in emscripten's LLVM fork and in emscripten's clang fork). That is, you can either use the master branch in all 3, or the incoming branch in all 3. If you don't use the same branch in all 3, you may run into errors (changes might land in emscripten incoming for example that will not work on the master branches of the other two). +- Emscripten: `emscripten `_. +- Emscripten's LLVM fork: `emscripten-fastcomp `_. +- Emscripten's *Clang* fork `emscripten-fastcomp-clang `_. -Run ``emcc -v`` to check if the branches are synchronized. Note that this checks the code in the repos, not the build - make sure you rebuilt LLVM+clang on the latest code you checked out. +Mixing *incoming* and *master* branches may result in errors when building the three repositories. + +Run ``emcc -v`` to check if the branches are synchronized. + +.. note:: ``emcc -v`` checks the code in the repositories, not the builds. Before building make sure that you fetch the latest changes to LLVM and Clang. Version numbers -^^^^^^^^^^^^^^^ +++++++++++++++++ -Bisecting across multiple git trees can be hard. We use version numbers -to synchronize points between them, which helps. +Bisecting across multiple git trees can be hard. We use version numbers to help synchronize points between them: -- tools/shared.py in emscripten -- emscripten-version.txt in fastcomp (llvm) -- emscripten-version.txt in fastcomp-clang (clang) +- `tools/shared.py `_ in Emscripten +- `emscripten-version.txt `_ in fastcomp (llvm) +- `emscripten-version.txt `_ in fastcomp-clang (clang) -Version numbers are typically X.Y.Z where +Version numbers are typically ``X.Y.Z`` where -- X is a major number (changes very rarely) -- Y is a release number (changes each time we merge incoming to master, so these numbers indicate points where all tests passed), and -- Z is minor update that is just a sync point between the repos, or is needed when libc changes in emscripten (version changes clear the cache). +- ``X`` is a major number (changes very rarely) +- ``Y`` is a release number (changes each time we merge incoming to master, so these numbers indicate points where all tests passed), and +- ``Z`` is minor update that is just a sync point between the repos, or is needed when libc changes in emscripten (version changes clear the cache). -Compilation Notes -~~~~~~~~~~~~~~~~~ +Additional compilation notes +---------------------------- -- If you are building a large project, you will need a 64-bit build of llvm+clang, as compiling and optimizing can take more memory than a 32-bit build can use. +- Windows: To build 64 bit using *CMmake* and *Visual Studio*, use the ``-G "Visual Studio 10 Win64"`` directive. -- To build 64 bit using cmake and visual studio, use the -G "Visual Studio 10 Win64" directive. Note: VS 11/12 don't work yet. + .. note:: Visual Studio 2011 and 2012 don't work yet. + +- Windows: To build using *MinGW* replace the ``-G`` directive above with ``-G "MinGW Makefiles"``, and run *mingw32-make* to build (not tested yet). -- If you want to build with MinGW instead and have that in path, replace -G directive in above with "-G MinGW Makefiles", and run mingw32-make to build (not tested yet). Backend code structure ---------------------- -The backend is in the repo linked to above, and code is in ``lib/Target/JSBackend/``. The main file is ``JSBackend.cpp`` but the the other files in that directory are important too. +The backend is in `emscripten-fastcomp `_. The main file is `JSBackend.cpp `_ but the the other files in that directory (`lib/Target/JSBackend/ `_) are also important. + + +.. _original-compiler-core: + +Original compiler core (deprecated) +=================================== + +The original compiler supported dozens of different code generation modes (no-typed arrays, typed arrays in various modes, **asm.js** vs. **non-asm.js**, etc.), many of which proved not to be particularly efficient. Over time, the compiler became harder to maintain and was susceptible to unpredictable compiler slow-downs. *Fastcomp* was created with a core focus on **asm.js** code generation, which has been shown to give the best results. + + + Why did this change happen? --------------------------- -Fastcomp is much more streamlined than the original compiler - the original compiler supports dozens of various code generation modes (no typed arrays, typed arrays in various modes, asm.js vs non-asm.js, etc.). Fastcomp on the other hand is directly focused on asm.js code generation, which has proven to give the best results. +*Fastcomp* is a much better compiler: -Fastcomp, as a C++ LLVM backend, is much faster than the original JS compiler, often 4x faster or more. It also requires much less memory and avoids unpredictable pathological compiler slowdowns that the old compiler had. +- It is much more streamlined than the original compiler. It focusses on **asm.js** code generation, which has been shown to give the best results. +- It is much faster and has more predictable performance (often 4x faster or more). +- It requires much less memory. +- It generates better code — as an LLVM backend it integrates more tightly with LLVM. -Fastcomp also generates better code - by being an LLVM backend, it can integrate more tightly with LLVM. Are there downsides? -~~~~~~~~~~~~~~~~~~~~ +--------------------------- + +The main downside is that Emscripten can no longer use a stock build of LLVM, because we have made changes that must be built with LLVM. We hope that the new Emscripten backend will eventually become part of the upstream LLVM, and hence become available in stock builds. + +.. note:: You actually **can** still use a stock build, but only because you can make Emscripten use the original compiler if needed. This is not a good idea as the original compiler is nowhere near as fast or as well tested. -The main downside is that Emscripten can no longer use a stock build of LLVM, because we have changes that must be built with LLVM. +There are also a few features that were present in the original compiler that are not present in *Fastcomp* (see the next section). -Note that you actually **can** still use a stock build, but only because you can make emscripten use the original compiler (see next section) - but this is not good, because you miss out on the benefits of the backend (see above), and also you are running a code path that is not recommended and less tested. -This will hopefully be a temporary issue because the new Emscripten backend might get upstreamed to LLVM eventually, in which case a stock build would contain it. +Features not present in Fastcomp +---------------------------------------- -Status of Original Compiler (and how to disable fastcomp) ---------------------------------------------------------- +Some features that were present in the original compiler that are not present in *Fastcomp* include: -You should **NOT** disable fastcomp. But, if you really, really must, you should know that you will have the following downsides: +- Various deprecated **settings.js** options (e.g. ``FORCE_ALIGNMENT``, ``HEAP_INIT``, etc.) have no effect. You should receive a compile-time error if you use a setting which is not yet supported. +- Linking of **asm.js** shared modules has not yet been ported. This is not deprecated, but may need to be reconsidered. -- Not taking advantage of the benefits of fastcomp (much faster compilation, better generated code). -- Using the old compiler which is deprecated and consequently less tested. + .. note:: Normal static linking as used by almost all projects works fine, it is just specifically the options ``MAIN_MODULE`` and ``SIDE_MODULE`` that do not work. -The original compiler is still present, and you may want to use it if you need a feature not present in fastcomp. There should be very few such features, as everything not deprecated or planned to be rewritten has already been ported. However, if you do need one of those features, you can use the old compiler, by building with + +How to disable Fastcomp +--------------------------- +.. warning:: You should **NOT** disable Fastcomp. If you "really must", this will have the following downsides: + + - Not taking advantage of the benefits of *Fastcomp* (much faster compilation, better generated code). + - The old compiler is deprecated, and consequently less tested. + +The original compiler is still present, and you may want to use it if you need a feature that is not yet present in *Fastcomp*. There should be very few such features, as almost everything that is not deprecated or planned to be rewritten has already been ported. + +However, if you do need to, you can use the old compiler by turning off *Fastcomp*. Specifically, by setting ``EMCC_FAST_COMPILER=0`` when you build: :: EMCC_FAST_COMPILER=0 emcc [..] -so that ``EMCC_FAST_COMPILER`` is set in the environment to ``0``. This will turn off fastcomp. -When you want to use fastcomp, you must be using a build from the fastcomp repos (see below), so that the backend is present. When you disable fastcomp on the other hand, you can use **either** a build from the fastcomp repos, **or** a stock LLVM build. The latter is less tested, but should work in principle: Disabling fastcomp does not use anything new in the fastcomp repo (neither the new backend, nor the new target triple). +When you disable *Fastcomp* you can use **either** a build from the *Fastcomp* repositories, **or** a stock LLVM build. The latter is less tested, but should work in principle: Disabling *Fastcomp* does not use anything new in the *Fastcomp* repo (neither the new backend, nor the new target triple). -You can check if fastcomp is on or off by looking at debug output. For example, run ``EMCC_DEBUG=1 emcc tests/hello_world.c`` and if fastcomp is on, then among the output will be +You can check whether *Fastcomp* is enabled by looking at debug output. For example, run ``EMCC_DEBUG=1 emcc tests/hello_world.c`` — if *Fastcomp* is on, then among the output will be: :: DEBUG root: emscript: llvm backend: ... DEBUG root: emscript: llvm backend took -That shows both the command used to run the backend, and how much time it took. If fastcomp is off on the other hand, the old compiler is used, and you will instead +That shows both the command used to run the backend, and how much time it took. If *Fastcomp* is off on the other hand, the old compiler is used, and you will instead see: :: @@ -185,16 +315,15 @@ That shows both the command used to run the backend, and how much time it took. ... DEBUG root: emcc step "emscript (llvm=>js)" took ... -This shows that the old compiler (``ll=>js``) is called, as well as how much time each step takes, and the total time. Again, this is the output for the **old** compiler, so hopefully you will never see it :) +This shows that the old compiler (``ll=>js``) is called, as well as how much time each step takes, and the total time. Again, this is the output for the **old** compiler, so hopefully you will never see it! + -Some features not present in fastcomp are: -- Various deprecated settings.js options (e.g. FORCE\_ALIGNMENT, HEAP\_INIT, etc.) have no effect. You should receive a compile-time error if you use a setting which is not yet supported, if it has not been missed. -- :ref:`Linking` of asm.js shared modules (note that normal static linking as used by almost all projects works fine, it is just specifically the options MAIN\_MODULE and SIDE\_MODULE that do not work). This is not deprecated, but may need to be partially reconsidered, so it has not been ported to fastcomp. +.. _fastcomp-faq: FAQ === - I see ``WARNING: Linking two modules of different target triples`` [..] ``'asmjs-unknown-emscripten' and 'le32-unknown-nacl'``..? -- You are linking together bitcode files compiled with the old compiler (or older versions of fastcomp) with bitcode files from the new one. This may work in some cases but is dangerous and should be avoided. To fix it, just recompile all your bitcode with the new compiler. +- You are linking together bitcode files compiled with the old compiler (or older versions of *Fastcomp*) with bitcode files from the new one. This may work in some cases but is dangerous and should be avoided. To fix it, just recompile all your bitcode with the new compiler. diff --git a/site/source/docs/building_from_source/building_emscripten_from_source_on_linux.rst b/site/source/docs/building_from_source/building_emscripten_from_source_on_linux.rst index 583a34fd91e0a..fb524f7c34b94 100644 --- a/site/source/docs/building_from_source/building_emscripten_from_source_on_linux.rst +++ b/site/source/docs/building_from_source/building_emscripten_from_source_on_linux.rst @@ -1,12 +1,12 @@ .. _building-emscripten-on-linux: -================================================ -Building Emscripten on Linux (ready-for-review) -================================================ +============================ +Building Emscripten on Linux +============================ .. tip:: The :ref:`Portable SDK for Linux ` (and Mac OS X) provides the **easiest** and **most reliable** method for **building from source**. Just :ref:`download and install the SDK ` and follow the brief instructions :ref:`here `. - These instructions are provided for developers who, for whatever reason, prefer a manual approach. + The instructions below are provided for developers who, for whatever reason, prefer a manual approach. This page contains basic instructions on how to manually build and configure Emscripten from source on a clean (Ubuntu 14.04.1 LTS 64bit) Linux box. diff --git a/site/source/docs/building_from_source/building_emscripten_from_source_on_mac_os_x.rst b/site/source/docs/building_from_source/building_emscripten_from_source_on_mac_os_x.rst index 65e5515201c11..4c08fb334db9e 100644 --- a/site/source/docs/building_from_source/building_emscripten_from_source_on_mac_os_x.rst +++ b/site/source/docs/building_from_source/building_emscripten_from_source_on_mac_os_x.rst @@ -6,9 +6,9 @@ Building Emscripten on Mac OS X (ready-for-review) .. tip:: The :ref:`Portable SDK for Linux ` (and Mac OS X) provides the **easiest** and **most reliable** method for **building from source**. Just :ref:`download and install the SDK ` and follow the brief instructions :ref:`here `. - These instructions are provided for developers who, for whatever reason, prefer a manual approach. + The instructions below are provided for developers who, for whatever reason, prefer a manual approach. -This page contains basic instructions on how to manually build and configure Emscripten from source on a clean (OS X version 10.8.2) clean Mac OS X box. +This page contains basic instructions on how to manually build and configure Emscripten from source on a clean Mac OS X box (OS X version 10.8.2). What you'll need ================= @@ -21,20 +21,20 @@ Installing required tools These instructions explain how to install **all** the :ref:`required tools `. You can :ref:`test whether some of these are already installed ` on the platform and skip those steps. -#. Install the *XCode Command Line Tools*. These include the toolchain to build :term:`Fastcomp`, and also are a precondition for *git*. +#. Install the *XCode Command Line Tools*. These include the toolchain to build :term:`Fastcomp`, and are a precondition for *git*. - Install XCode from the `Mac OS X App Store `_. - In **XCode | Preferences | Downloads**, install *Command Line Tools*. #. Install *git*: - - Allow installation of unsigned packages, or installing git package `won't succeed `_. + - `Allow installation of unsigned packages `_, or installing the git package won't succeed. - Install XCode and the XCode Command Line Tools (should already have been done). This will provide *git* to the system PATH (see `this stackoverflow post `_). - Download and install git directly from http://git-scm.com/. #. Install *cmake* if you do not have it yet: - - Download and install `cmake-2.8.10.2-Darwin64-universal.dmg `_ (or newer) + - Download and install `cmake-2.8.10.2-Darwin64-universal.dmg `_ (or newer). #. Install *node.js* from http://nodejs.org/ diff --git a/site/source/docs/building_from_source/building_emscripten_from_source_on_windows.rst b/site/source/docs/building_from_source/building_emscripten_from_source_on_windows.rst index 4147d90a105d8..db1c261c63f5a 100644 --- a/site/source/docs/building_from_source/building_emscripten_from_source_on_windows.rst +++ b/site/source/docs/building_from_source/building_emscripten_from_source_on_windows.rst @@ -6,7 +6,7 @@ Building Emscripten on Windows (ready-for-review) .. tip:: The :ref:`Emscripten Windows SDKs ` provide the **easiest** and **most reliable** method for **building from source**. Just :ref:`download and install the SDK ` and follow the brief instructions :ref:`here `. - These instructions are provided for developers who, for whatever reason, prefer a manual approach. + The instructions below are provided for developers who, for whatever reason, prefer a manual approach. This page contains basic instructions on how to manually build and configure Emscripten from source on a clean Windows box. @@ -16,7 +16,7 @@ What you'll need The topic :ref:`Emscripten Toolchain ` lists the specific versions of tools that are needed. -.. note:: 64-bit versions of all needed dependencies are preferred, and may be required if you are building large projects. However, if you plan to use the Visual Studio integration, do NOT install the 64-bit versions of the tools. +.. note:: 64-bit versions of all needed dependencies are preferred, and may be required if you are building large projects. However, if you plan to :ref:`integrate with Visual Studio `, do NOT install the 64-bit versions of the tools. Installing required tools ========================== @@ -24,32 +24,34 @@ Installing required tools These instructions explain how to install **all** the :ref:`required tools `. You can :ref:`test whether some of these are already installed ` on the platform and skip those steps. -#. Install `Python 2.x `_ (not 3.x) +#. Install `Python 2.x `_ (not 3.x): - For example `python-2.7.5.amd64.msi `_ (64-bit version) or `python-2.7.5.msi `_ (32-bit version). - Add the path to the Python directory containing **Python.exe** to your PATH. - - Paths are set by opening **System Settings | Advanced system properties**, clicking **Environment Variables** and select **PATH**. + - Paths are set by opening **System Settings | Advanced system properties**, clicking **Environment Variables** and selecting **PATH**. - Add the path to python, separated by semicolons: e.g. ``;C:/Python27/;`` or ``;C:/Python27/bin;`` (depending on the location of the exe). -#. Install `node.js `_ +#. Install `node.js `_: - - For example `node-v0.10.17-x64.msi `_ (64-bit version) or `node-v0.10.17-x86.msi `_. (32-bit version). + - For example `node-v0.10.17-x64.msi `_ (64-bit version) or `node-v0.10.17-x86.msi `_ (32-bit version). -#. Install `gcc 4.6 `_ +#. Install `gcc 4.6 `_. + +#. Install `cmake `_. #. Install `Github for Windows `_ (or any other git client). -#. Install `Java `_ +#. Install `Java `_. #. Build :term:`Fastcomp` (LLVM + Clang) from source using :ref:`these instructions `. #. Clone the `kripken/emscripten `_ repository from Github. This repository contains the main compiler tool for compiling C/C++ programs to JavaScript: - Using *Github for Windows*: - - Launch the *GitHub for Windows* Client. Click **Skip Setup** if you don't have a github account. + - Launch the *GitHub for Windows* Client. Click **Skip Setup** if you don't have a Github account. - (optional) Select **Options** from the gear menu, and customize the default storage directory. Ensure the path has no spaces. - In your web browser, open https://github.com/kripken/emscripten and press the **Clone in Windows** button. @@ -74,7 +76,7 @@ Instructions for creating and manually configuring this file are given in :ref:` Validating the environment =============================== -The best way to validate the environment is to build some code. Open the terminal in your *Emscripten* directory - the directory which contains *emcc* (if you installed using *Github for Windows* this will be **C:/Users/username/Documents/GitHub/emscripten**) and enter: :: +The best way to validate the environment is to build some code. Open the terminal in your *Emscripten* directory — the directory which contains *emcc* (if you installed using *Github for Windows* this will be **C:/Users/username/Documents/GitHub/emscripten**) and enter: :: emcc tests/hello_world.cpp diff --git a/site/source/docs/building_from_source/configuring_emscripten_settings.rst b/site/source/docs/building_from_source/configuring_emscripten_settings.rst index 3dcd2408535f5..f0f24001401eb 100644 --- a/site/source/docs/building_from_source/configuring_emscripten_settings.rst +++ b/site/source/docs/building_from_source/configuring_emscripten_settings.rst @@ -65,11 +65,11 @@ Editing the compiler configuration file The compiler configuration file can be edited with the text-editor of your choice. As stated above, most default settings are likely to be correct. If you're building manually from source, you are most likely to have to update the variable ``LLVM_ROOT`` (for :term:`Fastcomp`). -#. Edit the variable ``LLVM_ROOT`` to point directly to the path where you :ref:`built Fastcomp `. This path is likely to be something like **/build/Release/bin** or /build/bin**, where ```` is wherever you cloned LVVM: +#. Edit the variable ``LLVM_ROOT`` to point directly to the path where you :ref:`built Fastcomp `. This path is likely to be something like **/build/Release/bin** or /build/bin**, where ```` is wherever you cloned LLVM: :: - LLVM_ROOT = 'os.path.expanduser(os.getenv('LVVM') or '/home/ubuntu/a-path/emscripten-fastcomp/build/bin')' + LLVM_ROOT = 'os.path.expanduser(os.getenv('LLVM') or '/home/ubuntu/a-path/emscripten-fastcomp/build/bin')' .. note:: Use forward slashes! diff --git a/site/source/docs/building_from_source/manually_integrating_emscripten_with_vs2010.rst b/site/source/docs/building_from_source/manually_integrating_emscripten_with_vs2010.rst index da8a84bafcf79..2490bd3568c40 100644 --- a/site/source/docs/building_from_source/manually_integrating_emscripten_with_vs2010.rst +++ b/site/source/docs/building_from_source/manually_integrating_emscripten_with_vs2010.rst @@ -6,18 +6,18 @@ Manually Integrating Emscripten into Visual Studio 2010 (ready-for-review) .. tip:: The :term:`vs-tool` plugin is installed automatically by the :term:`Windows NSIS Installer Emscripten SDK` if *Visual Studio 2010* is present on the target system at install time. These instructions are only needed if you're :ref:`manually building from source `, or for some other reason cannot use the SDK. -*vs-tool* is a *MSBuild* plugin that tells *Visual Studio* how to use the *Fastcomp* (LVVM + Clang) and Emscripten toolchain. The plugin allows existing Visual Studio **.sln** files to be directly built through the IDE using :ref:`emcc `. The Microsoft compiler property pages are replaced by *Fastcomp*- and *emcc*- specific options. +*vs-tool* is an *MSBuild* plugin that tells *Visual Studio* how to use the *Fastcomp* (LLVM + Clang) and Emscripten toolchain. The plugin allows existing Visual Studio **.sln** files to be directly built through the IDE using :ref:`emcc `. The Microsoft compiler property pages are replaced by *Fastcomp*- and *emcc*- specific options. The following instructions explain how to manually set up *vs-tool*. -.. note:: `At time of writing `_ *vs-tool* only supports Visual Studio 2010. +.. note:: Currently (August 2014) *vs-tool* `only supports `_ Visual Studio 2010. Install the vs-tool plugin ============================ -1. Install Visual Studio 2010 +1. Install `Visual Studio 2010 `_: - .. note:: The Express version has not been tested, but should be work. :ref:`contact` if you have any problems integrating with VS2010 Express! + .. note:: The `Express `_ version has not been tested, but should work. :ref:`contact` if you have any problems integrating with VS2010 Express! #. Clone the juj/vs-tool repository from github: @@ -25,21 +25,22 @@ Install the vs-tool plugin git clone https://github.com/juj/vs-tool -#. Install vs-tool itself: +#. Install the *vs-tool* plugin: - #. Navigate to folder **vs-tool** in the repository clone. + #. Navigate to the **vs-tool** folder in the repository clone. #. Copy the folders **Clang** and **Emscripten** to **C:/Program Files (x86)/MSBuild/Microsoft.Cpp/v4.0/Platforms/**. #. Set up the required environment variables for *vs-tool*. #. Windows 7: Open **Control Panel | System | Advanced System Settings | Environment Variables**. + #. Windows 8: Right click on the **Windows menu icon | System | Advanced System Settings | Environment Variables**. #. Create a new environment variable ``CLANG_BIN`` and set it to point to the folder where you built *Fastcomp* (path to **clang.exe**) E.g.: :: SETX CLANG_BIN C:/Projects/llvm-build/bin/Release - This variable is how *vs-tool* locates the folder to your *Fastcomp* compiler. Alternatively, this path can be set on a per-project basis in the *Visual Studio project property* pages. + This variable is how *vs-tool* locates the folder containing your *Fastcomp* compiler. Alternatively, this path can be set on a per-project basis in the *Visual Studio project property* pages. #. Create a new environment variable ``EMSCRIPTEN`` and set it to point to the Emscripten git repository root folder (the path where you copied **emcc.exe** and the other exes). E.g.: @@ -49,20 +50,20 @@ Install the vs-tool plugin This variable is how *vs-tool* locates the Emscripten compiler. This path can also be overridden on a per-project basis in the Visual Studio property pages. - #. Create a new environment variable ``EMCC_WEBBROWSER_EXE`` and set it to point to an executable you want to use to browse in Emscripten-generated web pages from Visual Studio. This process is spawned when you tap **Start** (**Ctrl-F5**) in Visual Studio for an Emscripten-targeted project: + #. Create a new environment variable ``EMCC_WEBBROWSER_EXE`` and set it to point to an executable you want to use to browse web pages generated using Emscripten via Visual Studio. This process is spawned when you tap **Start** (**Ctrl-F5**) in Visual Studio for an Emscripten-targeted project: :: SETX EMCC_WEBBROWSER_EXE C:/Program Files (x86)/Mozilla Firefox/firefox.exe -#. Now you are all set to start developing Emscripten-based projects from *Visual Studio*. +#. Now you are all set to start developing Emscripten-based projects using *Visual Studio*. Test the installation ====================== To test the installation, open and build the Visual Studio solution file **/emscripten/tests/msvc10/tests_msvc10.sln**. -That project builds a few select samples from inside the Emscripten **tests/** folder (for example "hello world", "hello gles", etc.), and is a good verification of the integration. +That project builds a few select samples from inside the Emscripten **tests/** folder ("hello world", "hello gles", etc.), and is a good verification of the integration. Learn more diff --git a/site/source/docs/building_from_source/toolchain_what_is_needed.rst b/site/source/docs/building_from_source/toolchain_what_is_needed.rst index aff71252eac2c..24101a2661555 100644 --- a/site/source/docs/building_from_source/toolchain_what_is_needed.rst +++ b/site/source/docs/building_from_source/toolchain_what_is_needed.rst @@ -1,21 +1,24 @@ .. _emscripten-toolchain-top: -======================================= -Emscripten Toolchain (ready-for-review) -======================================= +================================= +Emscripten Toolchain Requirements +================================= The instructions below list the main tools and dependencies in an Emscripten environment, along with instructions on how to test which dependencies are installed. -.. tip:: The :ref:`SDK ` provides the **easiest** and **most reliable** method for getting, using, updating and managing Emscripten environments, including **building from source**. If you're using the SDK you won't *need* these instructions, and they are provided for information only. +.. tip:: The :ref:`SDK ` provides the **easiest** and **most reliable** method for getting, using, updating and managing Emscripten environments, including **building from source**. If you're using the SDK you won't *need* these instructions — they are provided for information only. - The instructions are useful if you're :ref:`manually ` building from source. + The instructions below are useful if you're :ref:`manually ` building from source. .. _toolchain-what-you-need: What you'll need ================ -A complete Emscripten environment includes the following tools: +Emscripten tools and dependencies +--------------------------------- + +A complete Emscripten environment requires the following tools. First test to see if they are already installed using the :ref:`instructions below `. Then install any missing tools using the instructions in the appropriate platform-specific build topic (:ref:`building-emscripten-on-linux`, :ref:`building-emscripten-on-windows-from-source`, :ref:`building-emscripten-on-mac-osx-from-source`): - :term:`Node.js` (0.8 or above; 0.10.17 or above to run websocket-using servers in node): - :term:`Python` 2.x (2.7.3 or above preferred) @@ -26,11 +29,27 @@ A complete Emscripten environment includes the following tools: .. note: 64-bit versions of all needed dependencies are preferred, and may be required if you are building large projects. -When building manually from sources you will also need a compiler environment (to build :ref:`Fastcomp `): +.. note:: The `Spidermonkey shell `_ is also required if you want to run **100%** of the tests in the test suite. Most developers will not need this, and should instead use *node.js*. + +.. _compiler-toolchain: + +Compiler toolchain +------------------ - - *gcc* (4.6 or later) +When building Emscripten from source code, whether "manually" or using the SDK, you will also need a compiler toolchain: + +- On Windows install `gcc 4.6 `_ +- On Linux install *gcc* from the **build-essential** package: + + :: + + sudo apt-get install build-essential -.. note:: The *Spidermonkey* shell is also required if you want to run **100%** of the tests in the test suite. Most developers will not need this, and need only *node.js*. +- On Mac OS X install the *XCode Command Line Tools*: + + - Install XCode from the `Mac OS X App Store `_. + - In **XCode | Preferences | Downloads**, install *Command Line Tools*. + .. _toolchain-test-which-dependencies-are-installed: @@ -39,7 +58,7 @@ Test which tools are installed Some of the tools are pre-installed on the various platforms (for example, Python is always available on Linux builds). -You can check which tools are already present and only install those files that are needed: +You can check which tools are already present using the following commands: :: @@ -50,7 +69,10 @@ You can check which tools are already present and only install those files that nodejs --version # Check for node.js on Windows - node --version # + node --version # + + # Check for node.js on Mac OS X + node -v # Check for git git --version @@ -61,3 +83,7 @@ You can check which tools are already present and only install those files that # Check for gcc / g++ gcc --version g++ + + # Check for cmake + cmake + diff --git a/site/source/docs/building_from_source/verify_emscripten_environment.rst b/site/source/docs/building_from_source/verify_emscripten_environment.rst index a15fb2ce74a7b..a31d89cb6f3ec 100644 --- a/site/source/docs/building_from_source/verify_emscripten_environment.rst +++ b/site/source/docs/building_from_source/verify_emscripten_environment.rst @@ -21,7 +21,7 @@ Open a terminal in the directory in which you installed Emscripten (on Windows o ./emcc -v -.. note:: On Windows, invoke the tool with **emsdk** instead of **./emsdk**: +.. note:: On Windows, invoke the tool with **emsdk** instead of **./emsdk**. For example, the following output reports an installation where Java is missing: diff --git a/site/source/docs/getting_started/Tutorial.rst b/site/source/docs/getting_started/Tutorial.rst index 0d4637b31ee19..3ceec1c1f43ac 100644 --- a/site/source/docs/getting_started/Tutorial.rst +++ b/site/source/docs/getting_started/Tutorial.rst @@ -56,7 +56,7 @@ To build the JavaScript version of this code we simply specify the C++ file afte emcc tests/hello_world.cpp -There should now be an **a.out.js** file in the current directory. Run it using :term:`node`: +There should now be an **a.out.js** file in the current directory. Run it using :term:`node.js`: :: @@ -149,7 +149,7 @@ The optimizations provided by ``-O2`` are much more aggressive. If you run the f emcc -O2 tests/hello_world.cpp -For more information about compiler optimization options see :ref:`Optimizing-Code` and the :ref:`emcc tool reference`. +For more information about compiler optimization options see :ref:`Optimizing-Code` and the :ref:`emcc tool reference `. .. _running-emscripten-tests: @@ -179,7 +179,7 @@ To view the generated code from that individual test, you can first set ``EMCC_D The generated code is copied into the the temp directory (**TEMP_DIR/emscripten_temp**, where ``TEMP_DIR`` is defined in :ref:`~/.emscripten `. By default the temporary directory location is **/tmp**). -.. note:: You can use ``EMCC_DEBUG`` with :ref:`emcc ` as well (not just with the test runner). This tells *emcc* to save the internal code generation stages (much like ``emcc -v``). +.. note:: You can use ``EMCC_DEBUG`` with :ref:`emcc ` as well (not just with the test runner). This tells *emcc* to save the internal code generation stages (much like ``emcc -v``). You can also specify ``EM_SAVE_DIR=1`` in the environment (this is a test suite specific feature) to save the temporary directory that the test runner users to the same place as mentioned in the previous paragraph. This is useful if the test being run creates temporary files. @@ -203,5 +203,5 @@ This tutorial walked you through your first steps in calling Emscripten from the - This site has lots more information about :ref:`compiling and building projects `, :ref:`integrating your native code with the web environment `, :ref:`packaging your code ` and publishing. - The Emscripten test suite is a great place to look for examples of how to use Emscripten. For example, if you want to better understand how the *emcc* ``--pre-js`` option works, search for ``--pre-js`` in the test suite: the test suite is extensive and there are likely to be at least some examples. -- To learn how to use Emscripten in advanced ways, read :ref:`src/settings.js ` and :ref:`emcc ` which describe the compiler options, and :ref:`emscripten-h` which describes JavaScript-specific C APIs that your C/C++ programs can use when compiled with Emscripten. +- To learn how to use Emscripten in advanced ways, read :ref:`src/settings.js ` and :ref:`emcc ` which describe the compiler options, and :ref:`emscripten-h` which describes JavaScript-specific C APIs that your C/C++ programs can use when compiled with Emscripten. - When in doubt, :ref:`get in touch `! diff --git a/site/source/docs/getting_started/downloads.rst b/site/source/docs/getting_started/downloads.rst index 9073ec6e032af..371c4623c9451 100644 --- a/site/source/docs/getting_started/downloads.rst +++ b/site/source/docs/getting_started/downloads.rst @@ -130,29 +130,17 @@ You can jump ahead to the :ref:`Tutorial`, but if you have any problems building .. _sdk-building-emscripten-from-source: Building Emscripten from source -====================================================== +=============================== The SDK can be used to fetch and build the latest version of Emscripten from source. This allows you to obtain new features and the latest fixes as soon as they are pushed to Github (without having to wait for release to be tagged). **No Github account or fork of Emscripten is required!** -.. note:: The SDK is the recommended method of building Emscripten from source because it makes the process very easy, and allows you to treat the build as "just another SDK". Using the SDK allows you to easily toggle between the current SDK, older SDKs, and source-built environments, and to update to new SDKs and source updates as they become available. +.. tip:: The SDK is the recommended method of building Emscripten from source because it makes the process very easy, and allows you to treat the build as "just another SDK". Using the SDK allows you to easily toggle between the current SDK, older SDKs, and source-built environments, and to update to new SDKs and source updates as they become available. It is also possible to :ref:`manually build from source `, but this approach is more difficult, incompatible with the :ref:`SDK manager `, and in general not really needed, unless you are contributing to Emscripten development itself (as opposed to just using it). -You will also need a compiler toolchain to build from source: - - - On Windows install `gcc 4.6 `_ - - On Linux install *gcc* from the **build-essential** package: - - :: - - sudo apt-get install build-essential - - - On Mac OS X install the *XCode Command Line Tools*: - - - Install XCode from the `Mac OS X App Store `_. - - In **XCode | Preferences | Downloads**, install *Command Line Tools*. +.. note:: You will need a :ref:`compiler-toolchain` to build the code (the link explains where you get the toolchain for each of the platforms). -To switch to using the latest upstream git development branch (``incoming``), run the following commands: +To start using the latest upstream git development branch (``incoming``), run the following commands: :: diff --git a/site/source/docs/getting_started/getting_started_with_emscripten_and_vs2010.rst b/site/source/docs/getting_started/getting_started_with_emscripten_and_vs2010.rst index 249ba6ebeb206..f3818c9c4a5d9 100644 --- a/site/source/docs/getting_started/getting_started_with_emscripten_and_vs2010.rst +++ b/site/source/docs/getting_started/getting_started_with_emscripten_and_vs2010.rst @@ -1,4 +1,4 @@ -.. getting-started-emscripten-from-vs2010: +.. _getting-started-emscripten-from-vs2010: =========================================================================================== Getting started using Emscripten from the Visual Studio 2010 IDE (under-construction) diff --git a/site/source/docs/site/glossary.rst b/site/source/docs/site/glossary.rst index 98dae7a4d982e..8bfbb6ee18c4f 100644 --- a/site/source/docs/site/glossary.rst +++ b/site/source/docs/site/glossary.rst @@ -3,6 +3,14 @@ Glossary (under-construction) =============================== +.. glossary:: + :sorted: + + xhr + **HamishW** + + LLVM backend + A (*Clang*) compiler backend that convert the LLVM Intermediate Representation (IR) to code for a specified machine or other languages. In the case of Emscripten, the specified target is JavaScript. Emscripten tools and dependencies ======================================= From a91fb06712a3c108812d47d1673ade725f9c3d27 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Tue, 12 Aug 2014 12:10:19 -0700 Subject: [PATCH 28/91] make browser.test_glgears_proxy more robust --- tests/test_browser.py | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/tests/test_browser.py b/tests/test_browser.py index 4cdca6e5e311f..aac4a0fa81311 100644 --- a/tests/test_browser.py +++ b/tests/test_browser.py @@ -756,16 +756,21 @@ def test_glgears_proxy(self): # run with noProxy self.run_browser('test.html?noProxy', None, ['/report_result?0']) - # run with noProxy, but make main thread fail original = open('test.js').read() - open('test.js', 'w').write(original.replace('function _main($argc,$argv) {', 'function _main($argc,$argv) { if (ENVIRONMENT_IS_WEB) { var xhr = new XMLHttpRequest(); xhr.open("GET", "http://localhost:8888/report_result?999");xhr.send(); }')) - self.run_browser('test.html?noProxy', None, ['/report_result?999']) - self.run_browser('test.html', None, ['/report_result?0']) # this is still cool + + def copy(to, js_mod): + open(to + '.html', 'w').write(open('test.html').read().replace('test.js', to + '.js')) + open(to + '.js', 'w').write(js_mod(open('test.js').read())) + + # run with noProxy, but make main thread fail + copy('two', lambda original: original.replace('function _main($argc,$argv) {', 'function _main($argc,$argv) { if (ENVIRONMENT_IS_WEB) { var xhr = new XMLHttpRequest(); xhr.open("GET", "http://localhost:8888/report_result?999");xhr.send(); }')) + self.run_browser('two.html?noProxy', None, ['/report_result?999']) + self.run_browser('two.html', None, ['/report_result?0']) # this is still cool # run without noProxy, so proxy, but make worker fail - open('test.js', 'w').write(original.replace('function _main($argc,$argv) {', 'function _main($argc,$argv) { if (ENVIRONMENT_IS_WORKER) { var xhr = new XMLHttpRequest(); xhr.open("GET", "http://localhost:8888/report_result?999");xhr.send(); }')) - self.run_browser('test.html', None, ['/report_result?999']) - self.run_browser('test.html?noProxy', None, ['/report_result?0']) # this is still cool + copy('three', lambda original: original.replace('function _main($argc,$argv) {', 'function _main($argc,$argv) { if (ENVIRONMENT_IS_WORKER) { var xhr = new XMLHttpRequest(); xhr.open("GET", "http://localhost:8888/report_result?999");xhr.send(); }')) + self.run_browser('three.html', None, ['/report_result?999']) + self.run_browser('three.html?noProxy', None, ['/report_result?0']) # this is still cool def test_glgears_proxy_jstarget(self): # test .js target with --proxy-worker; emits 2 js files, client and worker From a9e91a7bd327b9d94ff223cd087d0ff78b158c12 Mon Sep 17 00:00:00 2001 From: Lu Wang Date: Thu, 31 Jul 2014 14:13:45 -0700 Subject: [PATCH 29/91] support coroutine valid asm.js better test case for coroutine coding style fix asm.js fix test case save STACK_MAX for coroutine customized stack size for coroutine move doc to new stie fix typo --- .../docs/api_reference/emscripten.h.rst | 33 ++++++ src/library_async.js | 103 +++++++++++++++++- src/settings.js | 3 +- system/include/emscripten/emscripten.h | 10 +- tests/test_core.py | 49 +++++++++ 5 files changed, 188 insertions(+), 10 deletions(-) diff --git a/site/source/docs/api_reference/emscripten.h.rst b/site/source/docs/api_reference/emscripten.h.rst index 18a7db5878968..1796f83f45264 100644 --- a/site/source/docs/api_reference/emscripten.h.rst +++ b/site/source/docs/api_reference/emscripten.h.rst @@ -995,3 +995,36 @@ Typedefs .. note:: It is better to avoid unaligned operations, but if you are reading from a packed stream of bytes or such, these types may be useful! +Asyncify functions +================== + +Asyncify functions are asynchronous functions that appear synchronously in C, the linker flag `-s ASYNCIFY=1` is required to use these functions. See `Asyncify `_ for more details. + +Typedefs +-------- + +.. c:type:: emscripten_coroutine + + A handle to the strcture used by coroutine supporting functions. + +Functions +--------- + +.. c::function:: void emscripten_sleep(unsinged int ms) + + Sleep for `ms` milliseconds. + +.. c::function:: emscripten_coroutine emscripten_coroutine_create(em_arg_callback_func func, void *arg, int stack_size) + + Create a coroutine which will be run as `func(arg)`. + + :param int stack_size: the stack size that should be allocated for the coroutine, use 0 for the default value. + +.. c::function:: int emscripten_coroutine_next(emscripten_coroutine coroutine) + + Run `coroutine` until it returns, or `emscripten_yield` is called. A non-zero value is returned if `emscripten_yield` is called, otherwise 0 is returned, and future calls of `emscripten_coroutine_next` on this coroutine is undefined behaviour. + +.. c::function:: void emscripten_yield(void) + + This function should only be called in a coroutine created by `emscripten_coroutine_create`, when it called, the coroutine is paused and the caller will continue. + diff --git a/src/library_async.js b/src/library_async.js index ee3d554c1cea7..bdd910b57785c 100644 --- a/src/library_async.js +++ b/src/library_async.js @@ -1,3 +1,5 @@ +mergeInto(LibraryManager.library, { +#if ASYNCIFY /* * The layout of normal and async stack frames * @@ -13,15 +15,14 @@ * --------------------- <-- STACKTOP * */ - -mergeInto(LibraryManager.library, { -#if ASYNCIFY __async: 0, // whether a truly async function has been called __async_unwind: 1, // whether to unwind the async stack frame __async_retval: 'allocate(2, "i32", ALLOC_STATIC)', // store the return value for async functions __async_cur_frame: 0, // address to the current frame, which stores previous frame, stack pointer and async context - emscripten_async_resume__deps: ['__async', '__async_unwind', '__async_cur_frame'], + // __async_retval is not actually required in emscripten_async_resume + // but we want it included when ASYNCIFY is enabled + emscripten_async_resume__deps: ['__async', '__async_unwind', '__async_retval', '__async_cur_frame'], emscripten_async_resume__sig: 'v', emscripten_async_resume__asm: true, emscripten_async_resume: function() { @@ -99,10 +100,102 @@ mergeInto(LibraryManager.library, { emscripten_do_not_unwind_async: true, emscripten_get_async_return_value_addr__deps: ['__async_retval'], - emscripten_get_async_return_value_addr: true + emscripten_get_async_return_value_addr: true, + +/* + * Layout of a coroutine structure + * + * 0 callee's async ctx + * 4 callee's STACKTOP + * 8 callee's STACK_MAX + * 12 my async ctx + * 16 my STACKTOP + * 20 my stack size + * 24 coroutine function + * 28 coroutine arg + * 32 my stack: + * ... + */ + emscripten_coroutine_create__sig: 'iii', + emscripten_coroutine_create__asm: true, + emscripten_coroutine_create__deps: ['malloc'], + emscripten_coroutine_create: function(f, arg, stack_size) { + f = f|0; + arg = arg|0; + stack_size = stack_size|0; + var coroutine = 0; + + if(stack_size <= 0) stack_size = 4096; + + coroutine = _malloc(stack_size)|0; + {{{ makeSetValueAsm('coroutine', 12, 0, 'i32') }}}; + {{{ makeSetValueAsm('coroutine', 16, '(coroutine+32)', 'i32') }}}; + {{{ makeSetValueAsm('coroutine', 20, 'stack_size', 'i32') }}}; + {{{ makeSetValueAsm('coroutine', 24, 'f', 'i32') }}}; + {{{ makeSetValueAsm('coroutine', 28, 'arg', 'i32') }}}; + return coroutine|0; + }, + emscripten_coroutine_next__sig: 'ii', + emscripten_coroutine_next__asm: true, + emscripten_coroutine_next__deps: ['__async_cur_frame', '__async', 'emscripten_async_resume', 'free'], + emscripten_coroutine_next: function(coroutine) { + coroutine = coroutine|0; + var coroutine_not_finished = 0; + // switch context + {{{ makeSetValueAsm('coroutine', 0, '___async_cur_frame', 'i32') }}}; + {{{ makeSetValueAsm('coroutine', 4, 'stackSave()|0', 'i32') }}}; + {{{ makeSetValueAsm('coroutine', 8, 'STACK_MAX', 'i32') }}}; + ___async_cur_frame = {{{ makeGetValueAsm('coroutine', 12, 'i32') }}}; + stackRestore({{{ makeGetValueAsm('coroutine', 16, 'i32') }}}); + STACK_MAX = coroutine + 32 + {{{ makeGetValueAsm('coroutine', 20, 'i32') }}}; + + if (!___async_cur_frame) { + // first run + dynCall_vi( + {{{ makeGetValueAsm('coroutine', 24, 'i32') }}}, + {{{ makeGetValueAsm('coroutine', 28, 'i32') }}} + ); + } else { + _emscripten_async_resume(); + } + + // switch context + {{{ makeSetValueAsm('coroutine', 12, '___async_cur_frame', 'i32') }}}; + {{{ makeSetValueAsm('coroutine', 16, 'stackSave()|0', 'i32') }}}; + ___async_cur_frame = {{{ makeGetValueAsm('coroutine', 0, 'i32') }}}; + stackRestore({{{ makeGetValueAsm('coroutine', 4, 'i32') }}}); + STACK_MAX = {{{ makeGetValueAsm('coroutine', 8, 'i32') }}}; + + coroutine_not_finished = ___async; + if (!coroutine_not_finished) { + // coroutine has finished + _free(coroutine); + } + // coroutine may be created during an async function + // we do not want to affect the original async ctx + // strictly we should backup and restore ___async, ___async_retval and ___async_unwind + // but ___async=0 seems enough + ___async = 0; + + return coroutine_not_finished|0; + }, + emscripten_yield__sig: 'v', + emscripten_yield__asm: true, + emscripten_yield: function() { + ___async = 1; + } #else // ASYNCIFY emscripten_sleep: function() { throw 'Please compile your program with -s ASYNCIFY=1 in order to use asynchronous operations like emscripten_sleep'; + }, + emscripten_coroutine_create: function() { + throw 'Please compile your program with -s ASYNCIFY=1 in order to use asynchronous operations like emscripten_coroutine_create'; + }, + emscripten_coroutine_next: function() { + throw 'Please compile your program with -s ASYNCIFY=1 in order to use asynchronous operations like emscripten_coroutine_next'; + }, + emscripten_yield: function() { + throw 'Please compile your program with -s ASYNCIFY=1 in order to use asynchronous operations like emscripten_yield'; } #endif }); diff --git a/src/settings.js b/src/settings.js index 3f55d5c3235d3..59bc47f40ffad 100644 --- a/src/settings.js +++ b/src/settings.js @@ -298,7 +298,8 @@ var ASYNCIFY = 0; // Whether to enable asyncify transformation // This allows to inject some async functions to the C code that appear to be sync // e.g. emscripten_sleep var ASYNCIFY_FUNCTIONS = ['emscripten_sleep', // Functions that call any funcion in the list, directly or indirectly - 'emscripten_wget']; // will be transfromed + 'emscripten_wget', // will be transformed + 'emscripten_yield']; var ASYNCIFY_WHITELIST = ['qsort', // Functions in this list are never considered async, even if they appear in ASYNCIFY_FUNCTIONS 'trinkle', // In the asyncify transformation, any function that calls a function pointer is considered async '__toread', // This whitelist is useful when a function is known to be sync diff --git a/system/include/emscripten/emscripten.h b/system/include/emscripten/emscripten.h index c62dbd7d1beaf..44f6eb829028d 100644 --- a/system/include/emscripten/emscripten.h +++ b/system/include/emscripten/emscripten.h @@ -233,16 +233,18 @@ void emscripten_asm_const(const char *code); int emscripten_asm_const_int(const char *code, ...); double emscripten_asm_const_double(const char *code, ...); -/* - * Sleep for `ms` milliseconds - * This function should only be used when ASYNCIFY is enabled - */ #if __EMSCRIPTEN__ void emscripten_sleep(unsigned int ms); #else #define emscripten_sleep SDL_Delay #endif +typedef void * emscripten_coroutine; +emscripten_coroutine emscripten_coroutine_create(em_arg_callback_func func, void *arg, int stack_size); +int emscripten_coroutine_next(emscripten_coroutine); +void emscripten_yield(void); + + #ifdef __cplusplus } #endif diff --git a/tests/test_core.py b/tests/test_core.py index 597d4e8296eca..e5d8136fdae3e 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -6895,6 +6895,55 @@ def test_asyncify(self): Settings.ASYNCIFY = 1; self.do_run(src, 'HelloWorld!99'); + def test_coroutine(self): + if not Settings.ASM_JS: return self.skip('asyncify requires asm.js') + if os.environ.get('EMCC_FAST_COMPILER') == '0': return self.skip('asyncify requires fastcomp') + + src = r''' +#include +#include +void fib(void * arg) { + int * p = (int*)arg; + int cur = 1; + int next = 1; + for(int i = 0; i < 9; ++i) { + *p = cur; + emscripten_yield(); + int next2 = cur + next; + cur = next; + next = next2; + } +} +void f(void * arg) { + int * p = (int*)arg; + *p = 0; + emscripten_yield(); + fib(arg); // emscripten_yield in fib() can `pass through` f() back to main(), and then we can assume inside fib() +} +void g(void * arg) { + int * p = (int*)arg; + for(int i = 0; i < 10; ++i) { + *p = 100+i; + emscripten_yield(); + } +} +int main(int argc, char **argv) { + int i; + emscripten_coroutine co = emscripten_coroutine_create(f, (void*)&i, 0); + emscripten_coroutine co2 = emscripten_coroutine_create(g, (void*)&i, 0); + printf("*"); + while(emscripten_coroutine_next(co)) { + printf("%d-", i); + emscripten_coroutine_next(co2); + printf("%d-", i); + } + printf("*"); + return 0; +} +''' + Settings.ASYNCIFY = 1; + self.do_run(src, '*0-100-1-101-1-102-2-103-3-104-5-105-8-106-13-107-21-108-34-109-*'); + # Generate tests for everything def make_run(fullname, name=-1, compiler=-1, embetter=0, quantum_size=0, typed_arrays=0, emcc_args=None, env=None): From 70a171ee5967373223d7b75a1df4dba11b879aa6 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Tue, 12 Aug 2014 14:32:40 -0700 Subject: [PATCH 30/91] do not pass -g to LLVM if we were passed -gX with low X (less than 4, which is when we do include LLVM debug info); fixes #2657 --- emcc | 6 +++++- tests/test_other.py | 15 +++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/emcc b/emcc index 812b5f646ccfd..3cdf358ad79c7 100755 --- a/emcc +++ b/emcc @@ -948,7 +948,11 @@ try: elif newargs[i].startswith('-g'): requested_level = newargs[i][2:] or '3' debug_level = validate_arg_level(requested_level, 4, 'Invalid debug level: ' + newargs[i]) - newargs[i] = '-g' # we'll need this to get LLVM debug info + if newargs[i] != '-g': + if debug_level >= 4: + newargs[i] = '-g' # we'll need this to get LLVM debug info + else: + newargs[i] = '' elif newargs[i] == '-profiling': debug_level = 2 profiling = True diff --git a/tests/test_other.py b/tests/test_other.py index 45570a09a4adf..1233c1f69f6cc 100644 --- a/tests/test_other.py +++ b/tests/test_other.py @@ -3928,3 +3928,18 @@ def test(args, be_clean): test(['-o', 'c.html'], True) test(['-c'], False) + def dash_g_bc(self): + def get_size(name): + return len(open(name).read()) + Popen([PYTHON, EMCC, path_from_root('tests', 'hello_world.c'), '-o', 'a_.bc']).communicate() + sizes = { '_': get_size('a_.bc') } + Popen([PYTHON, EMCC, path_from_root('tests', 'hello_world.c'), '-g', '-o', 'ag.bc']).communicate() + sizes['g'] = get_size('ag.bc') + for i in range(0, 5): + Popen([PYTHON, EMCC, path_from_root('tests', 'hello_world.c'), '-g' + str(i), '-o', 'a' + str(i) + '.bc']).communicate() + sizes[i] = get_size('a' + str(i) + '.bc') + print sizes + assert sizes['_'] == sizes[0] == sizes[1] == sizes[2] == sizes[3], 'no debug or <4 debug, means no llvm debug info' + assert sizes['g'] == sizes[4], '-g or -g4 means llvm debug info' + assert sizes['_'] < sizes['g'], 'llvm debug info has positive size' + From d83e83b062fdd7a0feb24bb8e757dfb2736f3313 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Tue, 12 Aug 2014 14:41:08 -0700 Subject: [PATCH 31/91] allow websocket urls with slashes; fixes #2610 --- src/library_sockfs.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/library_sockfs.js b/src/library_sockfs.js index 6bd68b659156e..a460408e21e2e 100644 --- a/src/library_sockfs.js +++ b/src/library_sockfs.js @@ -180,7 +180,8 @@ mergeInto(LibraryManager.library, { } if (url === 'ws://' || url === 'wss://') { // Is the supplied URL config just a prefix, if so complete it. - url = url + addr + ':' + port; + var parts = addr.split('/'); + url = url + parts[0] + ":" + port + "/" + parts.slice(1).join('/'); } // Make the WebSocket subprotocol (Sec-WebSocket-Protocol) default to binary if no configuration is set. From 78ad1fc003a9907eff73b5fdde3e1b0d11e597e7 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Tue, 12 Aug 2014 15:08:18 -0700 Subject: [PATCH 32/91] verify file packager paths do not contain invalid characters; fixes #2649 --- tools/file_packager.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tools/file_packager.py b/tools/file_packager.py index 1a5c14259e3a4..fb3919c11a104 100644 --- a/tools/file_packager.py +++ b/tools/file_packager.py @@ -69,13 +69,17 @@ AV_WORKAROUND = 0 # Set to 1 to randomize file order and add some padding, to work around silly av false positives +def verify_paths(file_): + if file_['dstpath'].find('"') >= 0 or file_['dstpath'].find("'") >= 0: + raise Exception('''invalid file path: %s, should not contain illegal characters ('")''' % file_['dstpath']) + data_files = [] excluded_patterns = [] leading = '' has_preloaded = False compress_cnt = 0 crunch = 0 -plugins = [] +plugins = [verify_paths] jsoutput = None force = True # If set to True, IndexedDB (IDBFS in library_idbfs.js) is used to locally cache VFS XHR so that subsequent From f30112c86e5595a9be52b6ebc52a1e1291acb2bf Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Tue, 12 Aug 2014 15:51:05 -0700 Subject: [PATCH 33/91] add VoidPtr type to WebIDL binder, for void* --- .../connecting_cpp_and_javascript/WebIDL-Binder.rst | 8 ++++++++ tests/webidl/output.txt | 1 + tests/webidl/post.js | 1 + tests/webidl/test.h | 1 + tests/webidl/test.idl | 1 + tools/webidl_binder.py | 7 +++++-- 6 files changed, 17 insertions(+), 2 deletions(-) diff --git a/site/source/docs/coding/connecting_cpp_and_javascript/WebIDL-Binder.rst b/site/source/docs/coding/connecting_cpp_and_javascript/WebIDL-Binder.rst index adf810df01a85..fa488afcc6d46 100644 --- a/site/source/docs/coding/connecting_cpp_and_javascript/WebIDL-Binder.rst +++ b/site/source/docs/coding/connecting_cpp_and_javascript/WebIDL-Binder.rst @@ -318,3 +318,11 @@ JavaScript builtin object) or 0. The reason is that by always returning a wrapper, you can always take the output and pass it back to another binding function, without that function needing to check the type of the argument. + +void* +~~~~~ + +The ``void*`` type is supported through a ``VoidPtr`` type which you can use +in IDL files. + + diff --git a/tests/webidl/output.txt b/tests/webidl/output.txt index 138d1445eb5e7..e8291d87a2679 100644 --- a/tests/webidl/output.txt +++ b/tests/webidl/output.txt @@ -2,6 +2,7 @@ Parent:42 * 84 object +object c1 Parent:7 Child1:7 diff --git a/tests/webidl/post.js b/tests/webidl/post.js index 712f4e58db6c9..8b5943632f9dd 100644 --- a/tests/webidl/post.js +++ b/tests/webidl/post.js @@ -7,6 +7,7 @@ TheModule.print('*') TheModule.print(sme.getVal()); sme.parentFunc(90); TheModule.print(typeof sme.getAsConst()); +TheModule.print(typeof sme.voidStar(sme)); TheModule.print('c1'); diff --git a/tests/webidl/test.h b/tests/webidl/test.h index 7cd81b3c4fc98..39d8e44ccb1eb 100644 --- a/tests/webidl/test.h +++ b/tests/webidl/test.h @@ -12,6 +12,7 @@ class Parent { void mulVal(int mul); void parentFunc() {} const Parent *getAsConst() { return NULL; } + void *voidStar(void *something) { return something; } }; class Child1 : public Parent { diff --git a/tests/webidl/test.idl b/tests/webidl/test.idl index ab8b3e8a019d0..d01af02045321 100644 --- a/tests/webidl/test.idl +++ b/tests/webidl/test.idl @@ -7,6 +7,7 @@ interface Parent { void mulVal(long mul); void parentFunc(); [Const] Parent getAsConst(); + VoidPtr voidStar(VoidPtr something); }; interface Child1 { diff --git a/tools/webidl_binder.py b/tools/webidl_binder.py index cfe38965818f9..abbbf7324e764 100644 --- a/tools/webidl_binder.py +++ b/tools/webidl_binder.py @@ -29,7 +29,10 @@ def getExtendedAttribute(self, name): shared.try_delete(output_base + '.js') p = WebIDL.Parser() -p.parse(open(input_file).read()) +p.parse(r''' +interface VoidPtr { +}; +''' + open(input_file).read()) data = p.finish() interfaces = {} @@ -159,7 +162,7 @@ def type_to_c(t, non_pointing=False): return 'double' elif t == 'Boolean': return 'bool' - elif t == 'Any': + elif t == 'Any' or t == 'VoidPtr': return 'void*' elif t in interfaces: return (interfaces[t].getExtendedAttribute('Prefix') or [''])[0] + t + ('' if non_pointing else '*') From 00aab8dc63133c72ad7d5bb8b5ecf28ecc8aac32 Mon Sep 17 00:00:00 2001 From: hamishwillee Date: Wed, 13 Aug 2014 18:17:06 +1000 Subject: [PATCH 34/91] Build from source section updates. New standalone docs for SDK. Clear messaging on which should be used where: --- .../building_from_source/LLVM-Backend.rst | 257 ++---------------- ...ilding_emscripten_from_source_on_linux.rst | 18 +- ...ing_emscripten_from_source_on_mac_os_x.rst | 16 +- ...ding_emscripten_from_source_on_windows.rst | 16 +- ...g_emscripten_from_source_using_the_sdk.rst | 155 +++++++++++ ...building_fastcomp_manually_from_source.rst | 144 ++++++++++ .../configuring_emscripten_settings.rst | 17 +- .../docs/building_from_source/index.rst | 17 +- .../toolchain_what_is_needed.rst | 12 +- .../verify_emscripten_environment.rst | 2 +- .../source/docs/getting_started/downloads.rst | 42 +-- site/source/docs/tools_reference/emsdk.rst | 14 +- 12 files changed, 391 insertions(+), 319 deletions(-) create mode 100644 site/source/docs/building_from_source/building_emscripten_from_source_using_the_sdk.rst create mode 100644 site/source/docs/building_from_source/building_fastcomp_manually_from_source.rst diff --git a/site/source/docs/building_from_source/LLVM-Backend.rst b/site/source/docs/building_from_source/LLVM-Backend.rst index d48da501a6021..05429666fee4c 100644 --- a/site/source/docs/building_from_source/LLVM-Backend.rst +++ b/site/source/docs/building_from_source/LLVM-Backend.rst @@ -1,242 +1,40 @@ .. _LLVM-Backend: ==================================================== -LLVM Backend ("Fastcomp") (under-construction) +LLVM Backend ("Fastcomp") (ready-for-review) ==================================================== -*Fastcomp* is the default compiler core for Emscripten. It is a new :term:`LLVM backend` that converts the LLVM Intermediate Representation (IR) created by *Clang* (from C/C++) into JavaScript. - -The backend is still too new to be in the upstream LLVM repository. As such, builds from Linux distributions will **not** contain *Fastcomp*, and Emscripten will report an error if you try to use them. Instead you will need to use the Emscripten fork of LLVM, which you can either build from source or get as part of the :ref:`Emscripten SDK `. - -This article explains how to get *Fastcomp* — either from the SDK or by building it from source. There is also a :ref:`fastcomp-faq` at the very end for troubleshooting *Fastcomp* problems. - - -.. note:: *Fastcomp* was turned on by default in version 1.12.1. It replaces the :ref:`original compiler core `, which is now "deprecated". While it is possible to manually disable Fastcomp and build the original compiler from source (binaries are no longer provided), this is discouraged. - - The article also explains the reasons for changing to *Fastcomp*, and how you can use the old compiler if needed. +This article introduces *Fastcomp*, Emscripten's LLVM + Clang implementation. It explains how you can obtain the tool, why it replaced the :ref:`original compiler core `, and how you can turn off *Fastcomp* if needed. There is also a :ref:`fastcomp-faq` at the very end for troubleshooting *Fastcomp* problems. .. todo:: Emscripten tool (emcc) links to original wiki page when you use the wrong clang. Should point to here instead. - -Getting Fastcomp +Fastcomp overview ================ -*Fastcomp* (Clang) is part of the SDK, and the binaries are automatically installed during installation (except on Linux, where pre-built binaries are not supplied so the SDK builds them for you). - -It is also possible to build Fastcomp from source as a :ref:`fully manual process ` or :ref:`using the SDK ` (recommended). - -.. _building-fastcomp-from-source-using-the-sdk: - -Building Fastcomp from source using the SDK -============================================ - -The SDK (:term:`emsdk`) supports building *Fastcomp* from :ref:`the master or incoming branches `, or from :ref:`your own fork ` of these branches. The former allows you to get the latest and greatest code, while the later lets you additionally make and contribute your own modifications. - -.. tip:: This approach is recommended over :ref:`building-fastcomp-from-source` because the SDK does all the work of getting the correct sources and tools for each branch, and guides you through the build process. - -You can see the *Clang* SDK targets for this using ``./emsdk list``: :: - - clang-incoming-32bit - clang-incoming-64bit - clang-master-32bit - clang-master-64bit - -.. note:: - - - To build from source you first need to install a :ref:`compiler-toolchain` (see link for installation instructions). - - If you are building a large project, you will need a 64-bit build of LLVM and Clang. Compiling and optimizing can take more memory than is available to the 32-bit build. - -To get and build the latest upstream git development branch (``incoming``), run the following: - -:: - - # Install git. Skip if git is already installed. - ./emsdk install git-1.8.3 - - # Clone+pull the latest **/kripken/emscripten-fastcomp-clang** and **/kripken/emscripten-fastcomp** - ./emsdk install clang-incoming-64bit - - # Set the "incoming SDK" as the active version. - ./emsdk activate clang-incoming-64bit - -If you want to use the upstream stable branch ``master``, then replace ``-incoming-`` with ``-master-`` in the commands above. This is all you need to do to get the latest version of *Fastcomp*. - -.. note:: On Windows, *git* may fail with the error message: - - :: - - Unable to find remote helper for 'https' when cloning a repository with https:// url. - - The workaround is to uninstall git from *emsdk* (``emsdk uninstall git-1.8.3``) and install `Git for Windows `_. This issue is reported `here `_. - -.. todo:: **HamishW** Check whether the bug (https://github.com/juj/emsdk/issues/13) is fixed and remove the above note if it is. - -If you're :ref:`contributing` to Emscripten you will instead want to use a fork of the *incoming* branch on Github (so that you can make pull requests back to the project). - -The way this works is that you first install the ``clang-incoming-64bit`` SDK target (as explained above). Then you use familiar *git* commands to replace this branch with the information from your own fork. These commands are the same that are used when :ref:`building-fastcomp-from-source`: - -:: - - cd clang/fastcomp/src - - ## Get your fork of LLVM - - # Add a git remote link to your LLVM repository fork. - git remote add myllvmremote https://github.com/mygituseraccount/emscripten-fastcomp.git - - # Obtain the changes in the remote. - git fetch myllvmremote - - # Checkout the code in your LLVM fork to replace the original repository code - git checkout -b myllvmremote --track myremote/incoming - - - ## Get your fork of Clang - - # Add a git remote link to your Clang repository fork. - git remote add myclangremote https://github.com/mygituseraccount/emscripten-fastcomp-clang.git - - # Obtain the changes in the remote. - git fetch myclangremote - - # Checkout the code in your Clang fork to replace the original repository code - git checkout -b myclangremote --track myclangremote/incoming - - # At this point the clang-incoming-64bit target now points to your fork. - -You can switch back and forth between remotes (the original sources and your fork, or the incoming and master branches) using the ``git checkout`` command as usual. - - - -.. _building-fastcomp-from-source: - -Manually building Fastcomp from source -====================================== +*Fastcomp* is the default compiler core for Emscripten. Implemented as an :term:`LLVM backend`, its role is to convert the LLVM Intermediate Representation (IR) created by :term:`Clang` (from C/C++) into JavaScript. -.. note:: +*Fastcomp* has the following features: - - To build from source you first need to install a :ref:`compiler-toolchain` (see link for installation instructions). - - If you are building a large project, you will need a 64-bit build of LLVM and Clang. Compiling and optimizing can take more memory than is available to the 32-bit build. +- It is tightly integrated with LLVM (as an LLVM-backend) +- It has a core focus on **asm.js** code generation, which has been shown to give the best results. +- When compared to the previous compiler it is much faster (often 4x faster or more), uses less memory, and produces better code. +Fastcomp is maintained in two repositories: -To build the Fastcomp code from source "manually" (without the benefit of the SDK environment): - -- Clone the fastcomp LLVM repository (https://github.com/kripken/emscripten-fastcomp>): - - :: - - git clone https://github.com/kripken/emscripten-fastcomp - - .. note:: It doesn't matter where you clone *fastcomp* because Emscripten gets the information from the :ref:`compiler configuration file (~/.emscripten) `. We show how to update this file later in these instructions: - - -- Navigate to the **tools** directory (**emscripten-fastcomp/tools**) and clone the `kripken/emscripten-fastcomp-clang `_ repository into a **clang** subdirectory: +- https://github.com/kripken/emscripten-fastcomp (LLVM) +- https://github.com/kripken/emscripten-fastcomp-clang (Clang) - :: - - cd tools - git clone https://github.com/kripken/emscripten-fastcomp-clang clang - - .. warning:: You **must** clone it into a directory named **clang** as shown, so that :term:`Clang` is present in **tools/clang**! - - .. note:: This repository has changed. Early in fastcomp development we used a different directory. - -- Create a *build* directory (we highly recommend creating a separate build directory): - - - Navigate back to the root of the llvm clone (**/emscripten-fastcomp**) - - Create a new directory "**build**", and then navigate into it: - - :: - - cd .. - mkdir build - cd build - -- Configure the build using *either* the *configure* script or *cmake* (configure is located in the parent directory): - - - Using *configure*: - - :: - - ../configure --enable-optimized --disable-assertions --enable-targets=host,js - - - Using *CMake*: - - :: - - cmake .. -DCMAKE_BUILD_TYPE=Release -DLLVM_TARGETS_TO_BUILD="X86;JSBackend" -DLLVM_INCLUDE_EXAMPLES=OFF -DLLVM_INCLUDE_TESTS=OFF -DCLANG_INCLUDE_EXAMPLES=OFF -DCLANG_INCLUDE_TESTS=OFF - - .. note:: replace X86 if you are on something else.. - -- Determine the number of available cores on your system (Emscripten can run many operations in parallel, so using more cores may have a significant impact on compilation time): - - - On Mac OS X you can get the number of cores using: **Apple menu | About this mac | System report**. The **Hardware overview** on the resulting dialog includes a *Total number of cores* entry. - - On Linux you can find the number of cores by entering the following command on the terminal: ``cat /proc/cpuinfo | grep "^cpu cores" | uniq``. - - On Windows the number of cores is listed on the **Task Manager | Performance Tab**. YOu can open the *Task Manager* by entering **Ctrl + Shift + Esc** from the Desktop. - -- Call *make* to build the sources, specifying the number of available cores: - - :: - - make -j 4 - - - - -.. _llvm-update-compiler-configuration-file: - -- Update the :ref:`~/.emscripten ` file, specifying the location of *fastcomp* in using the ``LLVM_ROOT`` variable. The path should be set to the location of the *clang* binary under the **build** directory. This will be something like **/build/Release/bin** or **/build/bin**: - - :: - - LLVM_ROOT='/home/ubuntu/yourpath/emscripten-fastcomp/build/bin' - - .. note:: If **~/.emscripten** does not yet exist, you can create it by running ``./emcc --help`` in your **emscripten** directory (assuming Emscripten has already been downloaded). - -Branches ---------- - -You should use the **same** branch (*incoming*, or *master*) for building all three repositories: - -- Emscripten: `emscripten `_. -- Emscripten's LLVM fork: `emscripten-fastcomp `_. -- Emscripten's *Clang* fork `emscripten-fastcomp-clang `_. - -Mixing *incoming* and *master* branches may result in errors when building the three repositories. - -Run ``emcc -v`` to check if the branches are synchronized. - -.. note:: ``emcc -v`` checks the code in the repositories, not the builds. Before building make sure that you fetch the latest changes to LLVM and Clang. - -Version numbers -++++++++++++++++ - -Bisecting across multiple git trees can be hard. We use version numbers to help synchronize points between them: - -- `tools/shared.py `_ in Emscripten -- `emscripten-version.txt `_ in fastcomp (llvm) -- `emscripten-version.txt `_ in fastcomp-clang (clang) - -Version numbers are typically ``X.Y.Z`` where - -- ``X`` is a major number (changes very rarely) -- ``Y`` is a release number (changes each time we merge incoming to master, so these numbers indicate points where all tests passed), and -- ``Z`` is minor update that is just a sync point between the repos, or is needed when libc changes in emscripten (version changes clear the cache). - -Additional compilation notes ----------------------------- +Getting Fastcomp +================ -- Windows: To build 64 bit using *CMmake* and *Visual Studio*, use the ``-G "Visual Studio 10 Win64"`` directive. +*Fastcomp* (Clang) is part of the :ref:`Emscripten SDK `, and the binaries are automatically provided during installation (except on Linux, where pre-built binaries are not supplied so the SDK builds them for you). - .. note:: Visual Studio 2011 and 2012 don't work yet. - -- Windows: To build using *MinGW* replace the ``-G`` directive above with ``-G "MinGW Makefiles"``, and run *mingw32-make* to build (not tested yet). +If you need to build from source you can: +- :ref:`Use the SDK ` (these instructions show how to build the whole of Emscripten, including *Fastcomp*). +- :ref:`Build using a fully manual process `. -Backend code structure ----------------------- - -The backend is in `emscripten-fastcomp `_. The main file is `JSBackend.cpp `_ but the the other files in that directory (`lib/Target/JSBackend/ `_) are also important. +.. warning:: The backend is still too new to be in the upstream LLVM repository. As such, builds from Linux distributions will **not** contain *Fastcomp*, and Emscripten will report an error if you try to use them. .. _original-compiler-core: @@ -244,31 +42,32 @@ The backend is in `emscripten-fastcomp ` (and Mac OS X) provides the **easiest** and **most reliable** method for **building from source**. Just :ref:`download and install the SDK ` and follow the brief instructions :ref:`here `. - - The instructions below are provided for developers who, for whatever reason, prefer a manual approach. - This page contains basic instructions on how to manually build and configure Emscripten from source on a clean (Ubuntu 14.04.1 LTS 64bit) Linux box. +.. note:: The instructions clone from the main Emscripten repository (https://github.com/kripken/emscripten). :ref:`Contributors` should instead clone from their own Emscripten fork, and submit changes as pull requests. + +.. tip:: You can also build Emscripten from source :ref:`using the SDK `. This is recommended if you need easily switch between SDK and source builds. + What you'll need ================= -The previous topic (:ref:`Emscripten Toolchain `) lists the specific versions of tools that are needed. +The specific versions of tools that are needed are listed in the :ref:`Emscripten Toolchain Requirements `. Installing required tools @@ -61,7 +61,7 @@ These instructions explain how to install **all** the :ref:`required tools `. +#. Build :ref:`Fastcomp ` (LLVM + Clang) from source using :ref:`these instructions `. #. Clone the `kripken/emscripten `_ repository from Github. This repository contains the main compiler tool for compiling C/C++ programs to JavaScript: diff --git a/site/source/docs/building_from_source/building_emscripten_from_source_on_mac_os_x.rst b/site/source/docs/building_from_source/building_emscripten_from_source_on_mac_os_x.rst index 4c08fb334db9e..bea41a85fbae9 100644 --- a/site/source/docs/building_from_source/building_emscripten_from_source_on_mac_os_x.rst +++ b/site/source/docs/building_from_source/building_emscripten_from_source_on_mac_os_x.rst @@ -1,19 +1,19 @@ .. _building-emscripten-on-mac-osx-from-source: -================================================== -Building Emscripten on Mac OS X (ready-for-review) -================================================== +=========================================================== +Manually Building Emscripten on Mac OS X (ready-for-review) +=========================================================== -.. tip:: The :ref:`Portable SDK for Linux ` (and Mac OS X) provides the **easiest** and **most reliable** method for **building from source**. Just :ref:`download and install the SDK ` and follow the brief instructions :ref:`here `. +This page contains basic instructions on how to manually build and configure Emscripten from source on a clean Mac OS X box (OS X version 10.8.2). - The instructions below are provided for developers who, for whatever reason, prefer a manual approach. +.. note:: The instructions clone from the main Emscripten repository (https://github.com/kripken/emscripten). :ref:`Contributors` should instead clone from their own Emscripten fork, and submit changes as pull requests. -This page contains basic instructions on how to manually build and configure Emscripten from source on a clean Mac OS X box (OS X version 10.8.2). +.. tip:: You can also build Emscripten from source :ref:`using the SDK `. This is recommended if you need easily switch between SDK and source builds. What you'll need ================= -The topic :ref:`Emscripten Toolchain ` lists the specific versions of tools that are needed. +The specific versions of tools that are needed are listed in the :ref:`Emscripten Toolchain Requirements `. Installing required tools @@ -52,7 +52,7 @@ These instructions explain how to install **all** the :ref:`required tools `. +#. Build :ref:`Fastcomp ` (LLVM + Clang) from source using :ref:`these instructions `. #. Clone the `kripken/emscripten `_ repository from Github. This repository contains the main compiler tool for compiling C/C++ programs to JavaScript: diff --git a/site/source/docs/building_from_source/building_emscripten_from_source_on_windows.rst b/site/source/docs/building_from_source/building_emscripten_from_source_on_windows.rst index db1c261c63f5a..d9261501532e0 100644 --- a/site/source/docs/building_from_source/building_emscripten_from_source_on_windows.rst +++ b/site/source/docs/building_from_source/building_emscripten_from_source_on_windows.rst @@ -1,20 +1,20 @@ .. _building-emscripten-on-windows-from-source: -=================================================== -Building Emscripten on Windows (ready-for-review) -=================================================== +=========================================================== +Manually Building Emscripten on Windows (ready-for-review) +=========================================================== -.. tip:: The :ref:`Emscripten Windows SDKs ` provide the **easiest** and **most reliable** method for **building from source**. Just :ref:`download and install the SDK ` and follow the brief instructions :ref:`here `. +This page contains basic instructions on how to manually build and configure Emscripten from source on a clean Windows box. - The instructions below are provided for developers who, for whatever reason, prefer a manual approach. +.. note:: The instructions clone from the main Emscripten repository (https://github.com/kripken/emscripten). :ref:`Contributors` should instead clone from their own Emscripten fork, and submit changes as pull requests. -This page contains basic instructions on how to manually build and configure Emscripten from source on a clean Windows box. +.. tip:: You can also build Emscripten from source :ref:`using the SDK `. This is recommended if you need easily switch between SDK and source builds. What you'll need ================= -The topic :ref:`Emscripten Toolchain ` lists the specific versions of tools that are needed. +The specific versions of tools that are needed are listed in the :ref:`Emscripten Toolchain Requirements `. .. note:: 64-bit versions of all needed dependencies are preferred, and may be required if you are building large projects. However, if you plan to :ref:`integrate with Visual Studio `, do NOT install the 64-bit versions of the tools. @@ -46,7 +46,7 @@ These instructions explain how to install **all** the :ref:`required tools `_. -#. Build :term:`Fastcomp` (LLVM + Clang) from source using :ref:`these instructions `. +#. Build :ref:`Fastcomp ` (LLVM + Clang) from source using :ref:`these instructions `. #. Clone the `kripken/emscripten `_ repository from Github. This repository contains the main compiler tool for compiling C/C++ programs to JavaScript: diff --git a/site/source/docs/building_from_source/building_emscripten_from_source_using_the_sdk.rst b/site/source/docs/building_from_source/building_emscripten_from_source_using_the_sdk.rst new file mode 100644 index 0000000000000..7601d2eb825f4 --- /dev/null +++ b/site/source/docs/building_from_source/building_emscripten_from_source_using_the_sdk.rst @@ -0,0 +1,155 @@ +.. _building-emscripten-from-source-using-the-sdk: + +=================================================================== +Building Emscripten from Source using the SDK (ready-for-review) +=================================================================== + +The SDK can be used to fetch and build Emscripten from the latest sources in the Emscripten and :ref:`Fastcomp ` repositories. This allows you to obtain new features and defect fixes as soon as they are pushed to Github. + +:ref:`Contributors ` can replace these sources with their own forks of Emscripten and *Fastcomp*, build them, and then use the normal process to pull changes into the main repository. + +The instructions below explain how use the SDK to build Emscripten from both the main repositories and your own forks (for all supported platforms). + +.. note:: The SDK is recommended if you need to manage both SDK and source-built environments within the same user login. + + For :ref:`contributors ` the actual process of getting and building the sources for your fork is very similar to the :ref:`manual build process `. However the setup is easier because the SDK automatically installs and validates most of the needed tools and dependencies, and manages the compiler configuration file for you. + + +What you'll need +================ + +First :ref:`download and install the SDK `. The SDK automatically installs and activates *most* of the :ref:`central-list-of-emscripten-tools-and-dependencies`. + +Then :ref:`download and install the compiler toolchain ` for your platform. + + +.. _building-emscripten-from-the-main-repositories-using-the-sdk: + +Building Emscripten from the main repositories +============================================== + +The :ref:`emsdk` controls which tool and SDK "targets" are installed and activated. To start using the latest upstream git development branch (``incoming``), run the following commands: + +:: + + # Clone, pull, and build the latest "sdk" Emscripten environment + ./emsdk install sdk-incoming-64bit + + #On Windows, instead do the following: + emsdk install clang-incoming-64bit node-0.10.17-64bit python-2.7.5.3-64bit java-7.45-64bit emscripten-incoming + + # Set the "incoming SDK" as the active version. + ./emsdk activate sdk-incoming-64bit + +.. todo:: **HamishW** Check whether the bug (https://github.com/juj/emsdk/issues/13) is fixed and remove the windows specific line if it is. + +If you want to use the upstream stable branch ``master``, then replace ``-incoming-`` with ``-master-`` in the commands above. + +.. note:: The SDK supplies a number of "repository" targets. These targets are viewed by entering ``./emsdk list`` on the command prompt: + + - ``sdk-incoming-64bit`` is the target for a complete 64bit Emscripten environment build from the incoming branch of the Emscripten and *Fastcomp* repositories. Other ``sdk-``targets are provided for the master branch and 32bit builds. + - ``emscripten-incoming`` and ``emscripten-master`` are targets for the Emscripten repository (only) + - ``clang-incoming-64bit`` is the target for getting and building Fastcomp (only) from its repositories. Other ``clang-``targets are provided for the master branch and 32bit builds. + + Typically contributors use the *sdk-incoming-64bit* target as shown. + + +Building Emscripten using your own fork +======================================= + +:ref:`Emscripten Contributors ` need to be able to build Emscripten from their own fork — in order to use pull requests to merge changes back into Emscripten. This is achieved by first :ref:`installing source from the main repositories ` (as described in the previous section), and then replacing the sources with those from the fork. + +.. note:: You don't have to replace all of the code as shown below. If you're only working on *Fastcomp*, then there is no need to get your own fork of *Emscripten*. + +After installing the main repositories: + +#. Get your fork of Fastcomp: + + :: + + #From your emsdk "root" (where emsdk is installed). Navigate to the LLVM clone: + cd clang/fastcomp/src + + # Add a git remote link to your LLVM repository fork + git remote add myremote https://github.com/mygituseraccount/emscripten-fastcomp.git + + + # Fetch the changes in the remote. + git fetch myremote + + # Checkout the code in your LLVM fork to replace the original repository code + git checkout -b myremote --track myremote/incoming + + +#. Get your fork of Fastcomp-Clang: + + :: + + # Navigate to the tools/clang directory ( /clang/fastcomp/src/tools/clang ) + cd tools/clang + + # Add a git remote link to your Clang repository fork + git remote add myremote https://github.com/mygituseraccount/emscripten-fastcomp-clang.git + + + # Fetch the changes in the remote. + git fetch myremote + + # Checkout the code in your Clang fork to replace the original repository code + git checkout -b myremote --track myremote/incoming + +#. Build Fastcomp: + + #. The SDK builds *Fastcomp* into a branch and build specific directory — in this case **/clang/fastcomp/build_incoming_64**. We need to build to the same location. + + :: + + #Navigate to the /clang/fastcomp/build_incoming_64 + cd ../../../build_incoming_64 + + + + #. Configure the build using *cmake*: + + :: + + cmake .. -DCMAKE_BUILD_TYPE=Release -DLLVM_TARGETS_TO_BUILD="X86;JSBackend" -DLLVM_INCLUDE_EXAMPLES=OFF -DLLVM_INCLUDE_TESTS=OFF -DCLANG_INCLUDE_EXAMPLES=OFF -DCLANG_INCLUDE_TESTS=OFF + + #. Determine the number of available cores on your system (Emscripten can run many operations in parallel, so using more cores may have a significant impact on compilation time): + + - On Mac OS X you can get the number of cores using: **Apple menu | About this mac | System report**. The **Hardware overview** on the resulting dialog includes a *Total number of cores* entry. + - On Linux you can find the number of cores by entering the following command on the terminal: ``cat /proc/cpuinfo | grep "^cpu cores" | uniq``. + - On Windows the number of cores is listed on the **Task Manager | Performance Tab**. YOu can open the *Task Manager* by entering **Ctrl + Shift + Esc** from the Desktop. + + #. Call *make* to build the sources, specifying the number of available cores: + + :: + + make -j1 + + At this point Fastcomp is compiled, and available in the same location as the original. + + +#. Get your fork of Emscripten: + + :: + + #From your emsdk "root" (where emsdk is installed). Navigate to the LLVM clone: + cd clang/fastcomp/src + + # Add a git remote link to your LLVM repository fork, then fetch changes + git remote add myremote https://github.com/mygituseraccount/emscripten-fastcomp.git + git fetch myremote + + # Add a git remote link to your Clang repository fork. + git remote add myclangremote https://github.com/mygituseraccount/emscripten-fastcomp-clang.git + + # the changes in the remote. + git fetch myllvmremote + + # Checkout the code in your LLVM fork to replace the original repository code + git checkout -b myllvmremote --track myremote/incoming + + +You can switch back and forth between remotes (the original sources and your fork, or the incoming and master branches) using the ``git checkout`` command. You can switch between the SDK and source using the ``./emsdk activate `` command. + diff --git a/site/source/docs/building_from_source/building_fastcomp_manually_from_source.rst b/site/source/docs/building_from_source/building_fastcomp_manually_from_source.rst new file mode 100644 index 0000000000000..0515cf39c5a7a --- /dev/null +++ b/site/source/docs/building_from_source/building_fastcomp_manually_from_source.rst @@ -0,0 +1,144 @@ +.. _building-fastcomp-from-source: + +=========================================================== +Manually building Fastcomp from source (ready-for-review) +=========================================================== + +:ref:`Fastcomp ` is the default compiler core for Emscripten. It is a new :term:`LLVM backend` that converts the LLVM Intermediate Representation (IR) created by *Clang* (from C/C++) into JavaScript. + +This article explains how you can build the sources using a fully manual process. + +.. tip:: *Fastcomp* is delivered pre-built as part of the SDK, and can also be :ref:`built from source from within the SDK `. + +.. note:: If you are building a large project, you will need to create a 64-bit build of LLVM and Clang. Compiling and optimizing can take more memory than is available to the 32-bit build. + + +What you'll need +================ + +First follow the instructions for your platform showing how to :ref:`manually build Emscripten from source `. + +Then :ref:`download and install the compiler toolchain ` for your platform. + + +Building Fastcomp +================= + +To build the Fastcomp code from source: + +- Create a directory to store the build. It doesn't matter where, because Emscripten gets the information from the :ref:`compiler configuration file (~/.emscripten) `. We show how to update this file later in these instructions: + + :: + + mkdir myfastcomp + cd myfastcomp + + +- Clone the fastcomp LLVM repository (https://github.com/kripken/emscripten-fastcomp): + + :: + + git clone https://github.com/kripken/emscripten-fastcomp + + + +- Clone the `kripken/emscripten-fastcomp-clang `_ repository into **emscripten-fastcomp/tools/clang**: + + :: + + cd emscripten-fastcomp + git clone https://github.com/kripken/emscripten-fastcomp-clang tools/clang + + .. warning:: You **must** clone it into a directory named **clang** as shown, so that :term:`Clang` is present in **tools/clang**! + +- Create a *build* directory and then navigate into it (we highly recommend creating a separate build directory): + + :: + + mkdir build + cd build + +- Configure the build using *either* the *configure* script or *cmake* (configure is located in the parent directory): + + - Using *configure*: + + :: + + ../configure --enable-optimized --disable-assertions --enable-targets=host,js + + - Using *CMake*: + + :: + + cmake .. -DCMAKE_BUILD_TYPE=Release -DLLVM_TARGETS_TO_BUILD="X86;JSBackend" -DLLVM_INCLUDE_EXAMPLES=OFF -DLLVM_INCLUDE_TESTS=OFF -DCLANG_INCLUDE_EXAMPLES=OFF -DCLANG_INCLUDE_TESTS=OFF + +- Determine the number of available cores on your system (Emscripten can run many operations in parallel, so using more cores may have a significant impact on compilation time): + + - On Mac OS X you can get the number of cores using: **Apple menu | About this mac | System report**. The **Hardware overview** on the resulting dialog includes a *Total number of cores* entry. + - On Linux you can find the number of cores by entering the following command on the terminal: ``cat /proc/cpuinfo | grep "^cpu cores" | uniq``. + - On Windows the number of cores is listed on the **Task Manager | Performance Tab**. YOu can open the *Task Manager* by entering **Ctrl + Shift + Esc** from the Desktop. + +- Call *make* to build the sources, specifying the number of available cores: + + :: + + make -j4 + + + + +.. _llvm-update-compiler-configuration-file: + +- Update the :ref:`~/.emscripten ` file, specifying the location of *fastcomp* in using the ``LLVM_ROOT`` variable. The path should be set to the location of the *clang* binary under the **build** directory. This will be something like **/build/Release/bin** or **/build/bin**: + + :: + + LLVM_ROOT='/home/ubuntu/yourpath/emscripten-fastcomp/build/bin' + + .. note:: If **~/.emscripten** does not yet exist, you can create it by running ``./emcc --help`` in your **emscripten** directory (assuming Emscripten has already been downloaded). + +Branches +--------- + +You should use the **same** branch (*incoming*, or *master*) for building all three repositories: + +- Emscripten: `emscripten `_. +- Emscripten's LLVM fork: `emscripten-fastcomp `_. +- Emscripten's *Clang* fork `emscripten-fastcomp-clang `_. + +Mixing *incoming* and *master* branches may result in errors when building the three repositories. + +Run ``emcc -v`` to check if the branches are synchronized. + +.. note:: ``emcc -v`` checks the code in the repositories, not the builds. Before building make sure that you fetch the latest changes to LLVM and Clang. + +Version numbers +++++++++++++++++ + +Bisecting across multiple git trees can be hard. We use version numbers to help synchronize points between them: + +- `emscripten-version.txt `_ in Emscripten +- `emscripten-version.txt `_ in fastcomp (llvm) +- `emscripten-version.txt `_ in fastcomp-clang (clang) + +Version numbers are typically ``X.Y.Z`` where + +- ``X`` is a major number (changes very rarely) +- ``Y`` is a release number (changes each time we merge incoming to master, so these numbers indicate points where all tests passed), and +- ``Z`` is minor update that is just a sync point between the repos, or is needed when libc changes in emscripten (version changes clear the cache). + +Additional compilation notes +---------------------------- + +- Windows: To build 64 bit using *CMmake* and *Visual Studio*, use the ``-G "Visual Studio 10 Win64"`` directive. + + .. note:: Visual Studio 2011 and 2012 don't work yet. + +- Windows: To build using *MinGW* replace the ``-G`` directive above with ``-G "MinGW Makefiles"``, and run *mingw32-make* to build (not tested yet). + + +Backend code structure +---------------------- + +The backend is in `emscripten-fastcomp `_. The main file is `JSBackend.cpp `_ but the the other files in that directory (`lib/Target/JSBackend/ `_) are also important. + diff --git a/site/source/docs/building_from_source/configuring_emscripten_settings.rst b/site/source/docs/building_from_source/configuring_emscripten_settings.rst index f0f24001401eb..d67df2e66ebb6 100644 --- a/site/source/docs/building_from_source/configuring_emscripten_settings.rst +++ b/site/source/docs/building_from_source/configuring_emscripten_settings.rst @@ -4,9 +4,10 @@ Configuring Emscripten Settings when Manually Building from Source (ready-for-review) ===================================================================================== -.. note:: These instructions are are only useful if you are building Emscripten manually from source! If you're using the :ref:`SDK ` you should never manually update the settings, because the :ref:`emsdk` automatically overwrites the file with the appropriate compiler settings when you :term:`activate ` a tool or SDK. +.. note:: These instructions are are only useful if you are building Emscripten **manually** from source! If you're using the :ref:`SDK ` you should never manually update the settings, because the :ref:`emsdk` automatically overwrites the file with the appropriate compiler settings when you :term:`activate ` a tool or SDK. -The compiler settings used by Emscripten are defined in the :ref:`compiler configuration file (~/.emscripten) `. These settings include paths to the tools (LLVM, Clang, Java etc.) and the compiler's temporary directory for intermediate build files. + +The compiler settings used by Emscripten are defined in the :ref:`compiler configuration file (~/.emscripten) `. These settings include paths to the tools (LLVM, Clang, Java, etc.) and the compiler's temporary directory for intermediate build files. This article explains how to create and update the file when you are building Emscripten :ref:`manually ` from source. @@ -23,7 +24,7 @@ The settings file is created the first time a user runs :ref:`emcc ` (o ./emcc --help - You should get a ``Welcome to Emscripten!`` message. Behind the scenes, Emscripten generated a file called ``.emscripten`` in your home folder. + You should get a ``Welcome to Emscripten!`` message. Behind the scenes, Emscripten generates a file called ``.emscripten`` in your home folder. Emscripten makes a "best guess" at the correct locations for tools and updates the file appropriately. Where possible it will look for "system" apps (like Python and Java) and infer the location of the ``EMSCRIPTEN_ROOT`` (where :ref:`emcc ` is located) from the location of the command prompt. @@ -37,7 +38,7 @@ The settings file is created in the user's home directory: - On Linux and Mac OS X this file is named **~/.emscripten**, where ~ is the user's home directory. - .. note:: On Linux, files with the "." prefix are hidden by default. You may need to change your view settings to find the file. + .. note:: Files with the "." prefix are hidden by default. You may need to change your view settings to find the file. - On Windows the file can be found at a path like: **C:/Users/yourusername_000/.emscripten**. @@ -46,7 +47,7 @@ The settings file is created in the user's home directory: Compiler configuration file-format ================================== -.. note:: While the syntax is identical, the appearance of the default **.emscripten** file created by *emcc* is quite different than that created by *emsdk* (see :ref:`here `). This is because *emsdk* manages multiple target environments, and where possible hard codes the locations of those tools when a new environment is activated. The default file, by contrast, only needs to manage a single environment, but needs to make it as easy for the user as possible to configure manually. +.. note:: While the syntax is identical, the appearance of the default **.emscripten** file created by *emcc* is quite different than that created by :ref:`emsdk `. This is because *emsdk* manages multiple target environments, and where possible hard codes the locations of those tools when a new environment is activated. The default file, by contrast, is managed by the user — and is designed to make that task as easy as possible. The file simply assigns paths to a number of *variables* representing the the main tools used by Emscripten. For example, if the user cloned Emscripten to the **C:/Users/username/Documents/GitHub/emscripten** directory, then the file would have the line: :: @@ -62,10 +63,10 @@ You can find out the other variable names from the default *.emscripten* file or Editing the compiler configuration file ======================================= -The compiler configuration file can be edited with the text-editor of your choice. As stated above, most default settings are likely to be correct. If you're building manually from source, you are most likely to have to update the variable ``LLVM_ROOT`` (for :term:`Fastcomp`). +The compiler configuration file can be edited with the text editor of your choice. As stated above, most default settings are likely to be correct. If you're building manually from source, you are most likely to have to update the variable ``LLVM_ROOT`` (for :term:`Fastcomp`). -#. Edit the variable ``LLVM_ROOT`` to point directly to the path where you :ref:`built Fastcomp `. This path is likely to be something like **/build/Release/bin** or /build/bin**, where ```` is wherever you cloned LLVM: +#. Edit the variable ``LLVM_ROOT`` to point to the directory where you :ref:`built Fastcomp `. This path is likely to be something like **/build/Release/bin** or **/build/bin**, where ```` is wherever you cloned LLVM: :: @@ -84,7 +85,7 @@ The compiler configuration file can be edited with the text-editor of your choic .. comment .. The settings are now correct in the configuration file, but the paths and environment variables are not set in the command prompt/terminal. **HamishW** Follow up with Jukka on htis. -After setting those paths, run ``emcc`` again. It should again perform the sanity checks to test the specified paths. There are further validation tests in: :ref:`verifying-the-emscripten-environment`. +After setting those paths, run ``emcc`` again. It should again perform the sanity checks to test the specified paths. There are further validation tests available at: :ref:`verifying-the-emscripten-environment`. diff --git a/site/source/docs/building_from_source/index.rst b/site/source/docs/building_from_source/index.rst index 374fc3077542c..449472a0498ad 100644 --- a/site/source/docs/building_from_source/index.rst +++ b/site/source/docs/building_from_source/index.rst @@ -4,25 +4,30 @@ Building Emscripten from Source (ready-for-review) ================================================== -.. tip:: The *SDK* provides the **easiest** and **most reliable** method for **building from source**. Just :ref:`download the SDK ` and follow the brief instructions :ref:`here `. +Building from source allows you to access the very latest features and bug fixes, and is essential for developers who are :ref:`Contributing` to Emscripten. - This section is provided for developers who prefer a manual approach and/or are contributing to Emscripten development. - -.. note:: A user can't "manually " build from sources and use the SDK at the same time, because the SDK overwrites manual changes made to the user's :ref:`compiler configuration file `. +There are two approaches for building from source: + +- Manually setting up the sources and dependencies. +- Using the SDK package manager to set up the environment and get the sources. -This section shows how to get the source and dependencies and manually build the Emscripten toolchain. +The manual approach gives you a better understanding of the toolchain and all the build steps. The SDK method is easier because it automates and tests much of the set-up process. It also enables a workflow where you can easily switch between source builds and SDK environments. + +.. note:: You can't use both approaches at the same time because the SDK overwrites manual changes made to the user's :ref:`compiler configuration file `. -The instructions for building Emscripten on the different platforms are given below, followed by guidance on how to update the configuration file and validate your environment once it is complete: +The instructions for building Emscripten using both methods are given below, followed by guidance on how to update the configuration file and validate your environment once it is complete: .. toctree:: :maxdepth: 1 toolchain_what_is_needed + building_emscripten_from_source_using_the_sdk building_emscripten_from_source_on_linux building_emscripten_from_source_on_windows manually_integrating_emscripten_with_vs2010 building_emscripten_from_source_on_mac_os_x LLVM-Backend + building_fastcomp_manually_from_source configuring_emscripten_settings verify_emscripten_environment diff --git a/site/source/docs/building_from_source/toolchain_what_is_needed.rst b/site/source/docs/building_from_source/toolchain_what_is_needed.rst index 24101a2661555..2d67ae7b90dc6 100644 --- a/site/source/docs/building_from_source/toolchain_what_is_needed.rst +++ b/site/source/docs/building_from_source/toolchain_what_is_needed.rst @@ -6,7 +6,7 @@ Emscripten Toolchain Requirements The instructions below list the main tools and dependencies in an Emscripten environment, along with instructions on how to test which dependencies are installed. -.. tip:: The :ref:`SDK ` provides the **easiest** and **most reliable** method for getting, using, updating and managing Emscripten environments, including **building from source**. If you're using the SDK you won't *need* these instructions — they are provided for information only. +.. tip:: The :ref:`SDK ` provides the **easiest** and **most reliable** method for getting, using, updating and managing Emscripten environments. If you're using the SDK you won't *need* these instructions — they are provided for information only. The instructions below are useful if you're :ref:`manually ` building from source. @@ -15,6 +15,8 @@ The instructions below list the main tools and dependencies in an Emscripten env What you'll need ================ +.. _central-list-of-emscripten-tools-and-dependencies: + Emscripten tools and dependencies --------------------------------- @@ -36,16 +38,16 @@ A complete Emscripten environment requires the following tools. First test to se Compiler toolchain ------------------ -When building Emscripten from source code, whether "manually" or using the SDK, you will also need a compiler toolchain: +When building Emscripten from source code, whether "manually" or using the SDK, you will also need a *compiler toolchain* (including *gcc*, *g++*, *cmake*, etc.): -- On Windows install `gcc 4.6 `_ -- On Linux install *gcc* from the **build-essential** package: +- Windows: Install `gcc 4.6 `_ +- Linux: Install *gcc* from the **build-essential** package: :: sudo apt-get install build-essential -- On Mac OS X install the *XCode Command Line Tools*: +- Mac OS X: Install the *XCode Command Line Tools*: - Install XCode from the `Mac OS X App Store `_. - In **XCode | Preferences | Downloads**, install *Command Line Tools*. diff --git a/site/source/docs/building_from_source/verify_emscripten_environment.rst b/site/source/docs/building_from_source/verify_emscripten_environment.rst index a31d89cb6f3ec..39a639b81f6ed 100644 --- a/site/source/docs/building_from_source/verify_emscripten_environment.rst +++ b/site/source/docs/building_from_source/verify_emscripten_environment.rst @@ -4,7 +4,7 @@ Verifying the Emscripten Development Environment (ready-for-review) ======================================================================= -**After you've** :ref:`installed the SDK ` **or** :ref:`manually built an Emscripten development environment from sources ` **, the compiler should just work! This section shows how to verify that the environment has been set up correctly, and how to troubleshoot installation problems when they do occur.** +**After you've** :ref:`installed the SDK ` **or** :ref:`built an Emscripten development environment from sources ` **, the compiler should just work! This section shows how to verify that the environment has been set up correctly, and how to troubleshoot installation problems when they do occur.** Testing the environment diff --git a/site/source/docs/getting_started/downloads.rst b/site/source/docs/getting_started/downloads.rst index 371c4623c9451..565d9d9ece7ac 100644 --- a/site/source/docs/getting_started/downloads.rst +++ b/site/source/docs/getting_started/downloads.rst @@ -6,7 +6,7 @@ Download and install (ready-for-review) .. note:: The *Emscripten SDK* provides the whole Emscripten toolchain (*Clang*, *Python*, *Node.js* and *Visual Studio* integration) in a single easy-to-install package, with integrated support for :ref:`updating to newer SDKs ` as they are released. -.. tip:: If you are :ref:`contributing ` to Emscripten you should first install the SDK, and then use it to :ref:`build Emscripten from source `. +.. tip:: If you are :ref:`contributing ` to Emscripten you should first install the SDK, and then use it to :ref:`build Emscripten from source `. SDK Downloads @@ -127,46 +127,6 @@ The easiest way to verify the installation is to compile some code using Emscrip You can jump ahead to the :ref:`Tutorial`, but if you have any problems building you should run through the basic tests and troubleshooting instructions in :ref:`verifying-the-emscripten-environment`. -.. _sdk-building-emscripten-from-source: - -Building Emscripten from source -=============================== - -The SDK can be used to fetch and build the latest version of Emscripten from source. This allows you to obtain new features and the latest fixes as soon as they are pushed to Github (without having to wait for release to be tagged). **No Github account or fork of Emscripten is required!** - -.. tip:: The SDK is the recommended method of building Emscripten from source because it makes the process very easy, and allows you to treat the build as "just another SDK". Using the SDK allows you to easily toggle between the current SDK, older SDKs, and source-built environments, and to update to new SDKs and source updates as they become available. - - It is also possible to :ref:`manually build from source `, but this approach is more difficult, incompatible with the :ref:`SDK manager `, and in general not really needed, unless you are contributing to Emscripten development itself (as opposed to just using it). - -.. note:: You will need a :ref:`compiler-toolchain` to build the code (the link explains where you get the toolchain for each of the platforms). - -To start using the latest upstream git development branch (``incoming``), run the following commands: - -:: - - # Install latest git client. Skip if the system already has it. - ./emsdk install git-1.8.3 - - # Clone+pull the latest kripken/emscripten/incoming. - ./emsdk install sdk-incoming-64bit - - # Set the "incoming SDK" as the active version. - ./emsdk activate sdk-incoming-64bit - -If you want to use the upstream stable branch ``master``, then replace ``-incoming-`` with ``-master-`` in the commands above. - -.. note:: On Windows, *git* may fail with the error message: - - :: - - Unable to find remote helper for 'https' when cloning a repository with https:// url. - - The workaround is to uninstall git from *emsdk* (``emsdk uninstall git-1.8.3``) and install `Git for Windows `_. This issue is reported `here `_. - -.. todo:: **HamishW** Check whether the bug (https://github.com/juj/emsdk/issues/13) is fixed and remove the above note if it is. - -It is also possible to build your :ref:`own fork of the Emscripten using the SDK `. - .. _updating-the-emscripten-sdk: Updating the SDK diff --git a/site/source/docs/tools_reference/emsdk.rst b/site/source/docs/tools_reference/emsdk.rst index 1137f18f9605f..b9991a28ed93b 100644 --- a/site/source/docs/tools_reference/emsdk.rst +++ b/site/source/docs/tools_reference/emsdk.rst @@ -56,7 +56,7 @@ Arguments Tools and SDK targets ------------------------ -The ```` given above as a command argument is one of the targets listed using ``emsdk list`` (or ``emsdk list --old``). +The ```` given above as a command argument is one of the targets listed using ``./emsdk list`` (or ``./emsdk list --old``). Note that some of the tools and SDK names include *master* or *incoming*: these targets are used to clone and pull the very latest versions from the Emscripten incoming and master branches. @@ -65,11 +65,15 @@ You can also specify a target of ``latest`` to grab the most current SDK. SDK manager concepts -============================== +==================== -The Emscripten toolchain includes a number of different :term:`tools `, including *Clang*, *Emscripten*, *Java*, *Git*, *Node*, etc. The :term:`SDK` delivers a full set of these tools for a particular Emscripten release, in a convenient installer package. +The Emscripten toolchain includes a number of different tools, including *Clang*, *Emscripten*, *Java*, *Git*, *Node*, etc. *Emsdk* is a small package manager for controlling which tools are installed, and from the set of installed tools, which are active. -The *emsdk* can be used to fetch and install both current and legacy versions of individual tools and SDKs. A particular SDK (or tool) can then be set as :term:`active `, meaning that it will be used when Emscripten is run. The active "compiler configuration" is stored in a user-specific file (*~/.emscripten*), which is discussed in the next section. +The current set of available :term:`tools ` and :term:`SDKs ` are listed using ``./emsdk list``. These can be installed individually (``./emsdk install node-0.10.17-64bit``) or as a group (``./emsdk install node-0.10.17-64bit java-7.45-64bit``). + +The :term:`SDK` targets are a convenience mechanism for specifying the full set of tools used by a particular Emscripten release. For example, ``./emsdk install sdk-incoming-64bit`` is equivalent to typing ``./emsdk install git-1.8.3 clang-incoming-64bit node-0.10.17-64bit python-2.7.5.3-64bit java-7.45-64bit emscripten-incoming``. + +A particular installed SDK (or tool) can then be set as :term:`active `, meaning that it will be used when Emscripten is run. The active "compiler configuration" is stored in a user-specific file (*~/.emscripten*), which is discussed in the next section. .. note:: The different tools and SDKs managed by *emsdk* are stored in different directories under the root folder you specified when you first installed an SDK, grouped by tool and version. @@ -229,6 +233,8 @@ To switch to using the latest upstream git development branch (``incoming``), ru # Clone+pull the latest kripken/emscripten/incoming. ./emsdk install sdk-incoming-64bit + + # Set the "incoming SDK" as the active version. ./emsdk activate sdk-incoming-64bit From 708bd9c47db57b32cf1beec68e5d38bfd505f328 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Wed, 13 Aug 2014 09:16:35 -0700 Subject: [PATCH 35/91] fix test_unistd_misc --- tests/unistd/misc.c | 7 ------- tests/unistd/misc.out | 2 -- 2 files changed, 9 deletions(-) diff --git a/tests/unistd/misc.c b/tests/unistd/misc.c index 2ca5b3907439b..18b6294b05fe8 100644 --- a/tests/unistd/misc.c +++ b/tests/unistd/misc.c @@ -111,13 +111,6 @@ int main() { printf(", errno: %d\n", errno); errno = 0; - printf("alarm: %d", alarm(42)); - printf(", errno: %d\n", errno); - errno = 0; - printf("ualarm: %ld", ualarm(123, 456)); - printf(", errno: %d\n", errno); - errno = 0; - printf("fork: %d", fork()); printf(", errno: %d\n", errno); errno = 0; diff --git a/tests/unistd/misc.out b/tests/unistd/misc.out index ae641d571cd0b..66f283b16b221 100644 --- a/tests/unistd/misc.out +++ b/tests/unistd/misc.out @@ -25,8 +25,6 @@ lchown(good): 0, errno: 0 lchown(bad): -1, errno: 2 fchown(good): 0, errno: 0 fchown(bad): -1, errno: 9 -alarm: 0, errno: 0 -ualarm: 0, errno: 0 fork: -1, errno: 11 vfork: -1, errno: 11 crypt: (null), errno: 38 From 1393b4a91f3bff84abf6d2fc2dd83b25d440be7a Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Wed, 13 Aug 2014 10:16:09 -0700 Subject: [PATCH 36/91] document 'any' type in webidl binder --- .../coding/connecting_cpp_and_javascript/WebIDL-Binder.rst | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/site/source/docs/coding/connecting_cpp_and_javascript/WebIDL-Binder.rst b/site/source/docs/coding/connecting_cpp_and_javascript/WebIDL-Binder.rst index fa488afcc6d46..5d8cd4a1ad7b4 100644 --- a/site/source/docs/coding/connecting_cpp_and_javascript/WebIDL-Binder.rst +++ b/site/source/docs/coding/connecting_cpp_and_javascript/WebIDL-Binder.rst @@ -323,6 +323,8 @@ void* ~~~~~ The ``void*`` type is supported through a ``VoidPtr`` type which you can use -in IDL files. - +in IDL files. You can also use the ``any`` type. The difference between +them is that ``VoidPtr`` behaves like a pointer type in that you get +a wrapper object, while ``any`` behaves like a 32-bit integer (which is +what raw pointers are, in Emscripten-compiled code). From 217d69691b4e8ff89f59067dc1de67d244d587aa Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Wed, 13 Aug 2014 11:18:06 -0700 Subject: [PATCH 37/91] some commented-out logging options --- emcc | 1 + tools/shared.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/emcc b/emcc index 3cdf358ad79c7..750feb2010110 100755 --- a/emcc +++ b/emcc @@ -1017,6 +1017,7 @@ try: newargs[i] = '' elif newargs[i] == '-v': shared.COMPILER_OPTS += ['-v'] + #shared.LINK_CMD += ['-v'] # Enable verbose output from llvm-link, since it can take a long time and this gives some indication of progress. shared.check_sanity(force=True) newargs[i] = '' elif newargs[i].startswith('--shell-file'): diff --git a/tools/shared.py b/tools/shared.py index 1d1f805f8b7b6..71b6ec0bbac3b 100644 --- a/tools/shared.py +++ b/tools/shared.py @@ -614,7 +614,7 @@ def apply_configuration(): TEMP_DIR = configuration.TEMP_DIR apply_configuration() -logging.basicConfig(format='%(levelname)-8s %(name)s: %(message)s') +logging.basicConfig(format='%(levelname)-8s %(name)s: %(message)s') # can add %(asctime)s to see timestamps def set_logging(): logger = logging.getLogger() logger.setLevel(logging.DEBUG if os.environ.get('EMCC_DEBUG') else logging.INFO) From fcd39b851e52baf8f14dcc40a8e55058755a61b2 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Wed, 13 Aug 2014 11:42:12 -0700 Subject: [PATCH 38/91] avoid copying bitcode files in emcc when possible; copy them lazily when actually required --- emcc | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/emcc b/emcc index 750feb2010110..7831ddacec186 100755 --- a/emcc +++ b/emcc @@ -1473,15 +1473,11 @@ try: sys.exit(1) else: # bitcode if file_ending.endswith(BITCODE_ENDINGS): - logging.debug('copying bitcode file: ' + input_file) - temp_file = in_temp(unsuffixed(uniquename(input_file)) + '.o') - shutil.copyfile(input_file, temp_file) - temp_files.append((i, temp_file)) + logging.debug('using bitcode file: ' + input_file) + temp_files.append((i, input_file)) elif file_ending.endswith(DYNAMICLIB_ENDINGS) or shared.Building.is_ar(input_file): - logging.debug('copying library file: ' + input_file) - temp_file = in_temp(uniquename(input_file)) - shutil.copyfile(input_file, temp_file) - temp_files.append((i, temp_file)) + logging.debug('using library file: ' + input_file) + temp_files.append((i, input_file)) elif file_ending.endswith(ASSEMBLY_ENDINGS): if not LEAVE_INPUTS_RAW: logging.debug('assembling assembly file: ' + input_file) @@ -1502,10 +1498,12 @@ try: for pos, (_, input_file) in enumerate(input_files): file_ending = filename_type_ending(input_file) if file_ending.endswith(SOURCE_ENDINGS): - (_, temp_file) = temp_files[pos] + temp_file = temp_files[pos][1] logging.debug('optimizing %s', input_file) #if DEBUG: shutil.copyfile(temp_file, os.path.join(TEMP_DIR, 'to_opt.bc') # useful when LLVM opt aborts - shared.Building.llvm_opt(temp_file, llvm_opts) + new_temp_file = in_temp(unsuffixed(uniquename(temp_file)) + '.o') + shared.Building.llvm_opt(temp_file, llvm_opts, new_temp_file) + temp_files[pos] = (temp_files[pos][0], new_temp_file) # Decide what we will link linker_inputs = [val for _, val in sorted(temp_files + link_flags)] @@ -1519,7 +1517,11 @@ try: if len(input_files) == 1: _, input_file = input_files[0] _, temp_file = temp_files[0] - safe_move(temp_file, specified_target if specified_target else unsuffixed_basename(input_file) + final_ending) + bitcode_target = specified_target if specified_target else unsuffixed_basename(input_file) + final_ending + if temp_file != input_file: + safe_move(temp_file, bitcode_target) + else: + shutil.copyfile(temp_file, bitcode_target) temp_output_base = unsuffixed(temp_file) if os.path.exists(temp_output_base + '.d'): # There was a .d file generated, from -MD or -MMD and friends, save a copy of it to where the output resides, @@ -1564,8 +1566,12 @@ try: else: if not LEAVE_INPUTS_RAW: _, temp_file = temp_files[0] - shutil.move(temp_file, in_temp(target_basename + '.bc')) + _, input_file = input_files[0] final = in_temp(target_basename + '.bc') + if temp_file != input_file: + shutil.move(temp_file, final) + else: + shutil.copyfile(temp_file, final) else: _, input_file = input_files[0] final = in_temp(input_file) From 53c7b041198e3477db25ba62e9d928814a0f5c9d Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Wed, 13 Aug 2014 14:21:10 -0700 Subject: [PATCH 39/91] clean up -g handling --- emcc | 15 +++++++----- tests/test_core.py | 32 ------------------------- tests/test_other.py | 57 ++++++++++++++++++++++++++++++++++----------- 3 files changed, 52 insertions(+), 52 deletions(-) diff --git a/emcc b/emcc index 7831ddacec186..4d03bbc41eb86 100755 --- a/emcc +++ b/emcc @@ -819,6 +819,7 @@ try: opt_level = 0 debug_level = 0 + requested_debug = '' profiling = False emit_symbol_map = False js_opts = None @@ -948,11 +949,8 @@ try: elif newargs[i].startswith('-g'): requested_level = newargs[i][2:] or '3' debug_level = validate_arg_level(requested_level, 4, 'Invalid debug level: ' + newargs[i]) - if newargs[i] != '-g': - if debug_level >= 4: - newargs[i] = '-g' # we'll need this to get LLVM debug info - else: - newargs[i] = '' + requested_debug = newargs[i] + newargs[i] = '' elif newargs[i] == '-profiling': debug_level = 2 profiling = True @@ -1091,7 +1089,7 @@ try: if js_opts is None: js_opts = opt_level >= 2 if llvm_opts is None: llvm_opts = LLVM_OPT_LEVEL[opt_level] - if opt_level == 0: debug_level = 4 + if opt_level == 0: debug_level = max(3, debug_level) if memory_init_file is None: memory_init_file = opt_level >= 2 if llvm_lto is None and bind: @@ -1456,6 +1454,11 @@ try: if has_dash_c: return unsuffixed(input_file) + default_object_extension return in_temp(unsuffixed(uniquename(input_file)) + default_object_extension) + # Request LLVM debug info if explicitly specified, or building bitcode with -g, or if building a source all the way to JS with -g + if debug_level >= 4 or ((final_suffix not in JS_CONTAINING_SUFFIXES or (has_source_inputs and final_suffix in JS_CONTAINING_SUFFIXES)) and requested_debug == '-g'): + newargs.append('-g') # preserve LLVM debug info + debug_level = 4 + # First, generate LLVM bitcode. For each input file, we get base.o with bitcode for i, input_file in input_files: file_ending = filename_type_ending(input_file) diff --git a/tests/test_core.py b/tests/test_core.py index 597d4e8296eca..db1ab79652dd4 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -6474,38 +6474,6 @@ def test_safe_heap(self): # This test *should* fail, by throwing this exception assert 'Assertion failed: Load-store consistency assumption failure!' in str(e), str(e) - def test_debug(self): - if '-g' not in Building.COMPILER_TEST_OPTS: Building.COMPILER_TEST_OPTS.append('-g') - if self.emcc_args is not None: - if '-O1' in self.emcc_args or '-O2' in self.emcc_args or '-O3' in self.emcc_args: return self.skip('optimizations remove LLVM debug info') - - src = ''' - #include - #include - - void checker(int x) { - x += 20; - assert(x < 15); // this is line 7! - } - - int main() { - checker(10); - return 0; - } - ''' - try: - self.do_run(src, '*nothingatall*', assert_returncode=None) - except Exception, e: - # This test *should* fail - assert 'Assertion failed: x < 15' in str(e), str(e) - - lines = open('src.cpp.o.js', 'r').readlines() - lines = filter(lambda line: '___assert_fail(' in line or '___assert_func(' in line, lines) - found_line_num = any(('//@line 7 "' in line) for line in lines) - found_filename = any(('src.cpp"\n' in line) for line in lines) - assert found_line_num, 'Must have debug info with the line number' - assert found_filename, 'Must have debug info with the filename' - def test_source_map(self): if Settings.USE_TYPED_ARRAYS != 2: return self.skip("doesn't pass without typed arrays") if NODE_JS not in JS_ENGINES: return self.skip('sourcemapper requires Node to run') diff --git a/tests/test_other.py b/tests/test_other.py index 1233c1f69f6cc..a79cc579b5860 100644 --- a/tests/test_other.py +++ b/tests/test_other.py @@ -3928,18 +3928,47 @@ def test(args, be_clean): test(['-o', 'c.html'], True) test(['-c'], False) - def dash_g_bc(self): - def get_size(name): - return len(open(name).read()) - Popen([PYTHON, EMCC, path_from_root('tests', 'hello_world.c'), '-o', 'a_.bc']).communicate() - sizes = { '_': get_size('a_.bc') } - Popen([PYTHON, EMCC, path_from_root('tests', 'hello_world.c'), '-g', '-o', 'ag.bc']).communicate() - sizes['g'] = get_size('ag.bc') - for i in range(0, 5): - Popen([PYTHON, EMCC, path_from_root('tests', 'hello_world.c'), '-g' + str(i), '-o', 'a' + str(i) + '.bc']).communicate() - sizes[i] = get_size('a' + str(i) + '.bc') - print sizes - assert sizes['_'] == sizes[0] == sizes[1] == sizes[2] == sizes[3], 'no debug or <4 debug, means no llvm debug info' - assert sizes['g'] == sizes[4], '-g or -g4 means llvm debug info' - assert sizes['_'] < sizes['g'], 'llvm debug info has positive size' + def test_dash_g(self): + open('src.c', 'w').write(''' + #include + #include + + void checker(int x) { + x += 20; + assert(x < 15); // this is line 7! + } + + int main() { + checker(10); + return 0; + } + ''') + + Popen([PYTHON, EMCC, 'src.c', '-g']).communicate() + + lines = open('a.out.js', 'r').readlines() + lines = filter(lambda line: '___assert_fail(' in line or '___assert_func(' in line, lines) + found_line_num = any(('//@line 7 "' in line) for line in lines) + found_filename = any(('src.c"\n' in line) for line in lines) + assert found_line_num, 'Must have debug info with the line number' + assert found_filename, 'Must have debug info with the filename' + + def test_dash_g_bc(self): + def test(opts): + print opts + def get_size(name): + return len(open(name).read()) + Popen([PYTHON, EMCC, path_from_root('tests', 'hello_world.c'), '-o', 'a_.bc'] + opts).communicate() + sizes = { '_': get_size('a_.bc') } + Popen([PYTHON, EMCC, path_from_root('tests', 'hello_world.c'), '-g', '-o', 'ag.bc'] + opts).communicate() + sizes['g'] = get_size('ag.bc') + for i in range(0, 5): + Popen([PYTHON, EMCC, path_from_root('tests', 'hello_world.c'), '-g' + str(i), '-o', 'a' + str(i) + '.bc'] + opts).communicate() + sizes[i] = get_size('a' + str(i) + '.bc') + print ' ', sizes + assert sizes['_'] == sizes[0] == sizes[1] == sizes[2] == sizes[3], 'no debug or <4 debug, means no llvm debug info' + assert sizes['g'] == sizes[4], '-g or -g4 means llvm debug info' + assert sizes['_'] < sizes['g'], 'llvm debug info has positive size' + test([]) + test(['-O1']) From c9df6cbeabcefef01217ef8f1985b3600ec05e6e Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Wed, 13 Aug 2014 14:33:04 -0700 Subject: [PATCH 40/91] test for repeated -gX params --- tests/test_other.py | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/tests/test_other.py b/tests/test_other.py index a79cc579b5860..1c5da893ce860 100644 --- a/tests/test_other.py +++ b/tests/test_other.py @@ -3944,14 +3944,25 @@ def test_dash_g(self): } ''') - Popen([PYTHON, EMCC, 'src.c', '-g']).communicate() + def check(has): + print has + lines = open('a.out.js', 'r').readlines() + lines = filter(lambda line: '___assert_fail(' in line or '___assert_func(' in line, lines) + found_line_num = any(('//@line 7 "' in line) for line in lines) + found_filename = any(('src.c"\n' in line) for line in lines) + assert found_line_num == has, 'Must have debug info with the line number' + assert found_filename == has, 'Must have debug info with the filename' - lines = open('a.out.js', 'r').readlines() - lines = filter(lambda line: '___assert_fail(' in line or '___assert_func(' in line, lines) - found_line_num = any(('//@line 7 "' in line) for line in lines) - found_filename = any(('src.c"\n' in line) for line in lines) - assert found_line_num, 'Must have debug info with the line number' - assert found_filename, 'Must have debug info with the filename' + Popen([PYTHON, EMCC, 'src.c', '-g']).communicate() + check(True) + Popen([PYTHON, EMCC, 'src.c']).communicate() + check(False) + Popen([PYTHON, EMCC, 'src.c', '-g0']).communicate() + check(False) + Popen([PYTHON, EMCC, 'src.c', '-g0', '-g']).communicate() # later one overrides + check(True) + Popen([PYTHON, EMCC, 'src.c', '-g', '-g0']).communicate() # later one overrides + check(False) def test_dash_g_bc(self): def test(opts): From 7472dafbdaa825925bf5a7a101e4e865c8cc7739 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Wed, 13 Aug 2014 15:00:40 -0700 Subject: [PATCH 41/91] add faq entry about using main() to know when it is safe to call compiled methods, after startup is all complete --- .../docs/introducing_emscripten/FAQ.rst | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/site/source/docs/introducing_emscripten/FAQ.rst b/site/source/docs/introducing_emscripten/FAQ.rst index 0407f7fbacbab..e702a7ca610c0 100644 --- a/site/source/docs/introducing_emscripten/FAQ.rst +++ b/site/source/docs/introducing_emscripten/FAQ.rst @@ -483,4 +483,23 @@ Using Emscripten you will lose the advantages of le32 which includes better alignment of doubles). +- **Q.** I am building a library, and sometimes I get an error when + I call a compiled function before the page fully loaded. How can + I tell when is safe to call it? + + **A.** The easiest way to find out when loading is complete (which + is asynchronous, as it often requires loading files, such as the + .mem file or preloade files), is to just add a ``main()`` function. It + will be called when it is safe to do so, after startup is complete, + so that is a signal that it is safe to call any compiled method. + You can make ``main()`` call your JS to notify it, for example if + ``allReady()`` is a JS function you want called when everything is + ready, you can do + + :: + + #include + int main() { + EM_ASM( allReady() ); + } From 6e466b27fb25776f8a5a35221559d38499920e95 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Wed, 13 Aug 2014 15:19:03 -0700 Subject: [PATCH 42/91] fix extra _ in docs; fixes #2659 --- site/source/docs/api_reference/emscripten.h.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/site/source/docs/api_reference/emscripten.h.rst b/site/source/docs/api_reference/emscripten.h.rst index 18a7db5878968..480e4f808c1b3 100644 --- a/site/source/docs/api_reference/emscripten.h.rst +++ b/site/source/docs/api_reference/emscripten.h.rst @@ -202,8 +202,8 @@ Functions .. todo:: **HamishW** link to "Emscripten Browser Environment" doc when imported. -.. c:function:: void _emscripten_push_main_loop_blocker(em_arg_callback_func func, void *arg, const char *name) - void _emscripten_push_uncounted_main_loop_blocker(em_arg_callback_func func, void *arg, const char *name) +.. c:function:: void emscripten_push_main_loop_blocker(em_arg_callback_func func, void *arg, const char *name) + void emscripten_push_uncounted_main_loop_blocker(em_arg_callback_func func, void *arg, const char *name) Add a function that **blocks** the main loop. From 19eb7328ec6cc60382b4a76d18d53cffd4c14f28 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Wed, 13 Aug 2014 15:22:07 -0700 Subject: [PATCH 43/91] whitespace fix --- src/library_async.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/library_async.js b/src/library_async.js index bdd910b57785c..207327f1f5b61 100644 --- a/src/library_async.js +++ b/src/library_async.js @@ -125,7 +125,7 @@ mergeInto(LibraryManager.library, { stack_size = stack_size|0; var coroutine = 0; - if(stack_size <= 0) stack_size = 4096; + if (stack_size <= 0) stack_size = 4096; coroutine = _malloc(stack_size)|0; {{{ makeSetValueAsm('coroutine', 12, 0, 'i32') }}}; From 21fdc82e91910fd927e67421d8346998181cce7c Mon Sep 17 00:00:00 2001 From: Lu Wang Date: Wed, 13 Aug 2014 15:24:02 -0700 Subject: [PATCH 44/91] fix doc for emscripten_push_**_main_loop --- site/source/docs/api_reference/emscripten.h.rst | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/site/source/docs/api_reference/emscripten.h.rst b/site/source/docs/api_reference/emscripten.h.rst index 85ae66c6dcaa5..9c048884efe42 100644 --- a/site/source/docs/api_reference/emscripten.h.rst +++ b/site/source/docs/api_reference/emscripten.h.rst @@ -202,8 +202,8 @@ Functions .. todo:: **HamishW** link to "Emscripten Browser Environment" doc when imported. -.. c:function:: void emscripten_push_main_loop_blocker(em_arg_callback_func func, void *arg, const char *name) - void emscripten_push_uncounted_main_loop_blocker(em_arg_callback_func func, void *arg, const char *name) +.. c:function:: void emscripten_push_main_loop_blocker(em_arg_callback_func func, void *arg) + void emscripten_push_uncounted_main_loop_blocker(em_arg_callback_func func, void *arg) Add a function that **blocks** the main loop. @@ -218,8 +218,6 @@ Functions :param em_arg_callback_func func: The main loop blocker function. The function signature must have a ``void*`` parameter for passing the ``arg`` value. :param void* arg: User-defined arguments to pass to the blocker function. - :param name: A name for the function blocker. Used to identify the functions during debugging. - :type name: const char* :rtype: void From dcf835b8037c386aa3bc3534ff23c5eb14409dd9 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Wed, 13 Aug 2014 16:42:56 -0700 Subject: [PATCH 45/91] add an optional node to FS.ErrnoError, and use it in stat to tell if an error is about the relevant file - if not, it occurred when looking up its parents, and we should emit ENOTDIR; fixes #2669 --- src/library.js | 4 +++ src/library_fs.js | 20 +++++++----- tests/test_other.py | 76 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 92 insertions(+), 8 deletions(-) diff --git a/src/library.js b/src/library.js index 405a72daf8856..8c0f4a8d7c256 100644 --- a/src/library.js +++ b/src/library.js @@ -283,6 +283,10 @@ LibraryManager.library = { {{{ makeSetValue('buf', C_STRUCTS.stat.st_ino, 'stat.ino', 'i32') }}}; return 0; } catch (e) { + if (e.node && PATH.normalize(path) !== PATH.normalize(FS.getPath(e.node))) { + // an error occurred while trying to look up the path; we should just report ENOTDIR + e.setErrno(ERRNO_CODES.ENOTDIR); + } FS.handleFSError(e); return -1; } diff --git a/src/library_fs.js b/src/library_fs.js index 097cd5c9d3838..50481c4586fba 100644 --- a/src/library_fs.js +++ b/src/library_fs.js @@ -161,7 +161,7 @@ mergeInto(LibraryManager.library, { lookupNode: function(parent, name) { var err = FS.mayLookup(parent); if (err) { - throw new FS.ErrnoError(err); + throw new FS.ErrnoError(err, parent); } var hash = FS.hashName(parent.id, name); #if CASE_INSENSITIVE_FS @@ -1299,14 +1299,18 @@ mergeInto(LibraryManager.library, { }, ensureErrnoError: function() { if (FS.ErrnoError) return; - FS.ErrnoError = function ErrnoError(errno) { - this.errno = errno; - for (var key in ERRNO_CODES) { - if (ERRNO_CODES[key] === errno) { - this.code = key; - break; + FS.ErrnoError = function ErrnoError(errno, node) { + this.node = node; + this.setErrno = function(errno) { + this.errno = errno; + for (var key in ERRNO_CODES) { + if (ERRNO_CODES[key] === errno) { + this.code = key; + break; + } } - } + }; + this.setErrno(errno); this.message = ERRNO_MESSAGES[errno]; #if ASSERTIONS if (this.stack) this.stack = demangleAll(this.stack); diff --git a/tests/test_other.py b/tests/test_other.py index 1c5da893ce860..e7fa3829ef60c 100644 --- a/tests/test_other.py +++ b/tests/test_other.py @@ -3983,3 +3983,79 @@ def get_size(name): test([]) test(['-O1']) + def test_stat_fail_alongtheway(self): + open('src.cpp', 'w').write(r''' +#include +#include +#include +#include +#include +#include +#include +#include + +#define CHECK(expression) \ + if(!(expression)) { \ + error = errno; \ + printf("FAIL: %s\n", #expression); fail = 1; \ + } else { \ + error = errno; \ + printf("pass: %s\n", #expression); \ + } \ + +int +main() +{ + int error; + int fail = 0; + CHECK(mkdir("path", 0777) == 0); + CHECK(close(open("path/file", O_CREAT | O_WRONLY, 0644)) == 0); + { + struct stat st; + CHECK(stat("path", &st) == 0); + CHECK(st.st_mode = 0777); + } + { + struct stat st; + CHECK(stat("path/nosuchfile", &st) == -1); + printf("info: errno=%d %s\n", error, strerror(error)); + CHECK(error == ENOENT); + } + { + struct stat st; + CHECK(stat("path/file", &st) == 0); + CHECK(st.st_mode = 0666); + } + { + struct stat st; + CHECK(stat("path/file/impossible", &st) == -1); + printf("info: errno=%d %s\n", error, strerror(error)); + CHECK(error == ENOTDIR); + } + { + struct stat st; + CHECK(lstat("path/file/impossible", &st) == -1); + printf("info: errno=%d %s\n", error, strerror(error)); + CHECK(error == ENOTDIR); + } + return fail; +} +''') + Popen([PYTHON, EMCC, 'src.cpp']).communicate() + self.assertContained(r'''pass: mkdir("path", 0777) == 0 +pass: close(open("path/file", O_CREAT | O_WRONLY, 0644)) == 0 +pass: stat("path", &st) == 0 +pass: st.st_mode = 0777 +pass: stat("path/nosuchfile", &st) == -1 +info: errno=2 No such file or directory +pass: error == ENOENT +pass: stat("path/file", &st) == 0 +pass: st.st_mode = 0666 +pass: stat("path/file/impossible", &st) == -1 +info: errno=20 Not a directory +pass: error == ENOTDIR +pass: lstat("path/file/impossible", &st) == -1 +info: errno=20 Not a directory +pass: error == ENOTDIR +''', run_js('a.out.js')) + From 7054468bce661ffc194753ac5a5facd2e575f7f9 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Wed, 13 Aug 2014 20:27:40 -0700 Subject: [PATCH 46/91] force llvm debug info in SAFE_HEAP>=2 in slowcomp --- emcc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/emcc b/emcc index 4d03bbc41eb86..460e6ddbb5649 100755 --- a/emcc +++ b/emcc @@ -1340,7 +1340,7 @@ try: logging.warning('Disabling asm.js validation for memory growth (memory can grow, but you lose some amount of speed)'); shared.Settings.ASM_JS = 2 - if shared.Settings.CORRECT_SIGNS >= 2 or shared.Settings.CORRECT_OVERFLOWS >= 2 or shared.Settings.CORRECT_ROUNDINGS >= 2: + if shared.Settings.CORRECT_SIGNS >= 2 or shared.Settings.CORRECT_OVERFLOWS >= 2 or shared.Settings.CORRECT_ROUNDINGS >= 2 or shared.Settings.SAFE_HEAP >= 2: debug_level = 4 # must keep debug info to do line-by-line operations if debug_level > 1 and closure: From 8c58c709602632458af21d0c2bbdd3d242398aca Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Wed, 13 Aug 2014 20:39:21 -0700 Subject: [PATCH 47/91] do not save debug info if js opts will remove it anyhow --- emcc | 5 +++-- tests/test_other.py | 9 +++++---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/emcc b/emcc index 460e6ddbb5649..a9e8f5a297277 100755 --- a/emcc +++ b/emcc @@ -1456,8 +1456,9 @@ try: # Request LLVM debug info if explicitly specified, or building bitcode with -g, or if building a source all the way to JS with -g if debug_level >= 4 or ((final_suffix not in JS_CONTAINING_SUFFIXES or (has_source_inputs and final_suffix in JS_CONTAINING_SUFFIXES)) and requested_debug == '-g'): - newargs.append('-g') # preserve LLVM debug info - debug_level = 4 + if not (final_suffix in JS_CONTAINING_SUFFIXES and js_opts): # do not save llvm debug info if js optimizer will wipe it out anyhow + newargs.append('-g') # preserve LLVM debug info + debug_level = 4 # First, generate LLVM bitcode. For each input file, we get base.o with bitcode for i, input_file in input_files: diff --git a/tests/test_other.py b/tests/test_other.py index e7fa3829ef60c..587f0d5d61b00 100644 --- a/tests/test_other.py +++ b/tests/test_other.py @@ -1940,14 +1940,15 @@ def test_debuginfo(self): if os.environ.get('EMCC_DEBUG'): return self.skip('cannot run in debug mode') try: os.environ['EMCC_DEBUG'] = '1' - # llvm debug info is kept only when we can see it, which is without the js optimize, -O0. js debug info is lost by registerize in -O2, so - g disables it for args, expect_llvm, expect_js in [ - (['-O0'], True, True), + (['-O0'], False, True), (['-O0', '-g'], True, True), + (['-O0', '-g4'], True, True), (['-O1'], False, True), - (['-O1', '-g'], False, True), + (['-O1', '-g'], True, True), (['-O2'], False, False), - (['-O2', '-g'], False, True), + (['-O2', '-g'], False, True), # drop llvm debug info as js opts kill it anyway + (['-O2', '-g4'], True, True), # drop llvm debug info as js opts kill it anyway ]: print args, expect_llvm, expect_js output, err = Popen([PYTHON, EMCC, path_from_root('tests', 'hello_world.cpp')] + args, stdout=PIPE, stderr=PIPE).communicate() From a13d442f359442f243890caebb036614ad57cbe6 Mon Sep 17 00:00:00 2001 From: hamishwillee Date: Thu, 14 Aug 2014 17:22:13 +1000 Subject: [PATCH 48/91] Fixes to the downloads section and building from source. First draft of val.h. Partial first draft of bind.h --- site/source/docs/api_reference/bind.h.rst | 836 ++++++++++++++++++ site/source/docs/api_reference/index.rst | 6 + site/source/docs/api_reference/val.h.rst | 234 +++++ ...ilding_emscripten_from_source_on_linux.rst | 3 +- ...g_emscripten_from_source_using_the_sdk.rst | 25 +- .../toolchain_what_is_needed.rst | 8 +- .../source/docs/getting_started/downloads.rst | 45 +- 7 files changed, 1138 insertions(+), 19 deletions(-) create mode 100644 site/source/docs/api_reference/bind.h.rst create mode 100644 site/source/docs/api_reference/val.h.rst diff --git a/site/source/docs/api_reference/bind.h.rst b/site/source/docs/api_reference/bind.h.rst new file mode 100644 index 0000000000000..ce99748480380 --- /dev/null +++ b/site/source/docs/api_reference/bind.h.rst @@ -0,0 +1,836 @@ +.. _bind-h: + +================================ +bind.h (under-construction) +================================ + +The C++ APIs in `bind.h `_ define (**HamishW**-Replace with description.) + +**HamishW** Typenames etc. + +.. contents:: Table of Contents + :local: + :depth: 1 + +How to use this API +=================== + + +Defines +------- + + + +.. cpp:namespace: emscripten + + +.. cpp:type:: sharing_policy + + **HamishW**-Replace with description. Note this is a strongly typed enum. I can't see better way in Sphinx to represent it. + + .. cpp:type:: sharing_policy::NONE + + **HamishW**-Replace with description. + + .. cpp:type:: sharing_policy::INTRUSIVE + + **HamishW**-Replace with description. + + .. cpp:type:: sharing_policy::BY_EMVAL + + **HamishW**-Replace with description. + + +Policies +=================== + + +.. cpp:type:: arg + + .. cpp:member:: static constexpr int index + + **HamishW** Add description. Not sure if this best way to define a templated object which takes an argument like this. Kept declaration below for discussion: :: + + template + struct arg { + static constexpr int index = Index + 1; + }; + +.. cpp:type:: ret_val + + .. cpp:member:: static constexpr int index + + **HamishW** Add description. Not sure if this best way to define member in struct like this. Perhaps an example of usage, or even define as ``static constexpr int arg::index``. Kept declaration below for discussion: :: + + struct ret_val { + static constexpr int index = 0; + }; + + +.. cpp:type:: allow_raw_pointers::Transform::type + + **HamishW** Add description. Note from source is: // whitelist all raw pointers + + **HamishW** Not sure if this best way to define this data structure in sphinx, but is less cumbersome than having separate nested type declarations, particularly where I doubt they need individual descriptions. This works in sphinx because all the nested objects are "types" + + +.. cpp:type:: allow_raw_pointer + + **HamishW** Add description. + + .. note:: This type is temporary, it will be changed when arg policies are reworked + + **HamishW** Not sure if this best way to define this data structure. The templated parameter SLOT doesn't appear to be used, so no easy place to explain what is going on here. Declaration kept below for discussion: :: + + template + struct allow_raw_pointer : public allow_raw_pointers { + + +select_overload and select_const +====================================== + +**HamishW** Nicer title please. What are these actually "for" a good start. + + +.. cpp:function:: typename std::add_pointer::type select_overload(typename std::add_pointer::type fn) + + **HamishW** Add description. + + :param typename std::add_pointer::type fn: **HamishW** Add description. Note that ``Signature`` is a typename (templated type). + :returns: **HamishW** Add description. + + +.. cpp:function:: typename internal::MemberFunctionType::type select_overload(Signature (ClassType::*fn)) + + **HamishW** Add description. + + :param Signature (ClassType::*fn): **HamishW** Add description. Note that ``Signature`` and ``ClassType`` are typenames (templated types). + :returns: **HamishW** Add description. + + +.. cpp:function:: auto select_const(ReturnType (ClassType::*method)(Args...) const) + + **HamishW** Add description. + + :param ReturnType (ClassType::*method)(Args...) const: **HamishW** Add description. Note that ``ClassType``, ``ReturnType``, and ``Args`` are typenames (templated types). + :returns: **HamishW** Add description. + + +.. cpp:function:: typename internal::CalculateLambdaSignature::type optional_override(const LambdaType& fp) + + **HamishW** Add description. + + :param const LambdaType& fp: **HamishW** Add description. Note that ``LambdaType``is a typename (templated type). + :returns: **HamishW** Add description. + + + +Functions +============= + +.. cpp:function:: void* __getDynamicPointerType(void* p) + + **HamishW** Add description. + + :param void* p: **HamishW** Add description. + :returns: **HamishW** Add description. + + +.. cpp:function:: void* __getDynamicPointerType(void* p) + + **HamishW** Add description. + + :param void* p: **HamishW** Add description. + :returns: **HamishW** Add description. + + +.. cpp:function:: void function(const char* name, ReturnType (*fn)(Args...), Policies...) + + **HamishW** Add description. + + :param const char* name: **HamishW** Add description. + :param ReturnType (*fn)(Args...): **HamishW** Add description. Note that ``ReturnType`` and ``Args`` are typenames (templated types). + :param Policies...: **HamishW** Add description. Note that ``Policies`` is a typename (templated type). + + + +Value tuples +============== + +.. cpp:class:: value_array : public internal::noncopyable + + **HamishW** Add description. + + .. cpp:type:: class_type + + A typedef of ``ClassType``, the typename of the templated type for the class. + + + .. cpp:function:: value_array(const char* name) + + Constructor. **HamishW** Add description. + + :param const char* name: **HamishW** Add description. + + + .. cpp:function:: ~value_array() + + Destructor. **HamishW** Add description. + + + .. cpp:function:: value_array& element(ElementType InstanceType::*field) + + **HamishW** Add description. + + :param ElementType InstanceType::*field: **HamishW** Add description. Note that ``ElementType`` and ``InstanceType`` are typenames (templated types). + :returns: **HamishW** Add description. + + + .. cpp:function:: value_array& element(Getter getter, Setter setter) + + **HamishW** Add description. + + :param Getter getter: **HamishW** Add description. Note that ``Getter`` is a typename (templated type). + :param Setter setter: **HamishW** Add description. Note that ``Setter`` is a typename (templated type). + :returns: **HamishW** Add description. + + + .. cpp:function:: value_array& element(index) + + **HamishW** Add description. + + :param index: **HamishW** Add description. Note that ``Index`` is an integer template parameter. + :returns: **HamishW** Add description. + + + + + +Value structs +====================================== + +.. cpp:class:: value_object : public internal::noncopyable + + **HamishW** Add description. + + .. cpp:type:: class_type + + A typedef of ``ClassType``, the typename of the templated type for the class. + + + .. cpp:function:: value_object(const char* name) + + Constructor. **HamishW** Add description. + + :param const char* name: **HamishW** Add description. + + + .. cpp:function:: ~value_object() + + Destructor. **HamishW** Add description. + + + .. cpp:function:: value_object& field(const char* fieldName, FieldType InstanceType::*field) + + **HamishW** Add description. + + :param const char* fieldName: **HamishW** Add description. + :param FieldType InstanceType::*field: **HamishW** Add description. Note that ``InstanceType`` and ``FieldType`` are typenames (templated types). + :returns: **HamishW** Add description. + + + + .. cpp:function:: value_object& field(const char* fieldName, Getter getter, Setter setter) + + **HamishW** Add description. + + :param const char* fieldName: **HamishW** Add description. + :param Getter getter: **HamishW** Add description. Note that ``Getter`` is a typename (templated type). + :param Setter setter: **HamishW** Add description. Note that ``Setter`` is a typename (templated type). + :returns: **HamishW** Add description. + + + .. cpp:function:: value_object& field(const char* fieldName, index) + + **HamishW** Add description. + + :param const char* fieldName: **HamishW** Add description. + :param index: **HamishW** Add description. Note that ``Index`` is an integer template parameter. + :returns: **HamishW** Add description. + + + + + +Smart pointers +====================================== + + +.. cpp:type:: default_smart_ptr_trait + + **HamishW** Add description. + + .. cpp:function:: static sharing_policy get_sharing_policy() + + **HamishW** Add description. + + :returns: **HamishW** Add description. + + + .. cpp:function:: static void* share(void* v) + + **HamishW** Add description. + + :param void* v: **HamishW** Add description. + :returns: **HamishW** Add description. + + .. cpp:function:: static PointerType* construct_null() + + **HamishW** Add description. + + :returns: **HamishW** Add description. Note that the ``PointerType`` returned is a typename (templated type). + + + +.. cpp:type:: default_smart_ptr_trait + + **HamishW** Add description. Note from source is: // specialize if you have a different pointer type + + .. cpp:type:: element_type; + + **HamishW** Add description. A typedef for the PointerType::element_type, where ``PointerType`` is a typename (templated type). + + + + .. cpp:function:: static element_type* get(const PointerType& ptr) + + **HamishW** Add description. + + :param const PointerType& ptr: **HamishW** Add description. Note that ``PointerType`` is a typename (templated type) + :returns: **HamishW** Add description. + + + +.. cpp:type:: smart_ptr_trait + + **HamishW** Add description. + + .. cpp:type:: PointerType; + + **HamishW** Add description. A typedef to std::shared_ptr, where ``PointeeType`` is a typename (templated type). + + .. cpp:type:: element_type; + + **HamishW** Add description. A typedef for the ``PointerType::element_type``. + + + .. cpp:function:: static element_type* get(const PointerType& ptr) + + **HamishW** Add description. + + :param const PointerType& ptr: **HamishW** Add description. + :returns: **HamishW** Add description. + + .. cpp:function:: static sharing_policy get_sharing_policy() + + **HamishW** Add description. + + :returns: **HamishW** Add description. + + + .. cpp:function:: static std::shared_ptr* share(PointeeType* p, internal::EM_VAL v) + + **HamishW** Add description. + + :param PointeeType* p: **HamishW** Add description. Note that ``PointeeType`` is a typename (templated type). + :param internal::EM_VAL v: **HamishW** Add description. + :returns: **HamishW** Add description. + + .. cpp:function:: static PointerType* construct_null() + + **HamishW** Add description. + + :returns: **HamishW** Add description. + + +**HamishW** Note, did not include private class val_deleter. I am assuming all private classes are internal. + + +Classes +====================================== + + + // abstract classes + template + class wrapper : public T, public internal::WrapperBase { + public: + typedef T class_type; + + template + explicit wrapper(val&& wrapped, Args&&... args) + : T(std::forward(args)...) + , wrapped(std::forward(wrapped)) + {} + + ~wrapper() { + if (notifyJSOnDestruction) { + call("__destruct"); + } + } + + template + ReturnType call(const char* name, Args&&... args) const { + return wrapped.call(name, std::forward(args)...); + } + + + +#define EMSCRIPTEN_WRAPPER(T) \ + template \ + T(::emscripten::val&& v, Args&&... args) \ + : wrapper(std::forward<::emscripten::val>(v), std::forward(args)...) \ + {} + + + + template + struct base { + typedef BaseClass class_type; + + template + static void verify() { + static_assert(!std::is_same::value, "Base must not have same type as class"); + static_assert(std::is_base_of::value, "Derived class must derive from base"); + } + + static internal::TYPEID get() { + return internal::TypeID::get(); + } + + template + using Upcaster = BaseClass* (*)(ClassType*); + + template + using Downcaster = ClassType* (*)(BaseClass*); + + template + static Upcaster getUpcaster() { + return &convertPointer; + } + + template + static Downcaster getDowncaster() { + return &convertPointer; + } + + template + static To* convertPointer(From* ptr) { + return static_cast(ptr); + } + }; + + + + struct pure_virtual { + template + struct Transform { + typedef InputType type; + }; + }; + + + + template + struct constructor { + }; + + template + class class_ { + public: + typedef ClassType class_type; + typedef BaseSpecifier base_specifier; + + class_() = delete; + + EMSCRIPTEN_ALWAYS_INLINE explicit class_(const char* name) { + using namespace internal; + + BaseSpecifier::template verify(); + + auto _getActualType = &getActualType; + auto upcast = BaseSpecifier::template getUpcaster(); + auto downcast = BaseSpecifier::template getDowncaster(); + auto destructor = &raw_destructor; + + _embind_register_class( + TypeID::get(), + TypeID>::get(), + TypeID>::get(), + BaseSpecifier::get(), + getSignature(_getActualType), + reinterpret_cast(_getActualType), + getSignature(upcast), + reinterpret_cast(upcast), + getSignature(downcast), + reinterpret_cast(downcast), + name, + getSignature(destructor), + reinterpret_cast(destructor)); + } + + template + EMSCRIPTEN_ALWAYS_INLINE const class_& smart_ptr(const char* name) const { + using namespace internal; + + typedef smart_ptr_trait PointerTrait; + typedef typename PointerTrait::element_type PointeeType; + + static_assert(std::is_same::type>::value, "smart pointer must point to this class"); + + auto get = &PointerTrait::get; + auto construct_null = &PointerTrait::construct_null; + auto share = &PointerTrait::share; + auto destructor = &raw_destructor; + + _embind_register_smart_ptr( + TypeID::get(), + TypeID::get(), + name, + PointerTrait::get_sharing_policy(), + getSignature(get), + reinterpret_cast(get), + getSignature(construct_null), + reinterpret_cast(construct_null), + getSignature(share), + reinterpret_cast(share), + getSignature(destructor), + reinterpret_cast(destructor)); + return *this; + }; + + template + EMSCRIPTEN_ALWAYS_INLINE const class_& constructor(Policies... policies) const { + return constructor( + &internal::operator_new, + policies...); + } + + template + EMSCRIPTEN_ALWAYS_INLINE const class_& constructor(ReturnType (*factory)(Args...), Policies...) const { + using namespace internal; + + // TODO: allows all raw pointers... policies need a rethink + typename WithPolicies::template ArgTypeList args; + auto invoke = &Invoker::invoke; + _embind_register_class_constructor( + TypeID::get(), + args.getCount(), + args.getTypes(), + getSignature(invoke), + reinterpret_cast(invoke), + reinterpret_cast(factory)); + return *this; + } + + template + EMSCRIPTEN_ALWAYS_INLINE const class_& smart_ptr_constructor(const char* smartPtrName, SmartPtr (*factory)(Args...), Policies...) const { + using namespace internal; + + smart_ptr(smartPtrName); + + typename WithPolicies::template ArgTypeList args; + auto invoke = &Invoker::invoke; + _embind_register_class_constructor( + TypeID::get(), + args.getCount(), + args.getTypes(), + getSignature(invoke), + reinterpret_cast(invoke), + reinterpret_cast(factory)); + return *this; + } + + template + EMSCRIPTEN_ALWAYS_INLINE const class_& allow_subclass( + const char* wrapperClassName, + const char* pointerName = "", + ::emscripten::constructor = ::emscripten::constructor() + ) const { + using namespace internal; + + auto cls = class_>(wrapperClassName) + .function("notifyOnDestruction", select_overload([](WrapperType& wrapper) { + wrapper.setNotifyJSOnDestruction(true); + })) + ; + SmartPtrIfNeeded _(cls, pointerName); + + return + class_function( + "implement", + &wrapped_new, + allow_raw_pointer()) + .class_function( + "extend", + &wrapped_extend) + ; + } + + template + EMSCRIPTEN_ALWAYS_INLINE const class_& allow_subclass( + const char* wrapperClassName, + ::emscripten::constructor constructor + ) const { + return allow_subclass(wrapperClassName, "", constructor); + } + + template + EMSCRIPTEN_ALWAYS_INLINE const class_& function(const char* methodName, ReturnType (ClassType::*memberFunction)(Args...), Policies...) const { + using namespace internal; + + auto invoker = &MethodInvoker::invoke; + + typename WithPolicies::template ArgTypeList, Args...> args; + _embind_register_class_function( + TypeID::get(), + methodName, + args.getCount(), + args.getTypes(), + getSignature(invoker), + reinterpret_cast(invoker), + getContext(memberFunction), + isPureVirtual::value); + return *this; + } + + template + EMSCRIPTEN_ALWAYS_INLINE const class_& function(const char* methodName, ReturnType (ClassType::*memberFunction)(Args...) const, Policies...) const { + using namespace internal; + + auto invoker = &MethodInvoker::invoke; + + typename WithPolicies::template ArgTypeList, Args...> args; + _embind_register_class_function( + TypeID::get(), + methodName, + args.getCount(), + args.getTypes(), + getSignature(invoker), + reinterpret_cast(invoker), + getContext(memberFunction), + isPureVirtual::value); + return *this; + } + + template + EMSCRIPTEN_ALWAYS_INLINE const class_& function(const char* methodName, ReturnType (*function)(ThisType, Args...), Policies...) const { + using namespace internal; + + typename WithPolicies::template ArgTypeList args; + auto invoke = &FunctionInvoker::invoke; + _embind_register_class_function( + TypeID::get(), + methodName, + args.getCount(), + args.getTypes(), + getSignature(invoke), + reinterpret_cast(invoke), + getContext(function), + false); + return *this; + } + + template::value>::type> + EMSCRIPTEN_ALWAYS_INLINE const class_& property(const char* fieldName, const FieldType ClassType::*field) const { + using namespace internal; + + auto getter = &MemberAccess::template getWire; + _embind_register_class_property( + TypeID::get(), + fieldName, + TypeID::get(), + getSignature(getter), + reinterpret_cast(getter), + getContext(field), + 0, + 0, + 0, + 0); + return *this; + } + + template::value>::type> + EMSCRIPTEN_ALWAYS_INLINE const class_& property(const char* fieldName, FieldType ClassType::*field) const { + using namespace internal; + + auto getter = &MemberAccess::template getWire; + auto setter = &MemberAccess::template setWire; + _embind_register_class_property( + TypeID::get(), + fieldName, + TypeID::get(), + getSignature(getter), + reinterpret_cast(getter), + getContext(field), + TypeID::get(), + getSignature(setter), + reinterpret_cast(setter), + getContext(field)); + return *this; + } + + template + EMSCRIPTEN_ALWAYS_INLINE const class_& property(const char* fieldName, Getter getter) const { + using namespace internal; + typedef GetterPolicy GP; + auto gter = &GP::template get; + _embind_register_class_property( + TypeID::get(), + fieldName, + TypeID::get(), + getSignature(gter), + reinterpret_cast(gter), + GP::getContext(getter), + 0, + 0, + 0, + 0); + return *this; + } + + template + EMSCRIPTEN_ALWAYS_INLINE const class_& property(const char* fieldName, Getter getter, Setter setter) const { + using namespace internal; + typedef GetterPolicy GP; + typedef SetterPolicy SP; + + auto gter = &GP::template get; + auto ster = &SP::template set; + + _embind_register_class_property( + TypeID::get(), + fieldName, + TypeID::get(), + getSignature(gter), + reinterpret_cast(gter), + GP::getContext(getter), + TypeID::get(), + getSignature(ster), + reinterpret_cast(ster), + SP::getContext(setter)); + return *this; + } + + template + EMSCRIPTEN_ALWAYS_INLINE const class_& class_function(const char* methodName, ReturnType (*classMethod)(Args...), Policies...) const { + using namespace internal; + + typename WithPolicies::template ArgTypeList args; + auto invoke = &internal::Invoker::invoke; + _embind_register_class_class_function( + TypeID::get(), + methodName, + args.getCount(), + args.getTypes(), + getSignature(invoke), + reinterpret_cast(invoke), + reinterpret_cast(classMethod)); + return *this; + } + }; + + + +Vectors +====================================== + + + template + class_> register_vector(const char* name) { + typedef std::vector VecType; + + void (VecType::*push_back)(const T&) = &VecType::push_back; + return class_>(name) + .template constructor<>() + .function("push_back", push_back) + .function("size", &VecType::size) + .function("get", &internal::VectorAccess::get) + .function("set", &internal::VectorAccess::set) + ; + } + + +Maps +====================================== + + + + template + class_> register_map(const char* name) { + typedef std::map MapType; + + return class_(name) + .template constructor<>() + .function("size", &MapType::size) + .function("get", internal::MapAccess::get) + .function("set", internal::MapAccess::set) + ; + } + + + +Enums +====================================== + + template + class enum_ { + public: + typedef EnumType enum_type; + + enum_(const char* name) { + using namespace internal; + _embind_register_enum( + internal::TypeID::get(), + name, + sizeof(EnumType), + std::is_signed::type>::value); + } + + enum_& value(const char* name, EnumType value) { + using namespace internal; + // TODO: there's still an issue here. + // if EnumType is an unsigned long, then JS may receive it as a signed long + static_assert(sizeof(value) <= sizeof(internal::GenericEnumValue), "enum type must fit in a GenericEnumValue"); + + _embind_register_enum_value( + internal::TypeID::get(), + name, + static_cast(value)); + return *this; + } + }; + + +Constants +====================================== + + + + template + void constant(const char* name, const ConstantType& v) { + using namespace internal; + typedef BindingType BT; + _embind_register_constant( + name, + TypeID::get(), + asGenericValue(BT::toWireType(v))); + } +} + +#define EMSCRIPTEN_BINDINGS(name) \ + static struct EmscriptenBindingInitializer_##name { \ + EmscriptenBindingInitializer_##name(); \ + } EmscriptenBindingInitializer_##name##_instance; \ + EmscriptenBindingInitializer_##name::EmscriptenBindingInitializer_##name() + + diff --git a/site/source/docs/api_reference/index.rst b/site/source/docs/api_reference/index.rst index ac6fcbaf8cb1f..d6379d25b09b0 100644 --- a/site/source/docs/api_reference/index.rst +++ b/site/source/docs/api_reference/index.rst @@ -18,6 +18,10 @@ This section lists Emscripten's public API, organised by header file. At very hi - **Filesystem-API (library_fs.js)**: *APIs for (primarily) synchronous File I/O.* +- **val.h**: *Embind APIs for* **HamishW** - add description + +- **bind.h**: *Embind APIs for* **HamishW** - add description + - **Advanced APIs**: *APIs for advanced users/core developers* In addition to the public APIs listed above, there are additional APIs which are intended only when developing Emscripten itself, or which are complicated to use and hence considered suitable for "advanced users". At time of writing are not documented individually, but are mentioned at high level in :doc:`advanced-apis`. @@ -30,6 +34,8 @@ This section lists Emscripten's public API, organised by header file. At very hi html5.h preamble.js Filesystem-API + val.h + bind.h advanced-apis diff --git a/site/source/docs/api_reference/val.h.rst b/site/source/docs/api_reference/val.h.rst new file mode 100644 index 0000000000000..32f52a3296694 --- /dev/null +++ b/site/source/docs/api_reference/val.h.rst @@ -0,0 +1,234 @@ +.. _val-h: + +================================ +val.h (under-construction) +================================ + +The C++ APIs in `val.h `_ define (**HamishW**-Replace with description.) + +.. contents:: Table of Contents + :local: + :depth: 1 + +.. COMMENT (Not rendered) : This created from val.h header file on 10 Aug 2014-03 + + +.. cpp:type: EMSCRIPTEN_SYMBOL(name) + + **HamishW**-Replace with description. + + + +.. cpp:namespace:: emscripten + +.. cpp:class:: val + + **HamishW** Notes from source FYI: :: + + // missing operators: + // * delete + // * in + // * instanceof + // * ! ~ - + ++ -- + // * * / % + // * + - + // * << >> >>> + // * < <= > >= + // * == != === !== + // * & ^ | && || ?: + // + // exposing void, comma, and conditional is unnecessary + // same with: = += -= *= /= %= <<= >>= >>>= &= ^= |= + + + .. cpp:function:: static val array() + + **HamishW**-Replace with description. + + :returns: **HamishW**-Replace with description. + + + .. cpp:function:: static val object() + + **HamishW**-Replace with description. + + :returns: **HamishW**-Replace with description. + + + .. cpp:function:: static val undefined() + + **HamishW**-Replace with description. + + :returns: **HamishW**-Replace with description. + + + .. cpp:function:: static val null() + + **HamishW**-Replace with description. + + :returns: **HamishW**-Replace with description. + + + .. cpp:function:: static val take_ownership(internal::EM_VAL e) + + **HamishW**-Replace with description. + + :returns: **HamishW**-Replace with description. + + + .. cpp:function:: static val global(const char* name) + + **HamishW**-Replace with description. + + :param const char* name: **HamishW**-Replace with description. + :returns: **HamishW**-Replace with description. + + + + .. cpp:function:: static val module_property(const char* name) + + **HamishW**-Replace with description. + + :param const char* name: **HamishW**-Replace with description. + :returns: **HamishW**-Replace with description. + + + .. cpp:function:: static val module_property(const char* name) + + **HamishW**-Replace with description. + + :param const char* name: **HamishW**-Replace with description. + :returns: **HamishW**-Replace with description. + + .. cpp:function:: explicit val(T&& value) + + **HamishW**-Replace with description. + + :param T&& value: **HamishW**-Replace with description. + + + **HamishW** Don't know how following "floating statement works". Leaving here for discussion + val() = delete; + + .. cpp:function:: explicit val(const char* v) + + **HamishW**-Replace with description. + + :param const char* v: **HamishW**-Replace with description. + + + .. cpp:function:: val(val&& v) + + **HamishW**-Replace with description. + + :param val&& v: **HamishW**-Replace with description. + + + .. cpp:function:: val(const val& v) + + **HamishW**-Replace with description. + + :param const val& v: **HamishW**-Replace with description. + + + .. cpp:function:: ~val() + + Destructor. **HamishW**-Replace with further description or delete comment. + + + .. cpp:function:: val(const val& v) + + **HamishW**-Replace with description. + + :param const val& v: **HamishW**-Replace with description. + + + .. cpp:function:: val& operator=(val&& v) + + **HamishW**-Replace with description. + + :param val&& v: **HamishW**-Replace with description. + :returns: **HamishW**-Replace with description. + + + .. cpp:function:: val& operator=(const val& v) + + **HamishW**-Replace with description. + + :param val&& v: **HamishW**-Replace with description. + :returns: **HamishW**-Replace with description. + + + .. cpp:function:: bool hasOwnProperty(const char* key) const + + **HamishW**-Replace with description. + + :param const char* key: **HamishW**-Replace with description. + :returns: **HamishW**-Replace with description. + + + .. cpp:function:: val new_(Args&&... args) const + + **HamishW**-Replace with description. + + :param Args&&... args: **HamishW**-Replace with description. Note that this is a templated value. + :returns: **HamishW**-Replace with description. + + + + .. cpp:function:: val operator[](const T& key) const + + **HamishW**-Replace with description. + + :param const T& key: **HamishW**-Replace with description. Note that this is a templated value. + :returns: **HamishW**-Replace with description. + + + .. cpp:function:: void set(const K& key, const val& v) + + **HamishW**-Replace with description. + + :param const K& key: **HamishW**-Replace with description. Note that this is a templated value. + :param const val& v: **HamishW**-Replace with description. Note that this is a templated value. + + + .. cpp:function:: val operator()(Args&&... args) + + **HamishW**-Replace with description. + + :param Args&&... args: **HamishW**-Replace with description. Note that this is a templated value. + + + .. cpp:function:: ReturnValue call(const char* name, Args&&... args) const + + **HamishW**-Replace with description. + + :param const char* name: **HamishW**-Replace with description. + :param Args&&... args: **HamishW**-Replace with description. Note that this is a templated value. + + + .. cpp:function:: T as() const + + **HamishW**-Replace with description. + + :returns: **HamishW**-Replace with description. Note that this is a templated value. + + + .. cpp:function:: val typeof() const + + **HamishW**-Replace with description. + + :returns: **HamishW**-Replace with description. + + + .. cpp:function:: std::vector vecFromJSArray(val v) + + **HamishW**-Replace with description. + + **HamishW**. I believe NOT internal. Please confirm. + + :param val v: **HamishW**-Replace with description. + :returns: **HamishW**-Replace with description. + + + diff --git a/site/source/docs/building_from_source/building_emscripten_from_source_on_linux.rst b/site/source/docs/building_from_source/building_emscripten_from_source_on_linux.rst index 25690b27e41dd..b6497c004b5c9 100644 --- a/site/source/docs/building_from_source/building_emscripten_from_source_on_linux.rst +++ b/site/source/docs/building_from_source/building_emscripten_from_source_on_linux.rst @@ -42,11 +42,12 @@ These instructions explain how to install **all** the :ref:`required tools `_ with the git package. Instead of using ``sdk-incoming-64bit``, you may need to enter: - - ``sdk-incoming-64bit`` is the target for a complete 64bit Emscripten environment build from the incoming branch of the Emscripten and *Fastcomp* repositories. Other ``sdk-``targets are provided for the master branch and 32bit builds. - - ``emscripten-incoming`` and ``emscripten-master`` are targets for the Emscripten repository (only) - - ``clang-incoming-64bit`` is the target for getting and building Fastcomp (only) from its repositories. Other ``clang-``targets are provided for the master branch and 32bit builds. + :: + + emsdk install clang-incoming-64bit node-0.10.17-64bit python-2.7.5.3-64bit java-7.45-64bit emscripten-incoming + +.. note:: The SDK supplies a number of other "repository" targets. These targets are viewed by entering ``./emsdk list`` on the command prompt: + + - ``sdk-incoming-64bit`` is the target for a complete 64-bit Emscripten environment build from the incoming branch of the Emscripten and *Fastcomp* repositories. This is equivalent to: + + :: + + emsdk install clang-incoming-64bit node-0.10.17-64bit python-2.7.5.3-64bit java-7.45-64bit emscripten-incoming git-1.8.3 + + Other ``sdk-`` targets are provided for the master branch and 32bit builds. - Typically contributors use the *sdk-incoming-64bit* target as shown. + - ``emscripten-incoming`` and ``emscripten-master`` are targets for the Emscripten repository (only) + - ``clang-incoming-64bit`` is the target for getting and building Fastcomp (only) from its repositories. Other ``clang-`` targets are provided for the master branch and 32bit builds. + Building Emscripten using your own fork diff --git a/site/source/docs/building_from_source/toolchain_what_is_needed.rst b/site/source/docs/building_from_source/toolchain_what_is_needed.rst index 2d67ae7b90dc6..1303a24d4f786 100644 --- a/site/source/docs/building_from_source/toolchain_what_is_needed.rst +++ b/site/source/docs/building_from_source/toolchain_what_is_needed.rst @@ -40,12 +40,16 @@ Compiler toolchain When building Emscripten from source code, whether "manually" or using the SDK, you will also need a *compiler toolchain* (including *gcc*, *g++*, *cmake*, etc.): -- Windows: Install `gcc 4.6 `_ -- Linux: Install *gcc* from the **build-essential** package: +- Windows: Install `gcc 4.6 `_ and `cmake `_ (cmake-3.0.1-win32-x86.exe) + +- Linux: Install *gcc* and *cmake*: :: + #Install gcc sudo apt-get install build-essential + # Install cmake + sudo apt-get install cmake - Mac OS X: Install the *XCode Command Line Tools*: diff --git a/site/source/docs/getting_started/downloads.rst b/site/source/docs/getting_started/downloads.rst index 565d9d9ece7ac..eca915d597db5 100644 --- a/site/source/docs/getting_started/downloads.rst +++ b/site/source/docs/getting_started/downloads.rst @@ -43,14 +43,14 @@ Linux and Mac OS X Installation instructions ========================= -Check the relevant section below for instructions on installing your selected package. Then check the :ref:`Platform-specific notes ` at the end of the section to address any further prerequisites that exist for your system. +Check the relevant section below for instructions on installing your selected package. .. _windows-installation_instructions-NSIS: Windows: Installing using an NSIS installer -------------------------------------------- -The NSIS installers register the Emscripten SDK as a 'standard' Windows application. To install the SDK, download an NSIS .exe file, double-click on it, and run through the installer to perform the installation. +The NSIS installers register the Emscripten SDK as a *standard* Windows application. To install the SDK, download an NSIS **.exe** file, double-click on it, and run through the installer to perform the installation. After the installer finishes, the full Emscripten toolchain will be available in the directory that was chosen during the installation, and no other steps are necessary. If your system has *Visual Studio 2010* installed, the :term:`vs-tool` MSBuild plugin will be automatically installed as well. @@ -62,7 +62,9 @@ Windows, OSX and Linux: Installing the Portable SDK The *Portable Emscripten SDK* is a no-installer version of the SDK package. It is identical to the NSIS installer, except that it does not interact with the Windows registry. This allows Emscripten to be used on a computer without administrative privileges, and means that the installation can be migrated from one location (directory or computer) to another by simply copying the directory contents to the new location. -If you want to use the *Portable Emscripten SDK*, the initial setup process is as follows: +First check the :ref:`Platform-specific notes ` below and install any prerequisites. + +Install the SDK using the following steps: 1. Download and unzip the portable SDK package to a directory of your choice. This directory will contain the Emscripten SDK. #. Open a command prompt inside the SDK directory and run the following :ref:`emsdk ` commands to get the latest SDK tools and set them as :term:`active `. @@ -95,7 +97,7 @@ Mac OS X - *Git* is not installed automatically. Git is only needed if you want to use tools from one of the development branches: **emscripten-incoming** or **emscripten-master** directly. To install *git* on OSX: - 1. Install XCode and the XCode Command Line Tools. This will provide *git* to the system PATH. For more help on this step, see `this stackoverflow post `_. + 1. Install *XCode* and the *XCode Command Line Tools*. This will provide *git* to the system PATH. For more help on this step, see `this stackoverflow post `_. 2. Install git directly from http://git-scm.com/. - *Java* is not bundled with the Emscripten SDK. After installing Emscripten via :ref:`emsdk `, typing ``./emcc --help`` should pop up a dialog that will automatically download a Java Runtime to the system: :: @@ -112,11 +114,38 @@ Linux .. note:: Pre-built binaries of tools are not available on Linux. Installing a tool will automatically clone and build that tool from the sources inside the **emsdk** directory. *Emsdk* does not interact with Linux package managers on the behalf of the user, nor does it install any tools to the system. All file changes are done inside the **emsdk/** directory. -- The system must have a working compiler environment available (because *emsdk* builds software from the source). -- *Python*, *node.js* or *Java* are not provided by *emsdk*. The user is expected to install these beforehand with the *system package manager*. -- *Git* is not installed automatically. Git is only needed if you want to use tools from one of the development branches **emscripten-incoming** or **emscripten-master**. +- The system must have a working :ref:`compiler-toolchain` (because *emsdk* builds software from the source): + + :: + + #Update the package lists + sudo apt-get update + + # Install *gcc* (and related dependencies) + sudo apt-get install build-essential + # Install cmake + sudo apt-get install cmake + + +- *Python*, *node.js* or *Java* are not provided by *emsdk*. The user is expected to install these beforehand with the *system package manager*: + + :: + + # Install Python + sudo apt-get install python2.7 + # Install node.js + sudo apt-get install nodejs + # Install Java + sudo apt-get install default-jre + +- *Git* is not installed automatically. Git is only needed if you want to use tools from one of the development branches **emscripten-incoming** or **emscripten-master**: + + :: + + # Install git + sudo apt-get install git-core -.. todo:: **HamishW** Add instructions for installing Git on Linux. +More detailed instructions on the toolchain are provided in: :ref:`building-emscripten-on-linux`. Verifying the installation From 024f6a4349de99488d1f36f6b4077fbc44f46b0f Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 14 Aug 2014 10:48:36 -0700 Subject: [PATCH 49/91] better warning when no java --- tools/shared.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/shared.py b/tools/shared.py index 71b6ec0bbac3b..f9394be51a0c8 100644 --- a/tools/shared.py +++ b/tools/shared.py @@ -444,7 +444,7 @@ def check_sanity(force=False): try: subprocess.call([JAVA, '-version'], stdout=PIPE, stderr=PIPE) except: - logging.warning('java does not seem to exist, required for closure compiler. -O2 and above will fail. You need to define JAVA in ~/.emscripten') + logging.warning('java does not seem to exist, required for closure compiler, which is optional (define JAVA in ~/.emscripten if you want it)') if not os.path.exists(CLOSURE_COMPILER): logging.warning('Closure compiler (%s) does not exist, check the paths in %s. -O2 and above will fail' % (CLOSURE_COMPILER, EM_CONFIG)) From 7febd65fb3ee97a051df4e47593509edb69bb507 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 14 Aug 2014 11:27:51 -0700 Subject: [PATCH 50/91] save llvm debug info for source maps, even if js opts run --- emcc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/emcc b/emcc index a9e8f5a297277..333414d7e0e06 100755 --- a/emcc +++ b/emcc @@ -1456,7 +1456,7 @@ try: # Request LLVM debug info if explicitly specified, or building bitcode with -g, or if building a source all the way to JS with -g if debug_level >= 4 or ((final_suffix not in JS_CONTAINING_SUFFIXES or (has_source_inputs and final_suffix in JS_CONTAINING_SUFFIXES)) and requested_debug == '-g'): - if not (final_suffix in JS_CONTAINING_SUFFIXES and js_opts): # do not save llvm debug info if js optimizer will wipe it out anyhow + if debug_level == 4 or not (final_suffix in JS_CONTAINING_SUFFIXES and js_opts): # do not save llvm debug info if js optimizer will wipe it out anyhow (but if source maps are used, keep it) newargs.append('-g') # preserve LLVM debug info debug_level = 4 From c2788e0bf9f55f367e52e317a4875a4ae68d2beb Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 14 Aug 2014 12:55:05 -0700 Subject: [PATCH 51/91] fix testcase 1 of #1714, proper handling of resumeException, and remove hack in __cxa_begin_catch --- src/library.js | 23 +++++---- tests/core/test_exceptions_resume.cpp | 68 +++++++++++++++++++++++++++ tests/core/test_exceptions_resume.txt | 1 + tests/test_core.py | 12 ++++- 4 files changed, 94 insertions(+), 10 deletions(-) create mode 100644 tests/core/test_exceptions_resume.cpp create mode 100644 tests/core/test_exceptions_resume.txt diff --git a/src/library.js b/src/library.js index 8c0f4a8d7c256..e9e037b72e60b 100644 --- a/src/library.js +++ b/src/library.js @@ -3882,7 +3882,7 @@ LibraryManager.library = { } #endif #if EXCEPTION_DEBUG - Module.printErr('Compiled code throwing an exception, ' + [ptr,type,destructor] + ', at ' + stackTrace()); + Module.printErr('Compiled code throwing an exception, ' + [ptr,type,destructor]); #endif var header = ptr - ___cxa_exception_header_size; {{{ makeSetValue('header', 0, 'type', 'void*') }}}; @@ -3902,6 +3902,9 @@ LibraryManager.library = { __cxa_rethrow: function() { ___cxa_end_catch.rethrown = true; var ptr = ___cxa_caught_exceptions.pop(); +#if EXCEPTION_DEBUG + Module.printErr('Compiled code RE-throwing an exception, popped ' + [ptr,___cxa_last_thrown_exception, 'stack', ___cxa_caught_exceptions]); +#endif ___cxa_last_thrown_exception = ptr; {{{ makeThrow('ptr') }}} }, @@ -3921,15 +3924,13 @@ LibraryManager.library = { llvm_eh_typeid_for: function(type) { return type; }, - // Note that we push the last thrown exception here rather than the ptr. - // This is because if the exception is a pointer (as in test 3 of test_exceptions_typed), - // we don't actually get the value that we allocated, but something else. Easiest - // to remember that the last exception thrown is going to be the first to be caught, - // so just use that value instead as it is what we're really looking for. __cxa_begin_catch__deps: ['_ZSt18uncaught_exceptionv', '__cxa_caught_exceptions', '__cxa_last_thrown_exception'], __cxa_begin_catch: function(ptr) { __ZSt18uncaught_exceptionv.uncaught_exception--; - ___cxa_caught_exceptions.push(___cxa_last_thrown_exception); + ___cxa_caught_exceptions.push(ptr); +#if EXCEPTION_DEBUG + Module.printErr('cxa_begin_catch ' + [ptr, 'stack', ___cxa_caught_exceptions]); +#endif return ptr; }, // We're done with a catch. Now, we can run the destructor if there is one @@ -3950,6 +3951,9 @@ LibraryManager.library = { #endif // Call destructor if one is registered then clear it. var ptr = ___cxa_caught_exceptions.pop(); +#if EXCEPTION_DEBUG + Module.printErr('cxa_end_catch popped ' + [ptr,___cxa_last_thrown_exception, 'stack', ___cxa_caught_exceptions]); +#endif if (ptr) { var header = ptr - ___cxa_exception_header_size; var destructor = {{{ makeGetValue('header', 4, 'void*') }}}; @@ -3959,6 +3963,9 @@ LibraryManager.library = { } ___cxa_free_exception(ptr); ___cxa_last_thrown_exception = 0; +#if EXCEPTION_DEBUG + Module.printErr(' cxa_end_catch also freeing exception ' + [ptr,___cxa_last_thrown_exception, 'stack', ___cxa_caught_exceptions]); +#endif } }, __cxa_get_exception_ptr: function(ptr) { @@ -4034,7 +4041,7 @@ LibraryManager.library = { __resumeException__deps: [function() { Functions.libraryFunctions['___resumeException'] = 1 }, '__cxa_last_thrown_exception'], // will be called directly from compiled code __resumeException: function(ptr) { #if EXCEPTION_DEBUG - Module.print("Resuming exception"); + Module.print("Resuming exception " + [ptr, ___cxa_last_thrown_exception]); #endif if (!___cxa_last_thrown_exception) { ___cxa_last_thrown_exception = ptr; } {{{ makeThrow('ptr') }}} diff --git a/tests/core/test_exceptions_resume.cpp b/tests/core/test_exceptions_resume.cpp new file mode 100644 index 0000000000000..2c8fd63e2e1d7 --- /dev/null +++ b/tests/core/test_exceptions_resume.cpp @@ -0,0 +1,68 @@ +#include +#include +#include +#include + +using namespace std; + +class MathError: public std::runtime_error { + public: + explicit MathError(const std::string& what) : std::runtime_error(what) { } +}; + +std::string _latest_err_msg; +int _result; + +int cpp_adder(int a, int b) +{ + if (a < b) + throw MathError ("a cannot be less than b."); + + return a + b; +} + +extern "C" { + + const char* latest_err_msg() { + return _latest_err_msg.c_str(); + } + + int result() { return _result; } + + int c_adder(int a, int b) + { +/*_1*/ try { +/*_2*/ try { +/*_3*/ try { + _result = cpp_adder(a, b); +/*+3a*/ } catch (MathError& e) { + if (string(e.what()).find("not-found-here") == string::npos) + throw MathError(string("Special exception caught: ") + typeid(e).name() + ": " + e.what()); + else + throw; +/*+3b*/ } catch (exception& e) { + throw; + } +/*+2*/ } catch (exception& e) { + throw; + } + return 0; +/*+1*/ } catch (exception& e) { + _latest_err_msg = string(typeid(e).name()) + ": " + e.what(); + return 1; + } + } +} + +int main() { + int rc; + + rc = c_adder(20, 35); + if (rc == 0) + printf("2nd call, result = %d\n", result()); + else + printf("2nd call, sadface: %s\n", latest_err_msg()); + + return 0; +} + diff --git a/tests/core/test_exceptions_resume.txt b/tests/core/test_exceptions_resume.txt new file mode 100644 index 0000000000000..142e53351059a --- /dev/null +++ b/tests/core/test_exceptions_resume.txt @@ -0,0 +1 @@ +2nd call, sadface: 9MathError: Special exception caught: 9MathError: a cannot be less than b. diff --git a/tests/test_core.py b/tests/test_core.py index 09a4989ce614a..8164cc343f88b 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -1398,8 +1398,8 @@ def test_exceptions_white_list(self): disabled_size = len(open('src.cpp.o.js').read()) shutil.copyfile('src.cpp.o.js', 'disabled.js') - assert size - empty_size > 2000, [empty_size, size] # big change when we disable entirely - assert size - fake_size > 2000, [fake_size, size] + assert size - empty_size > 1000, [empty_size, size] # big change when we disable entirely + assert size - fake_size > 1000, [fake_size, size] assert abs(empty_size - fake_size) < 100, [empty_size, fake_size] assert empty_size - disabled_size < 100, [empty_size, disabled_size] # full disable removes a tiny bit more assert fake_size - disabled_size < 100, [disabled_size, fake_size] @@ -1516,6 +1516,14 @@ def test_exceptions_rethrow(self): src, output = (test_path + s for s in ('.cpp', '.txt')) self.do_run_from_file(src, output) + def test_exceptions_resume(self): + if os.environ.get('EMCC_FAST_COMPILER') == '0': return self.skip('needs fastcomp') + Settings.DISABLE_EXCEPTION_CATCHING = 0 + Settings.EXCEPTION_DEBUG = 1 + test_path = path_from_root('tests', 'core', 'test_exceptions_resume') + src, output = (test_path + s for s in ('.cpp', '.txt')) + self.do_run_from_file(src, output) + def test_bad_typeid(self): if self.emcc_args is None: return self.skip('requires emcc') if os.environ.get('EMCC_FAST_COMPILER') == '0': return self.skip('needs fastcomp') From d28b528e77298a3cf7a4e70e97dd00d6d11b08db Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 14 Aug 2014 13:15:24 -0700 Subject: [PATCH 52/91] ensure emscripten heap is at least 64K --- src/preamble.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/preamble.js b/src/preamble.js index 76eca122d7925..61eefc55f0a7e 100644 --- a/src/preamble.js +++ b/src/preamble.js @@ -1009,7 +1009,7 @@ var TOTAL_MEMORY = Module['TOTAL_MEMORY'] || {{{ TOTAL_MEMORY }}}; var FAST_MEMORY = Module['FAST_MEMORY'] || {{{ FAST_MEMORY }}}; #if ASM_JS -var totalMemory = 4096; +var totalMemory = 64*1024; while (totalMemory < TOTAL_MEMORY || totalMemory < 2*TOTAL_STACK) { if (totalMemory < 16*1024*1024) { totalMemory *= 2; From bc308abe8b4d36bf3fd473346d7d7b8c79288299 Mon Sep 17 00:00:00 2001 From: Lu Wang Date: Thu, 14 Aug 2014 12:40:11 -0700 Subject: [PATCH 53/91] fix asm.js validation for coroutine --- src/library_async.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/library_async.js b/src/library_async.js index 207327f1f5b61..42068a47c5873 100644 --- a/src/library_async.js +++ b/src/library_async.js @@ -125,7 +125,7 @@ mergeInto(LibraryManager.library, { stack_size = stack_size|0; var coroutine = 0; - if (stack_size <= 0) stack_size = 4096; + if ((stack_size|0) <= 0) stack_size = 4096; coroutine = _malloc(stack_size)|0; {{{ makeSetValueAsm('coroutine', 12, 0, 'i32') }}}; @@ -147,7 +147,7 @@ mergeInto(LibraryManager.library, { {{{ makeSetValueAsm('coroutine', 8, 'STACK_MAX', 'i32') }}}; ___async_cur_frame = {{{ makeGetValueAsm('coroutine', 12, 'i32') }}}; stackRestore({{{ makeGetValueAsm('coroutine', 16, 'i32') }}}); - STACK_MAX = coroutine + 32 + {{{ makeGetValueAsm('coroutine', 20, 'i32') }}}; + STACK_MAX = (coroutine|0) + 32 + {{{ makeGetValueAsm('coroutine', 20, 'i32') }}}; if (!___async_cur_frame) { // first run From e5c29207a8fe73ff74a5fa2355952749aa49bc7a Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 14 Aug 2014 16:27:46 -0700 Subject: [PATCH 54/91] fix coroutine asm coercion --- src/library_async.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/library_async.js b/src/library_async.js index 42068a47c5873..7c509aa399c65 100644 --- a/src/library_async.js +++ b/src/library_async.js @@ -147,7 +147,7 @@ mergeInto(LibraryManager.library, { {{{ makeSetValueAsm('coroutine', 8, 'STACK_MAX', 'i32') }}}; ___async_cur_frame = {{{ makeGetValueAsm('coroutine', 12, 'i32') }}}; stackRestore({{{ makeGetValueAsm('coroutine', 16, 'i32') }}}); - STACK_MAX = (coroutine|0) + 32 + {{{ makeGetValueAsm('coroutine', 20, 'i32') }}}; + STACK_MAX = coroutine + 32 + {{{ makeGetValueAsm('coroutine', 20, 'i32') }}} | 0; if (!___async_cur_frame) { // first run From acfec62ba803076429d19c2c292087e10575d82a Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Thu, 14 Aug 2014 16:33:31 -0700 Subject: [PATCH 55/91] make cDefine error at compile time on missing defines; fixes #2672 --- src/modules.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/modules.js b/src/modules.js index b340e5bee9caf..8adba58b5e443 100644 --- a/src/modules.js +++ b/src/modules.js @@ -537,7 +537,8 @@ var LibraryManager = { // Safe way to access a C define. We check that we don't add library functions with missing defines. function cDefine(key) { - return key in C_DEFINES ? C_DEFINES[key] : ('0 /* XXX missing C define ' + key + ' */'); + if (key in C_DEFINES) return C_DEFINES[key]; + throw 'XXX missing C define ' + key + '!'; } var PassManager = { From 17e4ca035b11b9582f2023f5e0065824cd984fe0 Mon Sep 17 00:00:00 2001 From: hamishwillee Date: Fri, 15 Aug 2014 11:05:15 +1000 Subject: [PATCH 56/91] Finished draft framework for bind.h --- site/source/docs/api_reference/bind.h.rst | 751 +++++++++------------- 1 file changed, 313 insertions(+), 438 deletions(-) diff --git a/site/source/docs/api_reference/bind.h.rst b/site/source/docs/api_reference/bind.h.rst index ce99748480380..20ef6754d7dc5 100644 --- a/site/source/docs/api_reference/bind.h.rst +++ b/site/source/docs/api_reference/bind.h.rst @@ -6,8 +6,6 @@ bind.h (under-construction) The C++ APIs in `bind.h `_ define (**HamishW**-Replace with description.) -**HamishW** Typenames etc. - .. contents:: Table of Contents :local: :depth: 1 @@ -100,7 +98,7 @@ select_overload and select_const :returns: **HamishW** Add description. -.. cpp:function:: typename internal::MemberFunctionType::type select_overload(Signature (ClassType::*fn)) +.. cpp:function:: typename internal::MemberFunctionType::type select_overload( Signature (ClassType::*fn) ) **HamishW** Add description. @@ -353,484 +351,361 @@ Smart pointers :returns: **HamishW** Add description. -**HamishW** Note, did not include private class val_deleter. I am assuming all private classes are internal. +**HamishW** Note, did not include private class val_deleter. I am assuming all private classes are internal. Delete this Chad when read! Classes ====================================== +**HamishW** Add description if needed. Note from source "// abstract classes" - // abstract classes - template - class wrapper : public T, public internal::WrapperBase { - public: - typedef T class_type; - template - explicit wrapper(val&& wrapped, Args&&... args) - : T(std::forward(args)...) - , wrapped(std::forward(wrapped)) - {} +.. cpp:class:: class wrapper : public T, public internal::WrapperBase - ~wrapper() { - if (notifyJSOnDestruction) { - call("__destruct"); - } - } + **HamishW** Add description. + + This is a templated class: ``template``. - template - ReturnType call(const char* name, Args&&... args) const { - return wrapped.call(name, std::forward(args)...); - } + .. cpp:type:: class_type + + **HamishW** Add description. A typedef of ``T``, the typename of the templated type for the class. + + .. cpp:function:: explicit wrapper(val&& wrapped, Args&&... args) + + Constructor. **HamishW** Add description. + + :param val&& wrapped: **HamishW** Add description. + :param Args&&... args: **HamishW** Add description. Note that ``Args`` is a typename (templated type). + :returns: **HamishW** Add description. + + + .. cpp:function:: ~wrapper() + + Destructor. **HamishW** Add description. + + .. cpp:function:: ReturnType call(const char* name, Args&&... args) const + + Constructor. **HamishW** Add description. + + :param const char* name: **HamishW** Add description. + :param Args&&... args: **HamishW** Add description. Note that ``Args`` is a typename (templated type). + :returns: **HamishW** Add description. Note that ``ReturnType`` is a typename (templated type). -#define EMSCRIPTEN_WRAPPER(T) \ - template \ - T(::emscripten::val&& v, Args&&... args) \ - : wrapper(std::forward<::emscripten::val>(v), std::forward(args)...) \ - {} +.. cpp:function:: EMSCRIPTEN_WRAPPER(T) + **HamishW** Add description. Note that this is actually a define, but I've implemented it as a function, because that is how it behaves, and it allows me to have the T as shown, which isn't possible on Sphinx type declaration. + + :param T: **HamishW** Add description. - template - struct base { - typedef BaseClass class_type; - template - static void verify() { - static_assert(!std::is_same::value, "Base must not have same type as class"); - static_assert(std::is_base_of::value, "Derived class must derive from base"); - } +.. cpp:type:: base - static internal::TYPEID get() { - return internal::TypeID::get(); - } - - template - using Upcaster = BaseClass* (*)(ClassType*); + **HamishW** Add description. + + .. cpp:type:: class_type + + **HamishW** Add description. A typedef of ``BaseClass``, the typename of the templated type for the class. + + + .. cpp:function:: static void verify() + + **HamishW** Add description. Note, is templated function which takes typename ``ClassType``. + + + .. cpp:function:: static internal::TYPEID get() + + **HamishW** Add description. + + :returns: **HamishW** Add description. + - template + + .. cpp:function:: HAMISHW_ HELP_Needed + + **HamishW** I don't understand this C++, so not sure how to document. Putting code here for Chad to advise on how to document :: + + template + using Upcaster = BaseClass* (*)(ClassType*); + + template using Downcaster = ClassType* (*)(BaseClass*); - - template - static Upcaster getUpcaster() { - return &convertPointer; - } - - template - static Downcaster getDowncaster() { - return &convertPointer; - } - - template - static To* convertPointer(From* ptr) { - return static_cast(ptr); - } - }; - - - - struct pure_virtual { - template - struct Transform { - typedef InputType type; - }; - }; - - - - template - struct constructor { - }; - - template - class class_ { - public: - typedef ClassType class_type; - typedef BaseSpecifier base_specifier; - - class_() = delete; - - EMSCRIPTEN_ALWAYS_INLINE explicit class_(const char* name) { - using namespace internal; - - BaseSpecifier::template verify(); - - auto _getActualType = &getActualType; - auto upcast = BaseSpecifier::template getUpcaster(); - auto downcast = BaseSpecifier::template getDowncaster(); - auto destructor = &raw_destructor; - - _embind_register_class( - TypeID::get(), - TypeID>::get(), - TypeID>::get(), - BaseSpecifier::get(), - getSignature(_getActualType), - reinterpret_cast(_getActualType), - getSignature(upcast), - reinterpret_cast(upcast), - getSignature(downcast), - reinterpret_cast(downcast), - name, - getSignature(destructor), - reinterpret_cast(destructor)); - } - - template - EMSCRIPTEN_ALWAYS_INLINE const class_& smart_ptr(const char* name) const { - using namespace internal; - - typedef smart_ptr_trait PointerTrait; - typedef typename PointerTrait::element_type PointeeType; - - static_assert(std::is_same::type>::value, "smart pointer must point to this class"); - - auto get = &PointerTrait::get; - auto construct_null = &PointerTrait::construct_null; - auto share = &PointerTrait::share; - auto destructor = &raw_destructor; - - _embind_register_smart_ptr( - TypeID::get(), - TypeID::get(), - name, - PointerTrait::get_sharing_policy(), - getSignature(get), - reinterpret_cast(get), - getSignature(construct_null), - reinterpret_cast(construct_null), - getSignature(share), - reinterpret_cast(share), - getSignature(destructor), - reinterpret_cast(destructor)); - return *this; - }; - - template - EMSCRIPTEN_ALWAYS_INLINE const class_& constructor(Policies... policies) const { - return constructor( - &internal::operator_new, - policies...); - } - - template - EMSCRIPTEN_ALWAYS_INLINE const class_& constructor(ReturnType (*factory)(Args...), Policies...) const { - using namespace internal; - - // TODO: allows all raw pointers... policies need a rethink - typename WithPolicies::template ArgTypeList args; - auto invoke = &Invoker::invoke; - _embind_register_class_constructor( - TypeID::get(), - args.getCount(), - args.getTypes(), - getSignature(invoke), - reinterpret_cast(invoke), - reinterpret_cast(factory)); - return *this; - } - - template - EMSCRIPTEN_ALWAYS_INLINE const class_& smart_ptr_constructor(const char* smartPtrName, SmartPtr (*factory)(Args...), Policies...) const { - using namespace internal; - - smart_ptr(smartPtrName); - - typename WithPolicies::template ArgTypeList args; - auto invoke = &Invoker::invoke; - _embind_register_class_constructor( - TypeID::get(), - args.getCount(), - args.getTypes(), - getSignature(invoke), - reinterpret_cast(invoke), - reinterpret_cast(factory)); - return *this; - } - - template - EMSCRIPTEN_ALWAYS_INLINE const class_& allow_subclass( - const char* wrapperClassName, - const char* pointerName = "", - ::emscripten::constructor = ::emscripten::constructor() - ) const { - using namespace internal; - - auto cls = class_>(wrapperClassName) - .function("notifyOnDestruction", select_overload([](WrapperType& wrapper) { - wrapper.setNotifyJSOnDestruction(true); - })) - ; - SmartPtrIfNeeded _(cls, pointerName); - - return - class_function( - "implement", - &wrapped_new, - allow_raw_pointer()) - .class_function( - "extend", - &wrapped_extend) - ; - } - - template - EMSCRIPTEN_ALWAYS_INLINE const class_& allow_subclass( - const char* wrapperClassName, - ::emscripten::constructor constructor - ) const { - return allow_subclass(wrapperClassName, "", constructor); - } - - template - EMSCRIPTEN_ALWAYS_INLINE const class_& function(const char* methodName, ReturnType (ClassType::*memberFunction)(Args...), Policies...) const { - using namespace internal; - - auto invoker = &MethodInvoker::invoke; - - typename WithPolicies::template ArgTypeList, Args...> args; - _embind_register_class_function( - TypeID::get(), - methodName, - args.getCount(), - args.getTypes(), - getSignature(invoker), - reinterpret_cast(invoker), - getContext(memberFunction), - isPureVirtual::value); - return *this; - } - - template - EMSCRIPTEN_ALWAYS_INLINE const class_& function(const char* methodName, ReturnType (ClassType::*memberFunction)(Args...) const, Policies...) const { - using namespace internal; - - auto invoker = &MethodInvoker::invoke; - - typename WithPolicies::template ArgTypeList, Args...> args; - _embind_register_class_function( - TypeID::get(), - methodName, - args.getCount(), - args.getTypes(), - getSignature(invoker), - reinterpret_cast(invoker), - getContext(memberFunction), - isPureVirtual::value); - return *this; - } - - template - EMSCRIPTEN_ALWAYS_INLINE const class_& function(const char* methodName, ReturnType (*function)(ThisType, Args...), Policies...) const { - using namespace internal; - - typename WithPolicies::template ArgTypeList args; - auto invoke = &FunctionInvoker::invoke; - _embind_register_class_function( - TypeID::get(), - methodName, - args.getCount(), - args.getTypes(), - getSignature(invoke), - reinterpret_cast(invoke), - getContext(function), - false); - return *this; - } - - template::value>::type> - EMSCRIPTEN_ALWAYS_INLINE const class_& property(const char* fieldName, const FieldType ClassType::*field) const { - using namespace internal; - - auto getter = &MemberAccess::template getWire; - _embind_register_class_property( - TypeID::get(), - fieldName, - TypeID::get(), - getSignature(getter), - reinterpret_cast(getter), - getContext(field), - 0, - 0, - 0, - 0); - return *this; - } - - template::value>::type> - EMSCRIPTEN_ALWAYS_INLINE const class_& property(const char* fieldName, FieldType ClassType::*field) const { - using namespace internal; - - auto getter = &MemberAccess::template getWire; - auto setter = &MemberAccess::template setWire; - _embind_register_class_property( - TypeID::get(), - fieldName, - TypeID::get(), - getSignature(getter), - reinterpret_cast(getter), - getContext(field), - TypeID::get(), - getSignature(setter), - reinterpret_cast(setter), - getContext(field)); - return *this; - } - - template - EMSCRIPTEN_ALWAYS_INLINE const class_& property(const char* fieldName, Getter getter) const { - using namespace internal; - typedef GetterPolicy GP; - auto gter = &GP::template get; - _embind_register_class_property( - TypeID::get(), - fieldName, - TypeID::get(), - getSignature(gter), - reinterpret_cast(gter), - GP::getContext(getter), - 0, - 0, - 0, - 0); - return *this; - } - - template - EMSCRIPTEN_ALWAYS_INLINE const class_& property(const char* fieldName, Getter getter, Setter setter) const { - using namespace internal; - typedef GetterPolicy GP; - typedef SetterPolicy SP; - - auto gter = &GP::template get; - auto ster = &SP::template set; - - _embind_register_class_property( - TypeID::get(), - fieldName, - TypeID::get(), - getSignature(gter), - reinterpret_cast(gter), - GP::getContext(getter), - TypeID::get(), - getSignature(ster), - reinterpret_cast(ster), - SP::getContext(setter)); - return *this; - } - - template - EMSCRIPTEN_ALWAYS_INLINE const class_& class_function(const char* methodName, ReturnType (*classMethod)(Args...), Policies...) const { - using namespace internal; - - typename WithPolicies::template ArgTypeList args; - auto invoke = &internal::Invoker::invoke; - _embind_register_class_class_function( - TypeID::get(), - methodName, - args.getCount(), - args.getTypes(), - getSignature(invoke), - reinterpret_cast(invoke), - reinterpret_cast(classMethod)); - return *this; - } - }; + + + .. cpp:function:: static Upcaster getUpcaster() + + **HamishW** Add description. Note that ``ClassType`` is a typename (template parameter). + + :returns: **HamishW** Add description. + + + .. cpp:function:: static Downcaster getDowncaster() + + **HamishW** Add description. Note that ``ClassType`` is a typename (template parameter). + + :returns: **HamishW** Add description. + + + .. cpp:function:: static To* convertPointer(From* ptr) + + **HamishW** Add description. Note that ``ClassType`` is a typename (template parameter). + + :param From* ptr: **HamishW** Add description. Note that ``From`` is a typename (template parameter). + :returns: **HamishW** Add description. Note that ``To`` is a typename (template parameter). + + + +.. cpp:type:: pure_virtual + + **HamishW** Add description. + + .. cpp:type:: Transform + + **HamishW** Add description. Note that this is a templated struct taking typename parameter ``InputType`` and integer ``Index``. + + .. cpp:type:: type + + **HamishW** Add description. This is a typdef to the parent struct typename parameter ``InputType``. + + +.. cpp:type:: constructor + + **HamishW** Add description. Note that this is a template struct taking typename ``... ConstructorArgs``. + + + +.. cpp:class:: class_ + + **HamishW** Add description. Note that this is a templated class with typename parameters ``ClassType`` and ``BaseSpecifier``. + + .. cpp:type:: class_type + + **HamishW** Add description. A typedef of ``ClassType`` (a typename for the class). + + + .. cpp:type:: base_specifier + + **HamishW** Add description. A typedef of ``BaseSpecifier`` (a typename for the class). + + + .. cpp:type:: HELPNEEDEDHERE + + **HamishW** Don't know what do do with this: :: + + class_() = delete; + + + .. cpp:function:: EMSCRIPTEN_ALWAYS_INLINE explicit class_(const char* name) + + Constructor. **HamishW** Add description. + + :param const char* name: **HamishW** Add description. + :returns: **HamishW** Add description. + + + .. cpp:function:: EMSCRIPTEN_ALWAYS_INLINE const class_& smart_ptr(const char* name) const + + **HamishW** Add description. Note that this is a function template taking a typename ``PointerType``. + + :param const char* name: **HamishW** Add description. + :returns: **HamishW** Add description. + + + .. cpp:function:: EMSCRIPTEN_ALWAYS_INLINE const class_& constructor(Policies... policies) const + + **HamishW** Add description. Note that this is a function template taking typenames ``... ConstructorArgs`` and ``... Policies``. + + :param Policies... policies: **HamishW** Add description. Note that ``... Policies`` is a template typename for this function. + :returns: **HamishW** Add description. + + + .. cpp:function:: EMSCRIPTEN_ALWAYS_INLINE const class_& constructor(ReturnType (*factory)(Args...), Policies...) const + + **HamishW** Add description. Note that this is a function template taking typenames ``... Args``, ``ReturnType`` and ``... Policies``. + + :param ReturnType (*factory)(Args...): **HamishW** Add description. Note that ``Args`` and ``ReturnType`` are template typenames for this function. + :param Policies... policies: **HamishW** Add description. Note that ``Policies`` is a template typename for this function. + :returns: **HamishW** Add description. + + + .. cpp:function:: EMSCRIPTEN_ALWAYS_INLINE const class_& smart_ptr_constructor(const char* smartPtrName, SmartPtr (*factory)(Args...), Policies...) const + + **HamishW** Add description. Note that this is a function template taking typenames ``SmartPtr``, ``... Args``, and ``... Policies``. + + :param const char* smartPtrName: **HamishW** Add description. + :param SmartPtr (*factory)(Args...): **HamishW** Add description. Note that ``Args`` and ``SmartPtr`` are template typenames for this function. + :param Policies... policies: **HamishW** Add description. Note that ``Policies`` is a template typename for this function. + :returns: **HamishW** Add description. + + + .. cpp:function:: EMSCRIPTEN_ALWAYS_INLINE const class_& allow_subclass(const char* wrapperClassName, const char* pointerName = "", ::emscripten::constructor = ::emscripten::constructor() ) const + + **HamishW** Add description. Note that this is a function template taking typenames ``WrapperType``, ``PointerType``, and ``... ConstructorArgs``. + + :param const char* wrapperClassName: **HamishW** Add description. + :param const char* pointerName: **HamishW** Add description. Note that this has a default value which is dependent on the template typename parameters. + :returns: **HamishW** Add description. + + + .. cpp:function:: EMSCRIPTEN_ALWAYS_INLINE const class_& allow_subclass(const char* wrapperClassName, ::emscripten::constructor constructor) ) const + + **HamishW** Add description. Note that this is a function template taking typenames ``WrapperType`` and ``... ConstructorArgs``: ``template`` + + :param const char* wrapperClassName: **HamishW** Add description. + :param ::emscripten::constructor constructor): **HamishW** Add description. Note that ``ConstructorArgs`` is a template typename for this function. + :returns: **HamishW** Add description. + + + + .. cpp:function:: EMSCRIPTEN_ALWAYS_INLINE const class_& function(const char* methodName, ReturnType (ClassType::*memberFunction)(Args...), Policies...) const + + **HamishW** Add description. Note that this is a function template taking typenames ``ReturnType``,, ``... Args`` and ``... Policies``: ``template`` + + :param const char* methodName: **HamishW** Add description. + :param ReturnType (ClassType::*memberFunction)(Args...): **HamishW** Add description. Note that ``ReturnType`` is a template typename for this function and ``ClassType`` is a template typename for the class. + :param typename... Policies: **HamishW** Add description. Note that ``Policies`` is a template typename for this function. + :returns: **HamishW** Add description. + + + .. cpp:function:: EMSCRIPTEN_ALWAYS_INLINE const class_& function( const char* methodName, ReturnType (*function)(ThisType, Args...), Policies... ) const + + **HamishW** Add description. Note that this is a function template taking typename ``FieldType``, **Not sure how to document the section parameter**: ``template::value>::type>`` + + :param const char* methodName: **HamishW** Add description. + :param ReturnType (*function)(ThisType, Args...): **HamishW** Add description. Note that ``ReturnType``, ``ThisType`` and ``Args`` are template typenames for this function. + :param typename... Policies: **HamishW** Add description. Note that ``Policies`` is a template typename for this function. + :returns: **HamishW** Add description. + + + .. cpp:function:: EMSCRIPTEN_ALWAYS_INLINE const class_& property(const char* fieldName, const FieldType ClassType::*field) const + + **HamishW** Add description. Note that this is a function template taking typenames ``ReturnType``, ``ThisType``, ``Args`` and ``... Policies``: ``template`` + + :param const char* fieldName: **HamishW** Add description. + :param const FieldType ClassType::*field: **HamishW** Add description. Note that ``FieldType`` is a function template typename, and ``ClassType`` is a class template typename. + :returns: **HamishW** Add description. + + + .. cpp:function:: EMSCRIPTEN_ALWAYS_INLINE const class_& property(const char* fieldName, FieldType ClassType::*field) const + + **HamishW** Add description. Note that this is a function template taking typenames ``FieldType`` - **Not sure how to document/describe second typename parameter** : ``template::value>::type>`` + + :param const char* fieldName: **HamishW** Add description. + :param FieldType ClassType::*field: **HamishW** Add description. Note that ``FieldType`` is a function template typename, and ``ClassType`` is a class template typename. + :returns: **HamishW** Add description. + + + .. cpp:function:: EMSCRIPTEN_ALWAYS_INLINE const class_& property(const char* fieldName, Getter getter) const + + **HamishW** Add description. Note that this is a function template taking typename ``Getter``: ``template`` + + :param const char* fieldName: **HamishW** Add description. + :param Getter getter: **HamishW** Add description. Note that ``Getter`` is a function template typename. + :returns: **HamishW** Add description. + + + .. cpp:function:: EMSCRIPTEN_ALWAYS_INLINE const class_& property(const char* fieldName, Getter getter, Setter setter) const + + **HamishW** Add description. Note that this is a function template taking typenames ``Setter`` and ``Getter``: ``template`` + + :param const char* fieldName: **HamishW** Add description. + :param Getter getter: **HamishW** Add description. Note that ``Getter`` is a function template typename. + :param Setter setter: **HamishW** Add description. Note that ``Setter`` is a function template typename. + :returns: **HamishW** Add description. + + .. cpp:function:: EMSCRIPTEN_ALWAYS_INLINE const class_& class_function(const char* methodName, ReturnType (*classMethod)(Args...), Policies...) const + + **HamishW** Add description. Note that this is a function template taking typenames ``Setter`` and ``Getter``: ``template`` + + :param const char* methodName: **HamishW** Add description. + :param ReturnType (*classMethod)(Args...): **HamishW** Add description. Note that ``ReturnType`` and ``Args`` are function template typenames. + :param Policies...: **HamishW** Add description. Note that ``Policies`` is a function template typename. + :returns: **HamishW** Add description. + Vectors -====================================== +======= +.. cpp:function:: class_> register_vector(const char* name) - template - class_> register_vector(const char* name) { - typedef std::vector VecType; + **HamishW** Add description. + + Note that this is a templated function: ``template`` + + :param const char* name: **HamishW** Add description. + :returns: **HamishW** Add description. - void (VecType::*push_back)(const T&) = &VecType::push_back; - return class_>(name) - .template constructor<>() - .function("push_back", push_back) - .function("size", &VecType::size) - .function("get", &internal::VectorAccess::get) - .function("set", &internal::VectorAccess::set) - ; - } -Maps -====================================== +Maps +==== - template - class_> register_map(const char* name) { - typedef std::map MapType; +.. cpp:function:: class_> register_map(const char* name) - return class_(name) - .template constructor<>() - .function("size", &MapType::size) - .function("get", internal::MapAccess::get) - .function("set", internal::MapAccess::set) - ; - } + **HamishW** Add description. Note that this is a templated function: ``template`` + + :param const char* name: **HamishW** Add description. + :returns: **HamishW** Add description. Enums -====================================== +===== + + +.. cpp:class:: enum_ + + **HamishW** Add description. Note that this is a templated class: ``template`` + + .. cpp:type:: enum_type + + **HamishW** Add description. A typedef of ``EnumType`` (a typename for the class). + + + .. cpp:function:: enum_(const char* name) + + Constructor. **HamishW** Add description. + + :param const char* name: **HamishW** Add description. + :returns: **HamishW** Add description. + + + .. cpp:function:: enum_& value(const char* name, EnumType value) + + Constructor. **HamishW** Add description. + + :param const char* name: **HamishW** Add description. + :param EnumType value: **HamishW** Add description. Note that ``EnumType`` is a class template typename. + :returns: **HamishW** Add description. - template - class enum_ { - public: - typedef EnumType enum_type; - - enum_(const char* name) { - using namespace internal; - _embind_register_enum( - internal::TypeID::get(), - name, - sizeof(EnumType), - std::is_signed::type>::value); - } - - enum_& value(const char* name, EnumType value) { - using namespace internal; - // TODO: there's still an issue here. - // if EnumType is an unsigned long, then JS may receive it as a signed long - static_assert(sizeof(value) <= sizeof(internal::GenericEnumValue), "enum type must fit in a GenericEnumValue"); - - _embind_register_enum_value( - internal::TypeID::get(), - name, - static_cast(value)); - return *this; - } - }; Constants -====================================== +========= +.. cpp:function:: void constant(const char* name, const ConstantType& v) + **HamishW** Add description. Note that this is a templated function: ``template`` - template - void constant(const char* name, const ConstantType& v) { - using namespace internal; - typedef BindingType BT; - _embind_register_constant( - name, - TypeID::get(), - asGenericValue(BT::toWireType(v))); - } -} + :param const char* name: **HamishW** Add description. + :param const ConstantType& v: **HamishW** Add description. Note that ``ConstantType`` is a template typename for the function. -#define EMSCRIPTEN_BINDINGS(name) \ - static struct EmscriptenBindingInitializer_##name { \ - EmscriptenBindingInitializer_##name(); \ - } EmscriptenBindingInitializer_##name##_instance; \ - EmscriptenBindingInitializer_##name::EmscriptenBindingInitializer_##name() + +.. cpp:function:: EMSCRIPTEN_BINDINGS(name) + + **HamishW** Add description. Note that this is actually a define, but I've implemented it as a function, because that is how it behaves, and it allows me to have the name parameter as shown, which isn't possible on Sphinx type declaration. + + :param name: **HamishW** Add description. + +.. COMMENT (not rendered): Following values are common to many functions, and currently only updated in one place (here). +.. COMMENT (not rendered): These can be properly replaced if required either wholesale or on an individual basis. + +.. |policies-argument| replace:: Some boilerplate, this is an example only and can be removed. From dcfc6be204c0d32a567da2cb2de5483a618aa4b2 Mon Sep 17 00:00:00 2001 From: Bruce Mitchener Date: Fri, 15 Aug 2014 08:53:58 +0700 Subject: [PATCH 57/91] [doc] Fix typo. --- site/source/docs/optimizing/Optimizing-Code.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/source/docs/optimizing/Optimizing-Code.rst b/site/source/docs/optimizing/Optimizing-Code.rst index 1f1dcb1a9016b..14427137684ae 100644 --- a/site/source/docs/optimizing/Optimizing-Code.rst +++ b/site/source/docs/optimizing/Optimizing-Code.rst @@ -103,7 +103,7 @@ emscripten can emit a binary file on the side by running emcc with ``--memory-init-file 1`` This is the default in ``-O2`` and above in emscripten 1.21.1 and above; -in earlier verisons, you can enable it manually. When utilized, a file +in earlier versions, you can enable it manually. When utilized, a file with suffix ``.mem`` should appear, and it will be loaded by the JS. See ``emcc --help`` for more details. From d859997709a8880a1aac82707305f0094754d99b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jukka=20Jyl=C3=A4nki?= Date: Fri, 15 Aug 2014 12:51:04 +0300 Subject: [PATCH 58/91] Make --emrun startup pre-js not fail when running in conjunction with --proxy-to-worker. --- src/emrun_prejs.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/emrun_prejs.js b/src/emrun_prejs.js index 14613c5df223e..fdc7508ebb8f9 100644 --- a/src/emrun_prejs.js +++ b/src/emrun_prejs.js @@ -1,5 +1,7 @@ // Route URL GET parameters to argc+argv -Module['arguments'] = window.location.search.substr(1).trim().split('&'); -// If no args were passed arguments = [''], in which case kill the single empty string. -if (!Module['arguments'][0]) - Module['arguments'] = []; +if (typeof window === "object") { + Module['arguments'] = window.location.search.substr(1).trim().split('&'); + // If no args were passed arguments = [''], in which case kill the single empty string. + if (!Module['arguments'][0]) + Module['arguments'] = []; +} \ No newline at end of file From 568d32ec75d5b71d0771046f870e8729bf07549a Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 15 Aug 2014 10:41:39 -0700 Subject: [PATCH 59/91] wait for window:load to run emrun_register_handlers --- src/emrun_postjs.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/emrun_postjs.js b/src/emrun_postjs.js index 8bcea9a99e94a..9b2f28b472cf4 100644 --- a/src/emrun_postjs.js +++ b/src/emrun_postjs.js @@ -17,7 +17,7 @@ function emrun_register_handlers() { // Notify emrun web server that this browser has successfully launched the page. post('^pageload^'); } -emrun_register_handlers(); +window.addEventListener('load', emrun_register_handlers); // POSTs the given binary data represented as a (typed) array data back to the emrun-based web server. // To use from C code, call e.g. EM_ASM_({emrun_file_dump("file.dat", HEAPU8.subarray($0, $0 + $1));}, my_data_pointer, my_data_pointer_byte_length); From cd0d4a00f6df8bf9c87636415c5bfa20247a2a13 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 15 Aug 2014 10:55:50 -0700 Subject: [PATCH 60/91] forward document.URL to worker --- src/proxyClient.js | 2 +- src/proxyWorker.js | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/proxyClient.js b/src/proxyClient.js index 3fc8313fe7a60..8ab99d887c010 100644 --- a/src/proxyClient.js +++ b/src/proxyClient.js @@ -82,7 +82,7 @@ var worker = new Worker('{{{ filename }}}.js'); WebGLClient.prefetch(); setTimeout(function() { - worker.postMessage({ target: 'worker-init', width: Module.canvas.width, height: Module.canvas.height, preMain: true }); + worker.postMessage({ target: 'worker-init', width: Module.canvas.width, height: Module.canvas.height, URL: document.URL, preMain: true }); }, 0); // delay til next frame, to make sure html is ready var workerResponded = false; diff --git a/src/proxyWorker.js b/src/proxyWorker.js index 7647b5dad27d6..1753dd33492a9 100644 --- a/src/proxyWorker.js +++ b/src/proxyWorker.js @@ -271,6 +271,8 @@ document.styleSheets = [{ } }]; +document.URL = 'http://worker.not.yet.ready.wait.for.window.onload?fake'; + function Audio() { Runtime.warnOnce('faking Audio elements, no actual sound will play'); } @@ -393,6 +395,8 @@ onmessage = function onmessage(message) { Module.canvas = document.createElement('canvas'); Module.canvas.width_ = message.data.width; Module.canvas.height_ = message.data.height; + document.URL = message.data.URL; + window.fireEvent({ type: 'load' }); removeRunDependency('worker-init'); break; } From 7bc8e4bf1ed5b3d96aed26cddde60128d0e97798 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 15 Aug 2014 11:07:36 -0700 Subject: [PATCH 61/91] comment on worker failure in emrun_file_dump --- src/emrun_postjs.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/emrun_postjs.js b/src/emrun_postjs.js index 9b2f28b472cf4..4f20d479e570a 100644 --- a/src/emrun_postjs.js +++ b/src/emrun_postjs.js @@ -25,5 +25,5 @@ function emrun_file_dump(filename, data) { var http = new XMLHttpRequest(); Module['print']('Dumping out file "' + filename + '" with ' + data.length + ' bytes of data.'); http.open("POST", "stdio.html?file=" + filename, true); - http.send(data); + http.send(data); // XXX this does not work in workers, for some odd reason (issue #2681) } From 6a14c99241270ab7e2f2be310722be018149b86a Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 15 Aug 2014 14:49:49 -0700 Subject: [PATCH 62/91] fix async assertion for asm --- src/library_async.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/library_async.js b/src/library_async.js index 7c509aa399c65..0e527f7aad203 100644 --- a/src/library_async.js +++ b/src/library_async.js @@ -89,7 +89,7 @@ mergeInto(LibraryManager.library, { // just undo a recent emscripten_alloc_async_context ctx = ctx|0; #if ASSERTIONS - assert(___async_cur_frame + 8 == ctx); + assert((((___async_cur_frame + 8)|0) == (ctx|0))|0); #endif stackRestore(___async_cur_frame); ___async_cur_frame = {{{ makeGetValueAsm('___async_cur_frame', 0, 'i32') }}}; From dc98c8b1b802fc5326719624a6d4fe63ac04701c Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Fri, 15 Aug 2014 15:35:48 -0700 Subject: [PATCH 63/91] Optimize 'HEAP32[(46 + 2|0) >> 2' to 'HEAP32[12]' Merge joinAdditions and "num >> num" folding into simplifyBitops, and rename it to simplifyOps. Make the main traversal in simplifyOps use a "post" function rather than a pre function to allow optimizations to cascade. The result is that given an expression like 'HEAP32[(46 + 2|0) >> 2', simplifyOps can start by folding the '46 + 2', and then work its way out and fold in the '>> 2', and arrive at 'HEAP32[12]'. --- tools/js-optimizer.js | 68 +++++++++-------------- tools/test-js-optimizer-asm-pre-output.js | 2 +- tools/test-js-optimizer-output.js | 8 ++- tools/test-js-optimizer.js | 4 ++ 4 files changed, 38 insertions(+), 44 deletions(-) diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js index 5ab0d8c6a93d8..23e242f67f1fc 100644 --- a/tools/js-optimizer.js +++ b/tools/js-optimizer.js @@ -406,7 +406,7 @@ function simplifyExpressions(ast) { // Likewise, if we have |0 inside a block that will be >>'d, then the |0 is unnecessary because some // 'useful' mathops already |0 anyhow. - function simplifyBitops(ast) { + function simplifyOps(ast) { var SAFE_BINARY_OPS; if (asm) { SAFE_BINARY_OPS = set('+', '-'); // division is unsafe as it creates non-ints in JS; mod is unsafe as signs matter so we can't remove |0's; mul does not nest with +,- in asm @@ -495,7 +495,9 @@ function simplifyExpressions(ast) { var hasTempDoublePtr = false, rerunOrZeroPass = false; - traverse(ast, function(node, type) { + // Use a "post" visitor so that we simplify a node's operands before the + // node itself. This allows optimizations to cascade. + traverse(ast, function(node, type) { }, function(node, type) { if (type === 'name') { if (node[1] === 'tempDoublePtr') hasTempDoublePtr = true; } else if (type === 'binary' && node[1] === '&' && node[3][0] === 'num') { @@ -587,6 +589,28 @@ function simplifyExpressions(ast) { } } else if (type == 'sub' && node[1][0] == 'name' && /^FUNCTION_TABLE.*/.exec(node[1][1])) { return null; // do not traverse subchildren here, we should not collapse 55 & 126. TODO: optimize this into a nonvirtual call (also because we lose some other opts here)! + } else if (type === 'binary' && node[1] === '>>' && node[2][0] === 'num' && node[3][0] === 'num') { + // optimize num >> num, in asm we need this since we do not run optimizeShifts + node[0] = 'num'; + node[1] = node[2][1] >> node[3][1]; + node.length = 2; + return node; + } else if (type === 'binary' && node[1] === '+') { + // The most common mathop is addition, e.g. in getelementptr done repeatedly. We can join all of those, + // by doing (num+num) ==> newnum, and (name+num)+num = name+newnum + if (node[2][0] === 'num' && node[3][0] === 'num') { + node[2][1] += node[3][1]; + return node[2]; + } + for (var i = 2; i <= 3; i++) { + var ii = 5-i; + for (var j = 2; j <= 3; j++) { + if (node[i][0] === 'num' && node[ii][0] === 'binary' && node[ii][1] === '+' && node[ii][j][0] === 'num') { + node[ii][j][1] += node[i][1]; + return node[ii]; + } + } + } } }); @@ -693,43 +717,6 @@ function simplifyExpressions(ast) { } denormalizeAsm(ast, asmData); } - - // optimize num >> num, in asm we need this here since we do not run optimizeShifts - traverse(ast, function(node, type) { - if (type === 'binary' && node[1] === '>>' && node[2][0] === 'num' && node[3][0] === 'num') { - node[0] = 'num'; - node[1] = node[2][1] >> node[3][1]; - node.length = 2; - } - }); - } - } - - // The most common mathop is addition, e.g. in getelementptr done repeatedly. We can join all of those, - // by doing (num+num) ==> newnum, and (name+num)+num = name+newnum - function joinAdditions(ast) { - var rerun = true; - while (rerun) { - rerun = false; - traverse(ast, function(node, type) { - if (type === 'binary' && node[1] === '+') { - if (node[2][0] === 'num' && node[3][0] === 'num') { - rerun = true; - node[2][1] += node[3][1]; - return node[2]; - } - for (var i = 2; i <= 3; i++) { - var ii = 5-i; - for (var j = 2; j <= 3; j++) { - if (node[i][0] === 'num' && node[ii][0] === 'binary' && node[ii][1] === '+' && node[ii][j][0] === 'num') { - rerun = true; - node[ii][j][1] += node[i][1]; - return node[ii]; - } - } - } - } - }); } } @@ -813,8 +800,7 @@ function simplifyExpressions(ast) { traverseGeneratedFunctions(ast, function(func) { simplifyIntegerConversions(func); - simplifyBitops(func); - joinAdditions(func); + simplifyOps(func); simplifyNotComps(func); conditionalize(func); // simplifyZeroComp(func); TODO: investigate performance diff --git a/tools/test-js-optimizer-asm-pre-output.js b/tools/test-js-optimizer-asm-pre-output.js index da3ebb4f5303e..230ba2736d0d8 100644 --- a/tools/test-js-optimizer-asm-pre-output.js +++ b/tools/test-js-optimizer-asm-pre-output.js @@ -19,7 +19,7 @@ function a() { f(g() | 0 & -1); f((g() | 0) >> 2); $56 = _fcntl() | 0 | 1; - FUNCTION_TABLE_ii[55 & 127]() | 0; + FUNCTION_TABLE_ii[55]() | 0; } function b($this, $__n) { $this = $this | 0; diff --git a/tools/test-js-optimizer-output.js b/tools/test-js-optimizer-output.js index 41f79f76870b0..570fbaa2b0b95 100644 --- a/tools/test-js-optimizer-output.js +++ b/tools/test-js-optimizer-output.js @@ -284,14 +284,18 @@ function tricky() { function asmy() { f(HEAPU8[_buf + i6 & 16777215]); f(HEAPU8[_buf + i6 & 16777215]); - f(HEAP8[_buf + i6 & 16777215] & 1); + f(HEAPU8[_buf + i6 & 16777215] & 1); f(HEAPU8[_buf + i6 & 16777215] & 1); f(HEAP8[_buf + i6 & 16777215] & 1); f(HEAPU8[_buf + i6 & 16777215] & 1); - f((HEAP8[_buf + i6 & 16777215] & 1) + i5 | 0); + f((HEAPU8[_buf + i6 & 16777215] & 1) + i5 | 0); f((HEAPU8[_buf + i6 & 16777215] & 1) + i5 | 0); f((HEAP8[_buf + i6 & 16777215] & 1) + i5 | 0); f((HEAPU8[_buf + i6 & 16777215] & 1) + i5 | 0); + f(HEAP32[12]); + f(HEAPU32[12]); + f(HEAP32[5]); + f(HEAPU32[5]); if ((_sbrk($419 | 0) | 0) == -1) { print("fleefl"); } diff --git a/tools/test-js-optimizer.js b/tools/test-js-optimizer.js index 09c59df273abe..3dc99779263e1 100644 --- a/tools/test-js-optimizer.js +++ b/tools/test-js-optimizer.js @@ -394,6 +394,10 @@ function asmy() { f((HEAPU8[_buf + i6 & 16777215] & 255 & 1) + i5 | 0); f((HEAP8[_buf + i6 & 16777215] & 1 & 255) + i5 | 0); f((HEAPU8[_buf + i6 & 16777215] & 1 & 255) + i5 | 0); + f(HEAP32[((46 + 2)|0) >> 2]); + f(HEAPU32[((46 + 2)|0) >> 2]); + f(HEAP32[((((((43 + 3)|0) + 2)|0) >> 2) + 8) >> 2]); + f(HEAPU32[((((((43 + 3)|0) + 2)|0) >> 2) + 8) >> 2]); if ((_sbrk($419 | 0) | 0 | 0) == -1) { print('fleefl'); } From 4fe5e75d847ad794cbcf3ccf93c6e9329a74ef91 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 15 Aug 2014 16:07:58 -0700 Subject: [PATCH 64/91] proxy some more gl calls --- src/webGLClient.js | 9 +++++++++ src/webGLWorker.js | 30 ++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/src/webGLClient.js b/src/webGLClient.js index 491eb4c05e738..2f2b31c7f1eb0 100644 --- a/src/webGLClient.js +++ b/src/webGLClient.js @@ -150,6 +150,10 @@ function WebGLClient() { ctx.uniform1f(objects[buffer[i]], buffer[i+1]); i += 2; } + function uniform3f() { + ctx.uniform3f(objects[buffer[i]], buffer[i+1], buffer[i+2], buffer[i+3]); + i += 4; + } function uniform3fv() { ctx.uniform3fv(objects[buffer[i]], buffer[i+1]); i += 2; @@ -233,6 +237,11 @@ function WebGLClient() { 66: { name: 'blendEquation', func: func1 }, 67: { name: 'generateMipmap', func: func1 }, 68: { name: 'uniformMatrix3fv', func: func3L0 }, + 69: { name: 'stencilMask', func: func1 }, + 70: { name: 'clearStencil', func: func1 }, + 71: { name: 'texSubImage2D', func: func9 }, + 72: { name: 'uniform3f', func: uniform3f }, + 73: { name: 'blendFuncSeparate', func: func4 }, }; function renderCommands(buf) { diff --git a/src/webGLWorker.js b/src/webGLWorker.js index 98fb008944ef3..8c7278c735046 100644 --- a/src/webGLWorker.js +++ b/src/webGLWorker.js @@ -936,6 +936,36 @@ function WebGLWorker() { if (!location) return; commandBuffer.push(68, location.id, transpose, new Float32Array(data)); }; + this.stencilMask = function(mask) { + commandBuffer.push(69, mask); + }; + this.clearStencil = function(s) { + commandBuffer.push(70, s); + }; + this.texSubImage2D = function(target, level, xoffset, yoffset, width, height, format, type, pixels) { + if (pixels === undefined) { + // shorter overload: target, level, xoffset, yoffset, format, type, pixels + var formatTemp = format; + format = width; + type = height; + pixels = formatTemp; + assert(pixels instanceof Image); + assert(format === this.RGBA); // HTML Images are RGBA, 8-bit + assert(type === this.UNSIGNED_BYTE); + var data = pixels.data; + width = data.width; + height = data.height; + pixels = new Uint8Array(data.data); // XXX transform from clamped to normal, could have been done in duplicate + } + commandBuffer.push(71, target, level, xoffset, yoffset, width, height, format, type, duplicate(pixels)); + }; + this.uniform3f = function(location, x, y, z) { + if (!location) return; + commandBuffer.push(72, location.id, x, y, z); + }; + this.blendFuncSeparate = function(srcRGB, dstRGB, srcAlpha, dstAlpha) { + commandBuffer.push(73, srcRGB, dstRGB, srcAlpha, dstAlpha); + } // Setup From e4c827a8f266e7d135639e43d81b929ba05db7a9 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Fri, 15 Aug 2014 17:17:27 -0700 Subject: [PATCH 65/91] fix bindAttribLocation semantics in gl proxying - they take place not immediately, but after the next link --- src/webGLWorker.js | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/webGLWorker.js b/src/webGLWorker.js index 8c7278c735046..a3855d81db995 100644 --- a/src/webGLWorker.js +++ b/src/webGLWorker.js @@ -10,6 +10,8 @@ function WebGLProgram(id) { this.shaders = []; this.attributes = {}; this.attributeVec = []; + this.nextAttributes = {}; + this.nextAttributeVec = []; } function WebGLFramebuffer(id) { this.what = 'frameBuffer'; @@ -584,8 +586,8 @@ function WebGLWorker() { commandBuffer.push(12, program.id, shader.id); }; this.bindAttribLocation = function(program, index, name) { - program.attributes[name] = { what: 'attribute', name: name, size: -1, location: index, type: '?' }; // fill in size, type later - program.attributeVec[index] = name; + program.nextAttributes[name] = { what: 'attribute', name: name, size: -1, location: index, type: '?' }; // fill in size, type later + program.nextAttributeVec[index] = name; commandBuffer.push(13, program.id, index, name); }; this.getAttribLocation = function(program, name) { @@ -647,6 +649,11 @@ function WebGLWorker() { program.uniforms = {}; program.uniformVec = []; + program.attributes = program.nextAttributes; + program.attributeVec = program.nextAttributeVec; + program.nextAttributes = {}; + program.nextAttributeVec = []; + var existingAttributes = {}; program.shaders.forEach(function(shader) { @@ -658,7 +665,9 @@ function WebGLWorker() { for (var attr in existingAttributes) { if (!(attr in program.attributes)) { var index = program.attributeVec.length; - this.bindAttribLocation(program, index, attr); + program.attributes[attr] = { what: 'attribute', name: attr, size: -1, location: index, type: '?' }; // fill in size, type later + program.attributeVec[index] = attr; + commandBuffer.push(13, program.id, index, attr); // do a bindAttribLocation as well, so this takes effect in the link we are about to do } program.attributes[attr].size = existingAttributes[attr].size; program.attributes[attr].type = existingAttributes[attr].type; From a1db100df3931e1e5c53d940420658427bfedf33 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sat, 16 Aug 2014 12:28:33 -0700 Subject: [PATCH 66/91] EXCEPTION_DEBUG additions --- src/library.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/library.js b/src/library.js index e9e037b72e60b..b887acd43b5b5 100644 --- a/src/library.js +++ b/src/library.js @@ -3969,6 +3969,9 @@ LibraryManager.library = { } }, __cxa_get_exception_ptr: function(ptr) { +#if EXCEPTION_DEBUG + Module.printErr('cxa_get_exception_ptr ' + ptr); +#endif return ptr; }, _ZSt18uncaught_exceptionv: function() { // std::uncaught_exception() @@ -4019,6 +4022,9 @@ LibraryManager.library = { var pointer = Module['___cxa_is_pointer_type'](throwntype); // can_catch receives a **, add indirection if (!___cxa_find_matching_catch.buffer) ___cxa_find_matching_catch.buffer = _malloc(4); +#if EXCEPTION_DEBUG + Module.print("can_catch on " + [thrown]); +#endif {{{ makeSetValue('___cxa_find_matching_catch.buffer', '0', 'thrown', '*') }}}; thrown = ___cxa_find_matching_catch.buffer; // The different catch blocks are denoted by different types. @@ -4028,6 +4034,9 @@ LibraryManager.library = { for (var i = 0; i < typeArray.length; i++) { if (typeArray[i] && Module['___cxa_can_catch'](typeArray[i], throwntype, thrown)) { thrown = {{{ makeGetValue('thrown', '0', '*') }}}; // undo indirection +#if EXCEPTION_DEBUG + Module.print(" can_catch found " + [thrown, typeArray[i]]); +#endif {{{ makeStructuralReturn(['thrown', 'typeArray[i]']) }}}; } } From b7689597ad71301acf896ac8d97474a31130d612 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sat, 16 Aug 2014 12:45:30 -0700 Subject: [PATCH 67/91] refactor exceptions info into JS objects --- src/library.js | 92 ++++++++++++++++++++++++-------------------------- 1 file changed, 45 insertions(+), 47 deletions(-) diff --git a/src/library.js b/src/library.js index b887acd43b5b5..194c70fbf1627 100644 --- a/src/library.js +++ b/src/library.js @@ -3836,26 +3836,21 @@ LibraryManager.library = { _ZTVN10__cxxabiv120__si_class_type_infoE: [2], // yes inherited classes #endif - // We store an extra header in front of the exception data provided - // by the user. - // This header is: - // * type - // * destructor function pointer - // This is then followed by the actual exception data. - __cxa_exception_header_size: 8, - __cxa_last_thrown_exception: 0, - __cxa_caught_exceptions: [], + $EXCEPTIONS: { + last: 0, + caught: [], + infos: {} + }, // Exceptions - __cxa_allocate_exception__deps: ['__cxa_exception_header_size', 'malloc'], + __cxa_allocate_exception__deps: ['malloc'], __cxa_allocate_exception: function(size) { - var ptr = _malloc(size + ___cxa_exception_header_size); - return ptr + ___cxa_exception_header_size; + return _malloc(size); }, - __cxa_free_exception__deps: ['__cxa_exception_header_size', 'free'], + __cxa_free_exception__deps: ['free'], __cxa_free_exception: function(ptr) { try { - return _free(ptr - ___cxa_exception_header_size); + return _free(ptr); } catch(e) { // XXX FIXME #if ASSERTIONS Module.printErr('exception during cxa_free_exception: ' + e); @@ -3865,7 +3860,7 @@ LibraryManager.library = { // Here, we throw an exception after recording a couple of values that we need to remember // We also remember that it was the last exception thrown as we need to know that later. __cxa_throw__sig: 'viii', - __cxa_throw__deps: ['_ZSt18uncaught_exceptionv', '__cxa_find_matching_catch', '__cxa_exception_header_size', '__cxa_last_thrown_exception'], + __cxa_throw__deps: ['_ZSt18uncaught_exceptionv', '__cxa_find_matching_catch', '$EXCEPTIONS'], __cxa_throw: function(ptr, type, destructor) { #if USE_TYPED_ARRAYS != 2 if (!___cxa_throw.initialized) { @@ -3884,10 +3879,13 @@ LibraryManager.library = { #if EXCEPTION_DEBUG Module.printErr('Compiled code throwing an exception, ' + [ptr,type,destructor]); #endif - var header = ptr - ___cxa_exception_header_size; - {{{ makeSetValue('header', 0, 'type', 'void*') }}}; - {{{ makeSetValue('header', 4, 'destructor', 'void*') }}}; - ___cxa_last_thrown_exception = ptr; + EXCEPTIONS.infos[ptr] = { + ptr: ptr, + adjusted: ptr, + type: type, + destructor: destructor + }; + EXCEPTIONS.last = ptr; if (!("uncaught_exception" in __ZSt18uncaught_exceptionv)) { __ZSt18uncaught_exceptionv.uncaught_exception = 1; } else { @@ -3898,24 +3896,24 @@ LibraryManager.library = { // This exception will be caught twice, but while begin_catch runs twice, // we early-exit from end_catch when the exception has been rethrown, so // pop that here from the caught exceptions. - __cxa_rethrow__deps: ['__cxa_end_catch', '__cxa_caught_exceptions'], + __cxa_rethrow__deps: ['__cxa_end_catch', '$EXCEPTIONS'], __cxa_rethrow: function() { ___cxa_end_catch.rethrown = true; - var ptr = ___cxa_caught_exceptions.pop(); + var ptr = EXCEPTIONS.caught.pop(); #if EXCEPTION_DEBUG - Module.printErr('Compiled code RE-throwing an exception, popped ' + [ptr,___cxa_last_thrown_exception, 'stack', ___cxa_caught_exceptions]); + Module.printErr('Compiled code RE-throwing an exception, popped ' + [ptr, EXCEPTIONS.last, 'stack', EXCEPTIONS.caught]); #endif - ___cxa_last_thrown_exception = ptr; + EXCEPTIONS.last = ptr; {{{ makeThrow('ptr') }}} }, - llvm_eh_exception__deps: ['__cxa_last_thrown_exception'], + llvm_eh_exception__deps: ['$EXCEPTIONS'], llvm_eh_exception: function() { - return ___cxa_last_thrown_exception; + return EXCEPTIONS.last; }, llvm_eh_selector__jsargs: true, - llvm_eh_selector__deps: ['__cxa_last_thrown_exception'], + llvm_eh_selector__deps: ['$EXCEPTIONS'], llvm_eh_selector: function(unused_exception_value, personality/*, varargs*/) { - var type = ___cxa_last_thrown_exception; + var type = EXCEPTIONS.last; for (var i = 2; i < arguments.length; i++) { if (arguments[i] == type) return type; } @@ -3924,12 +3922,12 @@ LibraryManager.library = { llvm_eh_typeid_for: function(type) { return type; }, - __cxa_begin_catch__deps: ['_ZSt18uncaught_exceptionv', '__cxa_caught_exceptions', '__cxa_last_thrown_exception'], + __cxa_begin_catch__deps: ['_ZSt18uncaught_exceptionv', '$EXCEPTIONS'], __cxa_begin_catch: function(ptr) { __ZSt18uncaught_exceptionv.uncaught_exception--; - ___cxa_caught_exceptions.push(ptr); + EXCEPTIONS.caught.push(ptr); #if EXCEPTION_DEBUG - Module.printErr('cxa_begin_catch ' + [ptr, 'stack', ___cxa_caught_exceptions]); + Module.printErr('cxa_begin_catch ' + [ptr, 'stack', EXCEPTIONS.caught]); #endif return ptr; }, @@ -3937,7 +3935,7 @@ LibraryManager.library = { // and free the exception. Note that if the dynCall on the destructor fails // due to calling apply on undefined, that means that the destructor is // an invalid index into the FUNCTION_TABLE, so something has gone wrong. - __cxa_end_catch__deps: ['__cxa_free_exception', '__cxa_last_thrown_exception', '__cxa_exception_header_size', '__cxa_caught_exceptions'], + __cxa_end_catch__deps: ['__cxa_free_exception', '$EXCEPTIONS'], __cxa_end_catch: function() { if (___cxa_end_catch.rethrown) { ___cxa_end_catch.rethrown = false; @@ -3950,21 +3948,20 @@ LibraryManager.library = { __THREW__ = 0; #endif // Call destructor if one is registered then clear it. - var ptr = ___cxa_caught_exceptions.pop(); + var ptr = EXCEPTIONS.caught.pop(); #if EXCEPTION_DEBUG - Module.printErr('cxa_end_catch popped ' + [ptr,___cxa_last_thrown_exception, 'stack', ___cxa_caught_exceptions]); + Module.printErr('cxa_end_catch popped ' + [ptr, EXCEPTIONS.last, 'stack', EXCEPTIONS.caught]); #endif if (ptr) { - var header = ptr - ___cxa_exception_header_size; - var destructor = {{{ makeGetValue('header', 4, 'void*') }}}; - if (destructor) { - Runtime.dynCall('vi', destructor, [ptr]); - {{{ makeSetValue('header', 4, '0', 'i32') }}}; + var info = EXCEPTIONS.infos[ptr]; + if (info && info.destructor) { + Runtime.dynCall('vi', info.destructor, [ptr]); + info.destructor = 0; } ___cxa_free_exception(ptr); - ___cxa_last_thrown_exception = 0; + EXCEPTIONS.last = 0; #if EXCEPTION_DEBUG - Module.printErr(' cxa_end_catch also freeing exception ' + [ptr,___cxa_last_thrown_exception, 'stack', ___cxa_caught_exceptions]); + Module.printErr(' cxa_end_catch also freeing exception ' + [ptr, EXCEPTIONS.last, 'stack', EXCEPTIONS.caught]); #endif } }, @@ -3972,6 +3969,7 @@ LibraryManager.library = { #if EXCEPTION_DEBUG Module.printErr('cxa_get_exception_ptr ' + ptr); #endif + // TODO: use info.adjusted? return ptr; }, _ZSt18uncaught_exceptionv: function() { // std::uncaught_exception() @@ -4004,15 +4002,15 @@ LibraryManager.library = { // functionality boils down to picking a suitable 'catch' block. // We'll do that here, instead, to keep things simpler. - __cxa_find_matching_catch__deps: ['__resumeException', '__cxa_last_thrown_exception', '__cxa_exception_header_size'], + __cxa_find_matching_catch__deps: ['__resumeException', '$EXCEPTIONS'], __cxa_find_matching_catch: function() { - var thrown = ___cxa_last_thrown_exception; + var thrown = EXCEPTIONS.last; if (!thrown) { // just pass through the null ptr {{{ makeStructuralReturn([0, 0]) }}}; } - var header = thrown - ___cxa_exception_header_size; - var throwntype = {{{ makeGetValue('header', 0, 'void*') }}}; + var info = EXCEPTIONS.infos[thrown]; + var throwntype = info.type; if (!throwntype) { // just pass through the thrown ptr {{{ makeStructuralReturn(['thrown', 0]) }}}; @@ -4047,12 +4045,12 @@ LibraryManager.library = { {{{ makeStructuralReturn(['thrown', 'throwntype']) }}}; }, - __resumeException__deps: [function() { Functions.libraryFunctions['___resumeException'] = 1 }, '__cxa_last_thrown_exception'], // will be called directly from compiled code + __resumeException__deps: ['$EXCEPTIONS', function() { Functions.libraryFunctions['___resumeException'] = 1 }], // will be called directly from compiled code __resumeException: function(ptr) { #if EXCEPTION_DEBUG - Module.print("Resuming exception " + [ptr, ___cxa_last_thrown_exception]); + Module.print("Resuming exception " + [ptr, EXCEPTIONS.last]); #endif - if (!___cxa_last_thrown_exception) { ___cxa_last_thrown_exception = ptr; } + if (!EXCEPTIONS.last) { EXCEPTIONS.last = ptr; } {{{ makeThrow('ptr') }}} }, From 13837b8f4fea423c3067b6fabc8657d37ebccd69 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sat, 16 Aug 2014 13:08:01 -0700 Subject: [PATCH 68/91] clean up exception infos --- src/library.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/library.js b/src/library.js index 194c70fbf1627..869da5a38f2c9 100644 --- a/src/library.js +++ b/src/library.js @@ -3954,9 +3954,11 @@ LibraryManager.library = { #endif if (ptr) { var info = EXCEPTIONS.infos[ptr]; - if (info && info.destructor) { - Runtime.dynCall('vi', info.destructor, [ptr]); - info.destructor = 0; + if (info) { + if (info.destructor) { + Runtime.dynCall('vi', info.destructor, [ptr]); + } + delete EXCEPTIONS.infos[ptr]; } ___cxa_free_exception(ptr); EXCEPTIONS.last = 0; From 40a68fc0676be30e468cfd148e41a7938e9448c2 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Sat, 16 Aug 2014 13:06:06 -0700 Subject: [PATCH 69/91] Fix FUNCTION_TABLE folding suppression. The check that disables simplification of expressions within FUNCTION_TABLE subscripts needs to run in the "pre" visitor, not the "post" visitor. Also drop a TODO which isn't important. Opportunities to convert an indirect call into a direct one would normally be already optimized by this point. --- tools/js-optimizer.js | 15 ++++++++++----- tools/test-js-optimizer-asm-pre-output.js | 2 +- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/tools/js-optimizer.js b/tools/js-optimizer.js index 23e242f67f1fc..dfee80c3e43d4 100644 --- a/tools/js-optimizer.js +++ b/tools/js-optimizer.js @@ -495,9 +495,16 @@ function simplifyExpressions(ast) { var hasTempDoublePtr = false, rerunOrZeroPass = false; - // Use a "post" visitor so that we simplify a node's operands before the - // node itself. This allows optimizations to cascade. - traverse(ast, function(node, type) { }, function(node, type) { + traverse(ast, function(node, type) { + // The "pre" visitor. Useful for detecting trees which should not + // be simplified. + if (type == 'sub' && node[1][0] == 'name' && /^FUNCTION_TABLE.*/.exec(node[1][1])) { + return null; // do not traverse subchildren here, we should not collapse 55 & 126. + } + }, function(node, type) { + // The "post" visitor. The simplifications are done in this visitor so + // that we simplify a node's operands before the node itself. This allows + // optimizations to cascade. if (type === 'name') { if (node[1] === 'tempDoublePtr') hasTempDoublePtr = true; } else if (type === 'binary' && node[1] === '&' && node[3][0] === 'num') { @@ -587,8 +594,6 @@ function simplifyExpressions(ast) { node[3] = value[2]; } } - } else if (type == 'sub' && node[1][0] == 'name' && /^FUNCTION_TABLE.*/.exec(node[1][1])) { - return null; // do not traverse subchildren here, we should not collapse 55 & 126. TODO: optimize this into a nonvirtual call (also because we lose some other opts here)! } else if (type === 'binary' && node[1] === '>>' && node[2][0] === 'num' && node[3][0] === 'num') { // optimize num >> num, in asm we need this since we do not run optimizeShifts node[0] = 'num'; diff --git a/tools/test-js-optimizer-asm-pre-output.js b/tools/test-js-optimizer-asm-pre-output.js index 230ba2736d0d8..da3ebb4f5303e 100644 --- a/tools/test-js-optimizer-asm-pre-output.js +++ b/tools/test-js-optimizer-asm-pre-output.js @@ -19,7 +19,7 @@ function a() { f(g() | 0 & -1); f((g() | 0) >> 2); $56 = _fcntl() | 0 | 1; - FUNCTION_TABLE_ii[55]() | 0; + FUNCTION_TABLE_ii[55 & 127]() | 0; } function b($this, $__n) { $this = $this | 0; From 40deab1f4df0bdd3f45256fdb5f26e3ea59dd3c2 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sat, 16 Aug 2014 14:04:41 -0700 Subject: [PATCH 70/91] de-adjust pointers to run the proper destructor when virtual inheritance is involved; fixes #2682 --- src/library.js | 31 ++++++++++--- .../core/test_exceptions_destroy_virtual.cpp | 43 +++++++++++++++++++ .../core/test_exceptions_destroy_virtual.txt | 3 ++ tests/test_core.py | 9 +++- 4 files changed, 78 insertions(+), 8 deletions(-) create mode 100644 tests/core/test_exceptions_destroy_virtual.cpp create mode 100644 tests/core/test_exceptions_destroy_virtual.txt diff --git a/src/library.js b/src/library.js index 869da5a38f2c9..82059d5e9790e 100644 --- a/src/library.js +++ b/src/library.js @@ -3839,7 +3839,23 @@ LibraryManager.library = { $EXCEPTIONS: { last: 0, caught: [], - infos: {} + infos: {}, + deAdjust: function(adjusted) { + if (!adjusted || EXCEPTIONS.infos[adjusted]) return adjusted; + for (var ptr in EXCEPTIONS.infos) { + var info = EXCEPTIONS.infos[ptr]; + if (info.adjusted === adjusted) { +#if EXCEPTION_DEBUG + Module.printErr('de-adjusted exception ptr ' + adjusted + ' to ' + ptr); +#endif + return ptr; + } + } +#if EXCEPTION_DEBUG + Module.printErr('no de-adjustment for unknown exception ptr ' + adjusted); +#endif + return adjusted; + }, }, // Exceptions @@ -3953,13 +3969,15 @@ LibraryManager.library = { Module.printErr('cxa_end_catch popped ' + [ptr, EXCEPTIONS.last, 'stack', EXCEPTIONS.caught]); #endif if (ptr) { + ptr = EXCEPTIONS.deAdjust(ptr); var info = EXCEPTIONS.infos[ptr]; - if (info) { - if (info.destructor) { - Runtime.dynCall('vi', info.destructor, [ptr]); - } - delete EXCEPTIONS.infos[ptr]; + if (!info) { + abort('cannot find exception info for ' + ptr + ' in ' + JSON.stringify(EXCEPTIONS.infos)); + } + if (info.destructor) { + Runtime.dynCall('vi', info.destructor, [ptr]); } + delete EXCEPTIONS.infos[ptr]; ___cxa_free_exception(ptr); EXCEPTIONS.last = 0; #if EXCEPTION_DEBUG @@ -4034,6 +4052,7 @@ LibraryManager.library = { for (var i = 0; i < typeArray.length; i++) { if (typeArray[i] && Module['___cxa_can_catch'](typeArray[i], throwntype, thrown)) { thrown = {{{ makeGetValue('thrown', '0', '*') }}}; // undo indirection + info.adjusted = thrown; #if EXCEPTION_DEBUG Module.print(" can_catch found " + [thrown, typeArray[i]]); #endif diff --git a/tests/core/test_exceptions_destroy_virtual.cpp b/tests/core/test_exceptions_destroy_virtual.cpp new file mode 100644 index 0000000000000..fcc7b93957584 --- /dev/null +++ b/tests/core/test_exceptions_destroy_virtual.cpp @@ -0,0 +1,43 @@ +#include +#include + +namespace +{ + // An exception that can be derived virtually or not based on macro + // definition. + class test_exception + : virtual public std::runtime_error + { + public: + test_exception() + : std::runtime_error("test_exception") + {} + }; + + // Test class that logs its construction and destruction. + class TestClass + { + public: + TestClass() + { std::cout << "TestClass::Construction" << std::endl; } + + ~TestClass() + { std::cout << "TestClass::Destruction" << std::endl; } + }; +} + +int main() +{ + try { + TestClass testClass; + throw test_exception(); + } + catch (const std::exception& ex) { + std::cout << "Caught exception: " << ex.what() << std::endl; + } + + // Something goes very wrong between handling the exception and resuming + // normal execution when the exception is virtually derived. + return 0; +} + diff --git a/tests/core/test_exceptions_destroy_virtual.txt b/tests/core/test_exceptions_destroy_virtual.txt new file mode 100644 index 0000000000000..2e9bcce66e61b --- /dev/null +++ b/tests/core/test_exceptions_destroy_virtual.txt @@ -0,0 +1,3 @@ +TestClass::Construction +TestClass::Destruction +Caught exception: test_exception diff --git a/tests/test_core.py b/tests/test_core.py index 8164cc343f88b..46b1940acb963 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -1307,8 +1307,6 @@ class MyException ''' Settings.DISABLE_EXCEPTION_CATCHING = 0 - if '-O2' in self.emcc_args: - self.emcc_args.pop() ; self.emcc_args.pop() # disable closure to work around a closure bug self.do_run(src, 'Throw...Construct...Caught...Destruct...Throw...Construct...Copy...Caught...Destruct...Destruct...') def test_exceptions_2(self): @@ -1524,6 +1522,13 @@ def test_exceptions_resume(self): src, output = (test_path + s for s in ('.cpp', '.txt')) self.do_run_from_file(src, output) + def test_exceptions_destroy_virtual(self): + if os.environ.get('EMCC_FAST_COMPILER') == '0': return self.skip('needs fastcomp') + Settings.DISABLE_EXCEPTION_CATCHING = 0 + test_path = path_from_root('tests', 'core', 'test_exceptions_destroy_virtual') + src, output = (test_path + s for s in ('.cpp', '.txt')) + self.do_run_from_file(src, output) + def test_bad_typeid(self): if self.emcc_args is None: return self.skip('requires emcc') if os.environ.get('EMCC_FAST_COMPILER') == '0': return self.skip('needs fastcomp') From e8113b001b97aa807378092cae036f7c1eec83c1 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sat, 16 Aug 2014 17:48:02 -0700 Subject: [PATCH 71/91] use Module.locateFilePackage as a further way to more generally customize the remote package name in file packager; fixes #2680 --- tools/file_packager.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tools/file_packager.py b/tools/file_packager.py index fb3919c11a104..0c26f18a471ac 100644 --- a/tools/file_packager.py +++ b/tools/file_packager.py @@ -485,7 +485,10 @@ def was_seen(name): PACKAGE_PATH = encodeURIComponent(location.pathname.toString().substring(0, location.pathname.toString().lastIndexOf('/')) + '/'); } var PACKAGE_NAME = '%s'; - var REMOTE_PACKAGE_NAME = (Module['filePackagePrefixURL'] || '') + '%s'; + var REMOTE_PACKAGE_BASE = '%s'; + var REMOTE_PACKAGE_NAME = typeof Module['locateFilePackage'] === 'function' ? + Module['locateFilePackage'](REMOTE_PACKAGE_BASE) : + ((Module['filePackagePrefixURL'] || '') + REMOTE_PACKAGE_BASE); var REMOTE_PACKAGE_SIZE = %d; var PACKAGE_UUID = '%s'; ''' % (data_target, remote_package_name, remote_package_size, package_uuid) From f87e1baff5f12916de3ad47d05d052e25d8f7dac Mon Sep 17 00:00:00 2001 From: Bruce Mitchener Date: Sun, 17 Aug 2014 23:51:32 +0700 Subject: [PATCH 72/91] [doc] Building the libc & libcxx doesn't use make/configure. --- site/source/docs/introducing_emscripten/FAQ.rst | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/site/source/docs/introducing_emscripten/FAQ.rst b/site/source/docs/introducing_emscripten/FAQ.rst index e702a7ca610c0..26d045885dd11 100644 --- a/site/source/docs/introducing_emscripten/FAQ.rst +++ b/site/source/docs/introducing_emscripten/FAQ.rst @@ -440,12 +440,8 @@ Using Emscripten actual error. Or, clean the emscripten cache (``~/.emscripten_cache``) and then compile your file with ``EMCC_DEBUG=1`` in the environment. libcxx will then be built in - ``/tmp/emscripten_temp/libcxx``, and you can see ``configure*,make*`` - files that are the output of configure and make, etc. - - One possible cause of this error is the lack of ``make``, which is - necessary to build these libraries. If you are on Windows, you need - cygwin which supplies ``make``. + ``/tmp/emscripten_temp/libcxx``, and you can see the output of + the build process. - **Q.** Running LLVM bitcode generated by emcc through ``lli`` breaks with errors about ``impure_ptr`` stuff..? From da4ac5c80b4945ddffb8f3f88231c4677ed59430 Mon Sep 17 00:00:00 2001 From: Bruce Mitchener Date: Sun, 17 Aug 2014 23:55:11 +0700 Subject: [PATCH 73/91] [doc] Fix a couple of typos. --- site/source/docs/introducing_emscripten/FAQ.rst | 2 +- site/source/docs/introducing_emscripten/community.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/site/source/docs/introducing_emscripten/FAQ.rst b/site/source/docs/introducing_emscripten/FAQ.rst index 26d045885dd11..d5987ac1744db 100644 --- a/site/source/docs/introducing_emscripten/FAQ.rst +++ b/site/source/docs/introducing_emscripten/FAQ.rst @@ -485,7 +485,7 @@ Using Emscripten **A.** The easiest way to find out when loading is complete (which is asynchronous, as it often requires loading files, such as the - .mem file or preloade files), is to just add a ``main()`` function. It + .mem file or preloaded files), is to just add a ``main()`` function. It will be called when it is safe to do so, after startup is complete, so that is a signal that it is safe to call any compiled method. You can make ``main()`` call your JS to notify it, for example if diff --git a/site/source/docs/introducing_emscripten/community.rst b/site/source/docs/introducing_emscripten/community.rst index 1657a3e99a710..f839ce9653a2e 100644 --- a/site/source/docs/introducing_emscripten/community.rst +++ b/site/source/docs/introducing_emscripten/community.rst @@ -39,7 +39,7 @@ Get the latest official Emscripten news on the blogs: `Developer blog (azakai) < In addition, other interesting blogs and demos are regularly shared on Twitter by the development team `(@kripken) `_ and the broader community `(#emscripten) `_. -.. todo :: **HamishW** At some point in future would be nice to actually display RSS feeds from above links here. Perhaps including @kripen in feed. In this case would need a dedicated blogs link as well. +.. todo :: **HamishW** At some point in future would be nice to actually display RSS feeds from above links here. Perhaps including @kripken in feed. In this case would need a dedicated blogs link as well. Contribute From 0457f493f036a9b78dac65bd0f184a8d9bb62f75 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sun, 17 Aug 2014 11:06:08 -0700 Subject: [PATCH 74/91] disable closure in non-fastcomp test_exceptions --- tests/test_core.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_core.py b/tests/test_core.py index 46b1940acb963..8c7d6fbb6a706 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -1229,7 +1229,7 @@ def test_exceptions(self): Settings.EXCEPTION_DEBUG = 1 Settings.DISABLE_EXCEPTION_CATCHING = 0 - if '-O2' in self.emcc_args: + if '-O2' in self.emcc_args and os.environ.get('EMCC_FAST_COMPILER') != '0': self.emcc_args += ['--closure', '1'] # Use closure here for some additional coverage src = ''' From 8d1b6d84b5507d0b68bcfa0733c27d01d95d1c43 Mon Sep 17 00:00:00 2001 From: hamishwillee Date: Mon, 18 Aug 2014 11:27:47 +1000 Subject: [PATCH 75/91] Minor fixes the building from source and toolchain docs. Also filesystem docs. --- .../docs/api_reference/Filesystem-API.rst | 77 ++++++------------- ...g_emscripten_from_source_using_the_sdk.rst | 2 + .../toolchain_what_is_needed.rst | 4 +- .../Talks-and-Publications.rst | 64 +++++++-------- site/source/docs/tools_reference/emcc.rst | 2 +- site/source/docs/tools_reference/emsdk.rst | 5 +- 6 files changed, 61 insertions(+), 93 deletions(-) diff --git a/site/source/docs/api_reference/Filesystem-API.rst b/site/source/docs/api_reference/Filesystem-API.rst index 7de92e64a3294..b3e4ac7d04cc3 100644 --- a/site/source/docs/api_reference/Filesystem-API.rst +++ b/site/source/docs/api_reference/Filesystem-API.rst @@ -4,12 +4,13 @@ Filesystem API (under-construction) ===================================== -File I/O in Emscripten is provided by the `FS `_ library. This same library is used internally for all of Emscripten's libc and libcxx file I/O. +File I/O in Emscripten is provided by the `FS `_ library. This library is *inspired* by the Linux/POSIX file system API. It is used internally for all of Emscripten's **libc** and **libcxx** file I/O. -Emscripten deals predominantly with synchronous file I/O, so the majority of the FS member functions offer a synchronous interface, with errors being reported by raising exceptions of type ``FS.ErrnorError``. +Emscripten deals predominantly with synchronous file I/O, so the majority of the ``FS`` member functions offer a synchronous interface, with errors being reported by raising exceptions of type `FS.ErrnoError `_ -The file data in Emscripten is partitioned by mounted filesystems, of which several are provided to work with. By default, an instance of `MEMFS` is mounted to ``/`` and instances of `NODEFS` and `IDBFS` can be mounted to other directories if your application needs to `persist data `__. +The file data in Emscripten is partitioned by mounted filesystems, of which several are provided to work with. By default, an instance of :ref:`MEMFS ` is mounted to ``/`` and instances of :ref:`NODEFS ` and :ref:`IDBFS ` can be mounted to other directories if your application needs to :ref:`persist data `. +.. _filesystem-api-persist-data: Persistence =========== @@ -18,22 +19,29 @@ Applications being compiled with Emscripten expect synchronous I/O, therefore, E Because of this, Emscripten offers multiple filesystems that can be mounted with :js:func:`FS.mount` to help deal with persistence depending on the execution context. +.. _filesystem-api-memfs: + MEMFS =========== This is the default filesystem mounted at ``/`` when the runtime is initialized. All files exist strictly in-memory, and any data written to it is lost when the page is reloaded. +.. _filesystem-api-nodefs: + NODEFS =========== -NODEFS lets a program in node directly access files on the local filesystem, as if the problem were running normally. See `this test `__ for an example. +NODEFS lets a program in node directly access files on the local filesystem, as if the problem were running normally. See `this test `_ for an example. Mount options ------------- - root ``string`` Path to persist the data to on the local filesystem. -This filesystem is only for use when running inside of node. It uses node's synchronous fs API to immediately persist any data written to emscripten's filesystem to your local disk. +This filesystem is only for use when running inside of *node*. It uses node's synchronous FS API to immediately persist any data written to the Emscripten filesystem to your local disk. + + +.. _filesystem-api-idbfs: IDBFS ===== @@ -52,8 +60,7 @@ Emscripten supports registering arbitrary device drivers composed of a device id Converts a major and minor number into a single unique integer. :param ma: **HamishW** - :param mi: **HamishW** - :throws **HamishW**: + :param mi: **HamishW** @@ -63,7 +70,7 @@ Emscripten supports registering arbitrary device drivers composed of a device id :param dev: ``MEMFS`` ``NODEFS`` ``IDBFS`` :param object ops: **HamishW** - :throws **HamishW**: + Setting up standard I/O devices @@ -95,9 +102,14 @@ Filesystem :param type: ``MEMFS`` ``NODEFS`` ``IDBFS`` :param object opts: **HamishW** :param string mountpoint: **HamishW** - :throws **HamishW**: +.. js:function:: FS.unmount(mountpoint) + + Unmounts the specified ``mountpoint``. + + :param string mountpoint: **HamishW** + .. js:function:: FS.syncfs(populate, callback) @@ -128,9 +140,8 @@ Filesystem .. note:: Currently, only the `IDBFS`_ filesystem implements the interfaces needed by this. All other filesystems are completely synchronous and don't require synchronization. - :param bool populate: ``true`` to initialize Emscripten's filesystem data with the data from the filesystem's persistent source, and ``false`` to save emscripten's filesystem data to the filesystem's persistent source. + :param bool populate: ``true`` to initialize Emscripten's filesystem data with the data from the filesystem's persistent source, and ``false`` to save Emscripten`s filesystem data to the filesystem's persistent source. :param callback: **HamishW** - :throws **HamishW**: .. js:function:: FS.mkdir(path, mode) @@ -143,7 +154,6 @@ Filesystem :param string path: The path name for the new directory node. :param int mode: **HamishW** Link to mode values. The default is 0777. - :throws **HamishW**: .. js:function:: FS.mkdev(path, mode, dev) @@ -159,7 +169,6 @@ Filesystem :param string path: The path name for the new device node. :param int mode: **HamishW** Link to mode values. The default is 0777. :param int dev: **HamishW**. - :throws **HamishW**: .. js:function:: FS.symlink(oldpath, newpath) @@ -173,7 +182,6 @@ Filesystem :param string oldpath: The path name of the file to link to. :param string newpath: The path to the new symlink node to ``oldpath``. - :throws **HamishW**: @@ -188,7 +196,6 @@ Filesystem :param string oldpath: The old path name. :param string newpath: The new path name - :throws **HamishW**: .. js:function:: FS.rmdir(path) @@ -203,13 +210,11 @@ Filesystem FS.rmdir('data'); :param string path: Path of the directory to be removed. - :throws **HamishW**: .. js:function:: FS.unlink(path) - Unlinks the node at ``path`` (this was previously called - ``deleteFile``). + Unlinks the node at ``path``. .. COMMENT :: **HamishW** What does unlinking actually mean? @@ -221,7 +226,6 @@ Filesystem FS.unlink('/foobar.txt'); :param string path: Path of the target node. - :throws **HamishW**: @@ -251,7 +255,6 @@ Filesystem :param string path: Path of the target file. :returns: The string value stored in the symbolic link at ``path``. - :throws **HamishW**: @@ -293,7 +296,6 @@ Filesystem } :param string path: Path of the target file. - :throws **HamishW**: .. js:function:: FS.lstat(path) @@ -301,7 +303,6 @@ Filesystem Identical to :js:func:`FS.stat`, However, if ``path`` is a symbolic link then the returned stats will be for the link itself, not the file that it links to. :param string path: Path of the target file. - :throws **HamishW**: .. js:function:: FS.chmod(path, mode) @@ -315,7 +316,6 @@ Filesystem :param string path: Path of the target file. :param int mode: **HamishW**. - :throws **HamishW**: @@ -325,7 +325,6 @@ Filesystem :param string path: Path of the target file. :param int mode: **HamishW**. - :throws **HamishW**: .. js:function:: FS.fchmod(fd, mode) @@ -334,8 +333,6 @@ Filesystem :param int fd: Descriptor of target file. :param int mode: **HamishW**. - :throws **HamishW**: - @@ -346,8 +343,6 @@ Filesystem :param string path: Path of the target file. :param int uid: **HamishW**. :param int gid: **HamishW**. - :throws **HamishW**: - @@ -358,7 +353,6 @@ Filesystem :param string path: Path of the target file. :param int uid: **HamishW**. :param int gid: **HamishW**. - :throws **HamishW**: @@ -369,7 +363,6 @@ Filesystem :param int fd: Descriptor of target file. :param int uid: **HamishW**. :param int gid: **HamishW**. - :throws **HamishW**: @@ -400,9 +393,6 @@ Filesystem :param string path: Path of the file to be truncated. :param int len: The truncation length for the file. - :throws ERRNO_CODES.EINVAL: - :throws ERRNO_CODES.EPERM: - :throws ERRNO_CODES.EISDIR: @@ -412,10 +402,6 @@ Filesystem :param int fd: Descriptor of file to be truncated. :param int len: The truncation length for the file. - :throws ERRNO_CODES.EBADF: - :throws ERRNO_CODES.EINVAL: - :throws ERRNO_CODES.EPERM: - :throws ERRNO_CODES.EISDIR: .. js:function:: FS.utime(path, atime, mtime) @@ -470,7 +456,7 @@ Filesystem :param object stream: The stream for which the offset is to be repositioned. :param int offset: The offset (in bytes) relative to ``whence``. - :param int whence: SEEK\_SET (0), SEEK\_CUR(1) or SEEK\_END(2); + :param int whence: SEEK_SET (0), SEEK_CUR(1) or SEEK_END(2); .. COMMENT :: **HamishW** I don't understand the whence parameter. Need to follow up and check test code. @@ -493,11 +479,6 @@ Filesystem :param int offset: The offset within ``buffer`` to store the data. :param int length: The length of data to write in ``buffer``. :param int position: The offset within the stream to read. By default this is the stream's current offset. - :throws ERRNO_CODES.EINVAL: Reading from an invalid position or length - :throws ERRNO_CODES.EBADF: - :throws ERRNO_CODES.ESPIPE: - :throws ERRNO_CODES.EISDIR: - :throws ERRNO_CODES.EINVAL: @@ -519,13 +500,7 @@ Filesystem :param int offset: The offset within ``buffer`` to write. :param int length: The length of data to write. :param int position: The offset within the stream to write. By default this is the stream's current offset. - :throws ERRNO_CODES.EINVAL: Reading from an invalid position or length - :throws ERRNO_CODES.EBADF: - :throws ERRNO_CODES.ESPIPE: - :throws ERRNO_CODES.EISDIR: - :throws ERRNO_CODES.EINVAL: - - .. COMMENT:: Need to check if Throws should be recorded, and if so, what should be said. **HamishW** + @@ -588,8 +563,6 @@ Filesystem :param bool canRead: Whether the file should have read permissions set from the program's point of view. :param bool canWrite: Whether the file should have write permissions set from the program's point of view. :returns: A reference to the new file. - :throws ERRNO_CODES.EIO: - :throws: if there is an invalid range or URL, or if synchronous binary XHRs have been disabled. diff --git a/site/source/docs/building_from_source/building_emscripten_from_source_using_the_sdk.rst b/site/source/docs/building_from_source/building_emscripten_from_source_using_the_sdk.rst index 4245d29f2a993..0b3c4dcbde390 100644 --- a/site/source/docs/building_from_source/building_emscripten_from_source_using_the_sdk.rst +++ b/site/source/docs/building_from_source/building_emscripten_from_source_using_the_sdk.rst @@ -22,6 +22,8 @@ First :ref:`download and install the SDK `. The SDK au Then :ref:`download and install the compiler toolchain ` for your platform. +.. note:: **Windows**: You will need `Visual Studio 2010 `_ (and `Microsoft Windows SDK for Windows 7 and .NET Framework 4 `_). + .. _building-emscripten-from-the-main-repositories-using-the-sdk: diff --git a/site/source/docs/building_from_source/toolchain_what_is_needed.rst b/site/source/docs/building_from_source/toolchain_what_is_needed.rst index 1303a24d4f786..1c6fdd3db5f18 100644 --- a/site/source/docs/building_from_source/toolchain_what_is_needed.rst +++ b/site/source/docs/building_from_source/toolchain_what_is_needed.rst @@ -38,10 +38,12 @@ A complete Emscripten environment requires the following tools. First test to se Compiler toolchain ------------------ -When building Emscripten from source code, whether "manually" or using the SDK, you will also need a *compiler toolchain* (including *gcc*, *g++*, *cmake*, etc.): +When building Emscripten from source code, whether "manually" or using the SDK, you will need a *compiler toolchain* (including *gcc*, *g++*, *cmake*, etc.): - Windows: Install `gcc 4.6 `_ and `cmake `_ (cmake-3.0.1-win32-x86.exe) + .. note:: To use an IDE, or if you want to :ref:`build from source using the SDK ` on **Windows**, you will also need `Visual Studio 2010 `_ (and possibly `Microsoft Windows SDK for Windows 7 and .NET Framework 4 `_). + - Linux: Install *gcc* and *cmake*: :: diff --git a/site/source/docs/introducing_emscripten/Talks-and-Publications.rst b/site/source/docs/introducing_emscripten/Talks-and-Publications.rst index 43a982268112c..72659ebbe43fe 100644 --- a/site/source/docs/introducing_emscripten/Talks-and-Publications.rst +++ b/site/source/docs/introducing_emscripten/Talks-and-Publications.rst @@ -1,51 +1,39 @@ .. _Talks-and-Publications: -==================================== -Talks and Publications (wiki-import) -==================================== -.. note:: This article was migrated from the wiki (Fri, 25 Jul 2014 04:21) and is now the "master copy" (the version in the wiki will be deleted). It may not be a perfect rendering of the original but we hope to fix that soon! +=========================================== +Talks and Publications (ready-for-review) +=========================================== -Talks -===== +Presentations +============= + +- Slides from GDC 2014: `Getting started with asm.js and Emscripten `_ (`kripken `_, `lwagner `_) + +- Slides from Strange Loop 2013: `Native speed on the web, JavaScript and asm.js `_ (`kripken `_) + +- Slides from GDC Europe 2013: `C++ on the Web `_ (`floh `_) + +- Slides from QCon 2013: `Connecting languages together `_ (`kripken `_) + +- Slides from Quo Vadis 2013: `C++ on the Web: Run your big 3D game in the browser! `_ (`floh `_) + +- Slides from GDC 2013: + + - `Compiling C/C++ to JavaScript `_ (`kripken `_) + - `Multiplatform C++ on the Web with Emscripten `_ (`chadaustin `_) + +- Slides from mloc.js: `Big Web App? Compile it! `_ (`kripken `_) + +- JSConf.eu 2011: `Emscripten `_ (`kripken `_) -- `Slides from GDC - 2014 `__ - - Getting started with asm.js and Emscripten (kripken, lwagner) -- `Slides from Strange Loop - 2013 `__ - - Native speed on the web, JavaScript and asm.js (kripken) -- `Slides from GDC Europe - 2013 `__ - - C++ on the Web (floh) -- `Slides from QCon - 2013 `__ - - Connecting languages together (kripken) -- `Slides from Quo Vadis - 2013 `__ - (floh) -- `Slides from GDC 2013 - (b) `__ - (chadaustin) -- `Slides from GDC 2013 - (a) `__ - (kripken) -- `Slides from - mloc.js `__ - (kripken) -- `Emscripten, JSConf.eu - 2011 `__ (kripken) Papers ====== -- `Technical - Paper `__ - - A detailed writeup about how Emscripten works (the memory model, - Relooper algorithm, etc. - somewhat outdated by now) +- `Emscripten: An LLVM-to-JavaScript Compiler `_ (`kripken `_) — A detailed explanation of how Emscripten works, covering the memory model, relooper algorithm, etc. **This is now somewhat outdated**. Books ===== -- `Book `__ - with a chapter on Emscripten +- `HTML5 Game Development Insights `_ — Book with a chapter on Emscripten diff --git a/site/source/docs/tools_reference/emcc.rst b/site/source/docs/tools_reference/emcc.rst index 5ad94ed3ed0bc..3fb6f484cd81a 100644 --- a/site/source/docs/tools_reference/emcc.rst +++ b/site/source/docs/tools_reference/emcc.rst @@ -28,7 +28,7 @@ Supported targets include: llvm bitcode, javascript, NOT elf (autoconf likes to Arguments --------- -Most normal gcc/g++ options will work, for example: +Most `normal gcc/g++ options `_ will work, for example: --help Display this information --version Display compiler version information diff --git a/site/source/docs/tools_reference/emsdk.rst b/site/source/docs/tools_reference/emsdk.rst index b9991a28ed93b..a2ed371b38d96 100644 --- a/site/source/docs/tools_reference/emsdk.rst +++ b/site/source/docs/tools_reference/emsdk.rst @@ -71,7 +71,10 @@ The Emscripten toolchain includes a number of different tools, including *Clang* The current set of available :term:`tools ` and :term:`SDKs ` are listed using ``./emsdk list``. These can be installed individually (``./emsdk install node-0.10.17-64bit``) or as a group (``./emsdk install node-0.10.17-64bit java-7.45-64bit``). -The :term:`SDK` targets are a convenience mechanism for specifying the full set of tools used by a particular Emscripten release. For example, ``./emsdk install sdk-incoming-64bit`` is equivalent to typing ``./emsdk install git-1.8.3 clang-incoming-64bit node-0.10.17-64bit python-2.7.5.3-64bit java-7.45-64bit emscripten-incoming``. +The :term:`SDK` targets are a convenience mechanism for specifying the full set of tools used by a particular Emscripten release. For example, the two lines below are equivalent: :: + + ./emsdk install sdk-incoming-64bit + ./emsdk install git-1.8.3 clang-incoming-64bit node-0.10.17-64bit python-2.7.5.3-64bit java-7.45-64bit emscripten-incoming A particular installed SDK (or tool) can then be set as :term:`active `, meaning that it will be used when Emscripten is run. The active "compiler configuration" is stored in a user-specific file (*~/.emscripten*), which is discussed in the next section. From b464d9f282d377c28374fa5ac5aadac6c219238c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jukka=20Jyl=C3=A4nki?= Date: Mon, 18 Aug 2014 17:09:46 +0300 Subject: [PATCH 76/91] Skip over updating already deleted OpenAL sources. --- src/library_openal.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/library_openal.js b/src/library_openal.js index e74d860f120e3..ff52b42d5720b 100644 --- a/src/library_openal.js +++ b/src/library_openal.js @@ -16,7 +16,8 @@ var LibraryOpenAL = { updateSources: function updateSources(context) { for (var i = 0; i < context.src.length; i++) { - AL.updateSource(context.src[i]); + var src = context.src[i]; + if (src) AL.updateSource(src); } }, From 882b3c1d7f2bf4ad082aac43b9f8d146b3f7c045 Mon Sep 17 00:00:00 2001 From: Boris Tsarev Date: Fri, 4 Jul 2014 15:29:11 +0400 Subject: [PATCH 77/91] Fixed OpenAL sources deeleting --- src/library_openal.js | 61 ++++++++++++++++++++++++++----------------- 1 file changed, 37 insertions(+), 24 deletions(-) diff --git a/src/library_openal.js b/src/library_openal.js index ff52b42d5720b..4251174287af8 100644 --- a/src/library_openal.js +++ b/src/library_openal.js @@ -14,16 +14,28 @@ var LibraryOpenAL = { QUEUE_INTERVAL: 25, QUEUE_LOOKAHEAD: 100, + newSrcId: 0, + + srcIdBySrc: function srcIdBySrc(src) { + var idx = 0; + for (var srcId in AL.currentContext.src) { + if (AL.currentContext.src[srcId] == src) { + idx = srcId; + break; + } + } + return idx; + }, + updateSources: function updateSources(context) { - for (var i = 0; i < context.src.length; i++) { - var src = context.src[i]; - if (src) AL.updateSource(src); + for (var srcId in context.src) { + AL.updateSource(context.src[srcId]); } }, updateSource: function updateSource(src) { #if OPENAL_DEBUG - var idx = AL.currentContext.src.indexOf(src); + var idx = AL.srcIdBySrc(src); #endif if (src.state !== 0x1012 /* AL_PLAYING */) { return; @@ -86,7 +98,7 @@ var LibraryOpenAL = { setSourceState: function setSourceState(src, state) { #if OPENAL_DEBUG - var idx = AL.currentContext.src.indexOf(src); + var idx = AL.srcIdBySrc(src); #endif if (state === 0x1012 /* AL_PLAYING */) { if (src.state !== 0x1013 /* AL_PAUSED */) { @@ -227,7 +239,7 @@ var LibraryOpenAL = { var context = { ctx: ctx, err: 0, - src: [], + src: {}, buf: [], interval: setInterval(function() { AL.updateSources(context); }, AL.QUEUE_INTERVAL), gain: gain @@ -306,7 +318,7 @@ var LibraryOpenAL = { return; } for (var i = 0; i < count; ++i) { - var sourceIdx = {{{ makeGetValue('sources', 'i*4', 'i32') }}} - 1; + var sourceIdx = {{{ makeGetValue('sources', 'i*4', 'i32') }}}; delete AL.currentContext.src[sourceIdx]; } }, @@ -321,7 +333,7 @@ var LibraryOpenAL = { for (var i = 0; i < count; ++i) { var gain = AL.currentContext.ctx.createGain(); gain.connect(AL.currentContext.gain); - AL.currentContext.src.push({ + AL.currentContext.src[AL.newSrcId] = { state: 0x1011 /* AL_INITIAL */, queue: [], loop: false, @@ -392,8 +404,9 @@ var LibraryOpenAL = { panner: null, buffersPlayed: 0, bufferPosition: 0 - }); - {{{ makeSetValue('sources', 'i*4', 'AL.currentContext.src.length', 'i32') }}}; + }; + {{{ makeSetValue('sources', 'i*4', 'AL.newSrcId', 'i32') }}}; + AL.newSrcId++; } }, @@ -402,7 +415,7 @@ var LibraryOpenAL = { return false; } - if (!AL.currentContext.src[sourceId - 1]) { + if (!AL.currentContext.src[sourceId]) { return false; } else { return true; @@ -416,7 +429,7 @@ var LibraryOpenAL = { #endif return; } - var src = AL.currentContext.src[source - 1]; + var src = AL.currentContext.src[source]; if (!src) { #if OPENAL_DEBUG console.error("alSourcei called with an invalid source"); @@ -490,7 +503,7 @@ var LibraryOpenAL = { #endif return; } - var src = AL.currentContext.src[source - 1]; + var src = AL.currentContext.src[source]; if (!src) { #if OPENAL_DEBUG console.error("alSourcef called with an invalid source"); @@ -550,7 +563,7 @@ var LibraryOpenAL = { #endif return; } - var src = AL.currentContext.src[source - 1]; + var src = AL.currentContext.src[source]; if (!src) { #if OPENAL_DEBUG console.error("alSource3f called with an invalid source"); @@ -592,7 +605,7 @@ var LibraryOpenAL = { #endif return; } - var src = AL.currentContext.src[source - 1]; + var src = AL.currentContext.src[source]; if (!src) { #if OPENAL_DEBUG console.error("alSourceQueueBuffers called with an invalid source"); @@ -627,7 +640,7 @@ var LibraryOpenAL = { #endif return; } - var src = AL.currentContext.src[source - 1]; + var src = AL.currentContext.src[source]; if (!src) { #if OPENAL_DEBUG console.error("alSourceUnqueueBuffers called with an invalid source"); @@ -681,8 +694,8 @@ var LibraryOpenAL = { // Make sure the buffer is no longer in use. var buffer = AL.currentContext.buf[bufferIdx]; - for (var j = 0; j < AL.currentContext.src.length; ++j) { - var src = AL.currentContext.src[j]; + for (var srcId in AL.currentContext.src) { + var src = AL.currentContext.src[srcId]; if (!src) { continue; } @@ -836,7 +849,7 @@ var LibraryOpenAL = { #endif return; } - var src = AL.currentContext.src[source - 1]; + var src = AL.currentContext.src[source]; if (!src) { #if OPENAL_DEBUG console.error("alSourcePlay called with an invalid source"); @@ -855,7 +868,7 @@ var LibraryOpenAL = { #endif return; } - var src = AL.currentContext.src[source - 1]; + var src = AL.currentContext.src[source]; if (!src) { #if OPENAL_DEBUG console.error("alSourceStop called with an invalid source"); @@ -874,7 +887,7 @@ var LibraryOpenAL = { #endif return; } - var src = AL.currentContext.src[source - 1]; + var src = AL.currentContext.src[source]; if (!src) { #if OPENAL_DEBUG console.error("alSourcePause called with an invalid source"); @@ -892,7 +905,7 @@ var LibraryOpenAL = { #endif return; } - var src = AL.currentContext.src[source - 1]; + var src = AL.currentContext.src[source]; if (!src) { #if OPENAL_DEBUG console.error("alGetSourcei called with an invalid source"); @@ -961,7 +974,7 @@ var LibraryOpenAL = { #endif return; } - var src = AL.currentContext.src[source - 1]; + var src = AL.currentContext.src[source]; if (!src) { #if OPENAL_DEBUG console.error("alGetSourcef called with an invalid source"); @@ -1016,7 +1029,7 @@ var LibraryOpenAL = { #endif return; } - var src = AL.currentContext.src[source - 1]; + var src = AL.currentContext.src[source]; if (!src) { #if OPENAL_DEBUG console.error("alGetSourcefv called with an invalid source"); From 81a3693dfc220c73483b341b8e0871d1bc3d0348 Mon Sep 17 00:00:00 2001 From: Boris Tsarev Date: Wed, 9 Jul 2014 00:09:27 +0400 Subject: [PATCH 78/91] Wrapped 'srcIdBySrc' method in OpenAL to OPENAL_DEBUG --- src/library_openal.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/library_openal.js b/src/library_openal.js index 4251174287af8..4f9161cde595e 100644 --- a/src/library_openal.js +++ b/src/library_openal.js @@ -16,6 +16,8 @@ var LibraryOpenAL = { newSrcId: 0, +#if OPENAL_DEBUG + //This function is slow and used only for debugging purposes srcIdBySrc: function srcIdBySrc(src) { var idx = 0; for (var srcId in AL.currentContext.src) { @@ -26,6 +28,7 @@ var LibraryOpenAL = { } return idx; }, +#endif updateSources: function updateSources(context) { for (var srcId in context.src) { From f1f5001a0b7341d572df9a9ddbefebddc204b084 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 18 Aug 2014 11:22:09 -0700 Subject: [PATCH 79/91] make the sphinx emcc docs the single source of information; emcc --help points to the local copy --- emcc | 441 +----- .../build/html/docs/tools_reference/emcc.html | 1301 +++++++++++++++++ 2 files changed, 1304 insertions(+), 438 deletions(-) create mode 100644 site/build/html/docs/tools_reference/emcc.html diff --git a/emcc b/emcc index 333414d7e0e06..85fe16c9df248 100755 --- a/emcc +++ b/emcc @@ -130,450 +130,15 @@ if len(sys.argv) == 1 or '--help' in sys.argv: print '''%s [options] file... -Most normal gcc/g++ options will work, for example: +Most normal gcc/g++/clang/clang++ options will work, for example: --help Display this information --version Display compiler version information -Options that are modified or new in %s include: - - -O0 No optimizations (default). This is the recommended - setting for starting to port a project, as it - includes various assertions. - - -O1 Simple optimizations, including asm.js, LLVM -O1 - optimizations, relooping, and no runtime assertions - or C++ exception catching (to re-enable - C++ exception catching, use - -s DISABLE_EXCEPTION_CATCHING=0 ), and enables - - -s ALIASING_FUNCTION_POINTERS=1 - - This is the recommended setting when you want a - reasonably optimized build that is generated as - quickly as possible (it builds much faster than -O2). - - (Note: for details on the affects of different - opt levels, see apply_opt_level() in - tools/shared.py and also src/settings.js.) - - -O2 As -O1, plus various js-level optimizations, LLVM - -O3 optimizations, and memory init file generation - (--memory-init-file 1). This is a good setting - for an optimized build: runs much faster than - -O1, and compiles much faster than -O3. - - -Os Like -O2 with extra optimizations for size. - - -Oz Like -Os but reduces code size further. - - -O3 Like -O2 plus additional JS optimizations that can - take a significant amount of compilation time and/or - are relatively new. Note that differs from -O2 only - during the bitcode to JS (final link + JS generation) - stage, as it is JS-specific, so you can run -Os - on your source files for example, and -O3 during - JS generation if you want. - - For tips on optimizing your code, see - https://github.com/kripken/emscripten/wiki/Optimizing-Code - - -s OPTION=VALUE JavaScript code generation option passed - into the emscripten compiler. For the - available options, see src/settings.js - Note that for options that are lists, you - need quotation marks in most shells, for - example - - -s RUNTIME_LINKED_LIBS="['liblib.so']" - - or - - -s "RUNTIME_LINKED_LIBS=['liblib.so']" - - (without the external "s in either of those, - you would get an error) - - You can also specify a file from which the - value would be read, for example, - - -s DEAD_FUNCTIONS=@/path/to/file - - The contents of /path/to/file will be read, - JSON.parsed and set into DEAD_FUNCTIONS (so - the file could contain - - ["_func1", "func2"] - - ). Note that the path must be absolute, not - relative. - - -g Use debug info. When compiling to bitcode, - this is the same as in clang and gcc, it - adds debug info to the object files. When - compiling from source to JS or bitcode to JS, - it is equivalent to -g3 (keep code as debuggable - as possible, except for discarding LLVM - debug info, so no C/C++ line numbers; use - -g4 to get line number debugging info in JS). - - -g When compiling from bitcode to JS, we can - keep the code debuggable to different - degrees. Each of these levels builds on the - previous: - - -g0 Make no effort to keep code debuggable. - Will discard LLVM debug info. (default - in -O1+) - -g1 Preserve (do not minify) whitespace - -g2 Preserve function names - -g3 Preserve variable names - -g4 Preserve LLVM debug info (if -g was - used when compiling the C/C++ sources), - show line number debug comments, and - generate source maps. This is the highest - level of debuggability. Note that this - may make -O1 and above significantly - slower because JS optimization will be - limited to 1 core. (default in -O0) - - -profiling Use reasonable defaults when emitting JS to - make the build useful for profiling. This - sets -g2 (preserve function names) and may - also enable optimizations that affect - performance and otherwise might not be - performed in -g2. - - --emit-symbol-map Save a map file between the minified - global names and the original function names. - This allows you to reconstruct meaningful - stack traces, for example. (This is only - relevant when minifying global names, which - happens in -O2 and above, and when no -g - option to prevent minification was specified.) - - --typed-arrays 0: No typed arrays - 1: Parallel typed arrays - 2: Shared (C-like) typed arrays (default) - - --js-opts 0: Prevent JS optimizer from running - 1: Use JS optimizer (default) - - --llvm-opts 0: No LLVM optimizations (default in -O0) - 1: -O1 LLVM optimizations (default in -O1) - 2: -O2 LLVM optimizations - 3: -O3 LLVM optimizations (default in -O2+) - - You can also specify arbitrary LLVM options, e.g. - - --llvm-opts "['-O3', '-somethingelse']" - - --llvm-lto 0: No LLVM LTO (default) - 1: LLVM LTO is performed - 2: We combine all the bitcode and run LLVM opt -O3 - on that (which optimizes across modules, but is - not the same as normal LTO), but do not do normal - LTO - 3: We do both 2 and then 1 - Note: If LLVM optimizations are not run - (see --llvm-opts), setting this has no - effect. - - Note that LLVM LTO is not perfectly stable yet, - and can can cause code to behave incorrectly. - - --closure 0: No closure compiler (default in -O2 and below) - 1: Run closure compiler. This greatly reduces - code size and may in some cases increase - runtime speed (although the opposite can also - occur). Note that it takes time to run, and - may require some changes to the code. - - In asm.js mode, closure will only be used on the - 'shell' code around the compiled code (the - compiled code will be processed by the custom - asm.js minifier). - - Note: If closure compiler hits an out-of-memory, - try adjusting JAVA_HEAP_SIZE in the environment - (for example, to 4096m for 4GB). - - Note: Closure is only run if js opts are being - done (-O2 or above, or --js-opts 1). - - --pre-js A file whose contents are added before the - generated code. This is done *before* - optimization, so it will be minified - properly if closure compiler is run. - - --post-js A file whose contents are added after the - generated code This is done *before* - optimization, so it will be minified - properly if closure compiler is run. - - Note that the post js will typically run after - main() completes (unless there is something - async). In that case, main() will exit and - the post js will not be reached (just as if - you call exit() in C code). If you want to - prevent that, you can build with - -s NO_EXIT_RUNTIME=1 - - --embed-file A file to embed inside the generated - JavaScript. The compiled code will be able - to access the file in the current directory - with the same name as given here. So if - you do --embed-file dir/file.dat, then - (1) dir/file.dat must exist relative to - where you run emcc, and (2) your compiled - code will be able to find the file by - reading that same path, dir/file.dat. - If a directory is passed here, its entire - contents will be embedded. - - Note: Embedding files is much less - efficient than preloading them. You - should only use it for small amounts - of small files. Instead, use - --preload-file which emits efficient - binary data. - - --preload-file A file to preload before running the - compiled code asynchronously. Otherwise - similar to --embed-file, except that this - option is only relevant when generating - HTML (it uses asynchronous binary XHRs), - or JS that will be used in a web page. - If a directory is passed here, its entire - contents will be preloaded. - Preloaded files are stored in filename.data, - where filename.html is the main file you - are compiling to. To run your code, you - will need both the .html and the .data. - - emcc runs tools/file_packager.py to do the - actual packaging of embedded and preloaded - files. You can run the file packager yourself - if you want, see docs inside that file. You - should then put the output of the file packager - in an emcc --pre-js, so that it executes before - your main compiled code (or run it before in - some other way). - - For more docs on the options --preload-file - accepts, see https://github.com/kripken/emscripten/wiki/Filesystem-Guide - - --exclude-file Files and directories to be excluded from - --embed-file and --preload-file - wildcard is supported - - --shell-file The path name to a skeleton HTML file used - when generating HTML output. The shell file - used needs to have this token inside it: - {{{ SCRIPT }}} - (see src/shell.html and - src/shell_minimal.html for examples) - Note that this argument is ignored if a - target other than HTML is specified using - the -o option. - - --compression **THIS OPTION IS DEPRECATED** - - Compress both the compiled code and embedded/ - preloaded files. should be a triple, - - ,, - - where native_encoder is a native executable - that compresses stdin to stdout (the simplest - possible interface), js_decoder is a - JavaScript file that implements a decoder, - and js_name is the name of the function to - call in the decoder file (which should - receive an array/typed array and return - an array/typed array. - Compression only works when generating HTML. - When compression is on, all filed specified - to be preloaded are compressed in one big - archive, which is given the same name as the - output HTML but with suffix .data.compress - - --minify 0 Identical to -g1 - - --js-transform will be called on the generated code - before it is optimized. This lets you modify - the JavaScript, for example adding some code - or removing some code, in a way that those - modifications will be optimized together with - the generated code properly. will be - called with the filename of the generated - code as a parameter; to modify the code, you - can read the original data and then append to - it or overwrite it with the modified data. - is interpreted as a space-separated - list of arguments, for example, of - "python processor.py" will cause a python - script to be run. - - --split Splits the resulting javascript file into pieces - to ease debugging. This option only works if - Javascript is generated (target -o .js). - Files with function declarations must be loaded - before main file upon execution. - - Without "-g" option: - Creates files with function declarations up - to the given size with the suffix - "_functions.partxxx.js" and a main file with - the suffix ".js". - - With "-g" option: - Recreates the directory structure of the C - source files and stores function declarations - in their respective C files with the suffix - ".js". If such a file exceeds the given size, - files with the suffix ".partxxx.js" are created. - The main file resides in the base directory and - has the suffix ".js". - - Note: this option is deprecated (modern JS debuggers - should work ok even on large files) - - --bind Compiles the source code using the "embind" - bindings approach, which connects C/C++ and JS. - - --ignore-dynamic-linking Normally emcc will treat dynamic linking like - static linking, by linking in the code from - the dynamic library. This fails if the same - dynamic library is linked more than once. - With this option, dynamic linking is ignored, - which allows the build system to proceed without - errors. However, you will need to manually - link to the shared libraries later on yourself. - - --js-library A JavaScript library to use in addition to - those in Emscripten's src/library_* - - -v Turns on verbose output. This will pass - -v to Clang. It will also run emscripten's internal - sanity checks, checking that things like the LLVM - directory path looks correct, etc. This works with or - without other arguments, so it can be useful to run - - emcc -v - - if you see odd errors, as it can help diagnose - things. - - To enable additional emscripten logging, you can - set EMCC_DEBUG=1 in the environment, which will - also save temporary files in the canonical location - (usually /tmp/emscripten_temp). - - --clear-cache Manually clears the cache of compiled - emscripten system libraries (libc++, - libc++abi, libc). This is normally - handled automatically, but if you update - llvm in-place (instead of having a different - directory for a new version), the caching - mechanism can get confused. Clearing the - cache can fix weird problems related to - cache incompatibilities, like clang failing - to link with library files. This also clears - other cached data like the jcache and - the bootstrapped relooper. After the cache - is cleared, this process will exit. - - --save-bc PATH When compiling to JavaScript or HTML, this - option will save a copy of the bitcode to - the specified path. The bitcode will include - all files being linked, including standard - libraries, and after any link-time optimizations - (if any). - - --memory-init-file 0: Do not emit a separate memory initialization - file, keep the static initialization inside - the generated JavaScript as text (default - in -O0 and -O1) - 1: Emit a separate memory initialization file - in binary format. This is more efficient than - storing it as text inside JavaScript, but does - mean you have another file to publish. The - binary file will also be loaded asynchronously, - which means main() will not be called until - the file is downloaded and applied; you cannot - call any C functions until it arrives. (Call - yourself from main() to know when all async - stuff has happened and it is safe to call - library functions, as main() will only be - called at that time. You can also call - addOnPreMain from a preRun.) (default in -O2+) - - Note the .mem file should be in the same - directory as the .js file when the code is run. - If you want it to be in a different directory, - you can define Module.memoryInitializerPrefixURL - which will be used as a prefix. - - -Wno-warn-absolute-paths If not specified, the compiler will warn about any - uses of absolute paths in -I and -L command line - directives. Pass this flag on the command line - to hide these warnings and acknowledge that the - explicit use of absolute paths is intentional. - - --proxy-to-worker Runs the main application code in a worker, proxying - events to it and output from it. - If emitting htmlL, this emits an html and a js file, - with the js to be run in a worker. If emitting - js, the target filename contains the part to be run - on the main thread, while a second js file with - suffix ".worker.js" will contain the worker portion. - - --emrun Enables the generated output to be aware of the - emrun command line tool. This allows stdout, stderr - and exit(returncode) capture when running the - generated application through emrun. - - --em-config Specifies the location of the .emscripten configuration - file for the current compiler run. If not specified, - the environment variable EM_CONFIG is read for this - file, and if that is not set, the default location - ~/.emscripten is assumed. - - --default-obj-ext .ext Specifies the file suffix to generate if the location - of a directory name is passed to -o directive, e.g. - emcc -c a.c -o dir/ - will by default generate an output name 'dir/a.o', - but this cmdline param can be passed to generate a - file with a custom suffix 'dir/a.ext'. - --valid_abspath path Whitelist an absolute path to prevent warnings about - absolute include paths. - -The target file, if specified (-o ), defines what will -be generated: - - .js JavaScript - .html HTML + side JavaScript file (.js) - (JS on the side improves page load time) - .bc LLVM bitcode (default) - .o LLVM bitcode (same as .bc) - -(Note that if --memory-init-file is used, then in addition to a -.js or .html file that is generated, a .mem file will also appear.) - -The -c option (which tells gcc not to run the linker) will -cause LLVM bitcode to be generated, as %s only generates -JavaScript in the final linking stage of building. - -The input file(s) can be either source code files that -Clang can handle (C or C++), LLVM bitcode in binary form, -or LLVM assembly files in human-readable form. - -emcc is affected by several environment variables. For details, view -the source of emcc (search for 'os.environ'). +%s has various additional options. See site/docs/tools_reference/emcc.html emcc: supported targets: llvm bitcode, javascript, NOT elf (autoconf likes to see elf above to enable shared object support) -''' % (this, this, this) +''' % (this, this) exit(0) elif sys.argv[1] == '--version': diff --git a/site/build/html/docs/tools_reference/emcc.html b/site/build/html/docs/tools_reference/emcc.html new file mode 100644 index 0000000000000..9c2846ae5b3fc --- /dev/null +++ b/site/build/html/docs/tools_reference/emcc.html @@ -0,0 +1,1301 @@ + + + + + + + + + + Emscripten Compiler Frontend (emcc) (under-construction) — Emscripten 1.20.0 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                                      + +
                                      + + + + + + +
                                      + + + + + + + +
                                      +
                                      + + + + + + + + + + + +
                                      + +
                                      +

                                      Emscripten Compiler Frontend (emcc) (under-construction)

                                      +

                                      This document provides the command syntax for the Emscription Compiler Frontend.

                                      +
                                      +

                                      Note

                                      +

                                      The information in this page was output by running emcc --help on the version of emcc in the Emscripten 1.20.0 SDK. The most recent version is emcc (master)

                                      +
                                      +
                                      +

                                      Purpose

                                      +

                                      The Emscripten Compiler Frontend (emcc) is used to call the Emscripten compiler from the command line. It is effectively a drop-in replacement for a standard compiler like gcc.

                                      +
                                      +
                                      +

                                      Command line syntax

                                      +
                                      emcc [options] file...
                                      +
                                      +
                                      +

                                      The input file(s) can be either source code files that Clang can handle (C or C++), LLVM bitcode in binary form, or LLVM assembly files in human-readable form.

                                      +

                                      Supported targets include: llvm bitcode, javascript, NOT elf (autoconf likes to see elf above to enable shared object support).

                                      +
                                      +

                                      Arguments

                                      +

                                      Most normal gcc/g++ options will work, for example:

                                      +
                                      +
                                      +++ + + + + + +
                                      +--helpDisplay this information
                                      +--versionDisplay compiler version information
                                      +
                                      +

                                      Options that are modified or new in emcc are listed below:

                                      + ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                                      Command
                                      +
                                      Description
                                      +
                                      +
                                      +
                                      -O0No optimizations (default). This is the recommended setting for starting to port a project, as it includes various assertions.
                                      -O1

                                      Simple optimizations, including asm.js, LLVM -O1 optimizations, relooping, and no runtime assertions or C++ exception catching, and enables -s ALIASING_FUNCTION_POINTERS=1. This is the recommended setting when you want a reasonably optimized build that is generated as quickly as possible (it builds much faster than -O2).

                                      +
                                      +
                                      +

                                      Note

                                      +
                                        +
                                      • For details on the affects of different opt levels, see apply_opt_level() in tools/shared.py and also src/settings.js.
                                      • +
                                      • (to re-enable C++ exception catching, use -s DISABLE_EXCEPTION_CATCHING=0 )
                                      • +
                                      +
                                      +
                                      +
                                      O2As -O1, plus various js-level optimizations and LLVM -O3 optimizations. This is the recommended setting for a release build: slower compilation time in return for the smallest and fastest output.
                                      -OsLike -O2 with extra optimizations for size.
                                      -OzLike -Os but reduces code size further.
                                      -O3Like -O2 plus additional JS optimizations that can take a significant amount of compilation time and/or are relatively new. Note that differs from -O2 only during the bitcode to JS (final link + JS generation) stage, as it is JS-specific, so you can run -Os on your source files for example, and -O3 during JS generation if you want. For tips on optimizing your code, see https://github.com/kripken/emscripten/wiki/Optimizing-Code
                                      -s OPTION=VALUE

                                      JavaScript code generation option passed into the Emscripten compiler. For the available options, see src/settings.js. Note that for options that are lists, you need quotation marks in most shells, for example

                                      +
                                      +
                                      -s RUNTIME_LINKED_LIBS="['liblib.so']"
                                      +
                                      +
                                      +

                                      or

                                      +
                                      -s "RUNTIME_LINKED_LIBS=['liblib.so']"
                                      +
                                      +
                                      +

                                      without the external “s in either of those, you would get an error)

                                      +

                                      You can also specify a file from which the value would be read, for example,

                                      +
                                      -s DEAD_FUNCTIONS=@/path/to/file
                                      +
                                      +
                                      +

                                      The contents of /path/to/file will be read, JSON.parsed and set into DEAD_FUNCTIONS (so the file could contain [“_func1”, “func2”] ). Note that the path must be absolute, not relative.

                                      +
                                      +
                                      -gUse debug info. When compiling to bitcode, this is the same as in clang and gcc, it adds debug info to the object files. When compiling from source to JS or bitcode to JS, it is equivalent to -g3 (keep code as debuggable as possible, except for discarding LLVM debug info, so no C/C++ line numbers; use -g4 to get line number debugging info in JS).
                                      -g<level>

                                      When compiling from bitcode to JS, we can keep the code debuggable to different degrees. Each of these levels builds on the previous:

                                      +
                                      +
                                        +
                                      • -g0 Make no effort to keep code debuggable. Will discard LLVM debug info. (default in -O1+)
                                      • +
                                      • -g1 Preserve (do not minify) whitespace
                                      • +
                                      • -g2 Preserve function names
                                      • +
                                      • -g3 Preserve variable names
                                      • +
                                      • -g4 Preserve LLVM debug info (if -g was used when compiling the C/C++ sources), show line number debug comments, and generate source maps. This is the highest level of debuggability. Note that this may make -O1 and above significantly slower because JS optimization will be limited to 1 core. (default in -O0)
                                      • +
                                      +
                                      +
                                      -profilingUse reasonable defaults when emitting JS to make the build useful for profiling. This sets -g2 (preserve function names) and may also enable optimizations that affect performance and otherwise might not be performed in -g2.
                                      --emit-symbol-mapSave a map file between the minified global names and the original function names. This allows you to reconstruct meaningful stack traces, for example. (This is only relevant when minifying global names, which happens in -O2 and above, and when no -g option to prevent minification was specified.).
                                      --typed-arrays <mode>

                                      Possible mode values are:

                                      +
                                      +
                                        +
                                      • 0: No typed arrays.
                                      • +
                                      • 1: Parallel typed arrays
                                      • +
                                      • 2: Shared (C-like) typed arrays (default)
                                      • +
                                      +
                                      +
                                      --js-opts <level>

                                      Possible level values are:

                                      +
                                      +
                                        +
                                      • 0: Prevent JS optimizer from running
                                      • +
                                      • 1: Use JS optimizer (default)
                                      • +
                                      +
                                      +
                                      --llvm-opts <level>

                                      Possible level values are:

                                      +
                                      +
                                      +
                                        +
                                      • 0: No LLVM optimizations (default in -O0)
                                      • +
                                      • 1: -O1 LLVM optimizations (default in -O1)
                                      • +
                                      • 2: -O2 LLVM optimizations
                                      • +
                                      • 3: -O3 LLVM optimizations (default in -O2+)
                                      • +
                                      +
                                      +

                                      You can also specify arbitrary LLVM options, e.g.:

                                      +
                                      --llvm-opts "['-O3', '-somethingelse']"
                                      +
                                      +
                                      +
                                      +
                                      --llvm-lto <level>

                                      Possible level values are:

                                      +
                                      +
                                      +
                                        +
                                      • 0: No LLVM LTO (default)
                                      • +
                                      • 1: LLVM LTO is performed
                                      • +
                                      • 2: We combine all the bitcode and run LLVM opt -O3 on that (which optimizes across modules, but is not the same as normal LTO), but do not do normal LTO
                                      • +
                                      • 3: We do both 2 and then 1
                                      • +
                                      +
                                      +
                                      +

                                      Note

                                      +
                                        +
                                      • If LLVM optimizations are not run (see --llvm-opts), setting this has no effect.

                                        +
                                      • +
                                      • +
                                        LLVM LTO is not perfectly stable yet, and can can cause code to behave incorrectly.
                                        +

                                        .

                                        +
                                        +
                                        +
                                      • +
                                      +
                                      +
                                      +
                                      --closure <on>

                                      Possible on values are:

                                      +
                                      +
                                      +
                                        +
                                      • 0: No closure compiler (default in -O2 and below)
                                      • +
                                      • 1: Run closure compiler. This greatly reduces code size and may in some cases increase runtime speed (although the opposite can also occur). Note that it takes time to run, and may require some changes to the code.
                                      • +
                                      +
                                      +

                                      In asm.js mode, closure will only be used on the ‘shell’ code around the compiled code (the compiled code will be processed by the custom asm.js minifier).

                                      +
                                      +

                                      Note

                                      +
                                        +
                                      • If closure compiler hits an out-of-memory, try adjusting JAVA_HEAP_SIZE in the environment (for example, to 4096m for 4GB).
                                      • +
                                      • Closure is only run if js opts are being done (-O2 or above, or –js-opts 1).
                                      • +
                                      +
                                      +
                                      +
                                      --pre-js <file>A file whose contents are added before the generated code. This is done before optimization, so it will be minified properly if closure compiler is run.
                                      --post-js <file>

                                      A file whose contents are added after the generated code. This is done before optimization, so it will be minified properly if closure compiler is run.

                                      +
                                      +
                                      +
                                      --embed-file <file>

                                      A file to embed inside the generated JavaScript. The compiled code will be able to access the file in the current directory with the same name as given here. So if you do --embed-file dir/file.dat, then (1) dir/file.dat must exist relative to where you run emcc, and (2) your compiled code will be able to find the file by reading that same path, dir/file.dat. If a directory is passed here, its entire contents will be embedded.

                                      +
                                      +
                                      +

                                      Note

                                      +

                                      Embedding files is much less efficient than preloading them. You should only use it for small amounts of small files. Instead, use --preload-file which emits efficient binary data.

                                      +
                                      +
                                      +
                                      --preload-file <name>

                                      A file to preload before running the compiled code asynchronously. Otherwise similar to –embed-file, except that this option is only relevant when generating HTML (it uses asynchronous binary XHRs), or JS that will be used in a web page. If a directory is passed here, its entire contents will be preloaded. Preloaded files are stored in filename.data, where filename.html is the main file you are compiling to. To run your code, you will need both the .html and the .data.

                                      +
                                      +

                                      emcc runs tools/file_packager.py to do the actual packaging of embedded and preloaded files. You can run the file packager yourself if you want, see docs inside that file. You should then put the output of the file packager in an emcc --pre-js, so that it executes before your main compiled code (or run it before in some other way).

                                      +

                                      For more docs on the options --preload-file accepts, see Filesystem Guide (wiki-import).

                                      +
                                      +
                                      --exclude-file <name>Files and directories to be excluded from –embed-file and –preload-file. Wildcard is supported.
                                      --shell-file <path>

                                      The path name to a skeleton HTML file used when generating HTML output. The shell file used needs to have this token inside it: {{{ SCRIPT }}}.

                                      +
                                      +
                                      +

                                      Note

                                      + +
                                      +
                                      +
                                      --compression <codec>

                                      Compress both the compiled code and embedded/ preloaded files.

                                      +
                                      +

                                      <codec> should be a triple: <native_encoder>,<js_decoder>,<js_name>, where native_encoder is a native executable that compresses stdin to stdout (the simplest possible interface), js_decoder is a JavaScript file that implements a decoder, and js_name is the name of the function to call in the decoder file (which should receive an array/typed array and return an array/typed array. Compression only works when generating HTML. When compression is on, all filed specified to be preloaded are compressed in one big archive, which is given the same name as the output HTML but with suffix .data.compress.

                                      +
                                      +

                                      Warning

                                      +

                                      THIS OPTION IS DEPRECATED

                                      +
                                      +
                                      +
                                      --minify 0Identical to -g1.
                                      --js-transform <cmd><cmd> will be called on the generated code before it is optimized. This lets you modify the JavaScript, for example adding some code or removing some code, in a way that those modifications will be optimized together with the generated code properly. <cmd> will be called with the filename of the generated code as a parameter; to modify the code, you can read the original data and then append to it or overwrite it with the modified data. <cmd> is interpreted as a space-separated list of arguments, for example, <cmd> of python processor.py will cause a Python script to be run.
                                      --split <size>

                                      Splits the resulting javascript file into pieces to ease debugging. This option only works if Javascript is generated (target -o <name>.js). Files with function declarations must be loaded before main file upon execution.

                                      +
                                      +
                                      +
                                      +
                                      Without “-g” option:
                                      +
                                      Creates files with function declarations up to the given size with the suffix “_functions.partxxx.js” and a main file with the suffix ”.js”.
                                      +
                                      With “-g” option:
                                      +
                                      Recreates the directory structure of the C source files and stores function declarations in their respective C files with the suffix ”.js”. If such a file exceeds the given size, files with the suffix ”.partxxx.js” are created. The main file resides in the base directory and has the suffix ”.js”.
                                      +
                                      +
                                      +
                                      +

                                      Warning

                                      +

                                      This option is deprecated (modern JS debuggers should work acceptable even on large files).

                                      +
                                      +
                                      +
                                      --bindCompiles the source code using the embind (wiki-import) bindings approach, which connects C/C++ and JavaScript.
                                      --ignore-dynamic-linkingNormally emcc will treat dynamic linking like static linking, by linking in the code from the dynamic library. This fails if the same dynamic library is linked more than once. With this option, dynamic linking is ignored, which allows the build system to proceed without errors. However, you will need to manually link to the shared libraries later on yourself.
                                      --js-library <lib>A JavaScript library to use in addition to those in Emscripten’s src/library_* .
                                      -vTurns on verbose output. This will pass -v to Clang, and also enable EMCC_DEBUG to details emcc’s operations. It will also run Emscripten’s internal sanity checks, checking that things like the LLVM directory path looks correct, etc. This works with or without other arguments, so it can be useful to run emcc -v if you see odd errors, as it can help diagnose things.
                                      --clear-cacheManually clears the cache of compiled Emscripten system libraries (libc++, libc++abi, libc). This is normally handled automatically, but if you update llvm in-place (instead of having a different directory for a new version), the caching mechanism can get confused. Clearing the cache can fix weird problems related to cache incompatibilities, like clang failing to link with library files. This also clears other cached data like the jcache and the bootstrapped relooper. After the cache is cleared, this process will exit.
                                      --save-bc PATHWhen compiling to JavaScript or HTML, this option will save a copy of the bitcode to the specified path. The bitcode will include all files being linked, including standard libraries, and after any link-time optimizations (if any).
                                      --memory-init-file <on>

                                      Possible on values are:

                                      +
                                      +
                                        +
                                      • 0: Do not emit a separate memory initialization file, keep the static initialization inside the generated JavaScript as text (default)
                                      • +
                                      • 1: Emit a separate memory initialization file in binary format. This is more efficient than storing it as text inside JavaScript, but does mean you have another file to publish. The binary file will also be loaded asynchronously, which means main() will not be called until the file is downloaded and applied; you cannot call any C functions until it arrives. (Call yourself from main() to know when all async stuff has happened and it is safe to call library functions, as main() will only be called at that time. You can also call addOnPreMain from a preRun.)
                                      • +
                                      +
                                      +
                                      -Wno-warn-absolute-paths
                                      +
                                      If not specified, the compiler will warn about any uses of absolute paths in -I and -L command line directives. Pass this flag on the command line to hide these warnings and acknowledge that the explicit use of absolute paths is intentional.
                                      +
                                      HamishW Is it really “Wno-war” - check the source.
                                      +
                                      +
                                      --proxy-to-workerRuns the main application code in a worker, proxying events to it and output from it. If emitting htmlL, this emits an html and a js file, with the js to be run in a worker. If emitting js, the target filename contains the part to be run on the main thread, while a second js file with suffix ”.worker.js” will contain the worker portion..
                                      --emrunEnables the generated output to be aware of the emrun command line tool. This allows stdout, stderr and exit(returncode) capture when running the generated application through emrun.
                                      --em-configSpecifies the location of the .emscripten configuration file for the current compiler run. If not specified, the environment variable EM_CONFIG is read for this file, and if that is not set, the default location ~/.emscripten is assumed..
                                      --default-obj-ext .ext

                                      Specifies the file suffix to generate if the location of a directory name is passed to -o directive, e.g.

                                      +
                                      +
                                      emcc -c a.c -o dir/
                                      +
                                      +
                                      +

                                      will by default generate an output name ‘dir/a.o’, but this cmdline param can be passed to generate a file with a custom suffix ‘dir/a.ext’.

                                      +
                                      +
                                      --valid_abspath pathWhitelist an absolute path to prevent warnings about absolute include paths.
                                      -o <target>

                                      The target filename extension defines what will be generated:

                                      +
                                      +
                                      +
                                        +
                                      • <name> .js : JavaScript
                                      • +
                                      • <name> .html : HTML + side JavaScript file (<name>.js) (JS on the side improves page load time)
                                      • +
                                      • <name> .bc : LLVM bitcode (default)
                                      • +
                                      • <name> .o : LLVM bitcode (same as .bc).
                                      • +
                                      +
                                      +
                                      +

                                      Note

                                      +

                                      If --memory-init-file is used, then in addition to a .js or .html file that is generated, a .mem file will also be created.

                                      +
                                      +
                                      +
                                      -cTells gcc not to run the linker and causes LLVM bitcode to be generated, as emcc only generates JavaScript in the final linking stage of building.
                                      +
                                      +
                                      +
                                      +

                                      Environment variables

                                      +

                                      emcc is affected by several environment variables, as listed below:

                                      +
                                      +
                                        +
                                      • EMMAKEN_JUST_CONFIGURE
                                      • +
                                      • EMMAKEN_JUST_CONFIGURE_RECURSE
                                      • +
                                      • EMCONFIGURE_JS
                                      • +
                                      • CONFIGURE_CC
                                      • +
                                      • EMMAKEN_CXX
                                      • +
                                      • EMMAKEN_CXX
                                      • +
                                      • EMMAKEN_COMPILER
                                      • +
                                      • EMMAKEN_CFLAGS
                                      • +
                                      • EMCC_DEBUG
                                      • +
                                      • EMCC_FAST_COMPILER
                                      • +
                                      +
                                      +

                                      Search for ‘os.environ’ in emcc to see how these are used. The most interesting is possibly EMCC_DEBUG, which forces the compiler to dump its build and temporary files to a temporary directory where they can be reviewed.

                                      +
                                      +
                                      + + +
                                      + +
                                      +
                                      + +
                                      + +
                                      + + + + + + + + + + + + + + + + + + + + + +
                                      + + \ No newline at end of file From 70d79fbd6f88e7e2ad884b8883393b9e1b8aa6f8 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 18 Aug 2014 13:11:12 -0700 Subject: [PATCH 80/91] gl-proxy uniform2fv, texParameterf, isContextLost --- src/webGLClient.js | 7 +++++++ src/webGLWorker.js | 12 ++++++++++++ 2 files changed, 19 insertions(+) diff --git a/src/webGLClient.js b/src/webGLClient.js index 2f2b31c7f1eb0..66ddde41be0b4 100644 --- a/src/webGLClient.js +++ b/src/webGLClient.js @@ -150,6 +150,10 @@ function WebGLClient() { ctx.uniform1f(objects[buffer[i]], buffer[i+1]); i += 2; } + function uniform2fv() { + ctx.uniform2fv(objects[buffer[i]], buffer[i+1]); + i += 2; + } function uniform3f() { ctx.uniform3f(objects[buffer[i]], buffer[i+1], buffer[i+2], buffer[i+3]); i += 4; @@ -242,6 +246,9 @@ function WebGLClient() { 71: { name: 'texSubImage2D', func: func9 }, 72: { name: 'uniform3f', func: uniform3f }, 73: { name: 'blendFuncSeparate', func: func4 }, + 74: { name: 'uniform2fv', func: uniform2fv }, + 75: { name: 'texParameterf', func: func3 }, + 76: { name: 'isContextLost', func: function() { assert(!ctx.isContextLost(), 'context lost which we cannot handle, we are async proxied WebGL') } }, }; function renderCommands(buf) { diff --git a/src/webGLWorker.js b/src/webGLWorker.js index a3855d81db995..295600f08bcde 100644 --- a/src/webGLWorker.js +++ b/src/webGLWorker.js @@ -975,6 +975,18 @@ function WebGLWorker() { this.blendFuncSeparate = function(srcRGB, dstRGB, srcAlpha, dstAlpha) { commandBuffer.push(73, srcRGB, dstRGB, srcAlpha, dstAlpha); } + this.uniform2fv = function(location, data) { + if (!location) return; + commandBuffer.push(74, location.id, new Float32Array(data)); + }; + this.texParameterf = function(target, pname, param) { + commandBuffer.push(75, target, pname, param); + }; + this.isContextLost = function() { + // optimisticaly return that everything is ok; client will abort on an actual context loss. we assume an error-free async workflow + commandBuffer.push(76); + return false; + }; // Setup From 506dfe5d9c6a8ded4eda573aa81312b8c09df457 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 18 Aug 2014 13:31:58 -0700 Subject: [PATCH 81/91] improve other.test_dash_g_bc error output --- tests/test_other.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/test_other.py b/tests/test_other.py index 587f0d5d61b00..140c9dbbb9380 100644 --- a/tests/test_other.py +++ b/tests/test_other.py @@ -3978,9 +3978,9 @@ def get_size(name): Popen([PYTHON, EMCC, path_from_root('tests', 'hello_world.c'), '-g' + str(i), '-o', 'a' + str(i) + '.bc'] + opts).communicate() sizes[i] = get_size('a' + str(i) + '.bc') print ' ', sizes - assert sizes['_'] == sizes[0] == sizes[1] == sizes[2] == sizes[3], 'no debug or <4 debug, means no llvm debug info' - assert sizes['g'] == sizes[4], '-g or -g4 means llvm debug info' - assert sizes['_'] < sizes['g'], 'llvm debug info has positive size' + assert sizes['_'] == sizes[0] == sizes[1] == sizes[2] == sizes[3], 'no debug or <4 debug, means no llvm debug info ' + str(sizes) + assert sizes['g'] == sizes[4], '-g or -g4 means llvm debug info ' + str(sizes) + assert sizes['_'] < sizes['g'], 'llvm debug info has positive size ' + str(sizes) test([]) test(['-O1']) From add0a1f2ffe5b31f41635f4dd48fd3961a0c2bad Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 18 Aug 2014 13:33:05 -0700 Subject: [PATCH 82/91] make other.test_dash_g_bc more robust --- tests/test_other.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_other.py b/tests/test_other.py index 140c9dbbb9380..d28ba0b163577 100644 --- a/tests/test_other.py +++ b/tests/test_other.py @@ -3969,7 +3969,7 @@ def test_dash_g_bc(self): def test(opts): print opts def get_size(name): - return len(open(name).read()) + return os.stat(name).st_size Popen([PYTHON, EMCC, path_from_root('tests', 'hello_world.c'), '-o', 'a_.bc'] + opts).communicate() sizes = { '_': get_size('a_.bc') } Popen([PYTHON, EMCC, path_from_root('tests', 'hello_world.c'), '-g', '-o', 'ag.bc'] + opts).communicate() From 71430b45afbe1bb6418aefb1bc886d9b60b67981 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 18 Aug 2014 15:55:11 -0700 Subject: [PATCH 83/91] make sdl_image.c work when REPORT_RESULT is not defined --- tests/sdl_image.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/sdl_image.c b/tests/sdl_image.c index 9639ea37f7bd9..782d4ebd9a073 100644 --- a/tests/sdl_image.c +++ b/tests/sdl_image.c @@ -52,7 +52,9 @@ int main() { SDL_Quit(); +#ifdef REPORT_RESULT REPORT_RESULT(); +#endif return 0; } From 0a4b5c011e19b13aa4193b7c86164219b9593e74 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 18 Aug 2014 15:56:27 -0700 Subject: [PATCH 84/91] allow customizing the DOM element we listen for key events on using Module.keyboardListeningElement; fixes #2668 --- src/library_sdl.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/library_sdl.js b/src/library_sdl.js index 2b1962f44edf1..7dc11e0c43d71 100644 --- a/src/library_sdl.js +++ b/src/library_sdl.js @@ -1221,9 +1221,10 @@ var LibrarySDL = { // capture all key events. we just keep down and up, but also capture press to prevent default actions if (!Module['doNotCaptureKeyboard']) { - document.addEventListener("keydown", SDL.receiveEvent); - document.addEventListener("keyup", SDL.receiveEvent); - document.addEventListener("keypress", SDL.receiveEvent); + var keyboardListeningElement = Module['keyboardListeningElement'] || document; + keyboardListeningElement.addEventListener("keydown", SDL.receiveEvent); + keyboardListeningElement.addEventListener("keyup", SDL.receiveEvent); + keyboardListeningElement.addEventListener("keypress", SDL.receiveEvent); window.addEventListener("focus", SDL.receiveEvent); window.addEventListener("blur", SDL.receiveEvent); document.addEventListener("visibilitychange", SDL.receiveEvent); From a57ecc76eeadd2ef3a3cc2118191058b2850b243 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 18 Aug 2014 16:03:37 -0700 Subject: [PATCH 85/91] help docs update --- site/source/docs/tools_reference/emcc.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/site/source/docs/tools_reference/emcc.rst b/site/source/docs/tools_reference/emcc.rst index 3fb6f484cd81a..38596e01b10e3 100644 --- a/site/source/docs/tools_reference/emcc.rst +++ b/site/source/docs/tools_reference/emcc.rst @@ -28,11 +28,13 @@ Supported targets include: llvm bitcode, javascript, NOT elf (autoconf likes to Arguments --------- -Most `normal gcc/g++ options `_ will work, for example: +Most `clang options `_ will work, as will `gcc options `_, for example: --help Display this information --version Display compiler version information +To see the full list of clang options supported on the version of clang used by Emscripten, run ``clang --help``. + Options that are modified or new in *emcc* are listed below: From d1f676b42067a475e9ff945f634af1dd365634ae Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 18 Aug 2014 17:44:49 -0700 Subject: [PATCH 86/91] update other.test_emcc --- tests/test_other.py | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/tests/test_other.py b/tests/test_other.py index d28ba0b163577..d62e755ef93f6 100644 --- a/tests/test_other.py +++ b/tests/test_other.py @@ -31,15 +31,8 @@ def test_emcc(self): # --help output = Popen([PYTHON, compiler, '--help'], stdout=PIPE, stderr=PIPE).communicate() - self.assertContained('''%s [options] file... - -Most normal gcc/g++ options will work, for example: - --help Display this information - --version Display compiler version information - -Options that are modified or new in %s include: - - -O0 No optimizations (default)''' % (shortcompiler, shortcompiler), output[0].replace('\r', ''), output[1].replace('\r', '')) + self.assertContained(''' --help Display this information + --version Display compiler version information''', output[0]) # emcc src.cpp ==> writes a.out.js self.clear() From 15a991d64ffdee5d2727dc3394299d0a9bac53c0 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Mon, 18 Aug 2014 17:53:27 -0700 Subject: [PATCH 87/91] faq updates --- .../docs/introducing_emscripten/FAQ.rst | 21 ++++++------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/site/source/docs/introducing_emscripten/FAQ.rst b/site/source/docs/introducing_emscripten/FAQ.rst index d5987ac1744db..5ad06598bb839 100644 --- a/site/source/docs/introducing_emscripten/FAQ.rst +++ b/site/source/docs/introducing_emscripten/FAQ.rst @@ -73,6 +73,11 @@ General can run gzip on your webserver, so the amount actually transferred over the network is much smaller than even that. + Note also that Emscripten must ship all the necessary library code + together with your application (like the parts of libc that your + program uses). This can increase code size, but it is mostly noticeable + only on small programs. + - **Q.** Where does Emscripten itself run? **A.** Emscripten is known to work on Windows, OS X and Linux. (There @@ -84,25 +89,11 @@ General - **Q.** What APIs/libraries does Emscripten support? - **A.** libc and stdlibc++ support is very good. SDL support is + **A.** The C and C++ standard libraries are supported. SDL support is sufficient to run quite a lot of code. OpenGL support is in very good shape for OpenGL ES 2.0-type code, and even some other types, see :ref:`OpenGL-support`. -- **Q.** Is this really a compiler? Isn't it better described as a - translator? - - **A.** Well, a *compiler* is usually defined as a program that - transforms source code written in one programming language into - another, which is what Emscripten does. A *translator* is a more - specific term that is usually used for compilation between high-level - languages, which isn't exactly applicable. On the other hand a - *decompiler* is something that translates a low-level language to a - higher-level one, so that might technically be a valid description, - but it sounds odd since we aren't going back to the original language - we compiled from (C/C++, most likely) but into something else - (JavaScript). - - **Q.** The name of the project sounds weird to me. **A.** I don't know why; it's a perfectly From 1c8a97ecea8aa1a1278d427dd2026ad75c417e76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jukka=20Jyl=C3=A4nki?= Date: Mon, 18 Aug 2014 15:57:51 +0300 Subject: [PATCH 88/91] Apply patch from upstream libc++ bug 18735: http://llvm.org/bugs/show_bug.cgi?id=18735 to fix self-assignment operators of std::map, multimap and unordered_map. --- system/include/libcxx/map | 20 ++++++++++++-------- system/include/libcxx/unordered_map | 28 ++++++++++++++++------------ 2 files changed, 28 insertions(+), 20 deletions(-) diff --git a/system/include/libcxx/map b/system/include/libcxx/map index 009e8e2162c5f..9779b70e21224 100644 --- a/system/include/libcxx/map +++ b/system/include/libcxx/map @@ -884,10 +884,12 @@ public: #if __cplusplus >= 201103L __tree_ = __m.__tree_; #else - __tree_.clear(); - __tree_.value_comp() = __m.__tree_.value_comp(); - __tree_.__copy_assign_alloc(__m.__tree_); - insert(__m.begin(), __m.end()); + if (this != &__m) { + __tree_.clear(); + __tree_.value_comp() = __m.__tree_.value_comp(); + __tree_.__copy_assign_alloc(__m.__tree_); + insert(__m.begin(), __m.end()); + } #endif return *this; } @@ -1616,10 +1618,12 @@ public: #if __cplusplus >= 201103L __tree_ = __m.__tree_; #else - __tree_.clear(); - __tree_.value_comp() = __m.__tree_.value_comp(); - __tree_.__copy_assign_alloc(__m.__tree_); - insert(__m.begin(), __m.end()); + if (this != &__m) { + __tree_.clear(); + __tree_.value_comp() = __m.__tree_.value_comp(); + __tree_.__copy_assign_alloc(__m.__tree_); + insert(__m.begin(), __m.end()); + } #endif return *this; } diff --git a/system/include/libcxx/unordered_map b/system/include/libcxx/unordered_map index 78fee4811fadf..4e2298bf9b2f3 100644 --- a/system/include/libcxx/unordered_map +++ b/system/include/libcxx/unordered_map @@ -831,12 +831,14 @@ public: #if __cplusplus >= 201103L __table_ = __u.__table_; #else - __table_.clear(); - __table_.hash_function() = __u.__table_.hash_function(); - __table_.key_eq() = __u.__table_.key_eq(); - __table_.max_load_factor() = __u.__table_.max_load_factor(); - __table_.__copy_assign_alloc(__u.__table_); - insert(__u.begin(), __u.end()); + if (this != &__u) { + __table_.clear(); + __table_.hash_function() = __u.__table_.hash_function(); + __table_.key_eq() = __u.__table_.key_eq(); + __table_.max_load_factor() = __u.__table_.max_load_factor(); + __table_.__copy_assign_alloc(__u.__table_); + insert(__u.begin(), __u.end()); + } #endif return *this; } @@ -1567,12 +1569,14 @@ public: #if __cplusplus >= 201103L __table_ = __u.__table_; #else - __table_.clear(); - __table_.hash_function() = __u.__table_.hash_function(); - __table_.key_eq() = __u.__table_.key_eq(); - __table_.max_load_factor() = __u.__table_.max_load_factor(); - __table_.__copy_assign_alloc(__u.__table_); - insert(__u.begin(), __u.end()); + if (this != &__u) { + __table_.clear(); + __table_.hash_function() = __u.__table_.hash_function(); + __table_.key_eq() = __u.__table_.key_eq(); + __table_.max_load_factor() = __u.__table_.max_load_factor(); + __table_.__copy_assign_alloc(__u.__table_); + insert(__u.begin(), __u.end()); + } #endif return *this; } From 6e35daa63a1ed2085a5ad368438b6d7a4b26e441 Mon Sep 17 00:00:00 2001 From: Jukka Jylanki Date: Tue, 19 Aug 2014 16:53:16 +0300 Subject: [PATCH 89/91] Add test for std::map self-assign. --- tests/test_core.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/tests/test_core.py b/tests/test_core.py index 8c7d6fbb6a706..b804e6badeac8 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -6925,6 +6925,25 @@ def test_coroutine(self): Settings.ASYNCIFY = 1; self.do_run(src, '*0-100-1-101-1-102-2-103-3-104-5-105-8-106-13-107-21-108-34-109-*'); + def test_cxx_self_assign(self): + # See https://github.com/kripken/emscripten/pull/2688 and http://llvm.org/bugs/show_bug.cgi?id=18735 + open('src.cpp', 'w').write(r''' + #include + #include + + int main() { + std::map m; + m[0] = 1; + m = m; + // size should still be one after self assignment + if (m.size() == 1) { + printf("ok.\n"); + } + } + ''') + Popen([PYTHON, EMCC, 'src.cpp']).communicate() + self.assertContained('ok.', run_js('a.out.js', args=['C'])) + # Generate tests for everything def make_run(fullname, name=-1, compiler=-1, embetter=0, quantum_size=0, typed_arrays=0, emcc_args=None, env=None): From ccc9d138396bd97287ba1c03fee7128d73a92a75 Mon Sep 17 00:00:00 2001 From: Jukka Jylanki Date: Tue, 19 Aug 2014 16:54:00 +0300 Subject: [PATCH 90/91] Add a note to readme.txt for libcxx to remind about backported std::map self-assign fix. --- system/lib/libcxx/readme.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/system/lib/libcxx/readme.txt b/system/lib/libcxx/readme.txt index ccac2fcdf3110..ae99316df3d1b 100644 --- a/system/lib/libcxx/readme.txt +++ b/system/lib/libcxx/readme.txt @@ -1 +1,3 @@ -These files are from libc++, svn revision 195693, 2013-11-26. +These files are from libc++, svn revision 195693, 2013-11-26. See http://libcxx.llvm.org + +A fix to http://llvm.org/bugs/show_bug.cgi?id=18735 is backported on top of the above svn revision. See https://github.com/kripken/emscripten/pull/2688 From f984d94836ef5b1f21ef2fa53fd6362af471442e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jukka=20Jyl=C3=A4nki?= Date: Mon, 18 Aug 2014 15:58:44 +0300 Subject: [PATCH 91/91] Bump version to 1.22.2 to ensure the previous patch is applied. --- emscripten-version.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/emscripten-version.txt b/emscripten-version.txt index 7355401e916ca..6379b274f0f6b 100644 --- a/emscripten-version.txt +++ b/emscripten-version.txt @@ -1,2 +1,2 @@ -1.22.1 +1.22.2