1 """Build a Pyrex file from .pyx source to .so loadable module using
2 the installed distutils infrastructure. Call:
4 out_fname = pyx_to_dll("foo.pyx")
9 from distutils.dist import Distribution
10 from distutils.errors import DistutilsArgError, DistutilsError, CCompilerError
11 from distutils.extension import Extension
12 from distutils.util import grok_environment_error
14 from Cython.Distutils import build_ext
23 def pyx_to_dll(filename, ext = None, force_rebuild = 0,
24 build_in_temp=False, pyxbuild_dir=None, setup_args={}, reload_support=False):
25 """Compile a PYX file to a DLL and return the name of the generated .so
27 assert os.path.exists(filename), "Could not find %s" % os.path.abspath(filename)
29 path, name = os.path.split(filename)
32 modname, extension = os.path.splitext(name)
33 assert extension in (".pyx", ".py"), extension
35 filename = filename[:-len(extension)] + '.c'
36 ext = Extension(name=modname, sources=[filename])
39 pyxbuild_dir = os.path.join(path, "_pyxbld")
41 script_args=setup_args.get("script_args",[])
42 if DEBUG or "--verbose" in script_args:
46 args = [quiet, "build_ext"]
48 args.append("--force")
49 if HAS_CYTHON and build_in_temp:
50 args.append("--pyrex-c-in-temp")
51 sargs = setup_args.copy()
54 "script_args": args + script_args} )
55 dist = Distribution(sargs)
56 if not dist.ext_modules:
58 dist.ext_modules.append(ext)
60 dist.cmdclass = {'build_ext': build_ext}
61 build = dist.get_command_obj('build')
62 build.build_base = pyxbuild_dir
64 config_files = dist.find_config_files()
65 try: config_files.remove('setup.cfg')
66 except ValueError: pass
67 dist.parse_config_files(config_files)
69 cfgfiles = dist.find_config_files()
70 try: cfgfiles.remove('setup.cfg')
71 except ValueError: pass
72 dist.parse_config_files(cfgfiles)
74 ok = dist.parse_command_line()
75 except DistutilsArgError:
79 print("options (after parsing command line):")
80 dist.dump_option_dicts()
86 obj_build_ext = dist.get_command_obj("build_ext")
87 so_path = obj_build_ext.get_outputs()[0]
88 if obj_build_ext.inplace:
89 # Python distutils get_outputs()[ returns a wrong so_path
90 # when --inplace ; see http://bugs.python.org/issue5977
92 so_path = os.path.join(os.path.dirname(filename),
93 os.path.basename(so_path))
96 timestamp = os.path.getmtime(org_path)
98 last_timestamp, last_path, count = _reloads.get(org_path, (None,None,0) )
99 if last_timestamp == timestamp:
102 basename = os.path.basename(org_path)
105 r_path = os.path.join(obj_build_ext.build_lib,
106 basename + '.reload%s'%count)
108 import shutil # late import / reload_support is: debugging
109 shutil.copy2(org_path, r_path)
115 # used up all 100 slots
116 raise ImportError("reload count for %s reached maximum"%org_path)
117 _reloads[org_path]=(timestamp, so_path, count)
119 except KeyboardInterrupt:
121 except (IOError, os.error):
122 exc = sys.exc_info()[1]
123 error = grok_environment_error(exc)
126 sys.stderr.write(error + "\n")
129 if __name__=="__main__":
130 pyx_to_dll("dummy.pyx")