Cython has moved to github.
cython-devel
view Cython/Compiler/Main.py @ 1470:49a8357fc01e
fixed FlattenInListTransform by providing a temp block expression that injects the temp result into a subexpression
| author | Stefan Behnel <scoder@users.berlios.de> |
|---|---|
| date | Sun Dec 07 21:14:13 2008 +0100 (3 years ago) |
| parents | 852db6ea1af1 |
| children | 8a2e7b51e770 |
line source
1 #
2 # Cython Top Level
3 #
5 import os, sys, re, codecs
6 if sys.version_info[:2] < (2, 3):
7 sys.stderr.write("Sorry, Cython requires Python 2.3 or later\n")
8 sys.exit(1)
10 try:
11 set
12 except NameError:
13 # Python 2.3
14 from sets import Set as set
16 from time import time
17 import Code
18 import Errors
19 import Parsing
20 import Version
21 from Scanning import PyrexScanner, FileSourceDescriptor
22 from Errors import PyrexError, CompileError, InternalError, error
23 from Symtab import BuiltinScope, ModuleScope
24 from Cython import Utils
25 from Cython.Utils import open_new_file, replace_suffix
26 import CythonScope
28 module_name_pattern = re.compile(r"[A-Za-z_][A-Za-z0-9_]*(\.[A-Za-z_][A-Za-z0-9_]*)*$")
30 verbose = 0
32 def dumptree(t):
33 # For quick debugging in pipelines
34 print t.dump()
35 return t
37 class CompilationData:
38 # Bundles the information that is passed from transform to transform.
39 # (For now, this is only)
41 # While Context contains every pxd ever loaded, path information etc.,
42 # this only contains the data related to a single compilation pass
43 #
44 # pyx ModuleNode Main code tree of this compilation.
45 # pxds {string : ModuleNode} Trees for the pxds used in the pyx.
46 # codewriter CCodeWriter Where to output final code.
47 # options CompilationOptions
48 # result CompilationResult
49 pass
51 class Context:
52 # This class encapsulates the context needed for compiling
53 # one or more Cython implementation files along with their
54 # associated and imported declaration files. It includes
55 # the root of the module import namespace and the list
56 # of directories to search for include files.
57 #
58 # modules {string : ModuleScope}
59 # include_directories [string]
60 # future_directives [object]
62 def __init__(self, include_directories, pragma_overrides):
63 #self.modules = {"__builtin__" : BuiltinScope()}
64 import Builtin, CythonScope
65 self.modules = {"__builtin__" : Builtin.builtin_scope}
66 self.modules["cython"] = CythonScope.create_cython_scope(self)
67 self.include_directories = include_directories
68 self.future_directives = set()
69 self.pragma_overrides = pragma_overrides
71 self.pxds = {} # full name -> node tree
73 standard_include_path = os.path.abspath(
74 os.path.join(os.path.dirname(__file__), '..', 'Includes'))
75 self.include_directories = include_directories + [standard_include_path]
77 def create_pipeline(self, pxd, py=False):
78 from Visitor import PrintTree
79 from ParseTreeTransforms import WithTransform, NormalizeTree, PostParse, PxdPostParse
80 from ParseTreeTransforms import AnalyseDeclarationsTransform, AnalyseExpressionsTransform
81 from ParseTreeTransforms import CreateClosureClasses, MarkClosureVisitor, DecoratorTransform
82 from ParseTreeTransforms import InterpretCompilerDirectives, TransformBuiltinMethods
83 from ParseTreeTransforms import AlignFunctionDefinitions
84 from AutoDocTransforms import EmbedSignature
85 from Optimize import FlattenInListTransform, SwitchTransform, DictIterTransform
86 from Optimize import FlattenBuiltinTypeCreation, FinalOptimizePhase
87 from Buffer import IntroduceBufferAuxiliaryVars
88 from ModuleNode import check_c_declarations
90 # Temporary hack that can be used to ensure that all result_code's
91 # are generated at code generation time.
92 import Visitor
93 class ClearResultCodes(Visitor.CythonTransform):
94 def visit_ExprNode(self, node):
95 self.visitchildren(node)
96 node.result_code = "<cleared>"
97 return node
99 if pxd:
100 _check_c_declarations = None
101 _specific_post_parse = PxdPostParse(self)
102 else:
103 _check_c_declarations = check_c_declarations
104 _specific_post_parse = None
106 if py and not pxd:
107 _align_function_definitions = AlignFunctionDefinitions(self)
108 else:
109 _align_function_definitions = None
111 return [
112 NormalizeTree(self),
113 PostParse(self),
114 _specific_post_parse,
115 InterpretCompilerDirectives(self, self.pragma_overrides),
116 _align_function_definitions,
117 FlattenInListTransform(),
118 WithTransform(self),
119 DecoratorTransform(self),
120 AnalyseDeclarationsTransform(self),
121 EmbedSignature(self),
122 TransformBuiltinMethods(self),
123 IntroduceBufferAuxiliaryVars(self),
124 _check_c_declarations,
125 AnalyseExpressionsTransform(self),
126 FlattenBuiltinTypeCreation(),
127 DictIterTransform(),
128 SwitchTransform(),
129 FinalOptimizePhase(self),
130 # ClearResultCodes(self),
131 # SpecialFunctions(self),
132 # CreateClosureClasses(context),
133 ]
135 def create_pyx_pipeline(self, options, result, py=False):
136 def generate_pyx_code(module_node):
137 module_node.process_implementation(options, result)
138 result.compilation_source = module_node.compilation_source
139 return result
141 def inject_pxd_code(module_node):
142 from textwrap import dedent
143 stats = module_node.body.stats
144 for name, (statlistnode, scope) in self.pxds.iteritems():
145 # Copy over function nodes to the module
146 # (this seems strange -- I believe the right concept is to split
147 # ModuleNode into a ModuleNode and a CodeGenerator, and tell that
148 # CodeGenerator to generate code both from the pyx and pxd ModuleNodes.
149 stats.append(statlistnode)
150 # Until utility code is moved to code generation phase everywhere,
151 # we need to copy it over to the main scope
152 module_node.scope.utility_code_list.extend(scope.utility_code_list)
153 return module_node
155 return ([
156 create_parse(self),
157 ] + self.create_pipeline(pxd=False, py=py) + [
158 inject_pxd_code,
159 generate_pyx_code,
160 ])
162 def create_pxd_pipeline(self, scope, module_name):
163 def parse_pxd(source_desc):
164 tree = self.parse(source_desc, scope, pxd=True,
165 full_module_name=module_name)
166 tree.scope = scope
167 tree.is_pxd = True
168 return tree
170 from CodeGeneration import ExtractPxdCode
172 # The pxd pipeline ends up with a CCodeWriter containing the
173 # code of the pxd, as well as a pxd scope.
174 return [parse_pxd] + self.create_pipeline(pxd=True) + [
175 ExtractPxdCode(self),
176 ]
178 def create_py_pipeline(self, options, result):
179 return self.create_pyx_pipeline(options, result, py=True)
182 def process_pxd(self, source_desc, scope, module_name):
183 pipeline = self.create_pxd_pipeline(scope, module_name)
184 result = self.run_pipeline(pipeline, source_desc)
185 return result
187 def nonfatal_error(self, exc):
188 return Errors.report_error(exc)
190 def run_pipeline(self, pipeline, source):
191 err = None
192 data = source
193 try:
194 for phase in pipeline:
195 if phase is not None:
196 data = phase(data)
197 except CompileError, err:
198 # err is set
199 Errors.report_error(err)
200 except InternalError, err:
201 # Only raise if there was not an earlier error
202 if Errors.num_errors == 0:
203 raise
204 return (err, data)
206 def find_module(self, module_name,
207 relative_to = None, pos = None, need_pxd = 1):
208 # Finds and returns the module scope corresponding to
209 # the given relative or absolute module name. If this
210 # is the first time the module has been requested, finds
211 # the corresponding .pxd file and process it.
212 # If relative_to is not None, it must be a module scope,
213 # and the module will first be searched for relative to
214 # that module, provided its name is not a dotted name.
215 debug_find_module = 0
216 if debug_find_module:
217 print("Context.find_module: module_name = %s, relative_to = %s, pos = %s, need_pxd = %s" % (
218 module_name, relative_to, pos, need_pxd))
220 scope = None
221 pxd_pathname = None
222 if not module_name_pattern.match(module_name):
223 if pos is None:
224 pos = (module_name, 0, 0)
225 raise CompileError(pos,
226 "'%s' is not a valid module name" % module_name)
227 if "." not in module_name and relative_to:
228 if debug_find_module:
229 print("...trying relative import")
230 scope = relative_to.lookup_submodule(module_name)
231 if not scope:
232 qualified_name = relative_to.qualify_name(module_name)
233 pxd_pathname = self.find_pxd_file(qualified_name, pos)
234 if pxd_pathname:
235 scope = relative_to.find_submodule(module_name)
236 if not scope:
237 if debug_find_module:
238 print("...trying absolute import")
239 scope = self
240 for name in module_name.split("."):
241 scope = scope.find_submodule(name)
242 if debug_find_module:
243 print("...scope =", scope)
244 if not scope.pxd_file_loaded:
245 if debug_find_module:
246 print("...pxd not loaded")
247 scope.pxd_file_loaded = 1
248 if not pxd_pathname:
249 if debug_find_module:
250 print("...looking for pxd file")
251 pxd_pathname = self.find_pxd_file(module_name, pos)
252 if debug_find_module:
253 print("......found ", pxd_pathname)
254 if not pxd_pathname and need_pxd:
255 error(pos, "'%s.pxd' not found" % module_name)
256 if pxd_pathname:
257 try:
258 if debug_find_module:
259 print("Context.find_module: Parsing %s" % pxd_pathname)
260 source_desc = FileSourceDescriptor(pxd_pathname)
261 err, result = self.process_pxd(source_desc, scope, module_name)
262 if err:
263 raise err
264 (pxd_codenodes, pxd_scope) = result
265 self.pxds[module_name] = (pxd_codenodes, pxd_scope)
266 except CompileError:
267 pass
268 return scope
270 def find_pxd_file(self, qualified_name, pos):
271 # Search include path for the .pxd file corresponding to the
272 # given fully-qualified module name.
273 # Will find either a dotted filename or a file in a
274 # package directory. If a source file position is given,
275 # the directory containing the source file is searched first
276 # for a dotted filename, and its containing package root
277 # directory is searched first for a non-dotted filename.
278 return self.search_include_directories(qualified_name, ".pxd", pos)
280 def find_pyx_file(self, qualified_name, pos):
281 # Search include path for the .pyx file corresponding to the
282 # given fully-qualified module name, as for find_pxd_file().
283 return self.search_include_directories(qualified_name, ".pyx", pos)
285 def find_include_file(self, filename, pos):
286 # Search list of include directories for filename.
287 # Reports an error and returns None if not found.
288 path = self.search_include_directories(filename, "", pos,
289 include=True)
290 if not path:
291 error(pos, "'%s' not found" % filename)
292 return path
294 def search_include_directories(self, qualified_name, suffix, pos,
295 include=False):
296 # Search the list of include directories for the given
297 # file name. If a source file position is given, first
298 # searches the directory containing that file. Returns
299 # None if not found, but does not report an error.
300 # The 'include' option will disable package dereferencing.
301 dirs = self.include_directories
302 if pos:
303 file_desc = pos[0]
304 if not isinstance(file_desc, FileSourceDescriptor):
305 raise RuntimeError("Only file sources for code supported")
306 if include:
307 dirs = [os.path.dirname(file_desc.filename)] + dirs
308 else:
309 dirs = [self.find_root_package_dir(file_desc.filename)] + dirs
311 dotted_filename = qualified_name + suffix
312 if not include:
313 names = qualified_name.split('.')
314 package_names = names[:-1]
315 module_name = names[-1]
316 module_filename = module_name + suffix
317 package_filename = "__init__" + suffix
319 for dir in dirs:
320 path = os.path.join(dir, dotted_filename)
321 if os.path.exists(path):
322 return path
323 if not include:
324 package_dir = self.check_package_dir(dir, package_names)
325 if package_dir is not None:
326 path = os.path.join(package_dir, module_filename)
327 if os.path.exists(path):
328 return path
329 path = os.path.join(dir, package_dir, module_name,
330 package_filename)
331 if os.path.exists(path):
332 return path
333 return None
335 def find_root_package_dir(self, file_path):
336 dir = os.path.dirname(file_path)
337 while self.is_package_dir(dir):
338 parent = os.path.dirname(dir)
339 if parent == dir:
340 break
341 dir = parent
342 return dir
344 def is_package_dir(self, dir):
345 package_init = os.path.join(dir, "__init__.py")
346 return os.path.exists(package_init) or \
347 os.path.exists(package_init + "x") # same with .pyx
349 def check_package_dir(self, dir, package_names):
350 package_dir = os.path.join(dir, *package_names)
351 if not os.path.exists(package_dir):
352 return None
353 for dirname in package_names:
354 dir = os.path.join(dir, dirname)
355 if not self.is_package_dir(dir):
356 return None
357 return package_dir
359 def c_file_out_of_date(self, source_path):
360 c_path = Utils.replace_suffix(source_path, ".c")
361 if not os.path.exists(c_path):
362 return 1
363 c_time = Utils.modification_time(c_path)
364 if Utils.file_newer_than(source_path, c_time):
365 return 1
366 pos = [source_path]
367 pxd_path = Utils.replace_suffix(source_path, ".pxd")
368 if os.path.exists(pxd_path) and Utils.file_newer_than(pxd_path, c_time):
369 return 1
370 for kind, name in self.read_dependency_file(source_path):
371 if kind == "cimport":
372 dep_path = self.find_pxd_file(name, pos)
373 elif kind == "include":
374 dep_path = self.search_include_directories(name, pos)
375 else:
376 continue
377 if dep_path and Utils.file_newer_than(dep_path, c_time):
378 return 1
379 return 0
381 def find_cimported_module_names(self, source_path):
382 return [ name for kind, name in self.read_dependency_file(source_path)
383 if kind == "cimport" ]
385 def is_package_dir(self, dir_path):
386 # Return true if the given directory is a package directory.
387 for filename in ("__init__.py", "__init__.pyx"):
388 path = os.path.join(dir_path, filename)
389 if os.path.exists(path):
390 return 1
392 def read_dependency_file(self, source_path):
393 dep_path = Utils.replace_suffix(source_path, ".dep")
394 if os.path.exists(dep_path):
395 f = open(dep_path, "rU")
396 chunks = [ line.strip().split(" ", 1)
397 for line in f.readlines()
398 if " " in line.strip() ]
399 f.close()
400 return chunks
401 else:
402 return ()
404 def lookup_submodule(self, name):
405 # Look up a top-level module. Returns None if not found.
406 return self.modules.get(name, None)
408 def find_submodule(self, name):
409 # Find a top-level module, creating a new one if needed.
410 scope = self.lookup_submodule(name)
411 if not scope:
412 scope = ModuleScope(name,
413 parent_module = None, context = self)
414 self.modules[name] = scope
415 return scope
417 def parse(self, source_desc, scope, pxd, full_module_name):
418 if not isinstance(source_desc, FileSourceDescriptor):
419 raise RuntimeError("Only file sources for code supported")
420 source_filename = Utils.encode_filename(source_desc.filename)
421 # Parse the given source file and return a parse tree.
422 try:
423 f = Utils.open_source_file(source_filename, "rU")
424 try:
425 s = PyrexScanner(f, source_desc, source_encoding = f.encoding,
426 scope = scope, context = self)
427 tree = Parsing.p_module(s, pxd, full_module_name)
428 finally:
429 f.close()
430 except UnicodeDecodeError, msg:
431 #import traceback
432 #traceback.print_exc()
433 error((source_desc, 0, 0), "Decoding error, missing or incorrect coding=<encoding-name> at top of source (%s)" % msg)
434 if Errors.num_errors > 0:
435 raise CompileError
436 return tree
438 def extract_module_name(self, path, options):
439 # Find fully_qualified module name from the full pathname
440 # of a source file.
441 dir, filename = os.path.split(path)
442 module_name, _ = os.path.splitext(filename)
443 if "." in module_name:
444 return module_name
445 if module_name == "__init__":
446 dir, module_name = os.path.split(dir)
447 names = [module_name]
448 while self.is_package_dir(dir):
449 parent, package_name = os.path.split(dir)
450 if parent == dir:
451 break
452 names.append(package_name)
453 dir = parent
454 names.reverse()
455 return ".".join(names)
457 def setup_errors(self, options):
458 if options.use_listing_file:
459 result.listing_file = Utils.replace_suffix(source, ".lis")
460 Errors.open_listing_file(result.listing_file,
461 echo_to_stderr = options.errors_to_stderr)
462 else:
463 Errors.open_listing_file(None)
465 def teardown_errors(self, err, options, result):
466 source_desc = result.compilation_source.source_desc
467 if not isinstance(source_desc, FileSourceDescriptor):
468 raise RuntimeError("Only file sources for code supported")
469 Errors.close_listing_file()
470 result.num_errors = Errors.num_errors
471 if result.num_errors > 0:
472 err = True
473 if err and result.c_file:
474 try:
475 Utils.castrate_file(result.c_file, os.stat(source_desc.filename))
476 except EnvironmentError:
477 pass
478 result.c_file = None
479 if result.c_file and not options.c_only and c_compile:
480 result.object_file = c_compile(result.c_file,
481 verbose_flag = options.show_version,
482 cplus = options.cplus)
483 if not options.obj_only and c_link:
484 result.extension_file = c_link(result.object_file,
485 extra_objects = options.objects,
486 verbose_flag = options.show_version,
487 cplus = options.cplus)
489 def create_parse(context):
490 def parse(compsrc):
491 source_desc = compsrc.source_desc
492 full_module_name = compsrc.full_module_name
493 initial_pos = (source_desc, 1, 0)
494 scope = context.find_module(full_module_name, pos = initial_pos, need_pxd = 0)
495 tree = context.parse(source_desc, scope, pxd = 0, full_module_name = full_module_name)
496 tree.compilation_source = compsrc
497 tree.scope = scope
498 tree.is_pxd = False
499 return tree
500 return parse
502 def create_default_resultobj(compilation_source, options):
503 result = CompilationResult()
504 result.main_source_file = compilation_source.source_desc.filename
505 result.compilation_source = compilation_source
506 source_desc = compilation_source.source_desc
507 if options.output_file:
508 result.c_file = os.path.join(compilation_source.cwd, options.output_file)
509 else:
510 if options.cplus:
511 c_suffix = ".cpp"
512 else:
513 c_suffix = ".c"
514 result.c_file = Utils.replace_suffix(source_desc.filename, c_suffix)
515 return result
517 def run_pipeline(source, options, full_module_name = None):
518 # Set up context
519 context = Context(options.include_path, options.pragma_overrides)
521 # Set up source object
522 cwd = os.getcwd()
523 source_desc = FileSourceDescriptor(os.path.join(cwd, source))
524 full_module_name = full_module_name or context.extract_module_name(source, options)
525 source = CompilationSource(source_desc, full_module_name, cwd)
527 # Set up result object
528 result = create_default_resultobj(source, options)
530 # Get pipeline
531 if source_desc.filename.endswith(".py"):
532 pipeline = context.create_py_pipeline(options, result)
533 else:
534 pipeline = context.create_pyx_pipeline(options, result)
536 context.setup_errors(options)
537 err, enddata = context.run_pipeline(pipeline, source)
538 context.teardown_errors(err, options, result)
539 return result
541 #------------------------------------------------------------------------
542 #
543 # Main Python entry points
544 #
545 #------------------------------------------------------------------------
547 class CompilationSource(object):
548 """
549 Contains the data necesarry to start up a compilation pipeline for
550 a single compilation unit.
551 """
552 def __init__(self, source_desc, full_module_name, cwd):
553 self.source_desc = source_desc
554 self.full_module_name = full_module_name
555 self.cwd = cwd
557 class CompilationOptions:
558 """
559 Options to the Cython compiler:
561 show_version boolean Display version number
562 use_listing_file boolean Generate a .lis file
563 errors_to_stderr boolean Echo errors to stderr when using .lis
564 include_path [string] Directories to search for include files
565 output_file string Name of generated .c file
566 generate_pxi boolean Generate .pxi file for public declarations
567 recursive boolean Recursively find and compile dependencies
568 timestamps boolean Only compile changed source files. If None,
569 defaults to true when recursive is true.
570 verbose boolean Always print source names being compiled
571 quiet boolean Don't print source names in recursive mode
572 pragma_overrides dict Overrides for pragma options (see Options.py)
574 Following options are experimental and only used on MacOSX:
576 c_only boolean Stop after generating C file (default)
577 obj_only boolean Stop after compiling to .o file
578 objects [string] Extra .o files to link with
579 cplus boolean Compile as c++ code
580 """
582 def __init__(self, defaults = None, c_compile = 0, c_link = 0, **kw):
583 self.include_path = []
584 self.objects = []
585 if defaults:
586 if isinstance(defaults, CompilationOptions):
587 defaults = defaults.__dict__
588 else:
589 defaults = default_options
590 self.__dict__.update(defaults)
591 self.__dict__.update(kw)
592 if c_compile:
593 self.c_only = 0
594 if c_link:
595 self.obj_only = 0
598 class CompilationResult:
599 """
600 Results from the Cython compiler:
602 c_file string or None The generated C source file
603 h_file string or None The generated C header file
604 i_file string or None The generated .pxi file
605 api_file string or None The generated C API .h file
606 listing_file string or None File of error messages
607 object_file string or None Result of compiling the C file
608 extension_file string or None Result of linking the object file
609 num_errors integer Number of compilation errors
610 compilation_source CompilationSource
611 """
613 def __init__(self):
614 self.c_file = None
615 self.h_file = None
616 self.i_file = None
617 self.api_file = None
618 self.listing_file = None
619 self.object_file = None
620 self.extension_file = None
621 self.main_source_file = None
624 class CompilationResultSet(dict):
625 """
626 Results from compiling multiple Pyrex source files. A mapping
627 from source file paths to CompilationResult instances. Also
628 has the following attributes:
630 num_errors integer Total number of compilation errors
631 """
633 num_errors = 0
635 def add(self, source, result):
636 self[source] = result
637 self.num_errors += result.num_errors
640 def compile_single(source, options, full_module_name = None):
641 """
642 compile_single(source, options, full_module_name)
644 Compile the given Pyrex implementation file and return a CompilationResult.
645 Always compiles a single file; does not perform timestamp checking or
646 recursion.
647 """
648 return run_pipeline(source, options, full_module_name)
651 def compile_multiple(sources, options):
652 """
653 compile_multiple(sources, options)
655 Compiles the given sequence of Pyrex implementation files and returns
656 a CompilationResultSet. Performs timestamp checking and/or recursion
657 if these are specified in the options.
658 """
659 sources = [os.path.abspath(source) for source in sources]
660 processed = set()
661 results = CompilationResultSet()
662 recursive = options.recursive
663 timestamps = options.timestamps
664 if timestamps is None:
665 timestamps = recursive
666 verbose = options.verbose or ((recursive or timestamps) and not options.quiet)
667 for source in sources:
668 if source not in processed:
669 # Compiling multiple sources in one context doesn't quite
670 # work properly yet.
671 if not timestamps or context.c_file_out_of_date(source):
672 if verbose:
673 sys.stderr.write("Compiling %s\n" % source)
675 result = run_pipeline(source, options)
676 results.add(source, result)
677 processed.add(source)
678 if recursive:
679 for module_name in context.find_cimported_module_names(source):
680 path = context.find_pyx_file(module_name, [source])
681 if path:
682 sources.append(path)
683 else:
684 sys.stderr.write(
685 "Cannot find .pyx file for cimported module '%s'\n" % module_name)
686 return results
688 def compile(source, options = None, c_compile = 0, c_link = 0,
689 full_module_name = None, **kwds):
690 """
691 compile(source [, options], [, <option> = <value>]...)
693 Compile one or more Pyrex implementation files, with optional timestamp
694 checking and recursing on dependecies. The source argument may be a string
695 or a sequence of strings If it is a string and no recursion or timestamp
696 checking is requested, a CompilationResult is returned, otherwise a
697 CompilationResultSet is returned.
698 """
699 options = CompilationOptions(defaults = options, c_compile = c_compile,
700 c_link = c_link, **kwds)
701 if isinstance(source, basestring) and not options.timestamps \
702 and not options.recursive:
703 return compile_single(source, options, full_module_name)
704 else:
705 return compile_multiple(source, options)
707 #------------------------------------------------------------------------
708 #
709 # Main command-line entry point
710 #
711 #------------------------------------------------------------------------
713 def main(command_line = 0):
714 args = sys.argv[1:]
715 any_failures = 0
716 if command_line:
717 from CmdLine import parse_command_line
718 options, sources = parse_command_line(args)
719 else:
720 options = CompilationOptions(default_options)
721 sources = args
723 if options.show_version:
724 sys.stderr.write("Cython version %s\n" % Version.version)
725 if options.working_path!="":
726 os.chdir(options.working_path)
727 try:
728 result = compile(sources, options)
729 if result.num_errors > 0:
730 any_failures = 1
731 except (EnvironmentError, PyrexError), e:
732 sys.stderr.write(str(e) + '\n')
733 any_failures = 1
734 if any_failures:
735 sys.exit(1)
739 #------------------------------------------------------------------------
740 #
741 # Set the default options depending on the platform
742 #
743 #------------------------------------------------------------------------
745 default_options = dict(
746 show_version = 0,
747 use_listing_file = 0,
748 errors_to_stderr = 1,
749 c_only = 1,
750 obj_only = 1,
751 cplus = 0,
752 output_file = None,
753 annotate = False,
754 generate_pxi = 0,
755 working_path = "",
756 recursive = 0,
757 timestamps = None,
758 verbose = 0,
759 quiet = 0,
760 pragma_overrides = {},
761 emit_linenums = False,
762 )
763 if sys.platform == "mac":
764 from Cython.Mac.MacSystem import c_compile, c_link, CCompilerError
765 default_options['use_listing_file'] = 1
766 elif sys.platform == "darwin":
767 from Cython.Mac.DarwinSystem import c_compile, c_link, CCompilerError
768 else:
769 c_compile = None
770 c_link = None
