post-install-win32.py 2.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  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 = []
  36. for file_name in args.binaries.copy():
  37. file_ext = os.path.splitext(file_name)[1]
  38. if (file_ext == ".dll" or file_ext == ".exe"):
  39. scan_queue.append(file_name)
  40. for file_name in scan_queue:
  41. file_ext = os.path.splitext(file_name)[1]
  42. if (file_ext == ".dll" or file_ext == ".exe"):
  43. pe = pefile.PE(file_name, fast_load = True)
  44. pe_bitness = pe.OPTIONAL_HEADER.Magic
  45. if bitness is None:
  46. bitness = pe_bitness
  47. elif bitness != pe_bitness:
  48. raise("binaries has different bitness")
  49. available_dlls = dict()
  50. for d in args.dirs:
  51. gather(resolve(d), available_dlls, bitness)
  52. existing_dir = os.path.dirname(args.binaries[0])
  53. existing_dlls = dict()
  54. gather(existing_dir, existing_dlls, bitness)
  55. visited = dict()
  56. needed_dlls = dict()
  57. while scan_queue:
  58. file_name = scan_queue.pop(0)
  59. # print(f"checking '{file_name}'")
  60. visited[file_name] = True
  61. pe = pefile.PE(file_name)
  62. if pe_bitness == bitness:
  63. for item in pe.DIRECTORY_ENTRY_IMPORT:
  64. dll = item.dll.lower().decode("utf-8")
  65. # print(f"{dll}, bitness = {bitness} / {pe_bitness}")
  66. if (dll not in needed_dlls and dll in available_dlls and dll not in existing_dlls):
  67. full_path = available_dlls[dll]
  68. needed_dlls[dll] = full_path
  69. if (dll not in visited):
  70. scan_queue.append(full_path)
  71. for dll, path in needed_dlls.items():
  72. print(f"{path}")
  73. shutil.copy(path, existing_dir)