From c81421795f37b764a6503b79eb2fd1561c0b5f1b Mon Sep 17 00:00:00 2001 From: Sam Clegg Date: Tue, 25 Nov 2025 09:05:49 -0800 Subject: [PATCH] Refactor legacy cmdline flag handling This does turn some warnings into errors, but I also think its appropriate to error when unsupported command line flags are passed. --- test/test_other.py | 15 +++++++-------- tools/cmdline.py | 42 +++++++++++++++--------------------------- 2 files changed, 22 insertions(+), 35 deletions(-) diff --git a/test/test_other.py b/test/test_other.py index 3842ba77b06ba..706c3edb67945 100644 --- a/test/test_other.py +++ b/test/test_other.py @@ -3691,9 +3691,7 @@ def test_embind_tsgen_exceptions(self, legacy): # Check that when Wasm exceptions and assertions are enabled bindings still generate. self.run_process([EMXX, test_file('other/embind_tsgen.cpp'), '-lembind', '-fwasm-exceptions', '-sASSERTIONS', - # Use the deprecated `--embind-emit-tsd` to ensure it - # still works until removed. - '--embind-emit-tsd', 'embind_tsgen.d.ts', '-Wno-deprecated'] + + '--emit-tsd', 'embind_tsgen.d.ts', '-Wno-deprecated'] + self.get_cflags()) self.assertFileContents(test_file('other/embind_tsgen.d.ts'), read_file('embind_tsgen.d.ts')) @@ -11494,11 +11492,12 @@ def test_backwards_deps_in_archive(self): def test_warning_flags(self): self.run_process([EMCC, '-c', '-o', 'hello.o', test_file('hello_world.c')]) - cmd = [EMCC, 'hello.o', '-o', 'a.js', '-g', '--llvm-opts=""'] + # -g4 will generte a deprecated warning + cmd = [EMCC, 'hello.o', '-o', 'a.js', '-g4'] # warning that is enabled by default stderr = self.run_process(cmd, stderr=PIPE).stderr - self.assertContained('emcc: warning: --llvm-opts is deprecated. All non-emcc args are passed through to clang. [-Wdeprecated]', stderr) + self.assertContained('emcc: warning: please replace -g4 with -gsource-map [-Wdeprecated]', stderr) # -w to suppress warnings stderr = self.run_process(cmd + ['-w'], stderr=PIPE).stderr @@ -11509,12 +11508,12 @@ def test_warning_flags(self): self.assertNotContained('warning', stderr) # with -Werror should fail - expected = 'error: --llvm-opts is deprecated. All non-emcc args are passed through to clang. [-Wdeprecated] [-Werror]' + expected = 'error: please replace -g4 with -gsource-map [-Wdeprecated] [-Werror]' self.assert_fail(cmd + ['-Werror'], expected) # with -Werror + -Wno-error= should only warn stderr = self.run_process(cmd + ['-Werror', '-Wno-error=deprecated'], stderr=PIPE).stderr - self.assertContained('emcc: warning: --llvm-opts is deprecated. All non-emcc args are passed through to clang. [-Wdeprecated]', stderr) + self.assertContained('emcc: warning: please replace -g4 with -gsource-map [-Wdeprecated]', stderr) # check that `-Werror=foo` also enales foo expected = 'error: use of legacy setting: TOTAL_MEMORY (setting renamed to INITIAL_MEMORY) [-Wlegacy-settings] [-Werror]' @@ -14072,7 +14071,7 @@ def test_wasi_with_sjlj(self): self.do_runf('core/test_longjmp.c', cflags=self.get_cflags()) def test_memory_init_file_unsupported(self): - self.assert_fail([EMCC, test_file('hello_world.c'), '--memory-init-file=1'], 'error: --memory-init-file is no longer supported') + self.assert_fail([EMCC, test_file('hello_world.c'), '-Werror', '--memory-init-file=1'], 'error: --memory-init-file is no longer supported') @node_pthreads def test_node_pthreads_err_out(self): diff --git a/tools/cmdline.py b/tools/cmdline.py index 54ef6202b97ee..995fda9f42853 100644 --- a/tools/cmdline.py +++ b/tools/cmdline.py @@ -210,6 +210,9 @@ def parse_args(newargs): # noqa: C901, PLR0912, PLR0915 """ should_exit = False skip = False + LEGACY_ARGS = {'--js-opts', '--llvm-opts', '--llvm-lto', '--memory-init-file'} + LEGACY_FLAGS = {'--separate-asm', '--jcache', '--proxy-to-worker', '--default-obj-ext', + '--embind-emit-tsd', '--remove-duplicates', '--no-heap-copy'} for i in range(len(newargs)): if skip: @@ -238,9 +241,9 @@ def check_flag(value): return False def check_arg(name): - nonlocal arg_value + nonlocal arg, arg_value if arg.startswith(name) and '=' in arg: - arg_value = arg.split('=', 1)[1] + arg, arg_value = arg.split('=', 1) newargs[i] = '' return True if arg == name: @@ -265,6 +268,16 @@ def consume_arg_file(): exit_with_error("'%s': file not found: '%s'" % (arg, name)) return name + if arg in LEGACY_FLAGS: + diagnostics.warning('deprecated', f'{arg} is no longer supported') + continue + + for l in LEGACY_ARGS: + if check_arg(l): + consume_arg() + diagnostics.warning('deprecated', f'{arg} is no longer supported') + continue + if arg.startswith('-s') and is_dash_s_for_emcc(newargs, i): s_arg = arg if arg == '-s': @@ -301,11 +314,6 @@ def consume_arg_file(): newargs[i] = '-O3' level = 3 settings.OPT_LEVEL = level - elif check_arg('--js-opts'): - logger.warning('--js-opts ignored when using llvm backend') - consume_arg() - elif check_arg('--llvm-opts'): - diagnostics.warning('deprecated', '--llvm-opts is deprecated. All non-emcc args are passed through to clang.') elif arg.startswith('-flto'): if '=' in arg: settings.LTO = arg.split('=')[1] @@ -315,9 +323,6 @@ def consume_arg_file(): settings.LTO = 0 elif arg == "--save-temps": options.save_temps = True - elif check_arg('--llvm-lto'): - logger.warning('--llvm-lto ignored when using llvm backend') - consume_arg() elif check_arg('--closure-args'): args = consume_arg() settings.CLOSURE_ARGS += shlex.split(args) @@ -432,8 +437,6 @@ def consume_arg_file(): options.exclude_files.append(consume_arg()) elif check_flag('--use-preload-cache'): options.use_preload_cache = True - elif check_flag('--no-heap-copy'): - diagnostics.warning('legacy-settings', 'ignoring legacy flag --no-heap-copy (that is the only mode supported now)') elif check_flag('--use-preload-plugins'): options.use_preload_plugins = True elif check_flag('--ignore-dynamic-linking'): @@ -446,17 +449,10 @@ def consume_arg_file(): options.shell_path = consume_arg_file() elif check_arg('--source-map-base'): options.source_map_base = consume_arg() - elif check_arg('--embind-emit-tsd'): - diagnostics.warning('deprecated', '--embind-emit-tsd is deprecated. Use --emit-tsd instead.') - options.emit_tsd = consume_arg() elif check_arg('--emit-tsd'): options.emit_tsd = consume_arg() elif check_flag('--no-entry'): options.no_entry = True - elif check_flag('--remove-duplicates'): - diagnostics.warning('legacy-settings', '--remove-duplicates is deprecated as it is no longer needed. If you cannot link without it, file a bug with a testcase') - elif check_flag('--jcache'): - logger.error('jcache is no longer supported') elif check_arg('--cache'): config.CACHE = os.path.abspath(consume_arg()) cache.setup() @@ -481,14 +477,8 @@ def consume_arg_file(): elif check_flag('--show-ports'): ports.show_ports() should_exit = True - elif check_arg('--memory-init-file'): - exit_with_error('--memory-init-file is no longer supported') - elif check_flag('--proxy-to-worker'): - exit_with_error('--proxy-to-worker is no longer supported') elif check_arg('--valid-abspath'): options.valid_abspaths.append(consume_arg()) - elif check_flag('--separate-asm'): - exit_with_error('cannot --separate-asm with the wasm backend, since not emitting asm.js') elif arg.startswith(('-I', '-L')): path_name = arg[2:] # Look for '/' explicitly so that we can also diagnose identically if -I/foo/bar is passed on Windows. @@ -549,8 +539,6 @@ def consume_arg_file(): settings.DISABLE_EXCEPTION_CATCHING = 1 elif arg == '-ffast-math': options.fast_math = True - elif check_arg('--default-obj-ext'): - exit_with_error('--default-obj-ext is no longer supported by emcc') elif arg.startswith('-fsanitize=cfi'): exit_with_error('emscripten does not currently support -fsanitize=cfi') elif check_arg('--output_eol') or check_arg('--output-eol'):