Restore variadic macros in DevToolsEmbedderMessageDispatcher
[chromium-blink-merge.git] / third_party / cython / src / pyximport / pyxbuild.py
blob82401cdbc921dff5733d90aa42065d624811ce11
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")
5 """
6 import os
7 import sys
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
13 try:
14 from Cython.Distutils import build_ext
15 HAS_CYTHON = True
16 except ImportError:
17 HAS_CYTHON = False
19 DEBUG = 0
21 _reloads={}
23 def pyx_to_dll(filename, ext = None, force_rebuild = 0,
24 build_in_temp=False, pyxbuild_dir=None, setup_args={},
25 reload_support=False, inplace=False):
26 """Compile a PYX file to a DLL and return the name of the generated .so
27 or .dll ."""
28 assert os.path.exists(filename), "Could not find %s" % os.path.abspath(filename)
30 path, name = os.path.split(os.path.abspath(filename))
32 if not ext:
33 modname, extension = os.path.splitext(name)
34 assert extension in (".pyx", ".py"), extension
35 if not HAS_CYTHON:
36 filename = filename[:-len(extension)] + '.c'
37 ext = Extension(name=modname, sources=[filename])
39 if not pyxbuild_dir:
40 pyxbuild_dir = os.path.join(path, "_pyxbld")
42 package_base_dir = path
43 for package_name in ext.name.split('.')[-2::-1]:
44 package_base_dir, pname = os.path.split(package_base_dir)
45 if pname != package_name:
46 # something is wrong - package path doesn't match file path
47 package_base_dir = None
48 break
50 script_args=setup_args.get("script_args",[])
51 if DEBUG or "--verbose" in script_args:
52 quiet = "--verbose"
53 else:
54 quiet = "--quiet"
55 args = [quiet, "build_ext"]
56 if force_rebuild:
57 args.append("--force")
58 if inplace and package_base_dir:
59 args.extend(['--build-lib', package_base_dir])
60 if ext.name == '__init__' or ext.name.endswith('.__init__'):
61 # package => provide __path__ early
62 if not hasattr(ext, 'cython_directives'):
63 ext.cython_directives = {'set_initial_path' : 'SOURCEFILE'}
64 elif 'set_initial_path' not in ext.cython_directives:
65 ext.cython_directives['set_initial_path'] = 'SOURCEFILE'
67 if HAS_CYTHON and build_in_temp:
68 args.append("--pyrex-c-in-temp")
69 sargs = setup_args.copy()
70 sargs.update(
71 {"script_name": None,
72 "script_args": args + script_args} )
73 dist = Distribution(sargs)
74 if not dist.ext_modules:
75 dist.ext_modules = []
76 dist.ext_modules.append(ext)
77 if HAS_CYTHON:
78 dist.cmdclass = {'build_ext': build_ext}
79 build = dist.get_command_obj('build')
80 build.build_base = pyxbuild_dir
82 config_files = dist.find_config_files()
83 try: config_files.remove('setup.cfg')
84 except ValueError: pass
85 dist.parse_config_files(config_files)
87 cfgfiles = dist.find_config_files()
88 try: cfgfiles.remove('setup.cfg')
89 except ValueError: pass
90 dist.parse_config_files(cfgfiles)
91 try:
92 ok = dist.parse_command_line()
93 except DistutilsArgError:
94 raise
96 if DEBUG:
97 print("options (after parsing command line):")
98 dist.dump_option_dicts()
99 assert ok
102 try:
103 obj_build_ext = dist.get_command_obj("build_ext")
104 dist.run_commands()
105 so_path = obj_build_ext.get_outputs()[0]
106 if obj_build_ext.inplace:
107 # Python distutils get_outputs()[ returns a wrong so_path
108 # when --inplace ; see http://bugs.python.org/issue5977
109 # workaround:
110 so_path = os.path.join(os.path.dirname(filename),
111 os.path.basename(so_path))
112 if reload_support:
113 org_path = so_path
114 timestamp = os.path.getmtime(org_path)
115 global _reloads
116 last_timestamp, last_path, count = _reloads.get(org_path, (None,None,0) )
117 if last_timestamp == timestamp:
118 so_path = last_path
119 else:
120 basename = os.path.basename(org_path)
121 while count < 100:
122 count += 1
123 r_path = os.path.join(obj_build_ext.build_lib,
124 basename + '.reload%s'%count)
125 try:
126 import shutil # late import / reload_support is: debugging
127 try:
128 # Try to unlink first --- if the .so file
129 # is mmapped by another process,
130 # overwriting its contents corrupts the
131 # loaded image (on Linux) and crashes the
132 # other process. On Windows, unlinking an
133 # open file just fails.
134 if os.path.isfile(r_path):
135 os.unlink(r_path)
136 except OSError:
137 continue
138 shutil.copy2(org_path, r_path)
139 so_path = r_path
140 except IOError:
141 continue
142 break
143 else:
144 # used up all 100 slots
145 raise ImportError("reload count for %s reached maximum"%org_path)
146 _reloads[org_path]=(timestamp, so_path, count)
147 return so_path
148 except KeyboardInterrupt:
149 sys.exit(1)
150 except (IOError, os.error):
151 exc = sys.exc_info()[1]
152 error = grok_environment_error(exc)
154 if DEBUG:
155 sys.stderr.write(error + "\n")
156 raise
158 if __name__=="__main__":
159 pyx_to_dll("dummy.pyx")
160 import test