diff --git a/emcc.py b/emcc.py index ef394a5f05a54..62560baa768d3 100755 --- a/emcc.py +++ b/emcc.py @@ -1821,6 +1821,7 @@ def check_human_readable_list(items): shared.Settings.BUNDLED_CD_DEBUG_FILE = target + ".cd" shared.Settings.SYSTEM_JS_LIBRARIES.append(shared.path_from_root('src', 'library_cyberdwarf.js')) shared.Settings.SYSTEM_JS_LIBRARIES.append(shared.path_from_root('src', 'library_debugger_toolkit.js')) + newargs.append('-g') if options.tracing: if shared.Settings.ALLOW_MEMORY_GROWTH: @@ -1891,11 +1892,8 @@ def check_human_readable_list(items): logger.debug("running (for precompiled headers): " + clang_compiler + ' ' + ' '.join(args)) return run_process([clang_compiler] + args, check=False).returncode - if need_llvm_debug_info(options): - newargs.append('-g') - # For asm.js, the generated JavaScript could preserve LLVM value names, which can be useful for debugging. - if options.debug_level >= 3 and not shared.Settings.WASM: + if options.debug_level >= 3 and not shared.Settings.WASM and not shared.Settings.WASM_BACKEND: newargs.append('-fno-discard-value-names') def is_link_flag(flag): @@ -2640,10 +2638,26 @@ def check_bad_eq(arg): newargs[i] = '' newargs[i + 1] = '' elif newargs[i].startswith('-g'): - requested_level = newargs[i][2:] or '3' - options.debug_level = validate_arg_level(requested_level, 4, 'Invalid debug level: ' + newargs[i]) options.requested_debug = newargs[i] - newargs[i] = '' + requested_level = newargs[i][2:] or '3' + if is_int(requested_level): + # the -gX value is the debug level (-g1, -g2, etc.) + options.debug_level = validate_arg_level(requested_level, 4, 'Invalid debug level: ' + newargs[i]) + # if we don't need to preserve LLVM debug info, do not keep this flag + # for clang + if options.debug_level < 3: + newargs[i] = '' + else: + # until we support full DWARF info, limit the clang frontend to just + # emit line tables, which can be represented in source maps + newargs[i] = '-gline-tables-only' + else: + # a non-integer level can be something like -gline-tables-only. keep + # the flag for the clang frontend to emit the appropriate DWARF info. + # set the emscripten debug level to 3 so that we do not remove that + # debug info during link (during compile, this does not make a + # difference). + options.debug_level = 3 elif newargs[i] == '-profiling' or newargs[i] == '--profiling': options.debug_level = max(options.debug_level, 2) options.profiling = True @@ -3676,6 +3690,14 @@ def validate_arg_level(level_string, max_level, err_msg, clamp=False): return level +def is_int(s): + try: + int(s) + return True + except ValueError: + return False + + if __name__ == '__main__': try: sys.exit(run(sys.argv)) diff --git a/site/source/docs/tools_reference/emcc.rst b/site/source/docs/tools_reference/emcc.rst index 3e9180eb35423..d6a0ff33dec3d 100644 --- a/site/source/docs/tools_reference/emcc.rst +++ b/site/source/docs/tools_reference/emcc.rst @@ -112,7 +112,7 @@ Options that are modified or new in *emcc* are listed below: Preserve debug information. - When compiling to object files, this is the same as in *Clang* and *gcc*, it adds debug information to the object files. - - When linking, this is equivalent to :ref:`-g3 ` (preserve JS whitespace and compiled function names). + - When linking, this is equivalent to :ref:`-g3 `. .. _emcc-gN: @@ -137,7 +137,7 @@ Options that are modified or new in *emcc* are listed below: - .. _emcc-g3: - ``-g3``: When compiling to object files, keep debug info (this is the same as :ref:`-g `). + ``-g3``: When compiling to object files, keep debug info, including JS whitespace, function names, and LLVM debug info if any (this is the same as :ref:`-g `). .. _emcc-g4: diff --git a/tests/test_other.py b/tests/test_other.py index 29194e345496f..b89532226669c 100644 --- a/tests/test_other.py +++ b/tests/test_other.py @@ -2329,6 +2329,33 @@ def test_debuginfo(self): else: self.assertIn('strip-debug', err) + @no_fastcomp() + def test_debuginfo_line_tables_only(self): + def test(do_compile): + do_compile([]) + no_size = os.path.getsize('a.out.wasm') + do_compile(['-gline-tables-only']) + line_size = os.path.getsize('a.out.wasm') + do_compile(['-g']) + full_size = os.path.getsize('a.out.wasm') + self.assertLess(no_size, line_size) + # currently we don't support full debug info anyhow, so line tables + # is all we have + self.assertEqual(line_size, full_size) + + def compile_directly(compile_args): + run_process([PYTHON, EMCC, path_from_root('tests', 'hello_world.cpp')] + compile_args) + + test(compile_directly) + + def compile_to_object_first(compile_args): + # compile with the specified args + run_process([PYTHON, EMCC, path_from_root('tests', 'hello_world.cpp')] + compile_args + ['-c', '-o', 'a.o']) + # link with debug info + run_process([PYTHON, EMCC, 'a.o', '-g']) + + test(compile_to_object_first) + @unittest.skipIf(not scons_path, 'scons not found in PATH') @with_env_modify({'EMSCRIPTEN_ROOT': path_from_root()}) def test_scons(self):