buildwin32.py 3.5 KB

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