summaryrefslogtreecommitdiff
path: root/Cython/Compiler/CmdLine.py
blob: 470fe6bd42edbd6e29a1a9e7f9cc93c0d63f3841 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
#
#   Cython - Command Line Parsing
#

from __future__ import absolute_import

import os
import sys
from . import Options

usage = """\
Cython (http://cython.org) is a compiler for code written in the
Cython language.  Cython is based on Pyrex by Greg Ewing.

Usage: cython [options] sourcefile.{pyx,py} ...

Options:
  -V, --version                  Display version number of cython compiler
  -l, --create-listing           Write error messages to a listing file
  -I, --include-dir <directory>  Search for include files in named directory
                                 (multiple include directories are allowed).
  -o, --output-file <filename>   Specify name of generated C file
  -t, --timestamps               Only compile newer source files
  -f, --force                    Compile all source files (overrides implied -t)
  -v, --verbose                  Be verbose, print file names on multiple compilation
  -p, --embed-positions          If specified, the positions in Cython files of each
                                 function definition is embedded in its docstring.
  --cleanup <level>              Release interned objects on python exit, for memory debugging.
                                 Level indicates aggressiveness, default 0 releases nothing.
  -w, --working <directory>      Sets the working directory for Cython (the directory modules
                                 are searched from)
  --gdb                          Output debug information for cygdb
  --gdb-outdir <directory>       Specify gdb debug information output directory. Implies --gdb.

  -D, --no-docstrings            Strip docstrings from the compiled module.
  -a, --annotate                 Produce a colorized HTML version of the source.
  --annotate-coverage <cov.xml>  Annotate and include coverage information from cov.xml.
  --line-directives              Produce #line directives pointing to the .pyx source
  --cplus                        Output a C++ rather than C file.
  --embed[=<method_name>]        Generate a main() function that embeds the Python interpreter.
  -2                             Compile based on Python-2 syntax and code semantics.
  -3                             Compile based on Python-3 syntax and code semantics.
  --3str                         Compile based on Python-3 syntax and code semantics without
                                 assuming unicode by default for string literals under Python 2.
  --lenient                      Change some compile time errors to runtime errors to
                                 improve Python compatibility
  --capi-reexport-cincludes      Add cincluded headers to any auto-generated header files.
  --fast-fail                    Abort the compilation on the first error
  --warning-errors, -Werror      Make all warnings into errors
  --warning-extra, -Wextra       Enable extra warnings
  -X, --directive <name>=<value>[,<name=value,...] Overrides a compiler directive
  -E, --compile-time-env name=value[,<name=value,...] Provides compile time env like DEF would do.
  --module-name                  Fully qualified module name. If not given, it is deduced from the
                                 import path if source file is in a package, or equals the
                                 filename otherwise.
  -M, --depfile                  Produce depfiles for the sources
"""


# The following experimental options are supported only on MacOSX:
#  -C, --compile    Compile generated .c file to .o file
#  --link           Link .o file to produce extension module (implies -C)
#  -+, --cplus      Use C++ compiler for compiling and linking
#  Additional .o files to link may be supplied when using -X."""

def bad_usage():
    sys.stderr.write(usage)
    sys.exit(1)

