setup.py 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. #
  4. # Copyright (C) AB Strakt 2001, All rights reserved
  5. # Copyright (C) Jean-Paul Calderone 2008-2010, All rights reserved
  6. #
  7. """
  8. Installation script for the OpenSSL module
  9. """
  10. import sys, os
  11. from distutils.core import Extension, setup
  12. from distutils.errors import DistutilsFileError
  13. from distutils.command.build_ext import build_ext
  14. # XXX Deduplicate this
  15. __version__ = '0.11'
  16. crypto_src = ['OpenSSL/crypto/crypto.c', 'OpenSSL/crypto/x509.c',
  17. 'OpenSSL/crypto/x509name.c', 'OpenSSL/crypto/pkey.c',
  18. 'OpenSSL/crypto/x509store.c', 'OpenSSL/crypto/x509req.c',
  19. 'OpenSSL/crypto/x509ext.c', 'OpenSSL/crypto/pkcs7.c',
  20. 'OpenSSL/crypto/pkcs12.c', 'OpenSSL/crypto/netscape_spki.c',
  21. 'OpenSSL/crypto/revoked.c', 'OpenSSL/crypto/crl.c',
  22. 'OpenSSL/util.c']
  23. crypto_dep = ['OpenSSL/crypto/crypto.h', 'OpenSSL/crypto/x509.h',
  24. 'OpenSSL/crypto/x509name.h', 'OpenSSL/crypto/pkey.h',
  25. 'OpenSSL/crypto/x509store.h', 'OpenSSL/crypto/x509req.h',
  26. 'OpenSSL/crypto/x509ext.h', 'OpenSSL/crypto/pkcs7.h',
  27. 'OpenSSL/crypto/pkcs12.h', 'OpenSSL/crypto/netscape_spki.h',
  28. 'OpenSSL/crypto/revoked.h', 'OpenSSL/crypto/crl.h',
  29. 'OpenSSL/util.h']
  30. rand_src = ['OpenSSL/rand/rand.c', 'OpenSSL/util.c']
  31. rand_dep = ['OpenSSL/util.h']
  32. ssl_src = ['OpenSSL/ssl/connection.c', 'OpenSSL/ssl/context.c', 'OpenSSL/ssl/ssl.c',
  33. 'OpenSSL/util.c']
  34. ssl_dep = ['OpenSSL/ssl/connection.h', 'OpenSSL/ssl/context.h', 'OpenSSL/ssl/ssl.h',
  35. 'OpenSSL/util.h']
  36. IncludeDirs = None
  37. LibraryDirs = None
  38. # Add more platforms here when needed
  39. if os.name == 'nt' or sys.platform == 'win32':
  40. Libraries = ['Ws2_32']
  41. class BuildExtension(build_ext):
  42. """
  43. A custom command that semiautomatically finds dependencies required by
  44. PyOpenSSL.
  45. """
  46. user_options = (build_ext.user_options +
  47. [("with-openssl=", None,
  48. "directory where OpenSSL is installed")])
  49. with_openssl = None
  50. openssl_dlls = ()
  51. openssl_mingw = False
  52. def finalize_options(self):
  53. """
  54. Update build options with details about OpenSSL.
  55. """
  56. build_ext.finalize_options(self)
  57. if self.with_openssl is None:
  58. self.find_openssl()
  59. self.find_openssl_dlls()
  60. self.add_openssl_compile_info()
  61. def find_openssl(self):
  62. """
  63. Find OpenSSL's install directory.
  64. """
  65. potentials = []
  66. dirs = os.environ.get("PATH").split(os.pathsep)
  67. for d in dirs:
  68. if os.path.exists(os.path.join(d, "openssl.exe")):
  69. ssldir, bin = os.path.split(d)
  70. if not bin:
  71. ssldir, bin = os.path.split(ssldir)
  72. potentials.append(ssldir)
  73. childdirs = os.listdir(ssldir)
  74. if "lib" in childdirs and "include" in childdirs:
  75. self.with_openssl = ssldir
  76. return
  77. if potentials:
  78. raise DistutilsFileError(
  79. "Only found improper OpenSSL directories: %r" % (
  80. potentials,))
  81. else:
  82. raise DistutilsFileError("Could not find 'openssl.exe'")
  83. def find_openssl_dlls(self):
  84. """
  85. Find OpenSSL's shared libraries.
  86. """
  87. self.openssl_dlls = []
  88. self.find_openssl_dll("libssl32.dll", False)
  89. if self.openssl_dlls:
  90. self.openssl_mingw = True
  91. else:
  92. self.find_openssl_dll("ssleay32.dll", True)
  93. self.find_openssl_dll("libeay32.dll", True)
  94. # add zlib to the mix if it looks like OpenSSL
  95. # was linked with a private copy of it
  96. self.find_openssl_dll("zlib1.dll", False)
  97. def find_openssl_dll(self, name, required):
  98. """
  99. Find OpenSSL's shared library and its path after installation.
  100. """
  101. dllpath = os.path.join(self.with_openssl, "bin", name)
  102. if not os.path.exists(dllpath):
  103. if required:
  104. raise DistutilsFileError("could not find '%s'" % name)
  105. else:
  106. return
  107. newpath = os.path.join(self.build_lib, "OpenSSL", name)
  108. self.openssl_dlls.append((dllpath, newpath))
  109. def add_openssl_compile_info(self):
  110. """
  111. Set up various compile and link parameters.
  112. """
  113. if self.compiler == "mingw32":
  114. if self.openssl_mingw:
  115. # Library path and library names are sane when OpenSSL is
  116. # built with MinGW .
  117. libdir = "lib"
  118. libs = ["eay32", "ssl32"]
  119. else:
  120. libdir = ""
  121. libs = []
  122. # Unlike when using the binary installer, which creates
  123. # an atypical shared library name 'ssleay32', so we have
  124. # to use this workaround.
  125. if self.link_objects is None:
  126. self.link_objects = []
  127. for dllpath, _ in self.openssl_dlls:
  128. dllname = os.path.basename(dllpath)
  129. libname = os.path.splitext(dllname)[0] + ".a"
  130. libpath = os.path.join(self.with_openssl,
  131. "lib", "MinGW", libname)
  132. self.link_objects.append(libpath)
  133. else:
  134. libdir = "lib"
  135. libs = ["libeay32", "ssleay32"]
  136. self.include_dirs.append(os.path.join(self.with_openssl, "include"))
  137. self.library_dirs.append(os.path.join(self.with_openssl, libdir))
  138. self.libraries.extend(libs)
  139. def run(self):
  140. """
  141. Build extension modules and copy shared libraries.
  142. """
  143. build_ext.run(self)
  144. for dllpath, newpath in self.openssl_dlls:
  145. self.copy_file(dllpath, newpath)
  146. def get_outputs(self):
  147. """
  148. Return a list of file paths built by this comand.
  149. """
  150. output = [pathpair[1] for pathpair in self.openssl_dlls]
  151. output.extend(build_ext.get_outputs(self))
  152. return output
  153. else:
  154. Libraries = ['ssl', 'crypto']
  155. BuildExtension = build_ext
  156. def mkExtension(name):
  157. modname = 'OpenSSL.' + name
  158. src = globals()[name.lower() + '_src']
  159. dep = globals()[name.lower() + '_dep']
  160. return Extension(modname, src, libraries=Libraries, depends=dep,
  161. include_dirs=IncludeDirs, library_dirs=LibraryDirs)
  162. setup(name='pyOpenSSL', version=__version__,
  163. packages = ['OpenSSL'],
  164. package_dir = {'OpenSSL': 'OpenSSL'},
  165. ext_modules = [mkExtension('crypto'), mkExtension('rand'),
  166. mkExtension('SSL')],
  167. py_modules = ['OpenSSL.__init__', 'OpenSSL.tsafe',
  168. 'OpenSSL.version', 'OpenSSL.test.__init__',
  169. 'OpenSSL.test.util',
  170. 'OpenSSL.test.test_crypto',
  171. 'OpenSSL.test.test_rand',
  172. 'OpenSSL.test.test_ssl'],
  173. zip_safe = False,
  174. cmdclass = {"build_ext": BuildExtension},
  175. description = 'Python wrapper module around the OpenSSL library',
  176. author = 'Martin Sjögren, AB Strakt',
  177. author_email = 'msjogren@gmail.com',
  178. maintainer = 'Jean-Paul Calderone',
  179. maintainer_email = 'exarkun@twistedmatrix.com',
  180. url = 'http://pyopenssl.sourceforge.net/',
  181. license = 'LGPL',
  182. long_description = """\
  183. High-level wrapper around a subset of the OpenSSL library, includes
  184. * SSL.Connection objects, wrapping the methods of Python's portable
  185. sockets
  186. * Callbacks written in Python
  187. * Extensive error-handling mechanism, mirroring OpenSSL's error codes
  188. ... and much more ;)"""
  189. )