blob: 7cc3760df7541a4fa41b7cd0a8ab2f4b316c5c53 [file] [log] [blame]
Paweł Hajdan, Jref4c48b2015-07-13 18:51:42 +09001#!/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)
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
247def is_userland_64_bit():
248 return platform.architecture()[0] == '64bit'
249
250
251def package_exists(pkg):
252 return pkg in subprocess.check_output(['apt-cache', 'pkgnames']).splitlines()
253
254
255def lsb_release_short_codename():
256 return subprocess.check_output(
257 ['lsb_release', '--codename', '--short']).strip()
258
259
260def write_error(message):
261 sys.stderr.write('ERROR: %s\n' % message)
262 sys.stderr.flush()
263
264
265def 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
273def 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
373def 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
382def 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
429if __name__ == '__main__':
430 sys.exit(main(sys.argv[1:]))