Skip to content

Commit 769087b

Browse files
committed
Merge branch 'master' of https://github.com/kripken/emscripten into 1.37.0-unity
2 parents d6aa966 + 6dc4ac5 commit 769087b

37 files changed

+902
-372
lines changed

AUTHORS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,3 +267,5 @@ a license to everyone to use it as detailed in LICENSE.)
267267
* Christopher Serr <[email protected]>
268268
* Aaron Ruß <[email protected]> (copyright owned by DFKI GmbH)
269269
* Vilibald Wanča <[email protected]>
270+
* Alex Hixon <[email protected]>
271+
* Vladimir Davidovich <[email protected]>

cmake/Modules/Platform/Emscripten.cmake

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,8 +134,6 @@ if (EMSCRIPTEN_FORCE_COMPILERS)
134134
set(CMAKE_CXX_COMPILER_ID Clang)
135135
set(CMAKE_CXX_STANDARD_COMPUTED_DEFAULT 98)
136136

137-
set(CMAKE_C_COMPILER_TARGET "asmjs-unknown-emscripten")
138-
set(CMAKE_CXX_COMPILER_TARGET "asmjs-unknown-emscripten")
139137
set(CMAKE_C_PLATFORM_ID "emscripten")
140138
set(CMAKE_CXX_PLATFORM_ID "emscripten")
141139

emcc.py

Lines changed: 82 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,8 @@ def run():
115115
if len(sys.argv) <= 1 or ('--help' not in sys.argv and len(sys.argv) >= 2 and sys.argv[1] != '--version'):
116116
shared.check_sanity(force=DEBUG)
117117

118+
misc_temp_files = shared.configuration.get_temp_files()
119+
118120
# Handle some global flags
119121

120122
if len(sys.argv) == 1:
@@ -181,6 +183,22 @@ def run():
181183
print shared.get_llvm_target()
182184
exit(0)
183185

186+
elif '--cflags' in sys.argv:
187+
# fake running the command, to see the full args we pass to clang
188+
debug_env = os.environ.copy()
189+
debug_env['EMCC_DEBUG'] = '1'
190+
args = filter(lambda x: x != '--cflags', sys.argv)
191+
with misc_temp_files.get_file(suffix='.o') as temp_target:
192+
input_file = 'hello_world.c'
193+
out, err = subprocess.Popen([shared.PYTHON] + args + [shared.path_from_root('tests', input_file), '-c', '-o', temp_target], stderr=subprocess.PIPE, env=debug_env).communicate()
194+
lines = filter(lambda x: shared.CLANG_CC in x and input_file in x, err.split(os.linesep))
195+
line = lines[0]
196+
assert 'running:' in line
197+
parts = line.split(' ')[2:]
198+
parts = filter(lambda x: x != '-c' and x != '-o' and input_file not in x and temp_target not in x and '-emit-llvm' not in x, parts)
199+
print ' '.join(parts)
200+
exit(0)
201+
184202
def is_minus_s_for_emcc(newargs, i):
185203
assert newargs[i] == '-s'
186204
if i+1 < len(newargs) and '=' in newargs[i+1] and not newargs[i+1].startswith('-'): # -s OPT=VALUE is for us, -s by itself is a linker option
@@ -250,7 +268,11 @@ def filter_emscripten_options(argv):
250268
if compiler == shared.EMCC: compiler = [shared.PYTHON, shared.EMCC]
251269
else: compiler = [compiler]
252270
cmd = compiler + list(filter_emscripten_options(sys.argv[1:]))
253-
if not use_js: cmd += shared.EMSDK_OPTS + ['-D__EMSCRIPTEN__', '-DEMSCRIPTEN']
271+
if not use_js:
272+
cmd += shared.EMSDK_OPTS + ['-D__EMSCRIPTEN__']
273+
# The preprocessor define EMSCRIPTEN is deprecated. Don't pass it to code in strict mode. Code should use the define __EMSCRIPTEN__ instead.
274+
if not shared.Settings.STRICT:
275+
cmd += ['-DEMSCRIPTEN']
254276
if use_js: cmd += ['-s', 'ERROR_ON_UNDEFINED_SYMBOLS=1'] # configure tests should fail when an undefined symbol exists
255277

256278
logging.debug('just configuring: ' + ' '.join(cmd))
@@ -397,8 +419,6 @@ def log_time(name):
397419

