From 887d46725b637b4212e08d19c921a0aefc71f96a Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Fri, 19 Mar 2021 17:02:11 +0200 Subject: [PATCH] Debug native (desktop) application on a host machine // Resolve #980 --- HISTORY.rst | 1 + platformio/commands/debug.py | 2 +- platformio/debug/config/base.py | 21 +++++++++++++------- platformio/debug/config/factory.py | 13 +++++++++--- platformio/debug/config/native.py | 32 ++++++++++++++++++++++++++++++ platformio/debug/process/gdb.py | 16 ++++++++++----- 6 files changed, 69 insertions(+), 16 deletions(-) create mode 100644 platformio/debug/config/native.py diff --git a/HISTORY.rst b/HISTORY.rst index 141fba3e..e626c5ca 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -14,6 +14,7 @@ PlatformIO Core 5 * **PlatformIO Debugging** - Boosted `PlatformIO Debugging `__ performance thanks to migrating the codebase to the pure Python 3 Asynchronous I/O stack + - Debug native (desktop) application on a host machine (`issue #980 `_) - Support debugging on Windows using Windows CMD/CLI (`pio debug `__) (`issue #3793 `_) - Configure a custom pattern to determine when debugging server is started with a new `debug_server_ready_pattern `__ option - Fixed an issue with silent hanging when a custom debug server is not found (`issue #3756 `_) diff --git a/platformio/commands/debug.py b/platformio/commands/debug.py index 3f468de9..c30fdc09 100644 --- a/platformio/commands/debug.py +++ b/platformio/commands/debug.py @@ -79,7 +79,7 @@ def cli(ctx, project_dir, project_conf, environment, verbose, interface, __unpro return helpers.predebug_project(ctx, project_dir, env_name, False, verbose) env_options = project_config.items(env=env_name, as_dict=True) - if not set(env_options.keys()) >= set(["platform", "board"]): + if "platform" not in env_options: raise ProjectEnvsNotAvailableError() try: diff --git a/platformio/debug/config/base.py b/platformio/debug/config/base.py index 8a8e5247..53abadc9 100644 --- a/platformio/debug/config/base.py +++ b/platformio/debug/config/base.py @@ -29,14 +29,21 @@ class DebugConfigBase: # pylint: disable=too-many-instance-attributes self.project_config = project_config self.env_name = env_name self.env_options = project_config.items(env=env_name, as_dict=True) - self.board_config = platform.board_config(self.env_options["board"]) self.build_data = self._load_build_data() - self.tool_name = self.board_config.get_debug_tool_name( - self.env_options.get("debug_tool") - ) - self.tool_settings = ( - self.board_config.get("debug", {}).get("tools", {}).get(self.tool_name, {}) - ) + + self.tool_name = None + self.board_config = {} + self.tool_settings = {} + if "board" in self.env_options: + self.board_config = platform.board_config(self.env_options["board"]) + self.tool_name = self.board_config.get_debug_tool_name( + self.env_options.get("debug_tool") + ) + self.tool_settings = ( + self.board_config.get("debug", {}) + .get("tools", {}) + .get(self.tool_name, {}) + ) self._load_cmds = None self._port = None diff --git a/platformio/debug/config/factory.py b/platformio/debug/config/factory.py index 87019dfa..d74dad38 100644 --- a/platformio/debug/config/factory.py +++ b/platformio/debug/config/factory.py @@ -16,6 +16,7 @@ import importlib import re from platformio.debug.config.generic import GenericDebugConfig +from platformio.debug.config.native import NativeDebugConfig class DebugConfigFactory(object): @@ -29,13 +30,19 @@ class DebugConfigFactory(object): board_config = platform.board_config( project_config.get("env:" + env_name, "board") ) - tool_name = board_config.get_debug_tool_name( - project_config.get("env:" + env_name, "debug_tool") + tool_name = ( + board_config.get_debug_tool_name( + project_config.get("env:" + env_name, "debug_tool") + ) + if board_config + else None ) config_cls = None try: mod = importlib.import_module("platformio.debug.config.%s" % tool_name) config_cls = getattr(mod, cls.get_clsname(tool_name)) except ModuleNotFoundError: - config_cls = GenericDebugConfig + config_cls = ( + GenericDebugConfig if platform.is_embedded() else NativeDebugConfig + ) return config_cls(platform, project_config, env_name) diff --git a/platformio/debug/config/native.py b/platformio/debug/config/native.py new file mode 100644 index 00000000..c406fd59 --- /dev/null +++ b/platformio/debug/config/native.py @@ -0,0 +1,32 @@ +# Copyright (c) 2014-present PlatformIO +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from platformio.debug.config.base import DebugConfigBase + + +class NativeDebugConfig(DebugConfigBase): + + GDB_INIT_SCRIPT = """ +define pio_reset_halt_target +end + +define pio_reset_run_target +end + +define pio_restart_target +end + +$INIT_BREAK +set startup-with-shell off +""" diff --git a/platformio/debug/process/gdb.py b/platformio/debug/process/gdb.py index 6e7e2d40..836c637f 100644 --- a/platformio/debug/process/gdb.py +++ b/platformio/debug/process/gdb.py @@ -37,7 +37,7 @@ class GDBClientProcess(DebugClientProcess): await super(GDBClientProcess, self).run() self.generate_init_script(os.path.join(self.working_dir, self.PIO_SRC_NAME)) - gdb_path = self.debug_config.client_executable_path + gdb_path = self.debug_config.client_executable_path or "gdb" # start GDB client args = [ gdb_path, @@ -115,7 +115,8 @@ class GDBClientProcess(DebugClientProcess): token, _ = data.split(b"-", 1) self.stdout_data_received(token + b"^running\n") return - data = data.replace(b"-exec-run", b"-exec-continue") + if self.debug_config.platform.is_embedded(): + data = data.replace(b"-exec-run", b"-exec-continue") if b"-exec-continue" in data: self._target_is_running = True @@ -158,9 +159,14 @@ class GDBClientProcess(DebugClientProcess): self.console_log( "PlatformIO: More configuration options -> http://bit.ly/pio-debug\n" ) - self.transport.get_pipe_transport(0).write( - b"0-exec-continue\n" if helpers.is_gdbmi_mode() else b"continue\n" - ) + if self.debug_config.platform.is_embedded(): + self.transport.get_pipe_transport(0).write( + b"0-exec-continue\n" if helpers.is_gdbmi_mode() else b"continue\n" + ) + else: + self.transport.get_pipe_transport(0).write( + b"0-exec-run\n" if helpers.is_gdbmi_mode() else b"run\n" + ) self._target_is_running = True def stderr_data_received(self, data):