diff --git a/emcc b/emcc
index 6fa558eded8e0..0e295d2f75b67 100755
--- a/emcc
+++ b/emcc
@@ -456,6 +456,8 @@ try:
raise Exception(err_msg)
return level
+ should_exit = False
+
for i in range(len(newargs)):
newargs[i] = newargs[i].strip() # On Windows Vista (and possibly others), excessive spaces in the command line leak into the items in this array, so trim e.g. 'foo.cpp ' -> 'foo.cpp'
if newargs[i].startswith('-O'):
@@ -623,11 +625,17 @@ try:
newargs[i] = ''
newargs[i+1] = ''
elif newargs[i] == '--clear-cache':
- newargs[i] = ''
logging.warning('clearing cache')
shared.Cache.erase()
shared.check_sanity(force=True) # this is a good time for a sanity check
- sys.exit(0)
+ should_exit = True
+ elif newargs[i] == '--clear-ports':
+ logging.warning('clearing ports')
+ system_libs.Ports.erase()
+ should_exit = True
+ elif newargs[i] == '--show-ports':
+ system_libs.show_ports()
+ should_exit = True
elif newargs[i] == '--save-bc':
check_bad_eq(newargs[i])
save_bc = newargs[i+1]
@@ -653,10 +661,6 @@ try:
elif newargs[i] == '--emrun':
emrun = True
newargs[i] = ''
- elif newargs[i] == '--em-config':
- # This option is parsed in tools/shared.py, here only clean it up from being passed to clang.
- newargs[i] = ''
- newargs[i+1] = ''
elif newargs[i] == '--default-obj-ext':
newargs[i] = ''
default_object_extension = newargs[i+1]
@@ -664,6 +668,9 @@ try:
default_object_extension = '.' + default_object_extension
newargs[i+1] = ''
+ if should_exit:
+ sys.exit(0)
+
newargs = [arg for arg in newargs if arg is not '']
# If user did not specify a default -std for C++ code, specify the emscripten default.
@@ -856,8 +863,7 @@ try:
for change in settings_changes:
key, value = change.split('=')
if value[0] == '@':
- value = '"@' + os.path.abspath(value[1:]) + '"'
- value = value.replace('\\\\', '/').replace('\\', '/') # Convert backslash paths to forward slashes on Windows as well, since the JS compiler otherwise needs the backslashes escaped (alternative is to escape all input paths passing to JS, which feels clumsier to read)
+ value = open(value[1:]).read()
else:
value = value.replace('\\', '\\\\')
exec('shared.Settings.' + key + ' = ' + value)
@@ -910,8 +916,6 @@ try:
if shared.Settings.ASM_JS:
assert opt_level >= 1 or fastcomp, 'asm.js requires -O1 or above'
- if bind:
- shared.Settings.RESERVED_FUNCTION_POINTERS = max(shared.Settings.RESERVED_FUNCTION_POINTERS, 10)
if shared.Settings.CORRECT_SIGNS != 1:
logging.warning('setting CORRECT_SIGNS to 1 for asm.js code generation')
shared.Settings.CORRECT_SIGNS = 1
@@ -985,6 +989,9 @@ try:
if not fastcomp and shared.Settings.ASSERTIONS and shared.Settings.ALIASING_FUNCTION_POINTERS:
logging.warning('ALIASING_FUNCTION_POINTERS is on, function pointer comparisons may be invalid across types')
+ if shared.Settings.EMULATE_FUNCTION_POINTER_CASTS:
+ shared.Settings.ALIASING_FUNCTION_POINTERS = 0
+
if shared.Settings.STB_IMAGE and final_suffix in JS_CONTAINING_SUFFIXES:
input_files.append((next_arg_index, shared.path_from_root('third_party', 'stb_image.c')))
next_arg_index += 1
@@ -1014,6 +1021,11 @@ try:
if js_opts:
shared.Settings.RUNNING_JS_OPTS = 1
+ if shared.Settings.EMTERPRETIFY:
+ shared.Settings.FINALIZE_ASM_JS = 0
+ shared.Settings.GLOBAL_BASE = 8*256 # keep enough space at the bottom for a full stack frame
+ shared.Settings.SIMPLIFY_IFS = 0 # this is just harmful for emterpreting
+
shared.Settings.RUNNING_FASTCOMP = fastcomp
shared.Settings.EMSCRIPTEN_VERSION = shared.EMSCRIPTEN_VERSION
@@ -1070,6 +1082,7 @@ try:
args = newargs + ['-emit-llvm', '-c', input_file, '-o', output_file]
if file_ending.endswith(CXX_ENDINGS):
args += shared.EMSDK_CXX_OPTS
+ args = system_libs.process_args(args, shared.Settings)
logging.debug("running: " + call + ' ' + ' '.join(args))
execute([call] + args) # let compiler frontend print directly, so colors are saved (PIPE kills that)
if not os.path.exists(output_file):
@@ -1156,12 +1169,13 @@ try:
logging.debug('will generate JavaScript')
+ extra_files_to_link = []
+
if not LEAVE_INPUTS_RAW and \
not shared.Settings.BUILD_AS_SHARED_LIB and \
not shared.Settings.SIDE_MODULE: # shared libraries/side modules link no C libraries, need them in parent
- extra_files_to_link = system_libs.calculate([f for _, f in sorted(temp_files)], in_temp, stdout, stderr, forced=forced_stdlibs)
- else:
- extra_files_to_link = []
+ extra_files_to_link = system_libs.get_ports(shared.Settings)
+ extra_files_to_link += system_libs.calculate([f for _, f in sorted(temp_files)] + extra_files_to_link, in_temp, stdout, stderr, forced=forced_stdlibs)
log_time('calculate system libraries')
@@ -1320,6 +1334,7 @@ try:
def repl(m):
# handle chunking of the memory initializer
s = m.groups(0)[0]
+ if len(s) == 0 and not shared.Settings.EMTERPRETIFY: return m.group(0) # emterpreter must have a mem init file; otherwise, don't emit 0-size ones
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
@@ -1411,6 +1426,9 @@ try:
js_optimizer_queue += ['simplifyExpressions']
+ if shared.Settings.EMTERPRETIFY: # emterpreter code will not run through a JS optimizing JIT, do more work ourselves
+ js_optimizer_queue += ['localCSE']
+
if shared.Settings.RELOOP and not shared.Settings.ASM_JS:
js_optimizer_queue += ['optimizeShiftsAggressive', get_eliminate()] # aggressive shifts optimization requires loops, it breaks on switches
@@ -1429,6 +1447,21 @@ try:
final = shared.Building.closure_compiler(final)
if DEBUG: save_intermediate('closure')
+ def do_minify():
+ global js_optimizer_queue
+
+ if opt_level >= 2:
+ 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 == 1:
+ js_optimizer_queue += ['closure']
+ elif debug_level <= 2 and not shared.Settings.MAIN_MODULE and shared.Settings.FINALIZE_ASM_JS and not closure:
+ js_optimizer_queue += ['cleanup']
+
if js_opts:
if shared.Settings.ASM_JS and shared.Settings.SAFE_HEAP: js_optimizer_queue += ['safeHeap']
@@ -1444,18 +1477,10 @@ try:
if shared.Settings.POINTER_MASKING and shared.Settings.ASM_JS: js_optimizer_queue += ['pointerMasking']
- if opt_level >= 2:
- 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 not shared.Settings.EMTERPRETIFY:
+ do_minify()
if shared.Settings.ASM_JS:
- if closure == 1:
- js_optimizer_queue += ['closure']
- elif debug_level <= 2 and not shared.Settings.MAIN_MODULE and not shared.Settings.SIDE_MODULE and not closure:
- js_optimizer_queue += ['cleanup']
-
js_optimizer_queue += ['asmLastOpts']
if shared.Settings.FINALIZE_ASM_JS: js_optimizer_queue += ['last']
@@ -1473,6 +1498,39 @@ try:
log_time('js opts')
+ js_target = unsuffixed(target) + '.js'
+
+ if shared.Settings.EMTERPRETIFY:
+ logging.debug('emterpretifying')
+ assert memory_init_file, 'emterpreter requires a mem init file'
+ import json
+ try:
+ # move temp js to final position, alongside its mem init file
+ shutil.move(final, js_target)
+ execute([shared.PYTHON, shared.path_from_root('tools', 'emterpretify.py'), js_target, final + '.em.js', memfile, json.dumps(shared.Settings.EMTERPRETIFY_BLACKLIST)])
+ final = final + '.em.js'
+ finally:
+ shared.try_delete(js_target)
+
+ # minify (if requested) after emterpreter processing, and finalize output
+ logging.debug('finalizing emterpreted code')
+ shared.Settings.FINALIZE_ASM_JS = 1
+ do_minify()
+ js_optimizer_queue += ['last']
+ flush_js_optimizer_queue()
+
+ # finalize the original as well, if we will be swapping it in (TODO: add specific option for this)
+ if shared.Settings.SWAPPABLE_ASM_MODULE:
+ real = final
+ original = js_target + '.orig.js' # the emterpretify tool saves the original here
+ final = original
+ logging.debug('finalizing original (non-emterpreted) code at ' + final)
+ do_minify()
+ js_optimizer_queue += ['last']
+ flush_js_optimizer_queue()
+ safe_move(final, original)
+ final = real
+
# Remove some trivial whitespace # TODO: do not run when compress has already been done on all parts of the code
#src = open(final).read()
#src = re.sub(r'\n+[ \n]*\n+', '\n', src)
@@ -1491,7 +1549,6 @@ try:
shell = open(shell_path).read()
assert '{{{ SCRIPT }}}' in shell, 'HTML shell must contain {{{ SCRIPT }}} , see src/shell.html for an example'
html = open(target, 'w')
- js_target = unsuffixed(target) + '.js'
base_js_target = os.path.basename(js_target)
if proxy_to_worker:
child_js = shared.Settings.PROXY_TO_WORKER_FILENAME or target_basename
diff --git a/emrun b/emrun
index 70e76b52e7632..3d0950b40c073 100755
--- a/emrun
+++ b/emrun
@@ -51,13 +51,16 @@ LINUX = False
OSX = False
if os.name == 'nt':
WINDOWS = True
-
- import win32api, _winreg
- from win32com.client import GetObject
- from win32api import GetFileVersionInfo, LOWORD, HIWORD
- import shlex
- from _winreg import HKEY_CURRENT_USER, OpenKey, QueryValue
-
+ try:
+ import shlex
+ import win32api, _winreg
+ from win32com.client import GetObject
+ from win32api import GetFileVersionInfo, LOWORD, HIWORD
+ from _winreg import HKEY_CURRENT_USER, OpenKey, QueryValue
+ except Exception, e:
+ print >> sys.stderr, str(e)
+ print >> sys.stderr, "Importing Python win32 modules failed! This most likely occurs if you do not have PyWin32 installed! Get it from http://sourceforge.net/projects/pywin32/"
+ sys.exit(1)
elif platform.system() == 'Linux':
LINUX = True
elif platform.mac_ver()[0] != '':
diff --git a/emscripten-version.txt b/emscripten-version.txt
index 28442b1906f79..958bb4d7634f3 100644
--- a/emscripten-version.txt
+++ b/emscripten-version.txt
@@ -1,2 +1,2 @@
-1.25.1
+1.26.0
diff --git a/emscripten.py b/emscripten.py
index 870767c195e27..6ae75282c5b77 100755
--- a/emscripten.py
+++ b/emscripten.py
@@ -815,6 +815,16 @@ def emscript_fast(infile, settings, outfile, libraries=[], compiler_engine=None,
#if DEBUG: print >> sys.stderr, "META", metadata
#if DEBUG: print >> sys.stderr, "meminit", mem_init
+ # if emulating pointer casts, force all tables to the size of the largest
+ if settings['EMULATE_FUNCTION_POINTER_CASTS']:
+ max_size = 0
+ for k, v in metadata['tables'].iteritems():
+ max_size = max(max_size, v.count(',')+1)
+ for k, v in metadata['tables'].iteritems():
+ curr = v.count(',')+1
+ if curr < max_size:
+ metadata['tables'][k] = v.replace(']', (',0'*(max_size - curr)) + ']')
+
# function table masks
table_sizes = {}
@@ -906,11 +916,13 @@ def save_settings():
global_initializers = ', '.join(map(lambda i: '{ func: function() { %s() } }' % i, metadata['initializers']))
if settings['SIMD'] == 1:
- pre = open(path_from_root(os.path.join('src', 'simd.js'))).read() + '\n\n' + pre
+ pre = open(path_from_root(os.path.join('src', 'ecmascript_simd.js'))).read() + '\n\n' + pre
- pre = pre.replace('STATICTOP = STATIC_BASE + 0;', '''STATICTOP = STATIC_BASE + Runtime.alignMemory(%d);
+ staticbump = mem_init.count(',')+1
+ while staticbump % 16 != 0: staticbump += 1
+ pre = pre.replace('STATICTOP = STATIC_BASE + 0;', '''STATICTOP = STATIC_BASE + %d;
/* global initializers */ __ATINIT__.push(%s);
- %s''' % (mem_init.count(',')+1, global_initializers, mem_init)) # XXX wrong size calculation!
+ %s''' % (staticbump, global_initializers, mem_init)) # XXX wrong size calculation!
funcs_js = [funcs]
if settings.get('ASM_JS'):
@@ -952,6 +964,19 @@ def save_settings():
#if DEBUG: outfile.write('// funcs\n')
if settings.get('ASM_JS'):
+ # when emulating function pointer casts, we need to know what is the target of each pointer
+ if settings['EMULATE_FUNCTION_POINTER_CASTS']:
+ function_pointer_targets = {}
+ for sig, table in last_forwarded_json['Functions']['tables'].iteritems():
+ start = table.index('[')
+ end = table.rindex(']')
+ body = table[start+1:end].split(',')
+ parsed = map(lambda x: x.strip(), body)
+ for i in range(len(parsed)):
+ if parsed[i] != '0':
+ assert i not in function_pointer_targets
+ function_pointer_targets[i] = [sig, str(parsed[i])]
+
# Move preAsms to their right place
def move_preasm(m):
contents = m.groups(0)[0]
@@ -976,12 +1001,15 @@ def unfloat(s):
if settings['ASSERTIONS'] >= 2:
debug_tables = {}
+ def make_params(sig): return ','.join(['p%d' % p for p in range(len(sig)-1)])
+ def make_coerced_params(sig): return ','.join([shared.JS.make_coercion('p%d', unfloat(sig[p+1]), settings) % p for p in range(len(sig)-1)])
+ def make_coercions(sig): return ';'.join(['p%d = %s' % (p, shared.JS.make_coercion('p%d' % p, sig[p+1], settings)) for p in range(len(sig)-1)]) + ';'
+ def make_func(name, code, params, coercions): return 'function %s(%s) { %s %s }' % (name, params, coercions, code)
+
def make_table(sig, raw):
- params = ','.join(['p%d' % p for p in range(len(sig)-1)])
- coerced_params = ','.join([shared.JS.make_coercion('p%d', unfloat(sig[p+1]), settings) % p for p in range(len(sig)-1)])
- coercions = ';'.join(['p%d = %s' % (p, shared.JS.make_coercion('p%d' % p, sig[p+1], settings)) for p in range(len(sig)-1)]) + ';'
- def make_func(name, code):
- return 'function %s(%s) { %s %s }' % (name, params, coercions, code)
+ params = make_params(sig)
+ coerced_params = make_coerced_params(sig)
+ coercions = make_coercions(sig)
def make_bad(target=None):
i = Counter.i
Counter.i += 1
@@ -993,7 +1021,7 @@ def make_bad(target=None):
code = 'nullFunc_' + sig + '(%d);' % target
if sig[0] != 'v':
code += 'return %s' % shared.JS.make_initializer(sig[0], settings) + ';'
- return name, make_func(name, code)
+ return name, make_func(name, code, params, coercions)
bad, bad_func = make_bad() # the default bad func
if settings['ASSERTIONS'] <= 1:
Counter.pre = [bad_func]
@@ -1008,13 +1036,33 @@ def make_bad(target=None):
implemented_functions.add(curr)
Counter.j = 0
def fix_item(item):
+ j = Counter.j
Counter.j += 1
newline = Counter.j % 30 == 29
if item == '0':
+ if j > 0 and settings['EMULATE_FUNCTION_POINTER_CASTS'] and j in function_pointer_targets: # emulate all non-null pointer calls, if asked to
+ proper_sig, proper_target = function_pointer_targets[j]
+ def make_emulated_param(i):
+ if i >= len(sig): return shared.JS.make_initializer(proper_sig[i], settings) # extra param, just send a zero
+ return shared.JS.make_coercion('p%d' % (i-1), proper_sig[i], settings, convert_from=sig[i])
+ proper_code = proper_target + '(' + ','.join(map(lambda i: make_emulated_param(i+1), range(len(proper_sig)-1))) + ')'
+ if proper_sig[0] != 'v':
+ # proper sig has a return, which the wrapper may or may not use
+ proper_code = shared.JS.make_coercion(proper_code, proper_sig[0], settings)
+ if sig[0] != 'v':
+ proper_code = 'return ' + proper_code
+ else:
+ # proper sig has no return, we may need a fake return
+ if sig[0] != 'v':
+ proper_code = 'return ' + shared.JS.make_initializer(sig[0], settings)
+ name = 'fpemu_%s_%d' % (sig, j)
+ wrapper = make_func(name, proper_code, params, coercions)
+ Counter.pre.append(wrapper)
+ return name if not newline else (name + '\n')
if settings['ASSERTIONS'] <= 1:
return bad if not newline else (bad + '\n')
else:
- specific_bad, specific_bad_func = make_bad(Counter.j-1)
+ specific_bad, specific_bad_func = make_bad(j)
Counter.pre.append(specific_bad_func)
return specific_bad if not newline else (specific_bad + '\n')
if item not in implemented_functions:
@@ -1028,7 +1076,7 @@ def fix_item(item):
if sig[0] == 'f': code = '+' + code
code = 'return ' + shared.JS.make_coercion(code, sig[0], settings)
code += ';'
- Counter.pre.append(make_func(item + '__wrapper', code))
+ Counter.pre.append(make_func(item + '__wrapper', code, params, coercions))
return item + '__wrapper'
return item if not newline else (item + '\n')
if settings['ASSERTIONS'] >= 2:
@@ -1063,7 +1111,6 @@ def fix_item(item):
fundamentals += ['SIMD']
if settings['ALLOW_MEMORY_GROWTH']: fundamentals.append('byteLength')
math_envs = ['Math.min'] # TODO: move min to maths
- asm_setup += '\n'.join(['var %s = %s;' % (f.replace('.', '_'), f) for f in math_envs])
if settings['PRECISE_F32']: maths += ['Math.fround']
@@ -1231,7 +1278,10 @@ def math_fix(g):
};
''' 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])
+ if not settings['SWAPPABLE_ASM_MODULE']:
+ receiving += ';\n'.join(['var ' + s + ' = Module["' + s + '"] = asm["' + s + '"]' for s in exported_implemented_functions + function_tables])
+ else:
+ receiving += 'Module["asm"] = asm;\n' + ';\n'.join(['var ' + s + ' = Module["' + s + '"] = function() { return Module["asm"]["' + s + '"].apply(null, arguments) }' for s in exported_implemented_functions + function_tables])
# finalize
@@ -1239,11 +1289,16 @@ def math_fix(g):
funcs_js = ['''
%s
+ Module%s = %s;
+ Module%s = %s;
// EMSCRIPTEN_START_ASM
var asm = (function(global, env, buffer) {
%s
%s
- ''' % (asm_setup, "'use asm';" if not metadata.get('hasInlineJS') and not settings['SIDE_MODULE'] and settings['ASM_JS'] == 1 else "'almost asm';", '''
+ ''' % (asm_setup,
+ access_quote('asmGlobalArg'), the_global,
+ access_quote('asmLibraryArg'), sending,
+ "'use asm';" if not metadata.get('hasInlineJS') and not settings['SIDE_MODULE'] and settings['ASM_JS'] == 1 else "'almost asm';", '''
var HEAP8 = new global%s(buffer);
var HEAP16 = new global%s(buffer);
var HEAP32 = new global%s(buffer);
@@ -1294,7 +1349,7 @@ def math_fix(g):
''' + ''.join(['''
var tempRet%d = 0;''' % i for i in range(10)]) + '\n' + asm_global_funcs] + [' var tempFloat = %s;\n' % ('Math_fround(0)' if settings.get('PRECISE_F32') else '0.0')] + ([' const f0 = Math_fround(0);\n'] if settings.get('PRECISE_F32') else []) + ['' if not settings['ALLOW_MEMORY_GROWTH'] else '''
function _emscripten_replace_memory(newBuffer) {
- if ((byteLength(newBuffer) & 0xffffff || byteLength(newBuffer) <= 0xffffff)) return false;
+ if ((byteLength(newBuffer) & 0xffffff || byteLength(newBuffer) <= 0xffffff) || byteLength(newBuffer) > 0x80000000) return false;
HEAP8 = new Int8View(newBuffer);
HEAP16 = new Int16View(newBuffer);
HEAP32 = new Int32View(newBuffer);
@@ -1369,7 +1424,10 @@ def math_fix(g):
// EMSCRIPTEN_END_ASM
(%s, %s, buffer);
%s;
- ''' % (pre_tables + '\n'.join(function_tables_impls) + '\n' + function_tables_defs.replace('\n', '\n '), exports, the_global, sending, receiving)]
+ ''' % (pre_tables + '\n'.join(function_tables_impls) + '\n' + function_tables_defs.replace('\n', '\n '), exports,
+ 'Module' + access_quote('asmGlobalArg'),
+ 'Module' + access_quote('asmLibraryArg'),
+ receiving)]
if not settings.get('SIDE_MODULE'):
funcs_js.append('''
diff --git a/site/source/_templates/layout.html b/site/source/_templates/layout.html
new file mode 100644
index 0000000000000..ca6d84b674303
--- /dev/null
+++ b/site/source/_templates/layout.html
@@ -0,0 +1,22 @@
+{% extends '!layout.html' %}
+
+{% block footer %}
+
+
+
+
+{% endblock %}
+
diff --git a/site/source/conf.py b/site/source/conf.py
index 65f934205fab2..cf2e4e313362b 100644
--- a/site/source/conf.py
+++ b/site/source/conf.py
@@ -89,10 +89,13 @@
# |version| and |release|, also used in various other places throughout the
# built documents.
#
+
+emscripten_version = open(os.path.abspath(os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))), 'emscripten-version.txt'))).read().strip()
+
# The short X.Y version.
-version = '1.23'
+version = emscripten_version[:emscripten_version.rindex('.')]
# The full version, including alpha/beta/rc tags.
-release = '1.23.0'
+release = emscripten_version
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
diff --git a/site/source/docs/api_reference/bind.h.rst b/site/source/docs/api_reference/bind.h.rst
index 0a6b5349ba170..12371d08eb84e 100644
--- a/site/source/docs/api_reference/bind.h.rst
+++ b/site/source/docs/api_reference/bind.h.rst
@@ -710,17 +710,18 @@ Classes
.. code-block:: cpp
//prototype
- template
+ template
EMSCRIPTEN_ALWAYS_INLINE const class_& allow_subclass(
const char* wrapperClassName,
- const char* pointerName = "",
- ::emscripten::constructor = ::emscripten::constructor()
+ const char* pointerName,
+ ::emscripten::constructor = ::emscripten::constructor<>()
) const
**HamishW** Add description.
:param const char* wrapperClassName: **HamishW** Add description.
- :param const char* pointerName: **HamishW** Add description. Note that this has a default value which is dependent on the template typename parameters.
+ :param const char* pointerName: **HamishW** Add description.
+ :param ::emscripten::constructor constructor): **HamishW** Add description.
:returns: |class_-function-returns|
@@ -732,7 +733,7 @@ Classes
template
EMSCRIPTEN_ALWAYS_INLINE const class_& allow_subclass(
const char* wrapperClassName,
- ::emscripten::constructor constructor
+ ::emscripten::constructor constructor = ::emscripten::constructor<>()
) const
**HamishW** Add description. Explain how this constructor differs from other one.
diff --git a/site/source/docs/api_reference/emscripten.h.rst b/site/source/docs/api_reference/emscripten.h.rst
index 875b704b7d20c..6af650e895047 100644
--- a/site/source/docs/api_reference/emscripten.h.rst
+++ b/site/source/docs/api_reference/emscripten.h.rst
@@ -713,7 +713,7 @@ Functions
.. c:function:: void emscripten_worker_respond(char *data, int size)
void emscripten_worker_respond_provisionally(char *data, int size)
- Sends a response when in a worker call.
+ Sends a response when in a worker call (that is, when called by the main thread using :c:func:`emscripten_call_worker`).
Both functions post a message back to the thread which called the worker. The :c:func:`emscripten_worker_respond_provisionally` variant can be invoked multiple times, which will queue up messages to be posted to the worker’s creator. Eventually, the _respond variant must be invoked, which will disallow further messages and free framework resources previously allocated for this worker call.
@@ -852,38 +852,6 @@ Functions
:rtype: char*
-
-Networking backend
-==================
-
-Defines
--------
-
-.. c:macro:: EMSCRIPTEN_NETWORK_WEBSOCKETS
-
- Used to select the websockets networking backend in :c:func:`emscripten_set_network_backend`
-
-.. c:macro:: EMSCRIPTEN_NETWORK_WEBRTC
-
- Used to select the WebRTC networking backend in :c:func:`emscripten_set_network_backend`
-
-
-Functions
----------
-
-.. c:function:: void emscripten_set_network_backend(int backend)
-
- Selects the networking backend to use.
-
- .. note::
- - This function must be called before any network functions are called.
-
- By default Emscripten's socket/networking implementation will use websockets. With this function you can change that to WebRTC.
-
- :param int backend: The backend to use. One of :c:macro:`EMSCRIPTEN_NETWORK_WEBSOCKETS` and :c:macro:`EMSCRIPTEN_NETWORK_WEBRTC`
-
-
-
.. _emscripten-api-reference-sockets:
Socket event registration
diff --git a/site/source/docs/building_from_source/LLVM-Backend.rst b/site/source/docs/building_from_source/LLVM-Backend.rst
index 6747c0edac979..cc2dea78d4bbb 100644
--- a/site/source/docs/building_from_source/LLVM-Backend.rst
+++ b/site/source/docs/building_from_source/LLVM-Backend.rst
@@ -8,7 +8,7 @@ This article introduces *Fastcomp*, Emscripten's LLVM + Clang implementation. It
Fastcomp overview
-================
+=================
*Fastcomp* is the default compiler core for Emscripten. Implemented as an :term:`LLVM backend`, its role is to convert the LLVM Intermediate Representation (IR) created by :term:`Clang` (from C/C++) into JavaScript.
@@ -26,7 +26,7 @@ Fastcomp is maintained in two repositories:
Getting Fastcomp
================
-*Fastcomp* (Clang) is part of the :ref:`Emscripten SDK `, and the binaries are automatically provided during installation (except on Linux, where pre-built binaries are not supplied so the SDK builds them for you).
+*Fastcomp* (Clang) is part of the :ref:`Emscripten SDK `, and the binaries are automatically provided during installation (except on Linux, where pre-built binaries are not supplied so the SDK builds them for you).
If you need to build from source you can:
@@ -41,9 +41,9 @@ If you need to build from source you can:
Original compiler core (deprecated)
===================================
-The original compiler supported dozens of different code generation modes (no-typed arrays, typed arrays in various modes, **asm.js** vs. **non-asm.js**, etc.), many of which were not very efficient. Over time, the compiler became harder to maintain and was susceptible to unpredictable compiler slow-downs.
+The original compiler supported dozens of different code generation modes (no-typed arrays, typed arrays in various modes, **asm.js** vs. **non-asm.js**, etc.), many of which were not very efficient. Over time, the compiler became harder to maintain and was susceptible to unpredictable compiler slow-downs.
-*Fastcomp* was turned on by default in version 1.12.1. The original compiler is now "deprecated".
+*Fastcomp* was turned on by default in version 1.12.1. The original compiler is now "deprecated".
.. note:: While it is possible to manually disable Fastcomp and build the original compiler from source, this is discouraged.
@@ -56,13 +56,13 @@ As a result of the problems with the original compiler, we developed *Fastcomp*,
- It is much more streamlined than the original compiler. It focuses on **asm.js** code generation, which has been shown to give the best results.
- It is much faster and has more predictable performance (often 4x faster or more).
- It requires much less memory.
-- It generates better code because, as an LLVM backend, it integrates more tightly with LLVM.
+- It generates better code because, as an LLVM backend, it integrates more tightly with LLVM.
Are there downsides?
--------------------
-The main downside is that Emscripten can no longer use a stock build of LLVM, because we have made changes that must be built with LLVM.
+The main downside is that Emscripten can no longer use a stock build of LLVM, because we have made changes that must be built with LLVM.
There are also a few features that were present in the original compiler that are not present in *Fastcomp* (see the next section).
@@ -76,18 +76,18 @@ Some features that were present in the original compiler that are not present in
- Various deprecated **settings.js** options (``FORCE_ALIGNMENT``, ``HEAP_INIT``, etc.) You should receive a compile-time error if you use a setting which is not supported.
- Linking of **asm.js** shared modules. This is not deprecated, but may need to be reconsidered.
- .. note:: Normal static linking as used by almost all projects works fine; it is just specifically the options ``MAIN_MODULE`` and ``SIDE_MODULE`` that do not work.
+ .. note:: Normal static linking as used by almost all projects works fine; it is just specifically the options ``MAIN_MODULE`` and ``SIDE_MODULE`` that do not work.
+
-
How to disable Fastcomp
-----------------------
.. warning:: You should **NOT** disable Fastcomp. If you "really must", then:
- - The build will be slower, consume more memory, and result in sub-optimal code.
- - There are more likely to be bugs, because the old compiler is less tested.
+ - The build will be slower, consume more memory, and result in sub-optimal code.
+ - There are more likely to be bugs, because the old compiler is less tested.
-The original compiler is still present, and you may want to use it if you need a feature that is not yet present in *Fastcomp*. There should be very few such features, as almost everything that is not deprecated or planned to be rewritten has already been ported.
+The original compiler is still present, and you may want to use it if you need a feature that is not yet present in *Fastcomp*. There should be very few such features, as almost everything that is not deprecated or planned to be rewritten has already been ported.
However, if you do need to, you can use the old compiler by turning off *Fastcomp*; you do this by setting ``EMCC_FAST_COMPILER=0`` when you build:
::
diff --git a/site/source/docs/compiling/Building-Projects.rst b/site/source/docs/compiling/Building-Projects.rst
index 817d9a51e254b..424c125928665 100644
--- a/site/source/docs/compiling/Building-Projects.rst
+++ b/site/source/docs/compiling/Building-Projects.rst
@@ -130,7 +130,7 @@ For more general information, see the topic :ref:`Debugging`.
Using libraries
===============
-Built in support is available for a number of standard libraries: *libc*, *libc++* and *SDL*. These will automatically be linked when you compile code that uses them (you do not even need to add ``-lSDL``).
+Built in support is available for a number of standard libraries: *libc*, *libc++* and *SDL*. These will automatically be linked when you compile code that uses them (you do not even need to add ``-lSDL``, but see below for more SDL-specific details).
If your project uses other libraries, for example `zlib `_ or *glib*, you will need to build and link them. The normal approach is to build the libraries to bitcode and then compile library and main program bitcode together to JavaScript.
@@ -165,13 +165,30 @@ It is also possible to link the bitcode libraries first, and then compile the co
-SDL Configuration
-=================
+Emscripten Ports
+================
+
+Emscripten Ports is a collection of useful libraries, ported to Emscripten. They reside `on github `_, and have integration support in *emcc*. When you request that a port be used, emcc will fetch it from the remote server, set it up and build it locally, then link it with your project, add necessary include to your build commands, etc. For example, SDL2 is in ports, and you can request that it be used with ``-s USE_SDL=2``. For example,
+
+.. code-block:: bash
+
+ ./emcc tests/sdl2glshader.c -s USE_SDL=2 -s LEGACY_GL_EMULATION=1 -o sdl2.html
+
+You should see some notifications about SDL2 being used, and built if it wasn't previously. You can then view ``sdl2.html`` in your browser.
+
+.. note:: *SDL_image* has also been added to ports, use it with ``-s USE_SDL_IMAGE=2``. To see a list of all available ports, run ``emcc --show-ports``.
+
+.. note:: Emscripten also has support for older SDL1, which is built in. If you do not specify SDL2 as in the command above, then SDL1 is linked in and the SDL1 include paths are used. SDL1 has support for *sdl-config*, which is present in `system/bin `_. Using the native *sdl-config* may result in compilation or missing-symbol errors. You will need to modify the build system to look for files in **emscripten/system** or **emscripten/system/bin** in order to use the Emscripten *sdl-config*.
-Projects that depend on SDL should use the Emscripten version of *sdl-config*, which is present in `system/bin `_. Using the native *sdl-config* may result in compilation or missing-symbol errors.
+Adding more ports
+-----------------
-.. note:: Modify the build system to look for files in **emscripten/system** or **emscripten/system/bin** in order to use SDL properly (the approach will be build system-specific).
+Adding more ports is fairly easy. Basically, the steps are
+ * Make sure the port is open source and has a suitable license.
+ * Add it to emscripten-ports on github. The ports maintainers can create the repo and add the relevant developers to a team for that repo, so they have write access.
+ * Add a script to handle it under ``tools/ports/`` (see existing code for examples) and use it in ``tools/ports/__init__.py``.
+ * Add testing in the test suite.
Build system issues
diff --git a/site/source/docs/introducing_emscripten/Talks-and-Publications.rst b/site/source/docs/introducing_emscripten/Talks-and-Publications.rst
index a592161d281d3..c64a7ead78fe5 100644
--- a/site/source/docs/introducing_emscripten/Talks-and-Publications.rst
+++ b/site/source/docs/introducing_emscripten/Talks-and-Publications.rst
@@ -9,6 +9,7 @@ Presentations
- Slides from CppCon 2014:
- `Emscripten & asm.js: C++'s role in the modern web `_ (`kripken `_)
+ - `Video of talk `_
- `Connecting C++ and JavaScript on the Web with Embind `_ (`chadaustin `_)
- `Video of talk `_
diff --git a/site/source/docs/porting/connecting_cpp_and_javascript/Interacting-with-code.rst b/site/source/docs/porting/connecting_cpp_and_javascript/Interacting-with-code.rst
index baf3978b3e814..bbca9a5cfabe4 100644
--- a/site/source/docs/porting/connecting_cpp_and_javascript/Interacting-with-code.rst
+++ b/site/source/docs/porting/connecting_cpp_and_javascript/Interacting-with-code.rst
@@ -5,33 +5,38 @@ Interacting with code
=====================
-Emscripten provides numerous methods to connect and interact between JavaScript and compiled C or C++:
+Emscripten provides numerous methods to connect and interact between
+JavaScript and compiled C or C++:
- Call compiled **C** functions from normal JavaScript:
- - :ref:`Using ccall or cwrap `.
- - :ref:`Using direct function calls ` (faster but more complicated).
+ - :ref:`Using ccall or cwrap `.
+ - :ref:`Using direct function calls ` (faster but more complicated).
-- Call compiled **C++** classes from JavaScript using bindings created with:
+- Call compiled **C++** classes from JavaScript using bindings
+ created with:
+
+ - :ref:`Embind or WebIDL-Binder`
- - :ref:`Embind or WebIDL-Binder`
-
- Call JavaScript functions from **C/C++**:
- - :ref:`Using emscripten_run_script() `.
- - :ref:`Using EM_ASM() ` (faster).
- - :ref:`Using a C API implemented in JavaScript `.
- - :ref:`As function pointers from C `.
- - :ref:`Using the Embind val class `.
+ - :ref:`Using emscripten_run_script() `.
+ - :ref:`Using EM_ASM() ` (faster).
+ - :ref:`Using a C API implemented in JavaScript `.
+ - :ref:`As function pointers from C `.
+ - :ref:`Using the Embind val class `.
- :ref:`Access compiled code memory from JavaScript `.
- :ref:`Affect execution behaviour `.
- :ref:`Access environment variables `.
-This article explains each of the methods listed above, and provides links to more detailed information.
+This article explains each of the methods listed above, and provides links
+to more detailed information.
-.. note:: For information on how compiled code interacts with the browser environment, see :ref:`emscripten-runtime-environment`. For file system related manners, see the :ref:`file-system-overview`.
+.. note:: For information on how compiled code interacts with the browser
+ environment, see :ref:`emscripten-runtime-environment`. For file system
+ related manners, see the :ref:`file-system-overview`.
.. _interacting-with-code-ccall-cwrap:
@@ -39,79 +44,129 @@ This article explains each of the methods listed above, and provides links to mo
Calling compiled C functions from JavaScript using ccall/cwrap
==============================================================
-The easiest way to call compiled C functions from JavaScript is to use :js:func:`ccall` or :js:func:`cwrap`.
+The easiest way to call compiled C functions from JavaScript is to use
+:js:func:`ccall` or :js:func:`cwrap`.
-:js:func:`ccall` calls a compiled C function with specified parameters and returns the result, while :js:func:`cwrap` "wraps" a compiled C function and returns a JavaScript function you can call normally. :js:func:`cwrap` is therefore more useful if you plan to call a compiled function a number of times.
+:js:func:`ccall` calls a compiled C function with specified parameters
+and returns the result, while :js:func:`cwrap` "wraps" a compiled C
+function and returns a JavaScript function you can call normally.
+:js:func:`cwrap` is therefore more useful if you plan to call a compiled
+function a number of times.
-Consider the **tests/hello_function.cpp** file shown below. The ``int_sqrt()`` function to be compiled is wrapped in ``extern "C"`` to prevent C++ name mangling.
+Consider the **tests/hello_function.cpp** file shown below. The
+``int_sqrt()`` function to be compiled is wrapped in ``extern "C"``
+to prevent C++ name mangling.
.. include:: ../../../../../tests/hello_function.cpp
- :literal:
-
-To compile this code run the following command in the Emscripten home directory:
+ :literal:
-::
+To compile this code run the following command in the Emscripten
+home directory::
./emcc tests/hello_function.cpp -o function.html -s EXPORTED_FUNCTIONS="['_int_sqrt']"
-After compiling, you can call this function with :js:func:`cwrap` using the following JavaScript:
-
-::
+After compiling, you can call this function with :js:func:`cwrap` using the
+following JavaScript::
int_sqrt = Module.cwrap('int_sqrt', 'number', ['number'])
int_sqrt(12)
int_sqrt(28)
-The first parameter is the name of the function to be wrapped, the second is the return type of the function, and the third is an array of parameter types (which may be omitted if there are no parameters). The types are native JavaScript types, "number" (for a C integer, float, or general pointer) or "string" (for a C ``char*`` that represents a string).
+The first parameter is the name of the function to be wrapped, the second is
+the return type of the function, and the third is an array of parameter
+types (which may be omitted if there are no parameters). The types are
+native JavaScript types, "number" (for a C integer, float, or general
+pointer) or "string" (for a C ``char*`` that represents a string).
-You can run this yourself by first opening the generated page **function.html** in a web browser (nothing will happen on page load because there is no ``main()``). Open a JavaScript environment (**Control-Shift-K** on Firefox, **Control-Shift-J** on Chrome), and enter the above commands as three separate commands, pressing **Enter** after each one. You should get the results ``3`` and ``5`` — the expected output for these inputs using C++ integer mathematics.
+You can run this yourself by first opening the generated page
+**function.html** in a web browser (nothing will happen on page
+load because there is no ``main()``). Open a JavaScript environment
+(**Control-Shift-K** on Firefox, **Control-Shift-J** on Chrome),
+and enter the above commands as three separate commands, pressing
+**Enter** after each one. You should get the results ``3`` and
+``5`` — the expected output for these inputs using C++ integer
+mathematics.
-:js:func:`ccall` is similar, but receives another parameter with the parameters to pass to the function:
+:js:func:`ccall` is similar, but receives another parameter with the
+parameters to pass to the function:
.. code-block:: javascript
- // Call C from JavaScript
- var result = Module.ccall('int_sqrt', // name of C function
- 'number', // return type
- ['number'], // argument types
- [28]); // arguments
+ // Call C from JavaScript
+ var result = Module.ccall('int_sqrt', // name of C function
+ 'number', // return type
+ ['number'], // argument types
+ [28]); // arguments
- // result is 5
+ // result is 5
.. note::
- This example illustrates a few other points, which you should remember when using :js:func:`ccall` or :js:func:`cwrap`:
+ This example illustrates a few other points, which you should remember
+ when using :js:func:`ccall` or :js:func:`cwrap`:
+
+ - These methods can be used with compiled **C** functions — name-mangled
+ C++ functions won't work.
+ - We highly recommended that you *export* functions that are to be called
+ from JavaScript:
+
+ - Exporting is done at compile time. For example:
+ ``-s EXPORTED_FUNCTIONS='["_main","_other_function"]'`` exports
+ ``main()`` and ``other_function()``. You need ``_`` at the
+ beginning of the function names in the ``EXPORTED_FUNCTIONS`` list.
+ - Emscripten does :ref:`dead code elimination `
+ to minimize code size — exporting ensures the functions you need
+ aren't removed.
+ - At higher optimisation levels (``-O2`` and above), the
+ :term:`closure compiler` runs and minifies (changes) function names.
+ Exporting functions allows you to continue to access them using the
+ original name through the global ``Module`` object.
+
+ - Use ``Module.ccall`` and not ``ccall`` by itself. The former will work
+ at all optimisation levels (even if the :term:`Closure Compiler`
+ minifies the function names).
- - These methods can be used with compiled **C** functions — name-mangled C++ functions won't work.
- - We highly recommended that you *export* functions that are to be called from JavaScript:
-
- - Exporting is done at compile time. For example: ``-s EXPORTED_FUNCTIONS='["_main","_other_function"]'`` exports ``main()`` and ``other_function()``. You need ``_`` at the beginning of the function names in the ``EXPORTED_FUNCTIONS`` list.
- - Emscripten does :ref:`dead code elimination ` to minimize code size — exporting ensures the functions you need aren't removed.
- - At higher optimisation levels (``-O2`` and above), the :term:`closure compiler` runs and minifies (changes) function names. Exporting functions allows you to continue to access them using the original name through the global ``Module`` object.
-
- - Use ``Module.ccall`` and not ``ccall`` by itself. The former will work at all optimisation levels (even if the :term:`Closure Compiler` minifies the function names).
-
.. _interacting-with-code-direct-function-calls:
-
+
Call compiled C/C++ code "directly" from JavaScript
===================================================
-Functions in the original source become JavaScript functions, so you can call them directly if you do type translations yourself — this will be faster than using :js:func:`ccall` or :js:func:`cwrap`, but a little more complicated.
+Functions in the original source become JavaScript functions, so you can
+call them directly if you do type translations yourself — this will be
+faster than using :js:func:`ccall` or :js:func:`cwrap`, but a little
+more complicated.
-To call the method directly, you will need to use the full name as it appears in the generated code. This will be the same as the original C function, but with a leading ``_``.
+To call the method directly, you will need to use the full name as it
+appears in the generated code. This will be the same as the original C
+function, but with a leading ``_``.
-.. note:: If you use :js:func:`ccall` or :js:func:`cwrap`, you do not need to prefix function calls with ``_`` — just use the C name.
+.. note:: If you use :js:func:`ccall` or :js:func:`cwrap`, you do not need
+ to prefix function calls with ``_`` — just use the C name.
-The types of the parameters you pass to functions need to make sense. Integers and floating point values can be passed as is. Pointers are simply integers in the generated code.
+The types of the parameters you pass to functions need to make sense.
+Integers and floating point values can be passed as is. Pointers are
+simply integers in the generated code.
-Strings in JavaScript must be converted to pointers for compiled code — the relevant function is :js:func:`Pointer_stringify`, which given a pointer returns a JavaScript string. Converting a JavaScript string ``someString`` to a pointer can be accomplished using :js:func:`allocate(intArrayFromString(someString), 'i8', ALLOC_STACK) `.
+Strings in JavaScript must be converted to pointers for compiled
+code — the relevant function is :js:func:`Pointer_stringify`, which
+given a pointer returns a JavaScript string. Converting a JavaScript
+string ``someString`` to a pointer can be accomplished using
+:js:func:`allocate(intArrayFromString(someString), 'i8', ALLOC_STACK) `.
-.. note:: The conversion to a pointer allocates memory, and in this case we allocate it on the stack (if you are calling it from a compiled function, it will rewind the stack for you; otherwise, you should do ``Runtime.stackSave()`` before and ``Runtime.stackRestore(..that value..)`` afterwards).
+.. note:: The conversion to a pointer allocates memory, and in this case
+ we allocate it on the stack (if you are calling it from a compiled
+ function, it will rewind the stack for you; otherwise, you should
+ do ``Runtime.stackSave()`` before and
+ ``Runtime.stackRestore(..that value..)`` afterwards).
-There are other convenience functions for converting strings and encodings in :ref:`preamble-js`.
+There are other convenience functions for converting strings and encodings
+in :ref:`preamble-js`.
-.. todo:: **HamishW** Might be better to show the allocate above using _malloc, as allocate is an advanced API. We also need to better explain the note about stackRestore etc, or remove it - as it doesn't mean a lot to me.
+.. todo:: **HamishW** Might be better to show the allocate above using
+ _malloc, as allocate is an advanced API. We also need to better
+ explain the note about stackRestore etc, or remove it - as it
+ doesn't mean a lot to me.
.. _interacting-with-code-call-javascript-from-native:
@@ -119,34 +174,52 @@ There are other convenience functions for converting strings and encodings in :r
Calling JavaScript from C/C++
=============================
-Emscripten provides two main approaches for calling JavaScript from C/C++: running the script using :c:func:`emscripten_run_script` or writing "inline JavaScript".
+Emscripten provides two main approaches for calling JavaScript from C/C++:
+running the script using :c:func:`emscripten_run_script` or writing
+"inline JavaScript".
-The most direct, but slightly slower, way is to use :c:func:`emscripten_run_script`. This effectively runs the specified JavaScript code from C/C++ using ``eval()``. For example, to call the browser's ``alert()`` function with the text 'hi', you would call the following JavaScript:
+The most direct, but slightly slower, way is to use
+:c:func:`emscripten_run_script`. This effectively runs the specified
+JavaScript code from C/C++ using ``eval()``. For example, to call the
+browser's ``alert()`` function with the text 'hi', you would call the
+following JavaScript:
.. code-block:: javascript
- emscripten_run_script("alert('hi')");
+ emscripten_run_script("alert('hi')");
-.. note:: The function ``alert`` is present in browsers, but not in *node* or other JavaScript shells. A more generic alternative is to call :js:func:`Module.print`.
+.. note:: The function ``alert`` is present in browsers, but not in *node*
+ or other JavaScript shells. A more generic alternative is to call
+ :js:func:`Module.print`.
-A faster way to call JavaScript from C is to write "inline JavaScript", using :c:func:`EM_ASM` (and related macros). These are used in a similar manner to inline assembly code. The "alert" example above might be written using inline JavaScript as:
+A faster way to call JavaScript from C is to write "inline JavaScript",
+using :c:func:`EM_ASM` (and related macros). These are used in a similar
+manner to inline assembly code. The "alert" example above might be
+written using inline JavaScript as:
.. code-block:: c++
- #include
-
- int main() {
- EM_ASM(
- alert('hello world!');
- throw 'all done';
- );
- return 0;
- }
+ #include
-When compiled and run, Emscripten will execute the two lines of JavaScript as if they appeared directly in the generated code. The result would be an alert, followed by an exception. (Note, however, that under the hood Emscripten still does a function call even in this case, which has some amount of overhead.)
+ int main() {
+ EM_ASM(
+ alert('hello world!');
+ throw 'all done';
+ );
+ return 0;
+ }
-You can also send values from C into JavaScript inside :c:macro:`EM_ASM_`, as well as receive values back (see the :c:macro:`linked macro ` for details. The following example will print out ``I received: 100`` and then ``101``.
+When compiled and run, Emscripten will execute the two lines of JavaScript
+as if they appeared directly in the generated code. The result would be
+an alert, followed by an exception. (Note, however, that under the hood
+Emscripten still does a function call even in this case, which has some
+amount of overhead.)
+
+You can also send values from C into JavaScript inside :c:macro:`EM_ASM_`,
+as well as receive values back (see the :c:macro:`linked macro `
+for details. The following example will print out ``I received: 100``
+and then ``101``.
.. code-block:: cpp
@@ -156,13 +229,20 @@ You can also send values from C into JavaScript inside :c:macro:`EM_ASM_`, as we
}, 100);
printf("%d\n", x);
-.. note::
+.. note::
- - You need to specify if the return value is an ``int`` or a ``double`` using the appropriate macro :c:macro:`EM_ASM_INT` or :c:macro:`EM_ASM_DOUBLE`.
- - The input values appear as ``$0``, ``$1``, etc.
- - ``return`` is used to provide the value sent from JavaScript back to C.
- - See how ``{`` and ``}`` are used here to enclose the code. This is necessary to differentiate the code from the arguments passed later, which are the input values (this is how C macros work).
- - When using the :c:macro:`EM_ASM` macro, ensure that you only use single quotes('). Double quotes(") will cause a syntax error that is not detected by the compiler and is only shown when looking at a JavaScript console while running the offending code.
+ - You need to specify if the return value is an ``int`` or a ``double``
+ using the appropriate macro :c:macro:`EM_ASM_INT` or
+ :c:macro:`EM_ASM_DOUBLE`.
+ - The input values appear as ``$0``, ``$1``, etc.
+ - ``return`` is used to provide the value sent from JavaScript back to C.
+ - See how ``{`` and ``}`` are used here to enclose the code. This is
+ necessary to differentiate the code from the arguments passed later,
+ which are the input values (this is how C macros work).
+ - When using the :c:macro:`EM_ASM` macro, ensure that you only use
+ single quotes('). Double quotes(") will cause a syntax error that
+ is not detected by the compiler and is only shown when looking at
+ a JavaScript console while running the offending code.
.. _implement-c-in-javascript:
@@ -170,11 +250,24 @@ You can also send values from C into JavaScript inside :c:macro:`EM_ASM_`, as we
Implement a C API in JavaScript
===============================
-It is possible to implement a C API in JavaScript! This is the approach that was used to write Emscripten's implementations of :term:`SDL` and *libc*.
-
-You can use it to write your own APIs to call from C/C++. To do this you define the interface, decorating with ``extern`` to mark the methods in the API as external symbols. You then implement the symbols in JavaScript by simply adding their definition to `library.js `_ (by default). When compiling the C code, the compiler looks in the JavaScript libraries for relevant external symbols.
-
-By default, the implementation is added to **library.js** (and this is where you'll find the Emscripten implementation of *libc*). You can put the JavaScript implementation in your own library file and add it using the :ref:`emcc option ` ``--js-library``. See `test_js_libraries `_ in **tests/test_other.py** for a complete working example, including the syntax you should use inside the JavaScript library file.
+It is possible to implement a C API in JavaScript! This is the approach
+that was used to write Emscripten's implementations of :term:`SDL` and
+*libc*.
+
+You can use it to write your own APIs to call from C/C++. To do this
+you define the interface, decorating with ``extern`` to mark the methods
+in the API as external symbols. You then implement the symbols in
+JavaScript by simply adding their definition to `library.js`_ (by
+default). When compiling the C code, the compiler looks in the JavaScript
+libraries for relevant external symbols.
+
+By default, the implementation is added to **library.js** (and this is
+where you'll find the Emscripten implementation of *libc*). You can put
+the JavaScript implementation in your own library file and add it using
+the :ref:`emcc option ` ``--js-library``. See
+`test_js_libraries`_ in **tests/test_other.py** for a complete working
+example, including the syntax you should use inside the JavaScript library
+file.
As a simple example, consider the case where you have some C code like this:
@@ -187,41 +280,57 @@ As a simple example, consider the case where you have some C code like this:
return 1;
}
-.. note:: When using C++ you should encapsulate ``extern void my_js();`` in an ``extern "C" {}`` block to prevent C++ name mangling:
+.. note:: When using C++ you should encapsulate ``extern void my_js();``
+ in an ``extern "C" {}`` block to prevent C++ name mangling:
- .. code-block:: cpp
+ .. code-block:: cpp
- extern "C" {
- extern void my_js();
- }
+ extern "C" {
+ extern void my_js();
+ }
-Then you can implement ``my_js`` in JavaScript by simply adding the implementation to **library.js** (or your own file). Like our other examples of calling JavaScript from C, the example below just creates a dialog box using a simple ``alert()`` function.
+Then you can implement ``my_js`` in JavaScript by simply adding the
+implementation to **library.js** (or your own file). Like our other
+examples of calling JavaScript from C, the example below just creates
+a dialog box using a simple ``alert()`` function.
.. code-block:: javascript
- my_js: function() {
- alert('hi');
- },
+ my_js: function() {
+ alert('hi');
+ },
If you add it to your own file, you should write something like
.. code-block:: javascript
- mergeInto(LibraryManager.library, {
- my_js: function() {
- alert('hi');
- },
- });
+ mergeInto(LibraryManager.library, {
+ my_js: function() {
+ alert('hi');
+ },
+ });
-``mergeInto`` just copies the properties on the second parameter onto the first, so this add ``my_js`` onto ``LibraryManager.library``, the global object where all JavaScript library code should be.
+``mergeInto`` just copies the properties on the second parameter onto the
+first, so this add ``my_js`` onto ``LibraryManager.library``, the global
+object where all JavaScript library code should be.
-See the `library_*.js `_ files for other examples.
+See the `library_*.js`_ files for other examples.
-.. note::
+.. note::
- - JavaScript libraries can declare dependencies (``__deps``), however those are only for other JavaScript libraries. See examples in `/src `_ with the name format **library_*.js**
- - You can add dependencies for all your methods using ``autoAddDeps(myLibrary, name)`` where myLibrary is the object with all your methods, and ``name`` is the thing they all depend upon. This is useful when all the implemented methods use a JavaScript singleton containing helper methods. See ``library_gl.js`` for an example.
- - If a JavaScript library depends on a compiled C library (like most of *libc*), you must edit `src/deps_info.json `_. Search for "deps_info" in `tools/system_libs.py `_.
+ - JavaScript libraries can declare dependencies (``__deps``), however
+ those are only for other JavaScript libraries. See examples in
+ `/src `_
+ with the name format **library_*.js**
+ - You can add dependencies for all your methods using
+ ``autoAddDeps(myLibrary, name)`` where myLibrary is the object with
+ all your methods, and ``name`` is the thing they all depend upon.
+ This is useful when all the implemented methods use a JavaScript
+ singleton containing helper methods. See ``library_gl.js`` for
+ an example.
+ - If a JavaScript library depends on a compiled C library (like most
+ of *libc*), you must edit `src/deps_info.json`_. Search for
+ "deps_info" in `tools/system_libs.py`_.
.. _interacting-with-code-call-function-pointers-from-c:
@@ -229,34 +338,58 @@ See the `library_*.js `_
Calling JavaScript 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 JavaScript function you sent to ``Runtime.addFunction`` will be called.
+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 JavaScript function you sent to
+``Runtime.addFunction`` will be called.
+
+See `test_add_function in tests/test_core.py`_ for an example.
-See ``test_add_function`` in `tests/test_core.py `_ for an example.
+When using ``Runtime.addFunction``, there is a backing array where these
+functions are stored. This array must be explicitly sized, which can be
+done via a compile-time setting, ``RESERVED_FUNCTION_POINTERS``. For
+example, to reserve space for 20 functions to be added::
+ emcc ... -s RESERVED_FUNCTION_POINTERS=20 ...
.. _interacting-with-code-access-memory:
Access memory from JavaScript
=============================
-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 ``*``).
+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 ``*``).
-There are examples of these functions being used in the tests — see `tests/core/test_utf.in `_ and `tests/test_core.py `_.
+There are examples of these functions being used in the tests — see
+`tests/core/test_utf.in`_ and `tests/test_core.py`_.
-.. note:: This is a lower-level operation than :js:func:`ccall` and :js:func:`cwrap` — we *do* need to care what specific type (e.g. integer) is being used.
+.. note:: This is a lower-level operation than :js:func:`ccall` and
+ :js:func:`cwrap` — we *do* need to care what specific type (e.g.
+ integer) is being used.
-You can also access memory 'directly' by manipulating the arrays that represent memory. This is not recommended unless you are sure you know what you are doing, and need the additional speed over :js:func:`getValue`/:js:func:`setValue`.
+You can also access memory 'directly' by manipulating the arrays that
+represent memory. This is not recommended unless you are sure you know
+what you are doing, and need the additional speed over :js:func:`getValue`
+and :js:func:`setValue`.
-A case where this might be required is if you want to import a large amount of data from JavaScript to be processed by compiled code. For example, the following code allocates a buffer, copies in some data, calls a C function to process the data, and finally frees the buffer.
+A case where this might be required is if you want to import a large amount
+of data from JavaScript to be processed by compiled code. For example, the
+following code allocates a buffer, copies in some data, calls a C function
+to process the data, and finally frees the buffer.
.. code-block:: javascript
- var buf = Module._malloc(myTypedArray.length*myTypedArray.BYTES_PER_ELEMENT);
- Module.HEAPU8.set(myTypedArray, buf);
- Module.ccall('my_function', 'number', ['number'], [buf]);
- Module._free(buf);
+ var buf = Module._malloc(myTypedArray.length*myTypedArray.BYTES_PER_ELEMENT);
+ Module.HEAPU8.set(myTypedArray, buf);
+ Module.ccall('my_function', 'number', ['number'], [buf]);
+ Module._free(buf);
-Here ``my_function`` is a C function that receives a single integer parameter (or a pointer, they are both just 32-bit integers for us) and returns an integer. This could be something like ``int my_function(char *buf)``.
+Here ``my_function`` is a C function that receives a single integer parameter
+(or a pointer, they are both just 32-bit integers for us) and returns an
+integer. This could be something like ``int my_function(char *buf)``.
.. _interacting-with-code-execution-behaviour:
@@ -264,41 +397,79 @@ Here ``my_function`` is a C function that receives a single integer parameter (o
Affect execution behaviour
==========================
-``Module`` is a global JavaScript object, with attributes that Emscripten-generated code calls at various points in its execution.
+``Module`` is a global JavaScript object, with attributes that
+Emscripten-generated code calls at various points in its execution.
-Developers provide an implementation of ``Module`` to control how notifications from Emscripten are displayed, which files that are loaded before the main loop is run, and a number of other behaviours. For more information see :ref:`module`.
+Developers provide an implementation of ``Module`` to control how
+notifications from Emscripten are displayed, which files that are
+loaded before the main loop is run, and a number of other behaviours.
+For more information see :ref:`module`.
.. _interacting-with-code-environment-variables:
Environment variables
=====================
-Sometimes compiled code needs to access environment variables (for instance, in C, by calling the ``getenv()`` function). Emscripten-generated JavaScript cannot access the computer's environment variables directly, so a "virtualised" environment is provided.
+Sometimes compiled code needs to access environment variables (for instance,
+in C, by calling the ``getenv()`` function). Emscripten-generated JavaScript
+cannot access the computer's environment variables directly, so a
+"virtualised" environment is provided.
-The JavaScript object ``ENV`` contains the 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.
+The JavaScript object ``ENV`` contains the 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.
-For example, to set an environment variable ``MY_FILE_ROOT`` to be ``"/usr/lib/test/"`` you could add the following JavaScript to your ``Module`` :ref:`setup code `:
+For example, to set an environment variable ``MY_FILE_ROOT`` to be
+``"/usr/lib/test/"`` you could add the following JavaScript to your
+``Module`` :ref:`setup code `:
.. code:: javascript
Module.preRun.push(function() {ENV.MY_FILE_ROOT = "/usr/lib/test"})
.. _interacting-with-code-binding-cpp:
-
+
Binding C++ and JavaScript — WebIDL Binder and Embind
======================================================
-The JavaScript methods for calling compiled C functions are efficient, but cannot be used with name-mangled C++ functions.
+The JavaScript methods for calling compiled C functions are efficient, but
+cannot be used with name-mangled C++ functions.
-:ref:`WebIDL-Binder` and :ref:`embind` create bindings between C++ and JavaScript, allowing C++ code entities to be used in a natural manner from JavaScript. *Embind* additionally supports calling JavaScript code from C++.
+:ref:`WebIDL-Binder` and :ref:`embind` create bindings between C++ and
+JavaScript, allowing C++ code entities to be used in a natural manner from
+JavaScript. *Embind* additionally supports calling JavaScript code from C++.
-*Embind* can bind almost any C++ code, including sophisticated C++ constructs (e.g. ``shared_ptr`` and ``unique_ptr``). The *WebIDL Binder* supports C++ types that can be expressed in WebIDL. While this subset is smaller than supported by *Embind*, it is more than sufficient for most use cases — examples of projects that have been ported using the binder include the `Box2D `_ and `Bullet `_ physics engines.
+*Embind* can bind almost any C++ code, including sophisticated C++ constructs
+(e.g. ``shared_ptr`` and ``unique_ptr``). The *WebIDL Binder* supports C++
+types that can be expressed in WebIDL. While this subset is smaller than
+supported by *Embind*, it is more than sufficient for most use cases —
+examples of projects that have been ported using the binder include the
+`Box2D`_ and `Bullet`_ physics engines.
-Both tools allow mapped items to be used from JavaScript in a similar way. However they operate at different levels, and use very different approaches for defining the binding:
+Both tools allow mapped items to be used from JavaScript in a similar way.
+However they operate at different levels, and use very different approaches
+for defining the binding:
- *Embind* declares bindings within the C/C++ file.
-- *WebIDL-Binder* declares the binding in a separate file. This is run through the binder tool to create "glue" code that is then compiled with the project.
-
-.. note:: There is no strong evidence that one tool is "better" than the other in terms of performance (no comparative benchmarks exist), and both have been used successfully in a number of projects. The selection of one tool over the other will usually be based on which is the most natural fit for the project and its build system.
-
-
+- *WebIDL-Binder* declares the binding in a separate file. This is run
+ through the binder tool to create "glue" code that is then compiled
+ with the project.
+
+.. note:: There is no strong evidence that one tool is "better" than the
+ other in terms of performance (no comparative benchmarks exist), and
+ both have been used successfully in a number of projects. The selection
+ of one tool over the other will usually be based on which is the most
+ natural fit for the project and its build system.
+
+.. _library.js: https://github.com/kripken/emscripten/blob/master/src/library.js
+.. _test_js_libraries: https://github.com/kripken/emscripten/blob/master/tests/test_core.py#L4800
+.. _src/deps_info.json: https://github.com/kripken/emscripten/blob/master/src/deps_info.json
+.. _tools/system_libs.py: https://github.com/kripken/emscripten/blob/master/tools/system_libs.py
+.. _library_\*.js: https://github.com/kripken/emscripten/tree/master/src
+.. _test_add_function in tests/test_core.py: https://github.com/kripken/emscripten/blob/master/tests/test_core.py#L5904
+.. _tests/core/test_utf.in: https://github.com/kripken/emscripten/blob/master/tests/core/test_utf.in
+.. _tests/test_core.py: https://github.com/kripken/emscripten/blob/master/tests/test_core.py#L5704
+.. _Box2D: https://github.com/kripken/box2d.js/#box2djs
+.. _Bullet: https://github.com/kripken/ammo.js/#ammojs
diff --git a/site/source/docs/porting/guidelines/function_pointer_issues.rst b/site/source/docs/porting/guidelines/function_pointer_issues.rst
index a6450ce758cdb..940a45d64314c 100644
--- a/site/source/docs/porting/guidelines/function_pointer_issues.rst
+++ b/site/source/docs/porting/guidelines/function_pointer_issues.rst
@@ -55,10 +55,11 @@ As mentioned :ref:`above `, in **asm.js** m
.. note:: Having a separate table for each type of function pointer allows the JavaScript engine to know the exact type of each function pointer call, and optimize those calls much better than would otherwise be possible.
-There are two solutions to this problem (the second is preferred):
+There are three solutions to this problem (the second is preferred):
- Cast the function pointer back to the correct type before it is called. This is problematic because it requires that the caller knows the original type.
- Make an adapter function that does not need to be cast, and will hence be found in the correct function-pointer table. From the adaptor function call the original function.
+ - Use ``EMULATE_FUNCTION_POINTER_CASTS``. When you build with ``-s EMULATE_FUNCTION_POINTER_CASTS=1``, Emscripten emits code to emulate function pointer casts at runtime, adding extra arguments/dropping them/changing their type/adding or dropping a return type/etc. This can add significant runtime overhead, so it is not recommended, but might be worth trying.
For a real-world example, consider the code below:
diff --git a/site/source/docs/tools_reference/emcc.rst b/site/source/docs/tools_reference/emcc.rst
index af1997857a7b5..d01394d4059a6 100644
--- a/site/source/docs/tools_reference/emcc.rst
+++ b/site/source/docs/tools_reference/emcc.rst
@@ -367,7 +367,21 @@ Options that are modified or new in *emcc* are listed below:
Manually clears the cache of compiled Emscripten system libraries (libc++, libc++abi, libc).
This is normally handled automatically, but if you update LLVM in-place (instead of having a different directory for a new version), the caching mechanism can get confused. Clearing the cache can fix weird problems related to cache incompatibilities, like *Clang* failing to link with library files. This also clears other cached data like the jcache and the bootstrapped relooper. After the cache is cleared, this process will exit.
+
+.. _emcc-clear-ports:
+
+``--clear-ports``
+ Manually clears the local copies and builds of projects from the Emscripten Ports repos (sdl2, etc.)
+
+ You should only need to do this if a problem happens and you want all ports that you use to be downloaded and built from scratch. After this operation is complete, this process will exit.
+
+.. _emcc-show-ports:
+
+``--show-ports``
+ Shows the list of available projects in the Emscripten Ports repos. After this operation is complete, this process will exit.
+.. _emcc-save-bc:
+
``--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.
diff --git a/site/source/home_page_layout.html b/site/source/home_page_layout.html
index 2edcd0200f6ce..26e9c55aac79e 100644
--- a/site/source/home_page_layout.html
+++ b/site/source/home_page_layout.html
@@ -23,7 +23,12 @@
Emscripten is an LLVM-based project that compiles C and C++ in
-
+
+