398420
use_cxx = True
399421

400-
misc_temp_files = shared.configuration.get_temp_files()
401-
402422
try:
403423
with ToolchainProfiler.profile_block('parse arguments and setup'):
404424
## Parse args
@@ -918,6 +938,29 @@ def detect_fixed_language_mode(args):
918938
if separate_asm:
919939
shared.Settings.SEPARATE_ASM = os.path.basename(asm_target)
920940

941+
if 'EMCC_STRICT' in os.environ:
942+
shared.Settings.STRICT = os.environ.get('EMCC_STRICT') != '0'
943+
944+
# Libraries are searched before settings_changes are applied, so apply the value for STRICT and ERROR_ON_MISSING_LIBRARIES from
945+
# command line already now.
946+
947+
def get_last_setting_change(setting):
948+
return ([None] + filter(lambda x: x.startswith(setting + '='), settings_changes))[-1]
949+
950+
strict_cmdline = get_last_setting_change('STRICT')
951+
if strict_cmdline:
952+
shared.Settings.STRICT = int(strict_cmdline[len('STRICT='):])
953+
954+
if shared.Settings.STRICT:
955+
shared.Settings.ERROR_ON_UNDEFINED_SYMBOLS = 1
956+
shared.Settings.ERROR_ON_MISSING_LIBRARIES = 1
957+
958+
error_on_missing_libraries_cmdline = get_last_setting_change('ERROR_ON_MISSING_LIBRARIES')
959+
if error_on_missing_libraries_cmdline:
960+
shared.Settings.ERROR_ON_MISSING_LIBRARIES = int(error_on_missing_libraries_cmdline[len('ERROR_ON_MISSING_LIBRARIES='):])
961+
962+
system_js_libraries = []
963+
921964
# Find library files
922965
for i, lib in libs:
923966
logging.debug('looking for library "%s"', lib)
@@ -934,8 +977,13 @@ def detect_fixed_language_mode(args):
934977
break
935978
if found: break
936979
if found: break
937-
if not found and lib not in ['GL', 'GLU', 'glut', 'm', 'c', 'SDL', 'stdc++', 'pthread']: # whitelist our default libraries
938-
logging.warning('emcc: cannot find library "%s"', lib)
980+
if not found:
981+
system_js_libraries += shared.Building.path_to_system_js_libraries(lib)
982+
983+
# Certain linker flags imply some link libraries to be pulled in by default.
984+
system_js_libraries += shared.Building.path_to_system_js_libraries_for_settings(settings_changes)
985+
986+
settings_changes.append('SYSTEM_JS_LIBRARIES="' + ','.join(system_js_libraries) + '"')
939987

940988
# If not compiling to JS, then we are compiling to an intermediate bitcode objects or library, so
941989
# ignore dynamic linking, since multiple dynamic linkings can interfere with each other
@@ -999,6 +1047,15 @@ def check(input_file):
9991047
if shared.get_llvm_target() == shared.WASM_TARGET:
10001048
shared.Settings.WASM_BACKEND = 1
10011049

1050+
if not shared.Settings.STRICT:
1051+
# The preprocessor define EMSCRIPTEN is deprecated. Don't pass it to code in strict mode. Code should use the define __EMSCRIPTEN__ instead.
1052+
shared.COMPILER_OPTS += ['-DEMSCRIPTEN']
1053+
1054+
# The system include path system/include/emscripten/ is deprecated, i.e. instead of #include <emscripten.h>, one should pass in #include <emscripten/emscripten.h>.
1055+
# This path is not available in Emscripten strict mode.
1056+
if shared.USE_EMSDK:
1057+
shared.C_INCLUDE_PATHS += [shared.path_from_root('system', 'include', 'emscripten')]
1058+
10021059
# Use settings
10031060

10041061
try:
@@ -1052,10 +1109,6 @@ def check(input_file):
10521109
assert not use_closure_compiler, 'cannot use closure compiler on shared modules'
10531110
assert not shared.Settings.ALLOW_MEMORY_GROWTH, 'memory growth is not supported with shared modules yet'
10541111

