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

The way set_config is set currently makes it difficult to introspect
moz.configure files to know what configuration items are being set,
because they're hidden in the control flow of functions.

This makes some of the moz.configure more convoluted, but this is why
there are templates, and we can improve the recurring cases afterwards.
This commit is contained in:
Mike Hommey 2016-03-22 14:21:32 +09:00
parent 8e6cfd60f3
commit 7cd6c430c1
15 changed files with 392 additions and 131 deletions

View File

@ -14,8 +14,10 @@ def mozttdir(value):
path = value[0]
if not os.path.isdir(path):
error('MOZTTDIR "%s" is not a valid directory' % path)
set_config('MOZTTDIR', path)
set_define('PACKAGE_MOZTT', True)
return path
set_config('MOZTTDIR', mozttdir)
include('../toolkit/moz.configure')

View File

@ -70,11 +70,16 @@ def check_prog(var, progs, allow_missing=False):
@depends(check)
@advanced
def postcheck(value):
set_config(var, ':' if value is not_found else value)
if value is not_found and not allow_missing:
from mozbuild.shellutil import quote
error('Cannot find %s (tried: %s)'
% (var.lower(), ', '.join(quote(p) for p in progs)))
return None if value is not_found else value
@depends(postcheck)
def normalized_for_config(value):
return ':' if value is None else value
set_config(var, normalized_for_config)
return postcheck

View File

@ -26,10 +26,6 @@ def check_build_environment(help, dist):
topobjdir=topobjdir,
dist=dist,
)
set_config('TOPSRCDIR', topsrcdir)
set_config('TOPOBJDIR', topobjdir)
set_config('MOZ_BUILD_ROOT', topobjdir)
set_config('DIST', dist)
if help:
return result
@ -69,6 +65,12 @@ def check_build_environment(help, dist):
return result
set_config('TOPSRCDIR', delayed_getattr(check_build_environment, 'topsrcdir'))
set_config('TOPOBJDIR', delayed_getattr(check_build_environment, 'topobjdir'))
set_config('MOZ_BUILD_ROOT', delayed_getattr(check_build_environment,
'topobjdir'))
set_config('DIST', delayed_getattr(check_build_environment, 'dist'))
option(env='OLD_CONFIGURE', nargs=1, help='Path to the old configure script')
@ -220,10 +222,10 @@ def virtualenv_python(env_python, build_env, mozconfig):
if not distutils.sysconfig.get_python_lib():
error('Could not determine python site packages directory')
set_config('PYTHON', python)
add_old_configure_assignment('PYTHON', python)
return python
set_config('PYTHON', virtualenv_python)
# Inject mozconfig options
# ==============================================================
@ -504,25 +506,32 @@ def target_variables(target):
os_target = target.os
os_arch = target.kernel
add_old_configure_assignment('OS_TARGET', os_target)
set_config('OS_TARGET', os_target)
add_old_configure_assignment('OS_ARCH', os_arch)
set_config('OS_ARCH', os_arch)
if target.os == 'Darwin' and target.cpu == 'x86':
os_test = 'i386'
else:
os_test = target.raw_cpu
add_old_configure_assignment('OS_TEST', os_test)
set_config('OS_TEST', os_test)
add_old_configure_assignment('CPU_ARCH', target.cpu)
set_config('CPU_ARCH', target.cpu)
if target.cpu in ('x86', 'x86_64'):
set_config('INTEL_ARCHITECTURE', True)
return namespace(
OS_TARGET=os_target,
OS_ARCH=os_arch,
OS_TEST=os_test,
INTEL_ARCHITECTURE=target.cpu in ('x86', 'x86_64') or None,
)
set_config('OS_TARGET', delayed_getattr(target_variables, 'OS_TARGET'))
set_config('OS_ARCH', delayed_getattr(target_variables, 'OS_ARCH'))
set_config('OS_TEST', delayed_getattr(target_variables, 'OS_TEST'))
set_config('CPU_ARCH', delayed_getattr(target, 'cpu'))
set_config('INTEL_ARCHITECTURE', delayed_getattr(target_variables,
'INTEL_ARCHITECTURE'))
set_config('TARGET_CPU', delayed_getattr(target, 'raw_cpu'))
set_config('TARGET_OS', delayed_getattr(target, 'raw_os'))
set_config('TARGET_CPU', target.raw_cpu)
set_config('TARGET_OS', target.raw_os)
@depends(host)
def host_variables(host):
@ -531,8 +540,11 @@ def host_variables(host):
else:
os_arch = host.kernel
add_old_configure_assignment('HOST_OS_ARCH', os_arch)
set_config('HOST_OS_ARCH', os_arch)
return namespace(
HOST_OS_ARCH=os_arch,
)
set_config('HOST_OS_ARCH', delayed_getattr(host_variables, 'HOST_OS_ARCH'))
@depends(target)
def target_platform_defines(target):
@ -585,7 +597,6 @@ def include_project_configure(project, external_source_dir, build_env, help):
base_dir = build_env.topsrcdir
if external_source_dir:
set_config('EXTERNAL_SOURCE_DIR', external_source_dir[0])
add_old_configure_assignment('EXTERNAL_SOURCE_DIR',
external_source_dir[0])
base_dir = os.path.join(base_dir, external_source_dir[0])
@ -595,15 +606,24 @@ def include_project_configure(project, external_source_dir, build_env, help):
error('Cannot find project %s' % project[0])
return path
@depends('--with-external-source-dir')
def external_source_dir(value):
if value:
return value[0]
set_config('EXTERNAL_SOURCE_DIR', external_source_dir)
@depends(include_project_configure, check_build_environment, '--help')
def build_project(include_project_configure, build_env, help):
ret = os.path.dirname(os.path.relpath(include_project_configure,
build_env.topsrcdir))
set_config('MOZ_BUILD_APP', ret)
set_define('MOZ_BUILD_APP', ret)
add_old_configure_assignment('MOZ_BUILD_APP', ret)
return ret
set_config('MOZ_BUILD_APP', build_project)
# set RELEASE_BUILD and NIGHTLY_BUILD variables depending on the cycle we're in
# The logic works like this:
@ -619,17 +639,13 @@ def milestone(build_env):
with open(milestone_path, 'r') as fh:
milestone = fh.read().splitlines()[-1]
set_config('GRE_MILESTONE', milestone)
is_nightly = is_release = False
is_nightly = is_release = None
if 'a1' in milestone:
set_config('NIGHTLY_BUILD', True)
set_define('NIGHTLY_BUILD', True)
add_old_configure_assignment('NIGHTLY_BUILD', True)
is_nightly = True
elif 'a' not in milestone:
set_config('RELEASE_BUILD', True)
set_define('RELEASE_BUILD', True)
add_old_configure_assignment('RELEASE_BUILD', True)
is_release = True
@ -638,6 +654,11 @@ def milestone(build_env):
is_nightly=is_nightly,
is_release=is_release)
set_config('GRE_MILESTONE', delayed_getattr(milestone, 'version'))
set_config('NIGHTLY_BUILD', delayed_getattr(milestone, 'is_nightly'))
set_config('RELEASE_BUILD', delayed_getattr(milestone, 'is_release'))
# This is temporary until js/src/configure and configure are merged.
# Use instead of option() in js/moz.configure
@template

