Tools: update idf_size.py types to pep-484 format

This commit is contained in:
simon.chupin 2021-08-18 15:14:47 +02:00 committed by bot
parent 10d083a4c1
commit a7be2cb9bb
3 changed files with 131 additions and 151 deletions

View File

@ -4148,7 +4148,6 @@ tools/idf_py_actions/global_options.py
tools/idf_py_actions/serial_ext.py
tools/idf_py_actions/tools.py
tools/idf_py_actions/uf2_ext.py
tools/idf_size.py
tools/kconfig/conf.c
tools/kconfig/confdata.c
tools/kconfig/expand_env.c

View File

@ -6,19 +6,8 @@
# Includes information which is not shown in "xtensa-esp32-elf-size",
# or easy to parse from "xtensa-esp32-elf-objdump" or raw map files.
#
# Copyright 2017-2021 Espressif Systems (Shanghai) CO LTD
#
# 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.
# SPDX-FileCopyrightText: 2017-2021 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: Apache-2.0
#
from __future__ import division, print_function, unicode_literals
@ -28,15 +17,13 @@ import json
import os.path
import re
import sys
from typing import Any, Callable, Collection, Dict, Iterable, List, Optional, TextIO, Tuple, Union
from future.utils import iteritems
try:
from typing import Any, Callable, Collection, Dict, Iterable, List, Optional, TextIO, Tuple, Union
Section = Dict[str, Union[str, int]]
SectionDict = Dict[str, Section]
except ImportError:
pass
try:
basestring
@ -50,7 +37,6 @@ GLOBAL_JSON_SEPARATORS = (',', ': ')
class MemRegions(object):
# Regions determined by the chip target.
# DIRAM is not added here. The DIRAM is indicated by the `secondary_addr` of each MemRegDef
(DRAM_ID, IRAM_ID, CACHE_D_ID, CACHE_I_ID, RTC_FAST_D_ID, RTC_FAST_I_ID, RTC_SLOW_D_ID) = range(7)
@ -59,15 +45,14 @@ class MemRegions(object):
class Region(object):
# Helper class to store region information
def __init__(self, start, length, region, section=None):
# type: (MemRegions.Region, int, int, MemRegions.MemRegDef, Optional[str]) -> None
def __init__(self, start: int, length: int, region: 'MemRegions.MemRegDef', section: Optional[str]=None) -> None:
self.start = start
self.len = length
self.region = region
self.section = section
@staticmethod
def get_mem_regions(target): # type: (str) -> List
def get_mem_regions(target: str) -> List:
# The target specific memory structure is deduced from soc_memory_types defined in
# $IDF_PATH/components/soc/**/soc_memory_layout.c files.
@ -124,13 +109,12 @@ class MemRegions(object):
else:
raise RuntimeError('Target not detected.')
def __init__(self, target): # type: (MemRegions, str) -> None
def __init__(self, target: str) -> None:
self.chip_mem_regions = self.get_mem_regions(target)
if not self.chip_mem_regions:
raise RuntimeError('Target {} is not implemented in idf_size'.format(target))
def _get_first_region(self, start, length):
# type: (int, int) -> Tuple[Union[MemRegions.MemRegDef, None], int]
def _get_first_region(self, start: int, length: int) -> Tuple[Union['MemRegions.MemRegDef', None], int]:
for region in self.chip_mem_regions: # type: ignore
if region.primary_addr <= start < region.primary_addr + region.length:
return (region, length)
@ -140,7 +124,7 @@ class MemRegions(object):
print('Check whether the LD file is compatible with the definitions in get_mem_regions in idf_size.py')
return (None, length)
def _get_regions(self, start, length, name=None): # type: (int, int, Optional[str]) -> List
def _get_regions(self, start: int, length: int, name: Optional[str]=None) -> List:
ret = []
while length > 0:
(region, cur_len) = self._get_first_region(start, length)
@ -155,7 +139,7 @@ class MemRegions(object):
return ret
def fit_segments_into_regions(self, segments): # type: (MemRegions, Dict) -> List
def fit_segments_into_regions(self, segments: Dict) -> List:
region_list = []
for segment in segments.values():
@ -164,7 +148,7 @@ class MemRegions(object):
return region_list
def fit_sections_into_regions(self, sections): # type: (MemRegions, Dict) -> List
def fit_sections_into_regions(self, sections: Dict) -> List:
region_list = []
for section in sections.values():
@ -187,7 +171,7 @@ class LinkingSections(object):
}.items()}
@staticmethod
def in_section(section, section_name_or_list): # type: (str, Union[str, Iterable]) -> bool
def in_section(section: str, section_name_or_list: Union[str, Iterable]) -> bool:
if isinstance(section_name_or_list, basestring):
section_name_or_list = [section_name_or_list]
@ -197,18 +181,18 @@ class LinkingSections(object):
return False
@staticmethod
def filter_sections(sections): # type: (Dict) -> Dict
def filter_sections(sections: Dict) -> Dict:
return {k: v for k, v in sections.items()
if LinkingSections.in_section(k, LinkingSections._section_type_dict.keys())}
@staticmethod
def get_display_name_order(section_name_list): # type: (List[str]) -> Tuple[List[str], List[str]]
def get_display_name_order(section_name_list: List[str]) -> Tuple[List[str], List[str]]:
'''
Return two lists, in the suggested display order.
First list is the reordered section_name_list, second list is the suggested display name, corresponding to the first list
'''
def get_name_score(name): # type: (str) -> int
def get_name_score(name: str) -> int:
score_dict = {
'.dram': 30,
'.iram': 20,
@ -241,6 +225,7 @@ class LinkingSections(object):
continue
memory_name = ''
split_name = section.split('.')
if len(split_name) > 1:
# If the section has a memory type, update the type and try to display the type properly
@ -261,7 +246,7 @@ class LinkingSections(object):
return ordered_name_list, display_name_list
def scan_to_header(f, header_line): # type: (Iterable, str) -> None
def scan_to_header(f: Iterable, header_line: str) -> None:
""" Scan forward in a file until you reach 'header_line', then return """
for line in f:
if line.strip() == header_line:
@ -269,14 +254,14 @@ def scan_to_header(f, header_line): # type: (Iterable, str) -> None
raise RuntimeError("Didn't find line '%s' in file" % header_line)
def format_json(json_object): # type: (Dict) -> str
def format_json(json_object: Dict) -> str:
return json.dumps(json_object,
allow_nan=True,
indent=GLOBAL_JSON_INDENT,
separators=GLOBAL_JSON_SEPARATORS) + os.linesep
def load_map_data(map_file): # type: (TextIO) -> Tuple[str, Dict, Dict]
def load_map_data(map_file: TextIO) -> Tuple[str, Dict, Dict]:
segments = load_segments(map_file)
detected_chip = detect_target_chip(map_file)
sections = load_sections(map_file)
@ -289,7 +274,7 @@ def load_map_data(map_file): # type: (TextIO) -> Tuple[str, Dict, Dict]
return detected_chip, segments, sections
def load_segments(map_file): # type: (TextIO) -> Dict
def load_segments(map_file: TextIO) -> Dict:
""" Memory Configuration section is the total size of each segment """
result = {} # type: Dict[Any, Dict]
scan_to_header(map_file, 'Memory Configuration')
@ -312,7 +297,7 @@ def load_segments(map_file): # type: (TextIO) -> Dict
raise RuntimeError('End of file while scanning memory configuration?')
def detect_target_chip(map_file): # type: (Iterable) -> str
def detect_target_chip(map_file: Iterable) -> str:
''' Detect target chip based on the target archive name in the linker script part of the MAP file '''
scan_to_header(map_file, 'Linker script and memory map')
@ -340,7 +325,7 @@ def detect_target_chip(map_file): # type: (Iterable) -> str
raise RuntimeError('Target not detected')
def load_sections(map_file): # type: (TextIO) -> Dict
def load_sections(map_file: TextIO) -> Dict:
""" Load section size information from the MAP file.
Returns a dict of 'sections', where each key is a section name and the value
@ -372,7 +357,7 @@ def load_sections(map_file): # type: (TextIO) -> Dict
# Extract archive and object_file from the file_info field
RE_FILE = re.compile(r'((?P<archive>[^ ]+\.a)?\(?(?P<object_file>[^ ]+\.(o|obj))\)?)')
def dump_src_line(src): # type: (Dict) -> str
def dump_src_line(src: Dict) -> str:
return '%s(%s) addr: 0x%08x, size: 0x%x+%d' % (src['sym_name'], src['file'], src['address'], src['size'], src['fill'])
sections = {} # type: Dict[Any, Dict]
@ -481,13 +466,13 @@ def load_sections(map_file): # type: (TextIO) -> Dict
return sections
def check_target(target, map_file): # type: (str, TextIO) -> None
def check_target(target: str, map_file: TextIO) -> None:
if target is None:
raise RuntimeError('The target chip cannot be detected for {}. '
'Please report the issue.'.format(map_file.name))
def main(): # type: () -> None
def main() -> None:
parser = argparse.ArgumentParser(description='idf_size - a tool to print size information from an IDF MAP file')
parser.add_argument(
@ -576,7 +561,7 @@ class StructureForSummary(object):
used_diram_ratio = 0.
used_flash_text, used_flash_rodata, used_flash_other, used_flash, total_size = (0, ) * 5
def __sub__(self, rhs): # type: (StructureForSummary) -> StructureForSummary
def __sub__(self, rhs: 'StructureForSummary') -> 'StructureForSummary':
assert isinstance(rhs, StructureForSummary)
ret = self
for key in StructureForSummary.get_required_items():
@ -584,33 +569,33 @@ class StructureForSummary(object):
return ret
def get_dram_overflowed(self): # type: (StructureForSummary) -> bool
def get_dram_overflowed(self) -> bool:
return self.used_dram_ratio > 1.0
def get_iram_overflowed(self): # type: (StructureForSummary) -> bool
def get_iram_overflowed(self) -> bool:
return self.used_iram_ratio > 1.0
def get_diram_overflowed(self): # type: (StructureForSummary) -> bool
def get_diram_overflowed(self) -> bool:
return self.used_diram_ratio > 1.0
@classmethod
def get_required_items(cls): # type: (Any) -> List
def get_required_items(cls: Any) -> List:
whole_list = list(filter(lambda x: not (x.startswith('__') or x.endswith('__') or callable(getattr(cls, x))), dir(cls)))
return whole_list
@staticmethod
def get(segments, sections): # type: (List, List) -> StructureForSummary
def get(segments: List, sections: List) -> 'StructureForSummary':
def get_size(sections): # type: (Iterable) -> int
def get_size(sections: Iterable) -> int:
return sum([x.len for x in sections])
def in_diram(x): # type: (MemRegions.Region) -> bool
def in_diram(x: MemRegions.Region) -> bool:
return x.region.type in (MemRegions.DRAM_ID, MemRegions.IRAM_ID) and x.region.secondary_addr > 0
def in_dram(x): # type: (MemRegions.Region) -> bool
def in_dram(x: MemRegions.Region) -> bool:
return x.region.type == MemRegions.DRAM_ID and x.region.secondary_addr == 0 # type: ignore
def in_iram(x): # type: (MemRegions.Region) -> bool
def in_iram(x: MemRegions.Region) -> bool:
return x.region.type == MemRegions.IRAM_ID and x.region.secondary_addr == 0 # type: ignore
r = StructureForSummary()
@ -626,7 +611,7 @@ class StructureForSummary(object):
if r.diram_total == 0:
r.diram_total = r.dram_total + r.iram_total
def filter_in_section(sections, section_to_check): # type: (Iterable[MemRegions.Region], str) -> List[MemRegions.Region]
def filter_in_section(sections: Iterable[MemRegions.Region], section_to_check: str) -> List[MemRegions.Region]:
return list(filter(lambda x: LinkingSections.in_section(x.section, section_to_check), sections)) # type: ignore
dram_sections = list(filter(in_dram, sections))
@ -700,7 +685,7 @@ class StructureForSummary(object):
r.total_size = r.used_dram - r.used_dram_bss + r.used_iram + r.used_diram - r.used_diram_bss + r.used_flash
return r
def get_json_dic(self): # type: (StructureForSummary) -> collections.OrderedDict
def get_json_dic(self) -> collections.OrderedDict:
ret = collections.OrderedDict([
('dram_data', self.used_dram_data),
('dram_bss', self.used_dram_bss),
@ -741,7 +726,7 @@ class StructureForSummary(object):
return ret
def get_structure_for_target(segments, sections, target): # type: (Dict, Dict, str) -> StructureForSummary
def get_structure_for_target(segments: Dict, sections: Dict, target: str) -> StructureForSummary:
"""
Return StructureForSummary for spasific target
"""
@ -752,10 +737,10 @@ def get_structure_for_target(segments, sections, target): # type: (Dict, Dict,
return current
def get_summary(path, segments, sections, target,
as_json=False,
path_diff='', segments_diff=None, sections_diff=None, target_diff='', print_suggestions=True):
# type: (str, Dict, Dict, str, bool, str, Optional[Dict], Optional[Dict], str, bool) -> str
def get_summary(path: str, segments: Dict, sections: Dict, target: str,
as_json: bool=False,
path_diff: str='', segments_diff: Optional[Dict]=None, sections_diff: Optional[Dict]=None,
target_diff: str='', print_suggestions: bool=True) -> str:
if segments_diff is None:
segments_diff = {}
if sections_diff is None:
@ -790,11 +775,11 @@ def get_summary(path, segments, sections, target,
title = ''
name = ''
def __init__(self, title, name): # type: (LineDef, str, str) -> None
def __init__(self, title: str, name: str) -> None:
self.title = title
self.name = name
def format_line(self): # type: (LineDef) -> Tuple[str, str, str, str]
def format_line(self) -> Tuple[str, str, str, str]:
return (self.title + ': {%s:>7} bytes' % self.name,
'{%s:>7}' % self.name,
'{%s:+}' % self.name,
@ -806,14 +791,14 @@ def get_summary(path, segments, sections, target,
total = ''
warning_message = ''
def __init__(self, title, name, remain, ratio, total, warning_message): # type: (HeadLineDef, str, str, str, str, str, str) -> None
def __init__(self, title: str, name: str, remain: str, ratio: str, total: str, warning_message: str) -> None:
super(HeadLineDef, self).__init__(title, name)
self.remain = remain
self.ratio = ratio
self.total = total
self.warning_message = warning_message
def format_line(self): # type: (HeadLineDef) -> Tuple[str, str, str, str]
def format_line(self) -> Tuple[str, str, str, str]:
return ('%s: {%s:>7} bytes ({%s:>7} remain, {%s:.1%%} used)%s' % (self.title, self.name, self.remain, self.ratio, self.warning_message),
'{%s:>7}' % self.name,
'{%s:+}' % self.name,
@ -821,7 +806,7 @@ def get_summary(path, segments, sections, target,
class TotalLineDef(LineDef):
def format_line(self): # type: (TotalLineDef) -> Tuple[str, str, str, str]
def format_line(self) -> Tuple[str, str, str, str]:
return (self.title + ': {%s:>7} bytes (.bin may be padded larger)' % self.name,
'{%s:>7}' % self.name,
'{%s:+}' % self.name,
@ -858,7 +843,7 @@ def get_summary(path, segments, sections, target,
TotalLineDef('Total image size', 'total_size')
]
def convert_to_fmt_dict(summary, suffix=''): # type: (StructureForSummary, str) -> Dict
def convert_to_fmt_dict(summary: StructureForSummary, suffix: str='') -> Dict:
required_items = StructureForSummary.get_required_items()
return dict([(key + suffix, getattr(summary, key)) for key in required_items])
@ -869,8 +854,7 @@ def get_summary(path, segments, sections, target,
lf = '{:60}{:>15}{:>15} {}' # Width for a, b, c, d columns
def print_in_columns(a, b='', c='', d=''):
# type: (str, Optional[str], Optional[str], Optional[str]) -> str
def print_in_columns(a: str, b: Optional[str]='', c: Optional[str]='', d: Optional[str]='') -> str:
return lf.format(a, b, c, d).rstrip() + os.linesep
output = ''
@ -900,7 +884,7 @@ def get_summary(path, segments, sections, target,
return output
def check_is_dict_sort(non_sort_list): # type: (List) -> List
def check_is_dict_sort(non_sort_list: List) -> List:
'''
sort with keeping the order data, bss, other, iram, diram, ram_st_total, flash_text, flash_rodata, flash_total
'''
@ -924,7 +908,7 @@ def check_is_dict_sort(non_sort_list): # type: (List) -> List
class StructureForDetailedSizes(object):
@staticmethod
def sizes_by_key(sections, key, include_padding=False): # type: (SectionDict, str, Optional[bool]) -> Dict[str, Dict[str, int]]
def sizes_by_key(sections: SectionDict, key: str, include_padding: Optional[bool]=False) -> Dict[str, Dict[str, int]]:
""" Takes a dict of sections (from load_sections) and returns
a dict keyed by 'key' with aggregate output size information.
@ -944,7 +928,7 @@ class StructureForDetailedSizes(object):
return result
@staticmethod
def get(sections, by_key): # type: (SectionDict, str) -> collections.OrderedDict
def get(sections: SectionDict, by_key: str) -> collections.OrderedDict:
# Get the detailed structure before using the filter to remove undesired sections,
# to show entries without desired sections
sizes = StructureForDetailedSizes.sizes_by_key(sections, by_key)
@ -970,7 +954,7 @@ class StructureForDetailedSizes(object):
return collections.OrderedDict(s)
def get_detailed_sizes(sections, key, header, as_json=False, sections_diff=None): # type: (Dict, str, str, bool, Dict) -> str
def get_detailed_sizes(sections: Dict, key: str, header: str, as_json: bool=False, sections_diff: Dict=None) -> str:
key_name_set = set()
current = StructureForDetailedSizes.get(sections, key)
@ -1004,13 +988,12 @@ def get_detailed_sizes(sections, key, header, as_json=False, sections_diff=None)
else:
output = format_json(current)
else:
def _get_header_format(disp_list=display_name_list): # type: (List) -> str
def _get_header_format(disp_list: List=display_name_list) -> str:
len_list = [len(x) for x in disp_list]
len_list.insert(0, 24)
return ' '.join(['{:>%d}' % x for x in len_list]) + os.linesep
def _get_output(data, selection, key_list=ordered_key_list, disp_list=display_name_list):
# type: (Dict[str, Dict[str, int]], Collection, List, List) -> str
def _get_output(data: Dict[str, Dict[str, int]], selection: Collection, key_list: List=ordered_key_list, disp_list: List=display_name_list) -> str:
header_format = _get_header_format(disp_list)
output = header_format.format(header, *disp_list)
@ -1025,14 +1008,14 @@ def get_detailed_sizes(sections, key, header, as_json=False, sections_diff=None)
# k remains the same
pass
def get_section_size(section_dict): # type: (Dict) -> Callable[[str], int]
def get_section_size(section_dict: Dict) -> Callable[[str], int]:
return lambda x: section_dict.get(x, 0)
section_size_list = map(get_section_size(section_dict=v), key_list)
output += header_format.format(k[:24], *(section_size_list))
return output
def _get_header_format_diff(disp_list=display_name_list, columns=False): # type: (List, bool) -> str
def _get_header_format_diff(disp_list: List=display_name_list, columns: bool=False) -> str:
if columns:
len_list = (24, ) + (7, ) * 3 * len(disp_list)
return '|'.join(['{:>%d}' % x for x in len_list]) + os.linesep
@ -1040,8 +1023,7 @@ def get_detailed_sizes(sections, key, header, as_json=False, sections_diff=None)
len_list = (24, ) + (23, ) * len(disp_list)
return ' '.join(['{:>%d}' % x for x in len_list]) + os.linesep
def _get_output_diff(curr, ref, key_list=ordered_key_list, disp_list=display_name_list):
# type: (Dict, Dict, List, List) -> str
def _get_output_diff(curr: Dict, ref: Dict, key_list: List=ordered_key_list, disp_list: List=display_name_list) -> str:
# First header without Current/Ref/Diff columns
header_format = _get_header_format_diff(columns=False)
output = header_format.format(header, *disp_list)
@ -1069,8 +1051,7 @@ def get_detailed_sizes(sections, key, header, as_json=False, sections_diff=None)
# k remains the same
pass
def _get_items(name, section_dict=v, section_dict_ref=v2):
# type: (str, Dict, Dict) -> Tuple[str, str, str]
def _get_items(name: str, section_dict: Dict=v, section_dict_ref: Dict=v2) -> Tuple[str, str, str]:
a = section_dict.get(name, 0)
b = section_dict_ref.get(name, 0)
diff = a - b
@ -1110,7 +1091,7 @@ def get_detailed_sizes(sections, key, header, as_json=False, sections_diff=None)
class StructureForArchiveSymbols(object):
@staticmethod
def get(archive, sections): # type: (str, Dict) -> Dict
def get(archive: str, sections: Dict) -> Dict:
interested_sections = LinkingSections.filter_sections(sections)
result = dict([(t, {}) for t in interested_sections]) # type: Dict[str, Dict[str, int]]
@ -1135,7 +1116,7 @@ class StructureForArchiveSymbols(object):
return section_symbols
def get_archive_symbols(sections, archive, as_json=False, sections_diff=None): # type: (Dict, str, bool, Dict) -> str
def get_archive_symbols(sections: Dict, archive: str, as_json: bool=False, sections_diff: Dict=None) -> str:
diff_en = sections_diff is not None
current = StructureForArchiveSymbols.get(archive, sections)
reference = StructureForArchiveSymbols.get(archive, sections_diff) if sections_diff else {}
@ -1157,10 +1138,10 @@ def get_archive_symbols(sections, archive, as_json=False, sections_diff=None):
else:
output = format_json(current)
else:
def _get_item_pairs(name, section): # type: (str, collections.OrderedDict) -> collections.OrderedDict
def _get_item_pairs(name: str, section: collections.OrderedDict) -> collections.OrderedDict:
return collections.OrderedDict([(key.replace(name + '.', ''), val) for key, val in iteritems(section)])
def _get_output(section_symbols): # type: (Dict) -> str
def _get_output(section_symbols: Dict) -> str:
output = ''
for t, s in iteritems(section_symbols):
output += '{}Symbols from section: {}{}'.format(os.linesep, t, os.linesep)
@ -1175,8 +1156,7 @@ def get_archive_symbols(sections, archive, as_json=False, sections_diff=None):
output = 'Symbols within the archive: {} (Not all symbols may be reported){}'.format(archive, os.linesep)
if diff_en:
def _generate_line_tuple(curr, ref, name):
# type: (collections.OrderedDict, collections.OrderedDict, str) -> Tuple[str, int, int, str]
def _generate_line_tuple(curr: collections.OrderedDict, ref: collections.OrderedDict, name: str) -> Tuple[str, int, int, str]:
cur_val = curr.get(name, 0)
ref_val = ref.get(name, 0)
diff_val = cur_val - ref_val

View File

@ -1,129 +1,130 @@
#!/usr/bin/env bash
{ coverage debug sys \
&& coverage erase &> output \
{ python -m coverage debug sys \
&& python -m coverage erase &> output \
&& echo -e "\n***\nRunning idf_size.py..." &>> output \
&& coverage run -a $IDF_PATH/tools/idf_size.py app.map &>> output \
&& python -m coverage run -a $IDF_PATH/tools/idf_size.py app.map &>> output \
&& echo -e "\n***\nRunning idf_size.py on bootloader..." &>> output \
&& coverage run -a $IDF_PATH/tools/idf_size.py bootloader.map &>> output \
&& python -m coverage run -a $IDF_PATH/tools/idf_size.py bootloader.map &>> output \
&& echo -e "\n***\nRunning idf_size.py with overflow..." &>> output \
&& coverage run -a $IDF_PATH/tools/idf_size.py overflow.map &>> output \
&& python -m coverage run -a $IDF_PATH/tools/idf_size.py overflow.map &>> output \
&& echo -e "\n***\nRunning idf_size.py --archives..." &>> output \
&& coverage run -a $IDF_PATH/tools/idf_size.py --archives app.map &>> output \
&& python -m coverage run -a $IDF_PATH/tools/idf_size.py --archives app.map &>> output \
&& echo -e "\n***\nRunning idf_size.py --files..." &>> output \
&& coverage run -a $IDF_PATH/tools/idf_size.py --files app.map &>> output \
&& python -m coverage run -a $IDF_PATH/tools/idf_size.py --files app.map &>> output \
&& echo -e "\n***\nRunning idf_size.py --archive_details..." &>> output \
&& coverage run -a $IDF_PATH/tools/idf_size.py --archive_details libdriver.a app.map &>> output \
&& python -m coverage run -a $IDF_PATH/tools/idf_size.py --archive_details libdriver.a app.map &>> output \
&& echo -e "\n***\nRunning idf_size.py diff with bootloader..." &>> output \
&& coverage run -a $IDF_PATH/tools/idf_size.py app.map --diff bootloader.map &>> output \
&& python -m coverage run -a $IDF_PATH/tools/idf_size.py app.map --diff bootloader.map &>> output \
&& echo -e "\n***\nRunning idf_size.py diff with itself..." &>> output \
&& coverage run -a $IDF_PATH/tools/idf_size.py app.map --diff app.map &>> output \
&& python -m coverage run -a $IDF_PATH/tools/idf_size.py app.map --diff app.map &>> output \
&& echo -e "\n***\nRunning idf_size.py diff with another app..." &>> output \
&& coverage run -a $IDF_PATH/tools/idf_size.py app.map --diff app2.map &>> output \
&& python -m coverage run -a $IDF_PATH/tools/idf_size.py app.map --diff app2.map &>> output \
&& echo -e "\n***\nRunning idf_size.py diff with app in reverse order..." &>> output \
&& coverage run -a $IDF_PATH/tools/idf_size.py app2.map --diff app.map &>> output \
&& python -m coverage run -a $IDF_PATH/tools/idf_size.py app2.map --diff app.map &>> output \
&& echo -e "\n***\nRunning idf_size.py diff --archives with bootloader..." &>> output \
&& coverage run -a $IDF_PATH/tools/idf_size.py app.map --archives --diff bootloader.map &>> output \
&& python -m coverage run -a $IDF_PATH/tools/idf_size.py app.map --archives --diff bootloader.map &>> output \
&& echo -e "\n***\nRunning idf_size.py diff --archives with itself..." &>> output \
&& coverage run -a $IDF_PATH/tools/idf_size.py app.map --archives --diff app.map &>> output \
&& python -m coverage run -a $IDF_PATH/tools/idf_size.py app.map --archives --diff app.map &>> output \
&& echo -e "\n***\nRunning idf_size.py diff --archives with another app..." &>> output \
&& coverage run -a $IDF_PATH/tools/idf_size.py app.map --archives --diff app2.map &>> output \
&& python -m coverage run -a $IDF_PATH/tools/idf_size.py app.map --archives --diff app2.map &>> output \
&& echo -e "\n***\nRunning idf_size.py diff --archives with app in reverse order..." &>> output \
&& coverage run -a $IDF_PATH/tools/idf_size.py app2.map --archives --diff app.map &>> output \
&& python -m coverage run -a $IDF_PATH/tools/idf_size.py app2.map --archives --diff app.map &>> output \
&& echo -e "\n***\nRunning idf_size.py diff --files with bootloader..." &>> output \
&& coverage run -a $IDF_PATH/tools/idf_size.py app.map --files --diff bootloader.map &>> output \
&& python -m coverage run -a $IDF_PATH/tools/idf_size.py app.map --files --diff bootloader.map &>> output \
&& echo -e "\n***\nRunning idf_size.py diff --files with itself..." &>> output \
&& coverage run -a $IDF_PATH/tools/idf_size.py app.map --files --diff app.map &>> output \
&& python -m coverage run -a $IDF_PATH/tools/idf_size.py app.map --files --diff app.map &>> output \
&& echo -e "\n***\nRunning idf_size.py diff --files with another app..." &>> output \
&& coverage run -a $IDF_PATH/tools/idf_size.py app.map --files --diff app2.map &>> output \
&& python -m coverage run -a $IDF_PATH/tools/idf_size.py app.map --files --diff app2.map &>> output \
&& echo -e "\n***\nRunning idf_size.py diff --files with app in reverse order..." &>> output \
&& coverage run -a $IDF_PATH/tools/idf_size.py app2.map --files --diff app.map &>> output \
&& python -m coverage run -a $IDF_PATH/tools/idf_size.py app2.map --files --diff app.map &>> output \
&& echo -e "\n***\nRunning idf_size.py diff --archive_details with bootloader..." &>> output \
&& coverage run -a $IDF_PATH/tools/idf_size.py app.map --archive_details libdriver.a --diff bootloader.map &>> output \
&& python -m coverage run -a $IDF_PATH/tools/idf_size.py app.map --archive_details libdriver.a --diff bootloader.map &>> output \
&& echo -e "\n***\nRunning idf_size.py diff --archive_details with bootloader..." &>> output \
&& coverage run -a $IDF_PATH/tools/idf_size.py app.map --archive_details libc.a --diff bootloader.map &>> output \
&& python -m coverage run -a $IDF_PATH/tools/idf_size.py app.map --archive_details libc.a --diff bootloader.map &>> output \
&& echo -e "\n***\nRunning idf_size.py diff --archive_details with itself..." &>> output \
&& coverage run -a $IDF_PATH/tools/idf_size.py app.map --archive_details libdriver.a --diff app.map &>> output \
&& python -m coverage run -a $IDF_PATH/tools/idf_size.py app.map --archive_details libdriver.a --diff app.map &>> output \
&& echo -e "\n***\nRunning idf_size.py diff --archive_details with another app..." &>> output \
&& coverage run -a $IDF_PATH/tools/idf_size.py app.map --archive_details libdriver.a --diff app2.map &>> output \
&& python -m coverage run -a $IDF_PATH/tools/idf_size.py app.map --archive_details libdriver.a --diff app2.map &>> output \
&& echo -e "\n***\nRunning idf_size.py diff --archive_details with app in reverse order..." &>> output \
&& coverage run -a $IDF_PATH/tools/idf_size.py app2.map --archive_details libdriver.a --diff app.map &>> output \
&& python -m coverage run -a $IDF_PATH/tools/idf_size.py app2.map --archive_details libdriver.a --diff app.map &>> output \
&& echo -e "\n***\nRunning idf_size.py diff --archive_details with another app..." &>> output \
&& coverage run -a $IDF_PATH/tools/idf_size.py app.map --archive_details libfreertos.a --diff app2.map &>> output \
&& python -m coverage run -a $IDF_PATH/tools/idf_size.py app.map --archive_details libfreertos.a --diff app2.map &>> output \
&& echo -e "\n***\nRunning idf_size.py for esp32s2..." &>> output \
&& coverage run -a $IDF_PATH/tools/idf_size.py --target esp32s2 app_esp32s2.map &>> output \
&& python -m coverage run -a $IDF_PATH/tools/idf_size.py --target esp32s2 app_esp32s2.map &>> output \
&& echo -e "\n***\nRunning idf_size.py for esp32s2 with overflow..." &>> output \
&& coverage run -a $IDF_PATH/tools/idf_size.py --target esp32s2 overflow_esp32s2.map &>> output \
&& python -m coverage run -a $IDF_PATH/tools/idf_size.py --target esp32s2 overflow_esp32s2.map &>> output \
&& echo -e "\n***\nRunning idf_size.py for esp32s2 (target autodetected)..." &>> output \
&& coverage run -a $IDF_PATH/tools/idf_size.py app_esp32s2.map &>> output \
&& python -m coverage run -a $IDF_PATH/tools/idf_size.py app_esp32s2.map &>> output \
&& echo -e "\n***\nRunning idf_size.py on bootloader for esp32s2..." &>> output \
&& coverage run -a $IDF_PATH/tools/idf_size.py --target esp32s2 bootloader_esp32s2.map &>> output \
&& python -m coverage run -a $IDF_PATH/tools/idf_size.py --target esp32s2 bootloader_esp32s2.map &>> output \
&& echo -e "\n***\nRunning idf_size.py on bootloader for esp32s2 (target autodetected)..." &>> output \
&& coverage run -a $IDF_PATH/tools/idf_size.py bootloader_esp32s2.map &>> output \
&& python -m coverage run -a $IDF_PATH/tools/idf_size.py bootloader_esp32s2.map &>> output \
&& echo -e "\n***\nRunning idf_size.py --archives for esp32s2..." &>> output \
&& coverage run -a $IDF_PATH/tools/idf_size.py --target esp32s2 --archives app_esp32s2.map &>> output \
&& python -m coverage run -a $IDF_PATH/tools/idf_size.py --target esp32s2 --archives app_esp32s2.map &>> output \
&& echo -e "\n***\nRunning idf_size.py --files for esp32s2..." &>> output \
&& coverage run -a $IDF_PATH/tools/idf_size.py --target esp32s2 --files app_esp32s2.map &>> output \
&& python -m coverage run -a $IDF_PATH/tools/idf_size.py --target esp32s2 --files app_esp32s2.map &>> output \
&& echo -e "\n***\nRunning idf_size.py --archive_details for esp32s2..." &>> output \
&& coverage run -a $IDF_PATH/tools/idf_size.py --target esp32s2 --archive_details libdriver.a app_esp32s2.map &>> output \
&& python -m coverage run -a $IDF_PATH/tools/idf_size.py --target esp32s2 --archive_details libdriver.a app_esp32s2.map &>> output \
&& echo -e "\n***\nRunning idf_size.py diff with another app (different target)..." &>> output \
&& coverage run -a $IDF_PATH/tools/idf_size.py app.map --diff app_esp32s2.map &>> output \
&& python -m coverage run -a $IDF_PATH/tools/idf_size.py app.map --diff app_esp32s2.map &>> output \
&& echo -e "\n***\nRunning idf_size.py for esp32h2..." &>> output \
&& coverage run -a $IDF_PATH/tools/idf_size.py --target esp32h2 app_esp32h2.map &>> output \
&& python -m coverage run -a $IDF_PATH/tools/idf_size.py --target esp32h2 app_esp32h2.map &>> output \
&& echo -e "\n***\nRunning idf_size.py for esp32h2 (target autodetected)..." &>> output \
&& coverage run -a $IDF_PATH/tools/idf_size.py app_esp32h2.map &>> output \
&& python -m coverage run -a $IDF_PATH/tools/idf_size.py app_esp32h2.map &>> output \
&& echo -e "\n***\nRunning idf_size.py --archives for esp32h2..." &>> output \
&& coverage run -a $IDF_PATH/tools/idf_size.py --target esp32h2 --archives app_esp32h2.map &>> output \
&& python -m coverage run -a $IDF_PATH/tools/idf_size.py --target esp32h2 --archives app_esp32h2.map &>> output \
&& echo -e "\n***\nRunning idf_size.py --files for esp32h2..." &>> output \
&& coverage run -a $IDF_PATH/tools/idf_size.py --target esp32h2 --files app_esp32h2.map &>> output \
&& python -m coverage run -a $IDF_PATH/tools/idf_size.py --target esp32h2 --files app_esp32h2.map &>> output \
&& echo -e "\n***\nRunning idf_size.py --archive_details for esp32h2..." &>> output \
&& coverage run -a $IDF_PATH/tools/idf_size.py --target esp32h2 --archive_details libdriver.a app_esp32h2.map &>> output \
&& python -m coverage run -a $IDF_PATH/tools/idf_size.py --target esp32h2 --archive_details libdriver.a app_esp32h2.map &>> output \
&& echo -e "\n***\nRunning idf_size.py for esp32c3..." &>> output \
&& coverage run -a $IDF_PATH/tools/idf_size.py --target esp32c3 app_esp32c3.map &>> output \
&& python -m coverage run -a $IDF_PATH/tools/idf_size.py --target esp32c3 app_esp32c3.map &>> output \
&& echo -e "\n***\nRunning idf_size.py for esp32c3 with overflow..." &>> output \
&& coverage run -a $IDF_PATH/tools/idf_size.py --target esp32c3 overflow_esp32c3.map &>> output \
&& python -m coverage run -a $IDF_PATH/tools/idf_size.py --target esp32c3 overflow_esp32c3.map &>> output \
&& echo -e "\n***\nRunning idf_size.py for esp32c3 (target autodetected)..." &>> output \
&& coverage run -a $IDF_PATH/tools/idf_size.py app_esp32c3.map &>> output \
&& python -m coverage run -a $IDF_PATH/tools/idf_size.py app_esp32c3.map &>> output \
&& echo -e "\n***\nRunning idf_size.py --archives for esp32c3..." &>> output \
&& coverage run -a $IDF_PATH/tools/idf_size.py --target esp32c3 --archives app_esp32c3.map &>> output \
&& python -m coverage run -a $IDF_PATH/tools/idf_size.py --target esp32c3 --archives app_esp32c3.map &>> output \
&& echo -e "\n***\nRunning idf_size.py --files for esp32c3..." &>> output \
&& coverage run -a $IDF_PATH/tools/idf_size.py --target esp32c3 --files app_esp32c3.map &>> output \
&& python -m coverage run -a $IDF_PATH/tools/idf_size.py --target esp32c3 --files app_esp32c3.map &>> output \
&& echo -e "\n***\nRunning idf_size.py --archive_details for esp32c3..." &>> output \
&& coverage run -a $IDF_PATH/tools/idf_size.py --target esp32c3 --archive_details libdriver.a app_esp32c3.map &>> output \
&& python -m coverage run -a $IDF_PATH/tools/idf_size.py --target esp32c3 --archive_details libdriver.a app_esp32c3.map &>> output \
&& echo -e "\n***\nRunning idf_size.py for esp32s3..." &>> output \
&& coverage run -a $IDF_PATH/tools/idf_size.py --target esp32s3 app_esp32s3.map &>> output \
&& python -m coverage run -a $IDF_PATH/tools/idf_size.py --target esp32s3 app_esp32s3.map &>> output \
&& echo -e "\n***\nRunning idf_size.py for esp32s3 with overflow..." &>> output \
&& coverage run -a $IDF_PATH/tools/idf_size.py --target esp32s3 overflow_esp32s3.map &>> output \
&& python -m coverage run -a $IDF_PATH/tools/idf_size.py --target esp32s3 overflow_esp32s3.map &>> output \
&& echo -e "\n***\nRunning idf_size.py for esp32s3 (target autodetected)..." &>> output \
&& coverage run -a $IDF_PATH/tools/idf_size.py app_esp32s3.map &>> output \
&& python -m coverage run -a $IDF_PATH/tools/idf_size.py app_esp32s3.map &>> output \
&& echo -e "\n***\nRunning idf_size.py --archives for esp32s3..." &>> output \
&& coverage run -a $IDF_PATH/tools/idf_size.py --target esp32s3 --archives app_esp32s3.map &>> output \
&& python -m coverage run -a $IDF_PATH/tools/idf_size.py --target esp32s3 --archives app_esp32s3.map &>> output \
&& echo -e "\n***\nRunning idf_size.py --files for esp32s3..." &>> output \
&& coverage run -a $IDF_PATH/tools/idf_size.py --target esp32s3 --files app_esp32s3.map &>> output \
&& python -m coverage run -a $IDF_PATH/tools/idf_size.py --target esp32s3 --files app_esp32s3.map &>> output \
&& echo -e "\n***\nRunning idf_size.py --archive_details for esp32s3..." &>> output \
&& coverage run -a $IDF_PATH/tools/idf_size.py --target esp32s3 --archive_details libdriver.a app_esp32s3.map &>> output \
&& python -m coverage run -a $IDF_PATH/tools/idf_size.py --target esp32s3 --archive_details libdriver.a app_esp32s3.map &>> output \
&& echo -e "\n***\nProducing JSON output..." &>> output \
&& coverage run -a $IDF_PATH/tools/idf_size.py --json app.map &>> output \
&& coverage run -a $IDF_PATH/tools/idf_size.py --json --archives app.map &>> output \
&& coverage run -a $IDF_PATH/tools/idf_size.py --json --files app.map &>> output \
&& coverage run -a $IDF_PATH/tools/idf_size.py --json --archive_details libdriver.a app.map &>> output \
&& coverage run -a $IDF_PATH/tools/idf_size.py --json app.map --diff app2.map &>> output \
&& coverage run -a $IDF_PATH/tools/idf_size.py --json --archives app.map --diff app2.map &>> output \
&& coverage run -a $IDF_PATH/tools/idf_size.py --json --files app.map --diff app2.map &>> output \
&& coverage run -a $IDF_PATH/tools/idf_size.py --json --archive_details libdriver.a app.map --diff app2.map &>> output \
&& python -m coverage run -a $IDF_PATH/tools/idf_size.py --json app.map &>> output \
&& python -m coverage run -a $IDF_PATH/tools/idf_size.py --json --archives app.map &>> output \
&& python -m coverage run -a $IDF_PATH/tools/idf_size.py --json --files app.map &>> output \
&& python -m coverage run -a $IDF_PATH/tools/idf_size.py --json --archive_details libdriver.a app.map &>> output \
&& python -m coverage run -a $IDF_PATH/tools/idf_size.py --json app.map --diff app2.map &>> output \
&& python -m coverage run -a $IDF_PATH/tools/idf_size.py --json --archives app.map --diff app2.map &>> output \
&& python -m coverage run -a $IDF_PATH/tools/idf_size.py --json --files app.map --diff app2.map &>> output \
&& python -m coverage run -a $IDF_PATH/tools/idf_size.py --json --archive_details libdriver.a app.map --diff app2.map &>> output \
&& echo -e "\n***\nProducing JSON file output..." &>> output \
&& coverage run -a $IDF_PATH/tools/idf_size.py --json --output-file output.json app.map &>> output \
&& python -m coverage run -a $IDF_PATH/tools/idf_size.py --json --output-file output.json app.map &>> output \
&& echo -e "\n***\nProducing text file output..." &>> output \
&& coverage run -a $IDF_PATH/tools/idf_size.py -o output.txt app.map &>> output \
&& python -m coverage run -a $IDF_PATH/tools/idf_size.py -o output.txt app.map &>> output \
&& echo -e "\n***\nRunning idf_size_tests.py..." &>> output \
&& coverage run -a $IDF_PATH/tools/test_idf_size/test_idf_size.py &>> output \
&& python -m coverage run -a $IDF_PATH/tools/test_idf_size/test_idf_size.py &>> output \
&& echo -e "\n\nComparing expected output..." \
&& diff -Z output expected_output \
&& echo -e "\n\nComparing expected json output..." \
&& diff -Z output.json expected_output.json \
&& echo -e "\n\nComparing expected text output..." \
&& diff -Z output.txt expected_output.txt \
&& coverage report \
&& python -m coverage report \
; } || { echo 'The test for idf_size has failed. Please examine the artifacts.' ; exit 1; }
# Note: "diff -Z is used because some versions of Python print trailing whitespace for JSON pretty-printing, and some don't