Bug 914411 - Option to force mach build to use pymake; r=glandium
authorGregory Szorc <gps@mozilla.com>
Mon, 09 Sep 2013 22:28:36 -0700
changeset 159304 32e968bcba07e2296ea6ab9f9a7c20a939f5b025
parent 159303 bd53e981282f9ed59ca35ce59776c2f94e9f6e7d
child 159305 77cd72a836e60548db0ae4013fca6786f5ac8c8f
push id2961
push userlsblakk@mozilla.com
push dateMon, 28 Oct 2013 21:59:28 +0000
treeherdermozilla-beta@73ef4f13486f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersglandium
bugs914411
milestone26.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 914411 - Option to force mach build to use pymake; r=glandium
python/mozbuild/mozbuild/base.py
python/mozbuild/mozbuild/mach_commands.py
--- a/python/mozbuild/mozbuild/base.py
+++ b/python/mozbuild/mozbuild/base.py
@@ -354,33 +354,33 @@ class MozbuildObject(ProcessExecutionMix
 
     def _wrap_path_argument(self, arg):
         return PathArgument(arg, self.topsrcdir, self.topobjdir)
 
     def _run_make(self, directory=None, filename=None, target=None, log=True,
             srcdir=False, allow_parallel=True, line_handler=None,
             append_env=None, explicit_env=None, ignore_errors=False,
             ensure_exit_code=0, silent=True, print_directory=True,
-            pass_thru=False, num_jobs=0):
+            pass_thru=False, num_jobs=0, force_pymake=False):
         """Invoke make.
 
         directory -- Relative directory to look for Makefile in.
         filename -- Explicit makefile to run.
         target -- Makefile target(s) to make. Can be a string or iterable of
             strings.
         srcdir -- If True, invoke make from the source directory tree.
             Otherwise, make will be invoked from the object directory.
         silent -- If True (the default), run make in silent mode.
         print_directory -- If True (the default), have make print directories
         while doing traversal.
+        force_pymake -- If True, pymake will be used instead of GNU make.
         """
         self._ensure_objdir_exists()
 
-        # Need to copy list since we modify it.
-        args = list(self._make_path)
+        args = [self._make_path(force_pymake=force_pymake)]
 
         if directory:
             args.extend(['-C', directory])
 
         if filename:
             args.extend(['-f', filename])
 
         if allow_parallel:
@@ -431,36 +431,28 @@ class MozbuildObject(ProcessExecutionMix
             'ignore_children': True,
         }
 
         if log:
             params['log_name'] = 'make'
 
         return fn(**params)
 
-    @property
-    def _make_path(self):
-        if self._make is None:
-            if self._is_windows():
-                make_py = os.path.join(self.topsrcdir, 'build', 'pymake',
-                    'make.py').replace(os.sep, '/')
-                self._make = [sys.executable, make_py]
+    def _make_path(self, force_pymake=False):
+        if self._is_windows() or force_pymake:
+            return os.path.join(self.topsrcdir, 'build', 'pymake',
+                'make.py').replace(os.sep, '/')
 
-            else:
-                for test in ['gmake', 'make']:
-                    try:
-                        self._make = [which.which(test)]
-                        break
-                    except which.WhichError:
-                        continue
+        for test in ['gmake', 'make']:
+            try:
+                return which.which(test)
+            except which.WhichError:
+                continue
 
-        if self._make is None:
-            raise Exception('Could not find suitable make binary!')
-
-        return self._make
+        raise Exception('Could not find a suitable make implementation.')
 
     def _run_command_in_srcdir(self, **args):
         return self.run_process(cwd=self.topsrcdir, **args)
 
     def _run_command_in_objdir(self, **args):
         return self.run_process(cwd=self.topobjdir, **args)
 
     def _is_windows(self):
--- a/python/mozbuild/mozbuild/mach_commands.py
+++ b/python/mozbuild/mozbuild/mach_commands.py
@@ -278,22 +278,25 @@ class BuildOutputManager(LoggingMixin):
 @CommandProvider
 class Build(MachCommandBase):
     """Interface to build the tree."""
 
     @Command('build', category='build', description='Build the tree.')
     @CommandArgument('--jobs', '-j', default='0', metavar='jobs', type=int,
         help='Number of concurrent jobs to run. Default is the number of CPUs.')
     @CommandArgument('what', default=None, nargs='*', help=BUILD_WHAT_HELP)
+    @CommandArgument('-p', '--pymake', action='store_true',
+        help='Force using pymake over GNU make.')
     @CommandArgument('-X', '--disable-extra-make-dependencies',
                      default=False, action='store_true',
                      help='Do not add extra make dependencies.')
     @CommandArgument('-v', '--verbose', action='store_true',
         help='Verbose output for what commands the build is running.')
-    def build(self, what=None, disable_extra_make_dependencies=None, jobs=0, verbose=False):
+    def build(self, what=None, pymake=False,
+        disable_extra_make_dependencies=None, jobs=0, verbose=False):
         import which
         from mozbuild.controller.building import BuildMonitor
         from mozbuild.util import resolve_target_to_make
 
         self.log_manager.register_structured_logger(logging.getLogger('mozbuild'))
 
         warnings_path = self._get_state_filename('warnings.json')
         monitor = self._spawn(BuildMonitor)
@@ -353,26 +356,27 @@ class Build(MachCommandBase):
                 for make_dir, make_target in target_pairs:
                     # We don't display build status messages during partial
                     # tree builds because they aren't reliable there. This
                     # could potentially be fixed if the build monitor were more
                     # intelligent about encountering undefined state.
                     status = self._run_make(directory=make_dir, target=make_target,
                         line_handler=output.on_line, log=False, print_directory=False,
                         ensure_exit_code=False, num_jobs=jobs, silent=not verbose,
-                        append_env={b'NO_BUILDSTATUS_MESSAGES': b'1'})
+                        append_env={b'NO_BUILDSTATUS_MESSAGES': b'1'},
+                        force_pymake=pymake)
 
                     if status != 0:
                         break
             else:
                 monitor.start_resource_recording()
                 status = self._run_make(srcdir=True, filename='client.mk',
                     line_handler=output.on_line, log=False, print_directory=False,
                     allow_parallel=False, ensure_exit_code=False, num_jobs=jobs,
-                    silent=not verbose)
+                    silent=not verbose, force_pymake=pymake)
 
                 self.log(logging.WARNING, 'warning_summary',
                     {'count': len(monitor.warnings_database)},
                     '{count} compiler warnings present.')
 
             monitor.finish(record_usage=status==0)
 
         high_finder, finder_percent = monitor.have_high_finder_usage()