Bug 1521996 - Part 2: Specialize `mach {run,install}` for Android. r=ahal,gbrown
authorNick Alexander <nalexander@mozilla.com>
Fri, 17 May 2019 21:40:15 +0000
changeset 474413 376efab28772a451060d9832e84c918b46aef8f4
parent 474412 e3a0fedff65ea47dba3607665a1d34241d0c39c4
child 474414 c0df3469a4cb5982613aca1cfef71af8ba38b843
push id85794
push usernalexander@mozilla.com
push dateFri, 17 May 2019 22:27:11 +0000
treeherderautoland@c0df3469a4cb [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersahal, gbrown
bugs1521996
milestone68.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 1521996 - Part 2: Specialize `mach {run,install}` for Android. r=ahal,gbrown This just separates out the Android definitions into mobile/android/mach_commands.py. There was vestigial support for running on Android with debuggers, but it was for wiring up JimDB, which is no longer supported and in fact hasn't worked on actual devices for a very long time. (The new flow for running on Android under a debugger goes through the Android Studio hybrid debugger.) Differential Revision: https://phabricator.services.mozilla.com/D18291
mobile/android/mach_commands.py
python/mozbuild/mozbuild/base.py
python/mozbuild/mozbuild/mach_commands.py
--- a/mobile/android/mach_commands.py
+++ b/mobile/android/mach_commands.py
@@ -587,16 +587,41 @@ class MachCommands(MachCommandBase):
             ensure_exit_code=False,  # Don't throw on non-zero exit code.
             cwd=mozpath.join(self.topsrcdir))
 
     @Command('gradle-install', category='devenv',
              conditions=[REMOVED])
     def gradle_install(self):
         pass
 
+    @Command('install-android', category='post-build',
+             conditional_name='install',
+             conditions=[conditions.is_android],
+             description='Install an Android package on a device or an emulator.')
+    @CommandArgument('--verbose', '-v', action='store_true',
+                     help='Print verbose output when installing.')
+    def install(self, verbose=False):
+        from mozrunner.devices.android_device import verify_android_device
+        verify_android_device(self, verbose=verbose)
+
+        ret = self._run_make(directory='.', target='install', ensure_exit_code=False)
+        if ret == 0:
+            self.notify('Install complete')
+        return ret
+
+    @Command('run-android', category='post-build',
+             conditional_name='run',
+             conditions=[conditions.is_android],
+             description='Run Fennec on an Android device or an emulator.')
+    def run(self):
+        from mozrunner.devices.android_device import verify_android_device, run_firefox_for_android
+
+        verify_android_device(self, install=True)
+        return run_firefox_for_android(self, [])
+
 
 def _get_maven_archive_abs_and_relative_paths(maven_folder):
     for subdir, _, files in os.walk(maven_folder):
         for file in files:
             full_path = os.path.join(subdir, file)
             relative_path = os.path.relpath(full_path, maven_folder)
 
             # maven-metadata is intended to be generated on the real maven server
--- a/python/mozbuild/mozbuild/base.py
+++ b/python/mozbuild/mozbuild/base.py
@@ -966,16 +966,23 @@ class MachCommandConditions(object):
     @staticmethod
     def is_android(cls):
         """Must have an Android build."""
         if hasattr(cls, 'substs'):
             return cls.substs.get('MOZ_WIDGET_TOOLKIT') == 'android'
         return False
 
     @staticmethod
+    def is_not_android(cls):
+        """Must not have an Android build."""
+        if hasattr(cls, 'substs'):
+            return cls.substs.get('MOZ_WIDGET_TOOLKIT') != 'android'
+        return False
+
+    @staticmethod
     def is_firefox_or_android(cls):
         """Must have a Firefox or Android build."""
         return MachCommandConditions.is_firefox(cls) or MachCommandConditions.is_android(cls)
 
     @staticmethod
     def is_hg(cls):
         """Must have a mercurial source checkout."""
         return getattr(cls, 'substs', {}).get('VCS_CHECKOUT_TYPE') == 'hg'
