]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
find-unused-library-symbols: apply "ruff format" and "ruff check --fix"
authorYu Watanabe <watanabe.yu+github@gmail.com>
Thu, 19 Feb 2026 17:09:45 +0000 (02:09 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Sun, 17 May 2026 17:44:47 +0000 (02:44 +0900)
tools/find-unused-library-symbols.py

index 47f96df2ee44fd7c1eab9e7d60ada19af2dd869b..66083c0ea4620d6bb0eea6ee37274e3f7f63d931 100755 (executable)
@@ -39,10 +39,10 @@ def get_exported_symbols(library_path):
             ['nm', '--dynamic', '--defined-only', '--extern-only', library_path],
             capture_output=True,
             text=True,
-            check=True
+            check=True,
         )
     except subprocess.CalledProcessError as e:
-        print(f"Error: Failed to run nm on {library_path}: {e}", file=sys.stderr)
+        print(f'Error: Failed to run nm on {library_path}: {e}', file=sys.stderr)
         sys.exit(1)
     except FileNotFoundError:
         print("Error: 'nm' command not found. Please install binutils.", file=sys.stderr)
@@ -79,10 +79,10 @@ def get_undefined_symbols(executable_path):
             ['nm', '--dynamic', '--undefined-only', executable_path],
             capture_output=True,
             text=True,
-            check=True
+            check=True,
         )
     except subprocess.CalledProcessError as e:
-        print(f"Warning: Failed to run nm on {executable_path}: {e}", file=sys.stderr)
+        print(f'Warning: Failed to run nm on {executable_path}: {e}', file=sys.stderr)
         return set()
     except FileNotFoundError:
         print("Error: 'nm' command not found. Please install binutils.", file=sys.stderr)
@@ -112,7 +112,7 @@ def verify_executable_links_library(executable_path, library_name):
             ['ldd', executable_path],
             capture_output=True,
             text=True,
-            check=True
+            check=True,
         )
     except (subprocess.CalledProcessError, FileNotFoundError):
         # If ldd fails or doesn't exist, we'll skip the verification
@@ -137,14 +137,16 @@ def get_library_internal_references(library_path, exported_symbols):
             ['objdump', '-R', library_path],
             capture_output=True,
             text=True,
-            check=True
+            check=True,
         )
     except subprocess.CalledProcessError as e:
-        print(f"Warning: Failed to run objdump on {library_path}: {e}", file=sys.stderr)
+        print(f'Warning: Failed to run objdump on {library_path}: {e}', file=sys.stderr)
         return set()
     except FileNotFoundError:
-        print("Warning: 'objdump' command not found. Internal references won't be detected.",
-              file=sys.stderr)
+        print(
+            "Warning: 'objdump' command not found. Internal references won't be detected.",
+            file=sys.stderr,
+        )
         return set()
 
     internal_refs = set()
@@ -181,7 +183,7 @@ def find_unused_symbols(library_path, executable_paths, verify_linkage=True):
     exported_symbols = get_exported_symbols(library_path)
 
     if not exported_symbols:
-        print(f"Warning: No exported symbols found in {library_path}", file=sys.stderr)
+        print(f'Warning: No exported symbols found in {library_path}', file=sys.stderr)
         return set(), set(), set()
 
     # Collect all symbols used by the executables
@@ -194,8 +196,7 @@ def find_unused_symbols(library_path, executable_paths, verify_linkage=True):
     for exe_path in executable_paths:
         # Optionally verify linkage
         if verify_linkage and not verify_executable_links_library(exe_path, library_name):
-            print(f"Warning: {exe_path} does not appear to link against {library_name}",
-                  file=sys.stderr)
+            print(f'Warning: {exe_path} does not appear to link against {library_name}', file=sys.stderr)
 
         undefined_symbols = get_undefined_symbols(exe_path)
         # Only count symbols that are actually exported by our library
@@ -209,31 +210,31 @@ def find_unused_symbols(library_path, executable_paths, verify_linkage=True):
 
 def main():
     parser = argparse.ArgumentParser(
-        description='Find unused exported symbols in a shared library'
+        description='Find unused exported symbols in a shared library',
     )
     parser.add_argument(
         'library',
-        help='Path to the shared library to analyze'
+        help='Path to the shared library to analyze',
     )
     parser.add_argument(
         'executables',
         nargs='+',
-        help='Paths to executables that link against the library'
+        help='Paths to executables that link against the library',
     )
     parser.add_argument(
         '--no-verify-linkage',
         action='store_true',
-        help='Skip verification that executables actually link against the library'
+        help='Skip verification that executables actually link against the library',
     )
     parser.add_argument(
         '--show-used',
         action='store_true',
-        help='Also show used symbols'
+        help='Also show used symbols',
     )
     parser.add_argument(
         '--stats-only',
         action='store_true',
-        help='Only show statistics, not individual symbols'
+        help='Only show statistics, not individual symbols',
     )
 
     args = parser.parse_args()
@@ -241,7 +242,7 @@ def main():
     # Verify library exists
     library_path = Path(args.library)
     if not library_path.exists():
-        print(f"Error: Library not found: {library_path}", file=sys.stderr)
+        print(f'Error: Library not found: {library_path}', file=sys.stderr)
         sys.exit(1)
 
     # Verify executables exist
@@ -249,47 +250,45 @@ def main():
     for exe in args.executables:
         exe_path = Path(exe)
         if not exe_path.exists():
-            print(f"Warning: Executable not found: {exe_path}", file=sys.stderr)
+            print(f'Warning: Executable not found: {exe_path}', file=sys.stderr)
         else:
             executable_paths.append(str(exe_path))
 
     if not executable_paths:
-        print("Error: No valid executables provided", file=sys.stderr)
+        print('Error: No valid executables provided', file=sys.stderr)
         sys.exit(1)
 
     # Analyze symbols
     unused, exported, used = find_unused_symbols(
-        str(library_path),
-        executable_paths,
-        verify_linkage=not args.no_verify_linkage
+        str(library_path), executable_paths, verify_linkage=not args.no_verify_linkage
     )
 
     # Print results
-    print(f"Analysis of {library_path.name}")
-    print("=" * 70)
-    print(f"Total exported symbols: {len(exported)}")
-    print(f"  (excluding public API symbols starting with 'sd_')")
-    print(f"Used symbols: {len(used)}")
-    print(f"Unused symbols: {len(unused)}")
-    print(f"Usage rate: {len(used)/len(exported)*100:.1f}%" if exported else "N/A")
+    print(f'Analysis of {library_path.name}')
+    print('=' * 70)
+    print(f'Total exported symbols: {len(exported)}')
+    print("  (excluding public API symbols starting with 'sd_')")
+    print(f'Used symbols: {len(used)}')
+    print(f'Unused symbols: {len(unused)}')
+    print(f'Usage rate: {len(used) / len(exported) * 100:.1f}%' if exported else 'N/A')
     print()
 
     if not args.stats_only:
         if unused:
-            print("Unused symbols:")
-            print("-" * 70)
+            print('Unused symbols:')
+            print('-' * 70)
             for symbol in sorted(unused):
-                print(f"  {symbol}")
+                print(f'  {symbol}')
             print()
         else:
-            print("All exported symbols are used!")
+            print('All exported symbols are used!')
             print()
 
         if args.show_used and used:
-            print("Used symbols:")
-            print("-" * 70)
+            print('Used symbols:')
+            print('-' * 70)
             for symbol in sorted(used):
-                print(f"  {symbol}")
+                print(f'  {symbol}')
             print()
 
     # Exit with non-zero if there are unused symbols (useful for CI)