3 # Scott Newton, 2005 (scottn)
4 # Thomas Nagy, 2006-2018 (ita)
7 Support for waf command-line options
9 Provides default and command-line options, as well the command
10 that reads the ``options`` wscript function.
13 import os
, tempfile
, optparse
, sys
, re
14 from waflib
import Logs
, Utils
, Context
, Errors
16 options
= optparse
.Values()
18 A global dictionary representing user-provided command-line options::
25 List of commands to execute extracted from the command-line. This list
26 is consumed during the execution by :py:func:`waflib.Scripting.run_commands`.
31 List of environment variable declarations placed after the Waf executable name.
32 These are detected by searching for "=" in the remaining arguments.
33 You probably do not want to use this.
36 lockfile
= os
.environ
.get('WAFLOCK', '.lock-waf_%s_build' % sys
.platform
)
38 Name of the lock file that marks a project as configured
41 class opt_parser(optparse
.OptionParser
):
43 Command-line options parser.
45 def __init__(self
, ctx
, allow_unknown
=False):
46 optparse
.OptionParser
.__init
__(self
, conflict_handler
='resolve', add_help_option
=False,
47 version
='waf %s (%s)' % (Context
.WAFVERSION
, Context
.WAFREVISION
))
48 self
.formatter
.width
= Logs
.get_term_cols()
50 self
.allow_unknown
= allow_unknown
52 def _process_args(self
, largs
, rargs
, values
):
54 Custom _process_args to allow unknown options according to the allow_unknown status
58 optparse
.OptionParser
._process
_args
(self
,largs
,rargs
,values
)
59 except (optparse
.BadOptionError
, optparse
.AmbiguousOptionError
) as e
:
60 if self
.allow_unknown
:
61 largs
.append(e
.opt_str
)
65 def print_usage(self
, file=None):
66 return self
.print_help(file)
70 Builds the message to print on ``waf --help``
75 for cls
in Context
.classes
:
76 if not cls
.cmd
or cls
.cmd
== 'options' or cls
.cmd
.startswith( '_' ):
83 for (k
, v
) in Context
.g_module
.__dict
__.items():
84 if k
in ('options', 'init', 'shutdown'):
87 if type(v
) is type(Context
.create_context
):
88 if v
.__doc
__ and not k
.startswith('_'):
89 cmds_str
[k
] = v
.__doc
__
93 just
= max(just
, len(k
))
95 lst
= [' %s: %s' % (k
.ljust(just
), v
) for (k
, v
) in cmds_str
.items()]
99 return '''waf [commands] [options]
101 Main commands (example: ./waf build -j4)
106 class OptionsContext(Context
.Context
):
108 Collects custom options from wscript files and parses the command line.
109 Sets the global :py:const:`waflib.Options.commands` and :py:const:`waflib.Options.options` values.
114 def __init__(self
, **kw
):
115 super(OptionsContext
, self
).__init
__(**kw
)
117 self
.parser
= opt_parser(self
)
118 """Instance of :py:class:`waflib.Options.opt_parser`"""
120 self
.option_groups
= {}
124 color
= os
.environ
.get('NOCOLOR', '') and 'no' or 'auto'
125 if os
.environ
.get('CLICOLOR', '') == '0':
127 elif os
.environ
.get('CLICOLOR_FORCE', '') == '1':
129 p('-c', '--color', dest
='colors', default
=color
, action
='store', help='whether to use colors (yes/no/auto) [default: auto]', choices
=('yes', 'no', 'auto'))
130 p('-j', '--jobs', dest
='jobs', default
=jobs
, type='int', help='amount of parallel jobs (%r)' % jobs
)
131 p('-k', '--keep', dest
='keep', default
=0, action
='count', help='continue despite errors (-kk to try harder)')
132 p('-v', '--verbose', dest
='verbose', default
=0, action
='count', help='verbosity level -v -vv or -vvv [default: 0]')
133 p('--zones', dest
='zones', default
='', action
='store', help='debugging zones (task_gen, deps, tasks, etc)')
134 p('--profile', dest
='profile', default
=0, action
='store_true', help=optparse
.SUPPRESS_HELP
)
135 p('--pdb', dest
='pdb', default
=0, action
='store_true', help=optparse
.SUPPRESS_HELP
)
136 p('-h', '--help', dest
='whelp', default
=0, action
='store_true', help="show this help message and exit")
138 gr
= self
.add_option_group('Configuration options')
139 self
.option_groups
['configure options'] = gr
141 gr
.add_option('-o', '--out', action
='store', default
='', help='build dir for the project', dest
='out')
142 gr
.add_option('-t', '--top', action
='store', default
='', help='src dir for the project', dest
='top')
144 gr
.add_option('--no-lock-in-run', action
='store_true', default
='', help=optparse
.SUPPRESS_HELP
, dest
='no_lock_in_run')
145 gr
.add_option('--no-lock-in-out', action
='store_true', default
='', help=optparse
.SUPPRESS_HELP
, dest
='no_lock_in_out')
146 gr
.add_option('--no-lock-in-top', action
='store_true', default
='', help=optparse
.SUPPRESS_HELP
, dest
='no_lock_in_top')
148 default_prefix
= getattr(Context
.g_module
, 'default_prefix', os
.environ
.get('PREFIX'))
149 if not default_prefix
:
150 if Utils
.unversioned_sys_platform() == 'win32':
151 d
= tempfile
.gettempdir()
152 default_prefix
= d
[0].upper() + d
[1:]
153 # win32 preserves the case, but gettempdir does not
155 default_prefix
= '/usr/local/'
156 gr
.add_option('--prefix', dest
='prefix', default
=default_prefix
, help='installation prefix [default: %r]' % default_prefix
)
157 gr
.add_option('--bindir', dest
='bindir', help='bindir')
158 gr
.add_option('--libdir', dest
='libdir', help='libdir')
160 gr
= self
.add_option_group('Build and installation options')
161 self
.option_groups
['build and install options'] = gr
162 gr
.add_option('-p', '--progress', dest
='progress_bar', default
=0, action
='count', help= '-p: progress bar; -pp: ide output')
163 gr
.add_option('--targets', dest
='targets', default
='', action
='store', help='task generators, e.g. "target1,target2"')
165 gr
= self
.add_option_group('Step options')
166 self
.option_groups
['step options'] = gr
167 gr
.add_option('--files', dest
='files', default
='', action
='store', help='files to process, by regexp, e.g. "*/main.c,*/test/main.o"')
169 default_destdir
= os
.environ
.get('DESTDIR', '')
171 gr
= self
.add_option_group('Installation and uninstallation options')
172 self
.option_groups
['install/uninstall options'] = gr
173 gr
.add_option('--destdir', help='installation root [default: %r]' % default_destdir
, default
=default_destdir
, dest
='destdir')
174 gr
.add_option('-f', '--force', dest
='force', default
=False, action
='store_true', help='force file installation')
175 gr
.add_option('--distcheck-args', metavar
='ARGS', help='arguments to pass to distcheck', default
=None, action
='store')
179 Finds the optimal amount of cpu cores to use for parallel jobs.
180 At runtime the options can be obtained from :py:const:`waflib.Options.options` ::
182 from waflib.Options import options
185 :return: the amount of cpu cores
188 count
= int(os
.environ
.get('JOBS', 0))
190 if 'NUMBER_OF_PROCESSORS' in os
.environ
:
191 # on Windows, use the NUMBER_OF_PROCESSORS environment variable
192 count
= int(os
.environ
.get('NUMBER_OF_PROCESSORS', 1))
194 # on everything else, first try the POSIX sysconf values
195 if hasattr(os
, 'sysconf_names'):
196 if 'SC_NPROCESSORS_ONLN' in os
.sysconf_names
:
197 count
= int(os
.sysconf('SC_NPROCESSORS_ONLN'))
198 elif 'SC_NPROCESSORS_CONF' in os
.sysconf_names
:
199 count
= int(os
.sysconf('SC_NPROCESSORS_CONF'))
200 if not count
and os
.name
not in ('nt', 'java'):
202 tmp
= self
.cmd_and_log(['sysctl', '-n', 'hw.ncpu'], quiet
=0)
203 except Errors
.WafError
:
206 if re
.match('^[0-9]+$', tmp
):
214 def add_option(self
, *k
, **kw
):
216 Wraps ``optparse.add_option``::
219 ctx.add_option('-u', '--use', dest='use', default=False,
220 action='store_true', help='a boolean option')
222 :rtype: optparse option object
224 return self
.parser
.add_option(*k
, **kw
)
226 def add_option_group(self
, *k
, **kw
):
228 Wraps ``optparse.add_option_group``::
231 gr = ctx.add_option_group('some options')
232 gr.add_option('-u', '--use', dest='use', default=False, action='store_true')
234 :rtype: optparse option group object
237 gr
= self
.option_groups
[k
[0]]
239 gr
= self
.parser
.add_option_group(*k
, **kw
)
240 self
.option_groups
[k
[0]] = gr
243 def get_option_group(self
, opt_str
):
245 Wraps ``optparse.get_option_group``::
248 gr = ctx.get_option_group('configure options')
249 gr.add_option('-o', '--out', action='store', default='',
250 help='build dir for the project', dest='out')
252 :rtype: optparse option group object
255 return self
.option_groups
[opt_str
]
257 for group
in self
.parser
.option_groups
:
258 if group
.title
== opt_str
:
262 def sanitize_path(self
, path
, cwd
=None):
264 cwd
= Context
.launch_dir
265 p
= os
.path
.expanduser(path
)
266 p
= os
.path
.join(cwd
, p
)
267 p
= os
.path
.normpath(p
)
268 p
= os
.path
.abspath(p
)
271 def parse_cmd_args(self
, _args
=None, cwd
=None, allow_unknown
=False):
273 Just parse the arguments
275 self
.parser
.allow_unknown
= allow_unknown
276 (options
, leftover_args
) = self
.parser
.parse_args(args
=_args
)
279 for arg
in leftover_args
:
282 elif arg
!= 'options':
285 for name
in 'top out destdir prefix bindir libdir'.split():
286 # those paths are usually expanded from Context.launch_dir
287 if getattr(options
, name
, None):
288 path
= self
.sanitize_path(getattr(options
, name
), cwd
)
289 setattr(options
, name
, path
)
290 return options
, commands
, envvars
292 def init_module_vars(self
, arg_options
, arg_commands
, arg_envvars
):
293 options
.__dict
__.clear()
297 options
.__dict
__.update(arg_options
.__dict
__)
298 commands
.extend(arg_commands
)
299 envvars
.extend(arg_envvars
)
302 (name
, value
) = var
.split('=', 1)
303 os
.environ
[name
.strip()] = value
305 def init_logs(self
, options
, commands
, envvars
):
306 Logs
.verbose
= options
.verbose
307 if options
.verbose
>= 1:
308 self
.load('errcheck')
310 colors
= {'yes' : 2, 'auto' : 1, 'no' : 0}[options
.colors
]
311 Logs
.enable_colors(colors
)
314 Logs
.zones
= options
.zones
.split(',')
317 elif Logs
.verbose
> 0:
318 Logs
.zones
= ['runner']
322 def parse_args(self
, _args
=None):
324 Parses arguments from a list which is not necessarily the command-line.
325 Initializes the module variables options, commands and envvars
326 If help is requested, prints it and exit the application
328 :param _args: arguments
329 :type _args: list of strings
331 options
, commands
, envvars
= self
.parse_cmd_args()
332 self
.init_logs(options
, commands
, envvars
)
333 self
.init_module_vars(options
, commands
, envvars
)
337 See :py:func:`waflib.Context.Context.execute`
339 super(OptionsContext
, self
).execute()
341 Utils
.alloc_process_pool(options
.jobs
)