post-install-win32.py 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. #!/usr/bin/env python
  2. import pefile
  3. import sys
  4. import os
  5. import shutil
  6. import subprocess
  7. import argparse
  8. from os.path import join
  9. onerror = lambda err: print(err)
  10. def gather(entry_dir, dlls, bitness):
  11. for root, dirs, files in os.walk(entry_dir, topdown=False, onerror = onerror, followlinks=True):
  12. for file in files:
  13. if (file.endswith(".dll")):
  14. full_path = join(root, file)
  15. #print(full_path)
  16. try:
  17. pe = pefile.PE(full_path, fast_load = True)
  18. pe_bitness = pe.OPTIONAL_HEADER.Magic
  19. if (pe_bitness == bitness):
  20. dlls[file.lower()] = full_path
  21. except Exception as e:
  22. None;
  23. def resolve(path):
  24. if (subprocess.check_output("uname").decode("utf-8").strip("\n") == "Linux"):
  25. # print(subprocess.check_output("uname").decode("utf-8").strip("\n"))
  26. return path
  27. else:
  28. # print(subprocess.check_output("uname"))
  29. return subprocess.check_output(["cygpath", "-w", path]).decode("utf-8").strip("\n")
  30. parser = argparse.ArgumentParser(description='Gathers DLLs.')
  31. parser.add_argument('--binaries', nargs='+', help='full paths to binaries for scaning')
  32. parser.add_argument('--dirs', nargs='*', help='additional dirs for looking up dependencies')
  33. bitness = None
  34. args = parser.parse_args()
  35. scan_queue = args.binaries.copy()
  36. for file_name in scan_queue:
  37. pe = pefile.PE(file_name, fast_load = True)
  38. pe_bitness = pe.OPTIONAL_HEADER.Magic
  39. if bitness is None:
  40. bitness = pe_bitness
  41. elif bitness != pe_bitness:
  42. raise("binaries has different bitness")
  43. available_dlls = dict()
  44. for d in args.dirs:
  45. gather(resolve(d), available_dlls, bitness)
  46. existing_dir = os.path.dirname(args.binaries[0])
  47. existing_dlls = dict()
  48. gather(existing_dir, existing_dlls, bitness)
  49. visited = dict()
  50. needed_dlls = dict()
  51. while scan_queue:
  52. file_name = scan_queue.pop(0)
  53. # print(f"checking '{file_name}'")
  54. visited[file_name] = True
  55. pe = pefile.PE(file_name)
  56. if pe_bitness == bitness:
  57. for item in pe.DIRECTORY_ENTRY_IMPORT:
  58. dll = item.dll.lower().decode("utf-8")
  59. # print(f"{dll}, bitness = {bitness} / {pe_bitness}")
  60. if (dll not in needed_dlls and dll in available_dlls and dll not in existing_dlls):
  61. full_path = available_dlls[dll]
  62. needed_dlls[dll] = full_path
  63. if (dll not in visited):
  64. scan_queue.append(full_path)
  65. for dll, path in needed_dlls.items():
  66. print(f"{path}")
  67. shutil.copy(path, existing_dir)