Bug 1257516 - Expose a sandboxed logger to moz.configure and use it. r=ted
authorMike Hommey <mh+mozilla@glandium.org>
Fri, 25 Mar 2016 16:30:42 +0900
changeset 328785 c2d739e9a7bc8463e1c7c29ba624e17c36f1e613
parent 328784 12248651d3ad2a6bacd79106899ec6464fd68e37
child 328786 7fc90e8065458a180533e08d85fd4c4086220056
push id6048
push userkmoir@mozilla.com
push dateMon, 06 Jun 2016 19:02:08 +0000
treeherdermozilla-beta@46d72a56c57d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersted
bugs1257516
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 1257516 - Expose a sandboxed logger to moz.configure and use it. r=ted This removes the warn() function and makes the die() function use the logger instead of print.
build/moz.configure/checks.configure
build/moz.configure/init.configure
build/moz.configure/old.configure
build/moz.configure/util.configure
python/mozbuild/mozbuild/configure/__init__.py
--- a/build/moz.configure/checks.configure
+++ b/build/moz.configure/checks.configure
@@ -7,45 +7,41 @@
 # Templates implementing some generic checks.
 
 # Helper to display "checking" messages
 #   @checking('for foo')
 #   def foo():
 #       return 'foo'
 # is equivalent to:
 #   def foo():
-#       sys.stdout.write('checking for foo... ')
+#       log.info('checking for foo... ')
 #       ret = foo
-#       sys.stdout.write(ret + '\n')
+#       log.info(ret)
 #       return ret
 # This can be combined with e.g. @depends:
 #   @depends(some_option)
 #   @checking('for something')
 #   def check(value):
 #       ...
 # An optional callback can be given, that will be used to format the returned
 # value when displaying it.
 @template
 def checking(what, callback=None):
     def decorator(func):
-        @advanced
         def wrapped(*args, **kwargs):
-            import sys
-            print('checking', what, end='... ')
-            sys.stdout.flush()
+            log.info('checking %s... ', what)
             ret = func(*args, **kwargs)
             if callback:
-                print(callback(ret))
+                log.info(callback(ret))
             elif ret is True:
-                print('yes')
+                log.info('yes')
             elif ret is False:
-                print('no')
+                log.info('no')
             else:
-                print(ret)
-            sys.stdout.flush()
+                log.info(ret)
             return ret
         return wrapped
     return decorator
 
 
 # Template to check for programs in $PATH.
 #   check('PROG', ('a', 'b'))
 # will look for 'a' or 'b' in $PATH, and set_config PROG to the one
--- a/build/moz.configure/init.configure
+++ b/build/moz.configure/init.configure
@@ -204,23 +204,23 @@ def virtualenv_python(env_python, build_
         if not found_python:
             die('The PYTHON environment variable does not contain '
                 'a valid path. Cannot find %s', python)
         python = found_python
     else:
         python = sys.executable
 
     if not manager.up_to_date(python):
-        warn('Creating Python environment')
+        log.info('Creating Python environment')
         manager.build(python)
 
     python = normsep(manager.python_path)
 
     if python != normsep(sys.executable):
-        warn('Reexecuting in the virtualenv')
+        log.info('Reexecuting in the virtualenv')
         if env_python:
             del os.environ['PYTHON']
         # One would prefer to use os.execl, but that's completely borked on
         # Windows.
         sys.exit(subprocess.call([python] + sys.argv))
 
     # We are now in the virtualenv
     import distutils.sysconfig
@@ -306,29 +306,29 @@ def wanted_mozconfig_variables(help):
          'ZIP',
      ])
 
 
 @depends(mozconfig, wanted_mozconfig_variables, '--help')
 def mozconfig_options(mozconfig, wanted_mozconfig_variables, help):
     if mozconfig['path']:
         helper = command_line_helper()
-        warn('Adding configure options from %s' % mozconfig['path'])
+        log.info('Adding configure options from %s' % mozconfig['path'])
         for arg in mozconfig['configure_args']:
-            warn('  %s' % arg)
+            log.info('  %s' % arg)
             # We could be using imply_option() here, but it has other
             # contraints that don't really apply to the command-line
             # emulation that mozconfig provides.
             helper.add(arg, origin='mozconfig', args=helper._args)
 
         def add(key, value):
             # See comment above wanted_mozconfig_variables
             if key in wanted_mozconfig_variables:
                 arg = '%s=%s' % (key, value)
