Skip to content

Commit 52e67f1

Browse files
authored
[emcc] Refactor incompatible settings error reporting. NFC (#24853)
1 parent a2b1fdd commit 52e67f1

File tree

2 files changed

+55
-53
lines changed

2 files changed

+55
-53
lines changed

test/test_other.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1652,10 +1652,10 @@ def test_minimal_runtime_export_all_modularize(self):
16521652
self.assertContained('libf1\nlibf2\n', self.run_js('main.mjs'))
16531653

16541654
def test_minimal_runtime_errors(self):
1655-
err = self.expect_fail([EMCC, test_file('hello_world.c'), '-sMINIMAL_RUNTIME_STREAMING_WASM_COMPILATION'])
1655+
err = self.expect_fail([EMCC, test_file('hello_world.c'), '-o', 'out.html', '-sMINIMAL_RUNTIME_STREAMING_WASM_COMPILATION'])
16561656
self.assertContained('emcc: error: MINIMAL_RUNTIME_STREAMING_WASM_COMPILATION requires MINIMAL_RUNTIME', err)
16571657

1658-
err = self.expect_fail([EMCC, test_file('hello_world.c'), '-sMINIMAL_RUNTIME_STREAMING_WASM_INSTANTIATION'])
1658+
err = self.expect_fail([EMCC, test_file('hello_world.c'), '-o', 'our.html', '-sMINIMAL_RUNTIME_STREAMING_WASM_INSTANTIATION'])
16591659
self.assertContained('emcc: error: MINIMAL_RUNTIME_STREAMING_WASM_INSTANTIATION requires MINIMAL_RUNTIME', err)
16601660

16611661
err = self.expect_fail([EMCC, test_file('hello_world.c'), '-sMINIMAL_RUNTIME', '-sMINIMAL_RUNTIME_STREAMING_WASM_COMPILATION'])
@@ -13527,7 +13527,7 @@ def test_wasm2js_no_dylink(self):
1352713527
for arg in ('-sMAIN_MODULE', '-sSIDE_MODULE', '-sRELOCATABLE'):
1352813528
print(arg)
1352913529
err = self.expect_fail([EMCC, test_file('hello_world.c'), '-sWASM=0', arg])
13530-
self.assertContained('WASM2JS is not compatible with relocatable output', err)
13530+
self.assertContained('emcc: error: WASM2JS is not compatible with RELOCATABLE', err)
1353113531

1353213532
def test_wasm2js_standalone(self):
1353313533
self.do_run_in_out_file_test('hello_world.c', cflags=['-sSTANDALONE_WASM', '-sWASM=0'])
@@ -14055,7 +14055,7 @@ def test_bad_export_name(self):
1405514055

1405614056
def test_offset_convertor_plus_wasm2js(self):
1405714057
err = self.expect_fail([EMCC, '-sUSE_OFFSET_CONVERTER', '-sWASM=0', test_file('hello_world.c')])
14058-
self.assertContained('wasm2js is not compatible with USE_OFFSET_CONVERTER', err)
14058+
self.assertContained('emcc: error: WASM2JS is not compatible with USE_OFFSET_CONVERTER (see #14630)', err)
1405914059

1406014060
def test_standard_library_mapping(self):
1406114061
# Test the `-l` flags on the command line get mapped the correct libraries variant
@@ -15255,7 +15255,7 @@ def test_standalone_settings(self):
1525515255
base_cmd = [EMCC, test_file('hello_world.c'), '-sSTANDALONE_WASM']
1525615256

1525715257
err = self.expect_fail(base_cmd + ['-sMINIMAL_RUNTIME'])
15258-
self.assertContained('error: MINIMAL_RUNTIME reduces JS size, and is incompatible with STANDALONE_WASM which focuses on ignoring JS anyhow and being 100% wasm', err)
15258+
self.assertContained('emcc: error: STANDALONE_WASM is not compatible with MINIMAL_RUNTIME', err)
1525915259

1526015260
err = self.expect_fail(base_cmd + ['-sMEMORY_GROWTH_GEOMETRIC_CAP=1mb'])
1526115261
self.assertContained('error: MEMORY_GROWTH_GEOMETRIC_CAP is not compatible with STANDALONE_WASM', err)

tools/link.py

Lines changed: 50 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -650,13 +650,56 @@ def add_system_js_lib(lib):
650650
settings.JS_LIBRARIES.append(lib)
651651

652652

653+
def report_incompatible_settings():
654+
# List of incompatible settings, of the form (SETTINGS_A, SETTING_B, OPTIONAL_REASON_FOR_INCOMPAT)
655+
incompatible_settings = [
656+
('MINIMAL_RUNTIME', 'RELOCATABLE', None),
657+
('WASM2JS', 'RELOCATABLE', None),
658+
('MODULARIZE', 'PROXY_TO_WORKER', 'if you want to run in a worker with -sMODULARIZE, you likely want to do the worker side setup manually'),
659+
('MODULARIZE', 'NO_DECLARE_ASM_MODULE_EXPORTS', None),
660+
('EVAL_CTORS', 'WASM2JS', None),
661+
('EVAL_CTORS', 'RELOCATABLE', 'movable segments'),
662+
# In Asyncify exports can be called more than once, and this seems to not
663+
# work properly yet (see test_emscripten_scan_registers).
664+
('EVAL_CTORS', 'ASYNCIFY', None),
665+
('PTHREADS_PROFILING', 'NO_ASSERTIONS', 'only works with ASSERTIONS enabled'),
666+
('SOURCE_PHASE_IMPORTS', 'NO_EXPORT_ES6', None),
667+
('STANDALONE_WASM', 'MINIMAL_RUNTIME', None),
668+
('STRICT_JS', 'MODULARIZE', None),
669+
('STRICT_JS', 'EXPORT_ES6', None),
670+
('MINIMAL_RUNTIME_STREAMING_WASM_COMPILATION', 'MINIMAL_RUNTIME_STREAMING_WASM_INSTANTIATION', 'they are mutually exclusive'),
671+
('SEPARATE_DWARF', 'WASM2JS', 'as there is no wasm file'),
672+
('GL_SUPPORT_AUTOMATIC_ENABLE_EXTENSIONS', 'NO_GL_SUPPORT_SIMPLE_ENABLE_EXTENSIONS', None),
673+
('MODULARIZE', 'NODEJS_CATCH_REJECTION', None),
674+
('MODULARIZE', 'NODEJS_CATCH_EXIT', None),
675+
('WASM2JS', 'USE_OFFSET_CONVERTER', 'see #14630'),
676+
]
677+
678+
for a, b, reason in incompatible_settings:
679+
invert_b = b.startswith('NO_')
680+
if invert_b:
681+
b = b[3:]
682+
683+
b_val = getattr(settings, b)
684+
if invert_b:
685+
b_val = not b_val
686+
687+
if getattr(settings, a) and b_val:
688+
msg = f'{a} is not compatible with {b}'
689+
if invert_b:
690+
msg += '=0'
691+
if reason:
692+
msg += f' ({reason})'
693+
exit_with_error(msg)
694+
695+
653696
@ToolchainProfiler.profile_block('linker_setup')
654697
def phase_linker_setup(options, linker_args): # noqa: C901, PLR0912, PLR0915
655698
"""Future modifications should consider refactoring to reduce complexity.
656699
657-
* The McCabe cyclomatiic complexity is currently 251 vs 10 recommended.
658-
* There are currently 262 branches vs 12 recommended.
659-
* There are currently 578 statements vs 50 recommended.
700+
* The McCabe cyclomatiic complexity is currently 244 vs 10 recommended.
701+
* There are currently 252 branches vs 12 recommended.
702+
* There are currently 563 statements vs 50 recommended.
660703
661704
To revalidate these numbers, run `ruff check --select=C901,PLR091`.
662705
"""
@@ -717,8 +760,6 @@ def phase_linker_setup(options, linker_args): # noqa: C901, PLR0912, PLR0915
717760
settings.MEMORYPROFILER = 1
718761

719762
if settings.PTHREADS_PROFILING:
720-
if not settings.ASSERTIONS:
721-
exit_with_error('PTHREADS_PROFILING only works with ASSERTIONS enabled')
722763
options.post_js.append(utils.path_from_root('src/threadprofiler.js'))
723764
settings.REQUIRED_EXPORTS.append('emscripten_main_runtime_thread_id')
724765
# threadprofiler.js needs these library functions.
@@ -798,10 +839,6 @@ def phase_linker_setup(options, linker_args): # noqa: C901, PLR0912, PLR0915
798839
if settings.GROWABLE_ARRAYBUFFERS:
799840
diagnostics.warning('experimental', '-sGROWABLE_ARRAYBUFFERS is still experimental and not yet supported in browsers')
800841

801-
if settings.SOURCE_PHASE_IMPORTS:
802-
if not settings.EXPORT_ES6:
803-
exit_with_error('SOURCE_PHASE_IMPORTS requires EXPORT_ES6')
804-
805842
if settings.WASM_ESM_INTEGRATION:
806843
diagnostics.warning('experimental', '-sWASM_ESM_INTEGRATION is still experimental and not yet supported in browsers')
807844
default_setting('MODULARIZE', 'instance')
@@ -946,8 +983,6 @@ def limit_incoming_module_api():
946983
exit_with_error('MEMORY_GROWTH_LINEAR_STEP is not compatible with STANDALONE_WASM')
947984
if 'MEMORY_GROWTH_GEOMETRIC_CAP' in user_settings:
948985
exit_with_error('MEMORY_GROWTH_GEOMETRIC_CAP is not compatible with STANDALONE_WASM')
949-
if settings.MINIMAL_RUNTIME:
950-
exit_with_error('MINIMAL_RUNTIME reduces JS size, and is incompatible with STANDALONE_WASM which focuses on ignoring JS anyhow and being 100% wasm')
951986

952987
# Note the exports the user requested
953988
building.user_requested_exports.update(settings.EXPORTED_FUNCTIONS)
@@ -998,9 +1033,6 @@ def limit_incoming_module_api():
9981033
exit_with_error('EXPORT_ES6 requires MODULARIZE to be set')
9991034
settings.MODULARIZE = 1
10001035

1001-
if settings.STRICT_JS and (settings.MODULARIZE or settings.EXPORT_ES6):
1002-
exit_with_error("STRICT_JS doesn't work with MODULARIZE or EXPORT_ES6")
1003-
10041036
if not options.shell_path:
10051037
# Minimal runtime uses a different default shell file
10061038
if settings.MINIMAL_RUNTIME:
@@ -1051,11 +1083,8 @@ def limit_incoming_module_api():
10511083
if settings.WASM == 2 and settings.SINGLE_FILE:
10521084
exit_with_error('cannot have both WASM=2 and SINGLE_FILE enabled at the same time')
10531085

1054-
if settings.SEPARATE_DWARF and settings.WASM2JS:
1055-
exit_with_error('cannot have both SEPARATE_DWARF and WASM2JS at the same time (as there is no wasm file)')
1056-
1057-
if settings.MINIMAL_RUNTIME_STREAMING_WASM_COMPILATION and settings.MINIMAL_RUNTIME_STREAMING_WASM_INSTANTIATION:
1058-
exit_with_error('MINIMAL_RUNTIME_STREAMING_WASM_COMPILATION and MINIMAL_RUNTIME_STREAMING_WASM_INSTANTIATION are mutually exclusive!')
1086+
if settings.MINIMAL_RUNTIME_STREAMING_WASM_COMPILATION and options.oformat != OFormat.HTML:
1087+
exit_with_error('MINIMAL_RUNTIME_STREAMING_WASM_COMPILATION is only compatible with html output')
10591088

10601089
if settings.MINIMAL_RUNTIME_STREAMING_WASM_INSTANTIATION and not settings.MINIMAL_RUNTIME:
10611090
exit_with_error('MINIMAL_RUNTIME_STREAMING_WASM_INSTANTIATION requires MINIMAL_RUNTIME')
@@ -1141,10 +1170,6 @@ def limit_incoming_module_api():
11411170
'__asyncify_data',
11421171
]
11431172

