blob: ca2d05e4f9acb1926912705eb3138ff1c6c4a282 [file] [log] [blame]
#!/usr/bin/env python3
# pylint: disable=invalid-name,missing-module-docstring,missing-function-docstring
#
# Copyright 2023 Richard Hughes <richard@hughsie.com>
#
# SPDX-License-Identifier: LGPL-2.1-or-later
import glob
import fnmatch
import os
import sys
import subprocess
def test_files() -> int:
fns = sys.argv[1:]
if not fns:
build = os.environ["BUILD"] if "BUILD" in os.environ else ""
fns.append(os.path.join(".", build, "plugins"))
fns.append(os.path.join(".", build, "src"))
data = []
# find all .o files
for fn in fns:
for fn in glob.glob(f"{fn}/**/*.o", recursive=True):
print(f"Analyzing {fn}...")
p = subprocess.run(["nm", fn], check=True, capture_output=True)
# parse data
for line in p.stdout.decode().split("\n"):
line = line.rstrip()
if len(line) == 0:
continue
if line.endswith(".o:"):
continue
t = line[17:18]
if t == "b" or t == "t" or t == "r" or t == "d" or t == "a":
continue
symb = line[19:]
data.append((t, symb))
# collect all the symbols defined
symbs = []
for t, symb in data:
if t != "T":
continue
if symb.endswith("_get_type"):
continue
if fnmatch.fnmatch(symb, "fu_struct_*_set_*"):
continue
if fnmatch.fnmatch(symb, "fu_struct_*_get_*"):
continue
if fnmatch.fnmatch(symb, "fu_*_ref"):
continue
if fnmatch.fnmatch(symb, "fu_*_unref"):
continue
if symb.find("__proto__") != -1:
continue
if symb in ["main", "fu_plugin_init_vfuncs"]:
continue
if symb not in symbs:
symbs.append(symb)
# remove the ones used
for t, symb in data:
if t != "U":
continue
if symb in symbs:
symbs.remove(symb)
# display
symbs.sort()
for symb in symbs:
print("Unused: ", symb)
return 1 if symbs else 0
if __name__ == "__main__":
# all done!
sys.exit(test_files())