Bug 1257823 - Move set_define() to the global scope. r=nalexander
authorMike Hommey <mh+mozilla@glandium.org>
Wed, 23 Mar 2016 10:22:08 +0900
changeset 290181 62ae3968b2d82f17ec2853714ab565c02a7cb9bc
parent 290180 9d2b6f4c3ee8366365c16cee6cbda90c4688c743
child 290182 407e18a1a0241fb62f0391d698ff9954625ad06b
push id18353
push usercbook@mozilla.com
push dateThu, 24 Mar 2016 15:20:25 +0000
treeherderfx-team@40ae8489939e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnalexander
bugs1257823
milestone48.0a1
Bug 1257823 - Move set_define() to the global scope. r=nalexander For the same reasons as set_config is being moved to the global scope, we're moving set_define to the global scope here. An additional change is that set_define is now part of the sandbox itself instead of being defined within the sandbox, which makes it share the implementation details with set_config.
b2g/common.configure
build/moz.configure/init.configure
build/moz.configure/old.configure
js/moz.configure
moz.configure
python/mozbuild/mozbuild/configure/__init__.py
python/mozbuild/mozbuild/test/configure/data/set_define.configure
python/mozbuild/mozbuild/test/configure/test_configure.py
toolkit/moz.configure
--- a/b2g/common.configure
+++ b/b2g/common.configure
@@ -9,15 +9,21 @@
 option(env='MOZTTDIR', nargs=1, help='Path to truetype fonts for B2G')
 
 @depends('MOZTTDIR')
 def mozttdir(value):
     if value:
         path = value[0]
         if not os.path.isdir(path):
             error('MOZTTDIR "%s" is not a valid directory' % path)
-        set_define('PACKAGE_MOZTT', True)
         return path
 
 set_config('MOZTTDIR', mozttdir)
 
+@depends('MOZTTDIR')
+def package_moztt(value):
+    if value:
+        return True
+
+set_define('PACKAGE_MOZTT', package_moztt)
+
 
 include('../toolkit/moz.configure')
--- a/build/moz.configure/init.configure
+++ b/build/moz.configure/init.configure
@@ -542,34 +542,59 @@ def host_variables(host):
     add_old_configure_assignment('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):
+def target_is_windows(target):
     if target.kernel == 'WINNT':
-        set_define('_WINDOWS', True)
-        set_define('WIN32', True)
-        set_define('XP_WIN', True)
-        set_define('XP_WIN32', True)
-    else:
-        set_define('XP_UNIX', True)
+        return True
+
+set_define('_WINDOWS', target_is_windows)
+set_define('WIN32', target_is_windows)
+set_define('XP_WIN', target_is_windows)
+set_define('XP_WIN32', target_is_windows)
+
+@depends(target)
+def target_is_unix(target):
+    if target.kernel != 'WINNT':
+        return True
+
+set_define('XP_UNIX', target_is_unix)
+
+@depends(target)
+def target_is_darwin(target):
+    if target.kernel == 'Darwin':
+        return True
 
-    if target.kernel == 'Darwin':
-        set_define('XP_DARWIN', True)
-        if target.os == 'iOS':
-            set_define('XP_IOS', True)
-        elif target.os == 'OSX':
-            set_define('XP_MACOSX', True)
-    elif target.kernel == 'Linux':
-        set_define('XP_LINUX', True)
+set_define('XP_DARWIN', target_is_darwin)
+
+@depends(target)
+def target_is_ios(target):
+    if target.kernel == 'Darwin' and target.os == 'iOS':
+        return True
+
+set_define('XP_IOS', target_is_ios)
 
+@depends(target)
+def target_is_osx(target):
+    if target.kernel == 'Darwin' and target.os == 'OSX':
+        return True
+
+set_define('XP_MACOSX', target_is_osx)
+
+@depends(target)
+def target_is_linux(target):
+    if target.kernel == 'Linux':
+        return True
+
+set_define('XP_LINUX', target_is_linux)
 
 # The application/project to build
 # ==============================================================
 option('--enable-application', nargs=1, env='MOZ_BUILD_APP',
        help='Application to build. Same as --enable-project.')
 
 @depends('--enable-application', '--help')
 def application(app, help):
@@ -613,21 +638,21 @@ def external_source_dir(value):
 
 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_define('MOZ_BUILD_APP', ret)
     add_old_configure_assignment('MOZ_BUILD_APP', ret)
     return ret
 
 set_config('MOZ_BUILD_APP', build_project)
+set_define('MOZ_BUILD_APP', build_project)
 
 
 # set RELEASE_BUILD and NIGHTLY_BUILD variables depending on the cycle we're in
 # The logic works like this:
 # - if we have "a1" in GRE_MILESTONE, we're building Nightly (define NIGHTLY_BUILD)
 # - otherwise, if we have "a" in GRE_MILESTONE, we're building Nightly or Aurora
 # - otherwise, we're building Release/Beta (define RELEASE_BUILD)
 @depends(check_build_environment)
@@ -637,31 +662,31 @@ def milestone(build_env):
                                   'config',
                                   'milestone.txt')
     with open(milestone_path, 'r') as fh:
         milestone = fh.read().splitlines()[-1]
 
     is_nightly = is_release = None
 
     if 'a1' in milestone:
