104 lines
		
	
	
	
		
			3.2 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			104 lines
		
	
	
	
		
			3.2 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| # -*- coding: utf-8 -*-
 | |
| # Copyright 2016 Christoph Reiter
 | |
| #
 | |
| # This program is free software; you can redistribute it and/or modify
 | |
| # it under the terms of the GNU General Public License as published by
 | |
| # the Free Software Foundation; either version 2 of the License, or
 | |
| # (at your option) any later version.
 | |
| 
 | |
| """
 | |
| Deletes unneeded DLLs and checks DLL dependencies.
 | |
| Execute with the build python, will figure out the rest.
 | |
| """
 | |
| 
 | |
| import subprocess
 | |
| import os
 | |
| import sys
 | |
| 
 | |
| import gi
 | |
| gi.require_version("GIRepository", "2.0")
 | |
| from gi.repository import GIRepository
 | |
| 
 | |
| 
 | |
| def get_required_by_typelibs():
 | |
|     deps = set()
 | |
|     repo = GIRepository.Repository()
 | |
|     for tl in os.listdir(repo.get_search_path()[0]):
 | |
|         namespace, version = os.path.splitext(tl)[0].split("-", 1)
 | |
|         repo.require(namespace, version, 0)
 | |
|         lib = repo.get_shared_library(namespace)
 | |
|         if lib:
 | |
|             deps.update(lib.split(","))
 | |
|     return deps
 | |
| 
 | |
| 
 | |
| EXTENSIONS = [".exe", ".pyd", ".dll"]
 | |
| SYSTEM_LIBS = ['advapi32.dll',
 | |
|     "cabinet.dll", "comctl32.dll", "comdlg32.dll", "crypt32.dll", "d3d9.dll",
 | |
|     "dnsapi.dll", "dsound.dll", "dwmapi.dll", "gdi32.dll", "imm32.dll",
 | |
|     "iphlpapi.dll", "kernel32.dll", "ksuser.dll", "msi.dll", "msimg32.dll",
 | |
|     "msvcr71.dll", "msvcr80.dll", "msvcrt.dll", "ole32.dll", "oleaut32.dll",
 | |
|     "opengl32.dll", "rpcrt4.dll", "setupapi.dll", "shell32.dll", "user32.dll",
 | |
|     "usp10.dll", "winmm.dll", "winspool.drv", "wldap32.dll", "ws2_32.dll",
 | |
|     "wsock32.dll", "shlwapi.dll"
 | |
| ]
 | |
| 
 | |
| 
 | |
| def get_dependencies(filename):
 | |
|     deps = []
 | |
|     data = subprocess.check_output(["objdump", "-p", filename])
 | |
|     data = data.decode("utf-8")
 | |
|     for line in data.splitlines():
 | |
|         line = line.strip()
 | |
|         if line.startswith("DLL Name:"):
 | |
|             deps.append(line.split(":", 1)[-1].strip().lower())
 | |
|     return deps
 | |
| 
 | |
| 
 | |
| def find_lib(root, name):
 | |
|     search_path = os.path.join(root, "bin")
 | |
|     if os.path.exists(os.path.join(search_path, name)):
 | |
|         return os.path.join(search_path, name)
 | |
|     elif name in SYSTEM_LIBS:
 | |
|         return name
 | |
| 
 | |
| 
 | |
| def get_things_to_delete(root):
 | |
|     all_libs = set()
 | |
|     needed = set()
 | |
|     for base, dirs, files in os.walk(root):
 | |
|         for f in files:
 | |
|             path = os.path.join(base, f)
 | |
|             if os.path.splitext(path)[-1].lower() in EXTENSIONS:
 | |
|                 all_libs.add(f.lower())
 | |
|                 for lib in get_dependencies(path):
 | |
|                     all_libs.add(lib)
 | |
|                     needed.add(lib)
 | |
|                     if not find_lib(root, lib):
 | |
|                         print("MISSING:", path, lib)
 | |
| 
 | |
|     for lib in get_required_by_typelibs():
 | |
|         needed.add(lib)
 | |
|         if not find_lib(root, lib):
 | |
|             print("MISSING:", path, lib)
 | |
| 
 | |
|     # get rid of things not in the search path,
 | |
|     # maybe loaded through other means?
 | |
|     not_needed = filter(
 | |
|         lambda l: find_lib(root, l) and \
 | |
|             os.path.splitext(l)[-1].lower() != ".exe", all_libs - needed)
 | |
| 
 | |
|     return [find_lib(root, l) for l in not_needed]
 | |
| 
 | |
| 
 | |
| def main():
 | |
|     libs = get_things_to_delete(sys.prefix)
 | |
|     while libs:
 | |
|         for l in libs:
 | |
|             print("DELETE:", l)
 | |
|             os.unlink(l)
 | |
|         libs = get_things_to_delete(sys.prefix)
 | |
| 
 | |
| 
 | |
| if __name__ == "__main__":
 | |
|     main()
 |