15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#!/usr/bin/python
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Copyright (c) 2012 The Chromium Authors. All rights reserved.
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Use of this source code is governed by a BSD-style license that can be
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# found in the LICENSE file.
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)"""Diagnose some common system configuration problems on Linux, and
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)suggest fixes."""
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import os
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import subprocess
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import sys
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)all_checks = []
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def Check(name):
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Decorator that defines a diagnostic check."""
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def wrap(func):
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        all_checks.append((name, func))
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return func
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return wrap
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)@Check("/usr/bin/ld is not gold")
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def CheckSystemLd():
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    proc = subprocess.Popen(['/usr/bin/ld', '-v'], stdout=subprocess.PIPE)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    stdout = proc.communicate()[0]
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if 'GNU gold' in stdout:
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return ("When /usr/bin/ld is gold, system updates can silently\n"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                "corrupt your graphics drivers.\n"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                "Try 'sudo apt-get remove binutils-gold'.\n")
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return None
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)@Check("random lds are not in the $PATH")
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def CheckPathLd():
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    proc = subprocess.Popen(['which', '-a', 'ld'], stdout=subprocess.PIPE)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    stdout = proc.communicate()[0]
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    instances = stdout.split()
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if len(instances) > 1:
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return ("You have multiple 'ld' binaries in your $PATH:\n"
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                + '\n'.join(' - ' + i for i in instances) + "\n"
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                "You should delete all of them but your system one.\n"
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                "gold is hooked into your build via gyp.\n")
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return None
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)@Check("/usr/bin/ld doesn't point to gold")
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def CheckLocalGold():
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Check /usr/bin/ld* symlinks.
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for path in ('ld.bfd', 'ld'):
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        path = '/usr/bin/' + path
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        try:
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            target = os.readlink(path)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        except OSError, e:
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if e.errno == 2:
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                continue  # No such file
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if e.errno == 22:
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                continue  # Not a symlink
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            raise
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if '/usr/local/gold' in target:
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return ("%s is a symlink into /usr/local/gold.\n"
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    "It's difficult to make a recommendation, because you\n"
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    "probably set this up yourself.  But you should make\n"
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    "/usr/bin/ld be the standard linker, which you likely\n"
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    "renamed /usr/bin/ld.bfd or something like that.\n" % path)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return None
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)@Check("random ninja binaries are not in the $PATH")
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def CheckPathNinja():
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    proc = subprocess.Popen(['which', 'ninja'], stdout=subprocess.PIPE)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    stdout = proc.communicate()[0]
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if not 'depot_tools' in stdout:
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return ("The ninja binary in your path isn't from depot_tools:\n"
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                + "    " + stdout +
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                "Remove custom ninjas from your path so that the one\n"
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                "in depot_tools is used.\n")
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return None
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
821e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)@Check("build dependencies are satisfied")
831e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)def CheckBuildDeps():
841e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    script_path = os.path.join(
851e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        os.path.dirname(os.path.dirname(os.path.abspath(__file__))), 'build',
861e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        'install-build-deps.sh')
871e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    proc = subprocess.Popen([script_path, '--quick-check'],
881e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                            stdout=subprocess.PIPE)
891e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    stdout = proc.communicate()[0]
901e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    if 'WARNING' in stdout:
911e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        return ("Your build dependencies are out-of-date.\n"
921e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                "Run '" + script_path + "' to update.")
931e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return None
941e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
951e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def RunChecks():
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for name, check in all_checks:
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        sys.stdout.write("* Checking %s: " % name)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        sys.stdout.flush()
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        error = check()
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if not error:
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            print "ok"
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        else:
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            print "FAIL"
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            print error
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)if __name__ == '__main__':
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RunChecks()
110