Bug 794729 - Run config.guess and mozconfig through shell; r=glandium
authorGregory Szorc <gps@mozilla.com>
Thu, 27 Sep 2012 10:12:48 -0700
changeset 108250 74522aafbcdcd34866826fbf84f76d74e2296f93
parent 108249 c7b8d71aa25d7136dacfcf548456f86a1dddc2dc
child 108251 7b385ab021186f18d6cd6e54b8cbec463d193a7a
push id23549
push usergszorc@mozilla.com
push dateThu, 27 Sep 2012 17:13:24 +0000
treeherdermozilla-central@74522aafbcdc [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersglandium
bugs794729
milestone18.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 794729 - Run config.guess and mozconfig through shell; r=glandium DONTBUILD (NPOTB)
python/mozbuild/mozbuild/base.py
--- a/python/mozbuild/mozbuild/base.py
+++ b/python/mozbuild/mozbuild/base.py
@@ -98,24 +98,30 @@ class MozbuildObject(object):
 
         loader = os.path.join(self.topsrcdir, 'build', 'autoconf',
             'mozconfig2client-mk')
 
         # os.environ from a library function is somewhat evil. But, mozconfig
         # files are tightly coupled with the environment by definition. In the
         # future, perhaps we'll have a more sanitized environment for mozconfig
         # execution.
+        #
+        # The force of str is required because subprocess on Python <2.7.3
+        # does not like unicode in environment keys or values. At the time this
+        # was written, Mozilla shipped Python 2.7.2 with MozillaBuild.
         env = dict(os.environ)
         if path is not None:
-            env['MOZCONFIG'] = path
+            env[str('MOZCONFIG')] = path
+
+        env[str('CONFIG_GUESS')] = self._config_guess
 
-        env['CONFIG_GUESS'] = self._config_guess
+        args = self._normalize_command([loader, self.topsrcdir], True)
 
-        output = subprocess.check_output([loader, self.topsrcdir],
-            stderr=subprocess.PIPE, cwd=self.topsrcdir, env=env)
+        output = subprocess.check_output(args, stderr=subprocess.PIPE,
+            cwd=self.topsrcdir, env=env)
 
         # The output is make syntax. We parse this in a specialized make
         # context.
         statements = pymake.parser.parsestring(output, 'mozconfig')
 
         makefile = Makefile(workdir=self.topsrcdir, env={
             'TOPSRCDIR': self.topsrcdir,
             'CONFIG_GUESS': self._config_guess})
@@ -142,17 +148,18 @@ class MozbuildObject(object):
             # If we want to extract other variables defined by mozconfig, here
             # is where we'd do it.
 
     @property
     def _config_guess(self):
         if self._config_guess_output is None:
             p = os.path.join(self.topsrcdir, 'build', 'autoconf',
                 'config.guess')
-            self._config_guess_output = subprocess.check_output([p],
+            args = self._normalize_command([p], True)
+            self._config_guess_output = subprocess.check_output(args,
                 cwd=self.topsrcdir).strip()
 
         return self._config_guess_output
 
     def _ensure_objdir_exists(self):
         if os.path.isdir(self.statedir):
             return
 
@@ -287,30 +294,17 @@ class MozbuildObject(object):
             set of environment variables.
         explicit_env -- Dict of environment variables to set for the new
             process. Any existing environment variables will be ignored.
 
         require_unix_environment if True will ensure the command is executed
         within a UNIX environment. Basically, if we are on Windows, it will
         execute the command via an appropriate UNIX-like shell.
         """
-        assert isinstance(args, list) and len(args)
-
-        if require_unix_environment and _in_msys:
-            # Always munge Windows-style into Unix style for the command.
-            prog = args[0].replace('\\', '/')
-
-            # PyMake removes the C: prefix. But, things seem to work here
-            # without it. Not sure what that's about.
-
-            # We run everything through the msys shell. We need to use
-            # '-c' and pass all the arguments as one argument because that is
-            # how sh works.
-            cline = subprocess.list2cmdline([prog] + args[1:])
-            args = [_current_shell, '-c', cline]
+        args = self._normalize_command(args, require_unix_environment)
 
         self.log(logging.INFO, 'process', {'args': args}, ' '.join(args))
 
         def handleLine(line):
             if line_handler:
                 line_handler(line)
 
             if not log_name:
@@ -331,16 +325,42 @@ class MozbuildObject(object):
             processOutputLine=[handleLine], universal_newlines=True)
         p.run()
         p.processOutput()
         status = p.wait()
 
         if status != 0 and not ignore_errors:
             raise Exception('Process executed with non-0 exit code: %s' % args)
 
+    def _normalize_command(self, args, require_unix_environment):
+        """Adjust command arguments to run in the necessary environment.
+
+        This exists mainly to facilitate execution of programs requiring a *NIX
+        shell when running on Windows. The caller specifies whether a shell
+        environment is required. If it is and we are running on Windows but
+        aren't running in the UNIX-like msys environment, then we rewrite the
+        command to execute via a shell.
+        """
+        assert isinstance(args, list) and len(args)
+
+        if not require_unix_environment or not _in_msys:
+            return args
+
+        # Always munge Windows-style into Unix style for the command.
+        prog = args[0].replace('\\', '/')
+
+        # PyMake removes the C: prefix. But, things seem to work here
+        # without it. Not sure what that's about.
+
+        # We run everything through the msys shell. We need to use
+        # '-c' and pass all the arguments as one argument because that is
+        # how sh works.
+        cline = subprocess.list2cmdline([prog] + args[1:])
+        return [_current_shell, '-c', cline]
+
     def _is_windows(self):
         return os.name in ('nt', 'ce')
 
     def _spawn(self, cls):
         """Create a new MozbuildObject-derived class instance from ourselves.
 
         This is used as a convenience method to create other
         MozbuildObject-derived class instances. It can only be used on