1144-
if settings.MINIMAL_RUNTIME:
1145-
exit_with_error('MINIMAL_RUNTIME is not compatible with relocatable output')
1146-
if settings.WASM2JS:
1147-
exit_with_error('WASM2JS is not compatible with relocatable output')
11481173
# shared modules need memory utilities to allocate their memory
11491174
settings.ALLOW_TABLE_GROWTH = 1
11501175

@@ -1231,8 +1256,6 @@ def limit_incoming_module_api():
12311256
settings.DEFAULT_LIBRARY_FUNCS_TO_INCLUDE += ['$setStackLimits']
12321257

12331258
if settings.MODULARIZE:
1234-
if settings.PROXY_TO_WORKER:
1235-
exit_with_error('-sMODULARIZE is not compatible with --proxy-to-worker (if you want to run in a worker with -sMODULARIZE, you likely want to do the worker side setup manually)')
12361259
# in MINIMAL_RUNTIME we may not need to emit the Promise code, as the
12371260
# HTML output creates a singleton instance, and it does so without the
12381261
# Promise. However, in Pthreads mode the Promise is used for worker
@@ -1251,8 +1274,6 @@ def limit_incoming_module_api():
12511274
if settings.MODULARIZE:
12521275
default_setting('NODEJS_CATCH_REJECTION', 0)
12531276
default_setting('NODEJS_CATCH_EXIT', 0)
1254-
if settings.NODEJS_CATCH_REJECTION or settings.NODEJS_CATCH_EXIT:
1255-
exit_with_error('cannot use -sNODEJS_CATCH_REJECTION or -sNODEJS_CATCH_EXIT with -sMODULARIZE')
12561277

