@@ -663,7 +663,7 @@ def uniquename(name):
663
663
664
664
specified_target = target
665
665
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 )
667
667
668
668
final_suffix = suffix (target )
669
669
@@ -1043,6 +1043,7 @@ def check(input_file):
1043
1043
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'
1044
1044
1045
1045
if options .emrun :
1046
+ assert not shared .Settings .MINIMAL_RUNTIME , '--emrun is not compatible with -s MINIMAL_RUNTIME=1'
1046
1047
shared .Settings .EXPORTED_RUNTIME_METHODS .append ('addOnExit' )
1047
1048
1048
1049
if options .use_closure_compiler :
@@ -1122,7 +1123,7 @@ def check(input_file):
1122
1123
shared .Settings .EXPORTED_FUNCTIONS += ['___cxa_demangle' ]
1123
1124
forced_stdlibs += ['libc++abi' ]
1124
1125
1125
- if not shared .Settings .ONLY_MY_CODE :
1126
+ if not shared .Settings .ONLY_MY_CODE and not shared . Settings . MINIMAL_RUNTIME :
1126
1127
# Always need malloc and free to be kept alive and exported, for internal use and other modules
1127
1128
shared .Settings .EXPORTED_FUNCTIONS += ['_malloc' , '_free' ]
1128
1129
if shared .Settings .WASM_BACKEND :
@@ -1285,6 +1286,24 @@ def check(input_file):
1285
1286
if not shared .Settings .SEPARATE_ASM_MODULE_NAME :
1286
1287
shared .Settings .SEPARATE_ASM_MODULE_NAME = 'Module["asm"]'
1287
1288
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
+
1288
1307
if shared .Settings .WASM :
1289
1308
if shared .Settings .SINGLE_FILE :
1290
1309
# placeholder strings for JS glue, to be replaced with subresource locations in do_binaryen
@@ -1317,18 +1336,20 @@ def check(input_file):
1317
1336
if any (s .startswith ('MEM_INIT_METHOD=' ) for s in settings_changes ):
1318
1337
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.' )
1319
1338
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 )
1332
1353
1333
1354
if not shared .Settings .DECLARE_ASM_MODULE_EXPORTS :
1334
1355
# Swappable wasm module/asynchronous wasm compilation requires an indirect stub
@@ -1337,10 +1358,6 @@ def check(input_file):
1337
1358
if shared .Settings .SWAPPABLE_ASM_MODULE == 1 :
1338
1359
shared .Settings .DECLARE_ASM_MODULE_EXPORTS = 1
1339
1360
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' )
1344
1361
1345
1362
# we will include the mem init data in the wasm, when we don't need the
1346
1363
# mem init file to be loadable by itself
@@ -1405,6 +1422,16 @@ def check(input_file):
1405
1422
if not shared .Settings .WASM and (shared .Settings .MAIN_MODULE or shared .Settings .SIDE_MODULE ):
1406
1423
assert not shared .Settings .ALLOW_MEMORY_GROWTH , 'memory growth is not supported with shared asm.js modules'
1407
1424
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
+
1408
1435
if shared .Settings .ALLOW_MEMORY_GROWTH and shared .Settings .ASM_JS == 1 :
1409
1436
# this is an issue in asm.js, but not wasm
1410
1437
if not shared .Settings .WASM :
@@ -1437,6 +1464,10 @@ def check(input_file):
1437
1464
options .separate_asm = True
1438
1465
shared .Settings .FINALIZE_ASM_JS = False
1439
1466
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
+
1440
1471
if shared .Settings .GLOBAL_BASE < 0 :
1441
1472
shared .Settings .GLOBAL_BASE = 8 # default if nothing else sets it
1442
1473
@@ -1918,7 +1949,11 @@ def get_final():
1918
1949
with ToolchainProfiler .profile_block ('memory initializer' ):
1919
1950
memfile = None
1920
1951
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'
1922
1957
1923
1958
if memfile and not shared .Settings .WASM_BACKEND :
1924
1959
# Strip the memory initializer out of the asmjs file
@@ -2109,6 +2144,15 @@ def get_eliminate():
2109
2144
2110
2145
module_export_name_substitution ()
2111
2146
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
+
2112
2156
# The JS is now final. Move it to its final location
2113
2157
shutil .move (final , js_target )
2114
2158
@@ -2690,15 +2734,39 @@ def module_export_name_substitution():
2690
2734
logger .debug ('Private module export name substitution with ' + shared .Settings .EXPORT_NAME )
2691
2735
src = open (final ).read ()
2692
2736
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 }
2694
2742
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 )
2696
2749
save_intermediate ('module_export_name_substitution' )
2697
2750
2698
2751
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
+
2699
2763
def generate_html (target , options , js_target , target_basename ,
2700
2764
asm_target , wasm_binary_target ,
2701
2765
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
+
2702
2770
script = ScriptSource ()
2703
2771
2704
2772
logger .debug ('generating HTML' )
0 commit comments