PageRenderTime 26ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

/windows_setup.py

https://github.com/lzamparo/CellProfiler
Python | 304 lines | 282 code | 8 blank | 14 comment | 9 complexity | 4f1dd9bf093b55a869a4dace701801e6 MD5 | raw file
Possible License(s): GPL-2.0, BSD-3-Clause
  1. """Windows setup file
  2. To invoke, from the command-line type:
  3. python windows_setup.py py2exe msi
  4. This script will create three subdirectories
  5. build: contains the collection of files needed during packaging
  6. dist: the contents that need to be given to the user to run WormProfiler.
  7. output: contains the .msi if you did the msi commmand
  8. """
  9. from distutils.core import setup
  10. import distutils.core
  11. import distutils.errors
  12. import py2exe
  13. import sys
  14. import glob
  15. import subprocess
  16. import re
  17. import os
  18. import _winreg
  19. import matplotlib
  20. import tempfile
  21. import xml.dom.minidom
  22. # make sure external dependencies match requirements
  23. import external_dependencies
  24. external_dependencies.fetch_external_dependencies('fail')
  25. from cellprofiler.utilities.version import version_number, dotted_version, version_string
  26. f = open("cellprofiler/frozen_version.py", "w")
  27. f.write("# MACHINE_GENERATED\nversion_string = '%s'" % version_string)
  28. f.close()
  29. is_win64 = (os.environ["PROCESSOR_ARCHITECTURE"] == "AMD64")
  30. is_2_6 = sys.version_info[0] >= 2 and sys.version_info[1] >= 6
  31. vcredist = os.path.join("windows",
  32. "vcredist_x64.exe" if is_win64
  33. else "vcredist_x86.exe")
  34. do_modify = is_2_6 and not os.path.exists(vcredist)
  35. class CellProfilerMSI(distutils.core.Command):
  36. description = "Make CellProfiler.msi using the CellProfiler.iss InnoSetup compiler"
  37. user_options = []
  38. def initialize_options(self):
  39. pass
  40. def finalize_options(self):
  41. pass
  42. def run(self):
  43. revision = str(version_number)
  44. if is_2_6 and do_modify:
  45. self.modify_manifest("CellProfiler.exe")
  46. self.modify_manifest("python26.dll;#2")
  47. self.modify_manifest("_imaging.pyd;#2")
  48. self.modify_manifest("wx._stc.pyd;#2")
  49. self.modify_manifest("wx._controls_.pyd;#2")
  50. self.modify_manifest("wx._aui.pyd;#2")
  51. self.modify_manifest("wx._misc_.pyd;#2")
  52. self.modify_manifest("wx._windows_.pyd;#2")
  53. self.modify_manifest("wx._gdi_.pyd;#2")
  54. self.modify_manifest("wx._html.pyd;#2")
  55. self.modify_manifest("wx._grid.pyd;#2")
  56. self.modify_manifest("PIL._imaging.pyd;#2")
  57. self.modify_manifest("wx._core_.pyd;#2")
  58. fd = open("version.iss", "w")
  59. fd.write("""
  60. AppVerName=CellProfiler %s r%s
  61. OutputBaseFilename=CellProfiler_%s_win%d_r%s
  62. """ % (dotted_version, revision, dotted_version, (64 if is_win64 else 32), revision))
  63. fd.close()
  64. if is_win64:
  65. cell_profiler_iss = "CellProfiler64.iss"
  66. cell_profiler_setup = "CellProfiler_%s_win64_r%s.exe" % (dotted_version, revision)
  67. else:
  68. cell_profiler_iss = "CellProfiler.iss"
  69. cell_profiler_setup = "CellProfiler_%s_win32_r%s.exe" % (dotted_version, revision)
  70. required_files = ["dist\\CellProfiler.exe",cell_profiler_iss]
  71. compile_command = self.__compile_command()
  72. compile_command = compile_command.replace("%1",cell_profiler_iss)
  73. self.make_file(required_files,"Output\\"+cell_profiler_setup,
  74. subprocess.check_call,([compile_command]),
  75. "Compiling %s" % cell_profiler_iss)
  76. os.remove("version.iss")
  77. def modify_manifest(self, resource_name):
  78. '''Change the manifest of a resource to match the CRT
  79. resource_name - the name of the executable or DLL maybe + ;#2
  80. to pick up the manifest in the assembly
  81. Read the manifest using "mt", hack the XML to change the version
  82. and reinsert it into the resource.
  83. '''
  84. #
  85. # Find mt
  86. #
  87. try:
  88. key_path = r"SOFTWARE\Microsoft\Microsoft SDKs\Windows\v7.0"
  89. key = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, key_path)
  90. path = _winreg.QueryValueEx(key, "InstallationFolder")[0]
  91. mt = os.path.join(path,"bin", "mt.exe")
  92. key.Close()
  93. except:
  94. print "Using MT from path"
  95. mt = "mt"
  96. directory = "dist"
  97. msvcrt = xml.dom.minidom.parse(os.path.join(
  98. directory, "Microsoft.VC90.CRT.manifest"))
  99. msvcrt_assembly = msvcrt.getElementsByTagName("assembly")[0]
  100. msvcrt_assembly_identity = msvcrt.getElementsByTagName("assemblyIdentity")[0]
  101. msvcrt_version = msvcrt_assembly_identity.getAttribute("version")
  102. manifest_file_name = tempfile.mktemp()
  103. pipe = subprocess.Popen(
  104. (mt,
  105. "-inputresource:%s" % os.path.join(directory, resource_name),
  106. "-out:%s" % manifest_file_name))
  107. pipe.communicate()
  108. if not os.path.exists(manifest_file_name):
  109. return
  110. manifest = xml.dom.minidom.parse(manifest_file_name)
  111. manifest_assembly = manifest.getElementsByTagName("assembly")[0]
  112. manifest_dependencies = manifest_assembly.getElementsByTagName("dependency")
  113. for dependency in manifest_dependencies:
  114. dependent_assemblies = dependency.getElementsByTagName("dependentAssembly")
  115. for dependent_assembly in dependent_assemblies:
  116. assembly_identity = dependent_assembly.getElementsByTagName("assemblyIdentity")[0]
  117. if assembly_identity.getAttribute("name") == "Microsoft.VC90.CRT":
  118. assembly_identity.setAttribute("version", msvcrt_version)
  119. fd = open(manifest_file_name, "wt")
  120. fd.write(manifest.toprettyxml())
  121. fd.close()
  122. pipe = subprocess.Popen(
  123. (mt,
  124. "-outputresource:%s" % os.path.join(directory, resource_name),
  125. "-manifest",
  126. manifest_file_name))
  127. pipe.communicate()
  128. os.remove(manifest_file_name)
  129. def __compile_command(self):
  130. """Return the command to use to compile an .iss file
  131. """
  132. try:
  133. key = _winreg.OpenKey(_winreg.HKEY_CLASSES_ROOT,
  134. "InnoSetupScriptFile\\shell\\Compile\\command")
  135. result = _winreg.QueryValueEx(key,None)[0]
  136. key.Close()
  137. return result
  138. except WindowsError:
  139. if key:
  140. key.Close()
  141. raise distutils.errors.DistutilsFileError, "Inno Setup does not seem to be installed properly. Specifically, there is no entry in the HKEY_CLASSES_ROOT for InnoSetupScriptFile\\shell\\Compile\\command"
  142. opts = {
  143. 'py2exe': { "includes" : ["numpy", "scipy","PIL","wx",
  144. "matplotlib", "matplotlib.numerix.random_array",
  145. "email.iterators",
  146. "cellprofiler.modules.*"],
  147. 'excludes': ['pylab', 'Tkinter', 'Cython', 'IPython'],
  148. 'dll_excludes': ["jvm.dll"]
  149. },
  150. 'msi': {}
  151. }
  152. data_files = []
  153. try:
  154. import nuageux
  155. opts['py2exe']['includes'] += ['nuageux']
  156. except:
  157. print "Nuageux not installed, no distributed support"
  158. try:
  159. import vigra
  160. import ilastik
  161. vigranumpy_path = os.path.join(vigra.__path__[0],"vigranumpycore.pyd")
  162. if os.path.exists(vigranumpy_path):
  163. data_files += [(".",[vigranumpy_path])]
  164. opts['py2exe']['includes'] += ["vigra", "vigra.impex",
  165. "h5py","h5py._stub","h5py._conv",
  166. "h5py.utils","h5py._proxy",
  167. "PyQt4", "PyQt4.QtOpenGL", "PyQt4.uic",
  168. "sip"]
  169. opts['py2exe']['excludes'] += ["ilastik"]
  170. #
  171. # Put path to QT dlls in PATH environment variable
  172. #
  173. import PyQt4
  174. pyqt4_path = os.path.split(PyQt4.__file__)[0]
  175. os.environ["PATH"] = os.environ["PATH"] + ";" + pyqt4_path
  176. il_path = ilastik.__path__[0]
  177. for root, subFolders, files in os.walk(il_path):
  178. #
  179. # Do not include experimental modules
  180. #
  181. relative_path = root[(len(il_path)+1):]
  182. if any([relative_path.startswith(os.path.join('modules',x))
  183. for x in (
  184. 'automatic_segmentation','object_picking',
  185. 'connected_components')]):
  186. continue
  187. dest = os.path.join('site-packages','ilastik')
  188. if root != il_path:
  189. dest = os.path.join(dest, relative_path)
  190. ilastik_files = [os.path.join(root, f) for f in files
  191. if f.endswith(".ui") or f.endswith(".png") or
  192. f.endswith(".py")]
  193. if len(ilastik_files) > 0:
  194. data_files += [(dest, ilastik_files)]
  195. #
  196. # port_v3 is for Python 3.1
  197. #
  198. opts['py2exe']['excludes'] += ['PyQt4.uic.port_v3']
  199. try:
  200. import OpenGL.platform.win32
  201. opts['py2exe']['includes'] += ['OpenGL.platform.win32',
  202. 'OpenGL.arrays.*']
  203. except:
  204. print "This installation will not supply OpenGL support for Ilastik"
  205. except:
  206. print "This installation will not include Ilastik"
  207. try:
  208. # Include this package if present
  209. import scipy.io.matlab.streams
  210. opts['py2exe']['includes'] += [ "scipy.io.matlab.streams"]
  211. except:
  212. pass
  213. if do_modify:
  214. # A trick to load the dlls
  215. if is_win64:
  216. path = r"SOFTWARE\WOW6432node\Microsoft\VisualStudio\9.0\Setup\VC"
  217. else:
  218. path = r"SOFTWARE\Microsoft\VisualStudio\9.0\Setup\VC"
  219. key = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, path)
  220. product_dir = _winreg.QueryValueEx(key, "ProductDir")[0]
  221. key.Close()
  222. redist = os.path.join(product_dir, r"redist\x86\Microsoft.VC90.CRT")
  223. data_files += [(".",[os.path.join(redist, x)
  224. for x in ("Microsoft.VC90.CRT.manifest",
  225. "msvcr90.dll",
  226. "msvcm90.dll",
  227. "msvcp90.dll")])]
  228. else:
  229. opts['py2exe']['dll_excludes'] += ["msvcr90.dll", "msvcm90.dll", "msvcp90.dll"]
  230. data_files += [('cellprofiler\\icons',
  231. ['cellprofiler\\icons\\%s'%(x)
  232. for x in os.listdir('cellprofiler\\icons')
  233. if x.endswith(".png") or x.endswith(".psd")]),
  234. ('bioformats', ['bioformats\\loci_tools.jar']),
  235. ('imagej', ['imagej\\'+jar_file
  236. for jar_file in os.listdir('imagej')
  237. if jar_file.endswith('.jar')])]
  238. data_files += matplotlib.get_py2exe_datafiles()
  239. # Collect the JVM
  240. #
  241. from cellprofiler.utilities.setup import find_jdk
  242. jdk_dir = find_jdk()
  243. def add_jre_files(path):
  244. files = []
  245. directories = []
  246. local_path = os.path.join(jdk_dir, path)
  247. for filename in os.listdir(local_path):
  248. if filename.startswith("."):
  249. continue
  250. local_file = os.path.join(jdk_dir, path, filename)
  251. relative_path = os.path.join(path, filename)
  252. if os.path.isfile(local_file):
  253. files.append(local_file)
  254. elif os.path.isdir(local_file):
  255. directories.append(relative_path)
  256. if len(files):
  257. data_files.append([path, files])
  258. for subdirectory in directories:
  259. add_jre_files(subdirectory)
  260. add_jre_files("jre")
  261. data_files += [("jre\\ext", [os.path.join(jdk_dir, "lib", "tools.jar")])]
  262. #
  263. # Call setup
  264. #
  265. try:
  266. setup(console=[{'script':'CellProfiler.py',
  267. 'icon_resources':[(1,'CellProfilerIcon.ico')]}],
  268. name='Cell Profiler',
  269. data_files = data_files,
  270. cmdclass={'msi':CellProfilerMSI
  271. },
  272. options=opts)
  273. finally:
  274. try:
  275. import cellprofiler.utilities.jutil as jutil
  276. jutil.kill_vm()
  277. sys.stderr.flush()
  278. sys.stdout.flush()
  279. os._exit(0)
  280. except:
  281. import traceback
  282. traceback.print_exc()
  283. print "Caught exception while killing VM"