2 # -*- coding: utf-8 -*-
4 # Copyright (C) AB Strakt 2001, All rights reserved
5 # Copyright (C) Jean-Paul Calderone 2008-2010, All rights reserved
9 Installation script for the OpenSSL module
13 from distutils.core import Extension, setup
14 from distutils.errors import DistutilsFileError
15 from distutils.command.build_ext import build_ext
17 # XXX Deduplicate this
20 crypto_src = ['OpenSSL/crypto/crypto.c', 'OpenSSL/crypto/x509.c',
21 'OpenSSL/crypto/x509name.c', 'OpenSSL/crypto/pkey.c',
22 'OpenSSL/crypto/x509store.c', 'OpenSSL/crypto/x509req.c',
23 'OpenSSL/crypto/x509ext.c', 'OpenSSL/crypto/pkcs7.c',
24 'OpenSSL/crypto/pkcs12.c', 'OpenSSL/crypto/netscape_spki.c',
25 'OpenSSL/crypto/revoked.c', 'OpenSSL/crypto/crl.c',
27 crypto_dep = ['OpenSSL/crypto/crypto.h', 'OpenSSL/crypto/x509.h',
28 'OpenSSL/crypto/x509name.h', 'OpenSSL/crypto/pkey.h',
29 'OpenSSL/crypto/x509store.h', 'OpenSSL/crypto/x509req.h',
30 'OpenSSL/crypto/x509ext.h', 'OpenSSL/crypto/pkcs7.h',
31 'OpenSSL/crypto/pkcs12.h', 'OpenSSL/crypto/netscape_spki.h',
32 'OpenSSL/crypto/revoked.h', 'OpenSSL/crypto/crl.h',
34 rand_src = ['OpenSSL/rand/rand.c', 'OpenSSL/util.c']
35 rand_dep = ['OpenSSL/util.h']
36 ssl_src = ['OpenSSL/ssl/connection.c', 'OpenSSL/ssl/context.c', 'OpenSSL/ssl/ssl.c',
38 ssl_dep = ['OpenSSL/ssl/connection.h', 'OpenSSL/ssl/context.h', 'OpenSSL/ssl/ssl.h',
44 # Add more platforms here when needed
45 if os.name == 'nt' or sys.platform == 'win32':
47 Libraries = ['Ws2_32']
51 class BuildExtension(build_ext):
53 A custom command that semiautomatically finds dependencies required by
57 user_options = (build_ext.user_options +
58 [("with-openssl=", None,
59 "directory where OpenSSL is installed")])
65 def finalize_options(self):
67 Update build options with details about OpenSSL.
69 build_ext.finalize_options(self)
70 if self.with_openssl is None:
72 self.find_openssl_dlls()
73 self.add_openssl_compile_info()
76 def find_openssl(self):
78 Find OpenSSL's install directory.
81 dirs = os.environ.get("PATH").split(os.pathsep)
83 if os.path.exists(os.path.join(d, "openssl.exe")):
84 ssldir, bin = os.path.split(d)
86 ssldir, bin = os.path.split(ssldir)
87 potentials.append(ssldir)
88 childdirs = os.listdir(ssldir)
89 if "lib" in childdirs and "include" in childdirs:
90 self.with_openssl = ssldir
93 raise DistutilsFileError(
94 "Only found improper OpenSSL directories: %r" % (
97 raise DistutilsFileError("Could not find 'openssl.exe'")
100 def find_openssl_dlls(self):
102 Find OpenSSL's shared libraries.
104 self.openssl_dlls = []
105 self.find_openssl_dll("libssl32.dll", False)
106 if self.openssl_dlls:
107 self.openssl_mingw = True
109 self.find_openssl_dll("ssleay32.dll", True)
110 self.find_openssl_dll("libeay32.dll", True)
111 # add zlib to the mix if it looks like OpenSSL
112 # was linked with a private copy of it
113 self.find_openssl_dll("zlib1.dll", False)
116 def find_openssl_dll(self, name, required):
118 Find OpenSSL's shared library and its path after installation.
120 dllpath = os.path.join(self.with_openssl, "bin", name)
121 if not os.path.exists(dllpath):
123 raise DistutilsFileError("could not find '%s'" % name)
126 newpath = os.path.join(self.build_lib, "OpenSSL", name)
127 self.openssl_dlls.append((dllpath, newpath))
130 def add_openssl_compile_info(self):
132 Set up various compile and link parameters.
134 if self.compiler == "mingw32":
135 if self.openssl_mingw:
136 # Library path and library names are sane when OpenSSL is
139 libs = ["eay32", "ssl32"]
143 # Unlike when using the binary installer, which creates
144 # an atypical shared library name 'ssleay32', so we have
145 # to use this workaround.
146 if self.link_objects is None:
147 self.link_objects = []
148 for dllpath, _ in self.openssl_dlls:
149 dllname = os.path.basename(dllpath)
150 libname = os.path.splitext(dllname)[0] + ".a"
151 libpath = os.path.join(self.with_openssl,
152 "lib", "MinGW", libname)
153 self.link_objects.append(libpath)
156 libs = ["libeay32", "ssleay32"]
157 self.include_dirs.append(os.path.join(self.with_openssl, "include"))
158 self.library_dirs.append(os.path.join(self.with_openssl, libdir))
159 self.libraries.extend(libs)
164 Build extension modules and copy shared libraries.
167 for dllpath, newpath in self.openssl_dlls:
168 self.copy_file(dllpath, newpath)
171 def get_outputs(self):
173 Return a list of file paths built by this comand.
175 output = [pathpair[1] for pathpair in self.openssl_dlls]
176 output.extend(build_ext.get_outputs(self))
182 Libraries = ['ssl', 'crypto']
183 BuildExtension = build_ext
187 def mkExtension(name):
188 modname = 'OpenSSL.' + name
189 src = globals()[name.lower() + '_src']
190 dep = globals()[name.lower() + '_dep']
191 return Extension(modname, src, libraries=Libraries, depends=dep,
192 include_dirs=IncludeDirs, library_dirs=LibraryDirs)
195 setup(name='pyOpenSSL', version=__version__,
196 packages = ['OpenSSL'],
197 package_dir = {'OpenSSL': 'OpenSSL'},
198 ext_modules = [mkExtension('crypto'), mkExtension('rand'),
200 py_modules = ['OpenSSL.__init__', 'OpenSSL.tsafe',
201 'OpenSSL.version', 'OpenSSL.test.__init__',
203 'OpenSSL.test.test_crypto',
204 'OpenSSL.test.test_rand',
205 'OpenSSL.test.test_ssl'],
207 cmdclass = {"build_ext": BuildExtension},
208 description = 'Python wrapper module around the OpenSSL library',
209 author = 'Martin Sjögren, AB Strakt',
210 author_email = 'msjogren@gmail.com',
211 maintainer = 'Jean-Paul Calderone',
212 maintainer_email = 'exarkun@twistedmatrix.com',
213 url = 'http://pyopenssl.sourceforge.net/',
215 long_description = """\
216 High-level wrapper around a subset of the OpenSSL library, includes
217 * SSL.Connection objects, wrapping the methods of Python's portable
219 * Callbacks written in Python
220 * Extensive error-handling mechanism, mirroring OpenSSL's error codes
221 ... and much more ;)"""