From 9658bcdb73535d928d342815226a1cc948a2e356 Mon Sep 17 00:00:00 2001 From: Ivan Kravets Date: Fri, 28 Apr 2017 01:38:25 +0300 Subject: [PATCH] The Unified Debugger --- platformio/__main__.py | 15 ++-- platformio/builder/main.py | 10 +-- platformio/builder/tools/piodebug.py | 115 --------------------------- platformio/builder/tools/pioide.py | 54 +------------ platformio/builder/tools/piomisc.py | 33 +++++++- platformio/builder/tools/piotest.py | 48 ----------- platformio/commands/debug.py | 9 ++- platformio/commands/run.py | 23 +++--- platformio/maintenance.py | 7 +- platformio/managers/core.py | 2 +- platformio/managers/platform.py | 12 +++ setup.py | 1 + 12 files changed, 87 insertions(+), 242 deletions(-) delete mode 100644 platformio/builder/tools/piodebug.py delete mode 100644 platformio/builder/tools/piotest.py diff --git a/platformio/__main__.py b/platformio/__main__.py index 3dd83244..da14d0dc 100644 --- a/platformio/__main__.py +++ b/platformio/__main__.py @@ -12,10 +12,10 @@ # See the License for the specific language governing permissions and # limitations under the License. -from os import getenv, listdir +import os +import sys from os.path import join from platform import system -from sys import exit as sys_exit from traceback import format_exc import click @@ -29,7 +29,7 @@ class PlatformioCLI(click.MultiCommand): # pylint: disable=R0904 def list_commands(self, ctx): cmds = [] - for filename in listdir(join(get_source_dir(), "commands")): + for filename in os.listdir(join(get_source_dir(), "commands")): if filename.startswith("__init__"): continue if filename.endswith(".py"): @@ -96,7 +96,7 @@ def main(): "< https://github.com/platformio/platformio-core/issues/252 >") # handle PLATFORMIO_FORCE_COLOR - if str(getenv("PLATFORMIO_FORCE_COLOR", "")).lower() == "true": + if str(os.getenv("PLATFORMIO_FORCE_COLOR", "")).lower() == "true": try: # pylint: disable=protected-access click._compat.isatty = lambda stream: True @@ -133,5 +133,10 @@ An unexpected error occurred. Further steps: return 0 +def debug_gdb_main(): + sys.argv = [sys.argv[0], "debug", "--interface", "gdb"] + sys.argv[1:] + return main() + + if __name__ == "__main__": - sys_exit(main()) + sys.exit(main()) diff --git a/platformio/builder/main.py b/platformio/builder/main.py index f6d32c4b..83eb6029 100644 --- a/platformio/builder/main.py +++ b/platformio/builder/main.py @@ -62,20 +62,14 @@ commonvars.AddVariables( ("UPLOAD_PROTOCOL",), ("UPLOAD_SPEED",), ("UPLOAD_FLAGS",), - ("UPLOAD_RESETMETHOD",), - - # debug options - ("DEBUG_TOOL",), - ("DEBUG_PORT",), - ("DEBUG_GDBINIT",) + ("UPLOAD_RESETMETHOD",) ) # yapf: disable DEFAULT_ENV_OPTIONS = dict( tools=[ "ar", "as", "gcc", "g++", "gnulink", "platformio", "pioplatform", - "piowinhooks", "piolib", "piotest", "pioupload", "piomisc", "pioide", - "piodebug" + "piowinhooks", "piolib", "pioupload", "piomisc", "pioide" ], # yapf: disable toolpath=[join(util.get_source_dir(), "builder", "tools")], variables=commonvars, diff --git a/platformio/builder/tools/piodebug.py b/platformio/builder/tools/piodebug.py deleted file mode 100644 index 4f841c26..00000000 --- a/platformio/builder/tools/piodebug.py +++ /dev/null @@ -1,115 +0,0 @@ -# Copyright 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 __future__ import absolute_import - -import sys -from fnmatch import fnmatch -from os.path import isfile -from platform import system - -from platformio import util - - -def ProcessDebug(env): - env.Append( - BUILD_FLAGS=["-Og", "-ggdb"], - BUILD_UNFLAGS=["-Os", "-O0", "-O1", "-O2", "-O3"]) - - -def DebugToolSettings(env): - if "BOARD" not in env: - return - board_debug = env.BoardConfig().get("debug", {}) - if not board_debug or not board_debug.get("tools"): - return - debug_tools = board_debug.get("tools") - tool_name = (env.subst("$DEBUG_TOOL") or - board_debug.get("default_tool", debug_tools.keys()[0])) - settings = debug_tools.get(tool_name) - if not settings: - return - settings.update({"name": tool_name}) - return settings - - -def AutodetectDebugPort(env): - - def _get_pattern(): - if "DEBUG_PORT" not in env: - return None - if set(["*", "?", "[", "]"]) & set(env['DEBUG_PORT']): - return env['DEBUG_PORT'] - return None - - def _is_match_pattern(port): - pattern = _get_pattern() - if not pattern: - return True - return fnmatch(port, pattern) - - def _look_for_serial_port(hwids): - for item in util.get_serialports(filter_hwid=True): - if not _is_match_pattern(item['port']): - continue - if "GDB" in item['port']: - return item['port'] - for hwid in hwids: - hwid_str = ("%s:%s" % (hwid[0], hwid[1])).replace("0x", "") - if hwid_str in item['hwid']: - return item['port'] - return None - - if "BOARD" not in env or ("DEBUG_PORT" in env and not _get_pattern()): - return - - tool_settings = env.DebugToolSettings() - if not tool_settings: - return - if not tool_settings.get("require_debug_port"): - return - - need_openocd_rules = [ - system() == "Linux", - "openocd" in tool_settings.get("server", {}).get("package", ""), - not any([ - isfile("/etc/udev/rules.d/98-openocd-udev.rules"), - isfile("/lib/udev/rules.d/98-openocd-udev.rules") - ]) - ] - if all(need_openocd_rules): - sys.stderr.write( - "\nWarning! Please install `98-openocd-udev.rules` and check " - "that your debug adapter's PID and VID are listed in the rules." - "\n https://raw.githubusercontent.com/platformio/platformio" - "/develop/scripts/98-openocd-udev.rules\n") - - env.Replace( - DEBUG_PORT=_look_for_serial_port(tool_settings.get("hwids", []))) - - if not env.subst("$DEBUG_PORT"): - sys.stderr.write( - "Error: Please specify `debug_port` for environment.\n") - env.Exit(1) - - -def exists(_): - return True - - -def generate(env): - env.AddMethod(ProcessDebug) - env.AddMethod(DebugToolSettings) - env.AddMethod(AutodetectDebugPort) - return env diff --git a/platformio/builder/tools/pioide.py b/platformio/builder/tools/pioide.py index 4b4e7fdd..11a57474 100644 --- a/platformio/builder/tools/pioide.py +++ b/platformio/builder/tools/pioide.py @@ -15,7 +15,7 @@ from __future__ import absolute_import from glob import glob -from os.path import join, sep +from os.path import join from SCons.Defaults import processDefines @@ -67,54 +67,6 @@ def dump_defines(env): return defines -def dump_debug(env): - - def _fix_path_sep(path): - result = [] - items = path if isinstance(path, list) else [path] - for item in items: - result.append(item.replace("/", sep).replace("\\", sep)) - return result if isinstance(path, list) else result[0] - - def _dump_server(configuration): - if not configuration: - return - if not set(configuration.keys()) >= set(["package", "executable"]): - return - pkg_dir = env.PioPlatform().get_package_dir(configuration['package']) - if not pkg_dir: - return - return { - "cwd": pkg_dir, - "executable": _fix_path_sep(configuration['executable']), - "arguments": _fix_path_sep(configuration.get("arguments")) - } - - gdbinit = None - if "DEBUG_GDBINIT" in env: - if isinstance(env['DEBUG_GDBINIT'], list): - gdbinit = env['DEBUG_GDBINIT'] - else: - gdbinit = [env['DEBUG_GDBINIT']] - - tool_settings = env.DebugToolSettings() - if tool_settings and not gdbinit: - gdbinit = tool_settings.get("gdbinit") - - env.AutodetectDebugPort() - - return { - "gdb_path": util.where_is_program( - env.subst("$GDB"), env.subst("${ENV['PATH']}")), - "prog_path": env.subst("$PROG_PATH"), - "tool": tool_settings['name'] if tool_settings else None, - "gdbinit": [env.subst(cmd) for cmd in gdbinit] if gdbinit else None, - "port": env.subst("$DEBUG_PORT"), - "server": (_dump_server(tool_settings['server']) - if tool_settings and "server" in tool_settings else None) - } - - def DumpIDEData(env): LINTCCOM = "$CFLAGS $CCFLAGS $CPPFLAGS $_CPPDEFFLAGS" LINTCXXCOM = "$CXXFLAGS $CCFLAGS $CPPFLAGS $_CPPDEFFLAGS" @@ -124,13 +76,15 @@ def DumpIDEData(env): [env.subst(l) for l in env.get("LIBSOURCE_DIRS", [])], "defines": dump_defines(env), "includes": dump_includes(env), - "debug": dump_debug(env), "cc_flags": env.subst(LINTCCOM), "cxx_flags": env.subst(LINTCXXCOM), "cc_path": util.where_is_program( env.subst("$CC"), env.subst("${ENV['PATH']}")), "cxx_path": util.where_is_program( env.subst("$CXX"), env.subst("${ENV['PATH']}")), + "gdb_path": util.where_is_program( + env.subst("$GDB"), env.subst("${ENV['PATH']}")), + "prog_path": env.subst("$PROG_PATH") } env_ = env.Clone() diff --git a/platformio/builder/tools/piomisc.py b/platformio/builder/tools/piomisc.py index ba6f496e..8fef5006 100644 --- a/platformio/builder/tools/piomisc.py +++ b/platformio/builder/tools/piomisc.py @@ -18,13 +18,14 @@ import atexit import re import sys from os import environ, remove, walk -from os.path import basename, isdir, isfile, join, relpath +from os.path import basename, isdir, isfile, join, relpath, sep from tempfile import mkstemp from SCons.Action import Action from SCons.Script import ARGUMENTS from platformio import util +from platformio.managers.core import get_core_package_dir class InoToCPPConverter(object): @@ -268,6 +269,34 @@ def PioClean(env, clean_dir): env.Exit(0) +def ProcessDebug(env): + if not env.subst("$PIODEBUGFLAGS"): + env.Replace(PIODEBUGFLAGS=["-Og", "-g3", "-ggdb"]) + env.Append( + BUILD_FLAGS=env.get("PIODEBUGFLAGS", []), + BUILD_UNFLAGS=["-Os", "-O0", "-O1", "-O2", "-O3"]) + + +def ProcessTest(env): + env.Append( + CPPDEFINES=["UNIT_TEST", "UNITY_INCLUDE_CONFIG_H"], + CPPPATH=[join("$BUILD_DIR", "UnityTestLib")]) + unitylib = env.BuildLibrary( + join("$BUILD_DIR", "UnityTestLib"), get_core_package_dir("tool-unity")) + env.Prepend(LIBS=[unitylib]) + + src_filter = None + if "PIOTEST" in env: + src_filter = "+" + src_filter += " +<%s%s>" % (env['PIOTEST'], sep) + + return env.CollectBuildFiles( + "$BUILDTEST_DIR", + "$PROJECTTEST_DIR", + src_filter=src_filter, + duplicate=False) + + def exists(_): return True @@ -278,4 +307,6 @@ def generate(env): env.AddMethod(GetActualLDScript) env.AddMethod(VerboseAction) env.AddMethod(PioClean) + env.AddMethod(ProcessDebug) + env.AddMethod(ProcessTest) return env diff --git a/platformio/builder/tools/piotest.py b/platformio/builder/tools/piotest.py deleted file mode 100644 index 04035e9c..00000000 --- a/platformio/builder/tools/piotest.py +++ /dev/null @@ -1,48 +0,0 @@ -# Copyright 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 __future__ import absolute_import - -from os.path import join, sep - -from platformio.managers.core import get_core_package_dir - - -def ProcessTest(env): - env.Append( - CPPDEFINES=["UNIT_TEST", "UNITY_INCLUDE_CONFIG_H"], - CPPPATH=[join("$BUILD_DIR", "UnityTestLib")]) - unitylib = env.BuildLibrary( - join("$BUILD_DIR", "UnityTestLib"), get_core_package_dir("tool-unity")) - env.Prepend(LIBS=[unitylib]) - - src_filter = None - if "PIOTEST" in env: - src_filter = "+" - src_filter += " +<%s%s>" % (env['PIOTEST'], sep) - - return env.CollectBuildFiles( - "$BUILDTEST_DIR", - "$PROJECTTEST_DIR", - src_filter=src_filter, - duplicate=False) - - -def exists(_): - return True - - -def generate(env): - env.AddMethod(ProcessTest) - return env diff --git a/platformio/commands/debug.py b/platformio/commands/debug.py index 24acae6c..7ea97940 100644 --- a/platformio/commands/debug.py +++ b/platformio/commands/debug.py @@ -20,7 +20,10 @@ import click from platformio.managers.core import pioplus_call -@click.command("debug", short_help="Project Debugger") +@click.command( + "debug", + context_settings=dict(ignore_unknown_options=True), + short_help="The Unified Debugger") @click.option( "-d", "--project-dir", @@ -32,8 +35,8 @@ from platformio.managers.core import pioplus_call writable=True, resolve_path=True)) @click.option("--environment", "-e", metavar="") -@click.option("--configuration", is_flag=True) -@click.option("--json-output", is_flag=True) @click.option("--verbose", "-v", is_flag=True) +@click.option("--interface", type=click.Choice(["gdb"])) +@click.argument("__unprocessed", nargs=-1, type=click.UNPROCESSED) def cli(*args, **kwargs): # pylint: disable=unused-argument pioplus_call(sys.argv[1:]) diff --git a/platformio/commands/run.py b/platformio/commands/run.py index 8c6e42ca..e723b085 100644 --- a/platformio/commands/run.py +++ b/platformio/commands/run.py @@ -122,15 +122,18 @@ def cli(ctx, environment, target, upload_port, project_dir, silent, verbose, class EnvironmentProcessor(object): - KNOWN_OPTIONS = ( - "platform", "framework", "board", "board_mcu", "board_f_cpu", - "board_f_flash", "board_flash_mode", "build_flags", "src_build_flags", - "build_unflags", "src_filter", "extra_script", "targets", - "upload_port", "upload_protocol", "upload_speed", "upload_flags", - "upload_resetmethod", "lib_install", "lib_deps", "lib_force", - "lib_ignore", "lib_extra_dirs", "lib_ldf_mode", "lib_compat_mode", - "test_ignore", "test_port", "piotest", "debug_tool", "debug_port", - "debug_gdbinit") + KNOWN_OPTIONS = ("platform", "framework", "board", "board_mcu", + "board_f_cpu", "board_f_flash", "board_flash_mode", + "build_flags", "src_build_flags", "build_unflags", + "src_filter", "extra_script", "targets", "upload_port", + "upload_protocol", "upload_speed", "upload_flags", + "upload_resetmethod", "lib_deps", "lib_ignore", + "lib_extra_dirs", "lib_ldf_mode", "lib_compat_mode", + "piotest", "test_ignore", "test_port", "debug_tool", + "debug_port", "debug_init_cmds", "debug_extra_cmds") + + IGNORE_BUILD_OPTIONS = ("debug_tool", "debug_port", "debug_init_cmds", + "debug_extra_cmds") REMAPED_OPTIONS = {"framework": "pioframework", "platform": "pioplatform"} @@ -224,6 +227,8 @@ class EnvironmentProcessor(object): for k, v in self.options.items(): if k in self.REMAPED_OPTIONS: k = self.REMAPED_OPTIONS[k] + if k in self.IGNORE_BUILD_OPTIONS: + continue if k == "targets" or (k == "upload_port" and self.upload_port): continue variables[k] = v diff --git a/platformio/maintenance.py b/platformio/maintenance.py index df811972..360bc960 100644 --- a/platformio/maintenance.py +++ b/platformio/maintenance.py @@ -38,8 +38,11 @@ def in_silence(ctx=None): ctx = ctx or app.get_session_var("command_ctx") assert ctx ctx_args = ctx.args or [] - return (ctx_args and - (ctx.args[0] == "upgrade" or "--json-output" in ctx_args)) + conditions = [ + ctx.args[0] == "upgrade", "--json-output" in ctx_args, + "--version" in ctx_args + ] + return ctx_args and any(conditions) def on_platformio_start(ctx, force, caller): diff --git a/platformio/managers/core.py b/platformio/managers/core.py index c0620855..23c67bb4 100644 --- a/platformio/managers/core.py +++ b/platformio/managers/core.py @@ -22,7 +22,7 @@ from platformio.managers.package import PackageManager CORE_PACKAGES = { "pysite-pioplus": ">=0.3.0,<2", - "tool-pioplus": ">=0.7.3,<2", + "tool-pioplus": ">=0.8.1,<2", "tool-unity": "~1.20302.1", "tool-scons": "~3.20501.2" } diff --git a/platformio/managers/platform.py b/platformio/managers/platform.py index ccd89b15..ad2800de 100644 --- a/platformio/managers/platform.py +++ b/platformio/managers/platform.py @@ -643,6 +643,18 @@ class PlatformBoardConfig(object): "ram": self._manifest.get("upload", {}).get("maximum_ram_size", 0), "rom": self._manifest.get("upload", {}).get("maximum_size", 0), "frameworks": self._manifest.get("frameworks"), + "debug": self.get_debug_data(), "vendor": self._manifest['vendor'], "url": self._manifest['url'] } + + def get_debug_data(self): + if not self._manifest.get("debug", {}).get("tools"): + return + tools = {} + for name, options in self._manifest['debug']['tools'].items(): + tools[name] = {} + for key, value in options.items(): + if key in ("default", "onboard"): + tools[name][key] = value + return {"tools": tools} diff --git a/setup.py b/setup.py index ae4ad614..d7ed7447 100644 --- a/setup.py +++ b/setup.py @@ -51,6 +51,7 @@ setup( entry_points={ "console_scripts": [ "pio = platformio.__main__:main", + "piodebuggdb = platformio.__main__:debug_gdb_main", "platformio = platformio.__main__:main" ] },