From 28fcbe2b771e5be21e14e0ca5ca3ac2f91ca9378 Mon Sep 17 00:00:00 2001 From: Mathias Agopian Date: Wed, 3 Sep 2025 22:07:19 -0700 Subject: [PATCH] zbloat: add support for .a --- tools/zbloat/README.md | 2 +- tools/zbloat/evmar_bloat.py | 5 +++++ tools/zbloat/zbloat.py | 14 ++++++++++---- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/tools/zbloat/README.md b/tools/zbloat/README.md index bbeb4c4683..443840772e 100644 --- a/tools/zbloat/README.md +++ b/tools/zbloat/README.md @@ -3,7 +3,7 @@ This tool makes it easy to analyze the composition of Android applications that use Filament. - Filament materials are shown in the treemap if `resgen --json` was used in the build. -- The input path can be a so file, folder, or zip archive (apk or aar). +- The input path can be a `.so` or `.a` file, a folder, or a zip archive (apk or aar). - If the path is a zip or folder, interactively finds the file to analyze. - The generated web report is a self-contained HTML file. - Reports the gzipped size of all Filament materials. diff --git a/tools/zbloat/evmar_bloat.py b/tools/zbloat/evmar_bloat.py index f90470a41a..fd2907c3f8 100644 --- a/tools/zbloat/evmar_bloat.py +++ b/tools/zbloat/evmar_bloat.py @@ -77,6 +77,11 @@ def parse_nm(input): noaddr_re = re.compile(r'^ + (.) (.*)$') for line in input: + # For static archives (.a), nm prints the object file name. + # e.g., "subfolder/file.cpp.o:" or just an empty line between objects. + if line.strip().endswith('.o:') or not line.strip(): + continue + line = line.rstrip() match = sym_re.match(line) if match: diff --git a/tools/zbloat/zbloat.py b/tools/zbloat/zbloat.py index 4a30ad47fb..e542564a9f 100755 --- a/tools/zbloat/zbloat.py +++ b/tools/zbloat/zbloat.py @@ -177,14 +177,20 @@ def main(args): path = choose_from_dir(path) elif path.suffix in ['.zip', '.aar', '.apk']: path = choose_from_zip(path) + elif path.suffix == '.a': + pass # It's a single file, just like a .so dsopath = Path(path) size = format_bytes(dsopath.stat().st_size, 2) - csize = format_bytes(get_compressed_size(open(dsopath, 'rb').read()), 2) - info = f'{size} ({csize})' - print('Scanning for resgen resources...') - resgen_jsons, resgen_blobs = extract_resgen(dsopath) + if dsopath.suffix == '.a': + info = f'{size}' + resgen_jsons, resgen_blobs = [], [] + else: + csize = format_bytes(get_compressed_size(open(dsopath, 'rb').read()), 2) + info = f'{size} ({csize})' + print('Scanning for resgen resources...') + resgen_jsons, resgen_blobs = extract_resgen(dsopath) print('Running nm... (this might take a while)') os.system(f'nm -C -S {path} > {TEMPDIR}/nm.out')