OLD | NEW |
(Empty) | |
| 1 #!/usr/bin/env python |
| 2 # Copyright 2015 The Chromium Authors. All rights reserved. |
| 3 # Use of this source code is governed by a BSD-style license that can be |
| 4 # found in the LICENSE file. |
| 5 |
| 6 import argparse |
| 7 import operator |
| 8 import os |
| 9 import platform |
| 10 import re |
| 11 import subprocess |
| 12 import sys |
| 13 |
| 14 |
| 15 SUPPORTED_UBUNTU_VERSIONS = ( |
| 16 {'number': '12.04', 'codename': 'precise'}, |
| 17 {'number': '14.04', 'codename': 'trusty'}, |
| 18 {'number': '14.10', 'codename': 'utopic'}, |
| 19 {'number': '15.04', 'codename': 'vivid'}, |
| 20 ) |
| 21 |
| 22 |
| 23 # Packages needed for chromeos only. |
| 24 _packages_chromeos_dev = ( |
| 25 'libbluetooth-dev', |
| 26 'libxkbcommon-dev', |
| 27 'realpath', |
| 28 ) |
| 29 |
| 30 |
| 31 # Packages needed for development. |
| 32 _packages_dev = ( |
| 33 'apache2.2-bin', |
| 34 'bison', |
| 35 'cdbs', |
| 36 'curl', |
| 37 'devscripts', |
| 38 'dpkg-dev', |
| 39 'elfutils', |
| 40 'fakeroot', |
| 41 'flex', |
| 42 'fonts-thai-tlwg', |
| 43 'g++', |
| 44 'git-core', |
| 45 'git-svn', |
| 46 'gperf', |
| 47 'language-pack-da', |
| 48 'language-pack-fr', |
| 49 'language-pack-he', |
| 50 'language-pack-zh-hant', |
| 51 'libapache2-mod-php5', |
| 52 'libasound2-dev', |
| 53 'libav-tools', |
| 54 'libbrlapi-dev', |
| 55 'libbz2-dev', |
| 56 'libcairo2-dev', |
| 57 'libcap-dev', |
| 58 'libcups2-dev', |
| 59 'libcurl4-gnutls-dev', |
| 60 'libdrm-dev', |
| 61 'libelf-dev', |
| 62 'libexif-dev', |
| 63 'libgconf2-dev', |
| 64 'libglib2.0-dev', |
| 65 'libglu1-mesa-dev', |
| 66 'libgnome-keyring-dev', |
| 67 'libgtk2.0-dev', |
| 68 'libkrb5-dev', |
| 69 'libnspr4-dev', |
| 70 'libnss3-dev', |
| 71 'libpam0g-dev', |
| 72 'libpci-dev', |
| 73 'libpulse-dev', |
| 74 'libsctp-dev', |
| 75 'libspeechd-dev', |
| 76 'libsqlite3-dev', |
| 77 'libssl-dev', |
| 78 'libudev-dev', |
| 79 'libwww-perl', |
| 80 'libxslt1-dev', |
| 81 'libxss-dev', |
| 82 'libxt-dev', |
| 83 'libxtst-dev', |
| 84 'openbox', |
| 85 'patch', |
| 86 'perl', |
| 87 'php5-cgi', |
| 88 'pkg-config', |
| 89 'python', |
| 90 'python-cherrypy3', |
| 91 'python-crypto', |
| 92 'python-dev', |
| 93 'python-numpy', |
| 94 'python-opencv', |
| 95 'python-openssl', |
| 96 'python-psutil', |
| 97 'python-yaml', |
| 98 'rpm', |
| 99 'ruby', |
| 100 'subversion', |
| 101 'ttf-dejavu-core', |
| 102 'ttf-indic-fonts', |
| 103 'ttf-kochi-gothic', |
| 104 'ttf-kochi-mincho', |
| 105 'wdiff', |
| 106 'xfonts-mathml', |
| 107 'zip', |
| 108 ) |
| 109 |
| 110 |
| 111 # Run-time libraries required by chromeos only. |
| 112 _packages_chromeos_lib = ( |
| 113 'libbz2-1.0', |
| 114 'libpulse0', |
| 115 ) |
| 116 |
| 117 |
| 118 # Full list of required run-time libraries. |
| 119 _packages_lib = ( |
| 120 'libasound2', |
| 121 'libatk1.0-0', |
| 122 'libc6', |
| 123 'libcairo2', |
| 124 'libcap2', |
| 125 'libcups2', |
| 126 'libexif12', |
| 127 'libexpat1', |
| 128 'libfontconfig1', |
| 129 'libfreetype6', |
| 130 'libglib2.0-0', |
| 131 'libgnome-keyring0', |
| 132 'libgtk2.0-0', |
| 133 'libpam0g', |
| 134 'libpango1.0-0', |
| 135 'libpci3', |
| 136 'libpcre3', |
| 137 'libpixman-1-0', |
| 138 'libpng12-0', |
| 139 'libspeechd2', |
| 140 'libsqlite3-0', |
| 141 'libstdc++6', |
| 142 'libx11-6', |
| 143 'libxau6', |
| 144 'libxcb1', |
| 145 'libxcomposite1', |
| 146 'libxcursor1', |
| 147 'libxdamage1', |
| 148 'libxdmcp6', |
| 149 'libxext6', |
| 150 'libxfixes3', |
| 151 'libxi6', |
| 152 'libxinerama1', |
| 153 'libxrandr2', |
| 154 'libxrender1', |
| 155 'libxtst6', |
| 156 'zlib1g', |
| 157 ) |
| 158 |
| 159 |
| 160 # Debugging symbols for all of the run-time libraries. |
| 161 _packages_dbg = ( |
| 162 'libatk1.0-dbg', |
| 163 'libc6-dbg', |
| 164 'libcairo2-dbg', |
| 165 'libfontconfig1-dbg', |
| 166 'libglib2.0-0-dbg', |
| 167 'libgtk2.0-0-dbg', |
| 168 'libpango1.0-0-dbg', |
| 169 'libpcre3-dbg', |
| 170 'libpixman-1-0-dbg', |
| 171 'libsqlite3-0-dbg', |
| 172 'libx11-6-dbg', |
| 173 'libxau6-dbg', |
| 174 'libxcb1-dbg', |
| 175 'libxcomposite1-dbg', |
| 176 'libxcursor1-dbg', |
| 177 'libxdamage1-dbg', |
| 178 'libxdmcp6-dbg', |
| 179 'libxext6-dbg', |
| 180 'libxfixes3-dbg', |
| 181 'libxi6-dbg', |
| 182 'libxinerama1-dbg', |
| 183 'libxrandr2-dbg', |
| 184 'libxrender1-dbg', |
| 185 'libxtst6-dbg', |
| 186 'zlib1g-dbg', |
| 187 ) |
| 188 |
| 189 |
| 190 # 32-bit libraries needed e.g. to compile V8 snapshot for Android or armhf. |
| 191 _packages_lib32 = ( |
| 192 'linux-libc-dev:i386', |
| 193 ) |
| 194 |
| 195 |
| 196 # arm cross toolchain packages needed to build chrome on armhf. |
| 197 _packages_arm = ( |
| 198 'g++-arm-linux-gnueabihf', |
| 199 'libc6-dev-armhf-cross', |
| 200 'linux-libc-dev-armhf-cross', |
| 201 ) |
| 202 |
| 203 |
| 204 # Packages to build NaCl, its toolchains, and its ports. |
| 205 _packages_naclports = ( |
| 206 'ant', |
| 207 'autoconf', |
| 208 'bison', |
| 209 'cmake', |
| 210 'gawk', |
| 211 'intltool', |
| 212 'xsltproc', |
| 213 'xutils-dev', |
| 214 ) |
| 215 _packages_nacl = ( |
| 216 'g++-mingw-w64-i686', |
| 217 'lib32ncurses5-dev', |
| 218 'lib32z1-dev', |
| 219 'libasound2:i386', |
| 220 'libcap2:i386', |
| 221 'libelf-dev:i386', |
| 222 'libexif12:i386', |
| 223 'libfontconfig1:i386', |
| 224 'libgconf-2-4:i386', |
| 225 'libglib2.0-0:i386', |
| 226 'libgpm2:i386', |
| 227 'libgtk2.0-0:i386', |
| 228 'libncurses5:i386', |
| 229 'libnss3:i386', |
| 230 'libpango1.0-0:i386', |
| 231 'libssl1.0.0:i386', |
| 232 'libtinfo-dev', |
| 233 'libtinfo-dev:i386', |
| 234 'libtool', |
| 235 'libxcomposite1:i386', |
| 236 'libxcursor1:i386', |
| 237 'libxdamage1:i386', |
| 238 'libxi6:i386', |
| 239 'libxrandr2:i386', |
| 240 'libxss1:i386', |
| 241 'libxtst6:i386', |
| 242 'texinfo', |
| 243 'xvfb', |
| 244 ) |
| 245 |
| 246 |
| 247 def is_userland_64_bit(): |
| 248 return platform.architecture()[0] == '64bit' |
| 249 |
| 250 |
| 251 def package_exists(pkg): |
| 252 return pkg in subprocess.check_output(['apt-cache', 'pkgnames']).splitlines() |
| 253 |
| 254 |
| 255 def lsb_release_short_codename(): |
| 256 return subprocess.check_output( |
| 257 ['lsb_release', '--codename', '--short']).strip() |
| 258 |
| 259 |
| 260 def write_error(message): |
| 261 sys.stderr.write('ERROR: %s\n' % message) |
| 262 sys.stderr.flush() |
| 263 |
| 264 |
| 265 def nonfatal_get_output(*popenargs, **kwargs): |
| 266 process = subprocess.Popen( |
| 267 stdout=subprocess.PIPE, stderr=subprocess.PIPE, *popenargs, **kwargs) |
| 268 stdout, stderr = process.communicate() |
| 269 retcode = process.poll() |
| 270 return retcode, stdout, stderr |
| 271 |
| 272 |
| 273 def compute_dynamic_package_lists(): |
| 274 global _packages_arm |
| 275 global _packages_dbg |
| 276 global _packages_dev |
| 277 global _packages_lib |
| 278 global _packages_lib32 |
| 279 global _packages_nacl |
| 280 |
| 281 if is_userland_64_bit(): |
| 282 # 64-bit systems need a minimum set of 32-bit compat packages |
| 283 # for the pre-built NaCl binaries. |
| 284 _packages_dev += ( |
| 285 'lib32gcc1', |
| 286 'lib32stdc++6', |
| 287 'libc6-i386', |
| 288 ) |
| 289 |
| 290 # When cross building for arm/Android on 64-bit systems the host binaries |
| 291 # that are part of v8 need to be compiled with -m32 which means |
| 292 # that basic multilib support is needed. |
| 293 # gcc-multilib conflicts with the arm cross compiler (at least in trusty) |
| 294 # but g++-X.Y-multilib gives us the 32-bit support that we need. Find out |
| 295 # the appropriate value of X and Y by seeing what version the current |
| 296 # distribution's g++-multilib package depends on. |
| 297 output = subprocess.check_output(['apt-cache', 'depends', 'g++-multilib']) |
| 298 multilib_package = re.search(r'g\+\+-[0-9.]+-multilib', output).group() |
| 299 _packages_lib32 += (multilib_package,) |
| 300 |
| 301 lsb_codename = lsb_release_short_codename() |
| 302 |
| 303 # Find the proper version of libstdc++6-4.x-dbg. |
| 304 if lsb_codename == 'precise': |
| 305 _packages_dbg += ('libstdc++6-4.6-dbg',) |
| 306 elif lsb_codename == 'trusty': |
| 307 _packages_dbg += ('libstdc++6-4.8-dbg',) |
| 308 else: |
| 309 _packages_dbg += ('libstdc++6-4.9-dbg',) |
| 310 |
| 311 # Work around for dependency issue Ubuntu/Trusty: http://crbug.com/435056 . |
| 312 if lsb_codename == 'trusty': |
| 313 _packages_arm += ( |
| 314 'g++-4.8-multilib-arm-linux-gnueabihf', |
| 315 'gcc-4.8-multilib-arm-linux-gnueabihf', |
| 316 ) |
| 317 |
| 318 # Find the proper version of libgbm-dev. We can't just install libgbm-dev as |
| 319 # it depends on mesa, and only one version of mesa can exists on the system. |
| 320 # Hence we must match the same version or this entire script will fail. |
| 321 mesa_variant = '' |
| 322 for variant in ('-lts-trusty', '-lts-utopic'): |
| 323 rc, stdout, stderr = nonfatal_get_output( |
| 324 ['dpkg-query', '-Wf\'{Status}\'', 'libgl1-mesa-glx' + variant]) |
| 325 if 'ok installed' in output: |
| 326 mesa_variant = variant |
| 327 _packages_dev += ( |
| 328 'libgbm-dev' + mesa_variant, |
| 329 'libgl1-mesa-dev' + mesa_variant, |
| 330 'libgles2-mesa-dev' + mesa_variant, |
| 331 'mesa-common-dev' + mesa_variant, |
| 332 ) |
| 333 |
| 334 if package_exists('ttf-mscorefonts-installer'): |
| 335 _packages_dev += ('ttf-mscorefonts-installer',) |
| 336 else: |
| 337 _packages_dev += ('msttcorefonts',) |
| 338 |
| 339 if package_exists('libnspr4-dbg'): |
| 340 _packages_dbg += ('libnspr4-dbg', 'libnss3-dbg') |
| 341 _packages_lib += ('libnspr4', 'libnss3') |
| 342 else: |
| 343 _packages_dbg += ('libnspr4-0d-dbg', 'libnss3-1d-dbg') |
| 344 _packages_lib += ('libnspr4-0d', 'libnss3-1d') |
| 345 |
| 346 if package_exists('libjpeg-dev'): |
| 347 _packages_dev += ('libjpeg-dev',) |
| 348 else: |
| 349 _packages_dev += ('libjpeg62-dev',) |
| 350 |
| 351 if package_exists('libudev1'): |
| 352 _packages_dev += ('libudev1',) |
| 353 _packages_nacl += ('libudev1:i386',) |
| 354 else: |
| 355 _packages_dev += ('libudev0',) |
| 356 _packages_nacl += ('libudev0:i386',) |
| 357 |
| 358 if package_exists('libbrlapi0.6'): |
| 359 _packages_dev += ('libbrlapi0.6',) |
| 360 else: |
| 361 _packages_dev += ('libbrlapi0.5',) |
| 362 |
| 363 # Some packages are only needed if the distribution actually supports |
| 364 # installing them. |
| 365 if package_exists('appmenu-gtk'): |
| 366 _packages_lib += ('appmenu-gtk',) |
| 367 |
| 368 _packages_dev += _packages_chromeos_dev |
| 369 _packages_lib += _packages_chromeos_lib |
| 370 _packages_nacl += _packages_naclports |
| 371 |
| 372 |
| 373 def quick_check(packages): |
| 374 rc, stdout, stderr = nonfatal_get_output([ |
| 375 'dpkg-query', '-W', '-f', '${PackageSpec}:${Status}\n'] + list(packages)) |
| 376 if rc == 0 and not stderr: |
| 377 return 0 |
| 378 print stderr |
| 379 return 1 |
| 380 |
| 381 |
| 382 def main(argv): |
| 383 parser = argparse.ArgumentParser() |
| 384 parser.add_argument('--quick-check', action='store_true', |
| 385 help='quickly try to determine if dependencies are ' |
| 386 'installed (this avoids interactive prompts and ' |
| 387 'sudo commands so might not be 100% accurate)') |
| 388 parser.add_argument('--unsupported', action='store_true', |
| 389 help='attempt installation even on unsupported systems') |
| 390 args = parser.parse_args(argv) |
| 391 |
| 392 lsb_codename = lsb_release_short_codename() |
| 393 if not args.unsupported and not args.quick_check: |
| 394 if lsb_codename not in map( |
| 395 operator.itemgetter('codename'), SUPPORTED_UBUNTU_VERSIONS): |
| 396 supported_ubuntus = ['%(number)s (%(codename)s)' % v |
| 397 for v in SUPPORTED_UBUNTU_VERSIONS] |
| 398 write_error('Only Ubuntu %s are currently supported.' % |
| 399 ', '.join(supported_ubuntus)) |
| 400 return 1 |
| 401 |
| 402 if platform.machine() not in ('i686', 'x86_64'): |
| 403 write_error('Only x86 architectures are currently supported.') |
| 404 return 1 |
| 405 |
| 406 if os.geteuid() != 0 and not args.quick_check: |
| 407 print 'Running as non-root user.' |
| 408 print 'You might have to enter your password one or more times' |
| 409 print 'for \'sudo\'.' |
| 410 print |
| 411 |
| 412 compute_dynamic_package_lists() |
| 413 |
| 414 packages = (_packages_dev + _packages_lib + _packages_dbg + _packages_lib32 + |
| 415 _packages_arm + _packages_nacl) |
| 416 def packages_key(pkg): |
| 417 s = pkg.rsplit(':', 1) |
| 418 if len(s) == 1: |
| 419 return (s, '') |
| 420 return s |
| 421 packages = sorted(set(packages), key=packages_key) |
| 422 |
| 423 if args.quick_check: |
| 424 return quick_check(packages) |
| 425 |
| 426 return 0 |
| 427 |
| 428 |
| 429 if __name__ == '__main__': |
| 430 sys.exit(main(sys.argv[1:])) |
OLD | NEW |