@@ -663,7 +663,7 @@ def uniquename(name):
663663
664664 specified_target = target
665665 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
666- target_basename = unsuffixed_basename (target )
666+ shared . Settings . TARGET_BASENAME = target_basename = unsuffixed_basename (target )
667667
668668 final_suffix = suffix (target )
669669
@@ -1043,6 +1043,7 @@ def check(input_file):
10431043 assert not (not shared .Settings .DYNAMIC_EXECUTION and options .use_closure_compiler ), 'cannot have both NO_DYNAMIC_EXECUTION and closure compiler enabled at the same time'
10441044
10451045 if options .emrun :
1046+ assert not shared .Settings .MINIMAL_RUNTIME , '--emrun is not compatible with -s MINIMAL_RUNTIME=1'
10461047 shared .Settings .EXPORTED_RUNTIME_METHODS .append ('addOnExit' )
10471048
10481049 if options .use_closure_compiler :
@@ -1122,7 +1123,7 @@ def check(input_file):
11221123 shared .Settings .EXPORTED_FUNCTIONS += ['___cxa_demangle' ]
11231124 forced_stdlibs += ['libc++abi' ]
11241125
1125- if not shared .Settings .ONLY_MY_CODE :
1126+ if not shared .Settings .ONLY_MY_CODE and not shared . Settings . MINIMAL_RUNTIME :
11261127 # Always need malloc and free to be kept alive and exported, for internal use and other modules
11271128 shared .Settings .EXPORTED_FUNCTIONS += ['_malloc' , '_free' ]
11281129 if shared .Settings .WASM_BACKEND :
@@ -1285,6 +1286,24 @@ def check(input_file):
12851286 if not shared .Settings .SEPARATE_ASM_MODULE_NAME :
12861287 shared .Settings .SEPARATE_ASM_MODULE_NAME = 'Module["asm"]'
12871288
1289+ if shared .Settings .MINIMAL_RUNTIME :
1290+ # Minimal runtime uses a different default shell file
1291+ if options .shell_path == shared .path_from_root ('src' , 'shell.html' ):
1292+ options .shell_path = shared .path_from_root ('src' , 'shell_minimal_runtime.html' )
1293+
1294+ # Remove the default exported functions 'memcpy', 'memset', 'malloc', 'free', etc. - those should only be linked in if used
1295+ shared .Settings .DEFAULT_LIBRARY_FUNCS_TO_INCLUDE = []
1296+
1297+ # Always build with STRICT mode enabled
1298+ shared .Settings .STRICT = 1
1299+
1300+ # Always use the new HTML5 API event target lookup rules (TODO: enable this when the other PR lands)
1301+ # shared.Settings.DISABLE_DEPRECATED_FIND_EVENT_TARGET_BEHAVIOR = 1
1302+
1303+ # In asm.js always use memory init file to get the best code size, other modes are not currently supported.
1304+ if not shared .Settings .WASM :
1305+ options .memory_init_file = True
1306+
12881307 if shared .Settings .WASM :
12891308 if shared .Settings .SINGLE_FILE :
12901309 # placeholder strings for JS glue, to be replaced with subresource locations in do_binaryen
@@ -1317,18 +1336,20 @@ def check(input_file):
13171336 if any (s .startswith ('MEM_INIT_METHOD=' ) for s in settings_changes ):
13181337 exit_with_error ('MEM_INIT_METHOD is not supported in wasm. Memory will be embedded in the wasm binary if threads are not used, and included in a separate file if threads are used.' )
13191338 options .memory_init_file = True
1320- if shared .Settings .BINARYEN_ASYNC_COMPILATION == 1 :
1321- # async compilation requires a swappable module - we swap it in when it's ready
1322- shared .Settings .SWAPPABLE_ASM_MODULE = 1
1323- else :
1324- # if not wasm-only, we can't do async compilation as the build can run in other
1325- # modes than wasm (like asm.js) which may not support an async step
1326- shared .Settings .BINARYEN_ASYNC_COMPILATION = 0
1327- warning = 'This will reduce performance and compatibility (some browsers limit synchronous compilation), see http://kripken.github.io/emscripten-site/docs/compiling/WebAssembly.html#codegen-effects'
1328- if 'BINARYEN_ASYNC_COMPILATION=1' in settings_changes :
1329- logger .warning ('BINARYEN_ASYNC_COMPILATION requested, but disabled because of user options. ' + warning )
1330- elif 'BINARYEN_ASYNC_COMPILATION=0' not in settings_changes :
1331- logger .warning ('BINARYEN_ASYNC_COMPILATION disabled due to user options. ' + warning )
1339+
1340+ if not shared .Settings .MINIMAL_RUNTIME : # BINARYEN_ASYNC_COMPILATION and SWAPPABLE_ASM_MODULE do not have a meaning in MINIMAL_RUNTIME (always async)
1341+ if shared .Settings .BINARYEN_ASYNC_COMPILATION == 1 :
1342+ # async compilation requires a swappable module - we swap it in when it's ready
1343+ shared .Settings .SWAPPABLE_ASM_MODULE = 1
1344+ else :
1345+ # if not wasm-only, we can't do async compilation as the build can run in other
1346+ # modes than wasm (like asm.js) which may not support an async step
1347+ shared .Settings .BINARYEN_ASYNC_COMPILATION = 0
1348+ warning = 'This will reduce performance and compatibility (some browsers limit synchronous compilation), see http://kripken.github.io/emscripten-site/docs/compiling/WebAssembly.html#codegen-effects'
1349+ if 'BINARYEN_ASYNC_COMPILATION=1' in settings_changes :
1350+ logger .warning ('BINARYEN_ASYNC_COMPILATION requested, but disabled because of user options. ' + warning )
1351+ elif 'BINARYEN_ASYNC_COMPILATION=0' not in settings_changes :
1352+ logger .warning ('BINARYEN_ASYNC_COMPILATION disabled due to user options. ' + warning )
13321353
13331354 if not shared .Settings .DECLARE_ASM_MODULE_EXPORTS :
13341355 # Swappable wasm module/asynchronous wasm compilation requires an indirect stub
@@ -1337,10 +1358,6 @@ def check(input_file):
13371358 if shared .Settings .SWAPPABLE_ASM_MODULE == 1 :
13381359 shared .Settings .DECLARE_ASM_MODULE_EXPORTS = 1
13391360 logger .warning ('Enabling -s DECLARE_ASM_MODULE_EXPORTS=1 since -s SWAPPABLE_ASM_MODULE=1 is used' )
1340- # Wasm -O3 builds use Meta-DCE which is currently not compatible with -s DECLARE_ASM_MODULE_EXPORTS=0 option.
1341- if will_metadce (options ):
1342- shared .Settings .DECLARE_ASM_MODULE_EXPORTS = 1
1343- logger .warning ('Enabling -s DECLARE_ASM_MODULE_EXPORTS=1 since -O3/-Os build with Wasm meta-DCE is used' )
13441361
13451362 # we will include the mem init data in the wasm, when we don't need the
13461363 # mem init file to be loadable by itself
@@ -1405,6 +1422,16 @@ def check(input_file):
14051422 if not shared .Settings .WASM and (shared .Settings .MAIN_MODULE or shared .Settings .SIDE_MODULE ):
14061423 assert not shared .Settings .ALLOW_MEMORY_GROWTH , 'memory growth is not supported with shared asm.js modules'
14071424
1425+ if shared .Settings .MINIMAL_RUNTIME :
1426+ if shared .Settings .ALLOW_MEMORY_GROWTH :
1427+ logging .warning ('-s ALLOW_MEMORY_GROWTH=1 is not yet supported with -s MINIMAL_RUNTIME=1' )
1428+
1429+ if shared .Settings .EMTERPRETIFY :
1430+ exit_with_error ('-s EMTERPRETIFY=1 is not supported with -s MINIMAL_RUNTIME=1' )
1431+
1432+ if shared .Settings .USE_PTHREADS :
1433+ exit_with_error ('-s USE_PTHREADS=1 is not yet supported with -s MINIMAL_RUNTIME=1' )
1434+
14081435 if shared .Settings .ALLOW_MEMORY_GROWTH and shared .Settings .ASM_JS == 1 :
14091436 # this is an issue in asm.js, but not wasm
14101437 if not shared .Settings .WASM :
@@ -1437,6 +1464,10 @@ def check(input_file):
14371464 options .separate_asm = True
14381465 shared .Settings .FINALIZE_ASM_JS = False
14391466
1467+ # MINIMAL_RUNTIME always use separate .asm.js file for best performance and memory usage
1468+ if shared .Settings .MINIMAL_RUNTIME and not shared .Settings .WASM :
1469+ options .separate_asm = True
1470+
14401471 if shared .Settings .GLOBAL_BASE < 0 :
14411472 shared .Settings .GLOBAL_BASE = 8 # default if nothing else sets it
14421473
@@ -1918,7 +1949,11 @@ def get_final():
19181949 with ToolchainProfiler .profile_block ('memory initializer' ):
19191950 memfile = None
19201951 if shared .Settings .MEM_INIT_METHOD > 0 or embed_memfile (options ):
1921- memfile = target + '.mem'
1952+ if shared .Settings .MINIMAL_RUNTIME :
1953+ # Independent of whether user is doing -o a.html or -o a.js, generate the mem init file as a.mem (and not as a.html.mem or a.js.mem)
1954+ memfile = target .replace ('.html' , '.mem' ).replace ('.js' , '.mem' )
1955+ else :
1956+ memfile = target + '.mem'
19221957
19231958 if memfile and not shared .Settings .WASM_BACKEND :
19241959 # Strip the memory initializer out of the asmjs file
@@ -2109,6 +2144,15 @@ def get_eliminate():
21092144
21102145 module_export_name_substitution ()
21112146
2147+ # Run a final regex pass to clean up items that were not possible to optimize by Closure, or unoptimalities that were left behind
2148+ # by processing steps that occurred after Closure.
2149+ if shared .Settings .MINIMAL_RUNTIME == 2 and shared .Settings .USE_CLOSURE_COMPILER and options .debug_level == 0 :
2150+ # Process .js runtime file
2151+ shared .run_process ([shared .PYTHON , shared .path_from_root ('tools' , 'hacky_postprocess_around_closure_limitations.py' ), final ])
2152+ # Process .asm.js file
2153+ if not shared .Settings .WASM :
2154+ shared .run_process ([shared .PYTHON , shared .path_from_root ('tools' , 'hacky_postprocess_around_closure_limitations.py' ), asm_target ])
2155+
21122156 # The JS is now final. Move it to its final location
21132157 shutil .move (final , js_target )
21142158
@@ -2690,15 +2734,39 @@ def module_export_name_substitution():
26902734 logger .debug ('Private module export name substitution with ' + shared .Settings .EXPORT_NAME )
26912735 src = open (final ).read ()
26922736 final = final + '.module_export_name_substitution.js'
2693- replacement = "typeof %(EXPORT_NAME)s !== 'undefined' ? %(EXPORT_NAME)s : {}" % {"EXPORT_NAME" : shared .Settings .EXPORT_NAME }
2737+ if shared .Settings .MINIMAL_RUNTIME :
2738+ # In MINIMAL_RUNTIME the Module object is always present to provide the .asm.js/.wasm content
2739+ replacement = shared .Settings .EXPORT_NAME
2740+ else :
2741+ replacement = "typeof %(EXPORT_NAME)s !== 'undefined' ? %(EXPORT_NAME)s : {}" % {"EXPORT_NAME" : shared .Settings .EXPORT_NAME }
26942742 with open (final , 'w' ) as f :
2695- f .write (src .replace (shared .JS .module_export_name_substitution_pattern , replacement ))
2743+ src = src .replace (shared .JS .module_export_name_substitution_pattern , replacement )
2744+ # For Node.js, create an unminified Module object so that loading external .asm.js file that assigns to Module['asm'] works
2745+ # even when Closure is used.
2746+ if shared .Settings .MINIMAL_RUNTIME and shared .Settings .target_environment_may_be ('node' ):
2747+ src = 'if(typeof process!=="undefined"){var Module={};}' + src
2748+ f .write (src )
26962749 save_intermediate ('module_export_name_substitution' )
26972750
26982751
2752+ def generate_minimal_runtime_html (target , options , js_target , target_basename ,
2753+ asm_target , wasm_binary_target ,
2754+ memfile , optimizer ):
2755+ logger .debug ('generating HTML for minimal runtime' )
2756+ shell = read_and_preprocess (options .shell_path )
2757+ html_contents = shell .replace ('{{{ TARGET_BASENAME }}}' , target_basename )
2758+ html_contents = tools .line_endings .convert_line_endings (html_contents , '\n ' , options .output_eol )
2759+ with open (target , 'wb' ) as f :
2760+ f .write (asbytes (html_contents ))
2761+
2762+
26992763def generate_html (target , options , js_target , target_basename ,
27002764 asm_target , wasm_binary_target ,
27012765 memfile , optimizer ):
2766+ if shared .Settings .MINIMAL_RUNTIME :
2767+ return generate_minimal_runtime_html (target , options , js_target , target_basename , asm_target ,
2768+ wasm_binary_target , memfile , optimizer )
2769+
27022770 script = ScriptSource ()
27032771
27042772 logger .debug ('generating HTML' )
0 commit comments