LINTIAN_OPTS is now a string
[pysqlcipher.git] / setup.py
1 #-*- coding: ISO-8859-1 -*-
2 # setup.py: the distutils script
3 #
4 # Copyright (C) 2013 Kali Kaneko <kali@futeisha.org> (sqlcipher support)
5 # Copyright (C) 2005-2010 Gerhard Häring <gh@ghaering.de>
6 #
7 # This file is part of pysqlcipher.
8 #
9 # This software is provided 'as-is', without any express or implied
10 # warranty.  In no event will the authors be held liable for any damages
11 # arising from the use of this software.
12 #
13 # Permission is granted to anyone to use this software for any purpose,
14 # including commercial applications, and to alter it and redistribute it
15 # freely, subject to the following restrictions:
16 #
17 # 1. The origin of this software must not be misrepresented; you must not
18 #    claim that you wrote the original software. If you use this software
19 #    in a product, an acknowledgment in the product documentation would be
20 #    appreciated but is not required.
21 # 2. Altered source versions must be plainly marked as such, and must not be
22 #    misrepresented as being the original software.
23 # 3. This notice may not be removed or altered from any source distribution.
24 import os
25 import re
26 import sys
27 import urllib
28 import zipfile
29
30 from types import ListType, TupleType
31
32 from distutils.command.build import build
33 from distutils.command.build_ext import build_ext
34 from distutils.dep_util import newer_group
35 from distutils.errors import DistutilsSetupError
36 from distutils import log
37
38 import setuptools
39 from setuptools import Extension, Command
40
41 import cross_bdist_wininst
42
43 # If you need to change anything, it should be enough to change setup.cfg.
44
45 sqlite = "sqlite"
46
47 PYSQLITE_EXPERIMENTAL = False
48
49 DEV_VERSION = None
50
51 PATCH_VERSION = None
52
53 sources = ["src/module.c", "src/connection.c", "src/cursor.c", "src/cache.c",
54            "src/microprotocols.c", "src/prepare_protocol.c", "src/statement.c",
55            "src/util.c", "src/row.c", "src/blob.c"]
56
57 if PYSQLITE_EXPERIMENTAL:
58     sources.append("src/backup.c")
59
60
61 if sys.platform == "darwin":
62     # Work around clang raising hard error for unused arguments
63     os.environ['CFLAGS'] = "-Qunused-arguments"
64     print "CFLAGS", os.environ['CFLAGS']
65
66 include_dirs = []
67 library_dirs = []
68 libraries = []
69 runtime_library_dirs = []
70 extra_objects = []
71 define_macros = []
72
73 long_description = \
74 """Python interface to SQLCipher
75
76 pysqlcipher is an interface to the SQLite 3.x embedded relational
77 database engine. It is almost fully compliant with the Python database API
78 version 2.0. At the same time, it also exposes the unique features of
79 SQLCipher."""
80
81 if sys.platform != "win32":
82     define_macros.append(('MODULE_NAME', '"pysqlcipher.dbapi2"'))
83 else:
84     define_macros.append(('MODULE_NAME', '\\"pysqlcipher.dbapi2\\"'))
85
86 BUNDLED = False
87 AMALGAMATION_ROOT = "amalgamation"
88
89 for idx, arg in enumerate(list(sys.argv)):
90     if arg.startswith('--bundled'):
91         sys.argv.pop(idx)
92         BUNDLED = True
93         break
94     if arg.startswith('--amalgamation='):
95         AMALGAMATION_ROOT = arg.split("=",1)[1]
96         break
97
98
99 class DocBuilder(Command):
100     description = "Builds the documentation"
101     user_options = []
102
103     def initialize_options(self):
104         pass
105
106     def finalize_options(self):
107         pass
108
109     def run(self):
110         import shutil
111         try:
112             shutil.rmtree("build/doc")
113         except OSError:
114             pass
115         os.makedirs("build/doc")
116         rc = os.system("sphinx-build doc/sphinx build/doc")
117         if rc != 0:
118             print ("Is sphinx installed? If not, "
119                    "try 'sudo easy_install sphinx'.")
120
121
122 class LibSQLCipherBuilder(build_ext):
123
124     description = ("Build C extension linking against libsqlcipher library.")
125
126     def build_extension(self, ext):
127         ext.extra_compile_args.append("-I/usr/include/sqlcipher/")
128         ext.extra_link_args.append("-lsqlcipher")
129         build_ext.build_extension(self, ext)
130
131
132 class AmalgamationBuildExt(build_ext):
133     
134     amalgamation = True
135
136     def build_extension(self, ext):
137         # build with fulltext search enabled
138         ext.define_macros.append(
139             ("SQLITE_ENABLE_FTS3", "1"))
140         ext.define_macros.append(
141             ("SQLITE_ENABLE_FTS5", "1"))
142         ext.define_macros.append(
143             ("SQLITE_ENABLE_RTREE", "1"))
144
145         # SQLCipher options
146         ext.define_macros.append(
147             ("SQLITE_ENABLE_LOAD_EXTENSION", "1"))
148         ext.define_macros.append(
149             ("SQLITE_HAS_CODEC", "1"))
150         ext.define_macros.append(
151             ("SQLITE_TEMP_STORE", "2"))
152         ext.define_macros.append(
153             ("HAVE_USLEEP", "1"))
154
155         ext.sources.append(os.path.join(AMALGAMATION_ROOT, "sqlite3.c"))
156         ext.include_dirs.append(AMALGAMATION_ROOT)
157
158         if sys.platform == "win32":
159             # Try to locate openssl
160             openssl_conf = os.environ.get('OPENSSL_CONF')
161             if not openssl_conf:
162                 sys.exit('Fatal error: OpenSSL could not be detected!')
163             openssl = os.path.dirname(os.path.dirname(openssl_conf))
164
165             # Configure the compiler
166             ext.include_dirs.append(os.path.join(openssl, "include"))
167             ext.define_macros.append(("inline", "__inline"))
168
169             # Configure the linker
170             if self.compiler.compiler_type == "msvc":
171                 ext.extra_link_args.append("libeay32.lib")
172                 ext.extra_link_args.append(
173                     "/LIBPATH:" + os.path.join(openssl, "lib")
174                 )
175             if self.compiler.compiler_type == "mingw32":
176                 ext.extra_link_args.append("-lcrypto")
177         else:
178             ext.extra_link_args.append("-lcrypto")
179
180         build_ext.build_extension(self, ext)
181
182     def __setattr__(self, k, v):
183         # Make sure we don't link against the SQLite
184         # library, no matter what setup.cfg says
185         if self.amalgamation and k == "libraries":
186             v = None
187         self.__dict__[k] = v
188
189
190 def get_setup_args():
191
192     PYSQLITE_VERSION = None
193
194     version_re = re.compile('#define PYSQLITE_VERSION "(.*)"')
195     f = open(os.path.join("src", "module.h"))
196     for line in f:
197         match = version_re.match(line)
198         if match:
199             PYSQLITE_VERSION = match.groups()[0]
200             PYSQLITE_MINOR_VERSION = ".".join(PYSQLITE_VERSION.split('.')[:2])
201             break
202     f.close()
203
204     if not PYSQLITE_VERSION:
205         print "Fatal error: PYSQLITE_VERSION could not be detected!"
206         sys.exit(1)
207
208     if DEV_VERSION:
209         PYSQLITE_VERSION += ".dev%s" % DEV_VERSION
210
211     if PATCH_VERSION:
212         PYSQLITE_VERSION += "-%s" % PATCH_VERSION
213
214     # Need to bump minor version, patch handled badly.
215     PYSQLCIPHER_VERSION = "2.6.10"
216
217     setup_args = dict(
218         name="pysqlcipher",
219         #version=PYSQLITE_VERSION,
220         version=PYSQLCIPHER_VERSION,
221         description="DB-API 2.0 interface for SQLCIPHER 3.x",
222         long_description=long_description,
223         author="Kali Kaneko",
224         author_email="kali@leap.se",
225         license="zlib/libpng",
226         # XXX check
227         # It says MIT in the google project
228         platforms="ALL",
229         url="http://github.com/leapcode/pysqlcipher/",
230         # Description of the modules and packages in the distribution
231         package_dir={"pysqlcipher": "lib"},
232         packages=["pysqlcipher", "pysqlcipher.test"] +
233             (["pysqlcipher.test.py25"], [])[sys.version_info < (2, 5)],
234         scripts=[],
235         ext_modules=[
236             Extension(
237                 name="pysqlcipher._sqlite",
238                 sources=sources,
239                 include_dirs=include_dirs,
240                 library_dirs=library_dirs,
241                 runtime_library_dirs=runtime_library_dirs,
242                 libraries=libraries,
243                 extra_objects=extra_objects,
244                 define_macros=define_macros)
245         ],
246         classifiers=[
247             "Development Status :: 4 - Beta",
248             "Intended Audience :: Developers",
249             "License :: OSI Approved :: zlib/libpng License",
250             "Operating System :: MacOS :: MacOS X",
251             "Operating System :: Microsoft :: Windows",
252             "Operating System :: POSIX",
253             "Programming Language :: C",
254             "Programming Language :: Python",
255             "Topic :: Database :: Database Engines/Servers",
256             "Topic :: Software Development :: Libraries :: Python Modules"],
257         cmdclass={"build_docs": DocBuilder}
258     )
259
260
261     if BUNDLED:
262        build_ext = AmalgamationBuildExt
263     else:
264        build_ext = LibSQLCipherBuilder
265
266     setup_args['cmdclass'].update({'build_ext': build_ext})
267
268     setup_args['cmdclass'].update(
269         {"build_docs": DocBuilder,
270          "cross_bdist_wininst": cross_bdist_wininst.bdist_wininst})
271
272     return setup_args
273
274
275 def main():
276     setuptools.setup(**get_setup_args())
277
278 if __name__ == "__main__":
279     main()