diff --git a/tools/idf_py_actions/debug_ext.py b/tools/idf_py_actions/debug_ext.py index ed1eed2ae5..eb05437e92 100644 --- a/tools/idf_py_actions/debug_ext.py +++ b/tools/idf_py_actions/debug_ext.py @@ -15,6 +15,7 @@ from typing import Any from typing import Dict from typing import List from typing import Optional +from typing import Tuple from typing import Union from click import INT @@ -157,10 +158,10 @@ def action_extensions(base_actions: Dict, project_path: str) -> Dict: def _get_espcoredump_instance(ctx: Context, args: PropertyDict, - gdb_timeout_sec: int = None, - core: str = None, - chip_rev: str = None, - save_core: str = None) -> CoreDump: + gdb_timeout_sec: Optional[int] = None, + core: Optional[str] = None, + chip_rev: Optional[str] = None, + save_core: Optional[str] = None) -> CoreDump: ensure_build_directory(args, ctx.info_name) project_desc = get_project_desc(args, ctx) @@ -243,7 +244,7 @@ def action_extensions(base_actions: Dict, project_path: str) -> Dict: with open(os.path.join(os.path.dirname(os.path.realpath(__file__)), ESP_ROM_INFO_FILE), 'r') as f: roms = json.load(f) if target not in roms: - msg_body = f'Target "{target}" was not found in "{ESP_ROM_INFO_FILE}". Please check IDF integrity.' + msg_body = f'Target "{target}" was not found in "{ESP_ROM_INFO_FILE}". Please check IDF integrity.' # noqa: E713 if os.getenv('ESP_IDF_GDB_TESTING'): raise FatalError(msg_body) print(f'Warning: {msg_body}') @@ -406,6 +407,24 @@ def action_extensions(base_actions: Dict, project_path: str) -> Dict: args.append('-ix={}'.format(debug_prefix_gdbinit)) return args + def _get_gdbgui_version(ctx: Context) -> Tuple[int, ...]: + completed_process = subprocess.run(['gdbgui', '--version'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + captured_output = completed_process.stdout.decode('utf-8', 'ignore') + + if completed_process.returncode != 0: + if sys.version_info[:2] >= (3, 11) and sys.platform == 'win32': + raise SystemExit('Unfortunately, gdbgui is supported only with Python 3.10 or older. ' + 'See: https://github.com/espressif/esp-idf/issues/10116. ' + 'Please use "idf.py gdb" or debug in Eclipse/Vscode instead.') + raise FatalError('Error starting gdbgui. Please make sure gdbgui has been installed with ' + '"install.{sh,bat,ps1,fish} --enable-gdbgui" and can be started. ' + f'Error: {captured_output}', ctx) + + v = re.search(r'(\d+)(?:\.(\d+))?(?:\.(\d+))?(?:\.(\d+))?', captured_output) + if not v: + raise SystemExit(f'Error: "gdbgui --version" returned "{captured_output}"') + return tuple(int(i) if i else 0 for i in (v[1], v[2], v[3], v[4])) + def gdbui(action: str, ctx: Context, args: PropertyDict, gdbgui_port: Optional[str], gdbinit: Optional[str], require_openocd: bool) -> None: """ @@ -416,11 +435,11 @@ def action_extensions(base_actions: Dict, project_path: str) -> Dict: gdb = project_desc['monitor_toolprefix'] + 'gdb' generate_gdbinit_files(gdb, gdbinit, project_desc) + gdbgui_version = _get_gdbgui_version(ctx) gdb_args_list = get_gdb_args(project_desc) - if sys.version_info[:2] >= (3, 11): - # If we use Python 3.11+ then the only compatible gdbgui doesn't support the --gdb-args argument. This - # check is easier than checking gdbgui version or re-running the process in case of gdb-args-related - # failure. + if gdbgui_version >= (0, 14, 0, 0): + # See breaking changes https://github.com/cs01/gdbgui/blob/master/CHANGELOG.md#01400, especially the + # replacement of command line arguments. gdb_args = ' '.join(gdb_args_list) args = ['gdbgui', '-g', ' '.join((gdb, gdb_args))] else: @@ -446,12 +465,7 @@ def action_extensions(base_actions: Dict, project_path: str) -> Dict: process = subprocess.Popen(args, stdout=gdbgui_out, stderr=subprocess.STDOUT, bufsize=1, env=env) except (OSError, subprocess.CalledProcessError) as e: print(e) - if sys.version_info[:2] >= (3, 11) and sys.platform == 'win32': - raise SystemExit('Unfortunately, gdbgui is supported only with Python 3.10 or older. ' - 'See: https://github.com/espressif/esp-idf/issues/10116. ' - 'Please use "idf.py gdb" or debug in Eclipse/Vscode instead.') - raise FatalError('Error starting gdbgui. Please make sure gdbgui has been installed with ' - '"install.{sh,bat,ps1,fish} --enable-gdbgui" and can be started.', ctx) + raise FatalError('Error starting gdbgui', ctx) processes['gdbgui'] = process processes['gdbgui_outfile'] = gdbgui_out @@ -529,9 +543,9 @@ def action_extensions(base_actions: Dict, project_path: str) -> Dict: ctx: Context, args: PropertyDict, gdb_timeout_sec: int, - core: str = None, - chip_rev: str = None, - save_core: str = None) -> None: + core: Optional[str] = None, + chip_rev: Optional[str] = None, + save_core: Optional[str] = None) -> None: espcoredump = _get_espcoredump_instance(ctx=ctx, args=args, gdb_timeout_sec=gdb_timeout_sec, core=core, chip_rev=chip_rev, save_core=save_core) @@ -541,9 +555,9 @@ def action_extensions(base_actions: Dict, project_path: str) -> Dict: def coredump_debug(action: str, ctx: Context, args: PropertyDict, - core: str = None, - chip_rev: str = None, - save_core: str = None) -> None: + core: Optional[str] = None, + chip_rev: Optional[str] = None, + save_core: Optional[str] = None) -> None: espcoredump = _get_espcoredump_instance(ctx=ctx, args=args, core=core, chip_rev=chip_rev, save_core=save_core) espcoredump.dbg_corefile()