8cb094e17c7c1e865386f485da791756996a64fe
[cython.git] / pyximport / pyxbuild.py
1 """Build a Pyrex file from .pyx source to .so loadable module using
2 the installed distutils infrastructure. Call:
3
4 out_fname = pyx_to_dll("foo.pyx")
5 """
6 import os
7 import sys
8
9 import distutils
10 from distutils.dist import Distribution
11 from distutils.errors import DistutilsArgError, DistutilsError, CCompilerError
12 from distutils.extension import Extension
13 from distutils.util import grok_environment_error
14 try:
15     from Cython.Distutils import build_ext
16     HAS_CYTHON = True
17 except ImportError:
18     HAS_CYTHON = False
19 import shutil
20
21 DEBUG = 0
22 def pyx_to_dll(filename, ext = None, force_rebuild = 0,
23                build_in_temp=False, pyxbuild_dir=None):
24     """Compile a PYX file to a DLL and return the name of the generated .so 
25        or .dll ."""
26     assert os.path.exists(filename), "Could not find %s" % os.path.abspath(filename)
27
28     path, name = os.path.split(filename)
29
30     if not ext:
31         modname, extension = os.path.splitext(name)
32         assert extension in (".pyx", ".py"), extension
33         if not HAS_CYTHON:
34             filename = filename[:-len(extension)] + '.c'
35         ext = Extension(name=modname, sources=[filename])
36
37     if not pyxbuild_dir:
38         pyxbuild_dir = os.path.join(path, "_pyxbld")
39
40     if DEBUG:
41         quiet = "--verbose"
42     else:
43         quiet = "--quiet"
44     args = [quiet, "build_ext"]
45     if force_rebuild:
46         args.append("--force")
47     if HAS_CYTHON and build_in_temp:
48         args.append("--pyrex-c-in-temp")
49     dist = Distribution({"script_name": None, "script_args": args})
50     if not dist.ext_modules:
51         dist.ext_modules = []
52     dist.ext_modules.append(ext)
53     if HAS_CYTHON:
54         dist.cmdclass = {'build_ext': build_ext}
55     build = dist.get_command_obj('build')
56     build.build_base = pyxbuild_dir
57
58     config_files = dist.find_config_files()
59     try: config_files.remove('setup.cfg')
60     except ValueError: pass
61     dist.parse_config_files(config_files)
62
63     try:
64         ok = dist.parse_command_line()
65     except DistutilsArgError:
66         raise
67
68     if DEBUG:
69         print("options (after parsing command line):")
70         dist.dump_option_dicts()
71     assert ok
72
73
74     try:
75         dist.run_commands()
76         return dist.get_command_obj("build_ext").get_outputs()[0]
77     except KeyboardInterrupt:
78         sys.exit(1)
79     except (IOError, os.error):
80         exc = sys.exc_info()[1]
81         error = grok_environment_error(exc)
82
83         if DEBUG:
84             sys.stderr.write(error + "\n")
85             raise
86         else:
87             raise RuntimeError(error)
88
89     except (DistutilsError, CCompilerError):
90         if DEBUG:
91             raise
92         else:
93             exc = sys.exc_info()[1]
94             raise RuntimeError(repr(exc))
95
96 if __name__=="__main__":
97     pyx_to_dll("dummy.pyx")
98     import test
99