diff --git a/emcc b/emcc index 7cf67b75cc65e..00daef0a794d0 100755 --- a/emcc +++ b/emcc @@ -419,6 +419,10 @@ try: valid_abspaths = [] def is_valid_abspath(path_name): + # Any path that is underneath the emscripten repository root must be ok. + if shared.path_from_root().replace('\\', '/') in path_name.replace('\\', '/'): + return True + for valid_abspath in valid_abspaths: if in_directory(valid_abspath, path_name): return True @@ -920,8 +924,11 @@ try: assert not (shared.Settings.NO_DYNAMIC_EXECUTION and closure), 'cannot have both NO_DYNAMIC_EXECUTION and closure compiler enabled at the same time' if closure: - shared.Settings.CLOSURE_COMPILER = 1 + shared.Settings.CLOSURE_COMPILER = closure assert os.path.exists(shared.CLOSURE_COMPILER), logging.error('fatal: Closure compiler (%s) does not exist', shared.CLOSURE_COMPILER) + if closure == 2 and shared.Settings.ASM_JS == 1: + logging.warning('not all asm.js optimizations are possible with --closure 2, disabling those - your code will be run more slowly') + shared.Settings.ASM_JS = 2 assert shared.LLVM_TARGET in shared.COMPILER_OPTS if shared.LLVM_TARGET == 'i386-pc-linux-gnu': @@ -986,6 +993,8 @@ try: if js_opts: shared.Settings.RUNNING_JS_OPTS = 1 + shared.Settings.RUNNING_FASTCOMP = fastcomp + shared.Settings.EMSCRIPTEN_VERSION = shared.EMSCRIPTEN_VERSION shared.Settings.OPT_LEVEL = opt_level shared.Settings.DEBUG_LEVEL = debug_level @@ -1288,9 +1297,7 @@ try: open(memfile, 'wb').write(''.join(map(lambda x: chr(int(x or '0')), s.split(',')))) if DEBUG: # Copy into temp dir as well, so can be run there too - temp_memfile = os.path.join(shared.EMSCRIPTEN_TEMP_DIR, os.path.basename(memfile)) - if os.path.abspath(memfile) != os.path.abspath(memfile): - shutil.copyfile(memfile, temp_memfile) + shared.safe_copy(memfile, os.path.join(shared.EMSCRIPTEN_TEMP_DIR, os.path.basename(memfile))) return 'var memoryInitializer = "%s";' % os.path.basename(memfile) src = re.sub(shared.JS.memory_initializer_pattern, repl, open(final).read(), count=1) open(final + '.mem.js', 'w').write(src) @@ -1352,7 +1359,7 @@ try: js_optimizer_extra_info = {} if opt_level >= 1 and js_opts: - logging.debug('running pre-closure post-opts') + logging.debug('running js post-opts') if DEBUG == '2': # Clean up the syntax a bit @@ -1399,28 +1406,37 @@ try: js_optimizer_queue += ['outline'] js_optimizer_extra_info['sizeToOutline'] = shared.Settings.OUTLINING_LIMIT - if opt_level >= 2 and (not closure or shared.Settings.ASM_JS) and shared.Settings.RELOOP and debug_level < 3: + if opt_level >= 2 and (not closure or shared.Settings.ASM_JS or closure == 2) and shared.Settings.RELOOP and debug_level < 3: if shared.Settings.ASM_JS and opt_level >= 3: js_optimizer_queue += ['registerizeHarder'] else: js_optimizer_queue += ['registerize'] if opt_level >= 2: - if debug_level < 2 and shared.Settings.ASM_JS: + if debug_level < 2 and shared.Settings.ASM_JS and not closure == 2: js_optimizer_queue += ['minifyNames'] if emit_symbol_map: js_optimizer_queue += ['symbolMap='+target+'.symbols'] if debug_level == 0: js_optimizer_queue += ['minifyWhitespace'] if shared.Settings.ASM_JS: - if closure: + if closure == 1: js_optimizer_queue += ['closure'] - elif debug_level <= 2 and not shared.Settings.MAIN_MODULE and not shared.Settings.SIDE_MODULE: + elif debug_level <= 2 and not shared.Settings.MAIN_MODULE and not shared.Settings.SIDE_MODULE and not closure: js_optimizer_queue += ['cleanup'] if not shared.Settings.SIDE_MODULE: js_optimizer_queue += ['last'] # side modules are not finalized until after relocation flush_js_optimizer_queue() + if shared.Settings.ASM_JS and closure == 2: + flush_js_optimizer_queue() + + logging.debug('running closure') + # no need to add this to js_transform_tempfiles, because closure and + # debug_level > 0 are never simultaneously true + final = shared.Building.closure_compiler(final, pretty=debug_level >= 1) + if DEBUG: save_intermediate('closure') + log_time('js opts') # Remove some trivial whitespace # TODO: do not run when compress has already been done on all parts of the code diff --git a/emscripten-version.txt b/emscripten-version.txt index 5f96aa7b34621..f2c16746929e2 100644 --- a/emscripten-version.txt +++ b/emscripten-version.txt @@ -1,2 +1,2 @@ -1.23.0 +1.23.1 diff --git a/emscripten.py b/emscripten.py index 1dc021eb43eb7..3face4016baf4 100755 --- a/emscripten.py +++ b/emscripten.py @@ -1023,7 +1023,7 @@ def fix_item(item): if settings['PRECISE_F32']: maths += ['Math.fround'] - basic_funcs = ['abort', 'assert', 'asmPrintInt', 'asmPrintFloat'] + [m.replace('.', '_') for m in math_envs] + basic_funcs = ['abort', 'assert'] + [m.replace('.', '_') for m in math_envs] if settings['RESERVED_FUNCTION_POINTERS'] > 0: basic_funcs.append('jsCall') if settings['SAFE_HEAP']: basic_funcs += ['SAFE_HEAP_LOAD', 'SAFE_HEAP_STORE', 'SAFE_FT_MASK'] if settings['CHECK_HEAP_ALIGN']: basic_funcs += ['CHECK_ALIGN_2', 'CHECK_ALIGN_4', 'CHECK_ALIGN_8'] @@ -1124,12 +1124,24 @@ def keyfunc(other): asm_setup += '\n' + shared.JS.make_extcall(sig) + '\n' basic_funcs.append('extCall_%s' % sig) + def quote(prop): + if settings['CLOSURE_COMPILER'] == 2: + return "'" + prop + "'" + else: + return prop + + def access_quote(prop): + if settings['CLOSURE_COMPILER'] == 2: + return "['" + prop + "']" + else: + return '.' + prop + # calculate exports exported_implemented_functions = list(exported_implemented_functions) + metadata['initializers'] exported_implemented_functions.append('runPostSets') exports = [] for export in exported_implemented_functions + asm_runtime_funcs + function_tables: - exports.append("%s: %s" % (export, export)) + exports.append(quote(export) + ": " + export) exports = '{ ' + ', '.join(exports) + ' }' # calculate globals try: @@ -1141,9 +1153,9 @@ def keyfunc(other): global_funcs = list(set([key for key, value in forwarded_json['Functions']['libraryFunctions'].iteritems() if value != 2]).difference(set(global_vars)).difference(implemented_functions)) def math_fix(g): return g if not g.startswith('Math_') else g.split('_')[1] - asm_global_funcs = ''.join([' var ' + g.replace('.', '_') + '=global.' + g + ';\n' for g in maths]) + \ - ''.join([' var ' + g + '=env.' + math_fix(g) + ';\n' for g in basic_funcs + global_funcs]) - asm_global_vars = ''.join([' var ' + g + '=env.' + g + '|0;\n' for g in basic_vars + global_vars]) + asm_global_funcs = ''.join([' var ' + g.replace('.', '_') + '=global' + access_quote(g) + ';\n' for g in maths]) + \ + ''.join([' var ' + g + '=env' + access_quote(math_fix(g)) + ';\n' for g in basic_funcs + global_funcs]) + asm_global_vars = ''.join([' var ' + g + '=env' + access_quote(g) + '|0;\n' for g in basic_vars + global_vars]) # In linkable modules, we need to add some explicit globals for global variables that can be linked and used across modules if settings.get('MAIN_MODULE') or settings.get('SIDE_MODULE'): assert settings.get('TARGET_ASMJS_UNKNOWN_EMSCRIPTEN'), 'TODO: support x86 target when linking modules (needs offset of 4 and not 8 here)' @@ -1167,6 +1179,7 @@ def math_fix(g): return real_''' + s + '''.apply(null, arguments); }; ''' for s in exported_implemented_functions if s not in ['_malloc', '_free', '_memcpy', '_memset']]) + receiving += ';\n'.join(['var ' + s + ' = Module["' + s + '"] = asm["' + s + '"]' for s in exported_implemented_functions + function_tables]) # finalize @@ -1175,24 +1188,26 @@ def math_fix(g): funcs_js = [''' %s - function asmPrintInt(x, y) { - Module.print('int ' + x + ',' + y);// + ' ' + new Error().stack); - } - function asmPrintFloat(x, y) { - Module.print('float ' + x + ',' + y);// + ' ' + new Error().stack); - } // EMSCRIPTEN_START_ASM var asm = (function(global, env, buffer) { %s - var HEAP8 = new global.Int8Array(buffer); - var HEAP16 = new global.Int16Array(buffer); - var HEAP32 = new global.Int32Array(buffer); - var HEAPU8 = new global.Uint8Array(buffer); - var HEAPU16 = new global.Uint16Array(buffer); - var HEAPU32 = new global.Uint32Array(buffer); - var HEAPF32 = new global.Float32Array(buffer); - var HEAPF64 = new global.Float64Array(buffer); - ''' % (asm_setup, "'use asm';" if not metadata.get('hasInlineJS') and not settings['SIDE_MODULE'] and settings['ASM_JS'] == 1 else "'almost asm';") + '\n' + asm_global_vars + ''' + var HEAP8 = new global%s(buffer); + var HEAP16 = new global%s(buffer); + var HEAP32 = new global%s(buffer); + var HEAPU8 = new global%s(buffer); + var HEAPU16 = new global%s(buffer); + var HEAPU32 = new global%s(buffer); + var HEAPF32 = new global%s(buffer); + var HEAPF64 = new global%s(buffer); + ''' % (asm_setup, "'use asm';" if not metadata.get('hasInlineJS') and not settings['SIDE_MODULE'] and settings['ASM_JS'] == 1 else "'almost asm';", + access_quote('Int8Array'), + access_quote('Int16Array'), + access_quote('Int32Array'), + access_quote('Uint8Array'), + access_quote('Uint16Array'), + access_quote('Uint32Array'), + access_quote('Float32Array'), + access_quote('Float64Array')) + '\n' + asm_global_vars + ''' var __THREW__ = 0; var threwValue = 0; var setjmpId = 0; diff --git a/site/build/text/docs/api_reference/preamble.js.txt b/site/build/text/docs/api_reference/preamble.js.txt index 68514c19ac584..6e7f203a35bca 100644 --- a/site/build/text/docs/api_reference/preamble.js.txt +++ b/site/build/text/docs/api_reference/preamble.js.txt @@ -8,7 +8,7 @@ functions, accessing memory, converting pointers to JavaScript "Strings" and "Strings" to pointers (with different encodings/formats), and other convenience functions. -Note: All functions should be called though the "Module" object (for +Note: All functions should be called though the *Module* object (for example: "Module.functionName"). At optimisation "-O2" (and higher) function names are minified by the closure compiler, and calling them directly will fail. @@ -76,10 +76,13 @@ ccall(ident, returnType, argTypes, args) Arguments: * **ident** -- The name of the C function to be called. - * **returnType** -- The return type of the function. This will - be one of the JavaScript 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). + * **returnType** -- The return type of the function. This can + be ""number"", ""string"" or ""array"", which correspond to + the appropriate JavaScript types (use ""number"" for any C + pointer, and ""array"" for JavaScript arrays and typed arrays; + note that arrays are 8-bit), or for a void function it can be + "null" (note: the JavaScript "null" value, not a string + containing the word "null"). * **argTypes** -- An array of the types of arguments for the function (if there are no arguments, this can be omitted). diff --git a/site/build/text/docs/tools_reference/emcc.txt b/site/build/text/docs/tools_reference/emcc.txt index a409d173a7aee..332c59c01a606 100644 --- a/site/build/text/docs/tools_reference/emcc.txt +++ b/site/build/text/docs/tools_reference/emcc.txt @@ -1,6 +1,6 @@ -Emscripten Compiler Frontend (emcc) (under-construction) -******************************************************** +Emscripten Compiler Frontend (emcc) (ready-for-review) +****************************************************** **This document provides the command syntax for the Emscription Compiler Frontend.** @@ -23,9 +23,6 @@ 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 --------- @@ -211,8 +208,6 @@ Options that are modified or new in *emcc* are listed below: * LLVM LTO is not perfectly stable yet, and can can cause code to behave incorrectly. - . - "--closure " Runs the *Closure Compiler*. Possible "on" values are: @@ -221,11 +216,16 @@ Options that are modified or new in *emcc* are listed 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. + 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). - 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). + * "2": Run closure compiler on *all* the emitted code, even on + **asm.js** output in **asm.js** mode. This can further reduce + code size, but does prevent a significant amount of **asm.js** + optimizations, so it is not recommended unless you want to + reduce code size at all costs. Note: * If closure compiler hits an out-of-memory, try adjusting @@ -284,7 +284,7 @@ Options that are modified or new in *emcc* are listed below: "--exclude-file " Files and directories to be excluded from *--embed-file* and - *--preload-file*. Wildcard is supported. + *--preload-file*. Wildcards (*) are supported. "--shell-file " The path name to a skeleton HTML file used when generating HTML @@ -420,10 +420,9 @@ Options that are modified or new in *emcc* are listed below: means "main()" will not be called until the file is downloaded and applied; you cannot call any C functions until it arrives. - Note: Call yourself from "main()" to know when all asynchronous - processing has completed 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". + Note: The *safest way* to ensure that it is safe to call + C functions (the initialisation file has loaded) is to + call a notifier function from "main()". "-Wno-warn-absolute-paths" Suppress warnings about the use of absolute paths in "-I" and "-L" @@ -482,9 +481,9 @@ Options that are modified or new in *emcc* are listed below: will also be created. "-c" - Tells *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. + Tells *emcc* to generate LLVM bitcode (which can then be linked + with other bitcode files), instead of compiling all the way to + JavaScript. Environment variables diff --git a/site/source/_themes/emscripten_sphinx_rtd_theme/footer.html b/site/source/_themes/emscripten_sphinx_rtd_theme/footer.html index 56a463c508b2d..51d542c44759b 100644 --- a/site/source/_themes/emscripten_sphinx_rtd_theme/footer.html +++ b/site/source/_themes/emscripten_sphinx_rtd_theme/footer.html @@ -41,7 +41,7 @@ {%- if hasdoc(document) %} {{ shorttext }}{{ longtext }} {%- elif document | truncate(4, True, end='') == 'http' %} - {{ shorttext }}{{ longtext }} + {{ shorttext }}{{ longtext }} {%- else %} {{ shorttext }} {%- endif %} diff --git a/site/source/_themes/emscripten_sphinx_rtd_theme/layout.html b/site/source/_themes/emscripten_sphinx_rtd_theme/layout.html index 2315ad930aaaf..04b3b419928f2 100644 --- a/site/source/_themes/emscripten_sphinx_rtd_theme/layout.html +++ b/site/source/_themes/emscripten_sphinx_rtd_theme/layout.html @@ -98,6 +98,7 @@ {% set toctree = toctree(maxdepth=4, collapse=False, includehidden=True) %} {% if toctree %} {{ toctree }} + Index {% else %}
{{ toc }}
@@ -144,7 +145,7 @@ {%- if hasdoc(document) %} {{ shorttext }}{{ longtext }} {%- elif document | truncate(4, True, end='') == 'http' %} - {{ shorttext }}{{ longtext }} + {{ shorttext }}{{ longtext }} {%- endif %} {% endfor %} diff --git a/site/source/_themes/emscripten_sphinx_rtd_theme/static/css/theme.css b/site/source/_themes/emscripten_sphinx_rtd_theme/static/css/theme.css index 8775c04111263..394f0a8760ad2 100644 --- a/site/source/_themes/emscripten_sphinx_rtd_theme/static/css/theme.css +++ b/site/source/_themes/emscripten_sphinx_rtd_theme/static/css/theme.css @@ -1,7 +1,9 @@ *{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block}audio,canvas,video{display:inline-block;*display:inline;*zoom:1}audio:not([controls]){display:none}[hidden]{display:none}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:100%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%} body{margin:0}a:hover,a:active{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:bold}blockquote{margin:0}dfn{font-style:italic}hr{display:block;height:1px;border:0;border-top:1px solid #ccc;margin:20px 0;padding:0}ins{background:#ff9;color:#000;text-decoration:none}mark{background:#ff0;color:#000;font-style:italic;font-weight:bold}pre,code,.rst-content tt,kbd,samp{font-family:monospace,serif;_font-family:"courier new",monospace;font-size:1em}pre{white-space:pre}q{quotes:none}q:before,q:after{content:"";content:none}small{font-size:85%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}ul,ol,dl{margin:0;padding:0;list-style:none;list-style-image:none}li{list-style:none}dd{margin:0}img{border:0;-ms-interpolation-mode:bicubic;vertical-align:middle;max-width:100%}svg:not(:root){overflow:hidden}figure{margin:0}form{margin:0}fieldset{border:0;margin:0;padding:0}label{cursor:pointer}legend{border:0;*margin-left:-7px;padding:0;white-space:normal}button,input,select,textarea{font-size:100%;margin:0;vertical-align:baseline;*vertical-align:middle}button,input{line-height:normal}button,input[type="button"],input[type="reset"],input[type="submit"]{cursor:pointer;-webkit-appearance:button;*overflow:visible}button[disabled],input[disabled]{cursor:default}input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0;*width:13px;*height:13px}input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}input[type="search"]::-webkit-search-decoration,input[type="search"]::-webkit-search-cancel-button{-webkit-appearance:none}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}textarea{overflow:auto;vertical-align:top;resize:vertical} -table{border-collapse:collapse;border-spacing:0}td{vertical-align:top}.chromeframe{margin:0.2em 0;background:#ccc;color:#000;padding:0.2em 0}.ir{display:block;border:0;text-indent:-999em;overflow:hidden;background-color:transparent;background-repeat:no-repeat;text-align:left;direction:ltr;*line-height:0}.ir br{display:none}.hidden{display:none !important;visibility:hidden}.visuallyhidden{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.visuallyhidden.focusable:active,.visuallyhidden.focusable:focus{clip:auto;height:auto;margin:0;overflow:visible;position:static;width:auto}.invisible{visibility:hidden}.relative{position:relative}big,small{font-size:100%}@media print{html,body,section{background:none !important}*{box-shadow:none !important;text-shadow:none !important;filter:none !important;-ms-filter:none !important}a,a:visited{text-decoration:underline}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}} +table{border-collapse:collapse;border-spacing:0}td{vertical-align:top}.chromeframe{margin:0.2em 0;background:#ccc;color:#000;padding:0.2em 0}.ir{display:block;border:0;text-indent:-999em;overflow:hidden;background-color:transparent;background-repeat:no-repeat;text-align:left;direction:ltr;*line-height:0}.ir br{display:none}.hidden{display:none !important;visibility:hidden}.visuallyhidden{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.visuallyhidden.focusable:active,.visuallyhidden.focusable:focus{clip:auto;height:auto;margin:0;overflow:visible;position:static;width:auto}.invisible{visibility:hidden}.relative{position:relative}big,small{font-size:100%}@media print{html,body,section{background:none !important}*{box-shadow:none !important;text-shadow:none !important;filter:none !important;-ms-filter:none !important}a,a:visited{text-decoration:underline} +.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""} +pre,blockquote{page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100% !important}@page{margin:0.5cm}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}} .fa:before,.rst-content .admonition-title:before,.rst-content h1 .headerlink:before,.rst-content h2 .headerlink:before,.rst-content h3 .headerlink:before,.rst-content h4 .headerlink:before,.rst-content h5 .headerlink:before,.rst-content h6 .headerlink:before,.rst-content dl dt .headerlink:before,.icon:before,.wy-dropdown .caret:before,.wy-inline-validate.wy-inline-validate-success .wy-input-context:before,.wy-inline-validate.wy-inline-validate-danger .wy-input-context:before,.wy-inline-validate.wy-inline-validate-warning .wy-input-context:before,.wy-inline-validate.wy-inline-validate-info .wy-input-context:before,.wy-alert,.rst-content .note,.rst-content .attention,.rst-content .caution,.rst-content .danger,.rst-content .error,.rst-content .hint,.rst-content .important,.rst-content .tip,.rst-content .warning,.rst-content .seealso,.btn,input[type="text"],input[type="password"],input[type="email"],input[type="url"],input[type="date"],input[type="month"],input[type="time"],input[type="datetime"],input[type="datetime-local"],input[type="week"],input[type="number"],input[type="search"],input[type="tel"],input[type="color"],select,textarea,.wy-menu-vertical li.on a,.wy-menu-vertical li.current>a,.wy-side-nav-search>a,.wy-side-nav-search .wy-dropdown>a,.wy-nav-top a{-webkit-font-smoothing:antialiased}.clearfix{*zoom:1} .clearfix:before,.clearfix:after{display:table;content:""}.clearfix:after{clear:both}/*! * Font Awesome 4.0.3 by @davegandy - http://fontawesome.io - @fontawesome @@ -37,7 +39,22 @@ body{ background:#edf0f2 } -.wy-text-left{text-align:left}.wy-text-center{text-align:center}.wy-text-right{text-align:right}.wy-text-large{font-size:120%}.wy-text-normal{font-size:100%}.wy-text-small,small{font-size:80%}.wy-text-strike{text-decoration:line-through}.wy-text-warning{color:#e67e22 !important}a.wy-text-warning:hover{color:#eb9950 !important}.wy-text-info{color:#2980b9 !important}a.wy-text-info:hover{color:#409ad5 !important}.wy-text-success{color:#27ae60 !important}a.wy-text-success:hover{color:#36d278 !important}.wy-text-danger{color:#e74c3c !important}a.wy-text-danger:hover{color:#ed7669 !important}.wy-text-neutral{color:#404040 !important}a.wy-text-neutral:hover{color:#595959 !important}h1,h2,h3,h4,h5,h6,legend{margin-top:0;font-weight:700;font-family:"Roboto Slab","ff-tisa-web-pro","Georgia",Arial,sans-serif}p{line-height:24px;margin:0;font-size:16px;margin-bottom:24px}h1{font-size:175%}h2{font-size:150%}h3{font-size:125%}h4{font-size:115%}h5{font-size:110%}h6{font-size:100%}code,.rst-content tt{white-space:nowrap;max-width:100%;background:#fff;border:solid 1px #e1e4e5;font-size:75%;padding:0 5px;font-family:"Inconsolata","Consolata","Monaco",monospace;color:#e74c3c;overflow-x:auto}code.code-large,.rst-content tt.code-large{font-size:90%}.wy-plain-list-disc,.rst-content .section ul,.rst-content .toctree-wrapper ul,article ul{list-style:disc;line-height:24px;margin-bottom:24px} +.wy-text-left{text-align:left}.wy-text-center{text-align:center}.wy-text-right{text-align:right}.wy-text-large{font-size:120%}.wy-text-normal{font-size:100%}.wy-text-small,small{font-size:80%}.wy-text-strike{text-decoration:line-through}.wy-text-warning{color:#e67e22 !important}a.wy-text-warning:hover{color:#eb9950 !important}.wy-text-info{color:#2980b9 !important}a.wy-text-info:hover{color:#409ad5 !important}.wy-text-success{color:#27ae60 !important}a.wy-text-success:hover{color:#36d278 !important}.wy-text-danger{color:#e74c3c !important}a.wy-text-danger:hover{color:#ed7669 !important}.wy-text-neutral{color:#404040 !important}a.wy-text-neutral:hover{color:#595959 !important}h1,h2,h3,h4,h5,h6,legend{margin-top:0;font-weight:700;font-family:"Roboto Slab","ff-tisa-web-pro","Georgia",Arial,sans-serif}p{line-height:24px;margin:0;font-size:16px;margin-bottom:24px}h1{font-size:175%}h2{font-size:150%}h3{font-size:125%}h4{font-size:115%}h5{font-size:110%}h6{font-size:100%} + +code, .rst-content tt + { + white-space:nowrap; + max-width:100%; + background:#fff; + border:solid 1px #e1e4e5; + /* font-size:75%; */ + font-size:90%; + padding:0 5px; + font-family:"Inconsolata","Consolata","Monaco",monospace;color:#e74c3c; + overflow-x:auto + } + +code.code-large,.rst-content tt.code-large{font-size:90%}.wy-plain-list-disc,.rst-content .section ul,.rst-content .toctree-wrapper ul,article ul{list-style:disc;line-height:24px;margin-bottom:24px} .wy-plain-list-disc li,.rst-content .section ul li,.rst-content .toctree-wrapper ul li,article ul li { list-style:disc;margin-left:24px} @@ -363,13 +380,19 @@ table.wrap-table-content td, table.wrap-table-content th { -/* HamishW - fix bullet lists inside arabic decimal lists not rendering properly */ -/* .wy-plain-list-decimal li, .rst-content .section ol li, .rst-content ol.arabic li, article ol li -.wy-plain-list-decimal ul .simple li { - list-style:disc; - margin-left:24px - } - */ +/* HamishW - add clear markup for external links */ + +a.external:after { + content: ""; + display: inline-block; + background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAYAAABWdVznAAAAV0lEQVR4Xq2QwQ2AAAwC3cmd2Kk7sRP64CEJ9qOX8OPatMc/QKppnEPhTmJh23CLiwAqIw21CybKQ28qQi37WGFYBJcwfJQpP8LlEHKyZMF0IdmF13zlAjZ/6H4wb+mUAAAAAElFTkSuQmCC); + background-repeat: no-repeat; + background-position: right top; + background-origin: border-box; + width: 12px; + height: 16px; +} + /* HamishW - some CSS for the breadcrumb (make elements inline blocks) */ diff --git a/site/source/conf.py b/site/source/conf.py index 29d2fa9fb48ae..65f934205fab2 100644 --- a/site/source/conf.py +++ b/site/source/conf.py @@ -90,9 +90,9 @@ # built documents. # # The short X.Y version. -version = '1.20' +version = '1.23' # The full version, including alpha/beta/rc tags. -release = '1.20.0' +release = '1.23.0' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. @@ -395,4 +395,5 @@ # HamishW - tell Breathe about projects. Breathe is tool to convert Doxygen to Python objects, for import into Sphinx. #breathe_projects = { "myproject": "/home/me/docproj/doxyxml/", "nutshell":"./headers/xml/", } # HamishW - Specify a default project: -#breathe_default_project = "nutshell" \ No newline at end of file +#breathe_default_project = "nutshell" + diff --git a/site/source/docs/api_reference/Filesystem-API.rst b/site/source/docs/api_reference/Filesystem-API.rst index 98e6b8bf5c475..65b04b3025656 100644 --- a/site/source/docs/api_reference/Filesystem-API.rst +++ b/site/source/docs/api_reference/Filesystem-API.rst @@ -1,7 +1,7 @@ .. _Filesystem-API: ===================================== -Filesystem API (under-construction) +File System API (under-construction) ===================================== File I/O in Emscripten is provided by the `FS `_ library. It is used internally for all of Emscripten's **libc** and **libcxx** file I/O. @@ -97,7 +97,7 @@ By default: - ``stdout`` will use a ``print`` function if one such is defined, printing to the terminal in command line engines and to the browser console in browsers that have a console (again, line-buffered). - ``stderr`` will use the same output function as ``stdout``. -.. note:: All the configuration should be done before the main ``run()`` method is executed, typically by implementing ``Module.preRun``, see :ref:`Interacting-with-code`. +.. note:: All the configuration should be done before the main ``run()`` method is executed, typically by implementing :js:attr:`Module.preRun`, see :ref:`Interacting-with-code`. .. js:function:: FS.init(input, output, error) diff --git a/site/source/docs/api_reference/emscripten.h.rst b/site/source/docs/api_reference/emscripten.h.rst index 9c048884efe42..dd8bacaf2c0af 100644 --- a/site/source/docs/api_reference/emscripten.h.rst +++ b/site/source/docs/api_reference/emscripten.h.rst @@ -68,7 +68,7 @@ Calling JavaScript From C/C++ ============================= Function pointer types for callbacks -------------------------------------- +------------------------------------ The following types are used to define function callback signatures used in a number of functions in this file. @@ -159,9 +159,10 @@ Functions :rtype: void +.. _emscripten-h-browser-execution-environment: Browser Execution Environment -================================= +============================= Functions --------- diff --git a/site/source/docs/api_reference/index.rst b/site/source/docs/api_reference/index.rst index d6379d25b09b0..a624cb8af2907 100644 --- a/site/source/docs/api_reference/index.rst +++ b/site/source/docs/api_reference/index.rst @@ -18,6 +18,8 @@ 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.* +- **Module**: **User-populated global JavaScript object, with attributes that Emscripten-generated code calls at various points in its execution.** + - **val.h**: *Embind APIs for* **HamishW** - add description - **bind.h**: *Embind APIs for* **HamishW** - add description @@ -34,6 +36,7 @@ This section lists Emscripten's public API, organised by header file. At very hi html5.h preamble.js Filesystem-API + module val.h bind.h advanced-apis diff --git a/site/source/docs/api_reference/module.rst b/site/source/docs/api_reference/module.rst new file mode 100644 index 0000000000000..c39065c663df5 --- /dev/null +++ b/site/source/docs/api_reference/module.rst @@ -0,0 +1,86 @@ +.. _module: + +==================================== +Module object (ready-for-review) +==================================== + +``Module`` is a global JavaScript object, with attributes that Emscripten-generated code calls at various points in its execution. + +Developers can provide an implementation of ``Module`` to control the execution of code. For example, to define how notification messages from Emscripten are displayed, developers implement the :js:attr:`Module.print` attribute. + +.. note:: ``Module`` is also used to provide access functions (see :js:func:`ccall`) in a way that avoids issues with function name minification at higher optimisation levels. These functions are documented as part of their own APIs. + +.. contents:: Table of Contents + :local: + :depth: 1 + + +.. _module-creating: + +Creating Module +================ + +Use :ref:`emcc's ` ``--pre-js`` option to add JavaScript code that defines (or extends) the ``Module`` object with the behaviour you need. + +When generating only JavaScript (as opposed to HTML), no ``Module`` object is created by default, and the behaviour is entirely defined by the developer. For example, creating a ``Module`` object with the following code will cause all notifications from the program to be calls to ``alert()``. + + :: + + var Module = { + 'print': function(text) { alert('stdout: ' + text) } + 'printErr': function(text) { alert('stderr: ' + text) } + }; + +.. important:: If you run closure compiler on your code (which is optional, and can be done by ``--closure 1``), you will need quotation marks around the properties of ``Module`` as in the example above (and you need to run closure on the compiled code together with the declaration of ``Module``, which is done automatically for a ``-pre-js`` file). + +When generating HTML, Emscripten creates a ``Module`` object with default methods (see `src/shell.html `_). In this case you should again use ``--pre-js``, but this time to add properties to the existing ``Module`` object, for example + + :: + + Module['print'] = function(text) { alert('stdout: ' + text) }; + + +Affecting execution +=================== + +The following ``Module`` attributes affect code execution. + + +.. js:attribute:: Module.print + + Called when something is printed to standard output (stdout) + +.. js:attribute:: Module.printErr + + Called when something is printed to standard error (stderr) + + +.. js:attribute:: Module.arguments + + The commandline arguments. The value of ``arguments`` is what is returned if compiled code checks ``argc`` and ``argv``. + + +.. js:attribute:: Module.preInit + + A function (or array of functions) that must be called before global initializers run, but after basic initialization of the JavaScript runtime. This is typically used for :ref:`File System operations ` and is called befroe C++ initializers have been run. + + +.. js:attribute:: Module.preRun + + A function (or array of functions) to call right before calling ``run()``, but after defining and setting up the environment, including global initializers. This is useful, for example, to set up directories and files using the :ref:`Filesystem-API` (since that needs the FileSystem API to be defined, but also needs to be done before the program starts to run. + + .. note:: If code needs to affect global initializers, it should instead be run using :js:attr:`preInit`. + + +.. js:attribute:: Module.noInitialRun + + If set to ``true``, ``main()`` will not be automatically called (you can do so yourself later). The program will still call global initializers, set up memory initialization, and so forth. + + +.. js:attribute:: Module.noExitRuntime + + If set to ``true``, the runtime is not shut down after ``run`` completes. Shutting down the runtime calls shutdown callbacks, for example ``atexit`` calls. If you want to be able to continue to use the code after ``run()`` finishes, it is necessary to set this. This is automatically set for you if you use an API command that implies that you want the runtime to not be shut down, for example ``emscripten_set_main_loop``. + + + + diff --git a/site/source/docs/api_reference/preamble.js.rst b/site/source/docs/api_reference/preamble.js.rst index 02e3e5eeadb6c..4291093a2ee23 100644 --- a/site/source/docs/api_reference/preamble.js.rst +++ b/site/source/docs/api_reference/preamble.js.rst @@ -4,7 +4,7 @@ preamble.js The JavaScript APIs in `preamble.js `_ provide programmatic access for interacting with the compiled C code, including: calling compiled C functions, accessing memory, converting pointers to JavaScript ``Strings`` and ``Strings`` to pointers (with different encodings/formats), and other convenience functions. -.. note:: All functions should be called though the ``Module`` object (for example: ``Module.functionName``). At optimisation ``-O2`` (and higher) function names are minified by the closure compiler, and calling them directly will fail. +.. note:: All functions should be called though the :ref:`Module ` object (for example: ``Module.functionName``). At optimisation ``-O2`` (and higher) function names are minified by the closure compiler, and calling them directly will fail. .. contents:: Table of Contents @@ -49,7 +49,7 @@ Calling compiled C functions from JavaScript :param ident: The name of the C function to be called. - :param returnType: The return type of the function. This will be one of the JavaScript 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 returnType: The return type of the function. This can be ``"number"``, ``"string"`` or ``"array"``, which correspond to the appropriate JavaScript types (use ``"number"`` for any C pointer, and ``"array"`` for JavaScript arrays and typed arrays; note that arrays are 8-bit), or for a void function it can be ``null`` (note: the JavaScript ``null`` value, not a string containing the word "null"). :param argTypes: An array of the types of arguments for the function (if there are no arguments, this can be omitted). Types are as in ``returnType``, except that ``array`` is not supported as 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 JavaScript values (as in ``returnType``). Note that string arguments will be stored on the stack (the JavaScript string will become a C string on the stack). :returns: The result of the function call as a native JavaScript value (as in ``returnType``). 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 2490bd3568c40..9c7012bbefc6e 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 @@ -32,8 +32,11 @@ Install the vs-tool plugin #. 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**. + #. Open the Environment Variables setting: + + - 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.: :: 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 53b5091a567ab..51e3852da02fe 100644 --- a/site/source/docs/building_from_source/verify_emscripten_environment.rst +++ b/site/source/docs/building_from_source/verify_emscripten_environment.rst @@ -43,9 +43,11 @@ At this point you need to :ref:`Install and activate `_ have a limitation that the timer precision is only in milliseconds. On other major browsers (IE10, Firefox 22, Chrome 28 on non-Windows), emscripten\_get\_now() will have sub-millisecond precision. -- Internet Explorer 10 and older do not support WebGL, which means trying to initialize a GL context via EGL, GLUT, SDL or similar will fail. Emscripten applications that do not depend on OpenGL can still be compiled for this browser however. See `WebGL support in different browsers `__. -- Internet Explorer 11 supports WebGL, but not all of WebGL 1.0, so certain commands, shaders etc. may not work. You may be able to limit your app to using the subset that is supported by IE11. Hopefully IE12 will support everything. -- Opera 12.16 has limited support for the W3C File API, in particular it does not support `createObjectURL functionality `_. As a result, it is not possible to use the browser image codecs on this version of Opera to decode preloaded files in the Emscripten virtual filesystem. -- OpenAL and SDL audio support in Emscripten depend on the Web Audio API. See `Web Audio API support in different browsers `_. - diff --git a/site/source/docs/coding/CodeGuidelinesAndLimitations.rst b/site/source/docs/coding/CodeGuidelinesAndLimitations.rst deleted file mode 100644 index eed4a20e6a132..0000000000000 --- a/site/source/docs/coding/CodeGuidelinesAndLimitations.rst +++ /dev/null @@ -1,57 +0,0 @@ -.. _CodeGuidelinesAndLimitations: - -============================================= -Code Guidelines And Limitations (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! - -Emscripten can work with pretty much any C/C++ code. However, it might be useful to know what types of code Emscripten compiles better than others, if you are rewriting part of the code you will be compiling. - -Code that CANNOT be compiled -============================= - -These issues are fundamental difficulties. We can get around them by emulation in theory, but it would be very slow. - -- Code that is multithreaded and uses shared state. JS has threads - web workers - but they cannot share state, instead they pass messages. -- Nonportable code that relies on endianness is problematic. It can work with USE_TYPED_ARRAYS=2, but it will not be portable! -- Nonportable code that relies on x86 alignment behavior. X86 allows unaligned reads and writes (so you can read a 16-bit value from a non-even address, i.e., which is only 8-bit aligned address, for example), but other archs do not: ARM will raise SIGILL, and when Emscripten generates JS you will get undefined behavior in this case. (If you build your code with ``SAFE_HEAP=1`` then you will get a clear runtime exception, see :ref:`Debugging`. Note: There is also a code generation mode, UNALIGNED\_MEMORY, which can support unaligned code like this - but it is very slow.) -- Nonportable code that uses low-level features of the native environment, like native stack manipulation (e.g. in conjunction with setjmp/longjmp. We support normal setjmp/longjmp, but not with stack replacing etc.) -- Nonportable code that scans registers or the stack, for example to do conservative garbage collection. A variable in a register or on the stack may be held in a JavaScript local variable, which cannot be scanned. (However, you can do conservative scanning when there is no other code on the stack, e.g. from an iteration of the main event loop.) - -Function pointer issues ---------------------------------------------------------- - -There are two general issues with function pointers: - -1. clang generates different code for C and C++ calls when a structure is passed **by value**. The two formats are incompatible in how we generate code in Emscripten, but each is compatible with itself. You should see a warning during compilation about this, and the workaround is to either not mix C and C++ in that location (just renaming a ``.c`` file to ``.cpp`` for example) or to pass the structure by reference. (More specifically, one convention is ``struct byval`` and the other is ``field a, field b``.) -2. In **asm.js** mode, there is an additional concern, with function tables. Without **asm.js**, all function pointers use a single table, but in **asm.js** each function pointer type has its own table (this allows the JS engine to know the exact type of each function pointer call, and optimize those calls much better than normally). As a consequence though, if you have a function that is say ``int (int)`` (return int, receive int) and you cast it to ``void (int)`` (no return, receive int), then the function pointer call will fail because we are looking in the wrong table. This is undefined behavior in C in any case, so it is recommended to refactor code to avoid this type of situation. You should see compilation warnings about these things. See :ref:`Asm-pointer-casts` for more information. -3. A related issue to do with function pointers is that in ``-O2`` and above we optimize the size of the separate function tables. That means that two functions can have the same function pointer so long as their type is different, and so potentially comparing function pointers of different types can give false positives. Also, it makes bugs with incorrect function pointers potentially more misleading, since there are fewer "holes" in function tables (holes would throw an error instead of running the wrong code). To check if this is causing issues, you can compile with ``-s ALIASING_FUNCTION_POINTERS=0``. - -Code that DOES compile, but might be slower than expected -========================================================== - -None of the issues here is a showstopper, but they might be slower than you expect. You probably don't need to worry about this stuff, but it might be useful to know about it. - -- 64-bit ints. Bitwise operations on these are reasonable, but math (+, -, \*, /) is emulated, very slowly. JavaScript does not have native 64-bit ints so this is unavoidable. -- 32-bit multiplication that needs all 64 bits of precision must be emulated like 64-bit integer math (JS doubles work fine up to ~52 bits). By default precise 32-bit multiplication is off as it makes a lot of common 32-bit code very slow, but if you need it you can enable it with ``-s PRECISE_I32_MUL=1``, see **src/settings.js** for more. -- 32-bit floats will end up as 64-bit doubles in JS engines. That means they might be a little slower than expected, depending on your CPU. -- memcpy/memset works, but JS engines don't optimize it very well. Native code will use SIMD on this, JS engines will not - yet. -- Exceptions and longjmp. In JS such code generally makes the JS engine turn off various optimizations. For that reason exceptions are turned off by default in ``-O1`` and above (to re-enable them, run emcc with ``-s DISABLE_EXCEPTION_CATCHING=0``). setjmp also prevents relooping around it. - -Code that MIGHT be useful to avoid -========================================================== - -Avoiding these kinds of code might be nice to do, to prevent warnings and to enable additional optimizations. But unless it is very easy for you to avoid them, just ignore this section. - -- Unions. These will trigger ``SAFE_HEAP`` warnings (like *Valgrind*), and make the ``QUANTUM_SIZE=1`` optimization impossible. -- Bitfields. Also ``SAFE_HEAP`` warnings. -- Reusing memory, that is, using the same allocated block of memory once for one kind of object, later for another. This prevents the ``QUANTUM_SIZE=1`` optimization. - -Libraries -========= - -Networking ----------- - -- Emscripten supports libc networking functions, but since JS networking is asynchronous, you must limit yourself to asynchronous (nonblocking) operations. - diff --git a/site/source/docs/coding/Garbage_Collection.rst b/site/source/docs/coding/Garbage_Collection.rst deleted file mode 100644 index 0e12a76368aec..0000000000000 --- a/site/source/docs/coding/Garbage_Collection.rst +++ /dev/null @@ -1,51 +0,0 @@ -.. _GC: - -================ -GC (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! - -Emscripten has support for a Boehm-like API for garbage collection in -C/C++ programs. This is useful if your application uses the Boehm API or -if you are compiling a language like Java into C/C++ with the goal of -then translating it to JavaScript. - -API Changes From Boehm ----------------------- - -There is no way to run another thread that interrupts the program at -intervals in order to GC. So you need to call ``GC_MAYBE_COLLECT`` at -reasonable intervals, which will do a collection if enough allocations -happened since the last one. If you compile to HTML, a timer will be -spun for this automatically and you don't need to do anything. - -You can also call ``GC_FORCE_COLLECT`` which forces a collection. This -is useful if there are times in your app when responsiveness is not -important (for example, right before starting a new level in a game). - -Mechanism ---------- - -Static allocations are scanned, but the C and JS stacks are not. We can -add such scanning at the cost of runtime performance, however, you don't -need stack scanning if you compile for browsers and call -``GC_MAYBE_COLLECT`` from a ``setInterval``, since the interval will run -when there is no relevant C or JS stack to scan (as mentioned before, -such a timer will be run for you automatically if you are compiling to -HTML). - -Pitfalls --------- - -The main risk with the current implementation is that we do not force a -collection directly from allocations. So if you allocate a lot in -between collections, you can run out of memory. You can call -``GC_FORCE_COLLECT`` to prevent this in some cases if you know relevant -parts in your code. - -Relevant Files --------------- - -- ``system/include/gc.h`` -- ``src/library_gc.js`` - diff --git a/site/source/docs/compiling/Code-Generation-Modes.rst b/site/source/docs/compiling/Code-Generation-Modes.rst index aff3b841c082c..bf695341c0a36 100644 --- a/site/source/docs/compiling/Code-Generation-Modes.rst +++ b/site/source/docs/compiling/Code-Generation-Modes.rst @@ -72,18 +72,26 @@ Exceptions can work in code compiled by emscripten, however due to how JS engine To get full exception handling support in ``-O1`` and above, run emcc with ``-s DISABLE_EXCEPTION_CATCHING=0``. Note that enabling exceptions will make the code larger due to the additional try-catch blocks (which cannot be minified very well). -Memory Compression (a.k.a QUANTUM\_SIZE == 1) +.. _code-generation-modes-quantum-size: + +Memory Compression (a.k.a QUANTUM_SIZE == 1) --------------------------------------------- -By default, Emscripten sets QUANTUM\_SIZE to 4, which means that a 'normal' element - like an int or a pointer - takes 4 'bytes'. That is the normal behavior on 32-bit systems, and allows Emscripten to properly compile a great deal of C/C++ code. However, the downside is that each int or pointer takes 4 places in the HEAP array, which is how Emscripten models the normal C/C++ memory space. This makes HEAP much bigger than it needs to be, which takes more memory, and also slows things down (for example, memset ends up clearing larger areas of memory). +By default, Emscripten sets ``QUANTUM_SIZE`` to 4, which means that a 'normal' element - like an int or a pointer - takes 4 'bytes'. That is the normal behavior on 32-bit systems, and allows Emscripten to properly compile a great deal of C/C++ code. However, the downside is that each int or pointer takes 4 places in the HEAP array, which is how Emscripten models the normal C/C++ memory space. This makes HEAP much bigger than it needs to be, which takes more memory, and also slows things down (for example, memset ends up clearing larger areas of memory). -By setting QUANTUM\_SIZE to 1, memory is 'compressed' - it is not longer isomorphic to normal C/C++ memory. So for example a structure with an int, a double, and a pointer would have a size of 3 (one for each variable), instead of the normal 16 (4 for the int and pointer, 8 for the double). This leads to significantly more optimized code, both in terms of speed and memory use. +By setting QUANTUM_SIZE to 1, memory is 'compressed' - it is not longer isomorphic to normal C/C++ memory. So for example a structure with an int, a double, and a pointer would have a size of 3 (one for each variable), instead of the normal 16 (4 for the int and pointer, 8 for the double). This leads to significantly more optimized code, both in terms of speed and memory use. -However, this is risky, since with QUANTUM\_SIZE of 1, Emscripten rewrites the .ll, trying to fix all the hardcoded places where it assumes the normal memory space. So consider this experimental for now. +However, this is risky, since with QUANTUM\_SIZE of 1, Emscripten rewrites the .ll, trying to fix all the hard-coded places where it assumes the normal memory space. So consider this experimental for now. Notes: -- With QUANTUM\_SIZE == 1, Emscripten will warn you about ptrtoint and inttoptr operations (in the generated .js file). You should make sure there are no problems in each of those cases, and perhaps modify the original C/C++ to avoid generating that kind of code (the changes are often simple). -- You can **not** use QUANTUM\_SIZE == 1 with typed arrays mode 2. The reason is that typed arrays mode 2 is C-like memory layout, whereas in QUANTUM\_SIZE == 1 we radically change the layout (ints take 1 memory address instead of 4, etc.), and the two can't be mixed. +- With QUANTUM_SIZE == 1, Emscripten will warn you about ``ptrtoint`` and ``inttoptr`` operations (in the generated .js file). You should make sure there are no problems in each of those cases, and perhaps modify the original C/C++ to avoid generating that kind of code (the changes are often simple). +- You can **not** use ``QUANTUM_SIZE == 1`` with typed arrays mode 2. The reason is that typed arrays mode 2 is C-like memory layout, whereas in ``QUANTUM_SIZE == 1`` we radically change the layout (ints take 1 memory address instead of 4, etc.), and the two can't be mixed. + +The second version of the Bullet demo in Emscripten uses ``QUANTUM_SIZE == 1``. It appears to give a speedup of around 25%. + + + +.. todo:: **HamishW** In :ref:`CodeGuidelinesAndLimitations` it mentions a code generation mode UNALIGNED_MEMORY - perhaps add? -The second version of the Bullet demo in Emscripten uses QUANTUM\_SIZE == 1. It appears to give a speedup of around 25%. +.. todo:: **HamishW** SAFE_HEAP gets mentioned. Anything we can link to? diff --git a/site/source/docs/getting_started/FAQ.rst b/site/source/docs/getting_started/FAQ.rst index 5046ed0b8901f..bfa0073e00b98 100644 --- a/site/source/docs/getting_started/FAQ.rst +++ b/site/source/docs/getting_started/FAQ.rst @@ -1,190 +1,300 @@ .. _FAQ: +================================== +FAQ (under-construction) +================================== + +This FAQ has many frequently asked questions from IRC and the mailing list. + +How do I compile code? +====================== + +See the :ref:`Tutorial` and :ref:`emccdoc`. + +I get many errors building basic code and the tests? +==================================================== + +All the tests in the :ref:`Emscripten test suite ` are known to build and pass on the **master** branch, so if these are failing it is likely that there is some problem with your environment. + +First call ``./emcc -v``, which runs basic sanity checks and prints out useful environment information. If that doesn't help, follow the instructions in :ref:`verifying-the-emscripten-environment`. + +You might also want to go through the :ref:`Tutorial` again, as this is updated as Emscripten changes. + + +I tried something and it doesn't work? +====================================== + +If something doesn't work (for example a :ref:`compiler flag `, a *libc* function, etc.) then first search the comprehensive documentation on this site. + +Next check if there is a test for the failing functionality in the :ref:`Emscripten test suite ` (run ``grep -r`` in **tests/**). **All** the tests are known to pass on the master branch, so they provide concrete "known-good" examples of how various options and code are used. + + +Do I need to change my build system to use Emscripten? +====================================================== + +In most cases you will be able to use your project's current build system with Emscripten. See :ref:`Building-Projects`. + + + +Code compilation is slow? +========================= + +Emscripten makes some trade-offs that make the generated code faster and smaller, at the cost of longer compilation times. For example, we build parts of the standard library along with your code which enables some additional optimizations, but takes a little longer to compile. + +.. note:: You can determine what compilation steps take longest by compiling with ``EMCC_DEBUG=1`` in the environment and then reviewing the debug logs (by default in ``/tmp/emscripten_temp``). Note that compiling in debug mode takes longer than normal, because we print out a lot of intermediate steps to disk. + +The main tips for improving build time are: + +- Create fully optimized builds less frequently — use ``-O0`` during frequent development iterations (or don't specify an optimization level). + + - Compiling with higher levels of optimization can in some cases be noticeably slower: ``-O2`` is slower than ``-O1``, which is in turn slower than ``-O0``. + - Compiling with ``-O3`` is **especially** slow — this can be mitigated by also enabling ``-s AGGRESSIVE_VARIABLE_ELIMINATION=1`` (removing variables makes the ``-O3`` regalloc easier). + +- Compile without :ref:`line number debug information ` (use ``-O1`` or ``-g0`` instead of ``-g``): + + - Currently builds with line-number debug information are slow (see issue `#216 `_). Stripping the debug information significantly improves compile times. + +- Compile on a machine with more cores: + + - Emscripten can run some passes in parallel (specifically, the JavaScript optimisations). Increasing the number of cores results in an almost linear improvement. + - Emscripten will automatically use more cores if they are available. You can control how many cores are used with ``EMCC_CORES=N`` (this is useful useful if you have many cores but relatively less memory). + + + +My code runs slowly? +===================== + +Make sure you optimize code by building with ``-O2`` (even more :ref:`aggressive optimization ` is available, at the cost of significantly increased compilation time). + +.. note: This is necessary both for each source file, and for the final stage of linking and compiling to JavaScript. For more information see :ref:`Building-Projects` and :ref:`Optimizing-Code`. + + +My code is large? ================= -FAQ (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! +Make sure you build with ``-O2`` so code is optimized and minified. You should also set up gzip compression on your webserver, which all browsers now support. + +.. note:: You can :ref:`use the closure compiler ` to reduce code size even further (``--closure 1``). However that will require that your code be prepared for closure compiler advanced optimizations, including proper exports and so forth. It is usually not worth the effort over an optimized build and supporting gzip on your webserver. + + + +Compiling code that works on another machine gives me errors? +============================================================= + +Make sure you are using the Emscripten bundled system headers. Using :ref:`emcc ` will do so by default, but problems may occur if you use your local system headers with ``emcc`` or compile into LLVM bitcode yourself. +My large codebase runs well, but startup time is significant? +============================================================= -- **Q.** How do I compile code? +Make sure that you are running an :ref:`optimized build ` (smaller builds are faster to start up). If the sheer code size is causing the slow startup, you can try `Outlining: a workaround for JITs and big functions `_. - **A.** See the :ref:`Tutorial`. +Network latency is also a possible factor in startup time. Consider putting the file loading code in a separate script element from the generated code so that the browser can start the network download in parallel to starting up the codebase (run the :ref:`file packager ` and put file loading code in one script element, and the generated codebase in a following script element). -- **Q.** I get lots of errors building the tests or even simple hello world type stuff? - **A.** Try to run ``emcc -v``, which prints out some helpful information and runs some sanity checks. You can also try ``emcc --clear-cache`` to empty the compiler's internal cache, which will then be rebuilt next time it is used. If none of those help or give an idea of what could be the matter, then some common problems to check for are: +My code fails to compile with an error message about inline assembly (or ``{"text":"asm"}``)? +============================================================================================= - - Typos in the paths in ``~/.emscripten``. - - Using older versions of Node or JS engines. Use the versions mentioned in the :ref:`Tutorial`. - - Using older versions of LLVM. See the :ref:`Emscripten-SDK` page for which version of LLVM is supported. Using other builds might not work. If you are using fastcomp, see :ref:`LLVM-Backend` for the proper repos for LLVM and clang that you should be using. - - Not having ``python2`` in your system. For compatibility with systems that install python 2.x alongside 3.x (increasingly common), we look for ``python2``. If you only have python 2.x installed, make ``python2`` be a link to ``python``. Or, instead you can invoke our python scripts directly, for example - ``python emcc`` instead of ``./emcc``. +Emscripten cannot compile inline assembly code (because it is CPU specific, and Emscripten is not a CPU emulator). - You might also want to go through the :ref:`Tutorial` again, if it's been a while since you have (we update it when things change). +You will need to find where inline assembly is used, and disable it or replace it with platform-independent code. -- **Q.** I tried something and it doesn't work? +.. note:: Emscripten automatically unsets the following ``#define`` values, as these are commonly set in projects to enable platform dependent code (inline assembly): - **A.** Emscripten has an extensive test suite. If you try something (a compiler flag, a libc function, etc.) and it fails, often the best thing is to ``grep -r`` in ``tests/`` to see if there is a test for it. On the master branch, **all** tests are known to pass. The tests can therefore both show you what works, and also they give concrete examples for how to use things, which can be helpful in addition to the docs. + :: -- **Q.** Can I compile my project using Emscripten? Do I need a new build system? + #undef __i386__ + #undef __x86_64__ - **A.** You can in most cases very easily use your project's current build system with Emscripten. See :ref:`Building-Projects`. -- **Q.** My code cannot access a file that is right there in the same directory? +.. _faq-my-html-app-hangs: - **A.** Emscripten-generated code cannot by default access local files on your machine like a native application. See :ref:`Filesystem-Guide` - for details: you can in node allow such access, and in other platforms you can use preloading to work around lack of synchronous file IO. +My HTML app hangs? +================== -- **Q.** My code compiles slowly. +The browser event model uses *co-operative multitasking* — each event has a "turn" to run, and must then return control to the browser event loop so that other events can be processed. A common cause of HTML pages hanging is JavaScript that does not complete and return control to the browser. - **A.** Emscripten makes some tradeoffs that make the generated code faster and smaller, at the cost of longer compilation times. For example, we build parts of the standard library along with your code which enables some additional optimizations, but takes a little longer to compile. +Graphical C++ apps typically have an "infinite" main loop in which event handling, processing and rendering is done, followed by a delay to keep the frame-rate right (``SDL_DELAY`` in SDL apps). As the main loop does not complete it cannot return control to the browser, and the app will hang. - Emscripten can run some passes in parallel (specifically, the JS opts), and will do so automatically, so running on a machine with more cores can give you almost a linear speedup (so doubling the amount of cores can almost halve the amount of time it takes to build and so forth). To see details of how work is parallelized, compile with ``EMCC_DEBUG=1`` in the environment (note though that in that debug mode compilation takes longer than normal, because we print out a lot of intermediate steps to disk, by default to ``/tmp/emscripten_temp``, but it's still useful to see which stages are slowing you down). You can affect how many cores are using with ``EMCC_CORES=N``, which can be useful if you have many cores but relatively less memory. +Apps that use an infinite loop should be re-coded to put the actions for a single iteration of the main loop are put into a single "finite" function. In the native build this function can be run in an infinite loop as before. In the Emscripten build it is set as the :ref:`main loop function ` and will be called by the browser at a specified frequency. - Note that optimization can in some cases be noticeably slower than unoptimized code, ``-O1`` is slower than ``-O0``, which in turn is slower than ``-O2`` (in return, though, they greatly improve the speed of the generated code). It might be useful to use ``-O0`` (or not specify an optimization level) during quick development iterations and to do fully optimized builds less frequently. Note that ``-O3`` is **especially** slow (you can mitigate the ``-O3`` slowness by also enabling ``-s AGGRESSIVE_VARIABLE_ELIMINATION=1``, as it removes variables which makes the ``-O3`` regalloc easier). +There is more information on this topic in :ref:`Emscripten-Browser-Environment`. - Currently builds with line-number debug info (where the source code was compiled with ``-g``) are slow, see issue #216. Stripping the debug info leads to much faster compile times. -- **Q.** My code runs slowly. +.. _faq-how-run-event-loop: - **A.** Make sure you build with ``-O2`` so code is optimized. **This is necessary both for each source file, and for the final stage of linking and compiling to JS**, see more details :ref:`Building-Projects`. See :ref:`Optimizing-Code` for more info. +How do I run an event loop? +=========================== -- **Q.** My code is large. +To run a C function repeatedly, use :c:func:`emscripten_set_main_loop` (this is discussed in :ref:`Emscripten-browser-environment`). The related functions in :ref:`emscripten.h ` are also useful, allowing you to add events that block the main loop, etc. - **A.** Make sure you build with ``-O2`` so code is optimized, which includes minification to reduce size. You should also set up gzip compression on your webserver, which all browsers now support. +To respond to browser events use the SDL API in the normal way. There are examples in the SDL tests (search for SDL in **tests/runner.py**). - You can use closure compile to reduce code size even more with ``--closure 1``, however that will require that your code with with closure compiler advanced optimizations, including proper exports and so forth. It is usually not worth the effort over an optimized build+server gzip. +See also: :ref:`faq-my-html-app-hangs` -- **Q.** When I compile code that should work, I get odd errors in Emscripten about various things. I get different errors (or it works) on another machine. - **A.** Make sure you are using the Emscripten bundled system headers. Using ``emcc`` will do so by default, but if you compile into LLVM bitcode yourself, or you use your local system headers even with ``emcc``, problems can happen. + +My SDL app doesn't work? +======================== -- **Q.** My large codebase runs ok, but the time it takes to start up is significant. What can I do to improve that? +See the SDL automatic tests for working examples: ``python tests/runner.py browser``. - **A.** First, make sure you are running an optimized build (which will be much smaller and faster to start up). Then, if the sheer code size is causing the slow startup, you can try the `outlining option in emscripten `__. - Another possible factor is network latency. If you load data off the network and also have a big codebase, try to put the file loading code in a separate script element - that is, run the file packager (``tools/file_packager.py``) and put its code in one script element, and in another script element after it put the generated codebase. That will allow the browser to start the network download immediately, so it can run in parallel to the browser parsing and starting up the codebase. +How do I link against system libraries like SDL, boost, etc.? +============================================================= -- **Q.** My code fails to compile, the error includes something about inline assembly (or ``{"text":"asm"}``). +System libraries that are included with Emscripten are automatically linked when you compile (just the necessary parts). This includes *libc*, *libc++* (C++ standard library) and SDL. - **A.** Emscripten cannot compile inline assembly code, which is CPU specific, because Emscripten is not a CPU emulator. +Libraries which are not included with Emscripten (like Boost) must be compiled and linked with the program just as if they were a module in the project. For example, see how `BananaBread links in libz `_. - Many projects have build options that generate only platform-independent code, without inline assembly. That should be used for Emscripten. For example, the following might help (and are done automatically for you by ``emcc``): +Another option is to implement needed as a JavaScript library (see ``--js-library`` in :ref:`emcc `). Emscripten itself does this for *libc* (not including *malloc*) and SDL (but not *libc++* or *malloc*). - :: +.. note:: - #undef __i386__ - #undef __x86_64__ + - Unlike other compilers, you don't need ``-lSDL`` to include SDL (specifying it will do no harm). + - In the specific case of *Boost*, if you only need the boost headers, you don't need to compile anything. - Since when no CPU-specific ``#define`` exists, many projects will not generate CPU specific code. In general though, you will need to find where inline assembly is generated, and how to disable that. -- **Q.** How do I run an event loop? +How can my compiled program access files? +================================================================== - **A.** To run a C function repeatedly, use :c:func:`emscripten_set_main_loop` (**emscripten.h**). The other functions in that file are also useful, they let you do things like add events that block the main loop, etc. +Emscripten uses a virtual file system that may be preloaded with data or linked to URLs for lazy loading. See the :ref:`Filesystem-Guide` for more details. - To respond to browser events and so forth, use the SDL API normally. See the SDL tests for examples (look for SDL in ``tests/runner.py``). - See also the next question. +My code cannot access a file in the same directory? +=================================================== -- **Q.** My HTML app hangs. +Emscripten-generated code running *in the browser* cannot access files in the local file system. Instead you can use :ref:`preloading ` and :ref:`embedding ` to work around lack of synchronous file IO. See :ref:`Filesystem-Guide` for more information. - **A.** Graphical C++ apps typically have a main loop that is an infinite loop, in which event handling is done, processing and rendering, then SDL_Delay. However, in JS there is no way for SDL_Delay to actually return control to the browser event loop. To do that, you must exit the current code. See - :ref:`Emscripten-Browser-Environment`. +It is possible to allow access to local file system for code running in *node.js*. -- **Q.** My SDL app doesn't work. - **A.** See the SDL automatic tests for working examples: ``python tests/runner.py browser``. +.. _faq-when-safe-to-call-compiled-functions: + +How can I tell when the page is fully loaded and it is safe to call compiled functions? +======================================================================================= + +Calling a compiled function before a page has fully loaded can result in an error, if the function relies on files that may not be present (for example the :ref:`.mem ` file and :ref:`preloaded ` files are loaded asynchronously). + +The easiest way to find out when loading is complete is to add a ``main()`` function, and within it call a JavaScript function to notify your code that loading is complete. + +.. note:: The ``main()`` function is called after startup is complete as a signal that it is safe to call any compiled method. + +For example if ``allReady()`` is a JavaScript function you want called when everything is ready, you can do: + +:: -- **Q.** How do I link against system libraries like SDL, boost, etc.? + #include - **A.** System libraries that are included with emscripten - libc, libc++ (C++ standard library) and SDL - are automatically included when you compile (and just the necessary parts of them). You don't even need ``-lSDL``, unlike other compilers (but ``-lSDL`` won't hurt either). + int main() { + EM_ASM( allReady() ); + } - Other libraries not included with emscripten, like boost, you would need to compile yourself and link with your program, just as if they were a module in your project. For example, see how `BananaBread links in libz `_. - (Note that in the specific case of boost, if you only need the boost headers, you don't need to compile anything.) - Another option for libraries not included is to implement them as a JS library, like emscripten does for libc (minus malloc) and SDL (but not libc++ or malloc). See ``--js-library`` in emcc. -- **Q.** How can my compiled program access files? +Functions in my C/C++ source code vanish when I compile to JavaScript, and/or I get ``No functions to process..``? +================================================================================================================== - **A.** Emscripten uses a virtual file system that may be preloaded with data or linked to URLs for lazy loading. See the :ref:`Filesystem-Guide` for more details. +By default, Emscripten does dead code elimination of functions that are not called from the compiled code. While this does minimize code size, it can remove functions that you plan to call yourself (outside of the compiled code). -- **Q.** Functions in my C/C++ source code vanish when I compile to JavaScript, and/or I get ``No functions to process``..? +To make sure a function is accessible to be called from normal JavaScript it must be added to the `EXPORTED_FUNCTIONS `_ using the *emcc* command line. For example, to prevent functions ``my_func()`` and ``main()`` from being removed/renamed, run *emcc* with: ``-s EXPORTED_FUNCTIONS="['_main', '_my_func']"``. - **A.** By default Emscripten does dead code elimination to minimize code size. However, it might end up removing functions you want to call yourself, that are not called from the compiled code (so the LLVM optimizer thinks they are unneeded). You can run emcc with ``-s LINKABLE=1`` which will disable link-time optimizations and dead code elimination, but this makes the code larger and less optimized than it could be. Instead, you should prevent specific functions from being eliminated by adding them to EXPORTED_FUNCTIONS (see ``src/settings.js``), for example, run emcc with something like ``-s EXPORTED_FUNCTIONS="['_main', '_my_func']"`` in order to keep my_func from being removed/renamed (as well as ``main()``)). Note that this assumes my_func is a C function, otherwise you would need to write out the C++ name mangling. +.. note:: - It can be useful to compile with ``EMCC_DEBUG=1`` (``EMCC_DEBUG=1 emcc ..``). Then the compilation steps are split up and saved in ``/tmp/emscripten_temp``. You can then see at what stage the code vanishes (you will need to do ``llvm-dis`` on the bitcode stages to read them, or ``llvm-nm``, etc.). + - Exported functions need to be C functions (to avoid C++ name mangling). + - Running *emcc* with ``-s LINKABLE=1`` will also disable link-time optimizations and dead code elimination. This is not recommended as it makes the code larger and less optimized. - In summary, the general procedure for making sure a function is accessible to be called from normal JS later is (1) make a C function interface (to avoid C++ name mangling), (2) run emcc with ``-s EXPORTED_FUNCTIONS="['_main', '_yourCfunc']"`` to make sure it is kept alive during optimization. +If your function is used in other functions, LLVM may inline it and it will not show up. Prevent inlining by defining the function with :c:type:`EMSCRIPTEN_KEEPALIVE`: :: - If your function is used in other functions, LLVM may inline it and it will not show up. In this case you can define it with ``void EMSCRIPTEN_KEEPALIVE yourCfunc() {..}`` which will preserve it (see :c:type:`EMSCRIPTEN_KEEPALIVE`). + void EMSCRIPTEN_KEEPALIVE yourCfunc() {..} - Another possible issue here is linking of ``.a`` files. ``.a`` files link only the internal object files needed by previous files on the command line, so the order of files matters, and this can be surprising. If you are linking ``.a`` files, make sure they are at the end of the list of files, and in the right order amongst themselves, or just use ``.so`` files instead in your project. +Another possible issue here is linking of ``.a`` files. ``.a`` files link only the internal object files needed by previous files on the command line, so the order of files matters, and this can be surprising. If you are linking ``.a`` files, make sure they are at the end of the list of files, and in the right order amongst themselves, or just use ``.so`` files instead in your project. - Note: In LLVM 3.2 dead code elimination is significantly more aggressive. All functions not kept alive through EXPORTED_FUNCTIONS will be potentially eliminated. Make sure to keep the things you need alive using one or both of those methods. +Note: In LLVM 3.2 dead code elimination is significantly more aggressive. All functions not kept alive through EXPORTED_FUNCTIONS will be potentially eliminated. Make sure to keep the things you need alive using one or both of those methods. -- **Q.** The FS API is not available when I build with closure? +.. tip:: It can be useful to compile with ``EMCC_DEBUG=1`` set for the environment (``EMCC_DEBUG=1 emcc ..`` on Linux, ``set EMMCC_DEBUG=1`` on Windows) which splits up the compilation steps and saves them in ``/tmp/emscripten_temp``. You can then see at what stage the code vanishes (you will need to do ``llvm-dis`` on the bitcode stages to read them, or ``llvm-nm``, etc.). - **A.** Closure compiler will minify the FS API code. To write code that uses it, it must be optimized **with** the FS API code by closure. To do that, use emcc's ``--pre-js`` option, see ``emcc --help``. +**HamishW** When use KEEPALIVE, when use EXPORTED FUNCTIONS. Note about LLVM3.2 being more aggressive a bit confusing in context. -- **Q.** My code breaks with ``-O2 --closure 1``, giving odd errors..? - **A.** The likely problem is that Closure Compiler minifies variable names. Names like ``i,j,xa`` can be generated, and if other code has such variables in the global scope, bad things can happen. +The File System API is not available when I build with closure? +=============================================================== - To check if this is the problem, compile with ``-O2`` (without ``--closure 1``). If that works, name minification might be the problem. If so, wrapping the generated code in a closure should fix it. (Or, wrap your other code in a closure, or stop it from using small variable names in the global scope, you might be using such variables by mistake by forgetting a ``var`` and assigning to a variable - which makes it be in the global scope.) +The :term:`Closure Compiler` will minify the File Server API code. Code that uses the file system must be optimized **with** the File System API, using emcc's ``--pre-js`` :ref:`option `. - To 'wrap' code in a closure, do something like this: + +My code breaks and gives odd errors when using ``-O2 --closure 1``? +=================================================================== + +The :term:`Closure Compiler` minifies variable names, which results in very short variable names like ``i``, ``j``, ``xa``. If other code declares variables with the same names in global scope, this can cause serious problems. + +This is likely to be the cause if you can successfully compile with ``-O2`` set but **not** ``--closure 1``. + +One solution is to stop using small variable names in the global scope (often this is a mistake - forgetting to use ``var`` when assigning to a variable). + +Another alternative is to wrap the generated code (or your other code) in a closure, as shown: :: - var CompiledModule = (function() { - .. GENERATED CODE .. - return Module; - })(); + var CompiledModule = (function() { + .. GENERATED CODE .. + return Module; + })(); + + +I get ``undefined is not a function`` or ``NAME is not a function``? +==================================================================== + +The likely cause is an undefined function — a function that was referred to, but not implemented or linked in. If you get ``undefined``, look at the line number to see the function name. + +Emscripten by default does *not* give fatal errors on undefined symbols, so you can get *runtime* errors like these (because in practice for many codebases it is easiest to get them working without refactoring them to remove all undefined symbol calls). If you prefer compile-time notifications, run *emcc* with ``-s WARN_ON_UNDEFINED_SYMBOLS=1`` or ``-s ERROR_ON_UNDEFINED_SYMBOLS=1``. + +Aside from just forgetting to link in a necessary object file, one possible cause for this error is inline functions in headers. If you have a header with ``inline int my_func() { .. }`` then *Clang* may not actually inline the function (since inline is just a hint), and also not generate code for it (since it's in a header). The result is that the generated bitcode and JavaScript will not have that function implemented. One solution is to add ``static`` to the function declaration, which forces code to be generated in the object file: ``static inline int my_func() { .. }``. + + +I get an odd python error complaining about libcxx.bc or libcxxabi.bc? +====================================================================== + +A possible cause it that building *libcxx* or *libcxxabi* failed. Go to **system/lib/libcxx** (or libcxxabi) and do ``emmake make`` to see the actual error. Or, clean the Emscripten cache (``./emcc --clear-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. -- **Q.** I get ``undefined is not a function`` or ``NAME is not a function``..? +Another possible cause of this error is the lack of ``make``, which is necessary to build these libraries. If you are on Windows, you need *cmake*. - **A.** The likely cause is an undefined function - something that was referred to, but not implemented or linked in. If you get ``undefined``, look at the line number to see the function name. - Emscripten by default does *not* give fatal errors on undefined symbols, so you can get runtime errors like these (because in practice in many codebases it is easiest to get them working without refactoring them to remove all undefined symbol calls). If you prefer compile-time notifications, run emcc with - ``-s WARN_ON_UNDEFINED_SYMBOLS=1`` or ``-s ERROR_ON_UNDEFINED_SYMBOLS=1``. +Running LLVM bitcode generated by emcc through **lli** breaks with errors about ``impure_ptr``? +=============================================================================================== - Aside from just forgetting to link in a necessary object file, one possible cause for this error is inline functions in headers. If you have a header with ``inline int my_func() { .. }`` then clang may not actually inline the function (since inline is just a hint), and also not generate code for it (since it's in a header), so the generated bitcode and js will not have that function implemented. One solution is to add ``static``, that is ``static inline int my_func() { .. }`` which forces code to be generated in the object file. +.. note:: `lli `_ is not maintained, and has odd errors and crashes. We do include **tools/nativize_llvm.py** (which compiles bitcode to a native executable) but it will also hit the ``impure_ptr`` error. -- **Q.** I get an odd python error complaining about libcxx.bc or libcxxabi.bc..? +The issue is that *newlib* uses ``impure_ptr`` code, while *glibc* uses something else. The result is that bitcode built with the Emscripten will not run locally unless your machine uses *newlib* (basically, only embedded systems). - **A.** Possibly building libcxx or libcxxabi failed. Go to system/lib/libcxx (or libcxxabi) and do ``emmake make`` to see the 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. +The ``impure_ptr`` error only occurs during explicit use of ``stdout`` etc., so ``printf(..)`` will work, but ``fprintf(stdout, ..)`` will not. **Usually it is simple to modify your code to avoid this problem.** - 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``. -- **Q.** Running LLVM bitcode generated by emcc through ``lli`` breaks with errors about ``impure_ptr`` stuff..? +I get a stack size error when optimizing: ``RangeError: Maximum call stack size exceeded`` or similar? +====================================================================================================== - **A.** First of all, lli is not maintained (sadly) and has odd errors and crashes. However there is ``tools/nativize_llvm.py`` which compiles bitcode to a native executable. It will also hit the ``impure_ptr`` error though. +You may need to increase the stack size for :term:`node.js`. - The issue is that newlib uses that impure pointer stuff, while glibc uses something else. So bitcode build with the emscripten SDK (which emcc does) will not run locally, unless your machine uses newlib (which basically only embedded systems do). The impure_ptr stuff is limited, however, it only applies to explicit use of ``stdout`` etc. So ``printf(..)`` will work, but ``fprintf(stdout, ..)`` will not. So often it is simple to modify your code to not hit this problem. +On Linux and Mac OS X, you can just do ``NODE_JS = ['node', '--stack_size=8192']`` in the :ref:`compiler-configuration-file`. On Windows, you will also need ``--max-stack-size=8192``, and also to run ``editbin /stack:33554432 node.exe``. -- **Q.** I get a stack size error when optimizing (``RangeError: Maximum call stack size exceeded`` or similar)? - **A.** You may need to increase the stack size for node. On linux and mac, you can just do ``NODE_JS = ['node', '--stack_size=8192']`` or such (in ``~/.emscripten``). On windows, you will also need ``--max-stack-size=8192``, and also to run ``editbin /stack:33554432 node.exe``. +I get ``error: cannot compile this aggregate va_arg expression yet`` and it says ``compiler frontend failed to generate LLVM bitcode, halting`` afterwards. +============================================================================================================================================================================================= -- **Q.** I get ``error: cannot compile this aggregate va_arg expression yet`` and it says ``compiler frontend failed to generate LLVM bitcode, halting`` afterwards. +This is a limitation of the le32 frontend in :term:`Clang`. You can use the x86 frontend instead by compiling with ``EMCC_LLVM_TARGET=i386-pc-linux-gnu`` in the environment (however you will lose the advantages of le32 which includes better alignment of doubles). - **A.** This is a limitation of the le32 frontend in clang. You can use the x86 frontend instead by compiling with ``EMCC_LLVM_TARGET=i386-pc-linux-gnu`` in the environment (however you will lose the advantages of le32 which includes better alignment of doubles). + +Build from source fails during linking (at 100%) +================================================ -- **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? +Building :ref:`Fastcomp from source ` (and hence the SDK) can fail at 100% progress. This is due to out of memory in the linking stage, and is reported as error: ``collect2: error: ld terminated with signal 9 [Killed]``. - **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 +The solution is to ensure the system has sufficient memory. On Ubuntu 14.04,1 LTS 64bit use at least 6Gb. - :: - #include - int main() { - EM_ASM( allReady() ); - } + +The name of the project sounds weird to me +========================================== -- **Q.** The name of the project sounds weird to me. +I don't know why; it's a perfectly `cromulent `_ word! - **A.** I don't know why; it's a perfectly `cromulent `_ word! diff --git a/site/source/docs/getting_started/Tutorial.rst b/site/source/docs/getting_started/Tutorial.rst index 0a32173d14e63..0c6989ad8f9a6 100644 --- a/site/source/docs/getting_started/Tutorial.rst +++ b/site/source/docs/getting_started/Tutorial.rst @@ -1,32 +1,30 @@ .. _Tutorial: -============================================ -Emscripten Tutorial (under-construction) -============================================ - -**Using Emscripten is, at a base level, fairly simple. This tutorial takes you through the steps needed to compile your first Emscripten examples from the command line. It also shows how to preload files and set the compiler optimization flags.** +====================================== +Emscripten Tutorial (ready-for-review) +====================================== -.. note:: We don't cover it in this tutorial, but Emscripten is also integrated with Microsoft Visual Studio 2010. +**Using Emscripten is, at a base level, fairly simple. This tutorial takes you through the steps needed to compile your first Emscripten examples from the command line. It also shows how to work with files and set the main compiler optimization flags.** - The :term:`vs-tool` plugin is automatically deployed by the :term:`Windows NSIS Installer Emscripten SDK` if *Visual Studio 2010* is present on your system. This adds an 'Emscripten' configuration to the list of available Solution Configurations in Visual Studio. Activate this configuration for a solution/project to make Visual Studio run the project build through Emscripten, producing **.html** or **.js** output depending on the configured project properties. +.. tip:: Check out :ref:`this topic ` if you want to use *Emscripten* with Microsoft *Visual Studio 2010*. 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). +Make sure you have :ref:`downloaded and installed ` Emscripten (the exact approach for doing this will depend your operating system: Linux, Windows, or Mac). -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:`emccdoc`. 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* or *clang*. 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``). +.. note:: On Windows the tool is called using the slightly different syntax: ``emcc`` or ``em++``. The remainder of this tutorial uses the Linux approach (``./emcc``). For the next section you will need to open a command prompt: - On Linux or Mac OS X, open a *Terminal*. - On Windows open the :ref:`Emscripten Command Prompt `, a command prompt that has been pre-configured with the correct system paths and settings to point to the :term:`active ` Emscripten tools. To access this prompt, type **Emscripten** in the Windows 8 start screen, and then select the **Emscripten Command Prompt** option. -Navigate with the command prompt to the :term:`SDK root directory` for your target SDK. This is an SDK-version-specific folder below the :term:`emsdk root directory`, e.g.: **\\emscripten\\1.20.0\\**. +Navigate with the command prompt to the :term:`SDK root directory` for your target SDK. This is an SDK-version-specific folder below the :term:`emsdk root directory`: **/emscripten/1.20.0/**. -.. warning:: Emscripten test code must be built from the "SDK Root" above (some of the code is dependent on file locations, and will build but not run if compiled from another location). +.. note:: The tests should be compiled from the "SDK Root" directory. This is required because some tests load files, and the locations of these files within Emscripten's virtual file system root is relative to the current directory at build time. Verifying Emscripten @@ -34,26 +32,25 @@ Verifying Emscripten If you haven't run Emscripten before, run it now with: :: - emcc -v + ./emcc -v If the output contains warnings about missing tools, see :ref:`verifying-the-emscripten-environment` for debugging help. Otherwise continue to the next sections where we'll build some code. Running Emscripten -====================================== +================== -You can now compile your first C++ file to JavaScript! +You can now compile your first C++ file to JavaScript. -First, lets have a look at the file to be compiled: **hello_world.cpp**. This is the simplest test code in the SDK, and as you can see, all it does is print "hello, world!" to the console and then exit. +First, lets have a look at the file to be compiled: **hello_world.c**. This is the simplest test code in the SDK, and as you can see, all it does is print "hello, world!" to the console and then exit. -.. include:: ../../../../tests/hello_world.cpp +.. include:: ../../../../tests/hello_world.c :literal: - -To build the JavaScript version of this code we simply specify the C++ file after *emcc*: :: +To build the JavaScript version of this code, simply specify the C++ file after *emcc*: :: - emcc tests/hello_world.cpp + ./emcc tests/hello_world.c There should now be an **a.out.js** file in the current directory. Run it using :term:`node.js`: @@ -68,19 +65,18 @@ This prints "hello, world!" to the console, as expected. - Generating HTML -====================================== +=============== -Emscripten can also generate HTML for testing embedded JavaScript. To generate HTML, use the ``-o`` (output) command and specify an html file as the target file: :: +Emscripten can also generate HTML for testing embedded JavaScript. To generate HTML, use the ``-o`` (:ref:`output `) command and specify an html file as the target file: :: - emcc tests/hello_world.cpp -o hello.html + ./emcc tests/hello_world.c -o hello.html Open the web page in a web browser. As you can see, the framework defines a text area for displaying the output of the ``printf()`` calls in the native code. -The HTML isn't limited just to just displaying text. You can also use the SDL API to show a colored cube in a Canvas element (on browsers that support it). For an example, build the **hello_world_sdl.cpp** test code and then refresh the browser: :: +The HTML output isn't limited just to just displaying text. You can also use the SDL API to show a colored cube in a Canvas element (on browsers that support it). For an example, build the `hello_world_sdl.cpp `_ test code and then refresh the browser: :: - emcc tests/hello_world_sdl.cpp -o hello.html + ./emcc tests/hello_world_sdl.cpp -o hello.html The source code for the second example is given below: @@ -89,15 +85,15 @@ The source code for the second example is given below: Using files -====================================== +=========== -Your C/C++ code can access files using the normal libc API (stdio: ``fopen``, etc.). +.. note:: Your C/C++ code can access files using the normal libc stdio API (``fopen``, ``fclose``, etc.) -JavaScript is usually run in the sandboxed environment of a web browser, without direct access to the local filesystem. Emscripten simulates a file system which you can access from the compiled code using the normal libc API. Files that you want to access should be :ref:`preloaded ` or :ref:`embedded ` into the virtual file system. +JavaScript is usually run in the sandboxed environment of a web browser, without direct access to the local file system. Emscripten simulates a file system which you can access from your compiled C/C++ code using the normal libc stdio API. -Preloading generates a virtual filesystem that corresponds to the filesystem structure at *compile* time, relative to the current directory. +Files that you want to access should be :ref:`preloaded ` or :ref:`embedded ` into the virtual file system. Preloading (or embedding) generates a virtual file system that corresponds to the file system structure at *compile* time, *relative to the current directory*. -.. todo:: **HamishW** When filesystem guide updated may be a better link for preloading and embedding than the emcc links above. These might even be better as term links in glossary. +.. todo:: **HamishW** When filesystem guide updated may be a better link for preloading and embedding than the *emcc* links above. These might even be better as term links in glossary. The `hello_world_file.cpp `_ example shows how to load a file (both the test code and the file to be loaded shown below): @@ -107,7 +103,11 @@ The `hello_world_file.cpp `_. We compile the example from the directory "above" **tests** to ensure that the text file is stored at this location in the virtual filesystem. +.. note:: The example expects to be able to load a file located at **tests/hello_world_file.txt**: :: + + FILE *file = fopen("tests/hello_world_file.txt", "rb"); + + We compile the example from the directory "above" **tests** to ensure that virtual filesystem is created with the correct structure relative to the compile-time directory. The following command is used to preload the data file. The ``--preload-file`` option will automatically preload the file before running the compiled code. This is useful because loading data from the network cannot be done synchronously in browsers outside Web Workers. :: @@ -116,38 +116,25 @@ The following command is used to preload the data file. The ``--preload-file`` o Open ``hello.html`` in the *Firefox web browser* to see the data from **hello_world_file.txt** being displayed. -.. note:: Unfortunately *Chrome* and *Internet Explorer* do not support ``file://`` :term:`XHR` requests, and can't directly load the local file in which preloaded data is stored. For these browsers you'll need to serve the files using a webserver. The easiest way to do this is to use the python **SimpleHTTPServer** (in the current directory do ``python -m SimpleHTTPServer 8080`` and then open ``localhost:8080/hello.html``). - ----- - -For an example of how to load files with SDL, check out `tests/hello_image_sdl.c `_: - -.. include:: ../../../../tests/hello_image_sdl.c - :literal: - -The source code expects a file **screenshot.jpg** in the current directory. As discussed above, this means that we need to compile the source and preload from the same directory that contains the screenshot. Change to the **tests/** directory and run: :: - - emcc hello_image_sdl.c --preload-file screenshot.jpg -o a.html - -Then browse to **a.html** (again, noting that you will need to use either Mozilla Firefox or a web server). You should see a pretty cool image displayed. +.. note:: Unfortunately *Chrome* and *Internet Explorer* do not support ``file://`` :term:`XHR` requests, and can't directly load the local file in which preloaded data is stored. For these browsers you'll need to serve the files using a webserver. The easiest way to do this is to use the python **SimpleHTTPServer** (in the current directory do ``python -m SimpleHTTPServer 8080`` and then open ``http://localhost:8080/hello.html``). For more information about working with the file system see the :ref:`Filesystem-Guide`, :ref:`Filesystem-API` and :ref:`Synchronous-virtual-XHR-backed-file-system-usage`. Optimizing code -====================================== +=============== -Emscripten, like *gcc*, generates unoptimized code by default. You can generate slightly-optimized code with the ``-O1`` command line argument (run the test code from the :term:`SDK root directory`): :: +Emscripten, like *gcc* and *clang*, generates unoptimized code by default. You can generate :ref:`slightly-optimized ` code with the ``-O1`` command line argument (run the test code from the :term:`SDK root directory`): :: - emcc -O1 tests/hello_world.cpp + ./emcc -O1 tests/hello_world.cpp The "hello world" code created in **a.out.js** doesn't really need to be optimized, so you won't see a difference in speed when compared to the unoptimized version. However, you can compare the generated code to see the differences. ``-O1`` applies several minor optimizations and removes some runtime assertions. For example, ``printf`` will have been replaced by ``puts`` in the generated code. -The optimizations provided by ``-O2`` are much more aggressive. If you run the following command and inspect the generated code (**a.out.js**) you will see that it looks very different: :: +The optimizations provided by ``-O2`` (see :ref:`here `) are much more aggressive. If you run the following command and inspect the generated code (**a.out.js**) you will see that it looks very different: :: - emcc -O2 tests/hello_world.cpp + ./emcc -O2 tests/hello_world.cpp For more information about compiler optimization options see :ref:`Optimizing-Code` and the :ref:`emcc tool reference `. @@ -155,19 +142,19 @@ For more information about compiler optimization options see :ref:`Optimizing-Co .. _running-emscripten-tests: Running the Emscripten Test Suite and Benchmarks -============================================================================ +================================================ Emscripten has an extensive test suite at `tests/runner.py `_. To run every test (this may take several hours), simply call the test script: :: python tests/runner.py -The individual tests are listed in the different test suites - for example "test_hello_world" is defined in the `core test suite here `_. You can run individual tests as shown: :: +The individual tests are listed in the different test suites — for example "test_hello_world" is defined in the `core test suite here `_. You can run individual tests as shown: :: python tests/runner.py test_hello_world .. todo:: **HamishW** Confirm that this is how test suites are done. We really should have a stand alone topic for this and link to it at this point. -To view the generated code from that individual test, you can first set ``EMCC_DEBUG=1``. This is shown for both Windows and Linxu below: :: +To view the generated code from that individual test, you can first set ``EMCC_DEBUG=1``: :: # On Windows, use "set" to set and un-set the environment variable: set EMCC_DEBUG=1 @@ -190,7 +177,7 @@ Note that **Node.js** cannot run all of the tests in the suite; if you care abou .. _running-emscripten-benchmarks: -To run the Emscripten benchmark tests, enter the following command: :: +To run the Emscripten *benchmark* tests, enter the following command: :: python tests/runner.py benchmark @@ -199,11 +186,12 @@ This will compile a sequence of benchmarks and run them several times, reporting General tips and next steps -====================================== +=========================== This tutorial walked you through your first steps in calling Emscripten from the command line. There is, of course, far more you can do with the tool. Below are other general tips for using Emscripten: -- 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. -- When in doubt, :ref:`get in touch `! +- 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. +- Read the :ref:`FAQ`. +- When in doubt, :ref:`get in touch `! diff --git a/site/source/docs/getting_started/bug_reports.rst b/site/source/docs/getting_started/bug_reports.rst index de177d5026131..b47d5a08db461 100644 --- a/site/source/docs/getting_started/bug_reports.rst +++ b/site/source/docs/getting_started/bug_reports.rst @@ -9,12 +9,12 @@ All bugs should be filed in the GitHub `main ` **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 :ref:`build Emscripten from source `. SDK Downloads @@ -64,10 +64,10 @@ The *Portable Emscripten SDK* is a no-installer version of the SDK package. It i First check the :ref:`Platform-specific notes ` below and install any prerequisites. -Install the SDK using the following steps: +Install or update 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 `. +#. Open a command prompt inside the SDK directory and run the following :ref:`emsdk ` commands to get the latest tools from Github and set them as :term:`active `. .. note:: On Windows, invoke the tool with **emsdk** instead of **./emsdk**: @@ -80,13 +80,20 @@ Install the SDK using the following steps: ./emsdk install latest # Make the "latest" SDK "active" - ./emsdk activate latest - -Whenever you change the location of the Portable SDK (e.g. take it to another computer), re-run the final command: ``./emsdk activate latest``. - -.. tip:: The instructions above can also be used to get new SDKs, as they are released. + ./emsdk activate latest +#. **Linux and Mac OS X only:** Call ``source ./emsdk_env.sh`` after ``activate`` to set the system path to the active version of Emscripten: + :: + + # Set the current Emscripten path on Linux/Mac OS X + source ./emsdk_env.sh + + This step is not required on Windows because calling the ``activate`` command also sets the correct system path (this is not possible on Linux due to security restrictions). + +Whenever you change the location of the Portable SDK (e.g. take it to another computer), re-run the ``./emsdk activate latest`` command (and ``source ./emsdk_env.sh`` for Linux). + + .. _platform-notes-installation_instructions-portable-SDK: Platform-specific notes @@ -112,7 +119,9 @@ Mac OS X 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. +**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. + +.. note:: *Emsdk* does not install any tools to the system, or otherwise interact with Linux package managers. All file changes are done inside the **emsdk/** directory. - The system must have a working :ref:`compiler-toolchain` (because *emsdk* builds software from the source): @@ -171,6 +180,9 @@ Type the following (omitting comments) on the :ref:`Emscripten Command Prompt ` (or even your own fork). Check out all the possibilities in the :ref:`emsdk_howto`. 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 f3818c9c4a5d9..7be256352e598 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,19 +1,69 @@ -.. _getting-started-emscripten-from-vs2010: +.. _getting-started-emscripten-from-visual-studio: -=========================================================================================== -Getting started using Emscripten from the Visual Studio 2010 IDE (under-construction) -=========================================================================================== +====================================================================== +Getting started using Emscripten from Visual Studio (ready-for-review) +====================================================================== +Windows Developers can develop, compile, and launch, their Emscripten projects from `Microsoft Visual Studio 2010 `_ (only). This topic shows you how. -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). +.. warning:: Visual Studio 2011 and 2012 are not supported. -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. +Integrating Emscripten and Visual Studio +======================================== -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. +Emscripten is integrated into Visual Studio (2010) using the :term:`vs-tool` plugin, which is is automatically deployed by the :term:`Windows NSIS Installer Emscripten SDK` if *Visual Studio 2010* is present on your system at install time (it is also possible to :ref:`manually integrate Emscripten into Visual Studio 2010 `). -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. +The *vs-tool* plugin adds an **Emscripten** configuration to the list of available *Solution Configurations* in Visual Studio. Activate this configuration for a solution/project to make Visual Studio run the project build through Emscripten, producing **.html** or **.js** output depending on the configured project properties. -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. +How to build a Visual Studio solution using Emscripten +====================================================== + +First select the **Emscripten** configuration from the *Configuration Manager* dropdown as the active configuration. Then choose **Build Solution** (F7). + + +How to launch a project in a web browser from Visual Studio +=========================================================== + +To launch a project directly to a web browser from Visual Studio: + +#. 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. Any browser can be used — below we specify *Mozilla Firefox*: + + :: + + SETX EMCC_WEBBROWSER_EXE C:/Program Files (x86)/Mozilla Firefox/firefox.exe + + +#. 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``. + +.. note:: Visual Studio occasionally opens a "Executable for Debug Session" dialog when you hit **Ctrl+F5**. This can be ignored by clicking **Yes** and then **No**, or simply by hitting **Esc** and then tapping **Ctrl+F5** again. + + +Specifying project compiler settings +==================================== + +:ref:`Fastcomp ` (Clang+LLVM) and :ref:`Emscripten compiler ` settings can be edited for the project in exactly the same way as other settings in Visual Studio. First make sure that the Emscripten platform configuration is active, right-click on a project, and then choose **Properties** to open the *Project properties* dialog. + +The Project Properties should contain two tree nodes: *Clang C/C++* and *Emcc Linker*. These allow you to specify the desired compilation options. + +.. _getting-started-emscripten-vs-existing-solution: + +Porting an existing solution file to use Emscripten +=================================================== + +To add Emscripten as a build option for an existing project: + +#. Open the *Configuration Manager* dialog for the solution. +#. In the *Active Solution Platform* dropdown, choose **New**. +#. In the *New* dialog, choose **Emscripten** as the platform name, and **Copy settings from Empty**. + +Now you should be able to switch between building the solution for Win32 and Emscripten by selecting the desired option from the *Configuration Manager* dropdown list. + + +Creating a new Visual Studio solution for Emscripten +==================================================== + +To create a new Visual Studio project for Emscripten, first create a **Visual C++ Empty Project** (a new project for the Win32 platform). Then convert that project to also build for Emscripten as outlined in the previous section: :ref:`getting-started-emscripten-vs-existing-solution`. + \ No newline at end of file diff --git a/site/source/docs/getting_started/index.rst b/site/source/docs/getting_started/index.rst index bcf71b4b17b28..22d10056db7ac 100644 --- a/site/source/docs/getting_started/index.rst +++ b/site/source/docs/getting_started/index.rst @@ -1,9 +1,14 @@ .. _getting-started-index: ===================================== -Getting Started (under-construction) +Getting Started (ready-for-review) ===================================== +Now you know why Emscripten is :ref:`right for you `, it's time to *get started*. + +This section provides a walk-through of :ref:`downloading and installing the SDK ` and the basics of :ref:`using the Emscripten toolchain `. The general :ref:`FAQ` answers many common questions about setting up and using Emscripten. + +We also explain where to :ref:`Report Bugs ` in the toolchain and the site, and how to use Emscripten with :ref:`Visual Studio 2010 ` (Windows only). .. toctree:: :maxdepth: 1 diff --git a/site/source/docs/index.rst b/site/source/docs/index.rst index f3162b2b30a62..100e4937f6781 100644 --- a/site/source/docs/index.rst +++ b/site/source/docs/index.rst @@ -8,7 +8,7 @@ Documentation Home (under-construction) introducing_emscripten/index getting_started/index - coding/index + porting/index optimizing/index compiling/index packaging/index diff --git a/site/source/docs/introducing_emscripten/about_emscripten.rst b/site/source/docs/introducing_emscripten/about_emscripten.rst index d7fc0cc9f1ef4..d8361830fb5fb 100644 --- a/site/source/docs/introducing_emscripten/about_emscripten.rst +++ b/site/source/docs/introducing_emscripten/about_emscripten.rst @@ -54,7 +54,7 @@ The :ref:`emsdk` is used to manage multiple SDKs and tools, and to specify the p A number of other tools are not shown — for example, Java can optionally be used by *emcc* to run the :term:`closure compiler`, which can further decrease code size. -The whole toolchain is delivered in the :ref:`Emscripten SDK ` +The whole toolchain is delivered in the :ref:`Emscripten SDK `, and can be used on Linux, Windows or Mac OS X. Porting code to use Emscripten diff --git a/site/source/docs/introducing_emscripten/community.rst b/site/source/docs/introducing_emscripten/community.rst index abaf79a05bec9..5306e61319484 100644 --- a/site/source/docs/introducing_emscripten/community.rst +++ b/site/source/docs/introducing_emscripten/community.rst @@ -17,12 +17,11 @@ The best ways to contact us for support are the *mailing list* and the *IRC* cha - Mailing list: `emscripten-discuss `_ - IRC: **#emscripten** on `irc.mozilla.org `_ +Emscripten also has a presence on social media: -Emscripten also has an *unofficial* presence on social media: - -- `Google+ page `_ - `#emscripten `_ (Emscripten Hashtag on Twitter) -- `@kripken `_ (Emscripten Developer Account on Twitter) +- Unofficial `Google+ page `_ +- `@kripken `_ (an Emscripten developer's account on Twitter, mentions Emscripten updates) Report a bug diff --git a/site/source/docs/introducing_emscripten/index.rst b/site/source/docs/introducing_emscripten/index.rst index 557cdc1699a53..e95c658861a15 100644 --- a/site/source/docs/introducing_emscripten/index.rst +++ b/site/source/docs/introducing_emscripten/index.rst @@ -1,8 +1,8 @@ -================================================= -Introducing Emscripten (under-construction) -================================================= +========================================= +Introducing Emscripten (ready-for-review) +========================================= -This section introduces Emscripten. It explains what the tool does, why it is needed, its limitations and its licensing. After reading, you will understand whether Emscripten is the right tool for you, and where to go if you have :ref:`further questions `. +This section explains what the Emscripten does, why it is needed, its limitations and its licensing. After reading, you will understand whether Emscripten is the right tool for you, and where to go if you have :ref:`further questions `. .. toctree:: :maxdepth: 1 diff --git a/site/source/docs/packaging/Filesystem-Guide.rst b/site/source/docs/packaging/Filesystem-Guide.rst index f9e2166391539..189dc67af9942 100644 --- a/site/source/docs/packaging/Filesystem-Guide.rst +++ b/site/source/docs/packaging/Filesystem-Guide.rst @@ -19,6 +19,8 @@ For concrete examples of using the filesystem API, see the automatic tests in `` The reason for the filesystem API is that JavaScript is most often run in web browsers, which sandbox content and prevent it from accessing the local filesystem. Therefore emscripten simulates a filesystem so that C/C++ code can be written normally, as if there were direct access to files. Note: if you want to run in a shell environment using node without sandboxing, then you can let code directly access the local filesystem using NODEFS, see :ref:`Filesystem-API`. +.. _packaging-files: + Packaging files =============== @@ -82,4 +84,5 @@ You can also look at ``FS.readFiles``, which will be an object whose keys are al Manually using the FS API ========================= -Checkout out the `Filesystem API docs `_. +Check out the :ref:`Filesystem-API`. + diff --git a/site/source/docs/coding/Emscripten-browser-environment.rst b/site/source/docs/porting/Emscripten-browser-environment.rst similarity index 100% rename from site/source/docs/coding/Emscripten-browser-environment.rst rename to site/source/docs/porting/Emscripten-browser-environment.rst diff --git a/site/source/docs/coding/Synchronous-Virtual-XHR-Backed-File-System-Usage.rst b/site/source/docs/porting/Synchronous-Virtual-XHR-Backed-File-System-Usage.rst similarity index 100% rename from site/source/docs/coding/Synchronous-Virtual-XHR-Backed-File-System-Usage.rst rename to site/source/docs/porting/Synchronous-Virtual-XHR-Backed-File-System-Usage.rst diff --git a/site/source/docs/coding/connecting_cpp_and_javascript/Interacting-with-code.rst b/site/source/docs/porting/connecting_cpp_and_javascript/Interacting-with-code.rst similarity index 75% rename from site/source/docs/coding/connecting_cpp_and_javascript/Interacting-with-code.rst rename to site/source/docs/porting/connecting_cpp_and_javascript/Interacting-with-code.rst index a20fccb4d31dc..8136b4dd9fb17 100644 --- a/site/source/docs/coding/connecting_cpp_and_javascript/Interacting-with-code.rst +++ b/site/source/docs/porting/connecting_cpp_and_javascript/Interacting-with-code.rst @@ -6,16 +6,13 @@ Interacting with code (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! -Interacting with Compiled Code -============================== - (If you are looking for how compiled code interacts with the browser environment, see :ref:`Emscripten-Browser-Environment`.) There are various ways to connect and interact between JS and compiled C++ in JS. An overview appears in the second half of these slides: http://kripken.github.io/mloc\_emscripten\_talk/qcon.html Calling Compiled Functions From Normal JavaScript -------------------------------------------------- +================================================= It's easy to call compiled code from normal JavaScript. For example, run this command in the Emscripten home directory: @@ -46,7 +43,7 @@ Some things to keep in mind with :js:func:`ccall` and :js:func:`cwrap`: **Note:** you need ``_`` at the beginning of the functions when exporting (but not with ccall), and note also that you need to use ``Module.ccall`` and not :js:func:`ccall` by itself, since closure will minify the function name, leaving only the Module object where we export names. Accessing Memory ----------------- +================ You can access memory using :js:func:`getValue(ptr, type) ` and :js:func:`setValue(ptr, value, type) `. The first argument is a pointer, a number representing a memory address. ``type`` must be an LLVM IR type, one of ``i8,i16,i32,i64,float,double`` or a pointer type like ``i8*`` (or just ``*``). Note that the types here are not as in :js:func:`ccall` and :js:func:`cwrap` - this is a lower-level operation, and we do need to care what specific integer etc. type is being used. @@ -62,7 +59,7 @@ You can also access memory 'directly' by manipulating the arrays that represent That allocates a buffer, copies in some data, then calls a C function to process the data, and finally frees the buffer. Here ``my_function`` is a C function that receives a single integer parameter (could be a pointer as well, as they are just 32-bit integers for us), and returns an integer as well, something like ``int my_function(char *buf)``. Calling JavaScript From C/C++ ------------------------------ +============================= The most direct way is to just use :c:func:`emscripten_run_script`, which basically runs some JS code from C/C++ using eval. So ``emscripten_run_script("alert('hi')");`` will show an alert with 'hi' (note: this calls ``alert`` which is present in browsers, but not in node or other JS shells. You can call ``Module.print`` to print to stdout). This is not very fast though. A faster alternative is to write "inline JavaScript", basically the same as inline assembly would be used, for example @@ -127,22 +124,22 @@ You can use the emcc option ``--js-library`` to add a file with such code, inste - JS libraries can declare dependencies (``__deps``, see examples in ``library*.js``), however those are only for other JS libraries. If a JS library depends on a compiled C library (like most of libc), you must edit ``src/deps_info.json``, see ``tools/system_libs.py`` (search for deps\_info). Calling JS functions as function pointers from C -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +-------------------------------------------------- You can use ``Runtime.addFunction`` to return an integer value that represents a function pointer. Passing that integer to C code then lets it call that value as a function pointer, and the JS function you sent to ``Runtime.addFunction`` will be called. See ``test_add_function`` in ``tests/test_core.py`` for an example. WebIDL Binder -------------- +============= The :ref:`WebIDL-Binder` is a tool to make C++ classes usable from JS as JS classes. It is used to port Bullet Physics to the web in the **ammo.js** project, and is a fairly simple lightweight approach to binding between the two languages. Embind ------- +====== Embind is a method to communicate from JS to C++ and C++ to JS, in a C++-like manner (whereas JS libraries are using C APIs, and just one direction). The only downside is that it is not as lightweight as JS libraries or the WebIDL binder. Docs: :ref:`embind`. -Other Methods -------------- +Other methods +============= You can directly interact in various other ways with the compiled code: @@ -152,44 +149,25 @@ You can directly interact in various other ways with the compiled code: - There are various other convenience functions, see **preamble.js** (that file will be included with the generated code). - For filesystem-related manners, see the :ref:`Filesystem-Guide`. -Affecting Execution -------------------- - -You can affect how code runs by creating an object called ``Module`` before the compiled script. Certain properties on ``Module`` can then have various effects: - -- ``arguments``: The commandline arguments (if the compiled code checks ``argc``, ``argv``, it will be seeing ``arguments``) -- ``print``: Called when something is printed to standard output. -- ``preInit``: A function (or array of functions) to call before global initializers run, but after basic initialization of the JS runtime (so you can do ``FS.*`` stuff, but no C++ initializers were called yet). -- ``preRun``: A function (or array of functions) to call right before calling ``run``, but after defining and setting up the environment, including global initializers. This is useful, for example, to set up directories and files using the FileSystem API (since that needs the FileSystem API to be defined, but also needs to be done before the program starts to run; if you need to affect global initializers, though, you should use preInit). -- ``noInitialRun``: If set to true, ``main()`` will not be called. The program will still call global initializers, set up memory initialization, and so forth. You can then call ``main()`` yourself later. -- ``noExitRuntime``: If set to true, the runtime is not shut down after ``run`` is called. Shutting down the runtime calls shutdown callbacks, for example ``atexit`` calls. If you want to be able to continue to use the code after ``run`` finishes, it is safer to set this. - -For example, - -:: - - var Module = { - 'print': function(text) { alert(text) } - }; +Affecting execution +=================== -This will cause all printouts from the program to be calls to ``alert``. +``Module`` is a global JavaScript object, with attributes that Emscripten-generated code calls at various points in its execution. -**Important**: If you run closure compiler on your code (which is done by default in ``-O2`` and above), you will need quotation marks around the properties of ``Module`` as in the example above (and you need to run closure on the compiled code together with the declaration of ``Module``). +Developers provide an implementation of ``Module`` to control, for example, how notifications from Emscripten are displayed, which files that are loaded before the main loop is run, etc. For more information see :ref:`module`. -Setting Module -~~~~~~~~~~~~~~ -When generating just JavaScript, no Module object is created. So you can use emcc's ``--pre-js`` to add some JS code that defines the Module object with the stuff you need. +Environment variables +============================== -When generating HTML, a Module object is created for you and filled with some defaults for printing, etc. (compile a little hello world example to see, or view ``src/shell.html``). The simplest thing is to use ``--pre-js`` to add some JS code that adds properties to that existing Module object. +Sometimes compiled code needs to access environment variables (for instance, in C, by calling the ``getenv()`` function). Just as with the file system, Emscripten generated JavaScript cannot access the computer's environment variables directly, so a virtualised environment is provided. -Environment variables -~~~~~~~~~~~~~~~~~~~~~ +The JavaScript object ``ENV`` contains these virtualised environment variables, and by modifying it you can pass variables to your compiled code. Care must be taken to ensure that the ``ENV`` variable has been initialised by Emscripten before it is modified - using :js:attr:`Module.preRun` is a convenient way to do this. -Sometimes, the code you are compiling will want to access environment variables (for instance, in C, by calling the ``getenv()`` function). Just as with the filesystem, emscripten generated JavaScript cannot access the computer's environment variables so a virtualised environment is provided. The JavaScript object ``ENV`` contains these virtualised environment variables, and by modifying it you can pass variables to your compiled code. Care must be taken to ensure that the ``ENV`` variable has been initialised by Emscripten before it is modified - using ``Module.preRun`` is a convenient way to do this. For example to set an environment variable ``MY_FILE_ROOT`` to be ``"/usr/lib/test/"`` you could add +For example to set an environment variable ``MY_FILE_ROOT`` to be ``"/usr/lib/test/"`` you could add the following JavaScript to your :ref:`setup code `: .. code:: javascript Module.preRun.push(function() {ENV.MY_FILE_ROOT = "/usr/lib/test"}) -to your setup code, as described above. + diff --git a/site/source/docs/coding/connecting_cpp_and_javascript/WebIDL-Binder.rst b/site/source/docs/porting/connecting_cpp_and_javascript/WebIDL-Binder.rst similarity index 100% rename from site/source/docs/coding/connecting_cpp_and_javascript/WebIDL-Binder.rst rename to site/source/docs/porting/connecting_cpp_and_javascript/WebIDL-Binder.rst diff --git a/site/source/docs/coding/connecting_cpp_and_javascript/embind.rst b/site/source/docs/porting/connecting_cpp_and_javascript/embind.rst similarity index 100% rename from site/source/docs/coding/connecting_cpp_and_javascript/embind.rst rename to site/source/docs/porting/connecting_cpp_and_javascript/embind.rst diff --git a/site/source/docs/coding/connecting_cpp_and_javascript/index.rst b/site/source/docs/porting/connecting_cpp_and_javascript/index.rst similarity index 100% rename from site/source/docs/coding/connecting_cpp_and_javascript/index.rst rename to site/source/docs/porting/connecting_cpp_and_javascript/index.rst diff --git a/site/source/docs/coding/connecting_cpp_and_javascript/using_the_embind_val_class_from_cpp.rst b/site/source/docs/porting/connecting_cpp_and_javascript/using_the_embind_val_class_from_cpp.rst similarity index 100% rename from site/source/docs/coding/connecting_cpp_and_javascript/using_the_embind_val_class_from_cpp.rst rename to site/source/docs/porting/connecting_cpp_and_javascript/using_the_embind_val_class_from_cpp.rst diff --git a/site/source/docs/coding/debugging/Debugging.rst b/site/source/docs/porting/debugging/Debugging.rst similarity index 100% rename from site/source/docs/coding/debugging/Debugging.rst rename to site/source/docs/porting/debugging/Debugging.rst diff --git a/site/source/docs/coding/debugging/index.rst b/site/source/docs/porting/debugging/index.rst similarity index 100% rename from site/source/docs/coding/debugging/index.rst rename to site/source/docs/porting/debugging/index.rst diff --git a/site/source/docs/coding/Asm-pointer-casts.rst b/site/source/docs/porting/guidelines/Asm-pointer-casts.rst similarity index 66% rename from site/source/docs/coding/Asm-pointer-casts.rst rename to site/source/docs/porting/guidelines/Asm-pointer-casts.rst index f3a0b504baa0e..6436e9c236849 100644 --- a/site/source/docs/coding/Asm-pointer-casts.rst +++ b/site/source/docs/porting/guidelines/Asm-pointer-casts.rst @@ -1,3 +1,16 @@ +======================================= +Function Pointer Issues (wiki-import) +======================================= + +There are three general issues with function pointers: + +#. clang generates different code for C and C++ calls when a structure is passed **by value**. The two formats are incompatible in how we generate code in Emscripten, but each is compatible with itself. You should see a warning during compilation about this, and the workaround is to either not mix C and C++ in that location (just renaming a **.c** file to **.cpp** for example) or to pass the structure by reference. (More specifically, one convention is ``struct byval`` and the other is ``field a, field b``.) + +#. In **asm.js** mode, there is an additional concern, with function tables. Without **asm.js**, all function pointers use a single table, but in **asm.js** each function pointer type has its own table (this allows the JavaScript engine to know the exact type of each function pointer call, and optimize those calls much better than normally). As a consequence though, if you have a function that is say ``int (int)`` (return int, receive int) and you cast it to ``void (int)`` (no return, receive int), then the function pointer call will fail because we are looking in the wrong table. This is undefined behavior in C in any case, so it is recommended to refactor code to avoid this type of situation. You should see compilation warnings about these things. See :ref:`Asm-pointer-casts` for more information. + +#. A related issue to do with function pointers is that in ``-O2`` and above we optimize the size of the separate function tables. That means that two functions can have the same function pointer so long as their type is different, and so potentially comparing function pointers of different types can give false positives. Also, it makes bugs with incorrect function pointers potentially more misleading, since there are fewer "holes" in function tables (holes would throw an error instead of running the wrong code). To check if this is causing issues, you can compile with ``-s ALIASING_FUNCTION_POINTERS=0``. + + .. _Asm-pointer-casts: =============================== diff --git a/site/source/docs/porting/guidelines/Browser-limitations.rst b/site/source/docs/porting/guidelines/Browser-limitations.rst new file mode 100644 index 0000000000000..1eab100f62bf5 --- /dev/null +++ b/site/source/docs/porting/guidelines/Browser-limitations.rst @@ -0,0 +1,14 @@ +.. _Browser-limitations: + +====================================== +Browser limitations (ready-for-review) +====================================== + +This page lists some of the most common differences between the latest versions of the major browsers and features that are relevant to Emscripten-compiled applications and games: + +- The function :c:func:`emscripten_get_now` returns a wallclock time as a ``float`` in milliseconds. *Opera 12.16* and on `Windows Google Chrome 28.0.1500.95 `_ have a limitation that the timer precision is only in milliseconds. On other major browsers (*IE10*, *Firefox 22*, *Chrome 28* on non-Windows) it has sub-millisecond precision. +- *Internet Explorer 10* and older do not support WebGL, which means trying to initialize a GL context via EGL, GLUT, SDL or similar will fail. Emscripten applications that do not depend on OpenGL can still be compiled for this browser however. See `WebGL support in different browsers `_. +- *Internet Explorer 11* supports WebGL, but not all of WebGL 1.0, so certain commands, shaders etc. may not work. You may be able to limit your app to using the subset that is supported by IE11. Hopefully IE12 will support everything. +- *Opera 12.16* has limited support for the W3C File API, in particular it does not support `createObjectURL functionality `_. As a result, it is not possible to use the browser image codecs on this version of Opera to decode preloaded files in the Emscripten virtual files system. +- OpenAL and SDL audio support in Emscripten depend on the Web Audio API. See `Web Audio API support in different browsers `_. + diff --git a/site/source/docs/porting/guidelines/CodeGuidelinesAndLimitations.rst b/site/source/docs/porting/guidelines/CodeGuidelinesAndLimitations.rst new file mode 100644 index 0000000000000..01e0341bd7a7c --- /dev/null +++ b/site/source/docs/porting/guidelines/CodeGuidelinesAndLimitations.rst @@ -0,0 +1,52 @@ +.. _CodeGuidelinesAndLimitations: + +========================================================= +Portability Guidelines (under-construction) +========================================================= + +This article describes the types of code that are more difficult to compile, code which compiles but may run more slowly, and issues and limitations with specific APIs. Developers will find it useful for evaluating the effort to port and re-write code. + +Code that cannot be compiled +============================= + +The following issues are fundamental difficulties. We can get around them by emulation in theory, but it would be very slow. + +- Code that is multithreaded and uses shared state. JavaScript has threads - web workers - but they cannot share state, instead they pass messages. +- Nonportable code that relies on endianness is problematic. It can work with :ref:`typed-arrays-mode-2`, but it will not be portable! +- Nonportable code that relies on x86 alignment behavior. X86 allows unaligned reads and writes (so you can read a 16-bit value from a non-even address, i.e., which is only 8-bit aligned address, for example), but other archs do not: ARM will raise ``SIGILL``, and when Emscripten generates JavaScript you will get undefined behavior in this case. (If you build your code with ``SAFE_HEAP=1`` then you will get a clear runtime exception, see :ref:`Debugging`. + + .. note:: The ``UNALIGNED_MEMORY`` code generation mode can support unaligned code like this, but it is very slow. + +- Nonportable code that uses low-level features of the native environment, like native stack manipulation (e.g. in conjunction with setjmp/longjmp. We support normal setjmp/longjmp, but not with stack replacing etc.) +- Nonportable code that scans registers or the stack, for example to do conservative garbage collection. A variable in a register or on the stack may be held in a JavaScript local variable, which cannot be scanned. (However, you can do conservative scanning when there is no other code on the stack, e.g. from an iteration of the main event loop.) + + +Code that compiles but might run slowly +======================================= + +None of the issues here is a showstopper, but they might be slower than you expect. You probably don't need to worry about this stuff, but it might be useful to know about it. + +- 64-bit ints. Bitwise operations on these are reasonable, but math (+, -, \*, /) is emulated, very slowly. JavaScript does not have native 64-bit ints so this is unavoidable. +- 32-bit multiplication that needs all 64 bits of precision must be emulated like 64-bit integer math (JavaScript doubles work fine up to ~52 bits). By default precise 32-bit multiplication is off as it makes a lot of common 32-bit code very slow, but if you need it you can enable it with ``-s PRECISE_I32_MUL=1``, see `src/settings.js `_ for more. +- 32-bit floats will end up as 64-bit doubles in JavaScript engines. That means they might be a little slower than expected, depending on your CPU. +- ``memcpy``/``memset`` works, but JavaScript engines don't optimize it very well. Native code will use SIMD on this, JavaScript engines will not - yet. +- Exceptions and ``longjmp``. In JavaScript such code generally makes the JavaScript engine turn off various optimizations. For that reason exceptions are turned off by default in ``-O1`` and above (to re-enable them, run *emcc* with ``-s DISABLE_EXCEPTION_CATCHING=0``). ``setjmp`` also prevents relooping around it. + +Code that should be avoided when easy to do +=========================================== + +Avoiding these kinds of code might be nice to do, to prevent warnings and to enable additional optimizations. But unless it is very easy for you to avoid them, just ignore this section. + +- Unions. These will trigger ``SAFE_HEAP`` warnings (like *Valgrind*), and make the ``QUANTUM_SIZE=1`` :ref:`optimization ` impossible. +- Bitfields. Also ``SAFE_HEAP`` warnings. +- Reusing memory, that is, using the same allocated block of memory once for one kind of object, later for another. This prevents the ``QUANTUM_SIZE=1`` optimization. + +Libraries +========= + +Networking +---------- + +- Emscripten supports libc networking functions, but since JavaScript networking is asynchronous, you must limit yourself to asynchronous (nonblocking) operations. + + diff --git a/site/source/docs/porting/guidelines/index.rst b/site/source/docs/porting/guidelines/index.rst new file mode 100644 index 0000000000000..64151d61dbb09 --- /dev/null +++ b/site/source/docs/porting/guidelines/index.rst @@ -0,0 +1,19 @@ +.. _guidelines-index: + +===================================================== +Code Portability and Limitations (under-construction) +===================================================== + +This section is for ..... + + +.. toctree:: + :maxdepth: 1 + + CodeGuidelinesAndLimitations + Asm-pointer-casts + Browser-limitations + + + + diff --git a/site/source/docs/coding/index.rst b/site/source/docs/porting/index.rst similarity index 67% rename from site/source/docs/coding/index.rst rename to site/source/docs/porting/index.rst index ac57508450505..eb579b95a1164 100644 --- a/site/source/docs/coding/index.rst +++ b/site/source/docs/porting/index.rst @@ -1,8 +1,8 @@ .. _integrating-porting-index: -================================================== -Integrating/Porting (under-construction) -================================================== +================================ +Porting (under-construction) +================================ This section is for articles explaining the integration points with Emscripten, and general coding guidelines to help you with porting. @@ -11,15 +11,12 @@ This section is for articles explaining the integration points with Emscripten, .. toctree:: :maxdepth: 1 - CodeGuidelinesAndLimitations + guidelines/index Emscripten-browser-environment connecting_cpp_and_javascript/index multimedia_and_graphics/index - Asm-pointer-casts Synchronous-Virtual-XHR-Backed-File-System-Usage debugging/index - Browser-limitations - Garbage_Collection diff --git a/site/source/docs/coding/multimedia_and_graphics/EGL-Support-in-Emscripten.rst b/site/source/docs/porting/multimedia_and_graphics/EGL-Support-in-Emscripten.rst similarity index 100% rename from site/source/docs/coding/multimedia_and_graphics/EGL-Support-in-Emscripten.rst rename to site/source/docs/porting/multimedia_and_graphics/EGL-Support-in-Emscripten.rst diff --git a/site/source/docs/coding/multimedia_and_graphics/OpenGL-support.rst b/site/source/docs/porting/multimedia_and_graphics/OpenGL-support.rst similarity index 100% rename from site/source/docs/coding/multimedia_and_graphics/OpenGL-support.rst rename to site/source/docs/porting/multimedia_and_graphics/OpenGL-support.rst diff --git a/site/source/docs/coding/multimedia_and_graphics/index.rst b/site/source/docs/porting/multimedia_and_graphics/index.rst similarity index 100% rename from site/source/docs/coding/multimedia_and_graphics/index.rst rename to site/source/docs/porting/multimedia_and_graphics/index.rst diff --git a/site/source/docs/site/about.rst b/site/source/docs/site/about.rst index 41e7c3967c89f..03383b62c3c28 100644 --- a/site/source/docs/site/about.rst +++ b/site/source/docs/site/about.rst @@ -28,11 +28,6 @@ By the end of the project all articles should be published and all of this page .. todo:: **HamishW** Delete this whole section at the end of the project. At that point there should only be HamishW markup for possible Todos. Note the search link immediately above too - this is to the kripken site and may need to change if the site moves. -Reporting bugs -============== - -Please :ref:`report documentation bugs ` as you would any other Emscripten bug. Help :ref:`fix them ` by updating existing documents or by creating new ones. - Searching the site ================== @@ -41,7 +36,19 @@ Searching returns only topics which contain **all** the specified keywords. .. tip:: Always start by searching for *single* words like "interacting" or "compiling". Generally this will be enough to find the relevant document. If not, you can refine the search by adding additional terms. -Note that searches that include characters like "-" and "+" will not work. There is no support for logical operators. +.. note:: Searches that include characters like "-" and "+" will not work. There is no support for logical operators. + +Reporting bugs +============== + +Please :ref:`report documentation bugs ` as you would any other Emscripten bug. Help :ref:`fix them ` by updating existing documents or by creating new ones. + +Contributing to the site +======================== + +:ref:`Contributions ` to this site (and indeed any part of Emscripten) are welcome! + +Check out the rest of this article for instructions on how to :ref:`build the site ` and :ref:`write and update articles `. .. _building-the-site: @@ -49,18 +56,11 @@ Note that searches that include characters like "-" and "+" will not work. There Building the site ================== -The site sources are in the Emscripten *incoming* branch, `site `_ directory. Changes should be committed to the incoming branch. +The site sources are stored on Github `here `_. Edits and additions should be submitted to this branch in the same way as any other change to the tool. The site is published to the **kripken/emscripten-site** *gh-pages* branch (Github pages). - -make html ---------- - -The site can be built from source on Ubuntu and Windows by navigating to the */emscripten/site* directory and using the command: :: - - make clean - make html +.. note:: Remember to update the :ref:`about-build-versions` for *public* builds. Installing Sphinx ----------------- @@ -76,8 +76,53 @@ The workaround is to use the Python package installer "pip" to get version 1.2.2 pip install sphinx pip install sphinx --upgrade + +.. _about-site-builds: + +Site builds +----------- +The site can be built from source on Ubuntu and Windows by navigating to the */emscripten/site* directory and using the command: :: + + make clean + make html + + +.. _about-sdk-builds: + +SDK Builds +------------------ + +SDK builds are virtually identical to :ref:`about-site-builds`. The main difference is that on SDK builds the :ref:`home page ` has a clear notification that it is an SDK build. + +SDK builds are enabled by enabling the ``sdkbuild`` tag. This is done through the ``SPHINXOPTS`` environment variable: :: + + # Set the sdkbuild tag. + set SPHINXOPTS=-t sdkbuild + make html + # Unset SPHINXOPTS + set SPHINXOPTS= + +.. _about-build-versions: + +Build version +------------- + +The documentation version should match the Emscripten version for the current build. For a general site build this will be the latest tagged release as defined in `Emscripten version `_. For an SDK build it will be the Emscripten version for the SDK. + +The version and release information is used in a few places in the documentation, for example :ref:`emscripten-authors`. + + + +The version can be ``version`` and ``release`` variables in **conf.py**, or on the command line by setting new values for these variables in the ``SPHINXOPTS`` environment variable. For example, to update the ``release`` variable through the command line: :: + + # Set SPHINXOPTS + set SPHINXOPTS=-D release=6.40 + make html + # Unset SPHINXOPTS + set SPHINXOPTS= + .. _writing-and-updating-articles: diff --git a/site/source/docs/tools_reference/emcc.rst b/site/source/docs/tools_reference/emcc.rst index b7e4abc022cf7..dc39f51d8f384 100644 --- a/site/source/docs/tools_reference/emcc.rst +++ b/site/source/docs/tools_reference/emcc.rst @@ -1,13 +1,11 @@ .. _emccdoc: -========================================================= -Emscripten Compiler Frontend (emcc) (under-construction) -========================================================= +====================================================== +Emscripten Compiler Frontend (emcc) (ready-for-review) +====================================================== **This document provides the command syntax for the Emscription Compiler Frontend.** -.. comment - 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 ============================================ @@ -23,10 +21,6 @@ Command line syntax 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). - -.. todo:: **HamishW** The line above makes no sense. Checking with Alon. - Arguments --------- @@ -49,6 +43,7 @@ Options that are modified or new in *emcc* are listed below: ``-O0`` No optimizations (default). This is the recommended setting for starting to port a project, as it includes various assertions. +.. _emcc-O1: ``-O1`` Simple optimizations. These include using **asm.js**, LLVM ``-O1`` optimizations, relooping, removing runtime assertions and C++ exception catching, and enabling ``-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``). @@ -57,6 +52,8 @@ Options that are modified or new in *emcc* are listed below: - 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``. + +.. _emcc-O2: ``-O2`` Like ``-O1``, but with various JavaScript-level optimizations and LLVM ``-O3`` optimizations. @@ -69,6 +66,8 @@ Options that are modified or new in *emcc* are listed below: ``-Oz`` Like ``-Os``, but reduces code size even further. +.. _emcc-O3: + ``-O3`` Like ``-O2``, but with additional JavaScript optimizations that can take a significant amount of compilation time and/or are relatively new. @@ -92,6 +91,8 @@ Options that are modified or new in *emcc* are listed below: 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. +.. _emcc-g: + ``-g`` Use debug info. @@ -154,20 +155,23 @@ Options that are modified or new in *emcc* are listed below: - If LLVM optimizations are not run (see ``--llvm-opts``), this setting has no effect. - LLVM LTO is not perfectly stable yet, and can can cause code to behave incorrectly. - . + +.. _emcc-closure: + ``--closure `` Runs the :term:`Closure Compiler`. 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). + - ``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). + - ``2``: Run closure compiler on *all* the emitted code, even on **asm.js** output in **asm.js** mode. This can further reduce code size, but does prevent a significant amount of **asm.js** optimizations, so it is not recommended unless you want to reduce code size at all costs. .. 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 JavaScript opts are being done (``-O2`` or above, or ``--js-opts 1``). - + +.. _emcc-pre-js: + ``--pre-js `` Specify a file whose contents are added before the generated code. This is done *before* optimization, so it will be minified properly if the *Closure Compiler* is run. @@ -197,7 +201,7 @@ Options that are modified or new in *emcc* are listed below: For more information about the ``--preload-file`` options, see :ref:`Filesystem-Guide`. ``--exclude-file `` - Files and directories to be excluded from :ref:`--embed-file ` and :ref:`--preload-file `. Wildcard is supported. + Files and directories to be excluded from :ref:`--embed-file ` and :ref:`--preload-file `. Wildcards (*) are 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 }}}``. @@ -249,7 +253,9 @@ Options that are modified or new in *emcc* are listed below: Tells the compiler to ignore dynamic linking (the user will need to manually link to the shared libraries later on). Normally *emcc* will simply link in code from the dynamic library as though it were statically linked, which will fail 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. - + +.. _emcc-js-library: + ``--js-library `` A JavaScript library to use in addition to those in Emscripten's core libraries (src/library_*). @@ -269,15 +275,17 @@ Options that are modified or new in *emcc* are listed below: ``--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 after link-time optimizations have been performed (if any), including standard libraries. - + +.. _emcc-memory-init-file: + ``--memory-init-file `` Specifies whether to emit a separate memory initialization file. Possible ``on`` values are: - ``0``: Do not emit a separate memory initialization file (default). Instead keep the static initialization inside the generated JavaScript as text. - ``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. - .. note:: Call yourself from ``main()`` to know when all asynchronous processing has completed 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``. - + .. note:: The :ref:`safest way ` to ensure that it is safe to call C functions (the initialisation file has loaded) is to call a notifier function from ``main()``. + ``-Wno-warn-absolute-paths`` Suppress warnings about the use of absolute paths in ``-I`` and ``-L`` command line directives. This is used to hide the warnings and acknowledge that the explicit use of absolute paths is intentional. @@ -303,6 +311,7 @@ Options that are modified or new in *emcc* are listed below: ``--valid_abspath path`` Whitelist an absolute path to prevent warnings about absolute include paths. +.. _emcc-o-target: ``-o `` The ``target`` file name extension defines what type of output be generated: @@ -315,7 +324,9 @@ Options that are modified or new in *emcc* are listed below: .. note:: If ``--memory-init-file`` is used, then in addition to the **.js** or **.html** file which is generated, a **.mem** file will also be created. ``-c`` - Tells *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. + Tells *emcc* to generate LLVM bitcode (which can then be linked with other bitcode files), instead of compiling all the way to JavaScript. + + Environment variables ===================== diff --git a/site/source/docs/tools_reference/emsdk.rst b/site/source/docs/tools_reference/emsdk.rst index ab411cf87ce08..05d70b5a9cb12 100644 --- a/site/source/docs/tools_reference/emsdk.rst +++ b/site/source/docs/tools_reference/emsdk.rst @@ -78,6 +78,7 @@ A particular installed SDK (or tool) can then be set as :term:`active Emscripten is an LLVM-based project that compiles C/C++ into h
-