12571278
if settings.POLYFILL:
12581279
# Emscripten requires certain ES6+ constructs by default in library code
@@ -1284,9 +1305,6 @@ def limit_incoming_module_api():
12841305
if settings.MIN_WEBGL_VERSION > settings.MAX_WEBGL_VERSION:
12851306
exit_with_error('MIN_WEBGL_VERSION must be smaller or equal to MAX_WEBGL_VERSION!')
12861307

1287-
if not settings.GL_SUPPORT_SIMPLE_ENABLE_EXTENSIONS and settings.GL_SUPPORT_AUTOMATIC_ENABLE_EXTENSIONS:
1288-
exit_with_error('-sGL_SUPPORT_SIMPLE_ENABLE_EXTENSIONS=0 only makes sense with -sGL_SUPPORT_AUTOMATIC_ENABLE_EXTENSIONS=0!')
1289-
12901308
if options.use_preload_plugins or len(options.preload_files) or len(options.embed_files):
12911309
if settings.NODERAWFS:
12921310
exit_with_error('--preload-file and --embed-file cannot be used with NODERAWFS which disables virtual filesystem')
@@ -1489,11 +1507,6 @@ def limit_incoming_module_api():
14891507

14901508
set_initial_memory()
14911509

1492-
if settings.MODULARIZE and not settings.DECLARE_ASM_MODULE_EXPORTS:
1493-
# When MODULARIZE option is used, currently requires declaring all module exports
1494-
# individually - TODO: this could be optimized
1495-
exit_with_error('DECLARE_ASM_MODULE_EXPORTS=0 is not compatible with MODULARIZE')
1496-
14971510
# When not declaring wasm module exports in outer scope one by one, disable minifying
14981511
# wasm module export names so that the names can be passed directly to the outer scope.
14991512
# Also, if using libexports.js API, disable minification so that the feature can work.
@@ -1533,17 +1546,6 @@ def limit_incoming_module_api():
15331546
diagnostics.warning('emcc', 'SINGLE_FILE disables source map support (which requires a .map file)')
15341547
settings.GENERATE_SOURCE_MAP = 0
15351548

