buildwin32.py 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. import shutil
  2. import os
  3. import subprocess
  4. from modulefinder import ModuleFinder
  5. # Creates standalone Windows executable
  6. # First build by following instructions from installation.rst
  7. builddir = 'win32exe'
  8. if os.path.exists(builddir):
  9. shutil.rmtree(builddir)
  10. os.mkdir(builddir)
  11. os.mkdir(builddir + '/bin')
  12. os.mkdir(builddir + '/lib')
  13. print('Compiling wrapper')
  14. gccpath = '' # check for compiler, path needed later
  15. for p in os.environ['PATH'].split(';'):
  16. if os.path.exists(os.path.join(p, 'gcc.exe')):
  17. gccpath = p
  18. break
  19. if gccpath == '':
  20. print('gcc not found.')
  21. exit(1)
  22. source = open('wrapper.c', 'w')
  23. source.write(
  24. """
  25. #include <python3.5m/python.h>
  26. #include <windows.h>
  27. #include <wchar.h>
  28. #include "Shlwapi.h"
  29. int wmain(int argc , wchar_t *argv[] )
  30. {
  31. wchar_t *program = argv[0];
  32. Py_SetProgramName(program);
  33. Py_Initialize();
  34. PySys_SetArgv(argc, argv);
  35. wchar_t path[MAX_PATH];
  36. GetModuleFileNameW(NULL, path, MAX_PATH);
  37. PathRemoveFileSpecW(path);
  38. FILE* file_1 = _wfopen(wcsncat(path, L"/borg/__main__.py", 17), L"r");
  39. PyRun_AnyFile(file_1, "borg/__main__.py");
  40. Py_Finalize();
  41. PyMem_RawFree(program);
  42. return 0;
  43. }
  44. """)
  45. source.close()
  46. subprocess.run('gcc wrapper.c -lpython3.5m -lshlwapi -municode -o ' + builddir + '/bin/borg.exe')
  47. os.remove('wrapper.c')
  48. print('Searching modules')
  49. modulepath = os.path.abspath(os.path.join(gccpath, '../lib/python3.5/'))
  50. shutil.copytree(os.path.join(modulepath, 'encodings'), os.path.join(builddir, 'lib/python3.5/encodings'))
  51. finder = ModuleFinder()
  52. finder.run_script('borg/__main__.py')
  53. extramodules = [os.path.join(modulepath, 'site.py')]
  54. for module in extramodules:
  55. finder.run_script(module)
  56. print('Copying files')
  57. def finddlls(exe):
  58. re = []
  59. output = subprocess.check_output(['ntldd', '-R', exe])
  60. for line in output.decode('utf-8').split('\n'):
  61. if 'not found' in line:
  62. continue
  63. if 'windows' in line.lower():
  64. continue
  65. words = line.split()
  66. if len(words) < 3:
  67. if len(words) == 2:
  68. re.append(words[0])
  69. continue
  70. dll = words[2]
  71. re.append(dll)
  72. return re
  73. items = finder.modules.items()
  74. for name, mod in items:
  75. file = mod.__file__
  76. if file is None:
  77. continue
  78. lib = file.find('lib')
  79. if lib == -1:
  80. relpath = os.path.relpath(file)
  81. os.makedirs(os.path.join(builddir, 'bin', os.path.split(relpath)[0]), exist_ok=True)
  82. shutil.copyfile(file, os.path.join(builddir, 'bin', relpath))
  83. continue
  84. relativepath = file[file.find('lib')+4:]
  85. os.makedirs(os.path.join(builddir, 'lib', os.path.split(relativepath)[0]), exist_ok=True)
  86. shutil.copyfile(file, os.path.join(builddir, 'lib', relativepath))
  87. if file[-4:] == '.dll' or file[-4:] == '.DLL':
  88. for dll in finddlls(file):
  89. if builddir not in dll:
  90. shutil.copyfile(dll, os.path.join(builddir, 'bin', os.path.split(dll)[1]))
  91. for dll in finddlls(os.path.join(builddir, "bin/borg.exe")):
  92. if builddir not in dll:
  93. shutil.copyfile(dll, os.path.join(builddir, 'bin', os.path.split(dll)[1]))
  94. shutil.copyfile('borg/__main__.py', os.path.join(builddir, 'bin/borg/__main__.py'))
  95. for extmodule in ['borg/chunker-cpython-35m.dll', 'borg/compress-cpython-35m.dll', 'borg/crypto-cpython-35m.dll', 'borg/hashindex-cpython-35m.dll']:
  96. for dll in finddlls(extmodule):
  97. if builddir not in dll:
  98. shutil.copyfile(dll, os.path.join(builddir, 'bin', os.path.split(dll)[1]))