-        set_define('NIGHTLY_BUILD', True)
         add_old_configure_assignment('NIGHTLY_BUILD', True)
         is_nightly = True
     elif 'a' not in milestone:
-        set_define('RELEASE_BUILD', True)
         add_old_configure_assignment('RELEASE_BUILD', True)
         is_release = True
 
     return namespace(version=milestone,
                      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_define('NIGHTLY_BUILD', delayed_getattr(milestone, 'is_nightly'))
 set_config('RELEASE_BUILD', delayed_getattr(milestone, 'is_release'))
+set_define('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
 def js_option(*args, **kwargs):
     opt = option(*args, **kwargs)
 
--- a/build/moz.configure/old.configure
+++ b/build/moz.configure/old.configure
@@ -422,23 +422,28 @@ def old_configure(prepare_configure, ext
 
 # 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)
 
+# Same as set_old_configure_config, but for set_define.
+@template
+def set_old_configure_define(name, value):
+    set_define(name, value)
+
 
 @depends(old_configure)
 @advanced
 def post_old_configure(raw_config):
     import types
 
     for k, v in raw_config['substs']:
         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_old_configure_define(k[1:-1], v[1:-1])
 
     set_old_configure_config('non_global_defines',
                              raw_config['non_global_defines'])
--- a/js/moz.configure
+++ b/js/moz.configure
@@ -39,49 +39,60 @@ set_config('JS_DISABLE_SHELL', js_disabl
 
 # Use SpiderMonkey Promise implementation if it's enabled
 # =======================================================
 js_option('--enable-sm-promise', help='Enable SpiderMonkey promises')
 
 @depends('--enable-sm-promise')
 def sm_promise(value):
     if value:
-        set_define('SPIDERMONKEY_PROMISE', True)
         return True
 
 set_config('SPIDERMONKEY_PROMISE', sm_promise)
+set_define('SPIDERMONKEY_PROMISE', sm_promise)
 
 # SpiderMonkey as a shared library, and how its symbols are exported
 # ==================================================================
 js_option('--disable-shared-js', default=building_js,
           help='Do not create a shared library')
 
 js_option('--disable-export-js', default=building_js,
           help='Do not mark JS symbols as DLL exported/visible')
 
 @depends('--disable-shared-js', '--disable-export-js')
-def static_js(shared_js, export_js):
+def shared_js(shared_js, export_js):
     if shared_js:
         if not export_js:
             error('Must export JS symbols when building a shared library.')
         add_old_configure_assignment('JS_SHARED_LIBRARY', True)
-    else:
-        if export_js:
-            set_define('STATIC_EXPORTABLE_JS_API', True)
-        else:
-            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)
 
+@depends('--disable-shared-js', '--disable-export-js')
+def exportable_js_api(shared_js, export_js):
+    if not shared_js and export_js:
+        return True
+
+set_define('STATIC_EXPORTABLE_JS_API', exportable_js_api)
+
+@depends('--disable-shared-js', '--disable-export-js')
+def static_js_api(shared_js, export_js):
+    if not shared_js and not export_js:
+        return True
+
+set_define('STATIC_JS_API', static_js_api)
+
+@depends('--disable-shared-js')
+def static_js(value):
+    if not value:
+        return True
+
+set_define('MOZ_STATIC_JS', static_js)
+
 @deprecated_option(env='DISABLE_SHARED_JS', nargs='?')
 def disable_shared_js(value):
     # DISABLE_SHARED_JS=1 gets us an empty PositiveOptionValue
     if value and not len(value):
         suggestion = '--disable-shared-js'
     else:
         suggestion = '--enable-shared-js'
 
@@ -106,52 +117,53 @@ js_option('--enable-instruments', env='M
           help='Enable instruments remote profiling')
 
 @depends('--enable-instruments', target)
 def instruments(value, target):
     if value and target.os != 'OSX':
         error('--enable-instruments cannot be used when targeting %s'
               % target.os)
     if value:
-        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)
+set_define('MOZ_INSTRUMENTS', instruments)
 
 js_option('--enable-callgrind', env='MOZ_CALLGRIND',
           help='Enable callgrind profiling')
 
 @depends('--enable-callgrind')
 def callgrind(value):
     if value:
-        set_define('MOZ_CALLGRIND', True)
         imply_option('--enable-profiling')
+        return True
 
+set_define('MOZ_CALLGRIND', 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):
     if value:
-        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)
+set_define('MOZ_PROFILING', profiling)
 
 
 js_option('--enable-vtune', env='MOZ_VTUNE', help='Enable vtune profiling')
 
 @depends('--enable-vtune')
 def vtune(value):
     if value:
-        set_define('MOZ_VTUNE', True)
         return True
 
 set_config('MOZ_VTUNE', vtune)
+set_define('MOZ_VTUNE', vtune)
--- a/moz.configure
+++ b/moz.configure
@@ -15,20 +15,20 @@ include('build/moz.configure/checks.conf
 # - Spidermonkey-specific options and rules should go in js/moz.configure.
 # - etc.
 
 # Multiprocess Firefox Testing UI - Nightly and Aurora
 # To be removed in Bug 1003313
 @depends(milestone)
 def e10s_testing_only(milestone):
     if not milestone.is_release:
-        set_define('E10S_TESTING_ONLY', True)
         return True
 
 set_config('E10S_TESTING_ONLY', e10s_testing_only)
+set_define('E10S_TESTING_ONLY', e10s_testing_only)
 
 
 option('--enable-artifact-builds', env='MOZ_ARTIFACT_BUILDS',
        help='Download and use prebuilt binary artifacts.')
 
 @depends('--enable-artifact-builds')
 def artifact_builds(value):
     if value:
--- a/python/mozbuild/mozbuild/configure/__init__.py
+++ b/python/mozbuild/mozbuild/configure/__init__.py
@@ -133,16 +133,17 @@ class ConfigureSandbox(dict):
         # infered.
         self._implied_options = {}
 
         # Store all results from _prepare_function
         self._prepared_functions = set()
 
         self._helper = CommandLineHelper(environ, argv)
 
+        assert isinstance(config, dict)
         self._config, self._stdout, self._stderr = config, stdout, stderr
 
         self._help = None
         self._help_option = self.option_impl('--help',
                                              help='print this message')
         self._seen.add(self._help_option)
         # self._option_impl('--help') will have set this if --help was on the
         # command line.
@@ -285,21 +286,19 @@ class ConfigureSandbox(dict):
         references. The decorated function is called as soon as the decorator
         is called, and the arguments it receives are the OptionValue or
         function results corresponding to each of the arguments to @depends.
         As an exception, when a HelpFormatter is attached, only functions that
         have '--help' in their @depends argument list are called.
 
         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 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.
+        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.
         '''
         if not args:
             raise ConfigureError('@depends needs at least one argument')
 
         with_help = False
         resolved_args = []
         for arg in args:
             if isinstance(arg, types.StringTypes):
@@ -329,17 +328,16 @@ class ConfigureSandbox(dict):
         def decorator(func):
             if inspect.isgeneratorfunction(func):
                 raise ConfigureError(
                     'Cannot decorate generator functions with @depends')
             func, glob = self._prepare_function(func)
             result = DependsOutput()
             glob.update(
                 imply_option=result.imply_option,
-                set_define=self._set_define,
             )
             dummy = wraps(func)(DummyFunction())
             self._depends[dummy] = func
             func.with_help = with_help
             if with_help:
                 for arg in args:
                     if (isinstance(arg, DummyFunction) and
                             not self._depends[arg].with_help):
@@ -401,57 +399,66 @@ class ConfigureSandbox(dict):
         helper decorators and somesuch.
         '''
         template, glob = self._prepare_function(func)
         glob.update(
             advanced=self.advanced_impl,
             depends=self.depends_impl,
             option=self.option_impl,
             set_config=self.set_config_impl,
+            set_define=self.set_define_impl,
         )
         self._templates.add(template)
         return template
 
     def advanced_impl(self, func):
         '''Implementation of @advanced.
         This function gives the decorated function access to the complete set
         of builtins, allowing the import keyword as an expected side effect.
         '''
         func, glob = self._prepare_function(func)
         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.
-        '''
+    def _resolve_and_set(self, data, name, value):
         # 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:
+        if name in data:
             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
+            data[name] = value
 
-    def _set_define(self, name, value):
+    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.
+        '''
+        self._resolve_and_set(self._config, name, value)
+
+    def set_define_impl(self, name, value):
+        '''Implementation of set_define().
+        Set the define 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 define is not set. If the result is False, the define is
+        explicitly undefined (-U).
+        '''
         defines = self._config.setdefault('DEFINES', {})
-        if name in defines:
-            raise ConfigureError("'%s' is already defined" % name)
-        defines[name] = value
+        self._resolve_and_set(defines, name, value)
 
     def _prepare_function(self, func):
         '''Alter the given function global namespace with the common ground
         for @depends, @template and @advanced.
         '''
         if not inspect.isfunction(func):
             raise TypeError("Unexpected type: '%s'" % type(func))
         if func in self._prepared_functions:
new file mode 100644
--- /dev/null
+++ b/python/mozbuild/mozbuild/test/configure/data/set_define.configure
@@ -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_define('FOO', foo)
+
+
+option('--set-bar', help='set bar')
+
+@depends('--set-bar')
+def bar(value):
+    return bool(value)
+
+set_define('BAR', bar)
+
+
+option('--set-value', nargs=1, help='set value')
+
+@depends('--set-value')
+def set_value(value):
+    if value:
+        return value[0]
+
+set_define('VALUE', set_value)
+
+
+option('--set-name', nargs=1, help='set name')
+
+@depends('--set-name')
+def set_name(value):
+    if value:
+        return value[0]
+
+set_define(set_name, True)
--- a/python/mozbuild/mozbuild/test/configure/test_configure.py
+++ b/python/mozbuild/mozbuild/test/configure/test_configure.py
@@ -334,11 +334,44 @@ class TestConfigure(unittest.TestCase):
         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'])
 
+    def test_set_define(self):
+        def get_config(*args):
+            return self.get_config(*args, configure='set_define.configure')
+
+        config, out = self.get_result(['--help'],
+                                      configure='set_define.configure')
+        self.assertEquals(config, {'DEFINES': {}})
+
+        config = get_config(['--set-foo'])
+        self.assertIn('FOO', config['DEFINES'])
+        self.assertEquals(config['DEFINES']['FOO'], True)
+
+        config = get_config(['--set-bar'])
+        self.assertNotIn('FOO', config['DEFINES'])
+        self.assertIn('BAR', config['DEFINES'])
+        self.assertEquals(config['DEFINES']['BAR'], True)
+
+        config = get_config(['--set-value=qux'])
+        self.assertIn('VALUE', config['DEFINES'])
+        self.assertEquals(config['DEFINES']['VALUE'], 'qux')
+
+        config = get_config(['--set-name=hoge'])
+        self.assertIn('hoge', config['DEFINES'])
+        self.assertEquals(config['DEFINES']['hoge'], True)
+
+        config = get_config([])
+        self.assertEquals(config['DEFINES'], {'BAR': False})
+
+        with self.assertRaises(ConfigureError):
+            # Both --set-foo and --set-name=FOO are going to try to
+            # set_define('FOO'...)
+            get_config(['--set-foo', '--set-name=FOO'])
+
 
 if __name__ == '__main__':
     main()
--- a/toolkit/moz.configure
+++ b/toolkit/moz.configure
@@ -13,61 +13,63 @@ option('--enable-systrace', env='MOZ_USE
        help='Turn on systrace for the Gecko profiler on android/b2g')
 
 @depends('--enable-systrace', target)
 def systrace(value, target):
     if value and target.os != 'Android':
         error('--enable-systrace cannot be used when targetting %s'
               % target.os)
     if value:
-        set_define('MOZ_USE_SYSTRACE', True)
+        return True
+
+set_define('MOZ_USE_SYSTRACE', systrace)
 
 
 option('--enable-jprof', env='MOZ_JPROF',
        help='Enable jprof profiling tool (needs mozilla/tools/jprof)')
 
 @depends('--enable-jprof')
 def jprof(value):
     if value:
-        set_define('MOZ_JPROF', True)
         imply_option('--enable-profiling')
         return True
 
 set_config('MOZ_JPROF', jprof)
+set_define('MOZ_JPROF', jprof)
 
 @depends(target)
 def sps_profiler(target):
     if target.os == 'Android':
         return target.cpu in ('arm', 'x86')
     elif target.kernel == 'Linux':
         return target.cpu in ('x86', 'x86_64')
     return target.os in ('OSX', 'WINNT')
 
 @depends(sps_profiler)
 def sps_profiler_define(value):
     if value:
-        set_define('MOZ_ENABLE_PROFILER_SPS', True)
         return True
 
 set_config('MOZ_ENABLE_PROFILER_SPS', sps_profiler_define)
+set_define('MOZ_ENABLE_PROFILER_SPS', sps_profiler_define)
 
 
 option('--enable-dmd', env='MOZ_DMD',
        help='Enable Dark Matter Detector (heap profiler). '
             'Also enables jemalloc, replace-malloc and profiling')
 
 @depends('--enable-dmd')
 def dmd(value):
     if value:
-        set_define('MOZ_DMD', True)
         add_old_configure_assignment('MOZ_DMD', True)
         imply_option('--enable-profiling')
         return True
 
 set_config('MOZ_DMD', dmd)
+set_define('MOZ_DMD', dmd)
 
 # Javascript engine
 # ==============================================================
 include('../js/moz.configure')
 
 
 # L10N
 # ==============================================================
@@ -133,73 +135,93 @@ def toolkit(value, target, gonkdir):
 @depends(toolkit)
 def toolkit(toolkit):
     if toolkit == 'cairo-gtk2-x11':
         widget_toolkit = 'gtk2'
     else:
         widget_toolkit = toolkit.replace('cairo-', '')
     add_old_configure_assignment('MOZ_WIDGET_TOOLKIT', widget_toolkit)
 
-    if widget_toolkit == 'gtk2':
-        set_define('MOZ_WIDGET_GTK', '2')
-    elif widget_toolkit == 'gtk3':
-        set_define('MOZ_WIDGET_GTK', '3')
-    elif widget_toolkit != 'windows':
-        set_define('MOZ_WIDGET_%s' % widget_toolkit.upper(), True)
-
     return widget_toolkit
 
 set_config('MOZ_WIDGET_TOOLKIT', toolkit)
 
+@depends(toolkit)
+def toolkit_gtk(toolkit):
+    if toolkit == 'gtk2':
+        return '2'
+    elif toolkit == 'gtk3':
+        return '3'
+
+set_define('MOZ_WIDGET_GTK', toolkit_gtk)
+
+@depends(toolkit)
+def toolkit_define(toolkit):
+    if toolkit not in ('gtk2', 'gtk3', 'windows'):
+        return 'MOZ_WIDGET_%s' % toolkit.upper()
+
+set_define(toolkit_define, True)
+
 
 option('--without-x', env='WITHOUT_X', help='Disable X11 support')
 
 @depends('--without-x', toolkit)
 def x11(value, toolkit):
     if not value and toolkit != 'qt':
         error('--without-x is only valid with --enable-default-toolkit=qt')
 
     x11_toolkits = ('gtk2', 'gtk3', 'qt')
     if value and value.origin != 'default' and toolkit not in x11_toolkits:
         error('--with-x is only valid with --enable-default-toolkit={%s}'
               % ','.join(x11_toolkits))
 
     if value and toolkit in x11_toolkits:
-        set_define('MOZ_ENABLE_XREMOTE', True)
-        set_define('MOZ_X11', True)
         add_old_configure_assignment('MOZ_X11', True)
 
     return True if value and toolkit in x11_toolkits else None
 
 set_config('MOZ_ENABLE_XREMOTE', x11)
+set_define('MOZ_ENABLE_XREMOTE', x11)
 set_config('MOZ_X11', x11)
+set_define('MOZ_X11', x11)
 
 # GL Provider
 # ==============================================================
 option('--with-gl-provider', nargs=1, help='Set GL provider backend type')
 
 @depends('--with-gl-provider')
 def gl_provider(value):
     if value:
-        provider = value[0]
-        set_define('MOZ_GL_PROVIDER', 'GLContextProvider%s' % provider)
-        set_define('GL_PROVIDER_%s' % provider, True)
-        return provider
+        return value[0]
+
+@depends(gl_provider)
+def gl_provider_define(provider):
+    if provider:
+        return 'GLContextProvider%s' % provider
+
+set_define('MOZ_GL_PROVIDER', gl_provider_define)
 
 @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)
 
+@depends(gl_default_provider)
+def gl_provider_define(provider):
+    if provider:
+        return 'GL_PROVIDER_%s' % provider
+
+set_define(gl_provider_define, True)
+
+
 # PDF printing
 # ==============================================================
 @depends(toolkit)
 def pdf_printing(toolkit):
     if toolkit in ('windows', 'gtk2', 'gtk3', 'qt', 'android', 'gonk'):
         return True
 
 @depends(pdf_printing)
@@ -218,20 +240,20 @@ set_config('PDF_SURFACE_FEATURE', pdf_su
 # ==============================================================
 option(env='MOZ_INSTRUMENT_EVENT_LOOP',
        help='Force-enable event loop instrumentation')
 
 @depends('MOZ_INSTRUMENT_EVENT_LOOP', toolkit)
 def instrument_event_loop(value, toolkit):
     if value or (toolkit in ('windows', 'gtk2', 'gtk3', 'cocoa', 'android',
                              'gonk') and value.origin == 'default'):
-        set_define('MOZ_INSTRUMENT_EVENT_LOOP', True)
         return True
 
 set_config('MOZ_INSTRUMENT_EVENT_LOOP', instrument_event_loop)
+set_define('MOZ_INSTRUMENT_EVENT_LOOP', instrument_event_loop)
 
 
 # Fontconfig Freetype
 # ==============================================================
 option(env='USE_FC_FREETYPE',
        help='Force-enable the use of fontconfig freetype')
 
 @depends('USE_FC_FREETYPE', toolkit)
@@ -241,21 +263,21 @@ def fc_freetype(value, toolkit):
         add_old_configure_assignment('USE_FC_FREETYPE', True)
 
 
 # Apple platform decoder support
 # ==============================================================
 @depends(toolkit)
 def applemedia(toolkit):
     if toolkit in ('cocoa', 'uikit'):
-        set_define('MOZ_APPLEMEDIA', True)
         add_old_configure_assignment('MOZ_APPLEMEDIA', True)
         return True
 
 set_config('MOZ_APPLEMEDIA', applemedia)
+set_define('MOZ_APPLEMEDIA', applemedia)
 
 # Windows Media Foundation support
 # ==============================================================
 option('--disable-wmf',
        help='Disable support for Windows Media Foundation')
 
 @depends('--disable-wmf', target)
 def wmf(value, target):
@@ -264,75 +286,75 @@ def wmf(value, target):
         # Enable Windows Media Foundation support by default.
         # Note our minimum SDK version is Windows 7 SDK, so we are (currently)
         # guaranteed to have a recent-enough SDK to build WMF.
         enabled = target.os == 'WINNT'
     if enabled and target.os != 'WINNT':
         error('Cannot enable Windows Media Foundation support on %s'
               % target.os)
     if enabled:
-        set_define('MOZ_WMF', True)
         return True
 
 set_config('MOZ_WMF', wmf)
+set_define('MOZ_WMF', wmf)
 
 # FFmpeg H264/AAC Decoding Support
 # ==============================================================
 option('--disable-ffmpeg',
        help='Disable FFmpeg for fragmented H264/AAC decoding')
 
 @depends('--disable-ffmpeg', target)
 def ffmpeg(value, target):
     enabled = bool(value)
     if value.origin == 'default':
         enabled = target.os not in ('Android', 'WINNT')
     if enabled:
-        set_define('MOZ_FFMPEG', True)
         imply_option('--enable-fmp4', '--enable-ffmpeg')
         return True
 
 set_config('MOZ_FFMPEG', ffmpeg)
+set_define('MOZ_FFMPEG', ffmpeg)
 
 # Built-in fragmented MP4 support.
 # ==============================================================
 option('--disable-fmp4', env='MOZ_FMP4',
        help='Disable support for in built Fragmented MP4 parsing')
 
 @depends('--disable-fmp4', target, wmf, applemedia)
 def fmp4(value, target, wmf, applemedia):
     enabled = bool(value)
     if value.origin == 'default':
         # target.os == 'Android' includes all B2G versions
         enabled = wmf or applemedia or target.os == 'Android'
     if enabled:
-        set_define('MOZ_FMP4', True)
         add_old_configure_assignment('MOZ_FMP4', True)
         return True
 
 set_config('MOZ_FMP4', fmp4)
+set_define('MOZ_FMP4', fmp4)
 
 # EME Support
 # ==============================================================
 option('--enable-eme', nargs='*', choices=('adobe',),
        help='Enable support for Encrypted Media Extensions')
 
 @depends('--enable-eme', fmp4)
 def eme(value, fmp4):
     enabled = bool(value)
     if value.origin == 'default':
         enabled = enabled or fmp4
     if enabled and not fmp4:
         error('Encrypted Media Extension support requires '
               'Fragmented MP4 support')
     if enabled:
-        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).
     return list(value) if value else []
 
 set_config('MOZ_EME', eme)
+set_define('MOZ_EME', eme)
 set_config('MOZ_EME_MODULES', eme_modules)