Add in-memory caching of network quality estimates across network changes.
[chromium-blink-merge.git] / build / install-build-deps.py
blob7cc3760df7541a4fa41b7cd0a8ab2f4b316c5c53
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.
6 import argparse
7 import operator
8 import os
9 import platform
10 import re
11 import subprocess
12 import sys
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'},
23 # Packages needed for chromeos only.
24 _packages_chromeos_dev = (
25 'libbluetooth-dev',
26 'libxkbcommon-dev',
27 'realpath',
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',
111 # Run-time libraries required by chromeos only.
112 _packages_chromeos_lib = (
113 'libbz2-1.0',
114 'libpulse0',
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',
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',
190 # 32-bit libraries needed e.g. to compile V8 snapshot for Android or armhf.
191 _packages_lib32 = (
192 'linux-libc-dev:i386',
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',
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',
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',
247 def is_userland_64_bit():
248 return platform.architecture()[0] == '64bit'
251 def package_exists(pkg):
252 return pkg in subprocess.check_output(['apt-cache', 'pkgnames']).splitlines()
255 def lsb_release_short_codename():
256 return subprocess.check_output(
257 ['lsb_release', '--codename', '--short']).strip()
260 def write_error(message):
261 sys.stderr.write('ERROR: %s\n' % message)
262 sys.stderr.flush()
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
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
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',
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,)
301 lsb_codename = lsb_release_short_codename()
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',)
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',
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,
334 if package_exists('ttf-mscorefonts-installer'):
335 _packages_dev += ('ttf-mscorefonts-installer',)
336 else:
337 _packages_dev += ('msttcorefonts',)
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')
346 if package_exists('libjpeg-dev'):
347 _packages_dev += ('libjpeg-dev',)
348 else:
349 _packages_dev += ('libjpeg62-dev',)
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',)
358 if package_exists('libbrlapi0.6'):
359 _packages_dev += ('libbrlapi0.6',)
360 else:
361 _packages_dev += ('libbrlapi0.5',)
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',)
368 _packages_dev += _packages_chromeos_dev
369 _packages_lib += _packages_chromeos_lib
370 _packages_nacl += _packages_naclports
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
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)
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
402 if platform.machine() not in ('i686', 'x86_64'):
403 write_error('Only x86 architectures are currently supported.')
404 return 1
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
412 compute_dynamic_package_lists()
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)
423 if args.quick_check:
424 return quick_check(packages)
426 return 0
429 if __name__ == '__main__':
430 sys.exit(main(sys.argv[1:]))