kit

kit
git clone https://git.ryansepassi.com/git/kit.git
Log | Files | Refs | README

lib_external_deps.py (1651B)


      1 #!/usr/bin/env python3
      2 """Print external symbols that an archive (.a) depends on.
      3 
      4 Runs `nm` over the archive, then reports symbols that are undefined in some
      5 member but not defined by any other member of the same archive.
      6 """
      7 
      8 import argparse
      9 import subprocess
     10 import sys
     11 
     12 
     13 def external_deps(archive: str, nm: str = "nm") -> list[str]:
     14     out = subprocess.run(
     15         [nm, archive], check=True, capture_output=True, text=True
     16     ).stdout
     17 
     18     defined: set[str] = set()
     19     undefined: set[str] = set()
     20 
     21     for line in out.splitlines():
     22         line = line.rstrip()
     23         if not line or line.endswith(":"):
     24             # Blank line or "<member>.o:" header.
     25             continue
     26         parts = line.split(None, 2)
     27         if len(parts) < 2:
     28             continue
     29         if len(parts) == 2:
     30             # Undefined: "<type> <name>" (no address column).
     31             type_, name = parts
     32         else:
     33             # Defined: "<addr> <type> <name>".
     34             _, type_, name = parts
     35 
     36         if type_ == "U":
     37             undefined.add(name)
     38         elif type_.isupper():
     39             # Global definition (T, D, B, R, S, A, C, ...).
     40             defined.add(name)
     41         # Lowercase = local (file-scope); irrelevant for archive linkage.
     42 
     43     return sorted(undefined - defined)
     44 
     45 
     46 def main() -> int:
     47     ap = argparse.ArgumentParser(description=__doc__)
     48     ap.add_argument("archive", help="Path to a static archive (.a)")
     49     ap.add_argument("--nm", default="nm", help="nm binary to use")
     50     args = ap.parse_args()
     51 
     52     for sym in external_deps(args.archive, args.nm):
     53         print(sym)
     54     return 0
     55 
     56 
     57 if __name__ == "__main__":
     58     sys.exit(main())