def parse_command_line(args):
    from .Main import CompilationOptions, default_options

    pending_arg = []

    def pop_arg():
        if not args or pending_arg:
            bad_usage()
        if '=' in args[0] and args[0].startswith('--'):  # allow "--long-option=xyz"
            name, value = args.pop(0).split('=', 1)
            pending_arg.append(value)
            return name
        return args.pop(0)

    def pop_value(default=None):
        if pending_arg:
            return pending_arg.pop()
        elif default is not None:
            return default
        elif not args:
            bad_usage()
        return args.pop(0)

    def get_param(option):
        tail = option[2:]
        if tail:
            return tail
        else:
            return pop_arg()

    options = CompilationOptions(default_options)
    sources = []
    while args:
        if args[0].startswith("-"):
            option = pop_arg()
            if option in ("-V", "--version"):
                options.show_version = 1
            elif option in ("-l", "--create-listing"):
                options.use_listing_file = 1
            elif option in ("-+", "--cplus"):
                options.cplus = 1
            elif option == "--embed":
                Options.embed = pop_value("main")
            elif option.startswith("-I"):
                options.include_path.append(get_param(option))
            elif option == "--include-dir":
                options.include_path.append(pop_value())
            elif option in ("-w", "--working"):
                options.working_path = pop_value()
            elif option in ("-o", "--output-file"):
                options.output_file = pop_value()
            elif option in ("-t", "--timestamps"):
                options.timestamps = 1
            elif option in ("-f", "--force"):
                options.timestamps = 0
            elif option in ("-v", "--verbose"):
                options.verbose += 1
            elif option in ("-p", "--embed-positions"):
                Options.embed_pos_in_docstring = 1
            elif option in ("-z", "--pre-import"):
                Options.pre_import = pop_value()
            elif option == "--cleanup":
                Options.generate_cleanup_code = int(pop_value())
            elif option in ("-D", "--no-docstrings"):
                Options.docstrings = False
            elif option in ("-a", "--annotate"):
                Options.annotate = True
            elif option == "--annotate-coverage":
                Options.annotate = True
                Options.annotate_coverage_xml = pop_value()
            elif option == "--convert-range":
                Options.convert_range = True
            elif option == "--line-directives":
                options.emit_linenums = True
            elif option == "--no-c-in-traceback":
                options.c_line_in_traceback = False
            elif option == "--gdb":
                options.gdb_debug = True
                options.output_dir = os.curdir
            elif option == "--gdb-outdir":
                options.gdb_debug = True
                options.output_dir = pop_value()
            elif option == "--lenient":
                Options.error_on_unknown_names = False
                Options.error_on_uninitialized = False
            elif option == '-2':
                options.language_level = 2
            elif option == '-3':
                options.language_level = 3
            elif option == '--3str':
                options.language_level = '3str'
            elif option == "--capi-reexport-cincludes":
                options.capi_reexport_cincludes = True
            elif option == "--fast-fail":
                Options.fast_fail = True
            elif option == "--cimport-from-pyx":
                Options.cimport_from_pyx = True
            elif option in ('-Werror', '--warning-errors'):
                Options.warning_errors = True
            elif option in ('-Wextra', '--warning-extra'):
                options.compiler_directives.update(Options.extra_warnings)
            elif option == "--old-style-globals":
                Options.old_style_globals = True
            elif option == "--directive" or option.startswith('-X'):
                if option.startswith('-X') and option[2:].strip():
                    x_args = option[2:]
                else:
                    x_args = pop_value()
                try:
                    options.compiler_directives = Options.parse_directive_list(
                        x_args, relaxed_bool=True,
                        current_settings=options.compiler_directives)
                except ValueError as e:
                    sys.stderr.write("Error in compiler directive: %s\n" % e.args[0])
                    sys.exit(1)
            elif option == "--compile-time-env" or option.startswith('-E'):
                if option.startswith('-E') and option[2:].strip():
                    x_args = option[2:]
                else:
                    x_args = pop_value()
                try:
                    options.compile_time_env = Options.parse_compile_time_env(
                        x_args, current_settings=options.compile_time_env)
                except ValueError as e:
                    sys.stderr.write("Error in compile-time-env: %s\n" % e.args[0])
                    sys.exit(1)
            elif option == "--module-name":
                options.module_name = pop_value()
            elif option in ('-M', '--depfile'):
                options.depfile = True
            elif option.startswith('--debug'):
                option = option[2:].replace('-', '_')
                from . import DebugFlags
                if option in dir(DebugFlags):
                    setattr(DebugFlags, option, True)
                else:
                    sys.stderr.write("Unknown debug flag: %s\n" % option)
                    bad_usage()
            elif option in ('-h', '--help'):
                sys.stdout.write(usage)
                sys.exit(0)
            else:
                sys.stderr.write(usage)
                sys.stderr.write("Unknown compiler flag: %s\n" % option)
                sys.exit(1)
        else:
            sources.append(pop_arg())

    if pending_arg:
        bad_usage()

    if options.use_listing_file and len(sources) > 1:
        sys.stderr.write(
            "cython: Only one source file allowed when using -o\n")
        sys.exit(1)
    if len(sources) == 0 and not options.show_version:
        bad_usage()
    if Options.embed and len(sources) > 1:
        sys.stderr.write(
            "cython: Only one source file allowed when using --embed\n")
        sys.exit(1)
    if options.module_name:
        if options.timestamps:
            sys.stderr.write(
                "cython: Cannot use --module-name with --timestamps\n")
            sys.exit(1)
        if len(sources) > 1:
            sys.stderr.write(
                "cython: Only one source file allowed when using --module-name\n")
            sys.exit(1)
    return options, sources