1055-
if shared.Settings.ALLOW_MEMORY_GROWTH:
1056-
logging.warning('not all asm.js optimizations are possible with ALLOW_MEMORY_GROWTH, disabling those')
1057-
shared.Settings.ASM_JS = 2 # memory growth does not validate as asm.js http://discourse.wicg.io/t/request-for-comments-switching-resizing-heaps-in-asm-js/641/23
1058-
10591112
if shared.Settings.EMULATE_FUNCTION_POINTER_CASTS:
10601113
shared.Settings.ALIASING_FUNCTION_POINTERS = 0
10611114

@@ -1155,13 +1208,16 @@ def check(input_file):
11551208

11561209
if shared.Settings.USE_PTHREADS:
11571210
if shared.Settings.LINKABLE:
1158-
logging.error('-s LINKABLE=1 is not supported with -s USE_PTHREADS=1!')
1211+
logging.error('-s LINKABLE=1 is not supported with -s USE_PTHREADS>0!')
11591212
exit(1)
11601213
if shared.Settings.SIDE_MODULE:
1161-
logging.error('-s SIDE_MODULE=1 is not supported with -s USE_PTHREADS=1!')
1214+
logging.error('-s SIDE_MODULE=1 is not supported with -s USE_PTHREADS>0!')
11621215
exit(1)
11631216
if shared.Settings.MAIN_MODULE:
1164-
logging.error('-s MAIN_MODULE=1 is not supported with -s USE_PTHREADS=1!')
1217+
logging.error('-s MAIN_MODULE=1 is not supported with -s USE_PTHREADS>0!')
1218+
exit(1)
1219+
if shared.Settings.EMTERPRETIFY:
1220+
logging.error('-s EMTERPRETIFY=1 is not supported with -s USE_PTHREADS>0!')
11651221
exit(1)
11661222

11671223
if shared.Settings.OUTLINING_LIMIT:
@@ -1216,6 +1272,12 @@ def check(input_file):
12161272
# * and js mem inits are useful for avoiding a side file, but the wasm module avoids that anyhow
12171273
memory_init_file = True
12181274

1275+
if shared.Settings.ALLOW_MEMORY_GROWTH and shared.Settings.ASM_JS == 1:
1276+
# this is an issue in asm.js, but not wasm
1277+
if not shared.Settings.WASM or 'asmjs' in shared.Settings.BINARYEN_METHOD:
1278+
logging.warning('not all asm.js optimizations are possible with ALLOW_MEMORY_GROWTH, disabling those')
1279+
shared.Settings.ASM_JS = 2 # memory growth does not validate as asm.js http://discourse.wicg.io/t/request-for-comments-switching-resizing-heaps-in-asm-js/641/23
1280+
12191281
if js_opts:
12201282
shared.Settings.RUNNING_JS_OPTS = 1
12211283

@@ -1987,6 +2049,14 @@ def do_minify(): # minifies the code. this is also when we do certain optimizati
19872049
print jsrun.run_js(shared.path_from_root('tools', 'js-optimizer.js'), shared.NODE_JS, args=[asm_target, 'eliminateDeadGlobals', 'last', 'asm'], stdout=open(temp, 'w'))
19882050
shutil.move(temp, asm_target)
19892051

2052+
if shared.Settings.BINARYEN_METHOD:
2053+
methods = shared.Settings.BINARYEN_METHOD.split(',')
2054+
valid_methods = ['asmjs', 'native-wasm', 'interpret-s-expr', 'interpret-binary', 'interpret-asm2wasm']
2055+
for m in methods:
2056+
if not m.strip() in valid_methods:
2057+
logging.error('Unrecognized BINARYEN_METHOD "' + m.strip() + '" specified! Please pass a comma-delimited list containing one or more of: ' + ','.join(valid_methods))
2058+
sys.exit(1)
2059+
19902060
if shared.Settings.BINARYEN:
19912061
logging.debug('using binaryen, with method: ' + shared.Settings.BINARYEN_METHOD)
19922062
binaryen_bin = os.path.join(shared.Settings.BINARYEN_ROOT, 'bin')

emscripten-version.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
"1.36.14"
1+
"1.37.0"

emscripten.py

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1329,7 +1329,7 @@ def emscript_wasm_backend(infile, settings, outfile, libraries=None, compiler_en
13291329
'-o', temp_s]
13301330
backend_args += ['-thread-model=single'] # no threads support in backend, tell llc to not emit atomics
13311331
# disable slow and relatively unimportant optimization passes
1332-
backend_args += ['-combiner-alias-analysis=false', '-combiner-global-alias-analysis=false']
1332+
backend_args += ['-combiner-global-alias-analysis=false']
13331333

