Refactor appending of debugging flags

This commit is contained in:
Ivan Kravets
2019-09-27 17:22:21 +03:00
parent cd2a4ea535
commit 1b74f380a6
6 changed files with 99 additions and 90 deletions

View File

@@ -1,3 +1,3 @@
[settings] [settings]
line_length=88 line_length=88
known_third_party=bottle,click,pytest,requests,SCons,semantic_version,serial,twisted,autobahn,jsonrpc,tabulate known_third_party=SCons, twisted, autobahn, jsonrpc

View File

@@ -194,10 +194,9 @@ if "idedata" in COMMAND_LINE_TARGETS:
if "sizedata" in COMMAND_LINE_TARGETS: if "sizedata" in COMMAND_LINE_TARGETS:
AlwaysBuild( AlwaysBuild(
env.Alias( env.Alias(
"sizedata", DEFAULT_TARGETS, "sizedata",
env.VerboseAction( DEFAULT_TARGETS,
env.DumpSizeData, "Generating memory usage report...", env.VerboseAction(env.DumpSizeData, "Generating memory usage report..."),
)
) )
) )

View File

@@ -23,6 +23,7 @@ from tempfile import mkstemp
from SCons.Action import Action # pylint: disable=import-error from SCons.Action import Action # pylint: disable=import-error
from SCons.Script import ARGUMENTS # pylint: disable=import-error from SCons.Script import ARGUMENTS # pylint: disable=import-error
from SCons.Script import COMMAND_LINE_TARGETS # pylint: disable=import-error
from platformio import fs, util from platformio import fs, util
from platformio.compat import get_file_contents, glob_escape from platformio.compat import get_file_contents, glob_escape
@@ -294,32 +295,37 @@ def VerboseAction(_, act, actstr):
def PioClean(env, clean_dir): def PioClean(env, clean_dir):
if not isdir(clean_dir): if not isdir(clean_dir):
print ("Build environment is clean") print("Build environment is clean")
env.Exit(0) env.Exit(0)
clean_rel_path = relpath(clean_dir) clean_rel_path = relpath(clean_dir)
for root, _, files in walk(clean_dir): for root, _, files in walk(clean_dir):
for f in files: for f in files:
dst = join(root, f) dst = join(root, f)
remove(dst) remove(dst)
print ( print(
"Removed %s" % (dst if clean_rel_path.startswith(".") else relpath(dst)) "Removed %s" % (dst if clean_rel_path.startswith(".") else relpath(dst))
) )
print ("Done cleaning") print("Done cleaning")
fs.rmtree(clean_dir) fs.rmtree(clean_dir)
env.Exit(0) env.Exit(0)
def ConfigureDebugTarget(env): def ConfigureDebugFlags(env):
if not env.subst("$PIODEBUGFLAGS"): def _cleanup_debug_flags(scope):
env.Replace(PIODEBUGFLAGS=["-Og", "-g3", "-ggdb3"]) if scope not in env:
env.Append( return
BUILD_FLAGS=list(env["PIODEBUGFLAGS"]) + ["-D__PLATFORMIO_BUILD_DEBUG__"] unflags = ["-Os", "-g"]
) for level in [0, 1, 2]:
unflags = ["-Os"] for flag in ("O", "g", "ggdb"):
for level in [0, 1, 2]: unflags.append("-%s%d" % (flag, level))
for flag in ("O", "g", "ggdb"): env[scope] = [f for f in env.get(scope, []) if f not in unflags]
unflags.append("-%s%d" % (flag, level))
env.Append(BUILD_UNFLAGS=unflags) env.Append(CPPDEFINES=["__PLATFORMIO_BUILD_DEBUG__"])
debug_flags = ["-Og", "-g3", "-ggdb3"]
for scope in ("ASFLAGS", "CCFLAGS", "LINKFLAGS"):
_cleanup_debug_flags(scope)
env.Append(**{scope: debug_flags})
def ConfigureTestTarget(env): def ConfigureTestTarget(env):
@@ -361,7 +367,7 @@ def generate(env):
env.AddMethod(GetActualLDScript) env.AddMethod(GetActualLDScript)
env.AddMethod(VerboseAction) env.AddMethod(VerboseAction)
env.AddMethod(PioClean) env.AddMethod(PioClean)
env.AddMethod(ConfigureDebugTarget) env.AddMethod(ConfigureDebugFlags)
env.AddMethod(ConfigureTestTarget) env.AddMethod(ConfigureTestTarget)
env.AddMethod(GetExtraScripts) env.AddMethod(GetExtraScripts)
return env return env

