1 # Copyright (c) 2012 The Chromium OS Authors.
3 # SPDX-License-Identifier: GPL-2.0+
17 gcc: Full path to C compiler
18 path: Directory path containing C compiler
19 cross: Cross compile string, e.g. 'arm-linux-'
20 arch: Architecture of toolchain as determined from the first
21 component of the filename. E.g. arm-linux-gcc becomes arm
24 def __init__(self, fname, test, verbose=False):
25 """Create a new toolchain object.
28 fname: Filename of the gcc component
29 test: True to run the toolchain to test it
32 self.path = os.path.dirname(fname)
33 self.cross = os.path.basename(fname)[:-3]
34 pos = self.cross.find('-')
35 self.arch = self.cross[:pos] if pos != -1 else 'sandbox'
37 env = self.MakeEnvironment()
39 # As a basic sanity check, run the C compiler with --version
40 cmd = [fname, '--version']
42 result = command.RunPipe([cmd], capture=True, env=env,
44 self.ok = result.return_code == 0
46 print 'Tool chain test: ',
51 print 'Command: ', cmd
56 self.priority = self.GetPriority(fname)
58 def GetPriority(self, fname):
59 """Return the priority of the toolchain.
61 Toolchains are ranked according to their suitability by their
65 fname: Filename of toolchain
67 Priority of toolchain, 0=highest, 20=lowest.
69 priority_list = ['-elf', '-unknown-linux-gnu', '-linux',
70 '-none-linux-gnueabi', '-uclinux', '-none-eabi',
71 '-gentoo-linux-gnu', '-linux-gnueabi', '-le-linux', '-uclinux']
72 for prio in range(len(priority_list)):
73 if priority_list[prio] in fname:
77 def MakeEnvironment(self):
78 """Returns an environment for using the toolchain.
80 Thie takes the current environment, adds CROSS_COMPILE and
81 augments PATH so that the toolchain will operate correctly.
83 env = dict(os.environ)
84 env['CROSS_COMPILE'] = self.cross
85 env['PATH'] += (':' + self.path)
90 """Manage a list of toolchains for building U-Boot
92 We select one toolchain for each architecture type
95 toolchains: Dict of Toolchain objects, keyed by architecture name
96 paths: List of paths to check for toolchains (may contain wildcards)
102 toolchains = bsettings.GetItems('toolchain')
104 print ("Warning: No tool chains - please add a [toolchain] section"
105 " to your buildman config file %s. See README for details" %
106 bsettings.config_fname)
108 for name, value in toolchains:
110 self.paths += glob.glob(value)
112 self.paths.append(value)
113 self._make_flags = dict(bsettings.GetItems('make-flags'))
115 def Add(self, fname, test=True, verbose=False):
116 """Add a toolchain to our list
118 We select the given toolchain as our preferred one for its
119 architecture if it is a higher priority than the others.
122 fname: Filename of toolchain's gcc driver
123 test: True to run the toolchain to test it
125 toolchain = Toolchain(fname, test, verbose)
126 add_it = toolchain.ok
127 if toolchain.arch in self.toolchains:
128 add_it = (toolchain.priority <
129 self.toolchains[toolchain.arch].priority)
131 self.toolchains[toolchain.arch] = toolchain
133 def Scan(self, verbose):
134 """Scan for available toolchains and select the best for each arch.
136 We look for all the toolchains we can file, figure out the
137 architecture for each, and whether it works. Then we select the
138 highest priority toolchain for each arch.
141 verbose: True to print out progress information
143 if verbose: print 'Scanning for tool chains'
144 for path in self.paths:
145 if verbose: print " - scanning path '%s'" % path
146 for subdir in ['.', 'bin', 'usr/bin']:
147 dirname = os.path.join(path, subdir)
148 if verbose: print " - looking in '%s'" % dirname
149 for fname in glob.glob(dirname + '/*gcc'):
150 if verbose: print " - found '%s'" % fname
151 self.Add(fname, True, verbose)
154 """List out the selected toolchains for each architecture"""
155 print 'List of available toolchains (%d):' % len(self.toolchains)
156 if len(self.toolchains):
157 for key, value in sorted(self.toolchains.iteritems()):
158 print '%-10s: %s' % (key, value.gcc)
162 def Select(self, arch):
163 """Returns the toolchain for a given architecture
166 args: Name of architecture (e.g. 'arm', 'ppc_8xx')
169 toolchain object, or None if none found
171 for name, value in bsettings.GetItems('toolchain-alias'):
175 if not arch in self.toolchains:
176 raise ValueError, ("No tool chain found for arch '%s'" % arch)
177 return self.toolchains[arch]
179 def ResolveReferences(self, var_dict, args):
180 """Resolve variable references in a string
182 This converts ${blah} within the string to the value of blah.
183 This function works recursively.
186 var_dict: Dictionary containing variables and their values
187 args: String containing make arguments
191 >>> bsettings.Setup()
192 >>> tcs = Toolchains()
193 >>> tcs.Add('fred', False)
194 >>> var_dict = {'oblique' : 'OBLIQUE', 'first' : 'fi${second}rst', \
196 >>> tcs.ResolveReferences(var_dict, 'this=${oblique}_set')
198 >>> tcs.ResolveReferences(var_dict, 'this=${oblique}_set${first}nd')
199 'this=OBLIQUE_setfi2ndrstnd'
201 re_var = re.compile('(\$\{[a-z0-9A-Z]{1,}\})')
204 m = re_var.search(args)
207 lookup = m.group(0)[2:-1]
208 value = var_dict.get(lookup, '')
209 args = args[:m.start(0)] + value + args[m.end(0):]
212 def GetMakeArguments(self, board):
213 """Returns 'make' arguments for a given board
215 The flags are in a section called 'make-flags'. Flags are named
216 after the target they represent, for example snapper9260=TESTING=1
217 will pass TESTING=1 to make when building the snapper9260 board.
219 References to other boards can be added in the string also. For
223 at91-boards=ENABLE_AT91_TEST=1
224 snapper9260=${at91-boards} BUILD_TAG=442
225 snapper9g45=${at91-boards} BUILD_TAG=443
227 This will return 'ENABLE_AT91_TEST=1 BUILD_TAG=442' for snapper9260
228 and 'ENABLE_AT91_TEST=1 BUILD_TAG=443' for snapper9g45.
230 A special 'target' variable is set to the board target.
233 board: Board object for the board to check.
235 'make' flags for that board, or '' if none
237 self._make_flags['target'] = board.target
238 arg_str = self.ResolveReferences(self._make_flags,
239 self._make_flags.get(board.target, ''))
240 args = arg_str.split(' ')