13341334
# asm.js-style exception handling
13351335
if settings['DISABLE_EXCEPTION_CATCHING'] != 1:
@@ -1422,21 +1422,29 @@ def asmjs_mangle(name):
14221422
# in metadata[declares], the invoke wrappers will be generated in
14231423
# this script later.
14241424
import_type = parts[3][1:]
1425+
import_name = parts[2][1:-1]
14251426
if import_type == 'memory':
14261427
continue
1427-
assert import_type == 'func', 'No support for imports other than functions and memories'
1428-
func_name = parts[2][1:-1]
1429-
if not func_name.startswith('invoke_'):
1430-
metadata['declares'].append(func_name)
1428+
elif import_type == 'func':
1429+
if not import_name.startswith('invoke_'):
1430+
metadata['declares'].append(import_name)
1431+
elif import_type == 'global':
1432+
metadata['externs'].append('_' + import_name)
1433+
else:
1434+
assert False, 'Unhandled import type "%s"' % import_type
14311435
elif line.startswith(' (func '):
14321436
parts = line.split()
14331437
func_name = parts[1][1:]
14341438
metadata['implementedFunctions'].append(func_name)
14351439
elif line.startswith(' (export '):
14361440
parts = line.split()
14371441
export_name = parts[1][1:-1]
1438-
assert asmjs_mangle(export_name) not in metadata['exports']
1439-
metadata['exports'].append(export_name)
1442+
export_type = parts[2][1:]
1443+
if export_type == 'func':
1444+
assert asmjs_mangle(export_name) not in metadata['exports']
1445+
metadata['exports'].append(export_name)
1446+
else:
1447+
assert False, 'Unhandled export type "%s"' % export_type
14401448

14411449
metadata['declares'] = filter(lambda x: not x.startswith('emscripten_asm_const'), metadata['declares']) # we emit those ourselves
14421450

site/source/docs/compiling/Building-Projects.rst

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -268,17 +268,22 @@ The :ref:`Tutorial` showed how :ref:`emcc <emccdoc>` can be used to compile sing
268268
In addition to the capabilities it shares with *gcc*, *emcc* supports options to optimize code, control what debug information is emitted, generate HTML and other output formats, etc. These options are documented in the :ref:`emcc tool reference <emccdoc>` (``./emcc --help`` on the command line).
269269

270270

271-
Alternatives to emcc
272-
====================
273-
274-
.. tip:: Do not attempt to bypass *emcc* and call the Emscripten tools directly from your build system.
275-
276-
You can in theory call *clang*, *llvm-ld*, and the other tools yourself. This is however considered dangerous because by default:
277-
278-
- *Clang* does not use the Emscripten-bundled headers, which can lead to various errors.
279-
- *llvm-ld* uses unsafe/unportable LLVM optimizations.
271+
Detecting Emscripten in Preprocessor
272+
====================================
280273

281-
*Emcc* automatically ensures the tools are configured and used properly.
274+
Emscripten provides the following preprocessor macros that can be used to identify the compiler version and platform:
275+
276+
* The preprocessor define ``__EMSCRIPTEN__`` is always defined when compiling programs with Emscripten.
277+
* The preprocessor variables ``__EMSCRIPTEN_major__``, ``__EMSCRIPTEN_minor__`` and ``__EMSCRIPTEN_tiny__`` specify, as integers, the currently used Emscripten compiler version.
278+
* Emscripten behaves like a variant of Unix, so the preprocessor defines ``unix``, ``__unix`` and ``__unix__`` are always present when compiling code with Emscripten.
279+
* Emscripten uses Clang/LLVM as its underlying codegen compiler, so the preprocessor defines ``__llvm__`` and ``__clang__`` are defined, and the preprocessor defines ``__clang_major__``, ``__clang_minor__`` and ``__clang_patchlevel__`` indicate the version of Clang that is used.
280+
* Clang/LLVM is GCC-compatible, so the preprocessor defines ``__GNUC__``, ``__GNUC_MINOR__`` and ``__GNUC_PATCHLEVEL__`` are also defined to represent the level of GCC compatibility that Clang/LLVM provides.
281+
* The preprocessor string ``__VERSION__`` indicates the GCC compatible version, which is expanded to also show Emscripten version information.
282+
* Likewise, ``__clang_version__`` is present and indicates both Emscripten and LLVM version information.
283+
* Emscripten is a 32-bit platform, so ``size_t`` is a 32-bit unsigned integer, ``__POINTER_WIDTH__=32``, ``__SIZEOF_LONG__=4`` and ``__LONG_MAX__`` equals ``2147483647L``.
284+
* When targeting asm.js, the preprocessor defines ``__asmjs`` and ``__asmjs__`` are present.
285+
* When targeting SSEx SIMD APIs using one of the command line compiler flags ``-msse``, ``-msse2``, ``-msse3``, ``-mssse3``, or ``-msse4.1``, one or more of the preprocessor flags ``__SSE__``, ``__SSE2__``, ``__SSE3__``, ``__SSSE3__``, ``__SSE4_1__`` will be present to indicate available support for these instruction sets.
286+
* If targeting the pthreads multithreading support with the compiler & linker flag ``-s USE_PTHREADS=1``, the preprocessor define ``__EMSCRIPTEN_PTHREADS__`` will be present.
282287

