summaryrefslogtreecommitdiffstats
path: root/python/mozboot
diff options
context:
space:
mode:
authorMatt A. Tobin <mattatobin@localhost.localdomain>2018-02-02 04:16:08 -0500
committerMatt A. Tobin <mattatobin@localhost.localdomain>2018-02-02 04:16:08 -0500
commit5f8de423f190bbb79a62f804151bc24824fa32d8 (patch)
tree10027f336435511475e392454359edea8e25895d /python/mozboot
parent49ee0794b5d912db1f95dce6eb52d781dc210db5 (diff)
downloadUXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.gz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.lz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.xz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.zip
Add m-esr52 at 52.6.0
Diffstat (limited to 'python/mozboot')
-rw-r--r--python/mozboot/README.rst19
-rw-r--r--python/mozboot/bin/bootstrap-msys2.vbs116
-rwxr-xr-xpython/mozboot/bin/bootstrap.py170
-rw-r--r--python/mozboot/mozboot/__init__.py0
-rw-r--r--python/mozboot/mozboot/android.py270
-rw-r--r--python/mozboot/mozboot/archlinux.py223
-rw-r--r--python/mozboot/mozboot/base.py452
-rw-r--r--python/mozboot/mozboot/bootstrap.py437
-rw-r--r--python/mozboot/mozboot/centosfedora.py153
-rw-r--r--python/mozboot/mozboot/debian.py188
-rw-r--r--python/mozboot/mozboot/freebsd.py63
-rw-r--r--python/mozboot/mozboot/gentoo.py33
-rw-r--r--python/mozboot/mozboot/mach_commands.py67
-rw-r--r--python/mozboot/mozboot/mozillabuild.py77
-rw-r--r--python/mozboot/mozboot/openbsd.py45
-rw-r--r--python/mozboot/mozboot/osx.py577
-rw-r--r--python/mozboot/mozboot/util.py20
-rw-r--r--python/mozboot/mozboot/windows.py95
-rw-r--r--python/mozboot/setup.py16
-rwxr-xr-xpython/mozboot/support/ConEmu.xml897
20 files changed, 3918 insertions, 0 deletions
diff --git a/python/mozboot/README.rst b/python/mozboot/README.rst
new file mode 100644
index 000000000..a1366eea2
--- /dev/null
+++ b/python/mozboot/README.rst
@@ -0,0 +1,19 @@
+mozboot - Bootstrap your system to build Mozilla projects
+=========================================================
+
+This package contains code used for bootstrapping a system to build
+mozilla-central.
+
+This code is not part of the build system per se. Instead, it is related
+to everything up to invoking the actual build system.
+
+If you have a copy of the source tree, you run:
+
+ python bin/bootstrap.py
+
+If you don't have a copy of the source tree, you can run:
+
+ curl https://hg.mozilla.org/mozilla-central/raw-file/default/python/mozboot/bin/bootstrap.py | python -
+
+The bootstrap script will download everything it needs from hg.mozilla.org
+automatically!
diff --git a/python/mozboot/bin/bootstrap-msys2.vbs b/python/mozboot/bin/bootstrap-msys2.vbs
new file mode 100644
index 000000000..304d4f9df
--- /dev/null
+++ b/python/mozboot/bin/bootstrap-msys2.vbs
@@ -0,0 +1,116 @@
+' 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/.
+
+' This script downloads and install MSYS2 and the preferred terminal emulator ConEmu
+
+Sub Download(uri, path)
+ Dim httpRequest, stream
+
+ Set httpRequest = CreateObject("MSXML2.ServerXMLHTTP.6.0")
+ Set stream = CreateObject("Adodb.Stream")
+
+ httpRequest.Open "GET", uri, False
+ httpRequest.Send
+
+ With stream
+ .type = 1
+ .open
+ .write httpRequest.responseBody
+ .savetofile path, 2
+ End With
+End Sub
+
+Function GetInstallPath()
+ Dim message, prompt
+
+ message = "When you click OK, we will download and extract a build environment to the directory specified. You should see various windows appear. Do NOT interact with them until one explicitly prompts you to continue." & vbCrLf & vbCrLf & "Installation Path:"
+ title = "Select Installation Location"
+ GetInstallPath = InputBox(message, title, "c:\mozdev")
+end Function
+
+Dim installPath, msysPath, conemuPath, conemuSettingsPath, conemuExecutable, bashExecutable
+Dim conemuSettingsURI, settingsFile, settingsText, fso, shell, msysArchive, appShell, errorCode
+Dim mingwExecutable
+
+' Set up OS interaction like filesystem and shell
+Set fso = CreateObject("Scripting.FileSystemObject")
+Set shell = CreateObject("WScript.Shell")
+Set appShell = CreateObject("Shell.Application")
+
+' Get where MSYS2 and ConEmu should be installed, create directories if necessary
+installPath = GetInstallPath()
+msysPath = fso.BuildPath(installPath, "msys64")
+conemuPath = fso.BuildPath(installPath, "ConEmu")
+If NOT fso.FolderExists(installPath) Then
+ fso.CreateFolder(installPath)
+ fso.CreateFolder(msysPath)
+End If
+If NOT fso.FolderExists(installPath) Then
+ MsgBox("Failed to create folder. Do you have permission to install in this directory?")
+ WScript.Quit 1
+End If
+
+On Error Resume Next
+' Download and move MSYS2 into the right place
+Download "https://api.pub.build.mozilla.org/tooltool/sha512/f93a685c8a10abbd349cbef5306441ba235c4cbfba1cc000299e11b58f258e9953cbe23463515407925eeca94c3f5d8e5f637c95be387e620845efa43cdcb0c0", "msys2.zip"
+Set FilesInZip = appShell.NameSpace(fso.GetAbsolutePathName("msys2.zip")).Items()
+appShell.NameSpace(msysPath).CopyHere(FilesInZip)
+' MSYS2 archive doesn't have tmp directory...
+fso.CreateFolder(fso.BuildPath(msysPath, "tmp"))
+fso.DeleteFile("msys2.zip")
+If Err.Number <> 0 Then
+ MsgBox("Error downloading and installing MSYS2. Make sure you have internet connection. If you think this is a bug, please file one in Bugzilla https://bugzilla.mozilla.org/enter_bug.cgi?product=Core&component=Build%20Config")
+ WScript.Quit 1
+End If
+On Error GoTo 0
+
+' Install ConEmu
+' Download installer
+On Error Resume Next
+Download "https://conemu.github.io/install2.ps1", "install2.ps1"
+conemuSettingsURI = "https://api.pub.build.mozilla.org/tooltool/sha512/9aa384ecc8025a974999e913c83064b3b797e05d19806e62ef558c8300e4c3f72967e9464ace59759f76216fc2fc66f338a1e5cdea3b9aa264529487f091d929"
+' Run installer
+errorCode = shell.Run("powershell.exe -NoProfile -ExecutionPolicy Unrestricted set dst '" & conemuPath & "'; set ver 'stable'; set lnk 'Mozilla Development Shell'; set xml '" & conemuSettingsURI & "'; set run $FALSE; .\install2.ps1", 0, true)
+' Delete ConEmu installer
+fso.DeleteFile("install2.ps1")
+If Err.Number <> 0 Then
+ MsgBox("Error downloading and installing ConEmu. Make sure you have internet connection and Powershell installed. If you think this is a bug, please file one in Bugzilla https://bugzilla.mozilla.org/enter_bug.cgi?product=Core&component=Build%20Config")
+ WScript.Quit 1
+End If
+On Error GoTo 0
+
+' Replace paths in ConEmu settings file
+conemuSettingsPath = fso.BuildPath(conemuPath, "ConEmu.xml")
+Set settingsFile = fso.OpenTextFile(conemuSettingsPath, 1)
+settingsText = settingsFile.ReadAll
+settingsFile.Close
+settingsText = Replace(settingsText, "%MSYS2_PATH", msysPath)
+Set settingsFile = fso.OpenTextFile(conemuSettingsPath, 2)
+settingsFile.WriteLine settingsText
+settingsFile.Close
+
+' Make MSYS2 Mozilla-ready
+bashExecutable = fso.BuildPath(msysPath, fso.BuildPath("usr", fso.BuildPath("bin", "bash.exe")))
+conemuExecutable = fso.BuildPath(conemuPath, "ConEmu.exe")
+' There may be spaces in the paths to the executable, this ensures they're parsed correctly
+bashExecutable = """" & bashExecutable & """"
+conemuExecutable = """" & conemuExecutable & """"
+
+errorCode = shell.Run(bashExecutable & " -l -c 'logout", 1, true)
+If errorCode <> 0 Then
+ MsgBox("MSYS2 initial setup failed. Make sure you have full access to the path you specified. If you think this is a bug, please file one in Bugzilla at https://bugzilla.mozilla.org/enter_bug.cgi?product=Core&component=Build%20Config")
+ WScript.Quit 1
+End If
+
+errorCode = shell.Run(bashExecutable & " -l -c 'pacman -Syu --noconfirm wget mingw-w64-x86_64-python2-pip && logout'", 1, true)
+If errorCode <> 0 Then
+ MsgBox("Package update failed. Make sure you have internet access. If you think this is a bug, please file one in Bugzilla at https://bugzilla.mozilla.org/enter_bug.cgi?product=Core&component=Build%20Config")
+ WScript.Quit 1
+End If
+
+errorCode = shell.Run(conemuExecutable & " -run set CHERE_INVOKING=1 & set MSYSTEM=MINGW64 & " & bashExecutable & " -cil 'export MOZ_WINDOWS_BOOTSTRAP=1 && cd """ & installPath & """ && wget -q https://hg.mozilla.org/mozilla-central/raw-file/default/python/mozboot/bin/bootstrap.py -O /tmp/bootstrap.py && python /tmp/bootstrap.py'", 1, true)
+If errorCode <> 0 Then
+ MsgBox("Bootstrap failed. Make sure you have internet access. If you think this is a bug, please file one in Bugzilla https://bugzilla.mozilla.org/enter_bug.cgi?product=Core&component=Build%20Config")
+ WScript.Quit 1
+End If
diff --git a/python/mozboot/bin/bootstrap.py b/python/mozboot/bin/bootstrap.py
new file mode 100755
index 000000000..d916351e7
--- /dev/null
+++ b/python/mozboot/bin/bootstrap.py
@@ -0,0 +1,170 @@
+#!/usr/bin/env 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/.
+
+# This script provides one-line bootstrap support to configure systems to build
+# the tree.
+#
+# The role of this script is to load the Python modules containing actual
+# bootstrap support. It does this through various means, including fetching
+# content from the upstream source repository.
+
+# If we add unicode_literals, optparse breaks on Python 2.6.1 (which is needed
+# to support OS X 10.6).
+
+from __future__ import print_function
+
+WRONG_PYTHON_VERSION_MESSAGE = '''
+Bootstrap currently only runs on Python 2.7 or Python 2.6. Please try re-running with python2.7 or python2.6.
+
+If these aren't available on your system, you may need to install them. Look for a "python2" or "python27" package in your package manager.
+'''
+
+import sys
+if sys.version_info[:2] not in [(2, 6), (2, 7)]:
+ print(WRONG_PYTHON_VERSION_MESSAGE)
+ sys.exit(1)
+
+import os
+import shutil
+from StringIO import StringIO
+import tempfile
+try:
+ from urllib2 import urlopen
+except ImportError:
+ from urllib.request import urlopen
+import zipfile
+
+from optparse import OptionParser
+
+# The next two variables define where in the repository the Python files
+# reside. This is used to remotely download file content when it isn't
+# available locally.
+REPOSITORY_PATH_PREFIX = 'python/mozboot/'
+
+TEMPDIR = None
+
+
+def setup_proxy():
+ # Some Linux environments define ALL_PROXY, which is a SOCKS proxy
+ # intended for all protocols. Python doesn't currently automatically
+ # detect this like it does for http_proxy and https_proxy.
+ if 'ALL_PROXY' in os.environ and 'https_proxy' not in os.environ:
+ os.environ['https_proxy'] = os.environ['ALL_PROXY']
+ if 'ALL_PROXY' in os.environ and 'http_proxy' not in os.environ:
+ os.environ['http_proxy'] = os.environ['ALL_PROXY']
+
+
+def fetch_files(repo_url, repo_type):
+ setup_proxy()
+ repo_url = repo_url.rstrip('/')
+
+ files = {}
+
+ if repo_type == 'hgweb':
+ url = repo_url + '/archive/default.zip/python/mozboot'
+ req = urlopen(url=url, timeout=30)
+ data = StringIO(req.read())
+ data.seek(0)
+ zip = zipfile.ZipFile(data, 'r')
+ for f in zip.infolist():
+ # The paths are prefixed with the repo and revision name before the
+ # directory name.
+ offset = f.filename.find(REPOSITORY_PATH_PREFIX) + len(REPOSITORY_PATH_PREFIX)
+ name = f.filename[offset:]
+
+ # We only care about the Python modules.
+ if not name.startswith('mozboot/'):
+ continue
+
+ files[name] = zip.read(f)
+ else:
+ raise NotImplementedError('Not sure how to handle repo type.', repo_type)
+
+ return files
+
+
+def ensure_environment(repo_url=None, repo_type=None):
+ """Ensure we can load the Python modules necessary to perform bootstrap."""
+
+ try:
+ from mozboot.bootstrap import Bootstrapper
+ return Bootstrapper
+ except ImportError:
+ # The first fallback is to assume we are running from a tree checkout
+ # and have the files in a sibling directory.
+ pardir = os.path.join(os.path.dirname(__file__), os.path.pardir)
+ include = os.path.normpath(pardir)
+
+ sys.path.append(include)
+ try:
+ from mozboot.bootstrap import Bootstrapper
+ return Bootstrapper
+ except ImportError:
+ sys.path.pop()
+
+ # The next fallback is to download the files from the source
+ # repository.
+ files = fetch_files(repo_url, repo_type)
+
+ # Install them into a temporary location. They will be deleted
+ # after this script has finished executing.
+ global TEMPDIR
+ TEMPDIR = tempfile.mkdtemp()
+
+ for relpath in files.keys():
+ destpath = os.path.join(TEMPDIR, relpath)
+ destdir = os.path.dirname(destpath)
+
+ if not os.path.exists(destdir):
+ os.makedirs(destdir)
+
+ with open(destpath, 'wb') as fh:
+ fh.write(files[relpath])
+
+ # This should always work.
+ sys.path.append(TEMPDIR)
+ from mozboot.bootstrap import Bootstrapper
+ return Bootstrapper
+
+
+def main(args):
+ parser = OptionParser()
+ parser.add_option('-r', '--repo-url', dest='repo_url',
+ default='https://hg.mozilla.org/mozilla-central/',
+ help='Base URL of source control repository where bootstrap files can '
+ 'be downloaded.')
+ parser.add_option('--repo-type', dest='repo_type',
+ default='hgweb',
+ help='The type of the repository. This defines how we fetch file '
+ 'content. Like --repo, you should not need to set this.')
+
+ parser.add_option('--application-choice', dest='application_choice',
+ help='Pass in an application choice (desktop/android) instead of using the '
+ 'default interactive prompt.')
+ parser.add_option('--no-interactive', dest='no_interactive', action='store_true',
+ help='Answer yes to any (Y/n) interactive prompts.')
+
+ options, leftover = parser.parse_args(args)
+
+ try:
+ try:
+ cls = ensure_environment(options.repo_url, options.repo_type)
+ except Exception as e:
+ print('Could not load the bootstrap Python environment.\n')
+ print('This should never happen. Consider filing a bug.\n')
+ print('\n')
+ print(e)
+ return 1
+ dasboot = cls(choice=options.application_choice, no_interactive=options.no_interactive)
+ dasboot.bootstrap()
+
+ return 0
+ finally:
+ if TEMPDIR is not None:
+ shutil.rmtree(TEMPDIR)
+
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv))
diff --git a/python/mozboot/mozboot/__init__.py b/python/mozboot/mozboot/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/python/mozboot/mozboot/__init__.py
diff --git a/python/mozboot/mozboot/android.py b/python/mozboot/mozboot/android.py
new file mode 100644
index 000000000..cac000610
--- /dev/null
+++ b/python/mozboot/mozboot/android.py
@@ -0,0 +1,270 @@
+# 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/.
+
+# If we add unicode_literals, Python 2.6.1 (required for OS X 10.6) breaks.
+from __future__ import print_function
+
+import errno
+import os
+import stat
+import subprocess
+import sys
+
+# These are the platform and build-tools versions for building
+# mobile/android, respectively. Try to keep these in synch with the
+# build system and Mozilla's automation.
+ANDROID_TARGET_SDK = '23'
+ANDROID_BUILD_TOOLS_VERSION = '23.0.3'
+
+# These are the "Android packages" needed for building Firefox for Android.
+# Use |android list sdk --extended| to see these identifiers.
+ANDROID_PACKAGES = [
+ 'tools',
+ 'platform-tools',
+ 'build-tools-%s' % ANDROID_BUILD_TOOLS_VERSION,
+ 'android-%s' % ANDROID_TARGET_SDK,
+ 'extra-google-m2repository',
+ 'extra-android-m2repository',
+]
+
+ANDROID_NDK_EXISTS = '''
+Looks like you have the Android NDK installed at:
+%s
+'''
+
+ANDROID_SDK_EXISTS = '''
+Looks like you have the Android SDK installed at:
+%s
+We will install all required Android packages.
+'''
+
+NOT_INSTALLING_ANDROID_PACKAGES = '''
+It looks like you already have the following Android packages:
+%s
+No need to update!
+'''
+
+INSTALLING_ANDROID_PACKAGES = '''
+We are now installing the following Android packages:
+%s
+You may be prompted to agree to the Android license. You may see some of
+output as packages are downloaded and installed.
+'''
+
+MISSING_ANDROID_PACKAGES = '''
+We tried to install the following Android packages:
+%s
+But it looks like we couldn't install:
+%s
+Install these Android packages manually and run this bootstrapper again.
+'''
+
+MOBILE_ANDROID_MOZCONFIG_TEMPLATE = '''
+Paste the lines between the chevrons (>>> and <<<) into your mozconfig file:
+
+<<<
+# Build Firefox for Android:
+ac_add_options --enable-application=mobile/android
+ac_add_options --target=arm-linux-androideabi
+
+# With the following Android SDK and NDK:
+ac_add_options --with-android-sdk="%s"
+ac_add_options --with-android-ndk="%s"
+>>>
+'''
+
+MOBILE_ANDROID_ARTIFACT_MODE_MOZCONFIG_TEMPLATE = '''
+Paste the lines between the chevrons (>>> and <<<) into your mozconfig file:
+
+<<<
+# Build Firefox for Android Artifact Mode:
+ac_add_options --enable-application=mobile/android
+ac_add_options --target=arm-linux-androideabi
+ac_add_options --enable-artifact-builds
+
+# With the following Android SDK:
+ac_add_options --with-android-sdk="%s"
+
+# Write build artifacts to:
+mk_add_options MOZ_OBJDIR=./objdir-frontend
+>>>
+'''
+
+
+def check_output(*args, **kwargs):
+ """Run subprocess.check_output even if Python doesn't provide it."""
+ from base import BaseBootstrapper
+ fn = getattr(subprocess, 'check_output', BaseBootstrapper._check_output)
+
+ return fn(*args, **kwargs)
+
+
+def list_missing_android_packages(android_tool, packages):
+ '''
+ Use the given |android| tool to return the sub-list of Android
+ |packages| given that are not installed.
+ '''
+ missing = []
+
+ # There's no obvious way to see what's been installed already,
+ # but packages that are installed don't appear in the list of
+ # available packages.
+ lines = check_output([android_tool,
+ 'list', 'sdk', '--no-ui', '--extended']).splitlines()
+
+ # Lines look like: 'id: 59 or "extra-google-simulators"'
+ for line in lines:
+ is_id_line = False
+ try:
+ is_id_line = line.startswith("id:")
+ except:
+ # Some lines contain non-ASCII characters. Ignore them.
+ pass
+ if not is_id_line:
+ continue
+
+ for package in packages:
+ if '"%s"' % package in line:
+ # Not installed!
+ missing.append(package)
+
+ return missing
+
+
+def install_mobile_android_sdk_or_ndk(url, path):
+ '''
+ Fetch an Android SDK or NDK from |url| and unpack it into
+ the given |path|.
+
+ We expect wget to be installed and found on the system path.
+
+ We use, and wget respects, https. We could also include SHAs for a
+ small improvement in the integrity guarantee we give. But this script is
+ bootstrapped over https anyway, so it's a really minor improvement.
+
+ We use |wget --continue| as a cheap cache of the downloaded artifacts,
+ writing into |path|/mozboot. We don't yet clean the cache; it's better
+ to waste disk and not require a long re-download than to wipe the cache
+ prematurely.
+ '''
+
+ old_path = os.getcwd()
+ try:
+ download_path = os.path.join(path, 'mozboot')
+ try:
+ os.makedirs(download_path)
+ except OSError as e:
+ if e.errno == errno.EEXIST and os.path.isdir(download_path):
+ pass
+ else:
+ raise
+
+ os.chdir(download_path)
+ subprocess.check_call(['wget', '--continue', url])
+ file = url.split('/')[-1]
+
+ os.chdir(path)
+ abspath = os.path.join(download_path, file)
+ if file.endswith('.tar.gz') or file.endswith('.tgz'):
+ cmd = ['tar', 'zxf', abspath]
+ elif file.endswith('.tar.bz2'):
+ cmd = ['tar', 'jxf', abspath]
+ elif file.endswith('.zip'):
+ cmd = ['unzip', '-q', abspath]
+ elif file.endswith('.bin'):
+ # Execute the .bin file, which unpacks the content.
+ mode = os.stat(path).st_mode
+ os.chmod(abspath, mode | stat.S_IXUSR)
+ cmd = [abspath]
+ else:
+ raise NotImplementedError("Don't know how to unpack file: %s" % file)
+
+ print('Unpacking %s...' % abspath)
+
+ with open(os.devnull, "w") as stdout:
+ # These unpack commands produce a ton of output; ignore it. The
+ # .bin files are 7z archives; there's no command line flag to quiet
+ # output, so we use this hammer.
+ subprocess.check_call(cmd, stdout=stdout)
+
+ print('Unpacking %s... DONE' % abspath)
+
+ finally:
+ os.chdir(old_path)
+
+
+def ensure_android_sdk_and_ndk(path, sdk_path, sdk_url, ndk_path, ndk_url, artifact_mode):
+ '''
+ Ensure the Android SDK and NDK are found at the given paths. If not, fetch
+ and unpack the SDK and/or NDK from the given URLs into |path|.
+ '''
+
+ # It's not particularly bad to overwrite the NDK toolchain, but it does take
+ # a while to unpack, so let's avoid the disk activity if possible. The SDK
+ # may prompt about licensing, so we do this first.
+ # Check for Android NDK only if we are not in artifact mode.
+ if not artifact_mode:
+ if os.path.isdir(ndk_path):
+ print(ANDROID_NDK_EXISTS % ndk_path)
+ else:
+ install_mobile_android_sdk_or_ndk(ndk_url, path)
+
+ # We don't want to blindly overwrite, since we use the |android| tool to
+ # install additional parts of the Android toolchain. If we overwrite,
+ # we lose whatever Android packages the user may have already installed.
+ if os.path.isdir(sdk_path):
+ print(ANDROID_SDK_EXISTS % sdk_path)
+ else:
+ install_mobile_android_sdk_or_ndk(sdk_url, path)
+
+
+def ensure_android_packages(android_tool, packages=None):
+ '''
+ Use the given android tool (like 'android') to install required Android
+ packages.
+ '''
+
+ if not packages:
+ packages = ANDROID_PACKAGES
+
+ # Bug 1171232: The |android| tool behaviour has changed; we no longer can
+ # see what packages are installed easily. Force installing everything until
+ # we find a way to actually see the missing packages.
+ missing = packages
+ if not missing:
+ print(NOT_INSTALLING_ANDROID_PACKAGES % ', '.join(packages))
+ return
+
+ # This tries to install all the required Android packages. The user
+ # may be prompted to agree to the Android license.
+ print(INSTALLING_ANDROID_PACKAGES % ', '.join(missing))
+ subprocess.check_call([android_tool,
+ 'update', 'sdk', '--no-ui', '--all',
+ '--filter', ','.join(missing)])
+
+ # Bug 1171232: The |android| tool behaviour has changed; we no longer can
+ # see what packages are installed easily. Don't check until we find a way
+ # to actually verify.
+ failing = []
+ if failing:
+ raise Exception(MISSING_ANDROID_PACKAGES % (', '.join(missing), ', '.join(failing)))
+
+
+def suggest_mozconfig(sdk_path=None, ndk_path=None, artifact_mode=False):
+ if artifact_mode:
+ print(MOBILE_ANDROID_ARTIFACT_MODE_MOZCONFIG_TEMPLATE % (sdk_path))
+ else:
+ print(MOBILE_ANDROID_MOZCONFIG_TEMPLATE % (sdk_path, ndk_path))
+
+
+def android_ndk_url(os_name, ver='r11b'):
+ # Produce a URL like 'https://dl.google.com/android/repository/android-ndk-r11b-linux-x86_64.zip
+ base_url = 'https://dl.google.com/android/repository/android-ndk'
+
+ if sys.maxsize > 2**32:
+ arch = 'x86_64'
+ else:
+ arch = 'x86'
+
+ return '%s-%s-%s-%s.zip' % (base_url, ver, os_name, arch)
diff --git a/python/mozboot/mozboot/archlinux.py b/python/mozboot/mozboot/archlinux.py
new file mode 100644
index 000000000..12ce6b4a4
--- /dev/null
+++ b/python/mozboot/mozboot/archlinux.py
@@ -0,0 +1,223 @@
+# 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/.
+
+import os
+import sys
+import tempfile
+import subprocess
+import glob
+
+from mozboot.base import BaseBootstrapper
+
+
+class ArchlinuxBootstrapper(BaseBootstrapper):
+ '''Archlinux experimental bootstrapper.'''
+
+ SYSTEM_PACKAGES = [
+ 'autoconf2.13',
+ 'base-devel',
+ 'ccache',
+ 'mercurial',
+ 'python2',
+ 'python2-setuptools',
+ 'unzip',
+ 'zip',
+ ]
+
+ BROWSER_PACKAGES = [
+ 'alsa-lib',
+ 'dbus-glib',
+ 'desktop-file-utils',
+ 'gconf',
+ 'gtk2',
+ 'gtk3',
+ 'hicolor-icon-theme',
+ 'hunspell',
+ 'icu',
+ 'libevent',
+ 'libvpx',
+ 'libxt',
+ 'mime-types',
+ 'mozilla-common',
+ 'nss',
+ 'sqlite',
+ 'startup-notification',
+ 'diffutils',
+ 'gst-plugins-base-libs',
+ 'imake',
+ 'inetutils',
+ 'libpulse',
+ 'mercurial',
+ 'mesa',
+ 'python2',
+ 'unzip',
+ 'xorg-server-xvfb',
+ 'yasm',
+ 'zip',
+ 'gst-libav',
+ 'gst-plugins-good',
+ 'networkmanager',
+ ]
+
+ BROWSER_AUR_PACKAGES = [
+ 'https://aur.archlinux.org/cgit/aur.git/snapshot/uuid.tar.gz',
+ ]
+
+ MOBILE_ANDROID_COMMON_PACKAGES = [
+ 'zlib', # mobile/android requires system zlib.
+ 'jdk7-openjdk', # It would be nice to handle alternative JDKs. See https://wiki.archlinux.org/index.php/Java.
+ 'wget', # For downloading the Android SDK and NDK.
+ 'multilib/lib32-libstdc++5', # See comment about 32 bit binaries and multilib below.
+ 'multilib/lib32-ncurses',
+ 'multilib/lib32-readline',
+ 'multilib/lib32-zlib',
+ ]
+
+ def __init__(self, version, dist_id, **kwargs):
+ print 'Using an experimental bootstrapper for Archlinux.'
+ BaseBootstrapper.__init__(self, **kwargs)
+
+ def install_system_packages(self):
+ self.pacman_install(*self.SYSTEM_PACKAGES)
+
+ def install_browser_packages(self):
+ self.ensure_browser_packages()
+
+ def install_browser_artifact_mode_packages(self):
+ self.ensure_browser_packages(artifact_mode=True)
+
+ def install_mobile_android_packages(self):
+ self.ensure_mobile_android_packages()
+
+ def install_mobile_android_artifact_mode_packages(self):
+ self.ensure_mobile_android_packages(artifact_mode=True)
+
+ def ensure_browser_packages(self, artifact_mode=False):
+ # TODO: Figure out what not to install for artifact mode
+ self.aur_install(*self.BROWSER_AUR_PACKAGES)
+ self.pacman_install(*self.BROWSER_PACKAGES)
+
+ def ensure_mobile_android_packages(self, artifact_mode=False):
+ import android
+
+ # Multi-part process:
+ # 1. System packages.
+ # 2. Android SDK. Android NDK only if we are not in artifact mode.
+ # 3. Android packages.
+
+ # 1. This is hard to believe, but the Android SDK binaries are 32-bit
+ # and that conflicts with 64-bit Arch installations out of the box. The
+ # solution is to add the multilibs repository; unfortunately, this
+ # requires manual intervention.
+ try:
+ self.pacman_install(*self.MOBILE_ANDROID_COMMON_PACKAGES)
+ except e:
+ print('Failed to install all packages. The Android developer '
+ 'toolchain requires 32 bit binaries be enabled (see '
+ 'https://wiki.archlinux.org/index.php/Android). You may need to '
+ 'manually enable the multilib repository following the instructions '
+ 'at https://wiki.archlinux.org/index.php/Multilib.')
+ raise e
+
+ # 2. The user may have an external Android SDK (in which case we save
+ # them a lengthy download), or they may have already completed the
+ # download. We unpack to ~/.mozbuild/{android-sdk-linux, android-ndk-r11b}.
+ mozbuild_path = os.environ.get('MOZBUILD_STATE_PATH', os.path.expanduser(os.path.join('~', '.mozbuild')))
+ self.sdk_path = os.environ.get('ANDROID_SDK_HOME', os.path.join(mozbuild_path, 'android-sdk-linux'))
+ self.ndk_path = os.environ.get('ANDROID_NDK_HOME', os.path.join(mozbuild_path, 'android-ndk-r11b'))
+ self.sdk_url = 'https://dl.google.com/android/android-sdk_r24.0.1-linux.tgz'
+ self.ndk_url = android.android_ndk_url('linux')
+
+ android.ensure_android_sdk_and_ndk(path=mozbuild_path,
+ sdk_path=self.sdk_path, sdk_url=self.sdk_url,
+ ndk_path=self.ndk_path, ndk_url=self.ndk_url,
+ artifact_mode=artifact_mode)
+ android_tool = os.path.join(self.sdk_path, 'tools', 'android')
+ android.ensure_android_packages(android_tool=android_tool)
+
+ def suggest_mobile_android_mozconfig(self, artifact_mode=False):
+ import android
+ android.suggest_mozconfig(sdk_path=self.sdk_path,
+ ndk_path=self.ndk_path,
+ artifact_mode=artifact_mode)
+
+ def suggest_mobile_android_artifact_mode_mozconfig(self):
+ self.suggest_mobile_android_mozconfig(artifact_mode=True)
+
+ def _update_package_manager(self):
+ self.pacman_update
+
+ def upgrade_mercurial(self, current):
+ self.pacman_install('mercurial')
+
+ def upgrade_python(self, current):
+ self.pacman_install('python2')
+
+ def pacman_install(self, *packages):
+ command = ['pacman', '-S', '--needed']
+ if self.no_interactive:
+ command.append('--noconfirm')
+
+ command.extend(packages)
+
+ self.run_as_root(command)
+
+ def pacman_update(self):
+ command = ['pacman', '-S', '--refresh']
+
+ self.run_as_root(command)
+
+ def run(self, command, env=None):
+ subprocess.check_call(command, stdin=sys.stdin, env=env)
+
+ def download(self, uri):
+ command = ['curl', '-L', '-O', uri]
+ self.run(command)
+
+ def unpack(self, path, name, ext):
+ if ext == 'gz':
+ compression = '-z'
+ elif ext == 'bz':
+ compression == '-j'
+ elif exit == 'xz':
+ compression == 'x'
+
+ name = os.path.join(path, name) + '.tar.' + ext
+ command = ['tar', '-x', compression, '-f', name, '-C', path]
+ self.run(command)
+
+ def makepkg(self, name):
+ command = ['makepkg', '-s']
+ makepkg_env = os.environ.copy()
+ makepkg_env['PKGEXT'] = '.pkg.tar.xz'
+ self.run(command, env=makepkg_env)
+ pack = glob.glob(name + '*.pkg.tar.xz')[0]
+ command = ['pacman', '-U']
+ if self.no_interactive:
+ command.append('--noconfirm')
+ command.append(pack)
+ self.run_as_root(command)
+
+ def aur_install(self, *packages):
+ path = tempfile.mkdtemp()
+ if not self.no_interactive:
+ print('WARNING! This script requires to install packages from the AUR '
+ 'This is potentially unsecure so I recommend that you carefully '
+ 'read each package description and check the sources.'
+ 'These packages will be built in ' + path + '.')
+ choice = raw_input('Do you want to continue? (yes/no) [no]')
+ if choice != 'yes':
+ sys.exit(1)
+
+ base_dir = os.getcwd()
+ os.chdir(path)
+ for package in packages:
+ name, _, ext = package.split('/')[-1].split('.')
+ directory = os.path.join(path, name)
+ self.download(package)
+ self.unpack(path, name, ext)
+ os.chdir(directory)
+ self.makepkg(name)
+
+ os.chdir(base_dir)
diff --git a/python/mozboot/mozboot/base.py b/python/mozboot/mozboot/base.py
new file mode 100644
index 000000000..0e1871da9
--- /dev/null
+++ b/python/mozboot/mozboot/base.py
@@ -0,0 +1,452 @@
+# 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/.
+
+from __future__ import print_function, unicode_literals
+
+import hashlib
+import os
+import re
+import subprocess
+import sys
+import urllib2
+
+from distutils.version import LooseVersion
+
+
+NO_MERCURIAL = '''
+Could not find Mercurial (hg) in the current shell's path. Try starting a new
+shell and running the bootstrapper again.
+'''
+
+MERCURIAL_UNABLE_UPGRADE = '''
+You are currently running Mercurial %s. Running %s or newer is
+recommended for performance and stability reasons.
+
+Unfortunately, this bootstrapper currently does not know how to automatically
+upgrade Mercurial on your machine.
+
+You can usually install Mercurial through your package manager or by
+downloading a package from http://mercurial.selenic.com/.
+'''
+
+MERCURIAL_UPGRADE_FAILED = '''
+We attempted to upgrade Mercurial to a modern version (%s or newer).
+However, you appear to have version %s still.
+
+It's possible your package manager doesn't support a modern version of
+Mercurial. It's also possible Mercurial is not being installed in the search
+path for this shell. Try creating a new shell and run this bootstrapper again.
+
+If it continues to fail, consider installing Mercurial by following the
+instructions at http://mercurial.selenic.com/.
+'''
+
+PYTHON_UNABLE_UPGRADE = '''
+You are currently running Python %s. Running %s or newer (but
+not 3.x) is required.
+
+Unfortunately, this bootstrapper does not currently know how to automatically
+upgrade Python on your machine.
+
+Please search the Internet for how to upgrade your Python and try running this
+bootstrapper again to ensure your machine is up to date.
+'''
+
+PYTHON_UPGRADE_FAILED = '''
+We attempted to upgrade Python to a modern version (%s or newer).
+However, you appear to still have version %s.
+
+It's possible your package manager doesn't yet expose a modern version of
+Python. It's also possible Python is not being installed in the search path for
+this shell. Try creating a new shell and run this bootstrapper again.
+
+If this continues to fail and you are sure you have a modern Python on your
+system, ensure it is on the $PATH and try again. If that fails, you'll need to
+install Python manually and ensure the path with the python binary is listed in
+the $PATH environment variable.
+
+We recommend the following tools for installing Python:
+
+ pyenv -- https://github.com/yyuu/pyenv)
+ pythonz -- https://github.com/saghul/pythonz
+ official installers -- http://www.python.org/
+'''
+
+BROWSER_ARTIFACT_MODE_MOZCONFIG = '''
+Paste the lines between the chevrons (>>> and <<<) into your mozconfig file:
+
+<<<
+# Automatically download and use compiled C++ components:
+ac_add_options --enable-artifact-builds
+>>>
+'''
+
+# Upgrade Mercurial older than this.
+# This should match OLDEST_NON_LEGACY_VERSION from
+# the hg setup wizard in version-control-tools.
+MODERN_MERCURIAL_VERSION = LooseVersion('3.7.3')
+
+# Upgrade Python older than this.
+MODERN_PYTHON_VERSION = LooseVersion('2.7.3')
+
+
+class BaseBootstrapper(object):
+ """Base class for system bootstrappers."""
+
+ def __init__(self, no_interactive=False):
+ self.package_manager_updated = False
+ self.no_interactive = no_interactive
+
+ def install_system_packages(self):
+ '''
+ Install packages shared by all applications. These are usually
+ packages required by the development (like mercurial) or the
+ build system (like autoconf).
+ '''
+ raise NotImplementedError('%s must implement install_system_packages()' %
+ __name__)
+
+ def install_browser_packages(self):
+ '''
+ Install packages required to build Firefox for Desktop (application
+ 'browser').
+ '''
+ raise NotImplementedError('Cannot bootstrap Firefox for Desktop: '
+ '%s does not yet implement install_browser_packages()' %
+ __name__)
+
+ def suggest_browser_mozconfig(self):
+ '''
+ Print a message to the console detailing what the user's mozconfig
+ should contain.
+
+ Firefox for Desktop can in simple cases determine its build environment
+ entirely from configure.
+ '''
+ pass
+
+ def install_browser_artifact_mode_packages(self):
+ '''
+ Install packages required to build Firefox for Desktop (application
+ 'browser') in Artifact Mode.
+ '''
+ raise NotImplementedError(
+ 'Cannot bootstrap Firefox for Desktop Artifact Mode: '
+ '%s does not yet implement install_browser_artifact_mode_packages()' %
+ __name__)
+
+ def suggest_browser_artifact_mode_mozconfig(self):
+ '''
+ Print a message to the console detailing what the user's mozconfig
+ should contain.
+
+ Firefox for Desktop Artifact Mode needs to enable artifact builds and
+ a path where the build artifacts will be written to.
+ '''
+ print(BROWSER_ARTIFACT_MODE_MOZCONFIG)
+
+ def install_mobile_android_packages(self):
+ '''
+ Install packages required to build Firefox for Android (application
+ 'mobile/android', also known as Fennec).
+ '''
+ raise NotImplementedError('Cannot bootstrap Firefox for Android: '
+ '%s does not yet implement install_mobile_android_packages()'
+ % __name__)
+
+ def suggest_mobile_android_mozconfig(self):
+ '''
+ Print a message to the console detailing what the user's mozconfig
+ should contain.
+
+ Firefox for Android needs an application and an ABI set, and it needs
+ paths to the Android SDK and NDK.
+ '''
+ raise NotImplementedError('%s does not yet implement suggest_mobile_android_mozconfig()' %
+ __name__)
+
+ def install_mobile_android_artifact_mode_packages(self):
+ '''
+ Install packages required to build Firefox for Android (application
+ 'mobile/android', also known as Fennec) in Artifact Mode.
+ '''
+ raise NotImplementedError(
+ 'Cannot bootstrap Firefox for Android Artifact Mode: '
+ '%s does not yet implement install_mobile_android_artifact_mode_packages()'
+ % __name__)
+
+ def suggest_mobile_android_artifact_mode_mozconfig(self):
+ '''
+ Print a message to the console detailing what the user's mozconfig
+ should contain.
+
+ Firefox for Android Artifact Mode needs an application and an ABI set,
+ and it needs paths to the Android SDK.
+ '''
+ raise NotImplementedError(
+ '%s does not yet implement suggest_mobile_android_artifact_mode_mozconfig()'
+ % __name__)
+
+ def which(self, name):
+ """Python implementation of which.
+
+ It returns the path of an executable or None if it couldn't be found.
+ """
+ for path in os.environ['PATH'].split(os.pathsep):
+ test = os.path.join(path, name)
+ if os.path.exists(test) and os.access(test, os.X_OK):
+ return test
+
+ return None
+
+ def run_as_root(self, command):
+ if os.geteuid() != 0:
+ if self.which('sudo'):
+ command.insert(0, 'sudo')
+ else:
+ command = ['su', 'root', '-c', ' '.join(command)]
+
+ print('Executing as root:', subprocess.list2cmdline(command))
+
+ subprocess.check_call(command, stdin=sys.stdin)
+
+ def dnf_install(self, *packages):
+ if self.which('dnf'):
+ command = ['dnf', 'install']
+ else:
+ command = ['yum', 'install']
+
+ if self.no_interactive:
+ command.append('-y')
+ command.extend(packages)
+
+ self.run_as_root(command)
+
+ def dnf_groupinstall(self, *packages):
+ if self.which('dnf'):
+ command = ['dnf', 'groupinstall']
+ else:
+ command = ['yum', 'groupinstall']
+
+ if self.no_interactive:
+ command.append('-y')
+ command.extend(packages)
+
+ self.run_as_root(command)
+
+ def dnf_update(self, *packages):
+ if self.which('dnf'):
+ command = ['dnf', 'update']
+ else:
+ command = ['yum', 'update']
+
+ if self.no_interactive:
+ command.append('-y')
+ command.extend(packages)
+
+ self.run_as_root(command)
+
+ def apt_install(self, *packages):
+ command = ['apt-get', 'install']
+ if self.no_interactive:
+ command.append('-y')
+ command.extend(packages)
+
+ self.run_as_root(command)
+
+ def apt_update(self):
+ command = ['apt-get', 'update']
+ if self.no_interactive:
+ command.append('-y')
+
+ self.run_as_root(command)
+
+ def apt_add_architecture(self, arch):
+ command = ['dpkg', '--add-architecture']
+ command.extend(arch)
+
+ self.run_as_root(command)
+
+ def check_output(self, *args, **kwargs):
+ """Run subprocess.check_output even if Python doesn't provide it."""
+ fn = getattr(subprocess, 'check_output', BaseBootstrapper._check_output)
+
+ return fn(*args, **kwargs)
+
+ @staticmethod
+ def _check_output(*args, **kwargs):
+ """Python 2.6 compatible implementation of subprocess.check_output."""
+ proc = subprocess.Popen(stdout=subprocess.PIPE, *args, **kwargs)
+ output, unused_err = proc.communicate()
+ retcode = proc.poll()
+ if retcode:
+ cmd = kwargs.get('args', args[0])
+ e = subprocess.CalledProcessError(retcode, cmd)
+ e.output = output
+ raise e
+
+ return output
+
+ def prompt_int(self, prompt, low, high, limit=5):
+ ''' Prompts the user with prompt and requires an integer between low and high. '''
+ valid = False
+ while not valid and limit > 0:
+ try:
+ choice = int(raw_input(prompt))
+ if not low <= choice <= high:
+ print("ERROR! Please enter a valid option!")
+ limit -= 1
+ else:
+ valid = True
+ except ValueError:
+ print("ERROR! Please enter a valid option!")
+ limit -= 1
+
+ if limit > 0:
+ return choice
+ else:
+ raise Exception("Error! Reached max attempts of entering option.")
+
+ def _ensure_package_manager_updated(self):
+ if self.package_manager_updated:
+ return
+
+ self._update_package_manager()
+ self.package_manager_updated = True
+
+ def _update_package_manager(self):
+ """Updates the package manager's manifests/package list.
+
+ This should be defined in child classes.
+ """
+
+ def _hgplain_env(self):
+ """ Returns a copy of the current environment updated with the HGPLAIN
+ environment variable.
+
+ HGPLAIN prevents Mercurial from applying locale variations to the output
+ making it suitable for use in scripts.
+ """
+ env = os.environ.copy()
+ env[b'HGPLAIN'] = b'1'
+
+ return env
+
+ def is_mercurial_modern(self):
+ hg = self.which('hg')
+ if not hg:
+ print(NO_MERCURIAL)
+ return False, False, None
+
+ info = self.check_output([hg, '--version'], env=self._hgplain_env()).splitlines()[0]
+
+ match = re.search('version ([^\+\)]+)', info)
+ if not match:
+ print('ERROR: Unable to identify Mercurial version.')
+ return True, False, None
+
+ our = LooseVersion(match.group(1))
+
+ return True, our >= MODERN_MERCURIAL_VERSION, our
+
+ def ensure_mercurial_modern(self):
+ installed, modern, version = self.is_mercurial_modern()
+
+ if modern:
+ print('Your version of Mercurial (%s) is sufficiently modern.' %
+ version)
+ return installed, modern
+
+ self._ensure_package_manager_updated()
+
+ if installed:
+ print('Your version of Mercurial (%s) is not modern enough.' %
+ version)
+ print('(Older versions of Mercurial have known security vulnerabilities. '
+ 'Unless you are running a patched Mercurial version, you may be '
+ 'vulnerable.')
+ else:
+ print('You do not have Mercurial installed')
+
+ if self.upgrade_mercurial(version) is False:
+ return installed, modern
+
+ installed, modern, after = self.is_mercurial_modern()
+
+ if installed and not modern:
+ print(MERCURIAL_UPGRADE_FAILED % (MODERN_MERCURIAL_VERSION, after))
+
+ return installed, modern
+
+ def upgrade_mercurial(self, current):
+ """Upgrade Mercurial.
+
+ Child classes should reimplement this.
+
+ Return False to not perform a version check after the upgrade is
+ performed.
+ """
+ print(MERCURIAL_UNABLE_UPGRADE % (current, MODERN_MERCURIAL_VERSION))
+
+ def is_python_modern(self):
+ python = None
+
+ for test in ['python2.7', 'python']:
+ python = self.which(test)
+ if python:
+ break
+
+ assert python
+
+ info = self.check_output([python, '--version'],
+ stderr=subprocess.STDOUT)
+ match = re.search('Python ([a-z0-9\.]+)', info)
+ if not match:
+ print('ERROR Unable to identify Python version.')
+ return False, None
+
+ our = LooseVersion(match.group(1))
+
+ return our >= MODERN_PYTHON_VERSION, our
+
+ def ensure_python_modern(self):
+ modern, version = self.is_python_modern()
+
+ if modern:
+ print('Your version of Python (%s) is new enough.' % version)
+ return
+
+ print('Your version of Python (%s) is too old. Will try to upgrade.' %
+ version)
+
+ self._ensure_package_manager_updated()
+ self.upgrade_python(version)
+
+ modern, after = self.is_python_modern()
+
+ if not modern:
+ print(PYTHON_UPGRADE_FAILED % (MODERN_PYTHON_VERSION, after))
+ sys.exit(1)
+
+ def upgrade_python(self, current):
+ """Upgrade Python.
+
+ Child classes should reimplement this.
+ """
+ print(PYTHON_UNABLE_UPGRADE % (current, MODERN_PYTHON_VERSION))
+
+ def http_download_and_save(self, url, dest, sha256hexhash):
+ f = urllib2.urlopen(url)
+ h = hashlib.sha256()
+ with open(dest, 'wb') as out:
+ while True:
+ data = f.read(4096)
+ if data:
+ out.write(data)
+ h.update(data)
+ else:
+ break
+ if h.hexdigest() != sha256hexhash:
+ os.remove(dest)
+ raise ValueError('Hash of downloaded file does not match expected hash')
diff --git a/python/mozboot/mozboot/bootstrap.py b/python/mozboot/mozboot/bootstrap.py
new file mode 100644
index 000000000..40bb7cc86
--- /dev/null
+++ b/python/mozboot/mozboot/bootstrap.py
@@ -0,0 +1,437 @@
+# 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/.
+
+# If we add unicode_literals, Python 2.6.1 (required for OS X 10.6) breaks.
+from __future__ import print_function
+
+import platform
+import sys
+import os
+import subprocess
+
+# Don't forgot to add new mozboot modules to the bootstrap download
+# list in bin/bootstrap.py!
+from mozboot.centosfedora import CentOSFedoraBootstrapper
+from mozboot.debian import DebianBootstrapper
+from mozboot.freebsd import FreeBSDBootstrapper
+from mozboot.gentoo import GentooBootstrapper
+from mozboot.osx import OSXBootstrapper
+from mozboot.openbsd import OpenBSDBootstrapper
+from mozboot.archlinux import ArchlinuxBootstrapper
+from mozboot.windows import WindowsBootstrapper
+from mozboot.mozillabuild import MozillaBuildBootstrapper
+from mozboot.util import (
+ get_state_dir,
+)
+
+APPLICATION_CHOICE = '''
+Please choose the version of Firefox you want to build:
+%s
+
+Note on Artifact Mode:
+
+Firefox for Desktop and Android supports a fast build mode called
+artifact mode. Artifact mode downloads pre-built C++ components rather
+than building them locally, trading bandwidth for time.
+
+Artifact builds will be useful to many developers who are not working
+with compiled code. If you want to work on look-and-feel of Firefox,
+you want "Firefox for Desktop Artifact Mode".
+
+Similarly, if you want to work on the look-and-feel of Firefox for Android,
+you want "Firefox for Android Artifact Mode".
+
+To work on the Gecko technology platform, you would need to opt to full,
+non-artifact mode. Gecko is Mozilla's web rendering engine, similar to Edge,
+Blink, and WebKit. Gecko is implemented in C++ and JavaScript. If you
+want to work on web rendering, you want "Firefox for Desktop", or
+"Firefox for Android".
+
+If you don't know what you want, start with just Artifact Mode of the desired
+platform. Your builds will be much shorter than if you build Gecko as well.
+But don't worry! You can always switch configurations later.
+
+You can learn more about Artifact mode builds at
+https://developer.mozilla.org/en-US/docs/Artifact_builds.
+
+Your choice:
+'''
+
+APPLICATIONS_LIST=[
+ ('Firefox for Desktop Artifact Mode', 'browser_artifact_mode'),
+ ('Firefox for Desktop', 'browser'),
+ ('Firefox for Android Artifact Mode', 'mobile_android_artifact_mode'),
+ ('Firefox for Android', 'mobile_android'),
+]
+
+# This is a workaround for the fact that we must support python2.6 (which has
+# no OrderedDict)
+APPLICATIONS = dict(
+ browser_artifact_mode=APPLICATIONS_LIST[0],
+ browser=APPLICATIONS_LIST[1],
+ mobile_android_artifact_mode=APPLICATIONS_LIST[2],
+ mobile_android=APPLICATIONS_LIST[3],
+)
+
+STATE_DIR_INFO = '''
+The Firefox build system and related tools store shared, persistent state
+in a common directory on the filesystem. On this machine, that directory
+is:
+
+ {statedir}
+
+If you would like to use a different directory, hit CTRL+c and set the
+MOZBUILD_STATE_PATH environment variable to the directory you'd like to
+use and re-run the bootstrapper.
+
+Would you like to create this directory?
+
+ 1. Yes
+ 2. No
+
+Your choice:
+'''
+
+FINISHED = '''
+Your system should be ready to build %s!
+'''
+
+SOURCE_ADVERTISE = '''
+Source code can be obtained by running
+
+ hg clone https://hg.mozilla.org/mozilla-unified
+
+Or, if you prefer Git, you should install git-cinnabar, and follow the
+instruction here to clone from the Mercurial repository:
+
+ https://github.com/glandium/git-cinnabar/wiki/Mozilla:-A-git-workflow-for-Gecko-development
+
+Or, if you really prefer vanilla flavor Git:
+
+ git clone https://git.mozilla.org/integration/gecko-dev.git
+'''
+
+CONFIGURE_MERCURIAL = '''
+Mozilla recommends a number of changes to Mercurial to enhance your
+experience with it.
+
+Would you like to run a configuration wizard to ensure Mercurial is
+optimally configured?
+
+ 1. Yes
+ 2. No
+
+Please enter your reply: '''.lstrip()
+
+CLONE_MERCURIAL = '''
+If you would like to clone the canonical Mercurial repository, please
+enter the destination path below.
+
+(If you prefer to use Git, leave this blank.)
+
+Destination directory for Mercurial clone (leave empty to not clone): '''.lstrip()
+
+
+DEBIAN_DISTROS = (
+ 'Debian',
+ 'debian',
+ 'Ubuntu',
+ # Most Linux Mint editions are based on Ubuntu. One is based on Debian.
+ # The difference is reported in dist_id from platform.linux_distribution.
+ # But it doesn't matter since we share a bootstrapper between Debian and
+ # Ubuntu.
+ 'Mint',
+ 'LinuxMint',
+ 'Elementary OS',
+ 'Elementary',
+ '"elementary OS"',
+)
+
+
+class Bootstrapper(object):
+ """Main class that performs system bootstrap."""
+
+ def __init__(self, finished=FINISHED, choice=None, no_interactive=False,
+ hg_configure=False):
+ self.instance = None
+ self.finished = finished
+ self.choice = choice
+ self.hg_configure = hg_configure
+ cls = None
+ args = {'no_interactive': no_interactive}
+
+ if sys.platform.startswith('linux'):
+ distro, version, dist_id = platform.linux_distribution()
+
+ if distro in ('CentOS', 'CentOS Linux', 'Fedora'):
+ cls = CentOSFedoraBootstrapper
+ args['distro'] = distro
+ elif distro in DEBIAN_DISTROS:
+ cls = DebianBootstrapper
+ elif distro == 'Gentoo Base System':
+ cls = GentooBootstrapper
+ elif os.path.exists('/etc/arch-release'):
+ # Even on archlinux, platform.linux_distribution() returns ['','','']
+ cls = ArchlinuxBootstrapper
+ else:
+ raise NotImplementedError('Bootstrap support for this Linux '
+ 'distro not yet available.')
+
+ args['version'] = version
+ args['dist_id'] = dist_id
+
+ elif sys.platform.startswith('darwin'):
+ # TODO Support Darwin platforms that aren't OS X.
+ osx_version = platform.mac_ver()[0]
+
+ cls = OSXBootstrapper
+ args['version'] = osx_version
+
+ elif sys.platform.startswith('openbsd'):
+ cls = OpenBSDBootstrapper
+ args['version'] = platform.uname()[2]
+
+ elif sys.platform.startswith('dragonfly') or \
+ sys.platform.startswith('freebsd'):
+ cls = FreeBSDBootstrapper
+ args['version'] = platform.release()
+ args['flavor'] = platform.system()
+
+ elif sys.platform.startswith('win32') or sys.platform.startswith('msys'):
+ if 'MOZILLABUILD' in os.environ:
+ cls = MozillaBuildBootstrapper
+ else:
+ cls = WindowsBootstrapper
+
+ if cls is None:
+ raise NotImplementedError('Bootstrap support is not yet available '
+ 'for your OS.')
+
+ self.instance = cls(**args)
+
+ def bootstrap(self):
+ if self.choice is None:
+ # Like ['1. Firefox for Desktop', '2. Firefox for Android Artifact Mode', ...].
+ labels = ['%s. %s' % (i + 1, name) for (i, (name, _)) in enumerate(APPLICATIONS_LIST)]
+ prompt = APPLICATION_CHOICE % '\n'.join(labels)
+ prompt_choice = self.instance.prompt_int(prompt=prompt, low=1, high=len(APPLICATIONS))
+ name, application = APPLICATIONS_LIST[prompt_choice-1]
+ elif self.choice not in APPLICATIONS.keys():
+ raise Exception('Please pick a valid application choice: (%s)' % '/'.join(APPLICATIONS.keys()))
+ else:
+ name, application = APPLICATIONS[self.choice]
+
+ self.instance.install_system_packages()
+
+ # Like 'install_browser_packages' or 'install_mobile_android_packages'.
+ getattr(self.instance, 'install_%s_packages' % application)()
+
+ hg_installed, hg_modern = self.instance.ensure_mercurial_modern()
+ self.instance.ensure_python_modern()
+
+ # The state directory code is largely duplicated from mach_bootstrap.py.
+ # We can't easily import mach_bootstrap.py because the bootstrapper may
+ # run in self-contained mode and only the files in this directory will
+ # be available. We /could/ refactor parts of mach_bootstrap.py to be
+ # part of this directory to avoid the code duplication.
+ state_dir, _ = get_state_dir()
+
+ if not os.path.exists(state_dir):
+ if not self.instance.no_interactive:
+ choice = self.instance.prompt_int(
+ prompt=STATE_DIR_INFO.format(statedir=state_dir),
+ low=1,
+ high=2)
+
+ if choice == 1:
+ print('Creating global state directory: %s' % state_dir)
+ os.makedirs(state_dir, mode=0o770)
+
+ state_dir_available = os.path.exists(state_dir)
+
+ # Possibly configure Mercurial if the user wants to.
+ # TODO offer to configure Git.
+ if hg_installed and state_dir_available:
+ configure_hg = False
+ if not self.instance.no_interactive:
+ choice = self.instance.prompt_int(prompt=CONFIGURE_MERCURIAL,
+ low=1, high=2)
+ if choice == 1:
+ configure_hg = True
+ else:
+ configure_hg = self.hg_configure
+
+ if configure_hg:
+ configure_mercurial(self.instance.which('hg'), state_dir)
+
+ # Offer to clone if we're not inside a clone.
+ checkout_type = current_firefox_checkout(check_output=self.instance.check_output,
+ hg=self.instance.which('hg'))
+ have_clone = False
+
+ if checkout_type:
+ have_clone = True
+ elif hg_installed and not self.instance.no_interactive:
+ dest = raw_input(CLONE_MERCURIAL)
+ dest = dest.strip()
+ if dest:
+ dest = os.path.expanduser(dest)
+ have_clone = clone_firefox(self.instance.which('hg'), dest)
+
+ if not have_clone:
+ print(SOURCE_ADVERTISE)
+
+ print(self.finished % name)
+
+ # Like 'suggest_browser_mozconfig' or 'suggest_mobile_android_mozconfig'.
+ getattr(self.instance, 'suggest_%s_mozconfig' % application)()
+
+
+def update_vct(hg, root_state_dir):
+ """Ensure version-control-tools in the state directory is up to date."""
+ vct_dir = os.path.join(root_state_dir, 'version-control-tools')
+
+ # Ensure the latest revision of version-control-tools is present.
+ update_mercurial_repo(hg, 'https://hg.mozilla.org/hgcustom/version-control-tools',
+ vct_dir, '@')
+
+ return vct_dir
+
+
+def configure_mercurial(hg, root_state_dir):
+ """Run the Mercurial configuration wizard."""
+ vct_dir = update_vct(hg, root_state_dir)
+
+ # Run the config wizard from v-c-t.
+ args = [
+ hg,
+ '--config', 'extensions.configwizard=%s/hgext/configwizard' % vct_dir,
+ 'configwizard',
+ ]
+ subprocess.call(args)
+
+
+def update_mercurial_repo(hg, url, dest, revision):
+ """Perform a clone/pull + update of a Mercurial repository."""
+ args = [hg]
+
+ # Disable common extensions whose older versions may cause `hg`
+ # invocations to abort.
+ disable_exts = [
+ 'bzexport',
+ 'bzpost',
+ 'firefoxtree',
+ 'hgwatchman',
+ 'mozext',
+ 'mqext',
+ 'qimportbz',
+ 'push-to-try',
+ 'reviewboard',
+ ]
+ for ext in disable_exts:
+ args.extend(['--config', 'extensions.%s=!' % ext])
+
+ if os.path.exists(dest):
+ args.extend(['pull', url])
+ cwd = dest
+ else:
+ args.extend(['clone', '--noupdate', url, dest])
+ cwd = '/'
+
+ print('=' * 80)
+ print('Ensuring %s is up to date at %s' % (url, dest))
+
+ try:
+ subprocess.check_call(args, cwd=cwd)
+ subprocess.check_call([hg, 'update', '-r', revision], cwd=dest)
+ finally:
+ print('=' * 80)
+
+
+def clone_firefox(hg, dest):
+ """Clone the Firefox repository to a specified destination."""
+ print('Cloning Firefox Mercurial repository to %s' % dest)
+
+ # We create an empty repo then modify the config before adding data.
+ # This is necessary to ensure storage settings are optimally
+ # configured.
+ args = [
+ hg,
+ # The unified repo is generaldelta, so ensure the client is as
+ # well.
+ '--config', 'format.generaldelta=true',
+ 'init',
+ dest
+ ]
+ res = subprocess.call(args)
+ if res:
+ print('unable to create destination repo; please try cloning manually')
+ return False
+
+ # Strictly speaking, this could overwrite a config based on a template
+ # the user has installed. Let's pretend this problem doesn't exist
+ # unless someone complains about it.
+ with open(os.path.join(dest, '.hg', 'hgrc'), 'ab') as fh:
+ fh.write('[paths]\n')
+ fh.write('default = https://hg.mozilla.org/mozilla-unified\n')
+ fh.write('\n')
+
+ # The server uses aggressivemergedeltas which can blow up delta chain
+ # length. This can cause performance to tank due to delta chains being
+ # too long. Limit the delta chain length to something reasonable
+ # to bound revlog read time.
+ fh.write('[format]\n')
+ fh.write('# This is necessary to keep performance in check\n')
+ fh.write('maxchainlen = 10000\n')
+
+ res = subprocess.call([hg, 'pull', 'https://hg.mozilla.org/mozilla-unified'], cwd=dest)
+ print('')
+ if res:
+ print('error pulling; try running `hg pull https://hg.mozilla.org/mozilla-unified` manually')
+ return False
+
+ print('updating to "central" - the development head of Gecko and Firefox')
+ res = subprocess.call([hg, 'update', '-r', 'central'], cwd=dest)
+ if res:
+ print('error updating; you will need to `hg update` manually')
+
+ print('Firefox source code available at %s' % dest)
+ return True
+
+
+def current_firefox_checkout(check_output, hg=None):
+ """Determine whether we're in a Firefox checkout.
+
+ Returns one of None, ``git``, or ``hg``.
+ """
+ HG_ROOT_REVISIONS = set([
+ # From mozilla-central.
+ '8ba995b74e18334ab3707f27e9eb8f4e37ba3d29',
+ ])
+
+ path = os.getcwd()
+ while path:
+ hg_dir = os.path.join(path, '.hg')
+ git_dir = os.path.join(path, '.git')
+ if hg and os.path.exists(hg_dir):
+ # Verify the hg repo is a Firefox repo by looking at rev 0.
+ try:
+ node = check_output([hg, 'log', '-r', '0', '--template', '{node}'], cwd=path)
+ if node in HG_ROOT_REVISIONS:
+ return 'hg'
+ # Else the root revision is different. There could be nested
+ # repos. So keep traversing the parents.
+ except subprocess.CalledProcessError:
+ pass
+
+ # TODO check git remotes or `git rev-parse -q --verify $sha1^{commit}`
+ # for signs of Firefox.
+ elif os.path.exists(git_dir):
+ return 'git'
+
+ path, child = os.path.split(path)
+ if child == '':
+ break
+
+ return None
diff --git a/python/mozboot/mozboot/centosfedora.py b/python/mozboot/mozboot/centosfedora.py
new file mode 100644
index 000000000..111e5eb90
--- /dev/null
+++ b/python/mozboot/mozboot/centosfedora.py
@@ -0,0 +1,153 @@
+# 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/.
+
+import os
+import platform
+
+from mozboot.base import BaseBootstrapper
+
+
+class CentOSFedoraBootstrapper(BaseBootstrapper):
+ def __init__(self, distro, version, dist_id, **kwargs):
+ BaseBootstrapper.__init__(self, **kwargs)
+
+ self.distro = distro
+ self.version = version
+ self.dist_id = dist_id
+
+ self.group_packages = []
+
+ self.packages = [
+ 'autoconf213',
+ 'mercurial',
+ ]
+
+ self.browser_group_packages = [
+ 'GNOME Software Development',
+ ]
+
+ self.browser_packages = [
+ 'alsa-lib-devel',
+ 'GConf2-devel',
+ 'glibc-static',
+ 'gtk2-devel', # It is optional in Fedora 20's GNOME Software
+ # Development group.
+ 'libstdc++-static',
+ 'libXt-devel',
+ 'mesa-libGL-devel',
+ 'pulseaudio-libs-devel',
+ 'wireless-tools-devel',
+ 'yasm',
+ ]
+
+ self.mobile_android_packages = []
+
+ if self.distro in ('CentOS', 'CentOS Linux'):
+ self.group_packages += [
+ 'Development Tools',
+ 'Development Libraries',
+ 'GNOME Software Development',
+ ]
+
+ self.packages += [
+ 'curl-devel',
+ ]
+
+ self.browser_packages += [
+ 'dbus-glib-devel',
+ 'gtk3-devel',
+ ]
+
+ elif self.distro == 'Fedora':
+ self.group_packages += [
+ 'C Development Tools and Libraries',
+ ]
+
+ self.packages += [
+ 'python2-devel',
+ ]
+
+ self.browser_packages += [
+ 'gcc-c++',
+ ]
+
+ self.mobile_android_packages += [
+ 'java-1.8.0-openjdk-devel',
+ 'ncurses-devel.i686',
+ 'libstdc++.i686',
+ 'zlib-devel.i686',
+ ]
+
+ def install_system_packages(self):
+ self.dnf_groupinstall(*self.group_packages)
+ self.dnf_install(*self.packages)
+
+ def install_browser_packages(self):
+ self.ensure_browser_packages()
+
+ def install_browser_artifact_mode_packages(self):
+ self.ensure_browser_packages(artifact_mode=True)
+
+ def install_mobile_android_packages(self):
+ if self.distro in ('CentOS', 'CentOS Linux'):
+ BaseBootstrapper.install_mobile_android_packages(self)
+ elif self.distro == 'Fedora':
+ self.install_fedora_mobile_android_packages()
+
+ def install_mobile_android_artifact_mode_packages(self):
+ if self.distro in ('CentOS', 'CentOS Linux'):
+ BaseBootstrapper.install_mobile_android_artifact_mode_packages(self)
+ elif self.distro == 'Fedora':
+ self.install_fedora_mobile_android_packages(artifact_mode=True)
+
+ def ensure_browser_packages(self, artifact_mode=False):
+ # TODO: Figure out what not to install for artifact mode
+ self.dnf_groupinstall(*self.browser_group_packages)
+ self.dnf_install(*self.browser_packages)
+
+ if self.distro in ('CentOS', 'CentOS Linux'):
+ yasm = 'http://pkgs.repoforge.org/yasm/yasm-1.1.0-1.el6.rf.i686.rpm'
+ if platform.architecture()[0] == '64bit':
+ yasm = 'http://pkgs.repoforge.org/yasm/yasm-1.1.0-1.el6.rf.x86_64.rpm'
+
+ self.run_as_root(['rpm', '-ivh', yasm])
+
+ def install_fedora_mobile_android_packages(self, artifact_mode=False):
+ import android
+
+ # Install Android specific packages.
+ self.dnf_install(*self.mobile_android_packages)
+
+ # Fetch Android SDK and NDK.
+ mozbuild_path = os.environ.get('MOZBUILD_STATE_PATH', os.path.expanduser(os.path.join('~', '.mozbuild')))
+ self.sdk_path = os.environ.get('ANDROID_SDK_HOME', os.path.join(mozbuild_path, 'android-sdk-linux'))
+ self.ndk_path = os.environ.get('ANDROID_NDK_HOME', os.path.join(mozbuild_path, 'android-ndk-r11b'))
+ self.sdk_url = 'https://dl.google.com/android/android-sdk_r24.0.1-linux.tgz'
+ self.ndk_url = android.android_ndk_url('linux')
+
+ android.ensure_android_sdk_and_ndk(path=mozbuild_path,
+ sdk_path=self.sdk_path, sdk_url=self.sdk_url,
+ ndk_path=self.ndk_path, ndk_url=self.ndk_url,
+ artifact_mode=artifact_mode)
+
+ # Most recent version of build-tools appears to be 23.0.1 on Fedora
+ packages = [p for p in android.ANDROID_PACKAGES if not p.startswith('build-tools')]
+ packages.append('build-tools-23.0.1')
+
+ # 3. We expect the |android| tool to be at
+ # ~/.mozbuild/android-sdk-linux/tools/android.
+ android_tool = os.path.join(self.sdk_path, 'tools', 'android')
+ android.ensure_android_packages(android_tool=android_tool, packages=packages)
+
+ def suggest_mobile_android_mozconfig(self, artifact_mode=False):
+ import android
+ android.suggest_mozconfig(sdk_path=self.sdk_path,
+ ndk_path=self.ndk_path,
+ artifact_mode=artifact_mode)
+
+ def suggest_mobile_android_artifact_mode_mozconfig(self):
+ self.suggest_mobile_android_mozconfig(artifact_mode=True)
+
+ def upgrade_mercurial(self, current):
+ self.dnf_update('mercurial')
diff --git a/python/mozboot/mozboot/debian.py b/python/mozboot/mozboot/debian.py
new file mode 100644
index 000000000..6e33e9e5b
--- /dev/null
+++ b/python/mozboot/mozboot/debian.py
@@ -0,0 +1,188 @@
+# 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/.
+
+import os
+import sys
+
+from mozboot.base import BaseBootstrapper
+
+
+MERCURIAL_INSTALL_PROMPT = '''
+Mercurial releases a new version every 3 months and your distro's package
+may become out of date. This may cause incompatibility with some
+Mercurial extensions that rely on new Mercurial features. As a result,
+you may not have an optimal version control experience.
+
+To have the best Mercurial experience possible, we recommend installing
+Mercurial via the "pip" Python packaging utility. This will likely result
+in files being placed in /usr/local/bin and /usr/local/lib.
+
+How would you like to continue?
+
+1) Install a modern Mercurial via pip (recommended)
+2) Install a legacy Mercurial via apt
+3) Do not install Mercurial
+
+Choice:
+'''.strip()
+
+
+class DebianBootstrapper(BaseBootstrapper):
+ # These are common packages for all Debian-derived distros (such as
+ # Ubuntu).
+ COMMON_PACKAGES = [
+ 'autoconf2.13',
+ 'build-essential',
+ 'ccache',
+ 'python-dev',
+ 'python-pip',
+ 'python-setuptools',
+ 'unzip',
+ 'uuid',
+ 'zip',
+ ]
+
+ # Subclasses can add packages to this variable to have them installed.
+ DISTRO_PACKAGES = []
+
+ # These are common packages for building Firefox for Desktop
+ # (browser) for all Debian-derived distros (such as Ubuntu).
+ BROWSER_COMMON_PACKAGES = [
+ 'libasound2-dev',
+ 'libcurl4-openssl-dev',
+ 'libdbus-1-dev',
+ 'libdbus-glib-1-dev',
+ 'libgconf2-dev',
+ 'libgtk-3-dev',
+ 'libgtk2.0-dev',
+ 'libiw-dev',
+ 'libnotify-dev',
+ 'libpulse-dev',
+ 'libx11-xcb-dev',
+ 'libxt-dev',
+ 'mesa-common-dev',
+ 'python-dbus',
+ 'xvfb',
+ 'yasm',
+ ]
+
+ # Subclasses can add packages to this variable to have them installed.
+ BROWSER_DISTRO_PACKAGES = []
+
+ # These are common packages for building Firefox for Android
+ # (mobile/android) for all Debian-derived distros (such as Ubuntu).
+ MOBILE_ANDROID_COMMON_PACKAGES = [
+ 'zlib1g-dev', # mobile/android requires system zlib.
+ 'openjdk-7-jdk',
+ 'wget', # For downloading the Android SDK and NDK.
+ 'libncurses5:i386', # See comments about i386 below.
+ 'libstdc++6:i386',
+ 'zlib1g:i386',
+ ]
+
+ # Subclasses can add packages to this variable to have them installed.
+ MOBILE_ANDROID_DISTRO_PACKAGES = []
+
+ def __init__(self, version, dist_id, **kwargs):
+ BaseBootstrapper.__init__(self, **kwargs)
+
+ self.version = version
+ self.dist_id = dist_id
+
+ self.packages = self.COMMON_PACKAGES + self.DISTRO_PACKAGES
+ self.browser_packages = self.BROWSER_COMMON_PACKAGES + self.BROWSER_DISTRO_PACKAGES
+ self.mobile_android_packages = self.MOBILE_ANDROID_COMMON_PACKAGES + self.MOBILE_ANDROID_DISTRO_PACKAGES
+
+
+ def install_system_packages(self):
+ self.apt_install(*self.packages)
+
+ def install_browser_packages(self):
+ self.ensure_browser_packages()
+
+ def install_browser_artifact_mode_packages(self):
+ self.ensure_browser_packages(artifact_mode=True)
+
+ def install_mobile_android_packages(self):
+ self.ensure_mobile_android_packages()
+
+ def install_mobile_android_artifact_mode_packages(self):
+ self.ensure_mobile_android_packages(artifact_mode=True)
+
+ def ensure_browser_packages(self, artifact_mode=False):
+ # TODO: Figure out what not to install for artifact mode
+ self.apt_install(*self.browser_packages)
+
+ def ensure_mobile_android_packages(self, artifact_mode=False):
+ import android
+
+ # Multi-part process:
+ # 1. System packages.
+ # 2. Android SDK. Android NDK only if we are not in artifact mode.
+ # 3. Android packages.
+
+ # 1. This is hard to believe, but the Android SDK binaries are 32-bit
+ # and that conflicts with 64-bit Debian and Ubuntu installations out of
+ # the box. The solution is to add the i386 architecture. See
+ # "Troubleshooting Ubuntu" at
+ # http://developer.android.com/sdk/installing/index.html?pkg=tools.
+ self.run_as_root(['dpkg', '--add-architecture', 'i386'])
+ # After adding a new arch, the list of packages has to be updated
+ self.apt_update()
+ self.apt_install(*self.mobile_android_packages)
+
+ # 2. The user may have an external Android SDK (in which case we save
+ # them a lengthy download), or they may have already completed the
+ # download. We unpack to ~/.mozbuild/{android-sdk-linux, android-ndk-r11b}.
+ mozbuild_path = os.environ.get('MOZBUILD_STATE_PATH', os.path.expanduser(os.path.join('~', '.mozbuild')))
+ self.sdk_path = os.environ.get('ANDROID_SDK_HOME', os.path.join(mozbuild_path, 'android-sdk-linux'))
+ self.ndk_path = os.environ.get('ANDROID_NDK_HOME', os.path.join(mozbuild_path, 'android-ndk-r11b'))
+ self.sdk_url = 'https://dl.google.com/android/android-sdk_r24.0.1-linux.tgz'
+ self.ndk_url = android.android_ndk_url('linux')
+
+ android.ensure_android_sdk_and_ndk(path=mozbuild_path,
+ sdk_path=self.sdk_path, sdk_url=self.sdk_url,
+ ndk_path=self.ndk_path, ndk_url=self.ndk_url,
+ artifact_mode=artifact_mode)
+
+ # 3. We expect the |android| tool to at
+ # ~/.mozbuild/android-sdk-linux/tools/android.
+ android_tool = os.path.join(self.sdk_path, 'tools', 'android')
+ android.ensure_android_packages(android_tool=android_tool)
+
+ def suggest_mobile_android_mozconfig(self, artifact_mode=False):
+ import android
+ android.suggest_mozconfig(sdk_path=self.sdk_path,
+ ndk_path=self.ndk_path,
+ artifact_mode=artifact_mode)
+
+ def suggest_mobile_android_artifact_mode_mozconfig(self):
+ self.suggest_mobile_android_mozconfig(artifact_mode=True)
+
+ def _update_package_manager(self):
+ self.apt_update()
+
+ def upgrade_mercurial(self, current):
+ """Install Mercurial from pip because Debian packages typically lag."""
+ if self.no_interactive:
+ # Install via Apt in non-interactive mode because it is the more
+ # conservative option and less likely to make people upset.
+ self.apt_install('mercurial')
+ return
+
+ res = self.prompt_int(MERCURIAL_INSTALL_PROMPT, 1, 3)
+
+ # Apt.
+ if res == 2:
+ self.apt_install('mercurial')
+ return False
+
+ # No Mercurial.
+ if res == 3:
+ print('Not installing Mercurial.')
+ return False
+
+ # pip.
+ assert res == 1
+ self.run_as_root(['pip', 'install', '--upgrade', 'Mercurial'])
diff --git a/python/mozboot/mozboot/freebsd.py b/python/mozboot/mozboot/freebsd.py
new file mode 100644
index 000000000..c524d188c
--- /dev/null
+++ b/python/mozboot/mozboot/freebsd.py
@@ -0,0 +1,63 @@
+# 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/.
+
+from mozboot.base import BaseBootstrapper
+
+
+class FreeBSDBootstrapper(BaseBootstrapper):
+ def __init__(self, version, flavor, **kwargs):
+ BaseBootstrapper.__init__(self, **kwargs)
+ self.version = int(version.split('.')[0])
+ self.flavor = flavor.lower()
+
+ self.packages = [
+ 'autoconf213',
+ 'gmake',
+ 'gtar',
+ 'mercurial',
+ 'pkgconf',
+ 'watchman',
+ 'zip',
+ ]
+
+ self.browser_packages = [
+ 'dbus-glib',
+ 'gconf2',
+ 'gtk2',
+ 'gtk3',
+ 'pulseaudio',
+ 'v4l_compat',
+ 'yasm',
+ ]
+
+ if not self.which('unzip'):
+ self.packages.append('unzip')
+
+ # GCC 4.2 or Clang 3.4 in base are too old
+ if self.flavor == 'freebsd' and self.version < 11:
+ self.browser_packages.append('gcc')
+
+ def pkg_install(self, *packages):
+ command = ['pkg', 'install']
+ if self.no_interactive:
+ command.append('-y')
+
+ command.extend(packages)
+ self.run_as_root(command)
+
+ def install_system_packages(self):
+ self.pkg_install(*self.packages)
+
+ def install_browser_packages(self):
+ self.ensure_browser_packages()
+
+ def install_browser_artifact_mode_packages(self):
+ self.ensure_browser_packages(artifact_mode=True)
+
+ def ensure_browser_packages(self, artifact_mode=False):
+ # TODO: Figure out what not to install for artifact mode
+ self.pkg_install(*self.browser_packages)
+
+ def upgrade_mercurial(self, current):
+ self.pkg_install('mercurial')
diff --git a/python/mozboot/mozboot/gentoo.py b/python/mozboot/mozboot/gentoo.py
new file mode 100644
index 000000000..085f03ae3
--- /dev/null
+++ b/python/mozboot/mozboot/gentoo.py
@@ -0,0 +1,33 @@
+# 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/.
+
+from mozboot.base import BaseBootstrapper
+
+
+class GentooBootstrapper(BaseBootstrapper):
+ def __init__(self, version, dist_id, **kwargs):
+ BaseBootstrapper.__init__(self, **kwargs)
+
+ self.version = version
+ self.dist_id = dist_id
+
+ def install_system_packages(self):
+ self.run_as_root(['emerge', '--quiet', 'dev-vcs/git', 'mercurial'])
+
+ def install_browser_packages(self):
+ self.ensure_browser_packages()
+
+ def install_browser_artifact_mode_packages(self):
+ self.ensure_browser_packages(artifact_mode=True)
+
+ def ensure_browser_packages(self, artifact_mode=False):
+ # TODO: Figure out what not to install for artifact mode
+ self.run_as_root(['emerge', '--onlydeps', '--quiet', 'firefox'])
+ self.run_as_root(['emerge', '--quiet', 'gtk+'])
+
+ def _update_package_manager(self):
+ self.run_as_root(['emerge', '--sync'])
+
+ def upgrade_mercurial(self, current):
+ self.run_as_root(['emerge', '--update', 'mercurial'])
diff --git a/python/mozboot/mozboot/mach_commands.py b/python/mozboot/mozboot/mach_commands.py
new file mode 100644
index 000000000..940ffabbb
--- /dev/null
+++ b/python/mozboot/mozboot/mach_commands.py
@@ -0,0 +1,67 @@
+# 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/.
+
+from __future__ import absolute_import, print_function, unicode_literals
+
+import sys
+
+from mach.decorators import (
+ CommandArgument,
+ CommandProvider,
+ Command,
+)
+
+
+@CommandProvider
+class Bootstrap(object):
+ """Bootstrap system and mach for optimal development experience."""
+
+ @Command('bootstrap', category='devenv',
+ description='Install required system packages for building.')
+ def bootstrap(self):
+ from mozboot.bootstrap import Bootstrapper
+
+ bootstrapper = Bootstrapper()
+ bootstrapper.bootstrap()
+
+
+@CommandProvider
+class VersionControlCommands(object):
+ def __init__(self, context):
+ self._context = context
+
+ @Command('mercurial-setup', category='devenv',
+ description='Help configure Mercurial for optimal development.')
+ @CommandArgument('-u', '--update-only', action='store_true',
+ help='Only update recommended extensions, don\'t run the wizard.')
+ def mercurial_setup(self, update_only=False):
+ """Ensure Mercurial is optimally configured.
+
+ This command will inspect your Mercurial configuration and
+ guide you through an interactive wizard helping you configure
+ Mercurial for optimal use on Mozilla projects.
+
+ User choice is respected: no changes are made without explicit
+ confirmation from you.
+
+ If "--update-only" is used, the interactive wizard is disabled
+ and this command only ensures that remote repositories providing
+ Mercurial extensions are up to date.
+ """
+ import which
+ import mozboot.bootstrap as bootstrap
+
+ # "hg" is an executable script with a shebang, which will be found
+ # be which.which. We need to pass a win32 executable to the function
+ # because we spawn a process
+ # from it.
+ if sys.platform in ('win32', 'msys'):
+ hg = which.which('hg.exe')
+ else:
+ hg = which.which('hg')
+
+ if update_only:
+ bootstrap.update_vct(hg, self._context.state_dir)
+ else:
+ bootstrap.configure_mercurial(hg, self._context.state_dir)
diff --git a/python/mozboot/mozboot/mozillabuild.py b/python/mozboot/mozboot/mozillabuild.py
new file mode 100644
index 000000000..6d4958812
--- /dev/null
+++ b/python/mozboot/mozboot/mozillabuild.py
@@ -0,0 +1,77 @@
+# 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/.
+
+import os
+import sys
+import subprocess
+import tempfile
+
+from mozboot.base import BaseBootstrapper
+
+class MozillaBuildBootstrapper(BaseBootstrapper):
+ '''Bootstrapper for MozillaBuild to install rustup.'''
+ def __init__(self, no_interactive=False):
+ BaseBootstrapper.__init__(self, no_interactive=no_interactive)
+ print("mach bootstrap is not fully implemented in MozillaBuild")
+
+ def which(self, name):
+ return BaseBootstrapper.which(self, name + '.exe')
+
+ def install_system_packages(self):
+ self.install_rustup()
+
+ def install_rustup(self):
+ try:
+ rustup_init = tempfile.gettempdir() + '/rustup-init.exe'
+ self.http_download_and_save(
+ 'https://static.rust-lang.org/rustup/archive/0.2.0/i686-pc-windows-msvc/rustup-init.exe',
+ rustup_init,
+ 'a45ab7462b567dacddaf6e9e48bb43a1b9c1db4404ba77868f7d6fc685282a46')
+ self.run([rustup_init, '--no-modify-path', '--default-host',
+ 'x86_64-pc-windows-msvc', '--default-toolchain', 'stable', '-y'])
+ mozillabuild_dir = os.environ['MOZILLABUILD']
+
+ with open(mozillabuild_dir + 'msys/etc/profile.d/profile-rustup.sh', 'wb') as f:
+ f.write('#!/bash/sh\n')
+ f.write('if test -n "$MOZILLABUILD"; then\n')
+ f.write(' WIN_HOME=$(cd "$HOME" && pwd)\n')
+ f.write(' PATH="$WIN_HOME/.cargo/bin:$PATH"\n')
+ f.write(' export PATH\n')
+ f.write('fi')
+ finally:
+ try:
+ os.remove(rustup_init)
+ except FileNotFoundError:
+ pass
+
+ def upgrade_mercurial(self, current):
+ self.pip_install('mercurial')
+
+ def upgrade_python(self, current):
+ pass
+
+ def install_browser_packages(self):
+ pass
+
+ def install_browser_artifact_mode_packages(self):
+ pass
+
+ def install_mobile_android_packages(self):
+ pass
+
+ def install_mobile_android_artifact_mode_packages(self):
+ pass
+
+ def _update_package_manager(self):
+ pass
+
+ def run(self, command):
+ subprocess.check_call(command, stdin=sys.stdin)
+
+ def pip_install(self, *packages):
+ pip_dir = os.path.join(os.environ['MOZILLABUILD'], 'python', 'Scripts', 'pip.exe')
+ command = [pip_dir, 'install', '--upgrade']
+ command.extend(packages)
+ self.run(command)
+
diff --git a/python/mozboot/mozboot/openbsd.py b/python/mozboot/mozboot/openbsd.py
new file mode 100644
index 000000000..df6a195fd
--- /dev/null
+++ b/python/mozboot/mozboot/openbsd.py
@@ -0,0 +1,45 @@
+# 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/.
+
+from mozboot.base import BaseBootstrapper
+
+
+class OpenBSDBootstrapper(BaseBootstrapper):
+ def __init__(self, version, **kwargs):
+ BaseBootstrapper.__init__(self, **kwargs)
+
+ self.packages = [
+ 'mercurial',
+ 'autoconf-2.13',
+ 'gmake',
+ 'gtar',
+ 'wget',
+ 'unzip',
+ 'zip',
+ ]
+
+ self.browser_packages = [
+ 'llvm',
+ 'yasm',
+ 'gconf2',
+ 'gtk+2',
+ 'gtk+3',
+ 'dbus-glib',
+ 'pulseaudio',
+ ]
+
+ def install_system_packages(self):
+ # we use -z because there's no other way to say "any autoconf-2.13"
+ self.run_as_root(['pkg_add', '-z'] + self.packages)
+
+ def install_browser_packages(self):
+ self.ensure_browser_packages()
+
+ def install_browser_artifact_mode_packages(self):
+ self.ensure_browser_packages(artifact_mode=True)
+
+ def ensure_browser_packages(self, artifact_mode=False):
+ # TODO: Figure out what not to install for artifact mode
+ # we use -z because there's no other way to say "any autoconf-2.13"
+ self.run_as_root(['pkg_add', '-z'] + self.browser_packages)
diff --git a/python/mozboot/mozboot/osx.py b/python/mozboot/mozboot/osx.py
new file mode 100644
index 000000000..d66d66d6b
--- /dev/null
+++ b/python/mozboot/mozboot/osx.py
@@ -0,0 +1,577 @@
+# 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/.
+
+from __future__ import print_function, unicode_literals
+
+import os
+import re
+import subprocess
+import sys
+import tempfile
+try:
+ from urllib2 import urlopen
+except ImportError:
+ from urllib.request import urlopen
+
+from distutils.version import StrictVersion
+
+from mozboot.base import BaseBootstrapper
+
+HOMEBREW_BOOTSTRAP = 'https://raw.githubusercontent.com/Homebrew/install/master/install'
+XCODE_APP_STORE = 'macappstore://itunes.apple.com/app/id497799835?mt=12'
+XCODE_LEGACY = 'https://developer.apple.com/downloads/download.action?path=Developer_Tools/xcode_3.2.6_and_ios_sdk_4.3__final/xcode_3.2.6_and_ios_sdk_4.3.dmg'
+HOMEBREW_AUTOCONF213 = 'https://raw.github.com/Homebrew/homebrew-versions/master/autoconf213.rb'
+
+MACPORTS_URL = {'11': 'https://distfiles.macports.org/MacPorts/MacPorts-2.3.4-10.11-ElCapitan.pkg',
+ '10': 'https://distfiles.macports.org/MacPorts/MacPorts-2.3.4-10.10-Yosemite.pkg',
+ '9': 'https://distfiles.macports.org/MacPorts/MacPorts-2.3.4-10.9-Mavericks.pkg',
+ '8': 'https://distfiles.macports.org/MacPorts/MacPorts-2.3.4-10.8-MountainLion.pkg',
+ '7': 'https://distfiles.macports.org/MacPorts/MacPorts-2.3.4-10.7-Lion.pkg',
+ '6': 'https://distfiles.macports.org/MacPorts/MacPorts-2.3.4-10.6-SnowLeopard.pkg', }
+
+MACPORTS_CLANG_PACKAGE = 'clang-3.3'
+
+RE_CLANG_VERSION = re.compile('Apple (?:clang|LLVM) version (\d+\.\d+)')
+
+APPLE_CLANG_MINIMUM_VERSION = StrictVersion('4.2')
+
+XCODE_REQUIRED = '''
+Xcode is required to build Firefox. Please complete the install of Xcode
+through the App Store.
+
+It's possible Xcode is already installed on this machine but it isn't being
+detected. This is possible with developer preview releases of Xcode, for
+example. To correct this problem, run:
+
+ `xcode-select --switch /path/to/Xcode.app`.
+
+e.g. `sudo xcode-select --switch /Applications/Xcode.app`.
+'''
+
+XCODE_REQUIRED_LEGACY = '''
+You will need to download and install Xcode to build Firefox.
+
+Please complete the Xcode download and then relaunch this script.
+'''
+
+XCODE_NO_DEVELOPER_DIRECTORY = '''
+xcode-select says you don't have a developer directory configured. We think
+this is due to you not having Xcode installed (properly). We're going to
+attempt to install Xcode through the App Store. If the App Store thinks you
+have Xcode installed, please run xcode-select by hand until it stops
+complaining and then re-run this script.
+'''
+
+XCODE_COMMAND_LINE_TOOLS_MISSING = '''
+The Xcode command line tools are required to build Firefox.
+'''
+
+INSTALL_XCODE_COMMAND_LINE_TOOLS_STEPS = '''
+Perform the following steps to install the Xcode command line tools:
+
+ 1) Open Xcode.app
+ 2) Click through any first-run prompts
+ 3) From the main Xcode menu, select Preferences (Command ,)
+ 4) Go to the Download tab (near the right)
+ 5) Install the "Command Line Tools"
+
+When that has finished installing, please relaunch this script.
+'''
+
+UPGRADE_XCODE_COMMAND_LINE_TOOLS = '''
+An old version of the Xcode command line tools is installed. You will need to
+install a newer version in order to compile Firefox. If Xcode itself is old,
+its command line tools may be too old even if it claims there are no updates
+available, so if you are seeing this message multiple times, please update
+Xcode first.
+'''
+
+PACKAGE_MANAGER_INSTALL = '''
+We will install the %s package manager to install required packages.
+
+You will be prompted to install %s with its default settings. If you
+would prefer to do this manually, hit CTRL+c, install %s yourself, ensure
+"%s" is in your $PATH, and relaunch bootstrap.
+'''
+
+PACKAGE_MANAGER_PACKAGES = '''
+We are now installing all required packages via %s. You will see a lot of
+output as packages are built.
+'''
+
+PACKAGE_MANAGER_OLD_CLANG = '''
+We require a newer compiler than what is provided by your version of Xcode.
+
+We will install a modern version of Clang through %s.
+'''
+
+PACKAGE_MANAGER_CHOICE = '''
+Please choose a package manager you'd like:
+1. Homebrew
+2. MacPorts (Does not yet support bootstrapping Firefox for Android.)
+Your choice:
+'''
+
+NO_PACKAGE_MANAGER_WARNING = '''
+It seems you don't have any supported package manager installed.
+'''
+
+PACKAGE_MANAGER_EXISTS = '''
+Looks like you have %s installed. We will install all required packages via %s.
+'''
+
+MULTI_PACKAGE_MANAGER_EXISTS = '''
+It looks like you have multiple package managers installed.
+'''
+
+# May add support for other package manager on os x.
+PACKAGE_MANAGER = {'Homebrew': 'brew',
+ 'MacPorts': 'port'}
+
+PACKAGE_MANAGER_CHOICES = ['Homebrew', 'MacPorts']
+
+PACKAGE_MANAGER_BIN_MISSING = '''
+A package manager is installed. However, your current shell does
+not know where to find '%s' yet. You'll need to start a new shell
+to pick up the environment changes so it can be found.
+
+Please start a new shell or terminal window and run this
+bootstrapper again.
+
+If this problem persists, you will likely want to adjust your
+shell's init script (e.g. ~/.bash_profile) to export a PATH
+environment variable containing the location of your package
+manager binary. e.g.
+
+ export PATH=/usr/local/bin:$PATH
+'''
+
+BAD_PATH_ORDER = '''
+Your environment's PATH variable lists a system path directory (%s)
+before the path to your package manager's binaries (%s).
+This means that the package manager's binaries likely won't be
+detected properly.
+
+Modify your shell's configuration (e.g. ~/.profile or
+~/.bash_profile) to have %s appear in $PATH before %s. e.g.
+
+ export PATH=%s:$PATH
+
+Once this is done, start a new shell (likely Command+T) and run
+this bootstrap again.
+'''
+
+JAVA_LICENSE_NOTICE = '''
+We installed a recent Java toolchain for you. We agreed to the Oracle Java
+license for you by downloading the JDK. If this is unacceptable you should
+uninstall.
+'''
+
+
+class OSXBootstrapper(BaseBootstrapper):
+ def __init__(self, version, **kwargs):
+ BaseBootstrapper.__init__(self, **kwargs)
+
+ self.os_version = StrictVersion(version)
+
+ if self.os_version < StrictVersion('10.6'):
+ raise Exception('OS X 10.6 or above is required.')
+
+ self.minor_version = version.split('.')[1]
+
+ def install_system_packages(self):
+ self.ensure_xcode()
+
+ choice = self.ensure_package_manager()
+ self.package_manager = choice
+ getattr(self, 'ensure_%s_system_packages' % self.package_manager)()
+
+ def install_browser_packages(self):
+ getattr(self, 'ensure_%s_browser_packages' % self.package_manager)()
+
+ def install_browser_artifact_mode_packages(self):
+ getattr(self, 'ensure_%s_browser_packages' % self.package_manager)(artifact_mode=True)
+
+ def install_mobile_android_packages(self):
+ getattr(self, 'ensure_%s_mobile_android_packages' % self.package_manager)()
+
+ def install_mobile_android_artifact_mode_packages(self):
+ getattr(self, 'ensure_%s_mobile_android_packages' % self.package_manager)(artifact_mode=True)
+
+ def suggest_mobile_android_mozconfig(self):
+ getattr(self, 'suggest_%s_mobile_android_mozconfig' % self.package_manager)()
+
+ def suggest_mobile_android_artifact_mode_mozconfig(self):
+ getattr(self, 'suggest_%s_mobile_android_mozconfig' % self.package_manager)(artifact_mode=True)
+
+ def ensure_xcode(self):
+ if self.os_version < StrictVersion('10.7'):
+ if not os.path.exists('/Developer/Applications/Xcode.app'):
+ print(XCODE_REQUIRED_LEGACY)
+
+ subprocess.check_call(['open', XCODE_LEGACY])
+ sys.exit(1)
+
+ # OS X 10.7 have Xcode come from the app store. However, users can
+ # still install Xcode into any arbitrary location. We honor the
+ # location of Xcode as set by xcode-select. This should also pick up
+ # developer preview releases of Xcode, which can be installed into
+ # paths like /Applications/Xcode5-DP6.app.
+ elif self.os_version >= StrictVersion('10.7'):
+ select = self.which('xcode-select')
+ try:
+ output = self.check_output([select, '--print-path'],
+ stderr=subprocess.STDOUT)
+ except subprocess.CalledProcessError as e:
+ # This seems to appear on fresh OS X machines before any Xcode
+ # has been installed. It may only occur on OS X 10.9 and later.
+ if b'unable to get active developer directory' in e.output:
+ print(XCODE_NO_DEVELOPER_DIRECTORY)
+ self._install_xcode_app_store()
+ assert False # Above should exit.
+
+ output = e.output
+
+ # This isn't the most robust check in the world. It relies on the
+ # default value not being in an application bundle, which seems to
+ # hold on at least Mavericks.
+ if b'.app/' not in output:
+ print(XCODE_REQUIRED)
+ self._install_xcode_app_store()
+ assert False # Above should exit.
+
+ # Once Xcode is installed, you need to agree to the license before you can
+ # use it.
+ try:
+ output = self.check_output(['/usr/bin/xcrun', 'clang'],
+ stderr=subprocess.STDOUT)
+ except subprocess.CalledProcessError as e:
+ if b'license' in e.output:
+ xcodebuild = self.which('xcodebuild')
+ try:
+ subprocess.check_call([xcodebuild, '-license'],
+ stderr=subprocess.STDOUT)
+ except subprocess.CalledProcessError as e:
+ if b'requires admin privileges' in e.output:
+ self.run_as_root([xcodebuild, '-license'])
+
+ # Even then we're not done! We need to install the Xcode command line tools.
+ # As of Mountain Lion, apparently the only way to do this is to go through a
+ # menu dialog inside Xcode itself. We're not making this up.
+ if self.os_version >= StrictVersion('10.7'):
+ if not os.path.exists('/usr/bin/clang'):
+ print(XCODE_COMMAND_LINE_TOOLS_MISSING)
+ print(INSTALL_XCODE_COMMAND_LINE_TOOLS_STEPS)
+ sys.exit(1)
+
+ output = self.check_output(['/usr/bin/clang', '--version'])
+ match = RE_CLANG_VERSION.search(output)
+ if match is None:
+ raise Exception('Could not determine Clang version.')
+
+ version = StrictVersion(match.group(1))
+
+ if version < APPLE_CLANG_MINIMUM_VERSION:
+ print(UPGRADE_XCODE_COMMAND_LINE_TOOLS)
+ print(INSTALL_XCODE_COMMAND_LINE_TOOLS_STEPS)
+ sys.exit(1)
+
+ def _install_xcode_app_store(self):
+ subprocess.check_call(['open', XCODE_APP_STORE])
+ print('Once the install has finished, please relaunch this script.')
+ sys.exit(1)
+
+ def _ensure_homebrew_packages(self, packages, extra_brew_args=[]):
+ self.brew = self.which('brew')
+ assert self.brew is not None
+ cmd = [self.brew] + extra_brew_args
+
+ installed = self.check_output(cmd + ['list']).split()
+
+ printed = False
+
+ for name, package in packages:
+ if name in installed:
+ continue
+
+ if not printed:
+ print(PACKAGE_MANAGER_PACKAGES % ('Homebrew',))
+ printed = True
+
+ subprocess.check_call(cmd + ['install', package])
+
+ return printed
+
+ def _ensure_homebrew_casks(self, casks):
+ # Change |brew install cask| into |brew cask install cask|.
+ return self._ensure_homebrew_packages(casks, extra_brew_args=['cask'])
+
+ def ensure_homebrew_system_packages(self):
+ packages = [
+ # We need to install Python because Mercurial requires the Python
+ # development headers which are missing from OS X (at least on
+ # 10.8) and because the build system wants a version newer than
+ # what Apple ships.
+ ('python', 'python'),
+ ('mercurial', 'mercurial'),
+ ('git', 'git'),
+ ('autoconf213', HOMEBREW_AUTOCONF213),
+ ('gnu-tar', 'gnu-tar'),
+ ('watchman', 'watchman',),
+ ('terminal-notifier', 'terminal-notifier')
+ ]
+ self._ensure_homebrew_packages(packages)
+
+ def ensure_homebrew_browser_packages(self, artifact_mode=False):
+ # TODO: Figure out what not to install for artifact mode
+ packages = [
+ ('yasm', 'yasm'),
+ ]
+ self._ensure_homebrew_packages(packages)
+
+ installed = self.check_output([self.brew, 'list']).split()
+ if self.os_version < StrictVersion('10.7') and b'llvm' not in installed:
+ print(PACKAGE_MANAGER_OLD_CLANG % ('Homebrew',))
+
+ subprocess.check_call([self.brew, '-v', 'install', 'llvm',
+ '--with-clang', '--all-targets'])
+
+ def ensure_homebrew_mobile_android_packages(self, artifact_mode=False):
+ # Multi-part process:
+ # 1. System packages.
+ # 2. Android SDK. Android NDK only if we are not in artifact mode.
+ # 3. Android packages.
+
+ import android
+
+ # 1. System packages.
+ packages = [
+ ('brew-cask', 'caskroom/cask/brew-cask'), # For installing Java later.
+ ('wget', 'wget'),
+ ]
+ self._ensure_homebrew_packages(packages)
+
+ casks = [
+ ('java', 'java'),
+ ]
+ installed = self._ensure_homebrew_casks(casks)
+ if installed:
+ print(JAVA_LICENSE_NOTICE) # We accepted a license agreement for the user.
+
+ # 2. The user may have an external Android SDK (in which case we save
+ # them a lengthy download), or they may have already completed the
+ # download. We unpack to ~/.mozbuild/{android-sdk-linux, android-ndk-r11b}.
+ mozbuild_path = os.environ.get('MOZBUILD_STATE_PATH', os.path.expanduser(os.path.join('~', '.mozbuild')))
+ self.sdk_path = os.environ.get('ANDROID_SDK_HOME', os.path.join(mozbuild_path, 'android-sdk-macosx'))
+ self.ndk_path = os.environ.get('ANDROID_NDK_HOME', os.path.join(mozbuild_path, 'android-ndk-r11b'))
+ self.sdk_url = 'https://dl.google.com/android/android-sdk_r24.0.1-macosx.zip'
+ is_64bits = sys.maxsize > 2**32
+ if is_64bits:
+ self.ndk_url = android.android_ndk_url('darwin')
+ else:
+ raise Exception('You need a 64-bit version of Mac OS X to build Firefox for Android.')
+
+ android.ensure_android_sdk_and_ndk(path=mozbuild_path,
+ sdk_path=self.sdk_path, sdk_url=self.sdk_url,
+ ndk_path=self.ndk_path, ndk_url=self.ndk_url,
+ artifact_mode=artifact_mode)
+
+ # 3. We expect the |android| tool to at
+ # ~/.mozbuild/android-sdk-macosx/tools/android.
+ android_tool = os.path.join(self.sdk_path, 'tools', 'android')
+ android.ensure_android_packages(android_tool=android_tool)
+
+ def suggest_homebrew_mobile_android_mozconfig(self, artifact_mode=False):
+ import android
+ android.suggest_mozconfig(sdk_path=self.sdk_path,
+ ndk_path=self.ndk_path,
+ artifact_mode=artifact_mode)
+
+ def _ensure_macports_packages(self, packages):
+ self.port = self.which('port')
+ assert self.port is not None
+
+ installed = set(self.check_output([self.port, 'installed']).split())
+
+ missing = [package for package in packages if package not in installed]
+ if missing:
+ print(PACKAGE_MANAGER_PACKAGES % ('MacPorts',))
+ self.run_as_root([self.port, '-v', 'install'] + missing)
+
+ def ensure_macports_system_packages(self):
+ packages = [
+ 'python27',
+ 'py27-readline',
+ 'mercurial',
+ 'autoconf213',
+ 'gnutar',
+ 'watchman',
+ ]
+
+ self._ensure_macports_packages(packages)
+ self.run_as_root([self.port, 'select', '--set', 'python', 'python27'])
+
+ def ensure_macports_browser_packages(self, artifact_mode=False):
+ # TODO: Figure out what not to install for artifact mode
+ packages = ['yasm']
+
+ self._ensure_macports_packages(packages)
+
+ installed = set(self.check_output([self.port, 'installed']).split())
+ if self.os_version < StrictVersion('10.7') and MACPORTS_CLANG_PACKAGE not in installed:
+ print(PACKAGE_MANAGER_OLD_CLANG % ('MacPorts',))
+ self.run_as_root([self.port, '-v', 'install', MACPORTS_CLANG_PACKAGE])
+ self.run_as_root([self.port, 'select', '--set', 'clang', 'mp-' + MACPORTS_CLANG_PACKAGE])
+
+ def ensure_macports_mobile_android_packages(self, artifact_mode=False):
+ # Multi-part process:
+ # 1. System packages.
+ # 2. Android SDK. Android NDK only if we are not in artifact mode.
+ # 3. Android packages.
+
+ import android
+
+ # 1. System packages.
+ packages = [
+ 'wget',
+ ]
+ self._ensure_macports_packages(packages)
+
+ # Verify the presence of java and javac.
+ if not self.which('java') or not self.which('javac'):
+ raise Exception('You need to have Java version 1.7 or later installed. Please visit http://www.java.com/en/download/mac_download.jsp to get the latest version.')
+
+ # 2. The user may have an external Android SDK (in which case we save
+ # them a lengthy download), or they may have already completed the
+ # download. We unpack to ~/.mozbuild/{android-sdk-linux, android-ndk-r11b}.
+ mozbuild_path = os.environ.get('MOZBUILD_STATE_PATH', os.path.expanduser(os.path.join('~', '.mozbuild')))
+ self.sdk_path = os.environ.get('ANDROID_SDK_HOME', os.path.join(mozbuild_path, 'android-sdk-macosx'))
+ self.ndk_path = os.environ.get('ANDROID_NDK_HOME', os.path.join(mozbuild_path, 'android-ndk-r11b'))
+ self.sdk_url = 'https://dl.google.com/android/android-sdk_r24.0.1-macosx.zip'
+ is_64bits = sys.maxsize > 2**32
+ if is_64bits:
+ self.ndk_url = android.android_ndk_url('darwin')
+ else:
+ raise Exception('You need a 64-bit version of Mac OS X to build Firefox for Android.')
+
+ android.ensure_android_sdk_and_ndk(path=mozbuild_path,
+ sdk_path=self.sdk_path, sdk_url=self.sdk_url,
+ ndk_path=self.ndk_path, ndk_url=self.ndk_url,
+ artifact_mode=artifact_mode)
+
+ # 3. We expect the |android| tool to at
+ # ~/.mozbuild/android-sdk-macosx/tools/android.
+ android_tool = os.path.join(self.sdk_path, 'tools', 'android')
+ android.ensure_android_packages(android_tool=android_tool)
+
+ def suggest_macports_mobile_android_mozconfig(self, artifact_mode=False):
+ import android
+ android.suggest_mozconfig(sdk_path=self.sdk_path,
+ ndk_path=self.ndk_path,
+ artifact_mode=artifact_mode)
+
+ def ensure_package_manager(self):
+ '''
+ Search package mgr in sys.path, if none is found, prompt the user to install one.
+ If only one is found, use that one. If both are found, prompt the user to choose
+ one.
+ '''
+ installed = []
+ for name, cmd in PACKAGE_MANAGER.iteritems():
+ if self.which(cmd) is not None:
+ installed.append(name)
+
+ active_name, active_cmd = None, None
+
+ if not installed:
+ print(NO_PACKAGE_MANAGER_WARNING)
+ choice = self.prompt_int(prompt=PACKAGE_MANAGER_CHOICE, low=1, high=2)
+ active_name = PACKAGE_MANAGER_CHOICES[choice - 1]
+ active_cmd = PACKAGE_MANAGER[active_name]
+ getattr(self, 'install_%s' % active_name.lower())()
+ elif len(installed) == 1:
+ print(PACKAGE_MANAGER_EXISTS % (installed[0], installed[0]))
+ active_name = installed[0]
+ active_cmd = PACKAGE_MANAGER[active_name]
+ else:
+ print(MULTI_PACKAGE_MANAGER_EXISTS)
+ choice = self.prompt_int(prompt=PACKAGE_MANAGER_CHOICE, low=1, high=2)
+
+ active_name = PACKAGE_MANAGER_CHOICES[choice - 1]
+ active_cmd = PACKAGE_MANAGER[active_name]
+
+ # Ensure the active package manager is in $PATH and it comes before
+ # /usr/bin. If it doesn't come before /usr/bin, we'll pick up system
+ # packages before package manager installed packages and the build may
+ # break.
+ p = self.which(active_cmd)
+ if not p:
+ print(PACKAGE_MANAGER_BIN_MISSING % active_cmd)
+ sys.exit(1)
+
+ p_dir = os.path.dirname(p)
+ for path in os.environ['PATH'].split(os.pathsep):
+ if path == p_dir:
+ break
+
+ for check in ('/bin', '/usr/bin'):
+ if path == check:
+ print(BAD_PATH_ORDER % (check, p_dir, p_dir, check, p_dir))
+ sys.exit(1)
+
+ return active_name.lower()
+
+ def install_homebrew(self):
+ print(PACKAGE_MANAGER_INSTALL % ('Homebrew', 'Homebrew', 'Homebrew', 'brew'))
+ bootstrap = urlopen(url=HOMEBREW_BOOTSTRAP, timeout=20).read()
+ with tempfile.NamedTemporaryFile() as tf:
+ tf.write(bootstrap)
+ tf.flush()
+
+ subprocess.check_call(['ruby', tf.name])
+
+ def install_macports(self):
+ url = MACPORTS_URL.get(self.minor_version, None)
+ if not url:
+ raise Exception('We do not have a MacPorts install URL for your '
+ 'OS X version. You will need to install MacPorts manually.')
+
+ print(PACKAGE_MANAGER_INSTALL % ('MacPorts', 'MacPorts', 'MacPorts', 'port'))
+ pkg = urlopen(url=url, timeout=300).read()
+ with tempfile.NamedTemporaryFile(suffix='.pkg') as tf:
+ tf.write(pkg)
+ tf.flush()
+
+ self.run_as_root(['installer', '-pkg', tf.name, '-target', '/'])
+
+ def _update_package_manager(self):
+ if self.package_manager == 'homebrew':
+ subprocess.check_call([self.brew, '-v', 'update'])
+ else:
+ assert self.package_manager == 'macports'
+ self.run_as_root([self.port, 'selfupdate'])
+
+ def _upgrade_package(self, package):
+ self._ensure_package_manager_updated()
+
+ if self.package_manager == 'homebrew':
+ try:
+ subprocess.check_output([self.brew, '-v', 'upgrade', package],
+ stderr=subprocess.STDOUT)
+ except subprocess.CalledProcessError as e:
+ if b'already installed' not in e.output:
+ raise
+ else:
+ assert self.package_manager == 'macports'
+
+ self.run_as_root([self.port, 'upgrade', package])
+
+ def upgrade_mercurial(self, current):
+ self._upgrade_package('mercurial')
+
+ def upgrade_python(self, current):
+ if self.package_manager == 'homebrew':
+ self._upgrade_package('python')
+ else:
+ self._upgrade_package('python27')
diff --git a/python/mozboot/mozboot/util.py b/python/mozboot/mozboot/util.py
new file mode 100644
index 000000000..f2bbb76db
--- /dev/null
+++ b/python/mozboot/mozboot/util.py
@@ -0,0 +1,20 @@
+# 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/.
+
+import os
+
+
+def get_state_dir():
+ """Obtain path to a directory to hold state.
+
+ Returns a tuple of the path and a bool indicating whether the
+ value came from an environment variable.
+ """
+ state_user_dir = os.path.expanduser('~/.mozbuild')
+ state_env_dir = os.environ.get('MOZBUILD_STATE_PATH')
+
+ if state_env_dir:
+ return state_env_dir, True
+ else:
+ return state_user_dir, False
diff --git a/python/mozboot/mozboot/windows.py b/python/mozboot/mozboot/windows.py
new file mode 100644
index 000000000..c072b1b91
--- /dev/null
+++ b/python/mozboot/mozboot/windows.py
@@ -0,0 +1,95 @@
+# 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/.
+
+import os
+import sys
+import subprocess
+
+from mozboot.base import BaseBootstrapper
+
+class WindowsBootstrapper(BaseBootstrapper):
+ '''Bootstrapper for msys2 based environments for building in Windows.'''
+
+ SYSTEM_PACKAGES = [
+ 'mingw-w64-x86_64-make',
+ 'mingw-w64-x86_64-python2-pip',
+ 'mingw-w64-x86_64-perl',
+ 'patch',
+ 'patchutils',
+ 'diffutils',
+ 'autoconf2.13',
+ 'tar',
+ 'zip',
+ 'unzip',
+ 'mingw-w64-x86_64-toolchain', # TODO: Should be removed when Mercurial is installable from a wheel.
+ 'mingw-w64-i686-toolchain'
+ ]
+
+ BROWSER_PACKAGES = [
+ 'mingw-w64-x86_64-yasm',
+ 'mingw-w64-i686-nsis'
+ ]
+
+ MOBILE_ANDROID_COMMON_PACKAGES = [
+ 'wget'
+ ]
+
+ def __init__(self, **kwargs):
+ if 'MOZ_WINDOWS_BOOTSTRAP' not in os.environ or os.environ['MOZ_WINDOWS_BOOTSTRAP'] != '1':
+ raise NotImplementedError('Bootstrap support for Windows is under development. For now, use MozillaBuild '
+ 'to set up a build environment on Windows. If you are testing Windows Bootstrap support, '
+ 'try `export MOZ_WINDOWS_BOOTSTRAP=1`')
+ BaseBootstrapper.__init__(self, **kwargs)
+ if not self.which('pacman'):
+ raise NotImplementedError('The Windows bootstrapper only works with msys2 with pacman. Get msys2 at '
+ 'http://msys2.github.io/')
+ print 'Using an experimental bootstrapper for Windows.'
+
+ def which(self, name):
+ return BaseBootstrapper.which(self, name + '.exe')
+
+ def install_system_packages(self):
+ self.pacman_install(*self.SYSTEM_PACKAGES)
+
+ def upgrade_mercurial(self, current):
+ self.pip_install('mercurial')
+
+ def upgrade_python(self, current):
+ self.pacman_install('mingw-w64-x86_64-python2')
+
+ def install_browser_packages(self):
+ self.pacman_install(*self.BROWSER_PACKAGES)
+
+ def install_mobile_android_packages(self):
+ raise NotImplementedError('We do not support building Android on Windows. Sorry!')
+
+ def install_mobile_android_artifact_mode_packages(self):
+ raise NotImplementedError('We do not support building Android on Windows. Sorry!')
+
+ def _update_package_manager(self):
+ self.pacman_update()
+
+ def run(self, command):
+ subprocess.check_call(command, stdin=sys.stdin)
+
+ def pacman_update(self):
+ command = ['pacman', '--sync', '--refresh']
+ self.run(command)
+
+ def pacman_upgrade(self):
+ command = ['pacman', '--sync', '--refresh', '--sysupgrade']
+ self.run(command)
+
+ def pacman_install(self, *packages):
+ command = ['pacman', '--sync', '--needed']
+ if self.no_interactive:
+ command.append('--noconfirm')
+
+ command.extend(packages)
+ self.run(command)
+
+ def pip_install(self, *packages):
+ command = ['pip', 'install', '--upgrade']
+ command.extend(packages)
+ self.run(command)
diff --git a/python/mozboot/setup.py b/python/mozboot/setup.py
new file mode 100644
index 000000000..2ad2c63ec
--- /dev/null
+++ b/python/mozboot/setup.py
@@ -0,0 +1,16 @@
+# 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/.
+
+from distutils.core import setup
+
+VERSION = '0.1'
+
+setup(
+ name='mozboot',
+ description='System bootstrap for building Mozilla projects.',
+ license='MPL 2.0',
+ packages=['mozboot'],
+ version=VERSION,
+ scripts=['bin/bootstrap.py'],
+)
diff --git a/python/mozboot/support/ConEmu.xml b/python/mozboot/support/ConEmu.xml
new file mode 100755
index 000000000..e2df514f1
--- /dev/null
+++ b/python/mozboot/support/ConEmu.xml
@@ -0,0 +1,897 @@
+<?xml version="1.0" encoding="utf-8"?>
+<key name="Software">
+ <key name="ConEmu">
+ <key name=".Vanilla" modified="2016-08-05 15:29:26" build="160724">
+ <value name="SingleInstance" type="hex" data="00"/>
+ <value name="KeyboardHooks" type="hex" data="01"/>
+ <value name="UseInjects" type="hex" data="01"/>
+ <value name="Update.CheckOnStartup" type="hex" data="00"/>
+ <value name="Update.CheckHourly" type="hex" data="00"/>
+ <value name="Update.ConfirmDownload" type="hex" data="01"/>
+ <value name="Update.UseBuilds" type="hex" data="02"/>
+ <value name="ColorTable00" type="dword" data="00000000"/>
+ <value name="ColorTable01" type="dword" data="00800000"/>
+ <value name="ColorTable02" type="dword" data="00008000"/>
+ <value name="ColorTable03" type="dword" data="00808000"/>
+ <value name="ColorTable04" type="dword" data="00000080"/>
+ <value name="ColorTable05" type="dword" data="00800080"/>
+ <value name="ColorTable06" type="dword" data="00008080"/>
+ <value name="ColorTable07" type="dword" data="00c0c0c0"/>
+ <value name="ColorTable08" type="dword" data="00808080"/>
+ <value name="ColorTable09" type="dword" data="00ff0000"/>
+ <value name="ColorTable10" type="dword" data="0000ff00"/>
+ <value name="ColorTable11" type="dword" data="00ffff00"/>
+ <value name="ColorTable12" type="dword" data="000000ff"/>
+ <value name="ColorTable13" type="dword" data="00ff00ff"/>
+ <value name="ColorTable14" type="dword" data="0000ffff"/>
+ <value name="ColorTable15" type="dword" data="00ffffff"/>
+ <value name="ColorTable16" type="dword" data="00000000"/>
+ <value name="ColorTable17" type="dword" data="00800000"/>
+ <value name="ColorTable18" type="dword" data="00008000"/>
+ <value name="ColorTable19" type="dword" data="00808000"/>
+ <value name="ColorTable20" type="dword" data="00000080"/>
+ <value name="ColorTable21" type="dword" data="00800080"/>
+ <value name="ColorTable22" type="dword" data="00008080"/>
+ <value name="ColorTable23" type="dword" data="00c0c0c0"/>
+ <value name="ColorTable24" type="dword" data="00808080"/>
+ <value name="ColorTable25" type="dword" data="00ff0000"/>
+ <value name="ColorTable26" type="dword" data="0000ff00"/>
+ <value name="ColorTable27" type="dword" data="00ffff00"/>
+ <value name="ColorTable28" type="dword" data="000000ff"/>
+ <value name="ColorTable29" type="dword" data="00ff00ff"/>
+ <value name="ColorTable30" type="dword" data="0000ffff"/>
+ <value name="ColorTable31" type="dword" data="00ffffff"/>
+ <value name="ExtendColors" type="hex" data="00"/>
+ <value name="ExtendColorIdx" type="hex" data="0e"/>
+ <value name="TextColorIdx" type="hex" data="10"/>
+ <value name="BackColorIdx" type="hex" data="10"/>
+ <value name="PopTextColorIdx" type="hex" data="10"/>
+ <value name="PopBackColorIdx" type="hex" data="10"/>
+ <value name="ExtendFonts" type="hex" data="00"/>
+ <value name="ExtendFontNormalIdx" type="hex" data="01"/>
+ <value name="ExtendFontBoldIdx" type="hex" data="0c"/>
+ <value name="ExtendFontItalicIdx" type="hex" data="0d"/>
+ <value name="CursorTypeActive" type="dword" data="000232c1"/>
+ <value name="CursorTypeInactive" type="dword" data="00823283"/>
+ <value name="ClipboardDetectLineEnd" type="hex" data="01"/>
+ <value name="ClipboardBashMargin" type="hex" data="00"/>
+ <value name="ClipboardTrimTrailing" type="hex" data="02"/>
+ <value name="ClipboardEOL" type="hex" data="00"/>
+ <value name="ClipboardArrowStart" type="hex" data="01"/>
+ <value name="ClipboardAllLines" type="hex" data="01"/>
+ <value name="ClipboardFirstLine" type="hex" data="01"/>
+ <value name="ClipboardClickPromptPosition" type="hex" data="02"/>
+ <value name="ClipboardDeleteLeftWord" type="hex" data="02"/>
+ <value name="TrueColorerSupport" type="hex" data="01"/>
+ <value name="FadeInactive" type="hex" data="01"/>
+ <value name="FadeInactiveLow" type="hex" data="00"/>
+ <value name="FadeInactiveHigh" type="hex" data="d0"/>
+ <value name="ConVisible" type="hex" data="00"/>
+ <value name="ConInMode" type="dword" data="ffffffff"/>
+ <value name="SetDefaultTerminal" type="hex" data="00"/>
+ <value name="SetDefaultTerminalStartup" type="hex" data="00"/>
+ <value name="SetDefaultTerminalStartupTSA" type="hex" data="01"/>
+ <value name="DefaultTerminalNoInjects" type="hex" data="00"/>
+ <value name="DefaultTerminalNewWindow" type="hex" data="00"/>
+ <value name="DefaultTerminalConfirm" type="hex" data="01"/>
+ <value name="DefaultTerminalApps" type="string" data="explorer.exe"/>
+ <value name="ProcessAnsi" type="hex" data="01"/>
+ <value name="AnsiLog" type="hex" data="00"/>
+ <value name="AnsiLogPath" type="string" data="%ConEmuDir%\Logs\"/>
+ <value name="ProcessNewConArg" type="hex" data="01"/>
+ <value name="ConsoleExceptionHandler" type="hex" data="00"/>
+ <value name="UseClink" type="hex" data="01"/>
+ <value name="StartType" type="hex" data="00"/>
+ <value name="CmdLine" type="string" data=""/>
+ <value name="StartTasksFile" type="string" data=""/>
+ <value name="StartTasksName" type="string" data=""/>
+ <value name="StartFarFolders" type="hex" data="00"/>
+ <value name="StartFarEditors" type="hex" data="00"/>
+ <value name="StoreTaskbarkTasks" type="hex" data="00"/>
+ <value name="StoreTaskbarCommands" type="hex" data="00"/>
+ <value name="SaveCmdHistory" type="hex" data="01"/>
+ <value name="CmdLineHistory" type="multi">
+ <line data="{Bash::mozdev}"/>
+ </value>
+ <value name="ShowHelpTooltips" type="hex" data="01"/>
+ <value name="Multi" type="hex" data="01"/>
+ <value name="Multi.ShowButtons" type="hex" data="01"/>
+ <value name="Multi.NumberInCaption" type="hex" data="00"/>
+ <value name="Multi.CloseConfirm" type="hex" data="01"/>
+ <value name="Multi.CloseEditViewConfirm" type="hex" data="00"/>
+ <value name="Multi.NewConfirm" type="hex" data="01"/>
+ <value name="Multi.UseArrows" type="hex" data="00"/>
+ <value name="Multi.UseNumbers" type="hex" data="01"/>
+ <value name="Multi.UseWinTab" type="hex" data="00"/>
+ <value name="Multi.AutoCreate" type="hex" data="00"/>
+ <value name="Multi.LeaveOnClose" type="hex" data="00"/>
+ <value name="Multi.HideOnClose" type="hex" data="00"/>
+ <value name="Multi.MinByEsc" type="hex" data="02"/>
+ <value name="MapShiftEscToEsc" type="hex" data="01"/>
+ <value name="Multi.Iterate" type="hex" data="01"/>
+ <value name="Multi.SplitWidth" type="hex" data="04"/>
+ <value name="Multi.SplitHeight" type="hex" data="04"/>
+ <value name="FontName" type="string" data="Consolas"/>
+ <value name="FontName2" type="string" data="Consolas"/>
+ <value name="FontAutoSize" type="hex" data="00"/>
+ <value name="FontSize" type="ulong" data="16"/>
+ <value name="FontSizeX" type="ulong" data="0"/>
+ <value name="FontSizeX2" type="ulong" data="0"/>
+ <value name="FontSizeX3" type="ulong" data="0"/>
+ <value name="FontCharSet" type="hex" data="cc"/>
+ <value name="Anti-aliasing" type="ulong" data="6"/>
+ <value name="FontBold" type="hex" data="00"/>
+ <value name="FontItalic" type="hex" data="00"/>
+ <value name="Monospace" type="hex" data="01"/>
+ <value name="BackGround Image show" type="hex" data="00"/>
+ <value name="BackGround Image" type="string" data="c:\back.bmp"/>
+ <value name="bgImageDarker" type="hex" data="ff"/>
+ <value name="bgImageColors" type="dword" data="ffffffff"/>
+ <value name="bgOperation" type="hex" data="00"/>
+ <value name="bgPluginAllowed" type="hex" data="01"/>
+ <value name="AlphaValue" type="hex" data="ff"/>
+ <value name="AlphaValueSeparate" type="hex" data="00"/>
+ <value name="AlphaValueInactive" type="hex" data="ff"/>
+ <value name="UserScreenTransparent" type="hex" data="00"/>
+ <value name="ColorKeyTransparent" type="hex" data="00"/>
+ <value name="ColorKeyValue" type="dword" data="00010101"/>
+ <value name="UseCurrentSizePos" type="hex" data="01"/>
+ <value name="WindowMode" type="dword" data="0000051f"/>
+ <value name="ConWnd Width" type="dword" data="00000050"/>
+ <value name="ConWnd Height" type="dword" data="00000019"/>
+ <value name="Cascaded" type="hex" data="01"/>
+ <value name="ConWnd X" type="long" data="164"/>
+ <value name="ConWnd Y" type="long" data="428"/>
+ <value name="16bit Height" type="ulong" data="0"/>
+ <value name="AutoSaveSizePos" type="hex" data="00"/>
+ <value name="IntegralSize" type="hex" data="00"/>
+ <value name="QuakeStyle" type="hex" data="00"/>
+ <value name="QuakeAnimation" type="ulong" data="300"/>
+ <value name="HideCaption" type="hex" data="00"/>
+ <value name="HideChildCaption" type="hex" data="01"/>
+ <value name="FocusInChildWindows" type="hex" data="01"/>
+ <value name="HideCaptionAlways" type="hex" data="00"/>
+ <value name="HideCaptionAlwaysFrame" type="hex" data="ff"/>
+ <value name="HideCaptionAlwaysDelay" type="ulong" data="2000"/>
+ <value name="HideCaptionAlwaysDisappear" type="ulong" data="2000"/>
+ <value name="DownShowHiddenMessage" type="hex" data="00"/>
+ <value name="ConsoleFontName" type="string" data="Lucida Console"/>
+ <value name="ConsoleFontWidth" type="long" data="3"/>
+ <value name="ConsoleFontHeight" type="long" data="5"/>
+ <value name="DefaultBufferHeight" type="long" data="1000"/>
+ <value name="AutoBufferHeight" type="hex" data="01"/>
+ <value name="CmdOutputCP" type="long" data="0"/>
+ <value name="ComSpec.Type" type="hex" data="00"/>
+ <value name="ComSpec.Bits" type="hex" data="00"/>
+ <value name="ComSpec.UpdateEnv" type="hex" data="00"/>
+ <value name="ComSpec.EnvAddPath" type="hex" data="01"/>
+ <value name="ComSpec.EnvAddExePath" type="hex" data="01"/>
+ <value name="ComSpec.UncPaths" type="hex" data="01"/>
+ <value name="ComSpec.Path" type="string" data=""/>
+ <value name="CTS.Intelligent" type="hex" data="01"/>
+ <value name="CTS.IntelligentExceptions" type="string" data="far|vim.exe"/>
+ <value name="CTS.AutoCopy" type="hex" data="01"/>
+ <value name="CTS.IBeam" type="hex" data="01"/>
+ <value name="CTS.EndOnTyping" type="hex" data="00"/>
+ <value name="CTS.EndOnKeyPress" type="hex" data="00"/>
+ <value name="CTS.Freeze" type="hex" data="00"/>
+ <value name="CTS.SelectBlock" type="hex" data="01"/>
+ <value name="CTS.SelectText" type="hex" data="01"/>
+ <value name="CTS.HtmlFormat" type="hex" data="00"/>
+ <value name="CTS.ActMode" type="hex" data="02"/>
+ <value name="CTS.RBtnAction" type="hex" data="03"/>
+ <value name="CTS.MBtnAction" type="hex" data="00"/>
+ <value name="CTS.ColorIndex" type="hex" data="e0"/>
+ <value name="ClipboardConfirmEnter" type="hex" data="01"/>
+ <value name="ClipboardConfirmLonger" type="ulong" data="200"/>
+ <value name="FarGotoEditorOpt" type="hex" data="01"/>
+ <value name="FarGotoEditorPath" type="string" data="far.exe /e%1:%2 &quot;%3&quot;"/>
+ <value name="HighlightMouseRow" type="hex" data="00"/>
+ <value name="HighlightMouseCol" type="hex" data="00"/>
+ <value name="FixFarBorders" type="hex" data="01"/>
+ <value name="FixFarBordersRanges" type="string" data="2013-25C4;"/>
+ <value name="ExtendUCharMap" type="hex" data="01"/>
+ <value name="EnhanceGraphics" type="hex" data="01"/>
+ <value name="EnhanceButtons" type="hex" data="00"/>
+ <value name="PartBrush75" type="hex" data="c8"/>
+ <value name="PartBrush50" type="hex" data="96"/>
+ <value name="PartBrush25" type="hex" data="5a"/>
+ <value name="PartBrushBlack" type="hex" data="20"/>
+ <value name="RightClick opens context menu" type="hex" data="02"/>
+ <value name="RightClickMacro2" type="string" data=""/>
+ <value name="SendAltTab" type="hex" data="00"/>
+ <value name="SendAltEsc" type="hex" data="00"/>
+ <value name="SendAltPrintScrn" type="hex" data="00"/>
+ <value name="SendPrintScrn" type="hex" data="00"/>
+ <value name="SendCtrlEsc" type="hex" data="00"/>
+ <value name="Min2Tray" type="hex" data="00"/>
+ <value name="AlwaysShowTrayIcon" type="hex" data="00"/>
+ <value name="SafeFarClose" type="hex" data="01"/>
+ <value name="SafeFarCloseMacro" type="string" data=""/>
+ <value name="FARuseASCIIsort" type="hex" data="00"/>
+ <value name="ShellNoZoneCheck" type="hex" data="00"/>
+ <value name="FixAltOnAltTab" type="hex" data="00"/>
+ <value name="DisableMouse" type="hex" data="00"/>
+ <value name="RSelectionFix" type="hex" data="01"/>
+ <value name="MouseSkipActivation" type="hex" data="01"/>
+ <value name="MouseSkipMoving" type="hex" data="01"/>
+ <value name="FarHourglass" type="hex" data="01"/>
+ <value name="FarHourglassDelay" type="ulong" data="500"/>
+ <value name="Dnd" type="hex" data="01"/>
+ <value name="DndDrop" type="hex" data="01"/>
+ <value name="DefCopy" type="hex" data="01"/>
+ <value name="DropUseMenu" type="hex" data="02"/>
+ <value name="DragOverlay" type="hex" data="01"/>
+ <value name="DragShowIcons" type="hex" data="01"/>
+ <value name="DebugSteps" type="hex" data="01"/>
+ <value name="DragPanel" type="hex" data="02"/>
+ <value name="DragPanelBothEdges" type="hex" data="00"/>
+ <value name="KeyBarRClick" type="hex" data="01"/>
+ <value name="StatusBar.Show" type="hex" data="01"/>
+ <value name="StatusBar.Flags" type="dword" data="00000002"/>
+ <value name="StatusFontFace" type="string" data="Segoe UI"/>
+ <value name="StatusFontCharSet" type="ulong" data="0"/>
+ <value name="StatusFontHeight" type="long" data="14"/>
+ <value name="StatusBar.Color.Back" type="dword" data="00404040"/>
+ <value name="StatusBar.Color.Light" type="dword" data="00ffffff"/>
+ <value name="StatusBar.Color.Dark" type="dword" data="00a0a0a0"/>
+ <value name="StatusBar.Hide.VCon" type="hex" data="00"/>
+ <value name="StatusBar.Hide.CapsL" type="hex" data="00"/>
+ <value name="StatusBar.Hide.NumL" type="hex" data="00"/>
+ <value name="StatusBar.Hide.ScrL" type="hex" data="00"/>
+ <value name="StatusBar.Hide.Lang" type="hex" data="01"/>
+ <value name="StatusBar.Hide.WPos" type="hex" data="01"/>
+ <value name="StatusBar.Hide.WSize" type="hex" data="01"/>
+ <value name="StatusBar.Hide.WClient" type="hex" data="01"/>
+ <value name="StatusBar.Hide.WWork" type="hex" data="01"/>
+ <value name="StatusBar.Hide.Style" type="hex" data="01"/>
+ <value name="StatusBar.Hide.StyleEx" type="hex" data="01"/>
+ <value name="StatusBar.Hide.hFore" type="hex" data="01"/>
+ <value name="StatusBar.Hide.hFocus" type="hex" data="01"/>
+ <value name="StatusBar.Hide.ABuf" type="hex" data="00"/>
+ <value name="StatusBar.Hide.CPos" type="hex" data="00"/>
+ <value name="StatusBar.Hide.CSize" type="hex" data="01"/>
+ <value name="StatusBar.Hide.BSize" type="hex" data="00"/>
+ <value name="StatusBar.Hide.CurX" type="hex" data="01"/>
+ <value name="StatusBar.Hide.CurY" type="hex" data="01"/>
+ <value name="StatusBar.Hide.CurS" type="hex" data="01"/>
+ <value name="StatusBar.Hide.CurI" type="hex" data="00"/>
+ <value name="StatusBar.Hide.ConEmuPID" type="hex" data="01"/>
+ <value name="StatusBar.Hide.ConEmuHWND" type="hex" data="01"/>
+ <value name="StatusBar.Hide.ConEmuView" type="hex" data="01"/>
+ <value name="StatusBar.Hide.Srv" type="hex" data="00"/>
+ <value name="StatusBar.Hide.SrvHWND" type="hex" data="01"/>
+ <value name="StatusBar.Hide.Transparency" type="hex" data="00"/>
+ <value name="StatusBar.Hide.New" type="hex" data="00"/>
+ <value name="StatusBar.Hide.Sync" type="hex" data="00"/>
+ <value name="StatusBar.Hide.Proc" type="hex" data="00"/>
+ <value name="StatusBar.Hide.Title" type="hex" data="01"/>
+ <value name="StatusBar.Hide.Time" type="hex" data="01"/>
+ <value name="StatusBar.Hide.Resize" type="hex" data="00"/>
+ <value name="Tabs" type="hex" data="01"/>
+ <value name="TabsLocation" type="hex" data="00"/>
+ <value name="TabIcons" type="hex" data="01"/>
+ <value name="OneTabPerGroup" type="hex" data="00"/>
+ <value name="ActivateSplitMouseOver" type="hex" data="02"/>
+ <value name="TabSelf" type="hex" data="01"/>
+ <value name="TabLazy" type="hex" data="01"/>
+ <value name="TabRecent" type="hex" data="01"/>
+ <value name="TabDblClick" type="ulong" data="1"/>
+ <value name="TabBtnDblClick" type="ulong" data="0"/>
+ <value name="TabsOnTaskBar" type="hex" data="02"/>
+ <value name="TaskBarOverlay" type="hex" data="01"/>
+ <value name="TaskbarProgress" type="hex" data="01"/>
+ <value name="TabCloseMacro" type="string" data=""/>
+ <value name="TabFontFace" type="string" data="Segoe UI"/>
+ <value name="TabFontCharSet" type="ulong" data="0"/>
+ <value name="TabFontHeight" type="long" data="16"/>
+ <value name="SaveAllEditors" type="string" data=""/>
+ <value name="ToolbarAddSpace" type="long" data="0"/>
+ <value name="TabConsole" type="string" data="&lt;%c&gt; %s"/>
+ <value name="TabSkipWords" type="string" data="Administrator:|Администратор:"/>
+ <value name="TabPanels" type="string" data="&lt;%c&gt; %s"/>
+ <value name="TabEditor" type="string" data="&lt;%c.%i&gt;{%s}"/>
+ <value name="TabEditorModified" type="string" data="&lt;%c.%i&gt;[%s] *"/>
+ <value name="TabViewer" type="string" data="&lt;%c.%i&gt;[%s]"/>
+ <value name="TabLenMax" type="ulong" data="20"/>
+ <value name="AdminTitleSuffix" type="string" data=" (Admin)"/>
+ <value name="AdminShowShield" type="hex" data="01"/>
+ <value name="HideInactiveConsoleTabs" type="hex" data="00"/>
+ <value name="ShowFarWindows" type="hex" data="01"/>
+ <value name="TryToCenter" type="hex" data="00"/>
+ <value name="CenterConsolePad" type="ulong" data="0"/>
+ <value name="ShowScrollbar" type="hex" data="02"/>
+ <value name="ScrollBarAppearDelay" type="ulong" data="100"/>
+ <value name="ScrollBarDisappearDelay" type="ulong" data="1000"/>
+ <value name="IconID" type="ulong" data="1"/>
+ <value name="MainTimerElapse" type="ulong" data="10"/>
+ <value name="MainTimerInactiveElapse" type="ulong" data="1000"/>
+ <value name="AffinityMask" type="dword" data="00000000"/>
+ <value name="SkipFocusEvents" type="hex" data="00"/>
+ <value name="MonitorConsoleLang" type="hex" data="03"/>
+ <value name="DesktopMode" type="hex" data="00"/>
+ <value name="SnapToDesktopEdges" type="hex" data="00"/>
+ <value name="AlwaysOnTop" type="hex" data="00"/>
+ <value name="SleepInBackground" type="hex" data="00"/>
+ <value name="RetardInactivePanes" type="hex" data="00"/>
+ <value name="MinimizeOnLoseFocus" type="hex" data="00"/>
+ <value name="DisableFarFlashing" type="hex" data="00"/>
+ <value name="DisableAllFlashing" type="hex" data="00"/>
+ <value name="FindText" type="string" data=""/>
+ <value name="FindMatchCase" type="hex" data="00"/>
+ <value name="FindMatchWholeWords" type="hex" data="00"/>
+ <value name="FindTransparent" type="hex" data="01"/>
+ <value name="PanView.BackColor" type="dword" data="30ffffff"/>
+ <value name="PanView.PFrame" type="long" data="1"/>
+ <value name="PanView.PFrameColor" type="dword" data="28808080"/>
+ <value name="PanView.SFrame" type="long" data="1"/>
+ <value name="PanView.SFrameColor" type="dword" data="07c0c0c0"/>
+ <value name="PanView.Thumbs.ImgSize" type="long" data="96"/>
+ <value name="PanView.Thumbs.SpaceX1" type="long" data="1"/>
+ <value name="PanView.Thumbs.SpaceY1" type="long" data="1"/>
+ <value name="PanView.Thumbs.SpaceX2" type="long" data="5"/>
+ <value name="PanView.Thumbs.SpaceY2" type="long" data="20"/>
+ <value name="PanView.Thumbs.LabelSpacing" type="long" data="2"/>
+ <value name="PanView.Thumbs.LabelPadding" type="long" data="0"/>
+ <value name="PanView.Thumbs.FontName" type="string" data="Segoe UI"/>
+ <value name="PanView.Thumbs.FontHeight" type="long" data="14"/>
+ <value name="PanView.Tiles.ImgSize" type="long" data="48"/>
+ <value name="PanView.Tiles.SpaceX1" type="long" data="4"/>
+ <value name="PanView.Tiles.SpaceY1" type="long" data="4"/>
+ <value name="PanView.Tiles.SpaceX2" type="long" data="172"/>
+ <value name="PanView.Tiles.SpaceY2" type="long" data="4"/>
+ <value name="PanView.Tiles.LabelSpacing" type="long" data="4"/>
+ <value name="PanView.Tiles.LabelPadding" type="long" data="1"/>
+ <value name="PanView.Tiles.FontName" type="string" data="Segoe UI"/>
+ <value name="PanView.Tiles.FontHeight" type="long" data="14"/>
+ <value name="PanView.LoadPreviews" type="hex" data="03"/>
+ <value name="PanView.LoadFolders" type="hex" data="01"/>
+ <value name="PanView.LoadTimeout" type="ulong" data="15"/>
+ <value name="PanView.MaxZoom" type="ulong" data="600"/>
+ <value name="PanView.UsePicView2" type="hex" data="01"/>
+ <value name="PanView.RestoreOnStartup" type="hex" data="00"/>
+ <value name="Update.VerLocation" type="string" data=""/>
+ <value name="Update.UseProxy" type="hex" data="00"/>
+ <value name="Update.Proxy" type="string" data=""/>
+ <value name="Update.ProxyUser" type="string" data=""/>
+ <value name="Update.ProxyPassword" type="string" data=""/>
+ <value name="Update.ExeCmdLine" type="string" data=""/>
+ <value name="Update.ArcCmdLine" type="string" data=""/>
+ <value name="Update.DownloadPath" type="string" data="%TEMP%\ConEmu"/>
+ <value name="Update.LeavePackages" type="hex" data="00"/>
+ <value name="Update.PostUpdateCmd" type="string" data="echo Last successful update&gt;ConEmuUpdate.info &amp;&amp; date /t&gt;&gt;ConEmuUpdate.info &amp;&amp; time /t&gt;&gt;ConEmuUpdate.info"/>
+ <value name="Multi.Modifier" type="dword" data="0000005b"/>
+ <value name="Multi.ArrowsModifier" type="dword" data="0000005b"/>
+ <value name="KeyMacroVersion" type="hex" data="02"/>
+ <value name="MinimizeRestore" type="dword" data="000011c0"/>
+ <value name="MinimizeRestore2" type="dword" data="00000000"/>
+ <value name="GlobalRestore" type="dword" data="00000000"/>
+ <value name="ForcedFullScreen" type="dword" data="125b110d"/>
+ <value name="SwitchGuiFocus" type="dword" data="00000000"/>
+ <value name="SetFocusGui" type="dword" data="00000000"/>
+ <value name="SetFocusChild" type="dword" data="00000000"/>
+ <value name="ChildSystemMenu" type="dword" data="00000000"/>
+ <value name="Multi.NewSplitV" type="dword" data="0010114f"/>
+ <value name="Multi.NewSplitH" type="dword" data="00101145"/>
+ <value name="Multi.SplitSizeVU" type="dword" data="00105d26"/>
+ <value name="Multi.SplitSizeVD" type="dword" data="00105d28"/>
+ <value name="Multi.SplitSizeHL" type="dword" data="00105d25"/>
+ <value name="Multi.SplitSizeHR" type="dword" data="00105d27"/>
+ <value name="Key.TabPane1" type="dword" data="00005d09"/>
+ <value name="Key.TabPane2" type="dword" data="00105d09"/>
+ <value name="Multi.SplitFocusU" type="dword" data="00005d26"/>
+ <value name="Multi.SplitFocusD" type="dword" data="00005d28"/>
+ <value name="Multi.SplitFocusL" type="dword" data="00005d25"/>
+ <value name="Multi.SplitFocusR" type="dword" data="00005d27"/>
+ <value name="Multi.NewConsole" type="dword" data="00005b57"/>
+ <value name="Multi.NewConsoleShift" type="dword" data="00105b57"/>
+ <value name="Multi.NewConsolePopup" type="dword" data="00005b4e"/>
+ <value name="Multi.NewConsolePopup2" type="dword" data="00000000"/>
+ <value name="Multi.NewWindow" type="dword" data="00000000"/>
+ <value name="Multi.NewAttach" type="dword" data="00005b47"/>
+ <value name="Multi.Next" type="dword" data="00005b51"/>
+ <value name="Multi.NextShift" type="dword" data="00105b51"/>
+ <value name="Multi.Recreate" type="dword" data="00005bc0"/>
+ <value name="Multi.AltCon" type="dword" data="00005b41"/>
+ <value name="Multi.Scroll" type="dword" data="00005b53"/>
+ <value name="Multi.Close" type="dword" data="00005b2e"/>
+ <value name="CloseTabKey" type="dword" data="00125b2e"/>
+ <value name="CloseGroupKey" type="dword" data="00000000"/>
+ <value name="CloseGroupPrcKey" type="dword" data="00000000"/>
+ <value name="CloseAllConKey" type="dword" data="00000000"/>
+ <value name="CloseExceptConKey" type="dword" data="00000000"/>
+ <value name="TerminateProcessKey" type="dword" data="00105b2e"/>
+ <value name="DuplicateRootKey" type="dword" data="00000000"/>
+ <value name="CloseConEmuKey" type="dword" data="00005b73"/>
+ <value name="Multi.Rename" type="dword" data="00005d52"/>
+ <value name="Multi.MoveLeft" type="dword" data="00125b25"/>
+ <value name="Multi.MoveRight" type="dword" data="00125b27"/>
+ <value name="Multi.CmdKey" type="dword" data="00005b58"/>
+ <value name="CTS.VkBlockStart" type="dword" data="00000000"/>
+ <value name="CTS.VkTextStart" type="dword" data="00000000"/>
+ <value name="CTS.VkCopyFmt0" type="dword" data="00001143"/>
+ <value name="CTS.VkCopyFmt1" type="dword" data="00101143"/>
+ <value name="CTS.VkCopyFmt2" type="dword" data="00000000"/>
+ <value name="CTS.VkCopyAll" type="dword" data="00000000"/>
+ <value name="HighlightMouseSwitch" type="dword" data="00005d4c"/>
+ <value name="Multi.ShowTabsList" type="dword" data="00000000"/>
+ <value name="Multi.ShowTabsList2" type="dword" data="00005d7b"/>
+ <value name="ClipboardVkAllLines" type="dword" data="0000102d"/>
+ <value name="ClipboardVkFirstLine" type="dword" data="00001156"/>
+ <value name="DeleteWordToLeft" type="dword" data="00001108"/>
+ <value name="FindTextKey" type="dword" data="00005d46"/>
+ <value name="ScreenshotKey" type="dword" data="00005b48"/>
+ <value name="ScreenshotFullKey" type="dword" data="00105b48"/>
+ <value name="ShowStatusBarKey" type="dword" data="00005d53"/>
+ <value name="ShowTabBarKey" type="dword" data="00005d54"/>
+ <value name="ShowCaptionKey" type="dword" data="00005d43"/>
+ <value name="AlwaysOnTopKey" type="dword" data="00000000"/>
+ <value name="TransparencyInc" type="dword" data="00000000"/>
+ <value name="TransparencyDec" type="dword" data="00000000"/>
+ <value name="Key.TabMenu" type="dword" data="00005d20"/>
+ <value name="Key.TabMenu2" type="dword" data="00001002"/>
+ <value name="Key.Maximize" type="dword" data="00001278"/>
+ <value name="Key.MaximizeWidth" type="dword" data="00000000"/>
+ <value name="Key.MaximizeHeight" type="dword" data="00000000"/>
+ <value name="Key.FullScreen" type="dword" data="0000120d"/>
+ <value name="Key.SysMenu" type="dword" data="00001220"/>
+ <value name="Key.SysMenu2" type="dword" data="00001102"/>
+ <value name="Key.BufUp" type="dword" data="00001126"/>
+ <value name="Key.BufDn" type="dword" data="00001128"/>
+ <value name="Key.BufPgUp" type="dword" data="00001121"/>
+ <value name="Key.BufPgDn" type="dword" data="00001122"/>
+ <value name="Key.PicViewSlide" type="dword" data="80808013"/>
+ <value name="Key.PicViewSlower" type="dword" data="808080bd"/>
+ <value name="Key.PicViewFaster" type="dword" data="808080bb"/>
+ <value name="FontLargerKey" type="dword" data="000011d0"/>
+ <value name="FontSmallerKey" type="dword" data="000011d1"/>
+ <value name="PasteFileKey" type="dword" data="00101146"/>
+ <value name="PastePathKey" type="dword" data="00101144"/>
+ <value name="PasteCygwinKey" type="dword" data="00005d2d"/>
+ <value name="Key.JumpPrevMonitor" type="dword" data="00105b25"/>
+ <value name="Key.JumpNextMonitor" type="dword" data="00105b27"/>
+ <value name="Key.TileToLeft" type="dword" data="00005b25"/>
+ <value name="Key.TileToRIght" type="dword" data="00005b27"/>
+ <value name="KeyMacro01" type="dword" data="00000000"/>
+ <value name="KeyMacro01.Text" type="string" data=""/>
+ <value name="KeyMacro02" type="dword" data="00000000"/>
+ <value name="KeyMacro02.Text" type="string" data=""/>
+ <value name="KeyMacro03" type="dword" data="00000000"/>
+ <value name="KeyMacro03.Text" type="string" data=""/>
+ <value name="KeyMacro04" type="dword" data="00000000"/>
+ <value name="KeyMacro04.Text" type="string" data=""/>
+ <value name="KeyMacro05" type="dword" data="00000000"/>
+ <value name="KeyMacro05.Text" type="string" data=""/>
+ <value name="KeyMacro06" type="dword" data="00000000"/>
+ <value name="KeyMacro06.Text" type="string" data=""/>
+ <value name="KeyMacro07" type="dword" data="00000000"/>
+ <value name="KeyMacro07.Text" type="string" data=""/>
+ <value name="KeyMacro08" type="dword" data="00000000"/>
+ <value name="KeyMacro08.Text" type="string" data=""/>
+ <value name="KeyMacro09" type="dword" data="00000000"/>
+ <value name="KeyMacro09.Text" type="string" data=""/>
+ <value name="KeyMacro10" type="dword" data="00000000"/>
+ <value name="KeyMacro10.Text" type="string" data=""/>
+ <value name="KeyMacro11" type="dword" data="00000000"/>
+ <value name="KeyMacro11.Text" type="string" data=""/>
+ <value name="KeyMacro12" type="dword" data="00000000"/>
+ <value name="KeyMacro12.Text" type="string" data=""/>
+ <value name="KeyMacro13" type="dword" data="00000000"/>
+ <value name="KeyMacro13.Text" type="string" data=""/>
+ <value name="KeyMacro14" type="dword" data="00000000"/>
+ <value name="KeyMacro14.Text" type="string" data=""/>
+ <value name="KeyMacro15" type="dword" data="00000000"/>
+ <value name="KeyMacro15.Text" type="string" data=""/>
+ <value name="KeyMacro16" type="dword" data="00000000"/>
+ <value name="KeyMacro16.Text" type="string" data=""/>
+ <value name="KeyMacro17" type="dword" data="00000000"/>
+ <value name="KeyMacro17.Text" type="string" data=""/>
+ <value name="KeyMacro18" type="dword" data="00000000"/>
+ <value name="KeyMacro18.Text" type="string" data=""/>
+ <value name="KeyMacro19" type="dword" data="00000000"/>
+ <value name="KeyMacro19.Text" type="string" data=""/>
+ <value name="KeyMacro20" type="dword" data="00000000"/>
+ <value name="KeyMacro20.Text" type="string" data=""/>
+ <value name="KeyMacro21" type="dword" data="00000000"/>
+ <value name="KeyMacro21.Text" type="string" data=""/>
+ <value name="KeyMacro22" type="dword" data="00000000"/>
+ <value name="KeyMacro22.Text" type="string" data=""/>
+ <value name="KeyMacro23" type="dword" data="00000000"/>
+ <value name="KeyMacro23.Text" type="string" data=""/>
+ <value name="KeyMacro24" type="dword" data="00000000"/>
+ <value name="KeyMacro24.Text" type="string" data=""/>
+ <value name="KeyMacro25" type="dword" data="00000000"/>
+ <value name="KeyMacro25.Text" type="string" data=""/>
+ <value name="KeyMacro26" type="dword" data="00000000"/>
+ <value name="KeyMacro26.Text" type="string" data=""/>
+ <value name="KeyMacro27" type="dword" data="00000000"/>
+ <value name="KeyMacro27.Text" type="string" data=""/>
+ <value name="KeyMacro28" type="dword" data="00000000"/>
+ <value name="KeyMacro28.Text" type="string" data=""/>
+ <value name="KeyMacro29" type="dword" data="00000000"/>
+ <value name="KeyMacro29.Text" type="string" data=""/>
+ <value name="KeyMacro30" type="dword" data="00000000"/>
+ <value name="KeyMacro30.Text" type="string" data=""/>
+ <value name="KeyMacro31" type="dword" data="00000000"/>
+ <value name="KeyMacro31.Text" type="string" data=""/>
+ <value name="KeyMacro32" type="dword" data="00000000"/>
+ <value name="KeyMacro32.Text" type="string" data=""/>
+ <value name="CTS.VkBlock" type="hex" data="a4"/>
+ <value name="CTS.VkText" type="hex" data="a0"/>
+ <value name="CTS.VkAct" type="hex" data="00"/>
+ <value name="CTS.VkPrompt" type="hex" data="00"/>
+ <value name="FarGotoEditorVk" type="hex" data="a2"/>
+ <value name="DndLKey" type="hex" data="00"/>
+ <value name="DndRKey" type="hex" data="a2"/>
+ <value name="WndDragKey" type="dword" data="00121101"/>
+ <value name="StartCreateDelay" type="ulong" data="100"/>
+ <value name="VividColors" type="hex" data="01"/>
+ <value name="DefaultTerminalAgressive" type="hex" data="01"/>
+ <value name="DefaultTerminalDebugLog" type="hex" data="00"/>
+ <value name="AnsiExecution" type="hex" data="01"/>
+ <value name="AnsiAllowedCommands" type="multi">
+ <line data="cmd -cur_console:R /cGitShowBranch.cmd"/>
+ </value>
+ <value name="ProcessCmdStart" type="hex" data="00"/>
+ <value name="ProcessCtrlZ" type="hex" data="00"/>
+ <value name="SuppressBells" type="hex" data="01"/>
+ <value name="JumpListAutoUpdate" type="hex" data="01"/>
+ <value name="Multi.ShowSearch" type="hex" data="01"/>
+ <value name="Multi.CloseConfirmFlags" type="hex" data="07"/>
+ <value name="Multi.DupConfirm" type="hex" data="01"/>
+ <value name="Multi.DetachConfirm" type="hex" data="01"/>
+ <value name="FontUseDpi" type="hex" data="01"/>
+ <value name="FontUseUnits" type="hex" data="00"/>
+ <value name="CompressLongStrings" type="hex" data="01"/>
+ <value name="LastMonitor" type="string" data="0,0,2880,1540"/>
+ <value name="Restore2ActiveMon" type="hex" data="00"/>
+ <value name="DownShowExOnTopMessage" type="hex" data="00"/>
+ <value name="UseScrollLock" type="hex" data="01"/>
+ <value name="EnvironmentSet" type="multi">
+ <line data="set PATH=%ConEmuBaseDir%\Scripts;%PATH%"/>
+ </value>
+ <value name="CTS.ResetOnRelease" type="hex" data="00"/>
+ <value name="CTS.EraseBeforeReset" type="hex" data="01"/>
+ <value name="CTS.ForceLocale" type="dword" data="00000000"/>
+ <value name="Anti-aliasing2" type="hex" data="00"/>
+ <value name="UseAltGrayPlus" type="hex" data="01"/>
+ <value name="MouseDragWindow" type="hex" data="01"/>
+ <value name="DebugLog" type="hex" data="00"/>
+ <value name="StatusBar.Hide.VisL" type="hex" data="01"/>
+ <value name="StatusBar.Hide.KeyHooks" type="hex" data="01"/>
+ <value name="StatusBar.Hide.TMode" type="hex" data="01"/>
+ <value name="StatusBar.Hide.RMode" type="hex" data="01"/>
+ <value name="StatusBar.Hide.WVBack" type="hex" data="01"/>
+ <value name="StatusBar.Hide.WVDC" type="hex" data="01"/>
+ <value name="StatusBar.Hide.Zoom" type="hex" data="01"/>
+ <value name="StatusBar.Hide.Dpi" type="hex" data="01"/>
+ <value name="TabFlashChanged" type="long" data="8"/>
+ <value name="TabModifiedSuffix" type="string" data="[*]"/>
+ <value name="Update.InetTool" type="hex" data="00"/>
+ <value name="Update.InetToolCmd" type="string" data=""/>
+ <key name="HotKeys" modified="2016-08-05 15:29:11" build="160724">
+ <value name="KeyMacroVersion" type="hex" data="02"/>
+ <value name="Multi.Modifier" type="dword" data="0000005b"/>
+ <value name="Multi.ArrowsModifier" type="dword" data="0000005b"/>
+ <value name="MinimizeRestore" type="dword" data="000011c0"/>
+ <value name="MinimizeRestore2" type="dword" data="00000000"/>
+ <value name="GlobalRestore" type="dword" data="00000000"/>
+ <value name="CdExplorerPath" type="dword" data="00000000"/>
+ <value name="ForcedFullScreen" type="dword" data="12115b0d"/>
+ <value name="SwitchGuiFocus" type="dword" data="00000000"/>
+ <value name="SetFocusGui" type="dword" data="00000000"/>
+ <value name="SetFocusChild" type="dword" data="00000000"/>
+ <value name="ChildSystemMenu" type="dword" data="00000000"/>
+ <value name="Multi.NewConsole" type="dword" data="00005b57"/>
+ <value name="Multi.NewConsoleShift" type="dword" data="00105b57"/>
+ <value name="Multi.CmdKey" type="dword" data="00005b58"/>
+ <value name="Multi.NewWindow" type="dword" data="00000000"/>
+ <value name="Multi.NewConsolePopup" type="dword" data="00005b4e"/>
+ <value name="Multi.NewConsolePopup2" type="dword" data="00000000"/>
+ <value name="Multi.NewAttach" type="dword" data="00005b47"/>
+ <value name="Multi.NewSplitV" type="dword" data="0010114f"/>
+ <value name="Multi.NewSplitH" type="dword" data="00101145"/>
+ <value name="Multi.SplitMaximize" type="dword" data="00005d0d"/>
+ <value name="Multi.SplitSizeVU" type="dword" data="00105d26"/>
+ <value name="Multi.SplitSizeVD" type="dword" data="00105d28"/>
+ <value name="Multi.SplitSizeHL" type="dword" data="00105d25"/>
+ <value name="Multi.SplitSizeHR" type="dword" data="00105d27"/>
+ <value name="Key.TabPane1" type="dword" data="00005d09"/>
+ <value name="Key.TabPane2" type="dword" data="00105d09"/>
+ <value name="Multi.SplitFocusU" type="dword" data="00005d26"/>
+ <value name="Multi.SplitFocusD" type="dword" data="00005d28"/>
+ <value name="Multi.SplitFocusL" type="dword" data="00005d25"/>
+ <value name="Multi.SplitFocusR" type="dword" data="00005d27"/>
+ <value name="Multi.Next" type="dword" data="00005b51"/>
+ <value name="Multi.NextShift" type="dword" data="00105b51"/>
+ <value name="Multi.Recreate" type="dword" data="00005bc0"/>
+ <value name="Multi.AltCon" type="dword" data="00005b41"/>
+ <value name="Multi.Pause" type="dword" data="80808013"/>
+ <value name="Multi.Scroll" type="dword" data="00005b53"/>
+ <value name="Multi.GroupInput" type="dword" data="00005d47"/>
+ <value name="Multi.Detach" type="dword" data="00000000"/>
+ <value name="Multi.Unfasten" type="dword" data="00000000"/>
+ <value name="Multi.Close" type="dword" data="00005b2e"/>
+ <value name="CloseTabKey" type="dword" data="00125b2e"/>
+ <value name="CloseGroupKey" type="dword" data="00000000"/>
+ <value name="CloseGroupPrcKey" type="dword" data="00000000"/>
+ <value name="CloseAllConKey" type="dword" data="00000000"/>
+ <value name="CloseZombiesKey" type="dword" data="00000000"/>
+ <value name="CloseExceptConKey" type="dword" data="00000000"/>
+ <value name="KillProcessKey" type="dword" data="00121103"/>
+ <value name="KillAllButShellKey" type="dword" data="00125b13"/>
+ <value name="DuplicateRootKey" type="dword" data="00000000"/>
+ <value name="CloseConEmuKey" type="dword" data="00005b73"/>
+ <value name="Multi.Rename" type="dword" data="00005d52"/>
+ <value name="AffinityPriorityKey" type="dword" data="00005d41"/>
+ <value name="Multi.MoveLeft" type="dword" data="00125b25"/>
+ <value name="Multi.MoveRight" type="dword" data="00125b27"/>
+ <value name="CTS.VkBlockStart" type="dword" data="00000000"/>
+ <value name="CTS.VkTextStart" type="dword" data="00000000"/>
+ <value name="CTS.VkCopyFmt0" type="dword" data="00001143"/>
+ <value name="CTS.VkCopyFmt1" type="dword" data="00101143"/>
+ <value name="CTS.VkCopyFmt2" type="dword" data="00000000"/>
+ <value name="CTS.VkCopyAll" type="dword" data="00000000"/>
+ <value name="HighlightMouseSwitch" type="dword" data="00005d4c"/>
+ <value name="HighlightMouseSwitchX" type="dword" data="00005d58"/>
+ <value name="Multi.ShowTabsList" type="dword" data="00000000"/>
+ <value name="Multi.ShowTabsList2" type="dword" data="00005d7b"/>
+ <value name="ClipboardVkAllLines" type="dword" data="0000102d"/>
+ <value name="ClipboardVkFirstLine" type="dword" data="00001156"/>
+ <value name="Key.AltNumpad" type="dword" data="00000000"/>
+ <value name="DeleteWordToLeft" type="dword" data="00001108"/>
+ <value name="FindTextKey" type="dword" data="00005d46"/>
+ <value name="ScreenshotKey" type="dword" data="00005b48"/>
+ <value name="ScreenshotFullKey" type="dword" data="00105b48"/>
+ <value name="ShowStatusBarKey" type="dword" data="00005d53"/>
+ <value name="ShowTabBarKey" type="dword" data="00005d54"/>
+ <value name="ShowCaptionKey" type="dword" data="00005d43"/>
+ <value name="AlwaysOnTopKey" type="dword" data="00000000"/>
+ <value name="TransparencyInc" type="dword" data="00000000"/>
+ <value name="TransparencyDec" type="dword" data="00000000"/>
+ <value name="Key.TabMenu" type="dword" data="00005d20"/>
+ <value name="Key.TabMenu2" type="dword" data="00001002"/>
+ <value name="Key.Maximize" type="dword" data="00001278"/>
+ <value name="Key.MaximizeWidth" type="dword" data="00000000"/>
+ <value name="Key.MaximizeHeight" type="dword" data="00000000"/>
+ <value name="Key.TileToLeft" type="dword" data="00005b25"/>
+ <value name="Key.TileToRight" type="dword" data="00005b27"/>
+ <value name="Key.JumpActiveMonitor" type="dword" data="00000000"/>
+ <value name="Key.JumpPrevMonitor" type="dword" data="00105b25"/>
+ <value name="Key.JumpNextMonitor" type="dword" data="00105b27"/>
+ <value name="Key.FullScreen" type="dword" data="0000120d"/>
+ <value name="Key.SysMenu" type="dword" data="00001220"/>
+ <value name="Key.SysMenu2" type="dword" data="00001102"/>
+ <value name="Key.DebugProcess" type="dword" data="00105b44"/>
+ <value name="Key.DumpProcess" type="dword" data="00000000"/>
+ <value name="Key.DumpTree" type="dword" data="00000000"/>
+ <value name="Key.BufUp" type="dword" data="00001126"/>
+ <value name="Key.BufDn" type="dword" data="00001128"/>
+ <value name="Key.BufPgUp" type="dword" data="00001121"/>
+ <value name="Key.BufPgDn" type="dword" data="00001122"/>
+ <value name="Key.BufHfPgUp" type="dword" data="00005d21"/>
+ <value name="Key.BufHfPgDn" type="dword" data="00005d22"/>
+ <value name="Key.BufTop" type="dword" data="00005d24"/>
+ <value name="Key.BufBottom" type="dword" data="00005d23"/>
+ <value name="Key.BufCursor" type="dword" data="00005d08"/>
+ <value name="Key.ResetTerm" type="dword" data="00000000"/>
+ <value name="FontLargerKey" type="dword" data="000011d0"/>
+ <value name="FontSmallerKey" type="dword" data="000011d1"/>
+ <value name="FontOriginalKey" type="dword" data="00001104"/>
+ <value name="PasteFileKey" type="dword" data="00101146"/>
+ <value name="PastePathKey" type="dword" data="00101144"/>
+ <value name="PasteCygwinKey" type="dword" data="00005d2d"/>
+ <value name="KeyMacro01" type="dword" data="00000000"/>
+ <value name="KeyMacro01.Text" type="string" data=""/>
+ <value name="KeyMacro02" type="dword" data="00000000"/>
+ <value name="KeyMacro02.Text" type="string" data=""/>
+ <value name="KeyMacro03" type="dword" data="00000000"/>
+ <value name="KeyMacro03.Text" type="string" data=""/>
+ <value name="KeyMacro04" type="dword" data="00000000"/>
+ <value name="KeyMacro04.Text" type="string" data=""/>
+ <value name="KeyMacro05" type="dword" data="00000000"/>
+ <value name="KeyMacro05.Text" type="string" data=""/>
+ <value name="KeyMacro06" type="dword" data="00000000"/>
+ <value name="KeyMacro06.Text" type="string" data=""/>
+ <value name="KeyMacro07" type="dword" data="00000000"/>
+ <value name="KeyMacro07.Text" type="string" data=""/>
+ <value name="KeyMacro08" type="dword" data="00000000"/>
+ <value name="KeyMacro08.Text" type="string" data=""/>
+ <value name="KeyMacro09" type="dword" data="00000000"/>
+ <value name="KeyMacro09.Text" type="string" data=""/>
+ <value name="KeyMacro10" type="dword" data="00000000"/>
+ <value name="KeyMacro10.Text" type="string" data=""/>
+ <value name="KeyMacro11" type="dword" data="00000000"/>
+ <value name="KeyMacro11.Text" type="string" data=""/>
+ <value name="KeyMacro12" type="dword" data="00000000"/>
+ <value name="KeyMacro12.Text" type="string" data=""/>
+ <value name="KeyMacro13" type="dword" data="00000000"/>
+ <value name="KeyMacro13.Text" type="string" data=""/>
+ <value name="KeyMacro14" type="dword" data="00000000"/>
+ <value name="KeyMacro14.Text" type="string" data=""/>
+ <value name="KeyMacro15" type="dword" data="00000000"/>
+ <value name="KeyMacro15.Text" type="string" data=""/>
+ <value name="KeyMacro16" type="dword" data="00000000"/>
+ <value name="KeyMacro16.Text" type="string" data=""/>
+ <value name="KeyMacro17" type="dword" data="00000000"/>
+ <value name="KeyMacro17.Text" type="string" data=""/>
+ <value name="KeyMacro18" type="dword" data="00000000"/>
+ <value name="KeyMacro18.Text" type="string" data=""/>
+ <value name="KeyMacro19" type="dword" data="00000000"/>
+ <value name="KeyMacro19.Text" type="string" data=""/>
+ <value name="KeyMacro20" type="dword" data="00000000"/>
+ <value name="KeyMacro20.Text" type="string" data=""/>
+ <value name="KeyMacro21" type="dword" data="00000000"/>
+ <value name="KeyMacro21.Text" type="string" data=""/>
+ <value name="KeyMacro22" type="dword" data="00000000"/>
+ <value name="KeyMacro22.Text" type="string" data=""/>
+ <value name="KeyMacro23" type="dword" data="00000000"/>
+ <value name="KeyMacro23.Text" type="string" data=""/>
+ <value name="KeyMacro24" type="dword" data="00000000"/>
+ <value name="KeyMacro24.Text" type="string" data=""/>
+ <value name="KeyMacro25" type="dword" data="00000000"/>
+ <value name="KeyMacro25.Text" type="string" data=""/>
+ <value name="KeyMacro26" type="dword" data="00000000"/>
+ <value name="KeyMacro26.Text" type="string" data=""/>
+ <value name="KeyMacro27" type="dword" data="00000000"/>
+ <value name="KeyMacro27.Text" type="string" data=""/>
+ <value name="KeyMacro28" type="dword" data="00000000"/>
+ <value name="KeyMacro28.Text" type="string" data=""/>
+ <value name="KeyMacro29" type="dword" data="00000000"/>
+ <value name="KeyMacro29.Text" type="string" data=""/>
+ <value name="KeyMacro30" type="dword" data="00000000"/>
+ <value name="KeyMacro30.Text" type="string" data=""/>
+ <value name="KeyMacro31" type="dword" data="00000000"/>
+ <value name="KeyMacro31.Text" type="string" data=""/>
+ <value name="KeyMacro32" type="dword" data="00000000"/>
+ <value name="KeyMacro32.Text" type="string" data=""/>
+ <value name="CTS.VkBlock" type="hex" data="a4"/>
+ <value name="CTS.VkText" type="hex" data="a0"/>
+ <value name="CTS.VkAct" type="hex" data="00"/>
+ <value name="CTS.VkPrompt" type="hex" data="00"/>
+ <value name="FarGotoEditorVk" type="hex" data="a2"/>
+ <value name="DndLKey" type="hex" data="00"/>
+ <value name="DndRKey" type="hex" data="a2"/>
+ <value name="WndDragKey" type="dword" data="00121101"/>
+ </key>
+ <key name="Tasks" modified="2016-08-05 15:29:11" build="160724">
+ <value name="Count" type="long" data="14"/>
+ <!-- MOZ: This task launches Mozilla's MSYS2 development enviornment -->
+ <key name="Task1" modified="2016-08-05 15:29:11" build="160724">
+ <value name="Name" type="string" data="{Bash::mozdev}"/>
+ <value name="Flags" type="dword" data="00000005"/>
+ <value name="Hotkey" type="dword" data="00000000"/>
+ <value name="GuiArgs" type="string" data=""/>
+ <value name="Cmd1" type="string" data="set CHERE_INVOKING=1 &amp; set MSYSTEM=MINGW64 &amp; %MSYS2_PATH\usr\bin\bash.exe --login -i -new_console:C:&quot;%MSYS2_PATH\msys2.ico&quot;"/>
+ <value name="Active" type="long" data="0"/>
+ <value name="Count" type="long" data="1"/>
+ </key>
+ <!-- MOZ: End of Mozilla code. -->
+ <key name="Task2" modified="2016-08-05 15:29:11" build="160724">
+ <value name="Name" type="string" data="{Shells::cmd}"/>
+ <value name="Flags" type="dword" data="00000002"/>
+ <value name="Hotkey" type="dword" data="00000000"/>
+ <value name="GuiArgs" type="string" data=""/>
+ <value name="Cmd1" type="string" data="cmd.exe /k &quot;%ConEmuBaseDir%\CmdInit.cmd&quot;"/>
+ <value name="Active" type="long" data="0"/>
+ <value name="Count" type="long" data="1"/>
+ </key>
+ <key name="Task3" modified="2016-08-05 15:29:11" build="160724">
+ <value name="Name" type="string" data="{Shells::cmd (Admin)}"/>
+ <value name="Flags" type="dword" data="00000004"/>
+ <value name="Hotkey" type="dword" data="00000000"/>
+ <value name="GuiArgs" type="string" data=""/>
+ <value name="Cmd1" type="string" data="cmd.exe /k &quot;%ConEmuBaseDir%\CmdInit.cmd&quot; -new_console:a"/>
+ <value name="Active" type="long" data="0"/>
+ <value name="Count" type="long" data="1"/>
+ </key>
+ <key name="Task4" modified="2016-08-05 15:29:11" build="160724">
+ <value name="Name" type="string" data="{Shells::cmd-32}"/>
+ <value name="Flags" type="dword" data="00000004"/>
+ <value name="Hotkey" type="dword" data="00000000"/>
+ <value name="GuiArgs" type="string" data=""/>
+ <value name="Cmd1" type="string" data="&quot;%windir%\syswow64\cmd.exe&quot; /k &quot;%ConEmuBaseDir%\CmdInit.cmd&quot;"/>
+ <value name="Active" type="long" data="0"/>
+ <value name="Count" type="long" data="1"/>
+ </key>
+ <key name="Task5" modified="2016-08-05 15:29:11" build="160724">
+ <value name="Name" type="string" data="{Shells::cmd 64/32}"/>
+ <value name="Flags" type="dword" data="00000004"/>
+ <value name="Hotkey" type="dword" data="00000000"/>
+ <value name="GuiArgs" type="string" data=""/>
+ <value name="Cmd1" type="string" data="&gt; &quot;%windir%\system32\cmd.exe&quot; /k &quot;&quot;%ConEmuBaseDir%\CmdInit.cmd&quot; &amp; echo This is Native cmd.exe&quot;"/>
+ <value name="Cmd2" type="string" data="&quot;%windir%\syswow64\cmd.exe&quot; /k &quot;&quot;%ConEmuBaseDir%\CmdInit.cmd&quot; &amp; echo This is 32 bit cmd.exe -new_console:s50V&quot;"/>
+ <value name="Active" type="long" data="1"/>
+ <value name="Count" type="long" data="2"/>
+ </key>
+ <key name="Task6" modified="2016-08-05 15:29:11" build="160724">
+ <value name="Name" type="string" data="{Shells::PowerShell}"/>
+ <value name="Flags" type="dword" data="00000004"/>
+ <value name="Hotkey" type="dword" data="00000000"/>
+ <value name="GuiArgs" type="string" data=""/>
+ <value name="Cmd1" type="string" data="powershell.exe"/>
+ <value name="Active" type="long" data="0"/>
+ <value name="Count" type="long" data="1"/>
+ </key>
+ <key name="Task7" modified="2016-08-05 15:29:11" build="160724">
+ <value name="Name" type="string" data="{Shells::PowerShell (Admin)}"/>
+ <value name="Flags" type="dword" data="00000004"/>
+ <value name="Hotkey" type="dword" data="00000000"/>
+ <value name="GuiArgs" type="string" data=""/>
+ <value name="Cmd1" type="string" data="powershell.exe -new_console:a"/>
+ <value name="Active" type="long" data="0"/>
+ <value name="Count" type="long" data="1"/>
+ </key>
+ <key name="Task8" modified="2016-08-05 15:29:11" build="160724">
+ <value name="Name" type="string" data="{Bash::bash}"/>
+ <value name="Flags" type="dword" data="00000004"/>
+ <value name="Hotkey" type="dword" data="00000000"/>
+ <value name="GuiArgs" type="string" data="-icon &quot;%USERPROFILE%\AppData\Local\lxss\bash.ico&quot;"/>
+ <value name="Cmd1" type="string" data="%windir%\system32\bash.exe -cur_console:p"/>
+ <value name="Active" type="long" data="0"/>
+ <value name="Count" type="long" data="1"/>
+ </key>
+ <key name="Task9" modified="2016-08-05 15:29:11" build="160724">
+ <value name="Name" type="string" data="{Bash::Msys2-64}"/>
+ <value name="Flags" type="dword" data="00000004"/>
+ <value name="Hotkey" type="dword" data="00000000"/>
+ <value name="GuiArgs" type="string" data=""/>
+ <value name="Cmd1" type="string" data="set CHERE_INVOKING=1 &amp; %ConEmuDrive%\msys64\usr\bin\bash.exe --login -i -new_console:C:&quot;%ConEmuDrive%\msys64\msys2.ico&quot;"/>
+ <value name="Active" type="long" data="0"/>
+ <value name="Count" type="long" data="1"/>
+ </key>
+ <key name="Task10" modified="2016-08-05 15:29:11" build="160724">
+ <value name="Name" type="string" data="{Helper::Show ANSI colors}"/>
+ <value name="Flags" type="dword" data="00000004"/>
+ <value name="Hotkey" type="dword" data="00000000"/>
+ <value name="GuiArgs" type="string" data=""/>
+ <value name="Cmd1" type="string" data="cmd.exe /k type &quot;%ConEmuBaseDir%\Addons\AnsiColors16t.ans&quot; -cur_console:n"/>
+ <value name="Active" type="long" data="0"/>
+ <value name="Count" type="long" data="1"/>
+ </key>
+ <key name="Task11" modified="2016-08-05 15:29:11" build="160724">
+ <value name="Name" type="string" data="{SDK::VS 11.0 x86 tools prompt}"/>
+ <value name="Flags" type="dword" data="00000004"/>
+ <value name="Hotkey" type="dword" data="00000000"/>
+ <value name="GuiArgs" type="string" data=""/>
+ <value name="Cmd1" type="string" data="cmd /k &quot;&quot;C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\vcvarsall.bat&quot;&quot; x86 -new_console:t:&quot;VS 11.0&quot; -new_console:C:&quot;%CommonProgramFiles(x86)%\microsoft shared\MSEnv\VSFileHandler.dll,23&quot;"/>
+ <value name="Active" type="long" data="0"/>
+ <value name="Count" type="long" data="1"/>
+ </key>
+ <key name="Task12" modified="2016-08-05 15:29:11" build="160724">
+ <value name="Name" type="string" data="{SDK::VS 12.0 x86 tools prompt}"/>
+ <value name="Flags" type="dword" data="00000004"/>
+ <value name="Hotkey" type="dword" data="00000000"/>
+ <value name="GuiArgs" type="string" data=""/>
+ <value name="Cmd1" type="string" data="cmd /k &quot;&quot;C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat&quot;&quot; x86 -new_console:t:&quot;VS 12.0&quot; -new_console:C:&quot;%CommonProgramFiles(x86)%\microsoft shared\MSEnv\VSFileHandler.dll,28&quot;"/>
+ <value name="Active" type="long" data="0"/>
+ <value name="Count" type="long" data="1"/>
+ </key>
+ <key name="Task13" modified="2016-08-05 15:29:11" build="160724">
+ <value name="Name" type="string" data="{SDK::VS 14.0 x86 tools prompt}"/>
+ <value name="Flags" type="dword" data="00000004"/>
+ <value name="Hotkey" type="dword" data="00000000"/>
+ <value name="GuiArgs" type="string" data=""/>
+ <value name="Cmd1" type="string" data="cmd /k &quot;&quot;C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat&quot;&quot; x86 -new_console:t:&quot;VS 14.0&quot; -new_console:C:&quot;%CommonProgramFiles(x86)%\microsoft shared\MSEnv\VSFileHandler.dll,33&quot;"/>
+ <value name="Active" type="long" data="0"/>
+ <value name="Count" type="long" data="1"/>
+ </key>
+ <key name="Task14" modified="2016-08-05 15:29:11" build="160724">
+ <value name="Name" type="string" data="{Tools::Chocolatey (Admin)}"/>
+ <value name="Flags" type="dword" data="00000004"/>
+ <value name="Hotkey" type="dword" data="00000000"/>
+ <value name="GuiArgs" type="string" data=""/>
+ <value name="Cmd1" type="string" data="*cmd.exe /k Title Chocolatey &amp; &quot;%ConEmuBaseDir%\Addons\ChocolateyAbout.cmd&quot;"/>
+ <value name="Active" type="long" data="0"/>
+ <value name="Count" type="long" data="1"/>
+ </key>
+ </key>
+ <key name="Apps" modified="2016-08-05 15:29:11" build="160724">
+ <value name="Count" type="long" data="0"/>
+ </key>
+ <key name="Colors" modified="2016-08-05 15:29:11" build="160724">
+ <value name="Count" type="long" data="0"/>
+ </key>
+ </key>
+ </key>
+</key>