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