-                warn('  %s' % arg)
+                log.info('  %s' % arg)
                 helper.add(arg, origin='mozconfig', args=helper._args)
 
         for key, value in mozconfig['env']['added'].iteritems():
             add(key, value)
         for key, (_, value) in mozconfig['env']['modified'].iteritems():
             add(key, value)
         for key, value in mozconfig['vars']['added'].iteritems():
             add(key, value)
--- a/build/moz.configure/old.configure
+++ b/build/moz.configure/old.configure
@@ -115,17 +115,17 @@ def prepare_configure(old_configure, moz
             glob.iglob(aclocal),
         ):
             if getmtime(input) > mtime:
                 break
         else:
             refresh = False
 
     if refresh:
-        warn('Refreshing %s with %s' % (old_configure, autoconf))
+        log.info('Refreshing %s with %s', old_configure, autoconf)
         with open(old_configure, 'wb') as fh:
             subprocess.check_call([
                 shell, autoconf,
                 '--localdir=%s' % os.path.dirname(old_configure),
                 old_configure + '.in'], stdout=fh)
 
     cmd = [shell, old_configure]
     with encoded_open('old-configure.vars', 'w') as out:
@@ -387,17 +387,17 @@ def old_configure(prepare_configure, ext
     # We also pass it the options from js/moz.configure so that it can pass
     # them down to js/src/configure. Note this list is empty when running
     # js/src/configure, in which case we don't need to pass those options
     # to old-configure since old-configure doesn't handle them anyways.
     if extra_old_configure_args:
         cmd += extra_old_configure_args
 
     # For debugging purpose, in case it's not what we'd expect.
-    warn('running %s' % ' '.join(quote(a) for a in cmd))
+    log.info('running %s', ' '.join(quote(a) for a in cmd))
     ret = subprocess.call(cmd)
     if ret:
         sys.exit(ret)
 
     raw_config = {}
     with encoded_open('config.data', 'r') as fh:
         code = compile(fh.read(), 'config.data', 'exec')
         # Every variation of the exec() function I tried led to:
--- a/build/moz.configure/util.configure
+++ b/build/moz.configure/util.configure
@@ -1,30 +1,20 @@
 # -*- 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/.
 
 @template
 @advanced
-def warn(*args):
-    'Print a warning.'
-    import sys
-    print(*args, file=sys.stderr)
-    sys.stderr.flush()
-
-
-@template
-@advanced
-def die(format, *args):
+def die(*args):
     'Print an error and terminate configure.'
     import sys
-    print(format % args, file=sys.stderr)
-    sys.stderr.flush()
+    log.error(*args)
     sys.exit(1)
 
 
 @template
 @advanced
 def configure_error(message):
     '''Raise a programming error and terminate configure.
     Primarily for use in moz.configure templates to sanity check
--- a/python/mozbuild/mozbuild/configure/__init__.py
+++ b/python/mozbuild/mozbuild/configure/__init__.py
@@ -135,16 +135,21 @@ class ConfigureSandbox(dict):
             handler = ConfigureOutputHandler(stdout, stderr)
             handler.setLevel(logging.INFO)
             handler.setFormatter(formatter)
             logger.addHandler(handler)
 
         else:
             assert isinstance(logger, logging.Logger)
 
+        self.log_impl = ReadOnlyNamespace(**{
+                k: getattr(logger, k)
+                for k in ('debug', 'info', 'warning', 'error')
+        })
+
         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.
         if self._option_values[self._help_option]:
             self._help = HelpFormatter(argv[0])
@@ -194,17 +199,17 @@ class ConfigureSandbox(dict):
         for option in self._options.itervalues():
             if option not in self._seen:
                 raise ConfigureError(
                     'Option `%s` is not handled ; reference it with a @depends'
                     % option.option
                 )
 
         if self._help:
-            with LineIO(logging.getLogger('moz.configure').info) as out:
+            with LineIO(self.log_impl.info) as out:
                 self._help.usage(out)
 
     def __getitem__(self, key):
         impl = '%s_impl' % key
         func = getattr(self, impl, None)
         if func:
             return func
 
@@ -513,16 +518,17 @@ class ConfigureSandbox(dict):
         if func in self._prepared_functions:
             return func, func.func_globals
 
         glob = SandboxedGlobal(func.func_globals)
         glob.update(
             __builtins__=self.BUILTINS,
             __file__=self._paths[-1],
             os=self.OS,
+            log=self.log_impl,
         )
         func = wraps(func)(types.FunctionType(
             func.func_code,
             glob,
             func.__name__,
             func.func_defaults,
             func.func_closure
         ))