forked from platformio/platformio-core
The Unified Debugger
This commit is contained in:
@ -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())
|
||||
|
@ -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,
|
||||
|
@ -1,115 +0,0 @@
|
||||
# Copyright 2014-present PlatformIO <contact@platformio.org>
|
||||
#
|
||||
# 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
|
@ -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()
|
||||
|
@ -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 = "+<output_export.cpp>"
|
||||
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
|
||||
|
@ -1,48 +0,0 @@
|
||||
# Copyright 2014-present PlatformIO <contact@platformio.org>
|
||||
#
|
||||
# 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 = "+<output_export.cpp>"
|
||||
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
|
@ -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="<environment>")
|
||||
@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:])
|
||||
|
@ -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
|
||||
|
@ -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):
|
||||
|
@ -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"
|
||||
}
|
||||
|
@ -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}
|
||||
|
Reference in New Issue
Block a user