283288

284289
Examples / test code

site/source/docs/tools_reference/emcc.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -450,6 +450,9 @@ Options that are modified or new in *emcc* are listed below:
450450
``--output-eol windows|linux``
451451
Specifies the line ending to generate for the text files that are outputted. If "--output-eol windows" is passed, the final output files will have Windows \r\n line endings in them. With "--output-eol linux", the final generated files will be written with Unix \n line endings.
452452

453+
``--cflags``
454+
Prints out the flags ``emcc`` would pass to ``clang`` to compile source code to object/bitcode form. You can use this to invoke clang yourself, and then run ``emcc`` on those outputs just for the final linking+conversion to JS.
455+
453456
.. _emcc-environment-variables:
454457

455458
Environment variables

src/deps_info.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
"freelocale": ["free"],
2121
"nl_langinfo": ["malloc"],
2222
"inet_ntoa": ["malloc"],
23-
"gethostbyname": ["malloc"],
23+
"gethostbyname": ["malloc", "htons"],
2424
"gethostbyname_r": ["free"],
2525
"getaddrinfo": ["malloc", "htonl", "htons", "ntohs"],
2626
"_inet_ntop6_raw": ["ntohs"],
@@ -44,6 +44,8 @@
4444
"bind": ["htonl", "htons", "ntohs"],
4545
"connect": ["htonl", "htons", "ntohs"],
4646
"socket": ["htonl", "htons", "ntohs"],
47-
"sleep": ["usleep"]
47+
"sleep": ["usleep"],
48+
"recv": ["htons"],
49+
"send": ["htons"]
4850
}
4951

src/embind/embind.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@ var LibraryEmbind = {
144144
}
145145
else {
146146
Module[name] = value;
147+
Module[name].argCount = numArguments;
147148
}
148149
},
149150

@@ -1949,6 +1950,8 @@ var LibraryEmbind = {
19491950
// Replace the initial unbound-handler-stub function with the appropriate member function, now that all types
19501951
// are resolved. If multiple overloads are registered for this function, the function goes into an overload table.
19511952
if (undefined === proto[methodName].overloadTable) {
1953+
// Set argCount in case an overload is registered later
1954+
memberFunction.argCount = argCount - 2;
19521955
proto[methodName] = memberFunction;
19531956
} else {
19541957
proto[methodName].overloadTable[argCount - 2] = memberFunction;

src/jsifier.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,10 @@ function JSify(data, functionsOnly) {
299299
print('// STATICTOP = STATIC_BASE + ' + Runtime.alignMemory(Variables.nextIndexedOffset) + ';\n'); // comment as metadata only
300300
}
301301
if (BINARYEN) {
302+
// export static base and bump, needed for linking in wasm binary's memory, dynamic linking, etc.
302303
print('var STATIC_BUMP = {{{ STATIC_BUMP }}};');
304+
print('Module["STATIC_BASE"] = STATIC_BASE;');
305+
print('Module["STATIC_BUMP"] = STATIC_BUMP;');
303306
}
304307
}
305308
var generated = itemsDict.function.concat(itemsDict.type).concat(itemsDict.GlobalVariableStub).concat(itemsDict.GlobalVariable);

0 commit comments

Comments
 (0)