Home | History | Annotate | Download | only in tools
      1 #!/usr/bin/python
      2 # Copyright (c) 2012 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 """Diagnose some common system configuration problems on Linux, and
      7 suggest fixes."""
      8 
      9 import os
     10 import subprocess
     11 import sys
     12 
     13 all_checks = []
     14 
     15 def Check(name):
     16     """Decorator that defines a diagnostic check."""
     17     def wrap(func):
     18         all_checks.append((name, func))
     19         return func
     20     return wrap
     21 
     22 
     23 @Check("/usr/bin/ld is not gold")
     24 def CheckSystemLd():
     25     proc = subprocess.Popen(['/usr/bin/ld', '-v'], stdout=subprocess.PIPE)
     26     stdout = proc.communicate()[0]
     27     if 'GNU gold' in stdout:
     28         return ("When /usr/bin/ld is gold, system updates can silently\n"
     29                 "corrupt your graphics drivers.\n"
     30                 "Try 'sudo apt-get remove binutils-gold'.\n")
     31     return None
     32 
     33 
     34 @Check("random lds are not in the $PATH")
     35 def CheckPathLd():
     36     proc = subprocess.Popen(['which', '-a', 'ld'], stdout=subprocess.PIPE)
     37     stdout = proc.communicate()[0]
     38     instances = stdout.split()
     39     if len(instances) > 1:
     40         return ("You have multiple 'ld' binaries in your $PATH:\n"
     41                 + '\n'.join(' - ' + i for i in instances) + "\n"
     42                 "You should delete all of them but your system one.\n"
     43                 "gold is hooked into your build via gyp.\n")
     44     return None
     45 
     46 
     47 @Check("/usr/bin/ld doesn't point to gold")
     48 def CheckLocalGold():
     49     # Check /usr/bin/ld* symlinks.
     50     for path in ('ld.bfd', 'ld'):
     51         path = '/usr/bin/' + path
     52         try:
     53             target = os.readlink(path)
     54         except OSError, e:
     55             if e.errno == 2:
     56                 continue  # No such file
     57             if e.errno == 22:
     58                 continue  # Not a symlink
     59             raise
     60         if '/usr/local/gold' in target:
     61             return ("%s is a symlink into /usr/local/gold.\n"
     62                     "It's difficult to make a recommendation, because you\n"
     63                     "probably set this up yourself.  But you should make\n"
     64                     "/usr/bin/ld be the standard linker, which you likely\n"
     65                     "renamed /usr/bin/ld.bfd or something like that.\n" % path)
     66 
     67     return None
     68 
     69 
     70 @Check("random ninja binaries are not in the $PATH")
     71 def CheckPathNinja():
     72     proc = subprocess.Popen(['which', 'ninja'], stdout=subprocess.PIPE)
     73     stdout = proc.communicate()[0]
     74     if not 'depot_tools' in stdout:
     75         return ("The ninja binary in your path isn't from depot_tools:\n"
     76                 + "    " + stdout +
     77                 "Remove custom ninjas from your path so that the one\n"
     78                 "in depot_tools is used.\n")
     79     return None
     80 
     81 
     82 @Check("build dependencies are satisfied")
     83 def CheckBuildDeps():
     84     script_path = os.path.join(
     85         os.path.dirname(os.path.dirname(os.path.abspath(__file__))), 'build',
     86         'install-build-deps.sh')
     87     proc = subprocess.Popen([script_path, '--quick-check'],
     88                             stdout=subprocess.PIPE)
     89     stdout = proc.communicate()[0]
     90     if 'WARNING' in stdout:
     91         return ("Your build dependencies are out-of-date.\n"
     92                 "Run '" + script_path + "' to update.")
     93     return None
     94 
     95 
     96 def RunChecks():
     97     for name, check in all_checks:
     98         sys.stdout.write("* Checking %s: " % name)
     99         sys.stdout.flush()
    100         error = check()
    101         if not error:
    102             print "ok"
    103         else:
    104             print "FAIL"
    105             print error
    106 
    107 
    108 if __name__ == '__main__':
    109     RunChecks()
    110