2016-03-26 13:32:11 +01:00
#!/usr/bin/env python
# encoding: utf-8
# Scott Newton, 2005 (scottn)
2018-01-31 11:48:43 +02:00
# Thomas Nagy, 2006-2018 (ita)
2016-03-26 13:32:11 +01:00
"""
Support for waf command - line options
Provides default and command - line options , as well the command
that reads the ` ` options ` ` wscript function .
"""
import os , tempfile , optparse , sys , re
from waflib import Logs , Utils , Context , Errors
2018-01-31 11:48:43 +02:00
options = optparse . Values ( )
2016-03-26 13:32:11 +01:00
"""
A global dictionary representing user - provided command - line options : :
$ waf - - foo = bar
"""
commands = [ ]
"""
List of commands to execute extracted from the command - line . This list
is consumed during the execution by : py : func : ` waflib . Scripting . run_commands ` .
"""
envvars = [ ]
"""
List of environment variable declarations placed after the Waf executable name .
These are detected by searching for " = " in the remaining arguments .
You probably do not want to use this .
"""
lockfile = os . environ . get ( ' WAFLOCK ' , ' .lock-waf_ %s _build ' % sys . platform )
"""
Name of the lock file that marks a project as configured
"""
class opt_parser ( optparse . OptionParser ) :
"""
Command - line options parser .
"""
2018-01-31 11:48:43 +02:00
def __init__ ( self , ctx , allow_unknown = False ) :
optparse . OptionParser . __init__ ( self , conflict_handler = ' resolve ' , add_help_option = False ,
2020-08-24 13:12:46 -06:00
version = ' %s %s ( %s ) ' % ( Context . WAFNAME , Context . WAFVERSION , Context . WAFREVISION ) )
2016-03-26 13:32:11 +01:00
self . formatter . width = Logs . get_term_cols ( )
self . ctx = ctx
2018-01-31 11:48:43 +02:00
self . allow_unknown = allow_unknown
def _process_args ( self , largs , rargs , values ) :
"""
Custom _process_args to allow unknown options according to the allow_unknown status
"""
while rargs :
try :
optparse . OptionParser . _process_args ( self , largs , rargs , values )
except ( optparse . BadOptionError , optparse . AmbiguousOptionError ) as e :
if self . allow_unknown :
largs . append ( e . opt_str )
else :
self . error ( str ( e ) )
2016-03-26 13:32:11 +01:00
2020-08-24 13:12:46 -06:00
def _process_long_opt ( self , rargs , values ) :
# --custom-option=-ftxyz is interpreted as -f -t... see #2280
if self . allow_unknown :
back = [ ] + rargs
try :
optparse . OptionParser . _process_long_opt ( self , rargs , values )
except optparse . BadOptionError :
while rargs :
rargs . pop ( )
rargs . extend ( back )
rargs . pop ( 0 )
raise
else :
optparse . OptionParser . _process_long_opt ( self , rargs , values )
2016-03-26 13:32:11 +01:00
def print_usage ( self , file = None ) :
return self . print_help ( file )
def get_usage ( self ) :
"""
Builds the message to print on ` ` waf - - help ` `
: rtype : string
"""
cmds_str = { }
for cls in Context . classes :
if not cls . cmd or cls . cmd == ' options ' or cls . cmd . startswith ( ' _ ' ) :
continue
s = cls . __doc__ or ' '
cmds_str [ cls . cmd ] = s
if Context . g_module :
for ( k , v ) in Context . g_module . __dict__ . items ( ) :
if k in ( ' options ' , ' init ' , ' shutdown ' ) :
continue
if type ( v ) is type ( Context . create_context ) :
if v . __doc__ and not k . startswith ( ' _ ' ) :
cmds_str [ k ] = v . __doc__
just = 0
for k in cmds_str :
just = max ( just , len ( k ) )
lst = [ ' %s : %s ' % ( k . ljust ( just ) , v ) for ( k , v ) in cmds_str . items ( ) ]
lst . sort ( )
ret = ' \n ' . join ( lst )
2020-08-24 13:12:46 -06:00
return ''' %s [commands] [options]
2016-03-26 13:32:11 +01:00
2020-08-24 13:12:46 -06:00
Main commands ( example : . / % s build - j4 )
2016-03-26 13:32:11 +01:00
% s
2020-08-24 13:12:46 -06:00
''' % (Context.WAFNAME, Context.WAFNAME, ret)
2016-03-26 13:32:11 +01:00
class OptionsContext ( Context . Context ) :
"""
Collects custom options from wscript files and parses the command line .
Sets the global : py : const : ` waflib . Options . commands ` and : py : const : ` waflib . Options . options ` values .
"""
cmd = ' options '
fun = ' options '
def __init__ ( self , * * kw ) :
super ( OptionsContext , self ) . __init__ ( * * kw )
self . parser = opt_parser ( self )
""" Instance of :py:class:`waflib.Options.opt_parser` """
self . option_groups = { }
jobs = self . jobs ( )
p = self . add_option
color = os . environ . get ( ' NOCOLOR ' , ' ' ) and ' no ' or ' auto '
if os . environ . get ( ' CLICOLOR ' , ' ' ) == ' 0 ' :
color = ' no '
elif os . environ . get ( ' CLICOLOR_FORCE ' , ' ' ) == ' 1 ' :
color = ' yes '
p ( ' -c ' , ' --color ' , dest = ' colors ' , default = color , action = ' store ' , help = ' whether to use colors (yes/no/auto) [default: auto] ' , choices = ( ' yes ' , ' no ' , ' auto ' ) )
p ( ' -j ' , ' --jobs ' , dest = ' jobs ' , default = jobs , type = ' int ' , help = ' amount of parallel jobs ( %r ) ' % jobs )
p ( ' -k ' , ' --keep ' , dest = ' keep ' , default = 0 , action = ' count ' , help = ' continue despite errors (-kk to try harder) ' )
p ( ' -v ' , ' --verbose ' , dest = ' verbose ' , default = 0 , action = ' count ' , help = ' verbosity level -v -vv or -vvv [default: 0] ' )
p ( ' --zones ' , dest = ' zones ' , default = ' ' , action = ' store ' , help = ' debugging zones (task_gen, deps, tasks, etc) ' )
2018-01-31 11:48:43 +02:00
p ( ' --profile ' , dest = ' profile ' , default = 0 , action = ' store_true ' , help = optparse . SUPPRESS_HELP )
p ( ' --pdb ' , dest = ' pdb ' , default = 0 , action = ' store_true ' , help = optparse . SUPPRESS_HELP )
p ( ' -h ' , ' --help ' , dest = ' whelp ' , default = 0 , action = ' store_true ' , help = " show this help message and exit " )
2016-03-26 13:32:11 +01:00
gr = self . add_option_group ( ' Configuration options ' )
self . option_groups [ ' configure options ' ] = gr
gr . add_option ( ' -o ' , ' --out ' , action = ' store ' , default = ' ' , help = ' build dir for the project ' , dest = ' out ' )
gr . add_option ( ' -t ' , ' --top ' , action = ' store ' , default = ' ' , help = ' src dir for the project ' , dest = ' top ' )
2020-08-24 13:12:46 -06:00
gr . add_option ( ' --no-lock-in-run ' , action = ' store_true ' , default = os . environ . get ( ' NO_LOCK_IN_RUN ' , ' ' ) , help = optparse . SUPPRESS_HELP , dest = ' no_lock_in_run ' )
gr . add_option ( ' --no-lock-in-out ' , action = ' store_true ' , default = os . environ . get ( ' NO_LOCK_IN_OUT ' , ' ' ) , help = optparse . SUPPRESS_HELP , dest = ' no_lock_in_out ' )
gr . add_option ( ' --no-lock-in-top ' , action = ' store_true ' , default = os . environ . get ( ' NO_LOCK_IN_TOP ' , ' ' ) , help = optparse . SUPPRESS_HELP , dest = ' no_lock_in_top ' )
2016-03-26 13:32:11 +01:00
default_prefix = getattr ( Context . g_module , ' default_prefix ' , os . environ . get ( ' PREFIX ' ) )
if not default_prefix :
if Utils . unversioned_sys_platform ( ) == ' win32 ' :
d = tempfile . gettempdir ( )
default_prefix = d [ 0 ] . upper ( ) + d [ 1 : ]
# win32 preserves the case, but gettempdir does not
else :
default_prefix = ' /usr/local/ '
gr . add_option ( ' --prefix ' , dest = ' prefix ' , default = default_prefix , help = ' installation prefix [default: %r ] ' % default_prefix )
gr . add_option ( ' --bindir ' , dest = ' bindir ' , help = ' bindir ' )
gr . add_option ( ' --libdir ' , dest = ' libdir ' , help = ' libdir ' )
gr = self . add_option_group ( ' Build and installation options ' )
self . option_groups [ ' build and install options ' ] = gr
gr . add_option ( ' -p ' , ' --progress ' , dest = ' progress_bar ' , default = 0 , action = ' count ' , help = ' -p: progress bar; -pp: ide output ' )
gr . add_option ( ' --targets ' , dest = ' targets ' , default = ' ' , action = ' store ' , help = ' task generators, e.g. " target1,target2 " ' )
gr = self . add_option_group ( ' Step options ' )
self . option_groups [ ' step options ' ] = gr
gr . add_option ( ' --files ' , dest = ' files ' , default = ' ' , action = ' store ' , help = ' files to process, by regexp, e.g. " */main.c,*/test/main.o " ' )
default_destdir = os . environ . get ( ' DESTDIR ' , ' ' )
gr = self . add_option_group ( ' Installation and uninstallation options ' )
self . option_groups [ ' install/uninstall options ' ] = gr
gr . add_option ( ' --destdir ' , help = ' installation root [default: %r ] ' % default_destdir , default = default_destdir , dest = ' destdir ' )
gr . add_option ( ' -f ' , ' --force ' , dest = ' force ' , default = False , action = ' store_true ' , help = ' force file installation ' )
gr . add_option ( ' --distcheck-args ' , metavar = ' ARGS ' , help = ' arguments to pass to distcheck ' , default = None , action = ' store ' )
def jobs ( self ) :
"""
Finds the optimal amount of cpu cores to use for parallel jobs .
At runtime the options can be obtained from : py : const : ` waflib . Options . options ` : :
from waflib . Options import options
njobs = options . jobs
: return : the amount of cpu cores
: rtype : int
"""
count = int ( os . environ . get ( ' JOBS ' , 0 ) )
if count < 1 :
if ' NUMBER_OF_PROCESSORS ' in os . environ :
# on Windows, use the NUMBER_OF_PROCESSORS environment variable
count = int ( os . environ . get ( ' NUMBER_OF_PROCESSORS ' , 1 ) )
else :
# on everything else, first try the POSIX sysconf values
if hasattr ( os , ' sysconf_names ' ) :
if ' SC_NPROCESSORS_ONLN ' in os . sysconf_names :
count = int ( os . sysconf ( ' SC_NPROCESSORS_ONLN ' ) )
elif ' SC_NPROCESSORS_CONF ' in os . sysconf_names :
count = int ( os . sysconf ( ' SC_NPROCESSORS_CONF ' ) )
if not count and os . name not in ( ' nt ' , ' java ' ) :
try :
tmp = self . cmd_and_log ( [ ' sysctl ' , ' -n ' , ' hw.ncpu ' ] , quiet = 0 )
except Errors . WafError :
pass
else :
if re . match ( ' ^[0-9]+$ ' , tmp ) :
count = int ( tmp )
if count < 1 :
count = 1
elif count > 1024 :
count = 1024
return count
def add_option ( self , * k , * * kw ) :
"""
Wraps ` ` optparse . add_option ` ` : :
def options ( ctx ) :
ctx . add_option ( ' -u ' , ' --use ' , dest = ' use ' , default = False ,
action = ' store_true ' , help = ' a boolean option ' )
: rtype : optparse option object
"""
return self . parser . add_option ( * k , * * kw )
def add_option_group ( self , * k , * * kw ) :
"""
Wraps ` ` optparse . add_option_group ` ` : :
def options ( ctx ) :
gr = ctx . add_option_group ( ' some options ' )
gr . add_option ( ' -u ' , ' --use ' , dest = ' use ' , default = False , action = ' store_true ' )
: rtype : optparse option group object
"""
try :
gr = self . option_groups [ k [ 0 ] ]
except KeyError :
gr = self . parser . add_option_group ( * k , * * kw )
self . option_groups [ k [ 0 ] ] = gr
return gr
def get_option_group ( self , opt_str ) :
"""
Wraps ` ` optparse . get_option_group ` ` : :
def options ( ctx ) :
gr = ctx . get_option_group ( ' configure options ' )
gr . add_option ( ' -o ' , ' --out ' , action = ' store ' , default = ' ' ,
help = ' build dir for the project ' , dest = ' out ' )
: rtype : optparse option group object
"""
try :
return self . option_groups [ opt_str ]
except KeyError :
for group in self . parser . option_groups :
if group . title == opt_str :
return group
return None
2018-01-31 11:48:43 +02:00
def sanitize_path ( self , path , cwd = None ) :
if not cwd :
cwd = Context . launch_dir
p = os . path . expanduser ( path )
p = os . path . join ( cwd , p )
p = os . path . normpath ( p )
p = os . path . abspath ( p )
return p
2016-03-26 13:32:11 +01:00
2018-01-31 11:48:43 +02:00
def parse_cmd_args ( self , _args = None , cwd = None , allow_unknown = False ) :
"""
Just parse the arguments
2016-03-26 13:32:11 +01:00
"""
2018-01-31 11:48:43 +02:00
self . parser . allow_unknown = allow_unknown
2016-03-26 13:32:11 +01:00
( options , leftover_args ) = self . parser . parse_args ( args = _args )
2018-01-31 11:48:43 +02:00
envvars = [ ]
commands = [ ]
2016-03-26 13:32:11 +01:00
for arg in leftover_args :
if ' = ' in arg :
envvars . append ( arg )
2018-01-31 11:48:43 +02:00
elif arg != ' options ' :
2016-03-26 13:32:11 +01:00
commands . append ( arg )
2020-08-24 13:12:46 -06:00
if options . jobs < 1 :
options . jobs = 1
2018-01-31 11:48:43 +02:00
for name in ' top out destdir prefix bindir libdir ' . split ( ) :
# those paths are usually expanded from Context.launch_dir
if getattr ( options , name , None ) :
path = self . sanitize_path ( getattr ( options , name ) , cwd )
setattr ( options , name , path )
return options , commands , envvars
def init_module_vars ( self , arg_options , arg_commands , arg_envvars ) :
options . __dict__ . clear ( )
del commands [ : ]
del envvars [ : ]
2016-03-26 13:32:11 +01:00
2018-01-31 11:48:43 +02:00
options . __dict__ . update ( arg_options . __dict__ )
commands . extend ( arg_commands )
envvars . extend ( arg_envvars )
for var in envvars :
( name , value ) = var . split ( ' = ' , 1 )
os . environ [ name . strip ( ) ] = value
def init_logs ( self , options , commands , envvars ) :
Logs . verbose = options . verbose
2016-03-26 13:32:11 +01:00
if options . verbose > = 1 :
self . load ( ' errcheck ' )
colors = { ' yes ' : 2 , ' auto ' : 1 , ' no ' : 0 } [ options . colors ]
Logs . enable_colors ( colors )
2018-01-31 11:48:43 +02:00
if options . zones :
Logs . zones = options . zones . split ( ' , ' )
if not Logs . verbose :
Logs . verbose = 1
elif Logs . verbose > 0 :
Logs . zones = [ ' runner ' ]
if Logs . verbose > 2 :
Logs . zones = [ ' * ' ]
def parse_args ( self , _args = None ) :
"""
Parses arguments from a list which is not necessarily the command - line .
Initializes the module variables options , commands and envvars
If help is requested , prints it and exit the application
: param _args : arguments
: type _args : list of strings
"""
options , commands , envvars = self . parse_cmd_args ( )
self . init_logs ( options , commands , envvars )
self . init_module_vars ( options , commands , envvars )
2016-03-26 13:32:11 +01:00
def execute ( self ) :
"""
See : py : func : ` waflib . Context . Context . execute `
"""
super ( OptionsContext , self ) . execute ( )
self . parse_args ( )
Utils . alloc_process_pool ( options . jobs )
2018-01-31 11:48:43 +02:00