Line number support
[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", "bin/cygdb"]
84     else:
85         scripts = ["cython.py", "cygdb.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.Compiler.Scanning",
91                         "Cython.Compiler.Parsing",
92                         "Cython.Compiler.Visitor",
93                         "Cython.Runtime.refnanny"]
94     extensions = []
95
96     if sys.version_info[0] >= 3:
97         from Cython.Distutils import build_ext as build_ext_orig
98         for module in compiled_modules:
99             source_file = os.path.join(source_root, *module.split('.'))
100             if os.path.exists(source_file + ".py"):
101                 pyx_source_file = source_file + ".py"
102             else:
103                 pyx_source_file = source_file + ".pyx"
104             extensions.append(
105                 Extension(module, sources = [pyx_source_file])
106                 )
107
108         class build_ext(build_ext_orig):
109             def build_extensions(self):
110                 # add path where 2to3 installed the transformed sources
111                 # and make sure Python (re-)imports them from there
112                 already_imported = [ module for module in sys.modules
113                                      if module == 'Cython' or module.startswith('Cython.') ]
114                 for module in already_imported:
115                     del sys.modules[module]
116                 sys.path.insert(0, os.path.join(source_root, self.build_lib))
117
118                 if profile:
119                     from Cython.Compiler.Options import directive_defaults
120                     directive_defaults['profile'] = True
121                     print("Enabled profiling for the Cython binary modules")
122                 build_ext_orig.build_extensions(self)
123
124         setup_args['ext_modules'] = extensions
125         add_command_class("build_ext", build_ext)
126
127     else: # Python 2.x
128         from distutils.command.build_ext import build_ext as build_ext_orig
129         try:
130             class build_ext(build_ext_orig):
131                 def build_extension(self, ext, *args, **kargs):
132                     try:
133                         build_ext_orig.build_extension(self, ext, *args, **kargs)
134                     except StandardError:
135                         print("Compilation of '%s' failed" % ext.sources[0])
136             from Cython.Compiler.Main import compile
137             from Cython import Utils
138             if profile:
139                 from Cython.Compiler.Options import directive_defaults
140                 directive_defaults['profile'] = True
141                 print("Enabled profiling for the Cython binary modules")
142             source_root = os.path.dirname(__file__)
143             for module in compiled_modules:
144                 source_file = os.path.join(source_root, *module.split('.'))
145                 if os.path.exists(source_file + ".py"):
146                     pyx_source_file = source_file + ".py"
147                 else:
148                     pyx_source_file = source_file + ".pyx"
149                 c_source_file = source_file + ".c"
150                 if not os.path.exists(c_source_file) or \
151                    Utils.file_newer_than(pyx_source_file,
152                                          Utils.modification_time(c_source_file)):
153                     print("Compiling module %s ..." % module)
154                     result = compile(pyx_source_file)
155                     c_source_file = result.c_file
156                 if c_source_file:
157                     # Py2 distutils can't handle unicode file paths
158                     if isinstance(c_source_file, unicode):
159                         filename_encoding = sys.getfilesystemencoding()
160                         if filename_encoding is None:
161                             filename_encoding = sys.getdefaultencoding()
162                         c_source_file = c_source_file.encode(filename_encoding)
163                     extensions.append(
164                         Extension(module, sources = [c_source_file])
165                         )
166                 else:
167                     print("Compilation failed")
168             if extensions:
169                 setup_args['ext_modules'] = extensions
170                 add_command_class("build_ext", build_ext)
171         except Exception:
172             print('''
173 ERROR: %s
174
175 Extension module compilation failed, looks like Cython cannot run
176 properly on this system.  To work around this, pass the option
177 "--no-cython-compile".  This will install a pure Python version of
178 Cython without compiling its own sources.
179 ''' % sys.exc_info()[1])
180             raise
181
182 cython_profile = '--cython-profile' in sys.argv
183 if cython_profile:
184     sys.argv.remove('--cython-profile')
185
186 try:
187     sys.argv.remove("--no-cython-compile")
188 except ValueError:
189     compile_cython_modules(cython_profile)
190
191 setup_args.update(setuptools_extra_args)
192
193 from Cython.Compiler.Version import version
194
195 setup(
196   name = 'Cython',
197   version = version,
198   url = 'http://www.cython.org',
199   author = 'Greg Ewing, Robert Bradshaw, Stefan Behnel, Dag Seljebotn, et al.',
200   author_email = 'cython-dev@codespeak.net',
201   description = "The Cython compiler for writing C extensions for the Python language.",
202   long_description = """\
203   The Cython language makes writing C extensions for the Python language as
204   easy as Python itself.  Cython is a source code translator based on the
205   well-known Pyrex_, but supports more cutting edge functionality and
206   optimizations.
207
208   The Cython language is very close to the Python language (and most Python
209   code is also valid Cython code), but Cython additionally supports calling C
210   functions and declaring C types on variables and class attributes. This
211   allows the compiler to generate very efficient C code from Cython code.
212
213   This makes Cython the ideal language for writing glue code for external C
214   libraries, and for fast C modules that speed up the execution of Python
215   code.
216
217   .. _Pyrex: http://www.cosc.canterbury.ac.nz/greg.ewing/python/Pyrex/
218   """,
219   classifiers = [
220     "Development Status :: 5 - Production/Stable",
221     "Intended Audience :: Developers",
222     "License :: OSI Approved :: Apache Software License",
223     "Operating System :: OS Independent",
224     "Programming Language :: Python",
225     "Programming Language :: Python :: 2",
226     "Programming Language :: Python :: 3",
227     "Programming Language :: C",
228     "Programming Language :: Cython",
229     "Topic :: Software Development :: Code Generators",
230     "Topic :: Software Development :: Compilers",
231     "Topic :: Software Development :: Libraries :: Python Modules"
232   ],
233
234   scripts = scripts,
235   packages=[
236     'Cython',
237     'Cython.Compiler',
238     'Cython.Runtime',
239     'Cython.Distutils',
240     'Cython.Plex',
241     'Cython.Debugger',
242     'Cython.Tests',
243     'Cython.Compiler.Tests',
244     ],
245
246   # pyximport
247   py_modules = ["pyximport/__init__",
248                 "pyximport/pyximport",
249                 "pyximport/pyxbuild",
250
251                 "cython"],
252
253   **setup_args
254   )