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