disabled compilation of Cython.Compiler.ParseTreeTransforms as it leads to hard crashes
[cython.git] / setup.py
1 from distutils.core import setup, Extension
2 from distutils.sysconfig import get_python_lib
3 import os, os.path
4 import sys
5
6 if 'sdist' in sys.argv and sys.platform != "win32" and sys.version_info >= (2,4):
7     # Record the current revision in .hgrev
8     import subprocess # os.popen is cleaner but deprecated
9     changeset = subprocess.Popen("hg identify --id --rev tip".split(),
10                                  stdout=subprocess.PIPE).stdout.read()
11     rev = changeset.decode('ISO-8859-1').strip()
12     hgrev = open('.hgrev', 'w')
13     hgrev.write(rev)
14     hgrev.close()
15
16 if sys.platform == "darwin":
17     # Don't create resource files on OS X tar.
18     os.environ['COPY_EXTENDED_ATTRIBUTES_DISABLE'] = 'true'
19     os.environ['COPYFILE_DISABLE'] = 'true'
20
21 setup_args = {}
22
23 def add_command_class(name, cls):
24     cmdclasses = setup_args.get('cmdclass', {})
25     cmdclasses[name] = cls
26     setup_args['cmdclass'] = cmdclasses
27
28 if sys.version_info[0] >= 3:
29     import lib2to3.refactor
30     from distutils.command.build_py \
31          import build_py_2to3 as build_py
32     # need to convert sources to Py3 on installation
33     fixers = [ fix for fix in lib2to3.refactor.get_fixers_from_package("lib2to3.fixes")
34                if fix.split('fix_')[-1] not in ('next',)
35                ]
36     build_py.fixer_names = fixers
37     add_command_class("build_py", build_py)
38
39 pxd_include_dirs = [
40     directory for directory, dirs, files in os.walk('Cython/Includes')
41     if '__init__.pyx' in files or '__init__.pxd' in files
42     or directory == 'Cython/Includes' or directory == 'Cython/Includes/Deprecated']
43
44 pxd_include_patterns = [
45     p+'/*.pxd' for p in pxd_include_dirs ] + [
46     p+'/*.pyx' for p in pxd_include_dirs ]
47
48 if sys.version_info < (2,4):
49     install_base_dir = get_python_lib(prefix='')
50     import glob
51     patterns = pxd_include_patterns + [
52         'Cython/Plex/*.pxd',
53         'Cython/Compiler/*.pxd',
54         'Cython/Runtime/*.pyx'
55         ]
56     setup_args['data_files'] = [
57         (os.path.dirname(os.path.join(install_base_dir, pattern)),
58          [ f for f in glob.glob(pattern) ])
59         for pattern in patterns
60         ]
61 else:
62     setup_args['package_data'] = {
63         'Cython.Plex'     : ['*.pxd'],
64         'Cython.Compiler' : ['*.pxd'],
65         'Cython.Runtime'  : ['*.pyx', '*.pxd'],
66         'Cython'          : [ p[7:] for p in pxd_include_patterns ],
67         }
68
69 # This dict is used for passing extra arguments that are setuptools 
70 # specific to setup
71 setuptools_extra_args = {}
72
73 if 'setuptools' in sys.modules:
74     setuptools_extra_args['zip_safe'] = False
75     setuptools_extra_args['entry_points'] = {
76         'console_scripts': [
77             'cython = Cython.Compiler.Main:setuptools_main',
78         ]
79     }
80     scripts = []
81 else:
82     if os.name == "posix":
83         scripts = ["bin/cython"]
84     else:
85         scripts = ["cython.py"]
86
87 def compile_cython_modules(profile=False):
88     source_root = os.path.abspath(os.path.dirname(__file__))
89     compiled_modules = ["Cython.Plex.Scanners",
90                         "Cython.Plex.Actions",
91                         "Cython.Compiler.Scanning",
92                         "Cython.Compiler.Parsing",
93                         "Cython.Compiler.Visitor",
94                         #"Cython.Compiler.ParseTreeTransforms",
95                         #"Cython.Compiler.Nodes",
96                         #"Cython.Compiler.ExprNodes",
97                         #"Cython.Compiler.ModuleNode",
98                         #"Cython.Compiler.Optimize",
99                         "Cython.Runtime.refnanny"]
100     extensions = []
101
102     if sys.version_info[0] >= 3:
103         from Cython.Distutils import build_ext as build_ext_orig
104         for module in compiled_modules:
105             source_file = os.path.join(source_root, *module.split('.'))
106             if os.path.exists(source_file + ".py"):
107                 pyx_source_file = source_file + ".py"
108             else:
109                 pyx_source_file = source_file + ".pyx"
110             dep_files = []
111             if os.path.exists(source_file + '.pxd'):
112                 dep_files.append(source_file + '.pxd')
113             extensions.append(
114                 Extension(module, sources = [pyx_source_file],
115                           depends = dep_files)
116                 )
117
118         class build_ext(build_ext_orig):
119             # we must keep the original modules alive to make sure
120             # their code keeps working when we remove them from
121             # sys.modules
122             dead_modules = []
123
124             def build_extensions(self):
125                 # add path where 2to3 installed the transformed sources
126                 # and make sure Python (re-)imports them from there
127                 already_imported = [ module for module in sys.modules
128                                      if module == 'Cython' or module.startswith('Cython.') ]
129                 keep_alive = self.dead_modules.append
130                 for module in already_imported:
131                     keep_alive(sys.modules[module])
132                     del sys.modules[module]
133                 sys.path.insert(0, os.path.join(source_root, self.build_lib))
134
135                 if profile:
136                     from Cython.Compiler.Options import directive_defaults
137                     directive_defaults['profile'] = True
138                     print("Enabled profiling for the Cython binary modules")
139                 build_ext_orig.build_extensions(self)
140
141         setup_args['ext_modules'] = extensions
142         add_command_class("build_ext", build_ext)
143
144     else: # Python 2.x
145         from distutils.command.build_ext import build_ext as build_ext_orig
146         try:
147             class build_ext(build_ext_orig):
148                 def build_extension(self, ext, *args, **kargs):
149                     try:
150                         build_ext_orig.build_extension(self, ext, *args, **kargs)
151                     except StandardError:
152                         print("Compilation of '%s' failed" % ext.sources[0])
153             from Cython.Compiler.Main import compile
154             from Cython import Utils
155             if profile:
156                 from Cython.Compiler.Options import directive_defaults
157                 directive_defaults['profile'] = True
158                 print("Enabled profiling for the Cython binary modules")
159             source_root = os.path.dirname(__file__)
160             for module in compiled_modules:
161                 source_file = os.path.join(source_root, *module.split('.'))
162                 if os.path.exists(source_file + ".py"):
163                     pyx_source_file = source_file + ".py"
164                 else:
165                     pyx_source_file = source_file + ".pyx"
166                 c_source_file = source_file + ".c"
167                 source_is_newer = False
168                 if not os.path.exists(c_source_file):
169                     source_is_newer = True
170                 else:
171                     c_last_modified = Utils.modification_time(c_source_file)
172                     if Utils.file_newer_than(pyx_source_file, c_last_modified):
173                         source_is_newer = True
174                     else:
175                         pxd_source_file = source_file + ".pxd"
176                         if os.path.exists(pxd_source_file) and Utils.file_newer_than(pxd_source_file, c_last_modified):
177                             source_is_newer = True
178                 if source_is_newer:
179                     print("Compiling module %s ..." % module)
180                     result = compile(pyx_source_file)
181                     c_source_file = result.c_file
182                 if c_source_file:
183                     # Py2 distutils can't handle unicode file paths
184                     if isinstance(c_source_file, unicode):
185                         filename_encoding = sys.getfilesystemencoding()
186                         if filename_encoding is None:
187                             filename_encoding = sys.getdefaultencoding()
188                         c_source_file = c_source_file.encode(filename_encoding)
189                     extensions.append(
190                         Extension(module, sources = [c_source_file])
191                         )
192                 else:
193                     print("Compilation failed")
194             if extensions:
195                 setup_args['ext_modules'] = extensions
196                 add_command_class("build_ext", build_ext)
197         except Exception:
198             print('''
199 ERROR: %s
200
201 Extension module compilation failed, looks like Cython cannot run
202 properly on this system.  To work around this, pass the option
203 "--no-cython-compile".  This will install a pure Python version of
204 Cython without compiling its own sources.
205 ''' % sys.exc_info()[1])
206             raise
207
208 cython_profile = '--cython-profile' in sys.argv
209 if cython_profile:
210     sys.argv.remove('--cython-profile')
211
212 try:
213     sys.argv.remove("--no-cython-compile")
214 except ValueError:
215     compile_cython_modules(cython_profile)
216
217 setup_args.update(setuptools_extra_args)
218
219 from Cython import __version__ as version
220
221 setup(
222   name = 'Cython',
223   version = version,
224   url = 'http://www.cython.org',
225   author = 'Greg Ewing, Robert Bradshaw, Stefan Behnel, Dag Seljebotn, et al.',
226   author_email = 'cython-dev@codespeak.net',
227   description = "The Cython compiler for writing C extensions for the Python language.",
228   long_description = """\
229   The Cython language makes writing C extensions for the Python language as
230   easy as Python itself.  Cython is a source code translator based on the
231   well-known Pyrex_, but supports more cutting edge functionality and
232   optimizations.
233
234   The Cython language is very close to the Python language (and most Python
235   code is also valid Cython code), but Cython additionally supports calling C
236   functions and declaring C types on variables and class attributes. This
237   allows the compiler to generate very efficient C code from Cython code.
238
239   This makes Cython the ideal language for writing glue code for external C
240   libraries, and for fast C modules that speed up the execution of Python
241   code.
242
243   .. _Pyrex: http://www.cosc.canterbury.ac.nz/greg.ewing/python/Pyrex/
244   """,
245   classifiers = [
246     "Development Status :: 5 - Production/Stable",
247     "Intended Audience :: Developers",
248     "License :: OSI Approved :: Apache Software License",
249     "Operating System :: OS Independent",
250     "Programming Language :: Python",
251     "Programming Language :: Python :: 2",
252     "Programming Language :: Python :: 3",
253     "Programming Language :: C",
254     "Programming Language :: Cython",
255     "Topic :: Software Development :: Code Generators",
256     "Topic :: Software Development :: Compilers",
257     "Topic :: Software Development :: Libraries :: Python Modules"
258   ],
259
260   scripts = scripts,
261   packages=[
262     'Cython',
263     'Cython.Build',
264     'Cython.Compiler',
265     'Cython.Runtime',
266     'Cython.Distutils',
267     'Cython.Plex',
268
269     'Cython.Tests',
270     'Cython.Compiler.Tests',
271     ],
272
273   # pyximport
274   py_modules = ["pyximport/__init__",
275                 "pyximport/pyximport",
276                 "pyximport/pyxbuild",
277
278                 "cython"],
279
280   **setup_args
281   )