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)
43 self.ok = result.return_code == 0
45 print 'Tool chain test: ',
50 print 'Command: ', cmd
55 self.priority = self.GetPriority(fname)
57 def GetPriority(self, fname):
58 """Return the priority of the toolchain.
60 Toolchains are ranked according to their suitability by their
64 fname: Filename of toolchain
66 Priority of toolchain, 0=highest, 20=lowest.
68 priority_list = ['-elf', '-unknown-linux-gnu', '-linux', '-elf',
69 '-none-linux-gnueabi', '-uclinux', '-none-eabi',
70 '-gentoo-linux-gnu', '-linux-gnueabi', '-le-linux', '-uclinux']
71 for prio in range(len(priority_list)):
72 if priority_list[prio] in fname:
76 def MakeEnvironment(self):
77 """Returns an environment for using the toolchain.
79 Thie takes the current environment, adds CROSS_COMPILE and
80 augments PATH so that the toolchain will operate correctly.
82 env = dict(os.environ)
83 env['CROSS_COMPILE'] = self.cross
84 env['PATH'] += (':' + self.path)
89 """Manage a list of toolchains for building U-Boot
91 We select one toolchain for each architecture type
94 toolchains: Dict of Toolchain objects, keyed by architecture name
95 paths: List of paths to check for toolchains (may contain wildcards)
101 toolchains = bsettings.GetItems('toolchain')
103 print ("Warning: No tool chains - please add a [toolchain] section"
104 " to your buildman config file %s. See README for details" %
107 for name, value in toolchains:
109 self.paths += glob.glob(value)
111 self.paths.append(value)
112 self._make_flags = dict(bsettings.GetItems('make-flags'))
114 def Add(self, fname, test=True, verbose=False):
115 """Add a toolchain to our list
117 We select the given toolchain as our preferred one for its
118 architecture if it is a higher priority than the others.
121 fname: Filename of toolchain's gcc driver
122 test: True to run the toolchain to test it
124 toolchain = Toolchain(fname, test, verbose)
125 add_it = toolchain.ok
126 if toolchain.arch in self.toolchains:
127 add_it = (toolchain.priority <
128 self.toolchains[toolchain.arch].priority)
130 self.toolchains[toolchain.arch] = toolchain
132 def Scan(self, verbose):
133 """Scan for available toolchains and select the best for each arch.
135 We look for all the toolchains we can file, figure out the
136 architecture for each, and whether it works. Then we select the
137 highest priority toolchain for each arch.
140 verbose: True to print out progress information
142 if verbose: print 'Scanning for tool chains'
143 for path in self.paths:
144 if verbose: print " - scanning path '%s'" % path
145 for subdir in ['.', 'bin', 'usr/bin']:
146 dirname = os.path.join(path, subdir)
147 if verbose: print " - looking in '%s'" % dirname
148 for fname in glob.glob(dirname + '/*gcc'):
149 if verbose: print " - found '%s'" % fname
150 self.Add(fname, True, verbose)
153 """List out the selected toolchains for each architecture"""
154 print 'List of available toolchains (%d):' % len(self.toolchains)
155 if len(self.toolchains):
156 for key, value in sorted(self.toolchains.iteritems()):
157 print '%-10s: %s' % (key, value.gcc)
161 def Select(self, arch):
162 """Returns the toolchain for a given architecture
165 args: Name of architecture (e.g. 'arm', 'ppc_8xx')
168 toolchain object, or None if none found
170 for name, value in bsettings.GetItems('toolchain-alias'):
174 if not arch in self.toolchains:
175 raise ValueError, ("No tool chain found for arch '%s'" % arch)
176 return self.toolchains[arch]
178 def ResolveReferences(self, var_dict, args):
179 """Resolve variable references in a string
181 This converts ${blah} within the string to the value of blah.
182 This function works recursively.
185 var_dict: Dictionary containing variables and their values
186 args: String containing make arguments
190 >>> bsettings.Setup()
191 >>> tcs = Toolchains()
192 >>> tcs.Add('fred', False)
193 >>> var_dict = {'oblique' : 'OBLIQUE', 'first' : 'fi${second}rst', \
195 >>> tcs.ResolveReferences(var_dict, 'this=${oblique}_set')
197 >>> tcs.ResolveReferences(var_dict, 'this=${oblique}_set${first}nd')
198 'this=OBLIQUE_setfi2ndrstnd'
200 re_var = re.compile('(\$\{[a-z0-9A-Z]{1,}\})')
203 m = re_var.search(args)
206 lookup = m.group(0)[2:-1]
207 value = var_dict.get(lookup, '')
208 args = args[:m.start(0)] + value + args[m.end(0):]
211 def GetMakeArguments(self, board):
212 """Returns 'make' arguments for a given board
214 The flags are in a section called 'make-flags'. Flags are named
215 after the target they represent, for example snapper9260=TESTING=1
216 will pass TESTING=1 to make when building the snapper9260 board.
218 References to other boards can be added in the string also. For
222 at91-boards=ENABLE_AT91_TEST=1
223 snapper9260=${at91-boards} BUILD_TAG=442
224 snapper9g45=${at91-boards} BUILD_TAG=443
226 This will return 'ENABLE_AT91_TEST=1 BUILD_TAG=442' for snapper9260
227 and 'ENABLE_AT91_TEST=1 BUILD_TAG=443' for snapper9g45.
229 A special 'target' variable is set to the board target.
232 board: Board object for the board to check.
234 'make' flags for that board, or '' if none
236 self._make_flags['target'] = board.target
237 arg_str = self.ResolveReferences(self._make_flags,
238 self._make_flags.get(board.target, ''))
239 args = arg_str.split(' ')