1 # Copyright (c) 2012 The Chromium OS Authors.
3 # SPDX-License-Identifier: GPL-2.0+
16 gcc: Full path to C compiler
17 path: Directory path containing C compiler
18 cross: Cross compile string, e.g. 'arm-linux-'
19 arch: Architecture of toolchain as determined from the first
20 component of the filename. E.g. arm-linux-gcc becomes arm
23 def __init__(self, fname, test, verbose=False):
24 """Create a new toolchain object.
27 fname: Filename of the gcc component
28 test: True to run the toolchain to test it
31 self.path = os.path.dirname(fname)
32 self.cross = os.path.basename(fname)[:-3]
33 pos = self.cross.find('-')
34 self.arch = self.cross[:pos] if pos != -1 else 'sandbox'
36 env = self.MakeEnvironment()
38 # As a basic sanity check, run the C compiler with --version
39 cmd = [fname, '--version']
41 result = command.RunPipe([cmd], capture=True, env=env)
42 self.ok = result.return_code == 0
44 print 'Tool chain test: ',
49 print 'Command: ', cmd
54 self.priority = self.GetPriority(fname)
56 def GetPriority(self, fname):
57 """Return the priority of the toolchain.
59 Toolchains are ranked according to their suitability by their
63 fname: Filename of toolchain
65 Priority of toolchain, 0=highest, 20=lowest.
67 priority_list = ['-elf', '-unknown-linux-gnu', '-linux', '-elf',
68 '-none-linux-gnueabi', '-uclinux', '-none-eabi',
69 '-gentoo-linux-gnu', '-linux-gnueabi', '-le-linux', '-uclinux']
70 for prio in range(len(priority_list)):
71 if priority_list[prio] in fname:
75 def MakeEnvironment(self):
76 """Returns an environment for using the toolchain.
78 Thie takes the current environment, adds CROSS_COMPILE and
79 augments PATH so that the toolchain will operate correctly.
81 env = dict(os.environ)
82 env['CROSS_COMPILE'] = self.cross
83 env['PATH'] += (':' + self.path)
88 """Manage a list of toolchains for building U-Boot
90 We select one toolchain for each architecture type
93 toolchains: Dict of Toolchain objects, keyed by architecture name
94 paths: List of paths to check for toolchains (may contain wildcards)
100 for name, value in bsettings.GetItems('toolchain'):
102 self.paths += glob.glob(value)
104 self.paths.append(value)
107 def Add(self, fname, test=True, verbose=False):
108 """Add a toolchain to our list
110 We select the given toolchain as our preferred one for its
111 architecture if it is a higher priority than the others.
114 fname: Filename of toolchain's gcc driver
115 test: True to run the toolchain to test it
117 toolchain = Toolchain(fname, test, verbose)
118 add_it = toolchain.ok
119 if toolchain.arch in self.toolchains:
120 add_it = (toolchain.priority <
121 self.toolchains[toolchain.arch].priority)
123 self.toolchains[toolchain.arch] = toolchain
125 def Scan(self, verbose):
126 """Scan for available toolchains and select the best for each arch.
128 We look for all the toolchains we can file, figure out the
129 architecture for each, and whether it works. Then we select the
130 highest priority toolchain for each arch.
133 verbose: True to print out progress information
135 if verbose: print 'Scanning for tool chains'
136 for path in self.paths:
137 if verbose: print " - scanning path '%s'" % path
138 for subdir in ['.', 'bin', 'usr/bin']:
139 dirname = os.path.join(path, subdir)
140 if verbose: print " - looking in '%s'" % dirname
141 for fname in glob.glob(dirname + '/*gcc'):
142 if verbose: print " - found '%s'" % fname
143 self.Add(fname, True, verbose)
146 """List out the selected toolchains for each architecture"""
147 print 'List of available toolchains (%d):' % len(self.toolchains)
148 if len(self.toolchains):
149 for key, value in sorted(self.toolchains.iteritems()):
150 print '%-10s: %s' % (key, value.gcc)
154 def Select(self, arch):
155 """Returns the toolchain for a given architecture
158 args: Name of architecture (e.g. 'arm', 'ppc_8xx')
161 toolchain object, or None if none found
163 for name, value in bsettings.GetItems('toolchain-alias'):
167 if not arch in self.toolchains:
168 raise ValueError, ("No tool chain found for arch '%s'" % arch)
169 return self.toolchains[arch]