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 330018 62ae3968b2d82f17ec2853714ab565c02a7cb9bc
parent 330017 9d2b6f4c3ee8366365c16cee6cbda90c4688c743
child 330019 407e18a1a0241fb62f0391d698ff9954625ad06b
push id1146
push userCallek@gmail.com
push dateMon, 25 Jul 2016 16:35:44 +0000
treeherdermozilla-release@a55778f9cd5a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnalexander
bugs1257823
milestone48.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
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)