mirror of https://gitlab.com/ita1024/waf.git
Accept relative prefix/bindir/libdir paths from launch_dir
Additionally: - Scripting.parse_options is back for compatibility reasons - The help message should only be displayed when this is intended - OptionsContext is responsible for the full initialization, so the framework should be usable without requiring Scripting.py - Make it clear that Options.options is an optparse.Values object - Get rid of the state in Options.options
This commit is contained in:
parent
8b49da2fa7
commit
be05b6ee8b
|
@ -197,17 +197,17 @@ class ConfigurationContext(Context.Context):
|
||||||
"""
|
"""
|
||||||
if not env.PREFIX:
|
if not env.PREFIX:
|
||||||
if Options.options.prefix or Utils.is_win32:
|
if Options.options.prefix or Utils.is_win32:
|
||||||
env.PREFIX = Utils.sane_path(Options.options.prefix)
|
env.PREFIX = Options.options.prefix
|
||||||
else:
|
else:
|
||||||
env.PREFIX = ''
|
env.PREFIX = '/'
|
||||||
if not env.BINDIR:
|
if not env.BINDIR:
|
||||||
if Options.options.bindir:
|
if Options.options.bindir:
|
||||||
env.BINDIR = Utils.sane_path(Options.options.bindir)
|
env.BINDIR = Options.options.bindir
|
||||||
else:
|
else:
|
||||||
env.BINDIR = Utils.subst_vars('${PREFIX}/bin', env)
|
env.BINDIR = Utils.subst_vars('${PREFIX}/bin', env)
|
||||||
if not env.LIBDIR:
|
if not env.LIBDIR:
|
||||||
if Options.options.libdir:
|
if Options.options.libdir:
|
||||||
env.LIBDIR = Utils.sane_path(Options.options.libdir)
|
env.LIBDIR = Options.options.libdir
|
||||||
else:
|
else:
|
||||||
env.LIBDIR = Utils.subst_vars('${PREFIX}/lib%s' % Utils.lib64(), env)
|
env.LIBDIR = Utils.subst_vars('${PREFIX}/lib%s' % Utils.lib64(), env)
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ that reads the ``options`` wscript function.
|
||||||
import os, tempfile, optparse, sys, re
|
import os, tempfile, optparse, sys, re
|
||||||
from waflib import Logs, Utils, Context, Errors
|
from waflib import Logs, Utils, Context, Errors
|
||||||
|
|
||||||
options = {}
|
options = optparse.Values()
|
||||||
"""
|
"""
|
||||||
A global dictionary representing user-provided command-line options::
|
A global dictionary representing user-provided command-line options::
|
||||||
|
|
||||||
|
@ -43,14 +43,10 @@ class opt_parser(optparse.OptionParser):
|
||||||
Command-line options parser.
|
Command-line options parser.
|
||||||
"""
|
"""
|
||||||
def __init__(self, ctx, allow_unknown=False):
|
def __init__(self, ctx, allow_unknown=False):
|
||||||
# Create a option parser without help function because we need to be able ignore '-h|--help'
|
optparse.OptionParser.__init__(self, conflict_handler='resolve', add_help_option=False,
|
||||||
# at configuration phase, once the main script found, we will add the help option to make sure
|
|
||||||
# we if help is needed it will containt also user defined options
|
|
||||||
optparse.OptionParser.__init__(self, conflict_handler="resolve", add_help_option=False,
|
|
||||||
version='waf %s (%s)' % (Context.WAFVERSION, Context.WAFREVISION))
|
version='waf %s (%s)' % (Context.WAFVERSION, Context.WAFREVISION))
|
||||||
self.formatter.width = Logs.get_term_cols()
|
self.formatter.width = Logs.get_term_cols()
|
||||||
self.ctx = ctx
|
self.ctx = ctx
|
||||||
# By default do not allow unknown options
|
|
||||||
self.allow_unknown = allow_unknown
|
self.allow_unknown = allow_unknown
|
||||||
|
|
||||||
def _process_args(self, largs, rargs, values):
|
def _process_args(self, largs, rargs, values):
|
||||||
|
@ -136,6 +132,7 @@ class OptionsContext(Context.Context):
|
||||||
p('-v', '--verbose', dest='verbose', default=0, action='count', help='verbosity level -v -vv or -vvv [default: 0]')
|
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)')
|
p('--zones', dest='zones', default='', action='store', help='debugging zones (task_gen, deps, tasks, etc)')
|
||||||
p('--profile', dest='profile', default='', action='store_true', help=optparse.SUPPRESS_HELP)
|
p('--profile', dest='profile', default='', action='store_true', help=optparse.SUPPRESS_HELP)
|
||||||
|
p('-h', '--help', dest='whelp', default=0, action='store_true', help="show this help message and exit")
|
||||||
|
|
||||||
gr = self.add_option_group('Configuration options')
|
gr = self.add_option_group('Configuration options')
|
||||||
self.option_groups['configure options'] = gr
|
self.option_groups['configure options'] = gr
|
||||||
|
@ -261,35 +258,50 @@ class OptionsContext(Context.Context):
|
||||||
return group
|
return group
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def parse_basic_args(self, _args=None):
|
def sanitize_path(self, path, cwd=None):
|
||||||
"""
|
if not cwd:
|
||||||
Parse basic arguments defined by this module.
|
cwd = Context.launch_dir
|
||||||
This can be called at the very beginning of the Waf initialitation
|
p = os.path.expanduser(path)
|
||||||
procedure to initialize pre-configuration commmand line driven options.
|
p = os.path.join(cwd, p)
|
||||||
"""
|
p = os.path.normpath(p)
|
||||||
try:
|
p = os.path.abspath(p)
|
||||||
if self.parsed_basic_args:
|
return p
|
||||||
return
|
|
||||||
except AttributeError:
|
|
||||||
self.parsed_basic_args = True
|
|
||||||
|
|
||||||
# Allow unknow argument, as at this point the command line may contain
|
def parse_cmd_args(self, _args=None, cwd=None, allow_unknown=False):
|
||||||
# custom-specified options the context still doesn't know.
|
"""
|
||||||
self.parser.allow_unknown = True
|
Just parse the arguments
|
||||||
|
"""
|
||||||
global options
|
self.parser.allow_unknown = allow_unknown
|
||||||
(options, leftover_args) = self.parser.parse_args(args=_args)
|
(options, leftover_args) = self.parser.parse_args(args=_args)
|
||||||
|
envvars = []
|
||||||
|
commands = []
|
||||||
|
for arg in leftover_args:
|
||||||
|
if '=' in arg:
|
||||||
|
envvars.append(arg)
|
||||||
|
elif arg != 'options':
|
||||||
|
commands.append(arg)
|
||||||
|
|
||||||
if options.destdir:
|
for name in 'top out destdir prefix bindir libdir'.split():
|
||||||
options.destdir = Utils.sane_path(options.destdir)
|
# 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
|
||||||
|
|
||||||
if options.top:
|
def init_module_vars(self, arg_options, arg_commands, arg_envvars):
|
||||||
options.top = Utils.sane_path(options.top)
|
options.__dict__.clear()
|
||||||
|
del commands[:]
|
||||||
|
del envvars[:]
|
||||||
|
|
||||||
if options.out:
|
options.__dict__.update(arg_options.__dict__)
|
||||||
options.out = Utils.sane_path(options.out)
|
commands.extend(arg_commands)
|
||||||
|
envvars.extend(arg_envvars)
|
||||||
|
|
||||||
Logs.verbose = options.verbose
|
for var in envvars:
|
||||||
|
(name, value) = var.split('=', 1)
|
||||||
|
os.environ[name.strip()] = value
|
||||||
|
|
||||||
|
def init_logs(self, options, commands, envvars):
|
||||||
if options.verbose >= 1:
|
if options.verbose >= 1:
|
||||||
self.load('errcheck')
|
self.load('errcheck')
|
||||||
|
|
||||||
|
@ -298,48 +310,25 @@ class OptionsContext(Context.Context):
|
||||||
|
|
||||||
if options.zones:
|
if options.zones:
|
||||||
Logs.zones = options.zones.split(',')
|
Logs.zones = options.zones.split(',')
|
||||||
if not Logs.verbose:
|
if not Logs.verbose:
|
||||||
Logs.verbose = 1
|
Logs.verbose = 1
|
||||||
elif Logs.verbose > 0:
|
elif Logs.verbose > 0:
|
||||||
Logs.zones = ['runner']
|
Logs.zones = ['runner']
|
||||||
|
|
||||||
if Logs.verbose > 2:
|
if Logs.verbose > 2:
|
||||||
Logs.zones = ['*']
|
Logs.zones = ['*']
|
||||||
|
|
||||||
def parse_args(self, _args=None):
|
def parse_args(self, _args=None):
|
||||||
"""
|
"""
|
||||||
Parses arguments from a list which is not necessarily the command-line.
|
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
|
:param _args: arguments
|
||||||
:type _args: list of strings
|
:type _args: list of strings
|
||||||
"""
|
"""
|
||||||
self.parse_basic_args()
|
options, commands, envvars = self.parse_cmd_args()
|
||||||
|
self.init_logs(options, commands, envvars)
|
||||||
# Make sure all specified arguments make sense
|
self.init_module_vars(options, commands, envvars)
|
||||||
self.parser.allow_unknown = False
|
|
||||||
self.parser._add_help_option()
|
|
||||||
|
|
||||||
global options, commands, envvars
|
|
||||||
(custom_options, leftover_args) = self.parser.parse_args(args=_args)
|
|
||||||
|
|
||||||
# Update global options with custom ones
|
|
||||||
for currOptionName, currOptionValue in vars(custom_options).iteritems():
|
|
||||||
try:
|
|
||||||
getattr(options, currOptionName)
|
|
||||||
except AttributeError:
|
|
||||||
setattr(options, currOptionName, currOptionValue)
|
|
||||||
|
|
||||||
for arg in leftover_args:
|
|
||||||
if '=' in arg:
|
|
||||||
envvars.append(arg)
|
|
||||||
(name, value) = var.split('=', 1)
|
|
||||||
os.environ[name.strip()] = value
|
|
||||||
else:
|
|
||||||
commands.append(arg)
|
|
||||||
|
|
||||||
if not commands:
|
|
||||||
commands = ['build']
|
|
||||||
commands = [x for x in commands if x != 'options'] # issue 1076
|
|
||||||
|
|
||||||
def execute(self):
|
def execute(self):
|
||||||
"""
|
"""
|
||||||
|
@ -348,3 +337,4 @@ class OptionsContext(Context.Context):
|
||||||
super(OptionsContext, self).execute()
|
super(OptionsContext, self).execute()
|
||||||
self.parse_args()
|
self.parse_args()
|
||||||
Utils.alloc_process_pool(options.jobs)
|
Utils.alloc_process_pool(options.jobs)
|
||||||
|
|
||||||
|
|
|
@ -32,42 +32,39 @@ def waf_entry_point(current_directory, version, wafdir):
|
||||||
|
|
||||||
# Store current directory before any chdir
|
# Store current directory before any chdir
|
||||||
Context.waf_dir = wafdir
|
Context.waf_dir = wafdir
|
||||||
Context.launch_dir = current_directory
|
Context.run_dir = Context.launch_dir = current_directory
|
||||||
|
start_dir = current_directory
|
||||||
|
no_climb = os.environ.get('NOCLIMB')
|
||||||
|
|
||||||
if len(sys.argv) > 1:
|
if len(sys.argv) > 1:
|
||||||
# os.path.join handles absolute paths in sys.argv[1] accordingly (it discards the previous ones)
|
# os.path.join handles absolute paths
|
||||||
# if sys.argv[1] is not an absolute path, then it is relative to the current working directory
|
# if sys.argv[1] is not an absolute path, then it is relative to the current working directory
|
||||||
potential_wscript = os.path.join(current_directory, sys.argv[1])
|
potential_wscript = os.path.join(current_directory, sys.argv[1])
|
||||||
# maybe check if the file is executable
|
if os.path.basename(potential_wscript) == Context.WSCRIPT_FILE and os.path.isfile(potential_wscript):
|
||||||
# perhaps extract 'wscript' as a constant
|
|
||||||
if os.path.basename(potential_wscript) == 'wscript' and os.path.isfile(potential_wscript):
|
|
||||||
# need to explicitly normalize the path, as it may contain extra '/.'
|
# need to explicitly normalize the path, as it may contain extra '/.'
|
||||||
# TODO abspath?
|
path = os.path.normpath(os.path.dirname(potential_wscript))
|
||||||
current_directory = os.path.normpath(os.path.dirname(potential_wscript))
|
start_dir = os.path.abspath(path)
|
||||||
|
no_climb = True
|
||||||
sys.argv.pop(1)
|
sys.argv.pop(1)
|
||||||
|
|
||||||
# Parse basic args to find out pre-configuration phase options
|
ctx = Context.create_context('options')
|
||||||
optsCtx = Context.create_context('options')
|
(options, commands, env) = ctx.parse_cmd_args(allow_unknown=True)
|
||||||
optsCtx.parse_basic_args()
|
if options.top:
|
||||||
|
Context.run_dir = Context.top_dir = options.top
|
||||||
|
if options.out:
|
||||||
|
Context.out_dir = options.out
|
||||||
|
|
||||||
# if 'configure' is in the commands, do not search any further
|
# if 'configure' is in the commands, do not search any further
|
||||||
no_climb = os.environ.get('NOCLIMB')
|
|
||||||
if not no_climb:
|
if not no_climb:
|
||||||
for k in no_climb_commands:
|
for k in no_climb_commands:
|
||||||
for y in sys.argv:
|
for y in commands:
|
||||||
if y.startswith(k):
|
if y.startswith(k):
|
||||||
no_climb = True
|
no_climb = True
|
||||||
break
|
break
|
||||||
|
|
||||||
# if --top is provided assume the build started in the top directory
|
|
||||||
if Options.options.top:
|
|
||||||
Context.run_dir = Context.top_dir = Options.options.top
|
|
||||||
if Options.options.out:
|
|
||||||
Context.out_dir = Options.options.out
|
|
||||||
|
|
||||||
# try to find a lock file (if the project was configured)
|
# try to find a lock file (if the project was configured)
|
||||||
# at the same time, store the first wscript file seen
|
# at the same time, store the first wscript file seen
|
||||||
cur = current_directory
|
cur = start_dir
|
||||||
while cur and not Context.top_dir:
|
while cur and not Context.top_dir:
|
||||||
try:
|
try:
|
||||||
lst = os.listdir(cur)
|
lst = os.listdir(cur)
|
||||||
|
@ -123,9 +120,11 @@ def waf_entry_point(current_directory, version, wafdir):
|
||||||
break
|
break
|
||||||
|
|
||||||
if not Context.run_dir:
|
if not Context.run_dir:
|
||||||
Logs.warn('No wscript file found: the help message may be incomplete')
|
if options.whelp:
|
||||||
optsCtx.parser.print_help()
|
Logs.warn('These are the generic options (no wscript/project found)')
|
||||||
Logs.error('Waf: Run from a directory containing a file named %r', Context.WSCRIPT_FILE)
|
ctx.parser.print_help()
|
||||||
|
sys.exit(0)
|
||||||
|
Logs.error('Waf: Run from a folder containing a %r file (or try -h for the generic options)', Context.WSCRIPT_FILE)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -145,14 +144,12 @@ def waf_entry_point(current_directory, version, wafdir):
|
||||||
traceback.print_exc(file=sys.stdout)
|
traceback.print_exc(file=sys.stdout)
|
||||||
sys.exit(2)
|
sys.exit(2)
|
||||||
|
|
||||||
if Options.options.profile:
|
if options.profile:
|
||||||
import cProfile, pstats
|
import cProfile, pstats
|
||||||
cProfile.runctx('from waflib import Scripting; Scripting.run_commands()', {}, {}, 'profi.txt')
|
cProfile.runctx('from waflib import Scripting; Scripting.run_commands()', {}, {}, 'profi.txt')
|
||||||
p = pstats.Stats('profi.txt')
|
p = pstats.Stats('profi.txt')
|
||||||
p.sort_stats('time').print_stats(75) # or 'cumulative'
|
p.sort_stats('time').print_stats(75) # or 'cumulative'
|
||||||
else:
|
else:
|
||||||
# Execute 'option' context to load custom defined commands
|
|
||||||
optsCtx.execute()
|
|
||||||
try:
|
try:
|
||||||
run_commands()
|
run_commands()
|
||||||
except Errors.WafError as e:
|
except Errors.WafError as e:
|
||||||
|
@ -198,6 +195,19 @@ def set_main_module(file_path):
|
||||||
if not 'options' in Context.g_module.__dict__:
|
if not 'options' in Context.g_module.__dict__:
|
||||||
Context.g_module.options = Utils.nada
|
Context.g_module.options = Utils.nada
|
||||||
|
|
||||||
|
def parse_options():
|
||||||
|
"""
|
||||||
|
Parses the command-line options and initialize the logging system.
|
||||||
|
Called by :py:func:`waflib.Scripting.waf_entry_point` during the initialization.
|
||||||
|
"""
|
||||||
|
ctx = Context.create_context('options')
|
||||||
|
ctx.execute()
|
||||||
|
if not Options.commands:
|
||||||
|
Options.commands.append(default_cmd)
|
||||||
|
if Options.options.whelp:
|
||||||
|
ctx.parser.print_help()
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
def run_command(cmd_name):
|
def run_command(cmd_name):
|
||||||
"""
|
"""
|
||||||
Executes a single Waf command. Called by :py:func:`waflib.Scripting.run_commands`.
|
Executes a single Waf command. Called by :py:func:`waflib.Scripting.run_commands`.
|
||||||
|
@ -222,6 +232,7 @@ def run_commands():
|
||||||
Called by :py:func:`waflib.Scripting.waf_entry_point` during the initialization, and executed
|
Called by :py:func:`waflib.Scripting.waf_entry_point` during the initialization, and executed
|
||||||
after :py:func:`waflib.Scripting.parse_options`.
|
after :py:func:`waflib.Scripting.parse_options`.
|
||||||
"""
|
"""
|
||||||
|
parse_options()
|
||||||
run_command('init')
|
run_command('init')
|
||||||
while Options.commands:
|
while Options.commands:
|
||||||
cmd_name = Options.commands.pop(0)
|
cmd_name = Options.commands.pop(0)
|
||||||
|
@ -494,11 +505,7 @@ def dist(ctx):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
class DistCheck(Dist):
|
class DistCheck(Dist):
|
||||||
"""
|
"""creates an archive with dist, then tries to build it"""
|
||||||
Creates an archive of the project, then attempts to build the project in a temporary directory::
|
|
||||||
|
|
||||||
$ waf distcheck
|
|
||||||
"""
|
|
||||||
fun = 'distcheck'
|
fun = 'distcheck'
|
||||||
cmd = 'distcheck'
|
cmd = 'distcheck'
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue