1fc3fe1c2SSimon Glass# Copyright (c) 2012 The Chromium OS Authors. 2fc3fe1c2SSimon Glass# 3*1a459660SWolfgang Denk# SPDX-License-Identifier: GPL-2.0+ 4fc3fe1c2SSimon Glass# 5fc3fe1c2SSimon Glass 6fc3fe1c2SSimon Glassimport glob 7fc3fe1c2SSimon Glassimport os 8fc3fe1c2SSimon Glass 9fc3fe1c2SSimon Glassimport bsettings 10fc3fe1c2SSimon Glassimport command 11fc3fe1c2SSimon Glass 12fc3fe1c2SSimon Glassclass Toolchain: 13fc3fe1c2SSimon Glass """A single toolchain 14fc3fe1c2SSimon Glass 15fc3fe1c2SSimon Glass Public members: 16fc3fe1c2SSimon Glass gcc: Full path to C compiler 17fc3fe1c2SSimon Glass path: Directory path containing C compiler 18fc3fe1c2SSimon Glass cross: Cross compile string, e.g. 'arm-linux-' 19fc3fe1c2SSimon Glass arch: Architecture of toolchain as determined from the first 20fc3fe1c2SSimon Glass component of the filename. E.g. arm-linux-gcc becomes arm 21fc3fe1c2SSimon Glass """ 22fc3fe1c2SSimon Glass 23fc3fe1c2SSimon Glass def __init__(self, fname, test, verbose=False): 24fc3fe1c2SSimon Glass """Create a new toolchain object. 25fc3fe1c2SSimon Glass 26fc3fe1c2SSimon Glass Args: 27fc3fe1c2SSimon Glass fname: Filename of the gcc component 28fc3fe1c2SSimon Glass test: True to run the toolchain to test it 29fc3fe1c2SSimon Glass """ 30fc3fe1c2SSimon Glass self.gcc = fname 31fc3fe1c2SSimon Glass self.path = os.path.dirname(fname) 32fc3fe1c2SSimon Glass self.cross = os.path.basename(fname)[:-3] 33fc3fe1c2SSimon Glass pos = self.cross.find('-') 34fc3fe1c2SSimon Glass self.arch = self.cross[:pos] if pos != -1 else 'sandbox' 35fc3fe1c2SSimon Glass 36fc3fe1c2SSimon Glass env = self.MakeEnvironment() 37fc3fe1c2SSimon Glass 38fc3fe1c2SSimon Glass # As a basic sanity check, run the C compiler with --version 39fc3fe1c2SSimon Glass cmd = [fname, '--version'] 40fc3fe1c2SSimon Glass if test: 41fc3fe1c2SSimon Glass result = command.RunPipe([cmd], capture=True, env=env) 42fc3fe1c2SSimon Glass self.ok = result.return_code == 0 43fc3fe1c2SSimon Glass if verbose: 44fc3fe1c2SSimon Glass print 'Tool chain test: ', 45fc3fe1c2SSimon Glass if self.ok: 46fc3fe1c2SSimon Glass print 'OK' 47fc3fe1c2SSimon Glass else: 48fc3fe1c2SSimon Glass print 'BAD' 49fc3fe1c2SSimon Glass print 'Command: ', cmd 50fc3fe1c2SSimon Glass print result.stdout 51fc3fe1c2SSimon Glass print result.stderr 52fc3fe1c2SSimon Glass else: 53fc3fe1c2SSimon Glass self.ok = True 54fc3fe1c2SSimon Glass self.priority = self.GetPriority(fname) 55fc3fe1c2SSimon Glass 56fc3fe1c2SSimon Glass def GetPriority(self, fname): 57fc3fe1c2SSimon Glass """Return the priority of the toolchain. 58fc3fe1c2SSimon Glass 59fc3fe1c2SSimon Glass Toolchains are ranked according to their suitability by their 60fc3fe1c2SSimon Glass filename prefix. 61fc3fe1c2SSimon Glass 62fc3fe1c2SSimon Glass Args: 63fc3fe1c2SSimon Glass fname: Filename of toolchain 64fc3fe1c2SSimon Glass Returns: 65fc3fe1c2SSimon Glass Priority of toolchain, 0=highest, 20=lowest. 66fc3fe1c2SSimon Glass """ 67fc3fe1c2SSimon Glass priority_list = ['-elf', '-unknown-linux-gnu', '-linux', '-elf', 68fc3fe1c2SSimon Glass '-none-linux-gnueabi', '-uclinux', '-none-eabi', 69fc3fe1c2SSimon Glass '-gentoo-linux-gnu', '-linux-gnueabi', '-le-linux', '-uclinux'] 70fc3fe1c2SSimon Glass for prio in range(len(priority_list)): 71fc3fe1c2SSimon Glass if priority_list[prio] in fname: 72fc3fe1c2SSimon Glass return prio 73fc3fe1c2SSimon Glass return prio 74fc3fe1c2SSimon Glass 75fc3fe1c2SSimon Glass def MakeEnvironment(self): 76fc3fe1c2SSimon Glass """Returns an environment for using the toolchain. 77fc3fe1c2SSimon Glass 78fc3fe1c2SSimon Glass Thie takes the current environment, adds CROSS_COMPILE and 79fc3fe1c2SSimon Glass augments PATH so that the toolchain will operate correctly. 80fc3fe1c2SSimon Glass """ 81fc3fe1c2SSimon Glass env = dict(os.environ) 82fc3fe1c2SSimon Glass env['CROSS_COMPILE'] = self.cross 83fc3fe1c2SSimon Glass env['PATH'] += (':' + self.path) 84fc3fe1c2SSimon Glass return env 85fc3fe1c2SSimon Glass 86fc3fe1c2SSimon Glass 87fc3fe1c2SSimon Glassclass Toolchains: 88fc3fe1c2SSimon Glass """Manage a list of toolchains for building U-Boot 89fc3fe1c2SSimon Glass 90fc3fe1c2SSimon Glass We select one toolchain for each architecture type 91fc3fe1c2SSimon Glass 92fc3fe1c2SSimon Glass Public members: 93fc3fe1c2SSimon Glass toolchains: Dict of Toolchain objects, keyed by architecture name 94fc3fe1c2SSimon Glass paths: List of paths to check for toolchains (may contain wildcards) 95fc3fe1c2SSimon Glass """ 96fc3fe1c2SSimon Glass 97fc3fe1c2SSimon Glass def __init__(self): 98fc3fe1c2SSimon Glass self.toolchains = {} 99fc3fe1c2SSimon Glass self.paths = [] 100fc3fe1c2SSimon Glass for name, value in bsettings.GetItems('toolchain'): 101fc3fe1c2SSimon Glass if '*' in value: 102fc3fe1c2SSimon Glass self.paths += glob.glob(value) 103fc3fe1c2SSimon Glass else: 104fc3fe1c2SSimon Glass self.paths.append(value) 105fc3fe1c2SSimon Glass 106fc3fe1c2SSimon Glass 107fc3fe1c2SSimon Glass def Add(self, fname, test=True, verbose=False): 108fc3fe1c2SSimon Glass """Add a toolchain to our list 109fc3fe1c2SSimon Glass 110fc3fe1c2SSimon Glass We select the given toolchain as our preferred one for its 111fc3fe1c2SSimon Glass architecture if it is a higher priority than the others. 112fc3fe1c2SSimon Glass 113fc3fe1c2SSimon Glass Args: 114fc3fe1c2SSimon Glass fname: Filename of toolchain's gcc driver 115fc3fe1c2SSimon Glass test: True to run the toolchain to test it 116fc3fe1c2SSimon Glass """ 117fc3fe1c2SSimon Glass toolchain = Toolchain(fname, test, verbose) 118fc3fe1c2SSimon Glass add_it = toolchain.ok 119fc3fe1c2SSimon Glass if toolchain.arch in self.toolchains: 120fc3fe1c2SSimon Glass add_it = (toolchain.priority < 121fc3fe1c2SSimon Glass self.toolchains[toolchain.arch].priority) 122fc3fe1c2SSimon Glass if add_it: 123fc3fe1c2SSimon Glass self.toolchains[toolchain.arch] = toolchain 124fc3fe1c2SSimon Glass 125fc3fe1c2SSimon Glass def Scan(self, verbose): 126fc3fe1c2SSimon Glass """Scan for available toolchains and select the best for each arch. 127fc3fe1c2SSimon Glass 128fc3fe1c2SSimon Glass We look for all the toolchains we can file, figure out the 129fc3fe1c2SSimon Glass architecture for each, and whether it works. Then we select the 130fc3fe1c2SSimon Glass highest priority toolchain for each arch. 131fc3fe1c2SSimon Glass 132fc3fe1c2SSimon Glass Args: 133fc3fe1c2SSimon Glass verbose: True to print out progress information 134fc3fe1c2SSimon Glass """ 135fc3fe1c2SSimon Glass if verbose: print 'Scanning for tool chains' 136fc3fe1c2SSimon Glass for path in self.paths: 137fc3fe1c2SSimon Glass if verbose: print " - scanning path '%s'" % path 138fc3fe1c2SSimon Glass for subdir in ['.', 'bin', 'usr/bin']: 139fc3fe1c2SSimon Glass dirname = os.path.join(path, subdir) 140fc3fe1c2SSimon Glass if verbose: print " - looking in '%s'" % dirname 141fc3fe1c2SSimon Glass for fname in glob.glob(dirname + '/*gcc'): 142fc3fe1c2SSimon Glass if verbose: print " - found '%s'" % fname 143fc3fe1c2SSimon Glass self.Add(fname, True, verbose) 144fc3fe1c2SSimon Glass 145fc3fe1c2SSimon Glass def List(self): 146fc3fe1c2SSimon Glass """List out the selected toolchains for each architecture""" 147fc3fe1c2SSimon Glass print 'List of available toolchains (%d):' % len(self.toolchains) 148fc3fe1c2SSimon Glass if len(self.toolchains): 149fc3fe1c2SSimon Glass for key, value in sorted(self.toolchains.iteritems()): 150fc3fe1c2SSimon Glass print '%-10s: %s' % (key, value.gcc) 151fc3fe1c2SSimon Glass else: 152fc3fe1c2SSimon Glass print 'None' 153fc3fe1c2SSimon Glass 154fc3fe1c2SSimon Glass def Select(self, arch): 155fc3fe1c2SSimon Glass """Returns the toolchain for a given architecture 156fc3fe1c2SSimon Glass 157fc3fe1c2SSimon Glass Args: 158fc3fe1c2SSimon Glass args: Name of architecture (e.g. 'arm', 'ppc_8xx') 159fc3fe1c2SSimon Glass 160fc3fe1c2SSimon Glass returns: 161fc3fe1c2SSimon Glass toolchain object, or None if none found 162fc3fe1c2SSimon Glass """ 163fc3fe1c2SSimon Glass for name, value in bsettings.GetItems('toolchain-alias'): 164fc3fe1c2SSimon Glass if arch == name: 165fc3fe1c2SSimon Glass arch = value 166fc3fe1c2SSimon Glass 167fc3fe1c2SSimon Glass if not arch in self.toolchains: 168fc3fe1c2SSimon Glass raise ValueError, ("No tool chain found for arch '%s'" % arch) 169fc3fe1c2SSimon Glass return self.toolchains[arch] 170