View File

@ -56,9 +56,10 @@ def autoconf(mozconfig, autoconf):
if not os.path.exists(autoconf):
error('Could not find autoconf 2.13 at %s' % (autoconf,))
set_config('AUTOCONF', autoconf)
return autoconf
set_config('AUTOCONF', autoconf)
# See comment in mozconfig_options() from build/moz.configure/init.configure
@template
@ -371,7 +372,6 @@ def old_configure(prepare_configure, extra_old_configure_args, all_options,
import os
import subprocess
import sys
import types
from mozbuild.shellutil import quote
cmd = prepare_configure
@ -417,12 +417,28 @@ def old_configure(prepare_configure, extra_old_configure_args, all_options,
# If the code execution above fails, we want to keep the file around for
# debugging.
os.remove('config.data')
return raw_config
# set_config is only available in the global namespace, not directly in
# @depends functions, but we do need to enumerate the result of
# old_configure, so we cheat.
@template
def set_old_configure_config(name, value):
set_config(name, value)
@depends(old_configure)
@advanced
def post_old_configure(raw_config):
import types
config = {}
for k, v in raw_config['substs']:
set_config(k[1:-1], v[1:-1] if isinstance(v, types.StringTypes) else v)
set_old_configure_config(
k[1:-1], v[1:-1] if isinstance(v, types.StringTypes) else v)
for k, v in dict(raw_config['defines']).iteritems():
set_define(k[1:-1], v[1:-1])
set_config('non_global_defines', raw_config['non_global_defines'])
set_old_configure_config('non_global_defines',
raw_config['non_global_defines'])

View File

@ -106,3 +106,21 @@ def deprecated_option(*args, **kwargs):
def namespace(**kwargs):
from mozbuild.util import ReadOnlyNamespace
return ReadOnlyNamespace(**kwargs)
# Some @depends function return namespaces, and one could want to use one
# specific attribute from such a namespace as a "value" given to functions
# such as `set_config`. But those functions do not take immediate values.
# The `delayed_getattr` function allows access to attributes from the result
# of a @depends function in a non-immediate manner.
# @depends('--option')
# def option(value)
# return namespace(foo=value)
# set_config('FOO', delayed_getattr(option, 'foo')
@template
def delayed_getattr(func, key):
@depends(func)
@advanced
def result(value):
return getattr(value, key)
return result

View File

@ -21,17 +21,20 @@ option(env='JS_STANDALONE', default=building_js,
@depends('JS_STANDALONE')
def js_standalone(value):
if value:
set_config('JS_STANDALONE', True)
add_old_configure_assignment('JS_STANDALONE', True)
return True
set_config('JS_STANDALONE', js_standalone)
js_option('--disable-js-shell', default=building_js,
help='Do not build the JS shell')
@depends('--disable-js-shell')
def js_shell(value):
def js_disable_shell(value):
if not value:
set_config('JS_DISABLE_SHELL', True)
return True
set_config('JS_DISABLE_SHELL', js_disable_shell)
# Use SpiderMonkey Promise implementation if it's enabled
@ -41,9 +44,10 @@ js_option('--enable-sm-promise', help='Enable SpiderMonkey promises')
@depends('--enable-sm-promise')
def sm_promise(value):
if value:
set_config('SPIDERMONKEY_PROMISE', True)
set_define('SPIDERMONKEY_PROMISE', True)
return True
set_config('SPIDERMONKEY_PROMISE', sm_promise)
# SpiderMonkey as a shared library, and how its symbols are exported
# ==================================================================
@ -58,7 +62,6 @@ def static_js(shared_js, export_js):
if shared_js:
if not export_js:
error('Must export JS symbols when building a shared library.')
set_config('JS_SHARED_LIBRARY', True)
add_old_configure_assignment('JS_SHARED_LIBRARY', True)
else:
if export_js:
@ -67,6 +70,12 @@ def static_js(shared_js, export_js):
set_define('STATIC_JS_API', True)
set_define('MOZ_STATIC_JS', True)
@depends('--disable-shared-js')
def shared_js(value):
if value:
return True
set_config('JS_SHARED_LIBRARY', shared_js)
@deprecated_option(env='DISABLE_SHARED_JS', nargs='?')
def disable_shared_js(value):
@ -102,11 +111,12 @@ def instruments(value, target):
error('--enable-instruments cannot be used when targeting %s'
% target.os)
if value:
set_config('MOZ_INSTRUMENTS', True)
set_define('MOZ_INSTRUMENTS', True)
add_old_configure_assignment('MOZ_INSTRUMENTS', True)
imply_option('--enable-profiling', reason='--enable-instruments')
return True
set_config('MOZ_INSTRUMENTS', instruments)
js_option('--enable-callgrind', env='MOZ_CALLGRIND',
help='Enable callgrind profiling')
@ -125,13 +135,15 @@ js_option('--enable-profiling', env='MOZ_PROFILING',
@depends('--enable-profiling', target)
def profiling(value, target):
if value:
set_config('MOZ_PROFILING', True)
set_define('MOZ_PROFILING', True)
add_old_configure_assignment('MOZ_PROFILING', True)
if target.kernel == 'WINNT' or (target.kernel == 'Linux' and
target.os == 'GNU'):
imply_option('--enable-vtune', reason='--enable-profiling')
return True
set_config('MOZ_PROFILING', profiling)
js_option('--enable-vtune', env='MOZ_VTUNE', help='Enable vtune profiling')
@ -139,5 +151,7 @@ js_option('--enable-vtune', env='MOZ_VTUNE', help='Enable vtune profiling')
@depends('--enable-vtune')
def vtune(value):
if value:
set_config('MOZ_VTUNE', True)
set_define('MOZ_VTUNE', True)
return True
set_config('MOZ_VTUNE', vtune)

View File

@ -12,11 +12,16 @@ option('--with-gradle', nargs='?',
help='Enable building mobile/android with Gradle '
'(argument: location of binary or wrapper (gradle/gradlew))')
@depends('--with-gradle')
def with_gradle(value):
if value:
return True
set_config('MOZ_BUILD_MOBILE_ANDROID_WITH_GRADLE', with_gradle)
@depends('--with-gradle', check_build_environment)
def gradle(value, build_env):
if value:
set_config('MOZ_BUILD_MOBILE_ANDROID_WITH_GRADLE', True)
gradle = value[0] if len(value) else \
os.path.join(build_env.topsrcdir, 'gradlew')
@ -24,10 +29,10 @@ def gradle(value, build_env):
if not os.path.isfile(gradle):
error('GRADLE must be executable: %s' % gradle)
set_config('GRADLE', gradle)
return gradle
set_config('GRADLE', gradle)
# Automation uses this to change log levels, not use the daemon, and use
# offline mode.
@ -35,7 +40,9 @@ option(env='GRADLE_FLAGS', default='', help='Flags to pass to Gradle.')
@depends('GRADLE_FLAGS')
def gradle_flags(value):
set_config('GRADLE_FLAGS', value[0] if value else '')
return value[0] if value else ''
set_config('GRADLE_FLAGS', gradle_flags)
# Automation will set this to file:///path/to/local via the mozconfig.
@ -46,4 +53,6 @@ option(env='GRADLE_MAVEN_REPOSITORY', default='https://jcenter.bintray.com/',
@depends('GRADLE_MAVEN_REPOSITORY')
def gradle_maven_repository(value):
if value:
set_config('GRADLE_MAVEN_REPOSITORY', value[0])
return value[0]
set_config('GRADLE_MAVEN_REPOSITORY', gradle_maven_repository)

View File

@ -20,8 +20,10 @@ include('build/moz.configure/checks.configure')
@depends(milestone)
def e10s_testing_only(milestone):
if not milestone.is_release:
set_config('E10S_TESTING_ONLY', True)
set_define('E10S_TESTING_ONLY', True)
return True
set_config('E10S_TESTING_ONLY', e10s_testing_only)
option('--enable-artifact-builds', env='MOZ_ARTIFACT_BUILDS',
@ -31,8 +33,9 @@ option('--enable-artifact-builds', env='MOZ_ARTIFACT_BUILDS',
def artifact_builds(value):
if value:
imply_option('--disable-compile-environment')
set_config('MOZ_ARTIFACT_BUILDS', True)
return bool(value)
return True
set_config('MOZ_ARTIFACT_BUILDS', artifact_builds)
option('--disable-compile-environment',
@ -41,9 +44,10 @@ option('--disable-compile-environment',
@depends('--disable-compile-environment')
def compile_environment(value):
if value:
set_config('COMPILE_ENVIRONMENT', True)
add_old_configure_assignment('COMPILE_ENVIRONMENT', True)
return bool(value)
return True
set_config('COMPILE_ENVIRONMENT', compile_environment)
@depends('--help')
@ -63,7 +67,9 @@ def build_backend(backends, artifact_builds):
else:
all_backends = ['RecursiveMake', 'FasterMake']
all_backends.extend(backends)
set_config('BUILD_BACKENDS', unique_list(all_backends))
return unique_list(all_backends)
set_config('BUILD_BACKENDS', build_backend)
# Awk detection
@ -160,12 +166,20 @@ def yasm_asflags(yasm, target):
asflags = '-f elf64'
if asflags:
asflags += ' -rnasm -pnasm'
set_config('YASM_ASFLAGS', asflags)
set_config('HAVE_YASM', True)
# Until the YASM variable is not necessary in old-configure.
add_old_configure_assignment('YASM', True)
return asflags
set_config('YASM_ASFLAGS', yasm_asflags)
@depends(yasm_asflags)
def have_yasm(value):
if value:
return True
set_config('HAVE_YASM', have_yasm)
# Miscellaneous programs
# ==============================================================
check_prog('DOXYGEN', ('doxygen',), allow_missing=True)

View File

@ -40,8 +40,8 @@ class SandboxedGlobal(dict):
'''Identifiable dict type for use as function global'''
class DependsOutput(dict):
'''Dict holding the results yielded by a @depends function.'''
class DependsOutput(object):
'''Class for objects holding the options implied by a @depends function.'''
__slots__ = ('implied_options',)
def __init__(self):
@ -222,13 +222,13 @@ class ConfigureSandbox(dict):
return super(ConfigureSandbox, self).__setitem__(key, value)
def _resolve(self, arg):
def _resolve(self, arg, need_help_dependency=True):
if isinstance(arg, DummyFunction):
assert arg in self._depends
func = self._depends[arg]
assert not inspect.isgeneratorfunction(func)
assert func in self._results
if not func.with_help:
if need_help_dependency and not func.with_help:
raise ConfigureError("Missing @depends for `%s`: '--help'" %
func.__name__)
result = self._results[func]
@ -290,12 +290,11 @@ 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 three additional functions:
`imply_option`, `set_config` and `set_define`. The first allows to
inject additional options as if they had been passed on the command
line. The second declares new configuration items for consumption by
moz.build. The last declares new defines, stored in a DEFINES
configuration item.
set of functions from os.path, and two additional functions:
`imply_option` and `set_define`. The former allows to inject
additional options as if they had been passed on the command line.
The latter declares new defines, stored in a DEFINES configuration
item.
'''
if not args:
raise ConfigureError('@depends needs at least one argument')
@ -335,7 +334,6 @@ class ConfigureSandbox(dict):
result = DependsOutput()
glob.update(
imply_option=result.imply_option,
set_config=result.__setitem__,
set_define=self._set_define,
)
dummy = wraps(func)(DummyFunction())
@ -376,14 +374,6 @@ class ConfigureSandbox(dict):
self._implied_options[option] = func, reason
if not self._help:
for k, v in result.iteritems():
if k in self._config:
raise ConfigureError(
"Cannot add '%s' to configuration: Key already "
"exists" % k)
self._config[k] = v
return dummy
return decorator
@ -415,6 +405,7 @@ class ConfigureSandbox(dict):
advanced=self.advanced_impl,
depends=self.depends_impl,
option=self.option_impl,
set_config=self.set_config_impl,
)
self._templates.add(template)
return template
@ -428,6 +419,29 @@ class ConfigureSandbox(dict):
glob.update(__builtins__=__builtins__)
return func
def set_config_impl(self, name, value):
'''Implementation of set_config().
Set the configuration items with the given name to the given value.
Both `name` and `value` can be references to @depends functions,
in which case the result from these functions is used. If the result
of either function is None, the configuration item is not set.
'''
# Don't set anything when --help was on the command line
if self._help:
return
name = self._resolve(name, need_help_dependency=False)
if name is None:
return
if not isinstance(name, types.StringTypes):
raise TypeError("Unexpected type: '%s'" % type(name))
if name in self._config:
raise ConfigureError(
"Cannot add '%s' to configuration: Key already "
"exists" % name)
value = self._resolve(value, need_help_dependency=False)
if value is not None:
self._config[name] = value
def _set_define(self, name, value):
defines = self._config.setdefault('DEFINES', {})
if name in defines:

View File

@ -8,4 +8,6 @@ option('--extra', help='Extra')
@depends('--extra')
def extra(extra):
set_config('EXTRA', extra)
return extra
set_config('EXTRA', extra)

View File

@ -10,10 +10,11 @@ def check_compiler_flag(flag):
@depends(is_gcc)
def check(value):
if value:
set_config('CFLAGS', [flag])
return [flag]
set_config('CFLAGS', check)
return check
check_compiler_flag('-Werror=foobar')
# A template that doesn't return functions can be used in @depends functions.
@ -28,9 +29,17 @@ def twentyone():
@depends(is_gcc)
def check(value):
if value:
set_config('TEMPLATE_VALUE', fortytwo())
return fortytwo()
set_config('TEMPLATE_VALUE', check)
@depends(is_gcc)
def check(value):
if value:
for val in twentyone():
set_config('TEMPLATE_VALUE_2', val)
return val
set_config('TEMPLATE_VALUE_2', check)
# Templates can use @advanced too to import modules and get the full set of
# builtins.
@ -44,4 +53,6 @@ option('--enable-advanced-template', help='Advanced template')
@depends('--enable-advanced-template')
def check(value):
if value:
set_config('PLATFORM', platform())
return platform()
set_config('PLATFORM', check)

View File

@ -40,38 +40,44 @@ option(env='CC', nargs=1, help='C Compiler')
@depends('--enable-simple')
def simple(simple):
if simple:
set_config('ENABLED_SIMPLE', simple)
return simple
set_config('ENABLED_SIMPLE', simple)
# There can be multiple functions depending on the same option.
@depends('--enable-simple')
def simple(simple):
set_config('SIMPLE', simple)
return simple
set_config('SIMPLE', simple)
@depends('--enable-with-env')
def with_env(with_env):
set_config('WITH_ENV', with_env)
return with_env
set_config('WITH_ENV', with_env)
# It doesn't matter if the dependency is on --enable or --disable
@depends('--disable-values')
def with_env2(values):
set_config('VALUES', values)
return values
set_config('VALUES', with_env2)
# It is possible to @depends on environment-only options.
@depends('CC')
def is_gcc(cc):
return cc and 'gcc' in cc[0]
@depends(is_gcc)
def is_gcc_check(is_gcc):
set_config('IS_GCC', is_gcc)
set_config('IS_GCC', is_gcc)
# It is possible to depend on the result from another function.
@depends(with_env2)
def with_env3(values):
set_config('VALUES2', values)
return values
set_config('VALUES2', with_env3)
# @depends functions can also return results for use as input to another
# @depends.
@depends(with_env3)
@ -80,7 +86,9 @@ def with_env4(values):
@depends(with_env4)
def with_env5(values):
set_config('VALUES3', values)
return values
set_config('VALUES3', with_env5)
# The result from @depends functions can also be used as input to options.
# The result must be returned, not implied. The function must also depend
@ -93,7 +101,9 @@ option('--with-returned-default', default=simple, help='Returned default')
@depends('--with-returned-default')
def default(value):
set_config('DEFAULTED', value)
return 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
@ -113,15 +123,21 @@ option(env='WITH_IMPLIED_ENV', nargs='*', help='Implied env')
@depends('--enable-implied')
def implied(value):
set_config('IMPLIED', value)
return value
set_config('IMPLIED', implied)
@depends('--with-implied-values')
def implied(values):
set_config('IMPLIED_VALUES', values)
return values
set_config('IMPLIED_VALUES', implied)
@depends('WITH_IMPLIED_ENV')
def implied(values):
set_config('IMPLIED_ENV', values)
return values
set_config('IMPLIED_ENV', implied)
@depends('--enable-values', '--help')
def choices(values, help):
@ -135,13 +151,17 @@ option('--returned-choices', choices=choices, help='Choices')
@depends('--returned-choices')
def returned_choices(values):
set_config('CHOICES', values)
return values
set_config('CHOICES', returned_choices)
# All options must be referenced by some @depends function.
# It is possible to depend on multiple options/functions
@depends('--without-thing', '--with-stuff', with_env4, '--option')
def remainder(*args):
set_config('REMAINDER', args)
return args
set_config('REMAINDER', remainder)
# It is possible to include other files to extend the configuration script.
include('included.configure')
@ -165,21 +185,27 @@ option('--with-advanced', nargs='?', help='Advanced')
def with_advanced(value):
if value:
from mozbuild.configure.options import OptionValue
set_config('ADVANCED', isinstance(value, OptionValue))
return isinstance(value, OptionValue)
set_config('ADVANCED', with_advanced)
# Trying to import without @advanced will fail at runtime.
@depends('--with-advanced')
def with_advanced(value):
if len(value) and value[0] == 'break':
from mozbuild.configure.options import OptionValue
set_config('ADVANCED', isinstance(value, OptionValue))
return isinstance(value, OptionValue)
set_config('ADVANCED2', with_advanced)
# A limited set of functions from os.path are exposed to non @advanced
# functions.
@depends('--with-advanced')
def with_advanced(value):
if len(value):
set_config('IS_FILE', os.path.isfile(value[0]))
return os.path.isfile(value[0])
set_config('IS_FILE', with_advanced)
# An @advanced function can still import the full set.
@depends('--with-advanced')
@ -187,10 +213,14 @@ def with_advanced(value):
def with_advanced(value):
if len(value):
import os.path
set_config('HAS_GETATIME', hasattr(os.path, 'getatime'))
return hasattr(os.path, 'getatime')
set_config('HAS_GETATIME', with_advanced)
@depends('--with-advanced')
@advanced
def with_advanced(value):
if len(value):
set_config('HAS_GETATIME2', hasattr(os.path, 'getatime'))
return hasattr(os.path, 'getatime')
set_config('HAS_GETATIME2', with_advanced)

View File

@ -0,0 +1,43 @@
# -*- 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('--set-foo', help='set foo')
@depends('--set-foo')
def foo(value):
if value:
return True
set_config('FOO', foo)
option('--set-bar', help='set bar')
@depends('--set-bar')
def bar(value):
return bool(value)
set_config('BAR', bar)
option('--set-value', nargs=1, help='set value')
@depends('--set-value')
def set_value(value):
if value:
return value[0]
set_config('VALUE', set_value)
option('--set-name', nargs=1, help='set name')
@depends('--set-name')
def set_name(value):
if value:
return value[0]
set_config(set_name, True)

View File

@ -15,7 +15,10 @@ from mozbuild.configure.options import (
NegativeOptionValue,
PositiveOptionValue,
)
from mozbuild.configure import ConfigureSandbox
from mozbuild.configure import (
ConfigureError,
ConfigureSandbox,
)
import mozpack.path as mozpath
@ -24,17 +27,18 @@ test_data_path = mozpath.join(test_data_path, 'data')
class TestConfigure(unittest.TestCase):
def get_result(self, args=[], environ={}, prog='/bin/configure'):
def get_result(self, args=[], environ={}, configure='moz.configure',
prog='/bin/configure'):
config = {}
out = StringIO()
sandbox = ConfigureSandbox(config, environ, [prog] + args, out, out)
sandbox.run(mozpath.join(test_data_path, 'moz.configure'))
sandbox.run(mozpath.join(test_data_path, configure))
return config, out.getvalue()
def get_config(self, options=[], env={}):
config, out = self.get_result(options, environ=env)
def get_config(self, options=[], env={}, **kwargs):
config, out = self.get_result(options, environ=env, **kwargs)
self.assertEquals('', out)
return config
@ -302,6 +306,39 @@ class TestConfigure(unittest.TestCase):
self.assertIn('PLATFORM', config)
self.assertEquals(config['PLATFORM'], sys.platform)
def test_set_config(self):
def get_config(*args):
return self.get_config(*args, configure='set_config.configure')
config, out = self.get_result(['--help'],
configure='set_config.configure')
self.assertEquals(config, {})
config = get_config(['--set-foo'])
self.assertIn('FOO', config)
self.assertEquals(config['FOO'], True)
config = get_config(['--set-bar'])
self.assertNotIn('FOO', config)
self.assertIn('BAR', config)
self.assertEquals(config['BAR'], True)
config = get_config(['--set-value=qux'])
self.assertIn('VALUE', config)
self.assertEquals(config['VALUE'], 'qux')
config = get_config(['--set-name=hoge'])
self.assertIn('hoge', config)
self.assertEquals(config['hoge'], True)
config = get_config([])
self.assertEquals(config, {'BAR': False})
with self.assertRaises(ConfigureError):
# Both --set-foo and --set-name=FOO are going to try to
# set_config('FOO'...)
get_config(['--set-foo', '--set-name=FOO'])
if __name__ == '__main__':
main()

View File

@ -27,10 +27,11 @@ option('--enable-jprof', env='MOZ_JPROF',
@depends('--enable-jprof')
def jprof(value):
if value:
set_config('MOZ_JPROF', True)
set_define('MOZ_JPROF', True)
imply_option('--enable-profiling')
return True
set_config('MOZ_JPROF', jprof)
@depends(target)
def sps_profiler(target):
@ -43,8 +44,10 @@ def sps_profiler(target):
@depends(sps_profiler)
def sps_profiler_define(value):
if value:
set_config('MOZ_ENABLE_PROFILER_SPS', True)
set_define('MOZ_ENABLE_PROFILER_SPS', True)
return True
set_config('MOZ_ENABLE_PROFILER_SPS', sps_profiler_define)
option('--enable-dmd', env='MOZ_DMD',
@ -54,11 +57,12 @@ option('--enable-dmd', env='MOZ_DMD',
@depends('--enable-dmd')
def dmd(value):
if value:
set_config('MOZ_DMD', True)
set_define('MOZ_DMD', True)
add_old_configure_assignment('MOZ_DMD', True)
imply_option('--enable-profiling')
return True
set_config('MOZ_DMD', dmd)
# Javascript engine
# ==============================================================
@ -76,8 +80,9 @@ def l10n_base(value):
path = value[0]
if not os.path.isdir(path):
error("Invalid value --with-l10n-base, %s doesn't exist" % path)
return os.path.realpath(os.path.abspath(path))
set_config('L10NBASEDIR', os.path.realpath(os.path.abspath(path)))
set_config('L10NBASEDIR', l10n_base)
# Default toolkit
@ -131,7 +136,6 @@ def toolkit(toolkit):
widget_toolkit = 'gtk2'
else:
widget_toolkit = toolkit.replace('cairo-', '')
set_config('MOZ_WIDGET_TOOLKIT', widget_toolkit)
add_old_configure_assignment('MOZ_WIDGET_TOOLKIT', widget_toolkit)
if widget_toolkit == 'gtk2':
@ -143,6 +147,8 @@ def toolkit(toolkit):
return widget_toolkit
set_config('MOZ_WIDGET_TOOLKIT', toolkit)
option('--without-x', env='WITHOUT_X', help='Disable X11 support')
@ -157,42 +163,55 @@ def x11(value, toolkit):
% ','.join(x11_toolkits))
if value and toolkit in x11_toolkits:
set_config('MOZ_ENABLE_XREMOTE', True)
set_define('MOZ_ENABLE_XREMOTE', True)
set_config('MOZ_X11', True)
set_define('MOZ_X11', True)
add_old_configure_assignment('MOZ_X11', True)
return value and toolkit in x11_toolkits
return True if value and toolkit in x11_toolkits else None
set_config('MOZ_ENABLE_XREMOTE', x11)
set_config('MOZ_X11', x11)
# GL Provider
# ==============================================================
option('--with-gl-provider', nargs=1, help='Set GL provider backend type')
@depends('--with-gl-provider', x11)
def gl_provider(value, x11):
@depends('--with-gl-provider')
def gl_provider(value):
if value:
provider = value[0]
set_config('MOZ_GL_PROVIDER', provider)
set_define('MOZ_GL_PROVIDER', 'GLContextProvider%s' % provider)
set_config('MOZ_GL_DEFAULT_PROVIDER', provider)
set_define('GL_PROVIDER_%s' % provider, True)
elif x11:
set_config('MOZ_GL_DEFAULT_PROVIDER', 'GLX')
set_define('GL_PROVIDER_GLX', True)
return provider
@depends(gl_provider, x11)
def gl_default_provider(value, x11):
if value:
return value
elif x11:
set_define('GL_PROVIDER_GLX', True)
return 'GLX'
set_config('MOZ_GL_PROVIDER', gl_provider)
set_config('MOZ_GL_DEFAULT_PROVIDER', gl_default_provider)
# PDF printing
# ==============================================================
@depends(toolkit)
def pdf_printing(toolkit):
if toolkit in ('windows', 'gtk2', 'gtk3', 'qt', 'android', 'gonk'):
set_config('MOZ_PDF_PRINTING', True)
set_config('PDF_SURFACE_FEATURE', '#define CAIRO_HAS_PDF_SURFACE 1')
return True
@depends(pdf_printing)
def pdf_surface_feature(pdf_printing):
if pdf_printing:
return '#define CAIRO_HAS_PDF_SURFACE 1'
else:
# CONFIGURE_SUBST_FILES need explicit empty values.
set_config('PDF_SURFACE_FEATURE', '')
return ''
set_config('MOZ_PDF_PRINTING', pdf_printing)
set_config('PDF_SURFACE_FEATURE', pdf_surface_feature)
# Event loop instrumentation
@ -204,8 +223,10 @@ option(env='MOZ_INSTRUMENT_EVENT_LOOP',
def instrument_event_loop(value, toolkit):
if value or (toolkit in ('windows', 'gtk2', 'gtk3', 'cocoa', 'android',
'gonk') and value.origin == 'default'):
set_config('MOZ_INSTRUMENT_EVENT_LOOP', True)
set_define('MOZ_INSTRUMENT_EVENT_LOOP', True)
return True
set_config('MOZ_INSTRUMENT_EVENT_LOOP', instrument_event_loop)
# Fontconfig Freetype
@ -225,12 +246,11 @@ def fc_freetype(value, toolkit):
@depends(toolkit)
def applemedia(toolkit):
if toolkit in ('cocoa', 'uikit'):
set_config('MOZ_APPLEMEDIA', True)
set_define('MOZ_APPLEMEDIA', True)
add_old_configure_assignment('MOZ_APPLEMEDIA', True)
return True
return False
set_config('MOZ_APPLEMEDIA', applemedia)
# Windows Media Foundation support
# ==============================================================
@ -249,10 +269,10 @@ def wmf(value, target):
error('Cannot enable Windows Media Foundation support on %s'
% target.os)
if enabled:
set_config('MOZ_WMF', True)
set_define('MOZ_WMF', True)
return enabled
return True
set_config('MOZ_WMF', wmf)
# FFmpeg H264/AAC Decoding Support
# ==============================================================
@ -266,10 +286,10 @@ def ffmpeg(value, target):
enabled = target.os not in ('Android', 'WINNT')
if enabled:
set_define('MOZ_FFMPEG', True)
set_config('MOZ_FFMPEG', True)
imply_option('--enable-fmp4', '--enable-ffmpeg')
return enabled
return True
set_config('MOZ_FFMPEG', ffmpeg)
# Built-in fragmented MP4 support.
# ==============================================================
@ -283,11 +303,11 @@ def fmp4(value, target, wmf, applemedia):
# target.os == 'Android' includes all B2G versions
enabled = wmf or applemedia or target.os == 'Android'
if enabled:
set_config('MOZ_FMP4', True)
set_define('MOZ_FMP4', True)
add_old_configure_assignment('MOZ_FMP4', True)
return enabled
return True
set_config('MOZ_FMP4', fmp4)
# EME Support
# ==============================================================
@ -303,11 +323,16 @@ def eme(value, fmp4):
error('Encrypted Media Extension support requires '
'Fragmented MP4 support')
if enabled:
set_config('MOZ_EME', True)
set_define('MOZ_EME', True)
return True
@depends('--enable-eme')
def eme_modules(value):
# Theoretically, we could pass `value` directly when it is a
# PositiveOptionValue, but somehow, the JSON serialization in configure.py
# outputs inconsistent data in some cases when we do (a closing bracket
# without an opening one).
set_config('MOZ_EME_MODULES', list(value) if value else [])
return enabled
return list(value) if value else []
set_config('MOZ_EME', eme)
set_config('MOZ_EME_MODULES', eme_modules)