View File

@@ -24,16 +24,14 @@ from platformio.proc import exec_command
def _get_file_location(env, elf_path, addr, sysenv): def _get_file_location(env, elf_path, addr, sysenv):
cmd = [env.subst("$CC").replace( cmd = [env.subst("$CC").replace("-gcc", "-addr2line"), "-e", elf_path, hex(addr)]
"-gcc", "-addr2line"), "-e", elf_path, hex(addr)]
result = exec_command(cmd, env=sysenv) result = exec_command(cmd, env=sysenv)
return result['out'].strip().replace("\\", "/") return result["out"].strip().replace("\\", "/")
def _determine_section(sections, symbol_addr): def _determine_section(sections, symbol_addr):
for section, info in sections.items(): for section, info in sections.items():
if symbol_addr in range(info['start_addr'], if symbol_addr in range(info["start_addr"], info["start_addr"] + info["size"]):
info['start_addr'] + info['size']):
return section return section
return "unknown" return "unknown"
@@ -41,20 +39,21 @@ def _determine_section(sections, symbol_addr):
def _demangle_cpp_name(env, symbol_name, sysenv): def _demangle_cpp_name(env, symbol_name, sysenv):
cmd = [env.subst("$CC").replace("-gcc", "-c++filt"), symbol_name] cmd = [env.subst("$CC").replace("-gcc", "-c++filt"), symbol_name]
result = exec_command(cmd, env=sysenv) result = exec_command(cmd, env=sysenv)
demangled_name = result['out'].strip() demangled_name = result["out"].strip()
if "(" in demangled_name: if "(" in demangled_name:
demangled_name = demangled_name[0:demangled_name.find("(")] demangled_name = demangled_name[0 : demangled_name.find("(")]
return demangled_name return demangled_name
def _is_ram_section(section): def _is_ram_section(section):
return section.get("type", "") in ( return (
"SHT_NOBITS", "SHT_PROGBITS") and section.get("flags", "") == "WA" section.get("type", "") in ("SHT_NOBITS", "SHT_PROGBITS")
and section.get("flags", "") == "WA"
)
def _is_flash_section(section): def _is_flash_section(section):
return section.get("type") == "SHT_PROGBITS" and "A" in section.get( return section.get("type") == "SHT_PROGBITS" and "A" in section.get("flags")
"flags")
def _is_valid_symbol(symbol_name, symbol_type, symbol_address): def _is_valid_symbol(symbol_name, symbol_type, symbol_address):
@@ -67,15 +66,15 @@ def _collect_sections_info(elffile):
if section.is_null(): if section.is_null():
continue continue
section_type = section['sh_type'] section_type = section["sh_type"]
section_flags = describe_sh_flags(section['sh_flags']) section_flags = describe_sh_flags(section["sh_flags"])
section_size = section.data_size section_size = section.data_size
sections[section.name] = { sections[section.name] = {
"size": section_size, "size": section_size,
"start_addr": section['sh_addr'], "start_addr": section["sh_addr"],
"type": section_type, "type": section_type,
"flags": section_flags "flags": section_flags,
} }
return sections return sections
@@ -84,7 +83,7 @@ def _collect_sections_info(elffile):
def _collect_symbols_info(env, elffile, elf_path, sections): def _collect_symbols_info(env, elffile, elf_path, sections):
symbols = [] symbols = []
symbol_section = elffile.get_section_by_name('.symtab') symbol_section = elffile.get_section_by_name(".symtab")
if symbol_section.is_null(): if symbol_section.is_null():
sys.stderr.write("Couldn't find symbol table. Is ELF file stripped?") sys.stderr.write("Couldn't find symbol table. Is ELF file stripped?")
env.Exit(1) env.Exit(1)
@@ -93,26 +92,26 @@ def _collect_symbols_info(env, elffile, elf_path, sections):
sysenv["PATH"] = str(env["ENV"]["PATH"]) sysenv["PATH"] = str(env["ENV"]["PATH"])
for s in symbol_section.iter_symbols(): for s in symbol_section.iter_symbols():
symbol_info = s.entry['st_info'] symbol_info = s.entry["st_info"]
symbol_addr = s['st_value'] symbol_addr = s["st_value"]
symbol_size = s['st_size'] symbol_size = s["st_size"]
symbol_type = symbol_info['type'] symbol_type = symbol_info["type"]
if not _is_valid_symbol(s.name, symbol_type, symbol_addr): if not _is_valid_symbol(s.name, symbol_type, symbol_addr):
continue continue
symbol = { symbol = {
"addr": symbol_addr, "addr": symbol_addr,
"bind": symbol_info['bind'], "bind": symbol_info["bind"],
"location": _get_file_location(env, elf_path, symbol_addr, sysenv), "location": _get_file_location(env, elf_path, symbol_addr, sysenv),
"name": s.name, "name": s.name,
"type": symbol_type, "type": symbol_type,
"size": symbol_size, "size": symbol_size,
"section": _determine_section(sections, symbol_addr) "section": _determine_section(sections, symbol_addr),
} }
if s.name.startswith("_Z"): if s.name.startswith("_Z"):
symbol['demangled_name'] = _demangle_cpp_name(env, s.name, sysenv) symbol["demangled_name"] = _demangle_cpp_name(env, s.name, sysenv)
symbols.append(symbol) symbols.append(symbol)
@@ -130,11 +129,8 @@ def _calculate_firmware_size(sections):
return ram_size, flash_size return ram_size, flash_size
def DumpSizeData(_, target, source, env): def DumpSizeData(_, target, source, env): # pylint: disable=unused-argument
data = { data = {"memory": {}, "version": 1}
"memory": {},
"version": 1
}
elf_path = env.subst("$PIOMAINPROG") elf_path = env.subst("$PIOMAINPROG")
@@ -147,10 +143,10 @@ def DumpSizeData(_, target, source, env):
sections = _collect_sections_info(elffile) sections = _collect_sections_info(elffile)
firmware_ram, firmware_flash = _calculate_firmware_size(sections) firmware_ram, firmware_flash = _calculate_firmware_size(sections)
data['memory']['total'] = { data["memory"]["total"] = {
"ram_size": firmware_ram, "ram_size": firmware_ram,
"flash_size": firmware_flash, "flash_size": firmware_flash,
"sections": sections "sections": sections,
} }
files = dict() files = dict()
@@ -160,38 +156,27 @@ def DumpSizeData(_, target, source, env):
file_path = "unknown" file_path = "unknown"
if not files.get(file_path, {}): if not files.get(file_path, {}):
files[file_path] = { files[file_path] = {"symbols": [], "ram_size": 0, "flash_size": 0}
"symbols": [],
"ram_size": 0,
"flash_size": 0
}
symbol_size = symbol.get("size", 0) symbol_size = symbol.get("size", 0)
section = sections.get(symbol.get("section", ""), {}) section = sections.get(symbol.get("section", ""), {})
if _is_ram_section(section): if _is_ram_section(section):
files[file_path]['ram_size'] += symbol_size files[file_path]["ram_size"] += symbol_size
if _is_flash_section(section): if _is_flash_section(section):
files[file_path]['flash_size'] += symbol_size files[file_path]["flash_size"] += symbol_size
files[file_path]['symbols'].append(symbol) files[file_path]["symbols"].append(symbol)
data['memory']['files'] = files data["memory"]["files"] = files
with open(join(env.subst("$BUILD_DIR"), "sizedata.json"), "w") as fp: with open(join(env.subst("$BUILD_DIR"), "sizedata.json"), "w") as fp:
fp.write(dump_json_to_unicode(data)) fp.write(dump_json_to_unicode(data))
def ConfigureSizeDataTarget(env):
for flags_section in ("ASFLAGS", "CCFLAGS", "LINKFLAGS"):
if not any("-g" in f for f in env.get(flags_section, [])):
env.Prepend(**{flags_section: ["-g"]})
def exists(_): def exists(_):
return True return True
def generate(env): def generate(env):
env.AddMethod(DumpSizeData) env.AddMethod(DumpSizeData)
env.AddMethod(ConfigureSizeDataTarget)
return env return env

