#!/bin/env python3 ''' Quick and dirty script to analyze the contents of the binary. Shows total size of a crate's added code, count of the number of sections, and the name of the crate. Names with non-rust names are lumped into esp-idf, as that's most likely what they are in this project. Unfortunately, since much of the actual functionality is carried out by the esp-idf, including newly added functionality (such as bluetooth) often mostly just grows the amount of esp-idf that is included. ''' import subprocess import os.path import os.getcwd # Shorten names to crates instead of the whole function mangle_name = True program_name = os.path.split(os.getcwd())[1] print(program_name) targets = ("./target/xtensa-esp32-espidf/release/", "./target/xtensa-esp32-espidf/debug/") def find_file(): for t in targets: if os.path.isfile(t + program_name): #return t analyze_file(t + program_name) def analyze_file(f): results = subprocess.run(["nm", "-S", "--demangle=rust", "--size-sort", f], capture_output=True).stdout lines = results.splitlines() data = {} for line in lines: cols = line.split() # Cols are: 0: position, 1: size, 2: ? 3: name if len(cols) < 4: pass # this shouldn't happen if we sort by size; but nm lists things without a size otherwise. else: raw_name = cols[3].decode("utf-8") raw_size = cols[1] if mangle_name: if len(raw_name): while "<" == raw_name[0] or "&" == raw_name[0]: raw_name = raw_name[1:] parts = raw_name.split(':') if len(parts[0]) == len(raw_name): # Assume if it has no crate delimiters that it is part of esp-idf name = "esp-idf" else: name = parts[0] else: name = "(blank)" else: name = raw_name size = int(raw_size, 16) if name in data: (count, total) = data[name] count += 1 total += size data[name] = (count, total) else: data[name] = (1, size) print(" total | ct | crate") sorted_data = [] for item in data.items(): (name, (count, size)) = item sorted_data.append((size, count, name)) sorted_data.sort(key=lambda tup: tup[0]) for i in sorted_data: (size, count, name) = i print(f'{size:8,}', f'{count:4}', name) i = 0 for tup in data.values(): i += tup[1] print("\n","Total size: ", f'{i:,}', "Actual binary size may differ due to included data and the chunks nm didn't identify") def main(): find_file() if __name__ == "__main__": main() ''' For comparison; the 'Hello, World' app generated by 'cargo generate esp-rs/esp-idf-template cargo' Hello, World (release) analysis total | ct | crate 9 1 panic_abort 11 1 esp_idf_sys 84 1 hello_world 223 1 memchr 315 12 log 654 2 adler 724 8 esp_idf_svc 2,757 24 object 8,104 6 miniz_oxide 15,044 181 alloc 15,765 42 rustc_demangle 19,581 37 addr2line 26,343 200 std 33,966 291 core 34,980 104 gimli 159,412 1778 esp-idf Total size: 317,972 Hello, World (debug) analysis total | ct | crate 9 1 panic_abort 11 1 esp_idf_sys 84 1 hello_world 267 2 memchr 356 13 log 817 8 esp_idf_svc 1,012 5 adler 3,571 45 object 9,796 13 miniz_oxide 13,331 45 rustc_demangle 20,043 45 addr2line 28,044 281 std 35,175 629 alloc 38,761 210 gimli 60,658 863 core 186,909 2286 esp-idf Total size: 398,844 '''