1536-
if settings.EVAL_CTORS:
1537-
if settings.WASM2JS:
1538-
# code size/memory and correctness issues TODO
1539-
exit_with_error('EVAL_CTORS is not compatible with wasm2js yet')
1540-
elif settings.RELOCATABLE:
1541-
exit_with_error('EVAL_CTORS is not compatible with relocatable yet (movable segments)')
1542-
elif settings.ASYNCIFY:
1543-
# In Asyncify exports can be called more than once, and this seems to not
1544-
# work properly yet (see test_emscripten_scan_registers).
1545-
exit_with_error('EVAL_CTORS is not compatible with asyncify yet')
1546-
15471549
if options.use_closure_compiler == 2 and not settings.WASM2JS:
15481550
exit_with_error('closure compiler mode 2 assumes the code is asm.js, so not meaningful for wasm')
15491551

@@ -1590,8 +1592,6 @@ def limit_incoming_module_api():
15901592
inc_initial_memory(50 * 1024 * 1024)
15911593

15921594
if settings.USE_OFFSET_CONVERTER:
1593-
if settings.WASM2JS:
1594-
exit_with_error('wasm2js is not compatible with USE_OFFSET_CONVERTER (see #14630)')
15951595
settings.DEFAULT_LIBRARY_FUNCS_TO_INCLUDE.append('$UTF8ArrayToString')
15961596

15971597
if options.sanitize & UBSAN_SANITIZERS:
@@ -1885,6 +1885,8 @@ def get_full_import_name(name):
18851885
if settings.USE_CLOSURE_COMPILER or not settings.MINIFY_WHITESPACE:
18861886
settings.MAYBE_CLOSURE_COMPILER = 1
18871887

1888+
report_incompatible_settings()
1889+
18881890
return target, wasm_target
18891891

18901892

0 commit comments

Comments
 (0)