1#
2#   Cython - Command Line Parsing
3#
4
5import os
6import sys
7import Options
8
9usage = """\
10Cython (http://cython.org) is a compiler for code written in the
11Cython language.  Cython is based on Pyrex by Greg Ewing.
12
13Usage: cython [options] sourcefile.{pyx,py} ...
14
15Options:
16  -V, --version                  Display version number of cython compiler
17  -l, --create-listing           Write error messages to a listing file
18  -I, --include-dir <directory>  Search for include files in named directory
19                                 (multiple include directories are allowed).
20  -o, --output-file <filename>   Specify name of generated C file
21  -t, --timestamps               Only compile newer source files
22  -f, --force                    Compile all source files (overrides implied -t)
23  -v, --verbose                  Be verbose, print file names on multiple compilation
24  -p, --embed-positions          If specified, the positions in Cython files of each
25                                 function definition is embedded in its docstring.
26  --cleanup <level>              Release interned objects on python exit, for memory debugging.
27                                 Level indicates aggressiveness, default 0 releases nothing.
28  -w, --working <directory>      Sets the working directory for Cython (the directory modules
29                                 are searched from)
30  --gdb                          Output debug information for cygdb
31  --gdb-outdir <directory>       Specify gdb debug information output directory. Implies --gdb.
32
33  -D, --no-docstrings            Strip docstrings from the compiled module.
34  -a, --annotate                 Produce a colorized HTML version of the source.
35  --line-directives              Produce #line directives pointing to the .pyx source
36  --cplus                        Output a C++ rather than C file.
37  --embed[=<method_name>]        Generate a main() function that embeds the Python interpreter.
38  -2                             Compile based on Python-2 syntax and code semantics.
39  -3                             Compile based on Python-3 syntax and code semantics.
40  --lenient                      Change some compile time errors to runtime errors to
41                                 improve Python compatibility
42  --capi-reexport-cincludes      Add cincluded headers to any auto-generated header files.
43  --fast-fail                    Abort the compilation on the first error
44  --warning-errors, -Werror      Make all warnings into errors
45  --warning-extra, -Wextra       Enable extra warnings
46  -X, --directive <name>=<value>[,<name=value,...] Overrides a compiler directive
47"""
48
49#The following experimental options are supported only on MacOSX:
50#  -C, --compile    Compile generated .c file to .o file
51#  --link           Link .o file to produce extension module (implies -C)
52#  -+, --cplus      Use C++ compiler for compiling and linking
53#  Additional .o files to link may be supplied when using -X."""
54
55def bad_usage():
56    sys.stderr.write(usage)
57    sys.exit(1)
58
59def parse_command_line(args):
60
61    from Cython.Compiler.Main import \
62        CompilationOptions, default_options
63
64    def pop_arg():
65        if args:
66            return args.pop(0)
67        else:
68            bad_usage()
69
70    def get_param(option):
71        tail = option[2:]
72        if tail:
73            return tail
74        else:
75            return pop_arg()
76
77    options = CompilationOptions(default_options)
78    sources = []
79    while args:
80        if args[0].startswith("-"):
81            option = pop_arg()
82            if option in ("-V", "--version"):
83                options.show_version = 1
84            elif option in ("-l", "--create-listing"):
85                options.use_listing_file = 1
86            elif option in ("-+", "--cplus"):
87                options.cplus = 1
88            elif option == "--embed":
89                Options.embed = "main"
90            elif option.startswith("--embed="):
91                Options.embed = option[8:]
92            elif option.startswith("-I"):
93                options.include_path.append(get_param(option))
94            elif option == "--include-dir":
95                options.include_path.append(pop_arg())
96            elif option in ("-w", "--working"):
97                options.working_path = pop_arg()
98            elif option in ("-o", "--output-file"):
99                options.output_file = pop_arg()
100            elif option in ("-t", "--timestamps"):
101                options.timestamps = 1
102            elif option in ("-f", "--force"):
103                options.timestamps = 0
104            elif option in ("-v", "--verbose"):
105                options.verbose += 1
106            elif option in ("-p", "--embed-positions"):
107                Options.embed_pos_in_docstring = 1
108            elif option in ("-z", "--pre-import"):
109                Options.pre_import = pop_arg()
110            elif option == "--cleanup":
111                Options.generate_cleanup_code = int(pop_arg())
112            elif option in ("-D", "--no-docstrings"):
113                Options.docstrings = False
114            elif option in ("-a", "--annotate"):
115                Options.annotate = True
116            elif option == "--convert-range":
117                Options.convert_range = True
118            elif option == "--line-directives":
119                options.emit_linenums = True
120            elif option == "--no-c-in-traceback":
121                options.c_line_in_traceback = False
122            elif option == "--gdb":
123                options.gdb_debug = True
124                options.output_dir = os.curdir
125            elif option == "--gdb-outdir":
126                options.gdb_debug = True
127                options.output_dir = pop_arg()
128            elif option == "--lenient":
129                Options.error_on_unknown_names = False
130                Options.error_on_uninitialized = False
131            elif option == '-2':
132                options.language_level = 2
133            elif option == '-3':
134                options.language_level = 3
135            elif option == "--capi-reexport-cincludes":
136                options.capi_reexport_cincludes = True
137            elif option == "--fast-fail":
138                Options.fast_fail = True
139            elif option in ('-Werror', '--warning-errors'):
140                Options.warning_errors = True
141            elif option in ('-Wextra', '--warning-extra'):
142                options.compiler_directives.update(Options.extra_warnings)
143            elif option == "--old-style-globals":
144                Options.old_style_globals = True
145            elif option == "--directive" or option.startswith('-X'):
146                if option.startswith('-X') and option[2:].strip():
147                    x_args = option[2:]
148                else:
149                    x_args = pop_arg()
150                try:
151                    options.compiler_directives = Options.parse_directive_list(
152                        x_args, relaxed_bool=True,
153                        current_settings=options.compiler_directives)
154                except ValueError, e:
155                    sys.stderr.write("Error in compiler directive: %s\n" % e.args[0])
156                    sys.exit(1)
157            elif option.startswith('--debug'):
158                option = option[2:].replace('-', '_')
159                import DebugFlags
160                if option in dir(DebugFlags):
161                    setattr(DebugFlags, option, True)
162                else:
163                    sys.stderr.write("Unknown debug flag: %s\n" % option)
164                    bad_usage()
165            elif option in ('-h', '--help'):
166                sys.stdout.write(usage)
167                sys.exit(0)
168            else:
169                sys.stderr.write("Unknown compiler flag: %s\n" % option)
170                sys.exit(1)
171        else:
172            sources.append(pop_arg())
173    if options.use_listing_file and len(sources) > 1:
174        sys.stderr.write(
175            "cython: Only one source file allowed when using -o\n")
176        sys.exit(1)
177    if len(sources) == 0 and not options.show_version:
178        bad_usage()
179    if Options.embed and len(sources) > 1:
180        sys.stderr.write(
181            "cython: Only one source file allowed when using -embed\n")
182        sys.exit(1)
183    return options, sources
184
185