--- a/python/mozbuild/mozbuild/mach_commands.py
+++ b/python/mozbuild/mozbuild/mach_commands.py
@@ -875,24 +875,23 @@ class Package(MachCommandBase):
         if ret == 0:
             self.notify('Packaging complete')
         return ret
 
 @CommandProvider
 class Install(MachCommandBase):
     """Install a package."""
 
-    @Command('install', category='post-build',
-        description='Install the package on the machine, or on a device.')
+    @Command('install-desktop', category='post-build',
+        conditional_name='install',
+        conditions=[conditions.is_not_android],
+        description='Install the package on the machine.')
     @CommandArgument('--verbose', '-v', action='store_true',
         help='Print verbose output when installing to an Android emulator.')
     def install(self, verbose=False):
-        if conditions.is_android(self):
-            from mozrunner.devices.android_device import verify_android_device
-            verify_android_device(self, verbose=verbose)
         ret = self._run_make(directory=".", target='install', ensure_exit_code=False)
         if ret == 0:
             self.notify('Install complete')
         return ret
 
 @SettingsProvider
 class RunSettings():
     config_settings = [
@@ -904,17 +903,19 @@ single quoted to force them to be string
     ]
 
 @CommandProvider
 class RunProgram(MachCommandBase):
     """Run the compiled program."""
 
     prog_group = 'the compiled program'
 
