Bug 1257823 - Move imply_option() to the global scope. r=nalexander

Like set_config and set_define, we move imply_option to the global
scope.
This commit is contained in:
Mike Hommey 2016-03-23 14:18:57 +09:00
Родитель 92c7aa3e65
Коммит 6a8ed3e4a8
12 изменённых файлов: 344 добавлений и 144 удалений

Просмотреть файл

@ -599,7 +599,9 @@ option('--enable-application', nargs=1, env='MOZ_BUILD_APP',
@depends('--enable-application', '--help')
def application(app, help):
if app:
imply_option(app.format('--enable-project'))
return app
imply_option('--enable-project', application)
@depends(check_build_environment, '--help')

Просмотреть файл

@ -123,11 +123,11 @@ def instruments(value, target):
% target.os)
if value:
add_old_configure_assignment('MOZ_INSTRUMENTS', True)
imply_option('--enable-profiling', reason='--enable-instruments')
return True
set_config('MOZ_INSTRUMENTS', instruments)
set_define('MOZ_INSTRUMENTS', instruments)
imply_option('--enable-profiling', instruments, reason='--enable-instruments')
js_option('--enable-callgrind', env='MOZ_CALLGRIND',
help='Enable callgrind profiling')
@ -135,27 +135,30 @@ js_option('--enable-callgrind', env='MOZ_CALLGRIND',
@depends('--enable-callgrind')
def callgrind(value):
if value:
imply_option('--enable-profiling')
return True
set_define('MOZ_CALLGRIND', callgrind)
imply_option('--enable-profiling', callgrind)
js_option('--enable-profiling', env='MOZ_PROFILING',
help='Set compile flags necessary for using sampling profilers '
'(e.g. shark, perf)')
@depends('--enable-profiling', target)
def profiling(value, target):
@depends('--enable-profiling')
def profiling(value):
if value:
add_old_configure_assignment('MOZ_PROFILING', True)
return True
if target.kernel == 'WINNT' or (target.kernel == 'Linux' and
target.os == 'GNU'):
imply_option('--enable-vtune', reason='--enable-profiling')
@depends(profiling, target)
def imply_vtune(value, target):
if value and (target.kernel == 'WINNT' or (target.kernel == 'Linux' and
target.os == 'GNU')):
return True
set_config('MOZ_PROFILING', profiling)
set_define('MOZ_PROFILING', profiling)
imply_option('--enable-vtune', imply_vtune, reason='--enable-profiling')
js_option('--enable-vtune', env='MOZ_VTUNE', help='Enable vtune profiling')

Просмотреть файл

@ -32,11 +32,16 @@ option('--enable-artifact-builds', env='MOZ_ARTIFACT_BUILDS',
@depends('--enable-artifact-builds')
def artifact_builds(value):
if value:
imply_option('--disable-compile-environment')
return True
set_config('MOZ_ARTIFACT_BUILDS', artifact_builds)
@depends('--enable-artifact-builds')
def imply_disable_compile_environment(value):
if value:
return False
imply_option('--enable-compile-environment', imply_disable_compile_environment)
option('--disable-compile-environment',
help='Disable compiler/library checks')

Просмотреть файл

@ -14,8 +14,10 @@ from mozbuild.configure.options import (
CommandLineHelper,
ConflictingOptionError,
InvalidOptionError,
NegativeOptionValue,
Option,
OptionValue,
PositiveOptionValue,
)
from mozbuild.configure.help import HelpFormatter
from mozbuild.util import (
@ -40,20 +42,6 @@ class SandboxedGlobal(dict):
'''Identifiable dict type for use as function global'''
class DependsOutput(object):
'''Class for objects holding the options implied by a @depends function.'''
__slots__ = ('implied_options',)
def __init__(self):
super(DependsOutput, self).__init__()
self.implied_options = []
def imply_option(self, option, reason=None):
if not isinstance(option, types.StringTypes):
raise TypeError('imply_option must be given a string')
self.implied_options.append((option, reason))
def forbidden_import(*args, **kwargs):
raise ImportError('Importing modules is forbidden')
@ -132,7 +120,7 @@ class ConfigureSandbox(dict):
# Store options added with `imply_option`, and the reason they were
# added (which can either have been given to `imply_option`, or
# infered.
# inferred.
self._implied_options = {}
# Store all results from _prepare_function
@ -187,11 +175,10 @@ class ConfigureSandbox(dict):
for arg in self._helper:
without_value = arg.split('=', 1)[0]
if arg in self._implied_options:
func, reason = self._implied_options[arg]
frameinfo, reason = self._implied_options[arg]
raise ConfigureError(
'`%s`, emitted by `%s` in `%s`, was not handled.'
% (without_value, func.__name__,
func.func_code.co_filename))
'`%s`, emitted from `%s` line `%d`, was not handled.'
% (without_value, frameinfo[1], frameinfo[2]))
raise InvalidOptionError('Unknown option: %s' % without_value)
# All options must be referenced by some @depends function
@ -264,7 +251,7 @@ class ConfigureSandbox(dict):
try:
value, option_string = self._helper.handle(option)
except ConflictingOptionError as e:
func, reason = self._implied_options[e.arg]
frameinfo, reason = self._implied_options[e.arg]
raise InvalidOptionError(
"'%s' implied by '%s' conflicts with '%s' from the %s"
% (e.arg, reason, e.old_arg, e.old_origin))
@ -293,9 +280,7 @@ class ConfigureSandbox(dict):
The decorated function is altered to use a different global namespace
for its execution. This different global namespace exposes a limited
set of functions from os.path, and one additional functions:
`imply_option`. It allows to inject additional options as if they had
been passed on the command line.
set of functions from os.path.
'''
if not args:
raise ConfigureError('@depends needs at least one argument')
@ -335,10 +320,6 @@ class ConfigureSandbox(dict):
raise ConfigureError(
'Cannot decorate generator functions with @depends')
func, glob = self._prepare_function(func)
result = DependsOutput()
glob.update(
imply_option=result.imply_option,
)
dummy = wraps(func)(DummyFunction())
self._depends[dummy] = func, dependencies
with_help = self._help_option in dependencies
@ -352,29 +333,8 @@ class ConfigureSandbox(dict):
"`%s` must depend on '--help'"
% (func.__name__, arg.__name__, arg.__name__))
if self._help and not with_help:
return dummy
self._results[func] = func(*resolved_args)
for option, reason in result.implied_options:
self._helper.add(option, 'implied')
if not reason:
deps = []
for arg in dependencies:
if not isinstance(arg, Option):
raise ConfigureError(
"Cannot infer what implied '%s'" % option)
if arg == self._help_option:
continue
deps.append(self._raw_options.get(arg) or
self.arg.option)
if len(deps) != 1:
raise ConfigureError(
"Cannot infer what implied '%s'" % option)
reason = deps[0]
self._implied_options[option] = func, reason
if not self._help or with_help:
self._results[func] = func(*resolved_args)
return dummy
@ -409,6 +369,7 @@ class ConfigureSandbox(dict):
option=self.option_impl,
set_config=self.set_config_impl,
set_define=self.set_define_impl,
imply_option=self.imply_option_impl,
)
self._templates.add(template)
return template
@ -459,6 +420,83 @@ class ConfigureSandbox(dict):
defines = self._config.setdefault('DEFINES', {})
self._resolve_and_set(defines, name, value)
def imply_option_impl(self, option, value, reason=None):
'''Implementation of imply_option().
Injects additional options as if they had been passed on the command
line. The `option` argument is a string as in option()'s `name` or
`env`. The option must be declared after `imply_option` references it.
The `value` argument indicates the value to pass to the option.
It can be:
- True. In this case `imply_option` injects the positive option
(--enable-foo/--with-foo).
imply_option('--enable-foo', True)
imply_option('--disable-foo', True)
are both equivalent to `--enable-foo` on the command line.
- False. In this case `imply_option` injects the negative option
(--disable-foo/--without-foo).
imply_option('--enable-foo', False)
imply_option('--disable-foo', False)
are both equivalent to `--disable-foo` on the command line.
- None. In this case `imply_option` does nothing.
imply_option('--enable-foo', None)
imply_option('--disable-foo', None)
are both equivalent to not passing any flag on the command line.
- a string or a tuple. In this case `imply_option` injects the positive
option with the given value(s).
imply_option('--enable-foo', 'a')
imply_option('--disable-foo', 'a')
are both equivalent to `--enable-foo=a` on the command line.
imply_option('--enable-foo', ('a', 'b'))
imply_option('--disable-foo', ('a', 'b'))
are both equivalent to `--enable-foo=a,b` on the command line.
Because imply_option('--disable-foo', ...) can be misleading, it is
recommended to use the positive form ('--enable' or '--with') for
`option`.
The `value` argument can also be (and usually is) a reference to a
@depends function, in which case the result of that function will be
used as per the descripted mapping above.
The `reason` argument indicates what caused the option to be implied.
It is necessary when it cannot be inferred from the `value`.
'''
if not reason and isinstance(value, DummyFunction):
deps = self._depends[value][1]
possible_reasons = [d for d in deps if d != self._help_option]
if len(possible_reasons) == 1:
if isinstance(possible_reasons[0], Option):
reason = (self._raw_options.get(possible_reasons[0]) or
possible_reasons[0].option)
if not reason or not isinstance(value, DummyFunction):
raise ConfigureError(
"Cannot infer what implies '%s'. Please add a `reason` to "
"the `imply_option` call."
% option)
value = self._resolve(value, need_help_dependency=False)
if value is not None:
if isinstance(value, OptionValue):
pass
elif value is True:
value = PositiveOptionValue()
elif value is False or value == ():
value = NegativeOptionValue()
elif isinstance(value, types.StringTypes):
value = PositiveOptionValue((value,))
elif isinstance(value, tuple):
value = PositiveOptionValue(value)
else:
raise TypeError("Unexpected type: '%s'" % type(value))
option = value.format(option)
self._helper.add(option, 'implied')
self._implied_options[option] = inspect.stack()[1], reason
def _prepare_function(self, func):
'''Alter the given function global namespace with the common ground
for @depends, @template and @advanced.

Просмотреть файл

@ -0,0 +1,24 @@
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
option('--enable-foo', help='enable foo')
@depends('--enable-foo', '--help')
def foo(value, help):
if value:
return True
imply_option('--enable-bar', foo)
option('--enable-bar', help='enable bar')
@depends('--enable-bar')
def bar(value):
if value:
return value
set_config('BAR', bar)

Просмотреть файл

@ -0,0 +1,31 @@
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
option('--enable-hoge', help='enable hoge')
@depends('--enable-hoge')
def hoge(value):
return value
option('--enable-foo', help='enable foo')
@depends('--enable-foo', hoge)
def foo(value, hoge):
if value:
return True
imply_option('--enable-bar', foo)
option('--enable-bar', help='enable bar')
@depends('--enable-bar')
def bar(value):
if value:
return value
set_config('BAR', bar)

Просмотреть файл

@ -0,0 +1,34 @@
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
option('--enable-foo', help='enable foo')
@depends('--enable-foo')
def foo(value):
if value:
return False
imply_option('--enable-bar', foo)
option('--disable-hoge', help='enable hoge')
@depends('--disable-hoge')
def hoge(value):
if not value:
return False
imply_option('--enable-bar', hoge)
option('--enable-bar', default=True, help='enable bar')
@depends('--enable-bar')
def bar(value):
if not value:
return value
set_config('BAR', bar)

Просмотреть файл

@ -0,0 +1,24 @@
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
option('--enable-foo', help='enable foo')
@depends('--enable-foo')
def foo(value):
if value:
return True
imply_option('--enable-bar', foo)
option('--enable-bar', help='enable bar')
@depends('--enable-bar')
def bar(value):
if value:
return value
set_config('BAR', bar)

Просмотреть файл

@ -0,0 +1,24 @@
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
option('--enable-foo', nargs='*', help='enable foo')
@depends('--enable-foo')
def foo(value):
if value:
return value
imply_option('--enable-bar', foo)
option('--enable-bar', nargs='*', help='enable bar')
@depends('--enable-bar')
def bar(value):
if value:
return value
set_config('BAR', bar)

Просмотреть файл

@ -105,40 +105,6 @@ def default(value):
set_config('DEFAULTED', default)
# @depends functions can also declare that some extra options are implied.
# Those options need to be defined _after_ the function, and they mustn't
# appear on the command line or the environment with conflicting values.
@depends('--enable-values')
def values(values):
if values:
imply_option('--enable-implied')
imply_option(values.format('--with-implied-values'))
imply_option(values.format('WITH_IMPLIED_ENV'))
option('--enable-implied', help='Implied')
option('--with-implied-values', nargs='*', help='Implied values')
option(env='WITH_IMPLIED_ENV', nargs='*', help='Implied env')
@depends('--enable-implied')
def implied(value):
return value
set_config('IMPLIED', implied)
@depends('--with-implied-values')
def implied(values):
return values
set_config('IMPLIED_VALUES', implied)
@depends('WITH_IMPLIED_ENV')
def implied(values):
return values
set_config('IMPLIED_ENV', implied)
@depends('--enable-values', '--help')
def choices(values, help):
if len(values):

Просмотреть файл

@ -56,9 +56,6 @@ class TestConfigure(unittest.TestCase):
'VALUES2': NegativeOptionValue(),
'VALUES3': NegativeOptionValue(),
'WITH_ENV': NegativeOptionValue(),
'IMPLIED': NegativeOptionValue(),
'IMPLIED_ENV': NegativeOptionValue(),
'IMPLIED_VALUES': NegativeOptionValue(),
}, config)
def test_help(self):
@ -77,8 +74,6 @@ class TestConfigure(unittest.TestCase):
' --with-stuff Build with stuff\n'
' --option Option\n'
' --with-returned-default Returned default [not-simple]\n'
' --enable-implied Implied\n'
' --with-implied-values Implied values\n'
' --returned-choices Choices\n'
' --enable-advanced-template\n'
' Advanced template\n'
@ -86,8 +81,7 @@ class TestConfigure(unittest.TestCase):
' --with-advanced Advanced\n'
'\n'
'Environment variables:\n'
' CC C Compiler\n'
' WITH_IMPLIED_ENV Implied env\n',
' CC C Compiler\n',
out
)
@ -190,47 +184,6 @@ class TestConfigure(unittest.TestCase):
self.assertEquals(
PositiveOptionValue(('not-simple',)), config['DEFAULTED'])
def test_implied_options(self):
config = self.get_config(['--enable-values'])
self.assertIn('IMPLIED', config)
self.assertIn('IMPLIED_VALUES', config)
self.assertIn('IMPLIED_ENV', config)
self.assertEquals(PositiveOptionValue(), config['IMPLIED'])
self.assertEquals(PositiveOptionValue(), config['IMPLIED_VALUES'])
self.assertEquals(PositiveOptionValue(), config['IMPLIED_ENV'])
config = self.get_config(['--enable-values=a'])
self.assertIn('IMPLIED', config)
self.assertIn('IMPLIED_VALUES', config)
self.assertIn('IMPLIED_ENV', config)
self.assertEquals(PositiveOptionValue(), config['IMPLIED'])
self.assertEquals(
PositiveOptionValue(('a',)), config['IMPLIED_VALUES'])
self.assertEquals(PositiveOptionValue(('a',)), config['IMPLIED_ENV'])
config = self.get_config(['--enable-values=a,b'])
self.assertIn('IMPLIED', config)
self.assertIn('IMPLIED_VALUES', config)
self.assertIn('IMPLIED_ENV', config)
self.assertEquals(PositiveOptionValue(), config['IMPLIED'])
self.assertEquals(
PositiveOptionValue(('a', 'b')), config['IMPLIED_VALUES'])
self.assertEquals(
PositiveOptionValue(('a', 'b')), config['IMPLIED_ENV'])
config = self.get_config(['--disable-values'])
self.assertIn('IMPLIED', config)
self.assertIn('IMPLIED_VALUES', config)
self.assertIn('IMPLIED_ENV', config)
self.assertEquals(NegativeOptionValue(), config['IMPLIED'])
self.assertEquals(NegativeOptionValue(), config['IMPLIED_VALUES'])
self.assertEquals(NegativeOptionValue(), config['IMPLIED_ENV'])
# --enable-values implies --enable-implied, which conflicts with
# --disable-implied
with self.assertRaises(InvalidOptionError):
self.get_config(['--enable-values', '--disable-implied'])
def test_returned_choices(self):
for val in ('a', 'b', 'c'):
config = self.get_config(
@ -372,6 +325,102 @@ class TestConfigure(unittest.TestCase):
# set_define('FOO'...)
get_config(['--set-foo', '--set-name=FOO'])
def test_imply_option_simple(self):
config = self.get_config([], configure='imply_option/simple.configure')
self.assertEquals(config, {})
config = self.get_config(['--enable-foo'],
configure='imply_option/simple.configure')
self.assertIn('BAR', config)
self.assertEquals(config['BAR'], PositiveOptionValue())
with self.assertRaises(InvalidOptionError) as e:
config = self.get_config(['--enable-foo', '--disable-bar'],
configure='imply_option/simple.configure')
self.assertEquals(
e.exception.message,
"'--enable-bar' implied by '--enable-foo' conflicts with "
"'--disable-bar' from the command-line")
def test_imply_option_negative(self):
config = self.get_config([],
configure='imply_option/negative.configure')
self.assertEquals(config, {})
config = self.get_config(['--enable-foo'],
configure='imply_option/negative.configure')
self.assertIn('BAR', config)
self.assertEquals(config['BAR'], NegativeOptionValue())
with self.assertRaises(InvalidOptionError) as e:
config = self.get_config(
['--enable-foo', '--enable-bar'],
configure='imply_option/negative.configure')
self.assertEquals(
e.exception.message,
"'--disable-bar' implied by '--enable-foo' conflicts with "
"'--enable-bar' from the command-line")
config = self.get_config(['--disable-hoge'],
configure='imply_option/negative.configure')
self.assertIn('BAR', config)
self.assertEquals(config['BAR'], NegativeOptionValue())
with self.assertRaises(InvalidOptionError) as e:
config = self.get_config(
['--disable-hoge', '--enable-bar'],
configure='imply_option/negative.configure')
self.assertEquals(
e.exception.message,
"'--disable-bar' implied by '--disable-hoge' conflicts with "
"'--enable-bar' from the command-line")
def test_imply_option_values(self):
config = self.get_config([], configure='imply_option/values.configure')
self.assertEquals(config, {})
config = self.get_config(['--enable-foo=a'],
configure='imply_option/values.configure')
self.assertIn('BAR', config)
self.assertEquals(config['BAR'], PositiveOptionValue(('a',)))
config = self.get_config(['--enable-foo=a,b'],
configure='imply_option/values.configure')
self.assertIn('BAR', config)
self.assertEquals(config['BAR'], PositiveOptionValue(('a','b')))
with self.assertRaises(InvalidOptionError) as e:
config = self.get_config(['--enable-foo=a,b', '--disable-bar'],
configure='imply_option/values.configure')
self.assertEquals(
e.exception.message,
"'--enable-bar=a,b' implied by '--enable-foo' conflicts with "
"'--disable-bar' from the command-line")
def test_imply_option_infer(self):
config = self.get_config([], configure='imply_option/infer.configure')
with self.assertRaises(InvalidOptionError) as e:
config = self.get_config(['--enable-foo', '--disable-bar'],
configure='imply_option/infer.configure')
self.assertEquals(
e.exception.message,
"'--enable-bar' implied by '--enable-foo' conflicts with "
"'--disable-bar' from the command-line")
with self.assertRaises(ConfigureError) as e:
self.get_config([], configure='imply_option/infer_ko.configure')
self.assertEquals(
e.exception.message,
"Cannot infer what implies '--enable-bar'. Please add a `reason` "
"to the `imply_option` call.")
if __name__ == '__main__':
main()

Просмотреть файл

@ -29,11 +29,11 @@ option('--enable-jprof', env='MOZ_JPROF',
@depends('--enable-jprof')
def jprof(value):
if value:
imply_option('--enable-profiling')
return True
set_config('MOZ_JPROF', jprof)
set_define('MOZ_JPROF', jprof)
imply_option('--enable-profiling', jprof)
@depends(target)
def sps_profiler(target):
@ -60,11 +60,11 @@ option('--enable-dmd', env='MOZ_DMD',
def dmd(value):
if value:
add_old_configure_assignment('MOZ_DMD', True)
imply_option('--enable-profiling')
return True
set_config('MOZ_DMD', dmd)
set_define('MOZ_DMD', dmd)
imply_option('--enable-profiling', dmd)
# Javascript engine
# ==============================================================
@ -307,11 +307,11 @@ def ffmpeg(value, target):
if value.origin == 'default':
enabled = target.os not in ('Android', 'WINNT')
if enabled:
imply_option('--enable-fmp4', '--enable-ffmpeg')
return True
set_config('MOZ_FFMPEG', ffmpeg)
set_define('MOZ_FFMPEG', ffmpeg)
imply_option('--enable-fmp4', ffmpeg, '--enable-ffmpeg')
# Built-in fragmented MP4 support.
# ==============================================================