View File

@@ -103,9 +103,6 @@ def BuildProgram(env):
if not Util.case_sensitive_suffixes(".s", ".S"): if not Util.case_sensitive_suffixes(".s", ".S"):
env.Replace(AS="$CC", ASCOM="$ASPPCOM") env.Replace(AS="$CC", ASCOM="$ASPPCOM")
if "debug" in COMMAND_LINE_TARGETS or env.GetProjectOption("build_type") == "debug":
env.ConfigureDebugTarget()
# process extra flags from board # process extra flags from board
if "BOARD" in env and "build.extra_flags" in env.BoardConfig(): if "BOARD" in env and "build.extra_flags" in env.BoardConfig():
env.ProcessFlags(env.BoardConfig().get("build.extra_flags")) env.ProcessFlags(env.BoardConfig().get("build.extra_flags"))
@@ -116,8 +113,11 @@ def BuildProgram(env):
# process framework scripts # process framework scripts
env.BuildFrameworks(env.get("PIOFRAMEWORK")) env.BuildFrameworks(env.get("PIOFRAMEWORK"))
# restore PIO macros if it was deleted by framework if (
_append_pio_macros() set(["debug", "sizedata"]) & set(COMMAND_LINE_TARGETS)
or env.GetProjectOption("build_type") == "debug"
):
env.ConfigureDebugFlags()
# remove specified flags # remove specified flags
env.ProcessUnFlags(env.get("BUILD_UNFLAGS")) env.ProcessUnFlags(env.get("BUILD_UNFLAGS"))
@@ -125,9 +125,6 @@ def BuildProgram(env):
if "__test" in COMMAND_LINE_TARGETS: if "__test" in COMMAND_LINE_TARGETS:
env.ConfigureTestTarget() env.ConfigureTestTarget()
if "sizedata" in COMMAND_LINE_TARGETS:
env.ConfigureSizeDataTarget()
# build project with dependencies # build project with dependencies
_build_project_deps(env) _build_project_deps(env)

View File

@@ -14,8 +14,15 @@
from setuptools import find_packages, setup from setuptools import find_packages, setup
from platformio import (__author__, __description__, __email__, __license__, from platformio import (
__title__, __url__, __version__) __author__,
__description__,
__email__,
__license__,
__title__,
__url__,
__version__,
)
install_requires = [ install_requires = [
"bottle<0.13", "bottle<0.13",
@@ -24,7 +31,8 @@ install_requires = [
"pyserial>=3,<4,!=3.3", "pyserial>=3,<4,!=3.3",
"requests>=2.4.0,<3", "requests>=2.4.0,<3",
"semantic_version>=2.8.1,<3", "semantic_version>=2.8.1,<3",
"tabulate>=0.8.3,<1" "tabulate>=0.8.3,<1",
"pyelftools>=0.25,<1",
] ]
setup( setup(
@@ -36,8 +44,9 @@ setup(
author_email=__email__, author_email=__email__,
url=__url__, url=__url__,
license=__license__, license=__license__,
python_requires=", ".join([ python_requires=", ".join(
">=2.7", "!=3.0.*", "!=3.1.*", "!=3.2.*", "!=3.3.*", "!=3.4.*"]), [">=2.7", "!=3.0.*", "!=3.1.*", "!=3.2.*", "!=3.3.*", "!=3.4.*"]
),
install_requires=install_requires, install_requires=install_requires,
packages=find_packages() + ["scripts"], packages=find_packages() + ["scripts"],
package_data={ package_data={
@@ -45,17 +54,15 @@ setup(
"ide/tpls/*/.*.tpl", "ide/tpls/*/.*.tpl",
"ide/tpls/*/*.tpl", "ide/tpls/*/*.tpl",
"ide/tpls/*/*/*.tpl", "ide/tpls/*/*/*.tpl",
"ide/tpls/*/.*/*.tpl" "ide/tpls/*/.*/*.tpl",
], ],
"scripts": [ "scripts": ["99-platformio-udev.rules"],
"99-platformio-udev.rules"
]
}, },
entry_points={ entry_points={
"console_scripts": [ "console_scripts": [
"platformio = platformio.__main__:main",
"pio = platformio.__main__:main", "pio = platformio.__main__:main",
"piodebuggdb = platformio.__main__:debug_gdb_main", "piodebuggdb = platformio.__main__:debug_gdb_main",
"platformio = platformio.__main__:main"
] ]
}, },
classifiers=[ classifiers=[
@@ -70,11 +77,26 @@ setup(
"Programming Language :: Python :: 3", "Programming Language :: Python :: 3",
"Topic :: Software Development", "Topic :: Software Development",
"Topic :: Software Development :: Build Tools", "Topic :: Software Development :: Build Tools",
"Topic :: Software Development :: Compilers" "Topic :: Software Development :: Compilers",
], ],
keywords=[ keywords=[
"iot", "embedded", "arduino", "mbed", "esp8266", "esp32", "fpga", "iot",
"firmware", "continuous-integration", "cloud-ide", "avr", "arm", "embedded",
"ide", "unit-testing", "hardware", "verilog", "microcontroller", "arduino",
"debug" "mbed",
]) "esp8266",
"esp32",
"fpga",
"firmware",
"continuous-integration",
"cloud-ide",
"avr",
"arm",
"ide",
"unit-testing",
"hardware",
"verilog",
"microcontroller",
"debug",
],
)