-    @Command('run', category='post-build',
+    @Command('run-desktop', category='post-build',
+        conditional_name='run',
+        conditions=[conditions.is_not_android],
         description='Run the compiled program, possibly under a debugger or DMD.')
     @CommandArgument('params', nargs='...', group=prog_group,
         help='Command-line arguments to be passed through to the program. Not specifying a --profile or -P option will result in a temporary profile being used.')
     @CommandArgumentGroup(prog_group)
     @CommandArgument('--remote', '-r', action='store_true', group=prog_group,
         help='Do not pass the --no-remote argument by default.')
     @CommandArgument('--background', '-b', action='store_true', group=prog_group,
         help='Do not pass the --foreground argument by default on Mac.')
@@ -951,99 +952,86 @@ class RunProgram(MachCommandBase):
     @CommandArgument('--stacks', choices=['partial', 'full'], group='DMD',
         help='Allocation stack trace coverage. The default is \'partial\'.')
     @CommandArgument('--show-dump-stats', action='store_true', group='DMD',
         help='Show stats when doing dumps.')
     def run(self, params, remote, background, noprofile, disable_e10s,
         enable_crash_reporter, setpref, temp_profile, macos_open, debug,
         debugger, debugger_args, dmd, mode, stacks, show_dump_stats):
 
-        if conditions.is_android(self):
-            # Running Firefox for Android is completely different
-            if dmd:
-                print("DMD is not supported for Firefox for Android")
+        from mozprofile import Profile, Preferences
+
+        try:
+            binpath = self.get_binary_path('app')
+        except Exception as e:
+            print("It looks like your program isn't built.",
+                "You can run |mach build| to build it.")
+            print(e)
+            return 1
+
+        args = []
+        if macos_open:
+            if debug:
+                print("The browser can not be launched in the debugger "
+                    "when using the macOS open command.")
                 return 1
-            from mozrunner.devices.android_device import verify_android_device, run_firefox_for_android
-            if not (debug or debugger or debugger_args):
-                verify_android_device(self, install=True)
-                return run_firefox_for_android(self, params)
-            verify_android_device(self, install=True, debugger=True)
-            args = ['']
-
-        else:
-            from mozprofile import Profile, Preferences
-
             try:
-                binpath = self.get_binary_path('app')
+                m = re.search(r'^.+\.app', binpath)
+                apppath = m.group(0)
+                args = ['open', apppath, '--args']
             except Exception as e:
-                print("It looks like your program isn't built.",
-                    "You can run |mach build| to build it.")
+                print("Couldn't get the .app path from the binary path. "
+                    "The macOS open option can only be used on macOS")
                 print(e)
                 return 1
-
-            args = []
-            if macos_open:
-                if debug:
-                    print("The browser can not be launched in the debugger "
-                        "when using the macOS open command.")
-                    return 1
-                try:
-                    m = re.search(r'^.+\.app', binpath)
-                    apppath = m.group(0)
-                    args = ['open', apppath, '--args']
-                except Exception as e:
-                    print("Couldn't get the .app path from the binary path. "
-                        "The macOS open option can only be used on macOS")
-                    print(e)
-                    return 1
+        else:
+            args = [binpath]
+
+        if params:
+            args.extend(params)
+
+        if not remote:
+            args.append('-no-remote')
+
+        if not background and sys.platform == 'darwin':
+            args.append('-foreground')
+
+        if sys.platform.startswith('win') and \
+           'MOZ_LAUNCHER_PROCESS' in self.defines:
+            args.append('-wait-for-browser')
+
+        no_profile_option_given = \
+            all(p not in params for p in ['-profile', '--profile', '-P'])
+        if no_profile_option_given and not noprofile:
+            prefs = {
+               'browser.aboutConfig.showWarning': False,
+               'browser.shell.checkDefaultBrowser': False,
+               'general.warnOnAboutConfig': False,
+            }
+            prefs.update(self._mach_context.settings.runprefs)
+            prefs.update([p.split('=', 1) for p in setpref])
+            for pref in prefs:
+                prefs[pref] = Preferences.cast(prefs[pref])
+
+            tmpdir = os.path.join(self.topobjdir, 'tmp')
+            if not os.path.exists(tmpdir):
+                os.makedirs(tmpdir)
+
+            if (temp_profile):
+                path = tempfile.mkdtemp(dir=tmpdir, prefix='profile-')
             else:
-                args = [binpath]
-
-            if params:
-                args.extend(params)
-
-            if not remote:
-                args.append('-no-remote')
-
-            if not background and sys.platform == 'darwin':
-                args.append('-foreground')
-
-            if sys.platform.startswith('win') and \
-               'MOZ_LAUNCHER_PROCESS' in self.defines:
-                args.append('-wait-for-browser')
-
-            no_profile_option_given = \
-                all(p not in params for p in ['-profile', '--profile', '-P'])
-            if no_profile_option_given and not noprofile:
-                prefs = {
-                   'browser.aboutConfig.showWarning': False,
-                   'browser.shell.checkDefaultBrowser': False,
-                   'general.warnOnAboutConfig': False,
-                }
-                prefs.update(self._mach_context.settings.runprefs)
-                prefs.update([p.split('=', 1) for p in setpref])
-                for pref in prefs:
-                    prefs[pref] = Preferences.cast(prefs[pref])
-
-                tmpdir = os.path.join(self.topobjdir, 'tmp')
-                if not os.path.exists(tmpdir):
-                    os.makedirs(tmpdir)
-
-                if (temp_profile):
-                    path = tempfile.mkdtemp(dir=tmpdir, prefix='profile-')
-                else:
-                    path = os.path.join(tmpdir, 'profile-default')
-
-                profile = Profile(path, preferences=prefs)
-                args.append('-profile')
-                args.append(profile.profile)
-
-            if not no_profile_option_given and setpref:
-                print("setpref is only supported if a profile is not specified")
-                return 1
+                path = os.path.join(tmpdir, 'profile-default')
+
+            profile = Profile(path, preferences=prefs)
+            args.append('-profile')
+            args.append(profile.profile)
+
+        if not no_profile_option_given and setpref:
+            print("setpref is only supported if a profile is not specified")
+            return 1
 
             if not no_profile_option_given:
                 # The profile name may be non-ascii, but come from the
                 # commandline as str, so convert here with a better guess at
                 # an encoding than the default.
                 encoding = (sys.getfilesystemencoding() or
                             sys.getdefaultencoding())
                 args = [unicode(a, encoding) if not isinstance(a, unicode) else a