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 |