5656LIB_PREFIXES = ('' , 'lib' )
5757
5858JS_CONTAINING_SUFFIXES = ('js' , 'html' )
59+ EXECUTABLE_SUFFIXES = JS_CONTAINING_SUFFIXES + ('wasm' ,)
5960
6061DEFERRED_REPONSE_FILES = ('EMTERPRETIFY_BLACKLIST' , 'EMTERPRETIFY_WHITELIST' )
6162
@@ -354,10 +355,6 @@ def uniquename(name):
354355 sys .argv = sys .argv [:i ] + sys .argv [i + 2 :]
355356 break
356357
357- if target and target .endswith (WASM_ENDINGS ):
358- logging .warning ('output file "%s" has a wasm suffix, but we cannot emit wasm by itself. specify an output file with suffix .js or .html, and a wasm file will be created on the side' % target )
359- sys .exit (1 )
360-
361358 specified_target = target
362359 target = specified_target if specified_target is not None else 'a.out.js' # specified_target is the user-specified one, target is what we will generate
363360 target_basename = unsuffixed_basename (target )
@@ -440,8 +437,9 @@ def log_time(name):
440437 default_cxx_std = '-std=c++03' # Enforce a consistent C++ standard when compiling .cpp files, if user does not specify one on the cmdline.
441438 use_closure_compiler = None
442439 js_transform = None
443- pre_js = ''
444- post_js = ''
440+ pre_js = '' # before all js
441+ post_module = '' # in js, after Module exists
442+ post_js = '' # after all js
445443 preload_files = []
446444 embed_files = []
447445 exclude_files = []
@@ -1098,7 +1096,7 @@ def check(input_file):
10981096 shared .Settings .INCLUDE_FULL_LIBRARY = 1
10991097 elif shared .Settings .SIDE_MODULE :
11001098 assert not shared .Settings .MAIN_MODULE
1101- memory_init_file = False # memory init file is not supported with side modules, must be executable synchronously (for dlopen)
1099+ memory_init_file = False # memory init file is not supported with asm.js side modules, must be executable synchronously (for dlopen)
11021100
11031101 if shared .Settings .MAIN_MODULE or shared .Settings .SIDE_MODULE :
11041102 assert shared .Settings .ASM_JS , 'module linking requires asm.js output (-s ASM_JS=1)'
@@ -1138,6 +1136,21 @@ def check(input_file):
11381136 # stb_image 2.x need to have STB_IMAGE_IMPLEMENTATION defined to include the implementation when compiling
11391137 newargs .append ('-DSTB_IMAGE_IMPLEMENTATION' )
11401138
1139+ if shared .Settings .ASMFS and final_suffix in JS_CONTAINING_SUFFIXES :
1140+ input_files .append ((next_arg_index , shared .path_from_root ('system' , 'lib' , 'fetch' , 'asmfs.cpp' )))
1141+ newargs .append ('-D__EMSCRIPTEN_ASMFS__=1' )
1142+ next_arg_index += 1
1143+ shared .Settings .NO_FILESYSTEM = 1
1144+ shared .Settings .FETCH = 1
1145+ if not shared .Settings .USE_PTHREADS :
1146+ logging .error ('-s ASMFS=1 requires either -s USE_PTHREADS=1 or -s USE_PTHREADS=2 to be set!' )
1147+ sys .exit (1 )
1148+
1149+ if shared .Settings .FETCH and final_suffix in JS_CONTAINING_SUFFIXES :
1150+ input_files .append ((next_arg_index , shared .path_from_root ('system' , 'lib' , 'fetch' , 'emscripten_fetch.cpp' )))
1151+ next_arg_index += 1
1152+ js_libraries .append (shared .path_from_root ('src' , 'library_fetch.js' ))
1153+
11411154 forced_stdlibs = []
11421155 if shared .Settings .DEMANGLE_SUPPORT :
11431156 shared .Settings .EXPORTED_FUNCTIONS += ['___cxa_demangle' ]
@@ -1226,11 +1239,6 @@ def check(input_file):
12261239 js_opts = True
12271240 force_js_opts = True
12281241
1229- if shared .Settings .EVAL_CTORS :
1230- # this option is not a js optimizer pass, but does run the js optimizer internally, so
1231- # we need to generate proper code for that
1232- shared .Settings .RUNNING_JS_OPTS = 1
1233-
12341242 if shared .Settings .WASM :
12351243 shared .Settings .BINARYEN = 1 # these are synonyms
12361244
@@ -1251,7 +1259,7 @@ def check(input_file):
12511259 debug_level = max (1 , debug_level ) # keep whitespace readable, for asm.js parser simplicity
12521260 shared .Settings .GLOBAL_BASE = 1024 # leave some room for mapping global vars
12531261 assert not shared .Settings .SPLIT_MEMORY , 'WebAssembly does not support split memory'
1254- assert not shared .Settings .INCLUDE_FULL_LIBRARY , 'The WebAssembly libc overlaps with JS libs, so INCLUDE_FULL_LIBRARY does not just work (FIXME) '
1262+ assert not shared .Settings .USE_PTHREADS , 'WebAssembly does not support pthreads '
12551263 # if root was not specified in -s, it might be fixed in ~/.emscripten, copy from there
12561264 if not shared .Settings .BINARYEN_ROOT :
12571265 try :
@@ -1271,6 +1279,20 @@ def check(input_file):
12711279 # * if we also supported js mem inits we'd have 4 modes
12721280 # * and js mem inits are useful for avoiding a side file, but the wasm module avoids that anyhow
12731281 memory_init_file = True
1282+ if shared .Building .is_wasm_only () and shared .Settings .EVAL_CTORS :
1283+ logging .debug ('disabling EVAL_CTORS, as in wasm-only mode it hurts more than it helps. TODO: a wasm version of it' )
1284+ shared .Settings .EVAL_CTORS = 0
1285+
1286+ # wasm outputs are only possible with a side wasm
1287+ if target .endswith (WASM_ENDINGS ):
1288+ if not (shared .Settings .BINARYEN and shared .Settings .SIDE_MODULE ):
1289+ logging .warning ('output file "%s" has a wasm suffix, but we cannot emit wasm by itself, except as a dynamic library (see SIDE_MODULE option). specify an output file with suffix .js or .html, and a wasm file will be created on the side' % target )
1290+ sys .exit (1 )
1291+
1292+ if shared .Settings .EVAL_CTORS :
1293+ # this option is not a js optimizer pass, but does run the js optimizer internally, so
1294+ # we need to generate proper code for that
1295+ shared .Settings .RUNNING_JS_OPTS = 1
12741296
12751297 if shared .Settings .ALLOW_MEMORY_GROWTH and shared .Settings .ASM_JS == 1 :
12761298 # this is an issue in asm.js, but not wasm
@@ -1437,7 +1459,7 @@ def compile_source_file(i, input_file):
14371459 linker_inputs = [val for _ , val in sorted (temp_files + link_flags )]
14381460
14391461 # If we were just asked to generate bitcode, stop there
1440- if final_suffix not in JS_CONTAINING_SUFFIXES :
1462+ if final_suffix not in EXECUTABLE_SUFFIXES :
14411463 if not specified_target :
14421464 assert len (temp_files ) == len (input_files )
14431465 for i in range (len (input_files )):
@@ -1674,12 +1696,15 @@ def save_intermediate(name=None, suffix='js'):
16741696 else :
16751697 wasm_js_glue = wasm_js_glue .replace ('{{{ wasmJSMethod }}}' , 'null' )
16761698 wasm_js_glue = wasm_js_glue .replace ('{{{ WASM_BACKEND }}}' , str (shared .Settings .WASM_BACKEND )) # if wasm backend, wasm contains memory segments
1677- pre_js = wasm_js_glue + '\n ' + pre_js
1699+ wasm_js_glue += '\n integrateWasmJS(Module);\n ' # add a call
1700+ post_module += str (wasm_js_glue ) # we can set up the glue once we have the module
16781701
16791702 # Apply pre and postjs files
1680- if pre_js or post_js :
1703+ if pre_js or post_module or post_js :
16811704 logging .debug ('applying pre/postjses' )
16821705 src = open (final ).read ()
1706+ if post_module :
1707+ src = src .replace ('// {{PREAMBLE_ADDITIONS}}' , post_module + '\n // {{PREAMBLE_ADDITIONS}}' )
16831708 final += '.pp.js'
16841709 if WINDOWS : # Avoid duplicating \r\n to \r\r\n when writing out.
16851710 if pre_js : pre_js = pre_js .replace ('\r \n ' , '\n ' )
@@ -1754,12 +1779,9 @@ def repl(m):
17541779 if shared .Settings .USE_PTHREADS :
17551780 shutil .copyfile (shared .path_from_root ('src' , 'pthread-main.js' ), os .path .join (os .path .dirname (os .path .abspath (target )), 'pthread-main.js' ))
17561781
1757- if shared .Settings .BINARYEN :
1758- # Insert a call to integrate with wasm.js
1759- js = open (final ).read ()
1760- js = js .replace ('// {{PREAMBLE_ADDITIONS}}' , 'integrateWasmJS(Module);\n // {{PREAMBLE_ADDITIONS}}' )
1761- final += '.binaryen.js'
1762- open (final , 'w' ).write (js )
1782+ # Generate the fetch-worker.js script for multithreaded emscripten_fetch() support if targeting pthreads.
1783+ if shared .Settings .FETCH and shared .Settings .USE_PTHREADS :
1784+ shared .make_fetch_worker (final , os .path .join (os .path .dirname (os .path .abspath (target )), 'fetch-worker.js' ))
17631785
17641786 # exit block 'memory initializer'
17651787 log_time ('memory initializer' )
@@ -2090,18 +2112,23 @@ def do_minify(): # minifies the code. this is also when we do certain optimizati
20902112 cmd += ['--mem-init=' + memfile ]
20912113 if not shared .Settings .RELOCATABLE :
20922114 cmd += ['--mem-base=' + str (shared .Settings .GLOBAL_BASE )]
2093- if shared .Settings .BINARYEN_MEM_MAX >= 0 :
2115+ # various options imply that the imported table may not be the exact size as the wasm module's own table segments
2116+ if shared .Settings .RELOCATABLE or shared .Settings .RESERVED_FUNCTION_POINTERS > 0 or shared .Settings .EMULATED_FUNCTION_POINTERS :
2117+ cmd += ['--table-max=-1' ]
2118+ if shared .Settings .SIDE_MODULE :
2119+ cmd += ['--mem-max=-1' ]
2120+ elif shared .Settings .BINARYEN_MEM_MAX >= 0 :
20942121 cmd += ['--mem-max=' + str (shared .Settings .BINARYEN_MEM_MAX )]
20952122 if shared .Building .is_wasm_only ():
20962123 cmd += ['--wasm-only' ] # this asm.js is code not intended to run as asm.js, it is only ever going to be wasm, an can contain special fastcomp-wasm support
20972124 logging .debug ('asm2wasm (asm.js => WebAssembly): ' + ' ' .join (cmd ))
20982125 TimeLogger .update ()
20992126 subprocess .check_call (cmd , stdout = open (wasm_text_target , 'w' ))
2100- log_time ('asm2wasm' )
21012127 if import_mem_init :
21022128 # remove and forget about the mem init file in later processing; it does not need to be prefetched in the html, etc.
21032129 os .unlink (memfile )
21042130 memory_init_file = False
2131+ log_time ('asm2wasm' )
21052132 if shared .Settings .BINARYEN_PASSES :
21062133 shutil .move (wasm_text_target , wasm_text_target + '.pre' )
21072134 cmd = [os .path .join (binaryen_bin , 'wasm-opt' ), wasm_text_target + '.pre' , '-o' , wasm_text_target ] + map (lambda p : '--' + p , shared .Settings .BINARYEN_PASSES .split (',' ))
@@ -2126,6 +2153,16 @@ def do_minify(): # minifies the code. this is also when we do certain optimizati
21262153 for script in shared .Settings .BINARYEN_SCRIPTS .split (',' ):
21272154 logging .debug ('running binaryen script: ' + script )
21282155 subprocess .check_call ([shared .PYTHON , os .path .join (binaryen_scripts , script ), js_target , wasm_text_target ], env = script_env )
2156+ # after generating the wasm, do some final operations
2157+ if not shared .Settings .WASM_BACKEND :
2158+ if shared .Settings .SIDE_MODULE :
2159+ wso = shared .WebAssembly .make_shared_library (js_target , wasm_binary_target )
2160+ # replace the wasm binary output with the dynamic library. TODO: use a specific suffix for such files?
2161+ shutil .move (wso , wasm_binary_target )
2162+ if not DEBUG :
2163+ os .unlink (js_target ) # we don't need the js, it can just confuse
2164+ os .unlink (asm_target ) # we don't need the asm.js, it can just confuse
2165+ sys .exit (0 ) # and we are done.
21292166
21302167 # If we were asked to also generate HTML, do that
21312168 if final_suffix == 'html' :
0 commit comments