1# This Source Code Form is subject to the terms of the Mozilla Public 2# License, v. 2.0. If a copy of the MPL was not distributed with this 3# file, You can obtain one at http://mozilla.org/MPL/2.0/. 4 5from __future__ import absolute_import, print_function 6 7import os 8import sys 9import tempfile 10import subprocess 11import glob 12 13from mozboot.base import BaseBootstrapper 14from mozboot.linux_common import StyloInstall 15 16 17class ArchlinuxBootstrapper(StyloInstall, BaseBootstrapper): 18 '''Archlinux experimental bootstrapper.''' 19 20 SYSTEM_PACKAGES = [ 21 'autoconf2.13', 22 'base-devel', 23 'ccache', 24 'mercurial', 25 'nodejs', 26 'npm', 27 'python2', 28 'python2-setuptools', 29 'unzip', 30 'zip', 31 ] 32 33 BROWSER_PACKAGES = [ 34 'alsa-lib', 35 'dbus-glib', 36 'desktop-file-utils', 37 'gconf', 38 'gtk2', 39 'gtk3', 40 'hicolor-icon-theme', 41 'hunspell', 42 'icu', 43 'libevent', 44 'libvpx', 45 'libxt', 46 'mime-types', 47 'mozilla-common', 48 'nss', 49 'sqlite', 50 'startup-notification', 51 'diffutils', 52 'gst-plugins-base-libs', 53 'imake', 54 'inetutils', 55 'libpulse', 56 'xorg-server-xvfb', 57 'yasm', 58 'gst-libav', 59 'gst-plugins-good', 60 'networkmanager', 61 ] 62 63 BROWSER_AUR_PACKAGES = [ 64 'https://aur.archlinux.org/cgit/aur.git/snapshot/uuid.tar.gz', 65 ] 66 67 MOBILE_ANDROID_COMMON_PACKAGES = [ 68 # It would be nice to handle alternative JDKs. See 69 # https://wiki.archlinux.org/index.php/Java. 70 'jdk8-openjdk', 71 # For downloading the Android SDK and NDK. 72 'wget', 73 # See comment about 32 bit binaries and multilib below. 74 'multilib/lib32-libstdc++5', 75 'multilib/lib32-ncurses', 76 'multilib/lib32-readline', 77 'multilib/lib32-zlib', 78 ] 79 80 def __init__(self, version, dist_id, **kwargs): 81 print('Using an experimental bootstrapper for Archlinux.') 82 BaseBootstrapper.__init__(self, **kwargs) 83 84 def install_system_packages(self): 85 self.pacman_install(*self.SYSTEM_PACKAGES) 86 87 def install_browser_packages(self): 88 self.ensure_browser_packages() 89 90 def install_browser_artifact_mode_packages(self): 91 self.ensure_browser_packages(artifact_mode=True) 92 93 def install_mobile_android_packages(self): 94 self.ensure_mobile_android_packages() 95 96 def install_mobile_android_artifact_mode_packages(self): 97 self.ensure_mobile_android_packages(artifact_mode=True) 98 99 def ensure_browser_packages(self, artifact_mode=False): 100 # TODO: Figure out what not to install for artifact mode 101 self.aur_install(*self.BROWSER_AUR_PACKAGES) 102 self.pacman_install(*self.BROWSER_PACKAGES) 103 104 def ensure_mobile_android_packages(self, artifact_mode=False): 105 # Multi-part process: 106 # 1. System packages. 107 # 2. Android SDK. Android NDK only if we are not in artifact mode. Android packages. 108 109 # 1. This is hard to believe, but the Android SDK binaries are 32-bit 110 # and that conflicts with 64-bit Arch installations out of the box. The 111 # solution is to add the multilibs repository; unfortunately, this 112 # requires manual intervention. 113 try: 114 self.pacman_install(*self.MOBILE_ANDROID_COMMON_PACKAGES) 115 except Exception as e: 116 print('Failed to install all packages. The Android developer ' 117 'toolchain requires 32 bit binaries be enabled (see ' 118 'https://wiki.archlinux.org/index.php/Android). You may need to ' 119 'manually enable the multilib repository following the instructions ' 120 'at https://wiki.archlinux.org/index.php/Multilib.') 121 raise e 122 123 # 2. Android pieces. 124 from mozboot import android 125 android.ensure_android('linux', artifact_mode=artifact_mode, 126 no_interactive=self.no_interactive) 127 128 def suggest_mobile_android_mozconfig(self, artifact_mode=False): 129 from mozboot import android 130 android.suggest_mozconfig('linux', artifact_mode=artifact_mode) 131 132 def suggest_mobile_android_artifact_mode_mozconfig(self): 133 self.suggest_mobile_android_mozconfig(artifact_mode=True) 134 135 def _update_package_manager(self): 136 self.pacman_update 137 138 def upgrade_mercurial(self, current): 139 self.pacman_install('mercurial') 140 141 def upgrade_python(self, current): 142 self.pacman_install('python2') 143 144 def pacman_install(self, *packages): 145 command = ['pacman', '-S', '--needed'] 146 if self.no_interactive: 147 command.append('--noconfirm') 148 149 command.extend(packages) 150 151 self.run_as_root(command) 152 153 def pacman_update(self): 154 command = ['pacman', '-S', '--refresh'] 155 156 self.run_as_root(command) 157 158 def run(self, command, env=None): 159 subprocess.check_call(command, stdin=sys.stdin, env=env) 160 161 def download(self, uri): 162 command = ['curl', '-L', '-O', uri] 163 self.run(command) 164 165 def unpack(self, path, name, ext): 166 if ext == 'gz': 167 compression = '-z' 168 elif ext == 'bz': 169 compression == '-j' 170 elif exit == 'xz': 171 compression == 'x' 172 173 name = os.path.join(path, name) + '.tar.' + ext 174 command = ['tar', '-x', compression, '-f', name, '-C', path] 175 self.run(command) 176 177 def makepkg(self, name): 178 command = ['makepkg', '-s'] 179 makepkg_env = os.environ.copy() 180 makepkg_env['PKGEXT'] = '.pkg.tar.xz' 181 self.run(command, env=makepkg_env) 182 pack = glob.glob(name + '*.pkg.tar.xz')[0] 183 command = ['pacman', '-U'] 184 if self.no_interactive: 185 command.append('--noconfirm') 186 command.append(pack) 187 self.run_as_root(command) 188 189 def aur_install(self, *packages): 190 path = tempfile.mkdtemp() 191 if not self.no_interactive: 192 print('WARNING! This script requires to install packages from the AUR ' 193 'This is potentially unsecure so I recommend that you carefully ' 194 'read each package description and check the sources.' 195 'These packages will be built in ' + path + '.') 196 choice = raw_input('Do you want to continue? (yes/no) [no]') 197 if choice != 'yes': 198 sys.exit(1) 199 200 base_dir = os.getcwd() 201 os.chdir(path) 202 for package in packages: 203 name, _, ext = package.split('/')[-1].split('.') 204 directory = os.path.join(path, name) 205 self.download(package) 206 self.unpack(path, name, ext) 207 os.chdir(directory) 208 self.makepkg(name) 209 210 os.chdir(base_dir) 211