]> Git Repo - J-u-boot.git/blame - tools/buildman/toolchain.py
tools: kwbimage: Set BOOT_FROM by default to SPI
[J-u-boot.git] / tools / buildman / toolchain.py
CommitLineData
83d290c5 1# SPDX-License-Identifier: GPL-2.0+
fc3fe1c2
SG
2# Copyright (c) 2012 The Chromium OS Authors.
3#
fc3fe1c2 4
4281ad8e 5import re
fc3fe1c2 6import glob
c05aa036 7from html.parser import HTMLParser
fc3fe1c2 8import os
827e37b5
SG
9import sys
10import tempfile
c05aa036 11import urllib.request, urllib.error, urllib.parse
fc3fe1c2 12
0ede00fd 13from buildman import bsettings
bf776679
SG
14from patman import command
15from patman import terminal
16from patman import tools
fc3fe1c2 17
17bce66c 18(PRIORITY_FULL_PREFIX, PRIORITY_PREFIX_GCC, PRIORITY_PREFIX_GCC_PATH,
c05aa036 19 PRIORITY_CALC) = list(range(4))
ff690df9 20
57cb9d52
SG
21(VAR_CROSS_COMPILE, VAR_PATH, VAR_ARCH, VAR_MAKE_ARGS) = range(4)
22
827e37b5
SG
23# Simple class to collect links from a page
24class MyHTMLParser(HTMLParser):
25 def __init__(self, arch):
26 """Create a new parser
27
28 After the parser runs, self.links will be set to a list of the links
29 to .xz archives found in the page, and self.arch_link will be set to
30 the one for the given architecture (or None if not found).
31
32 Args:
33 arch: Architecture to search for
34 """
35 HTMLParser.__init__(self)
36 self.arch_link = None
37 self.links = []
4c58d273 38 self.re_arch = re.compile('[-_]%s-' % arch)
827e37b5
SG
39
40 def handle_starttag(self, tag, attrs):
41 if tag == 'a':
42 for tag, value in attrs:
43 if tag == 'href':
44 if value and value.endswith('.xz'):
45 self.links.append(value)
4c58d273 46 if self.re_arch.search(value):
827e37b5
SG
47 self.arch_link = value
48
49
fc3fe1c2
SG
50class Toolchain:
51 """A single toolchain
52
53 Public members:
54 gcc: Full path to C compiler
55 path: Directory path containing C compiler
56 cross: Cross compile string, e.g. 'arm-linux-'
57 arch: Architecture of toolchain as determined from the first
58 component of the filename. E.g. arm-linux-gcc becomes arm
ff690df9 59 priority: Toolchain priority (0=highest, 20=lowest)
00beb248
SG
60 override_toolchain: Toolchain to use for sandbox, overriding the normal
61 one
fc3fe1c2 62 """
608e399f 63 def __init__(self, fname, test, verbose=False, priority=PRIORITY_CALC,
00beb248 64 arch=None, override_toolchain=None):
fc3fe1c2
SG
65 """Create a new toolchain object.
66
67 Args:
68 fname: Filename of the gcc component
69 test: True to run the toolchain to test it
ad24ebac 70 verbose: True to print out the information
ff690df9
SG
71 priority: Priority to use for this toolchain, or PRIORITY_CALC to
72 calculate it
fc3fe1c2
SG
73 """
74 self.gcc = fname
75 self.path = os.path.dirname(fname)
00beb248 76 self.override_toolchain = override_toolchain
b5324123
SG
77
78 # Find the CROSS_COMPILE prefix to use for U-Boot. For example,
79 # 'arm-linux-gnueabihf-gcc' turns into 'arm-linux-gnueabihf-'.
80 basename = os.path.basename(fname)
81 pos = basename.rfind('-')
82 self.cross = basename[:pos + 1] if pos != -1 else ''
83
84 # The architecture is the first part of the name
fc3fe1c2 85 pos = self.cross.find('-')
608e399f
SG
86 if arch:
87 self.arch = arch
88 else:
89 self.arch = self.cross[:pos] if pos != -1 else 'sandbox'
00beb248
SG
90 if self.arch == 'sandbox' and override_toolchain:
91 self.gcc = override_toolchain
fc3fe1c2 92
bb1501f2 93 env = self.MakeEnvironment(False)
fc3fe1c2
SG
94
95 # As a basic sanity check, run the C compiler with --version
96 cmd = [fname, '--version']
ff690df9
SG
97 if priority == PRIORITY_CALC:
98 self.priority = self.GetPriority(fname)
99 else:
100 self.priority = priority
fc3fe1c2 101 if test:
8bb2bddc
SW
102 result = command.RunPipe([cmd], capture=True, env=env,
103 raise_on_error=False)
fc3fe1c2
SG
104 self.ok = result.return_code == 0
105 if verbose:
c05aa036 106 print('Tool chain test: ', end=' ')
fc3fe1c2 107 if self.ok:
c05aa036
SG
108 print("OK, arch='%s', priority %d" % (self.arch,
109 self.priority))
fc3fe1c2 110 else:
c05aa036
SG
111 print('BAD')
112 print('Command: ', cmd)
113 print(result.stdout)
114 print(result.stderr)
fc3fe1c2
SG
115 else:
116 self.ok = True
fc3fe1c2
SG
117
118 def GetPriority(self, fname):
119 """Return the priority of the toolchain.
120
121 Toolchains are ranked according to their suitability by their
122 filename prefix.
123
124 Args:
125 fname: Filename of toolchain
126 Returns:
ff690df9 127 Priority of toolchain, PRIORITY_CALC=highest, 20=lowest.
fc3fe1c2 128 """
8708267f 129 priority_list = ['-elf', '-unknown-linux-gnu', '-linux',
546a6f3a
TR
130 '-none-linux-gnueabi', '-none-linux-gnueabihf', '-uclinux',
131 '-none-eabi', '-gentoo-linux-gnu', '-linux-gnueabi',
132 '-linux-gnueabihf', '-le-linux', '-uclinux']
fc3fe1c2
SG
133 for prio in range(len(priority_list)):
134 if priority_list[prio] in fname:
ff690df9
SG
135 return PRIORITY_CALC + prio
136 return PRIORITY_CALC + prio
fc3fe1c2 137
d5fe013c
YS
138 def GetWrapper(self, show_warning=True):
139 """Get toolchain wrapper from the setting file.
140 """
ccd2979a
SG
141 value = ''
142 for name, value in bsettings.GetItems('toolchain-wrapper'):
d5fe013c 143 if not value:
c05aa036 144 print("Warning: Wrapper not found")
d5fe013c
YS
145 if value:
146 value = value + ' '
147
148 return value
149
57cb9d52
SG
150 def GetEnvArgs(self, which):
151 """Get an environment variable/args value based on the the toolchain
152
153 Args:
154 which: VAR_... value to get
155
156 Returns:
157 Value of that environment variable or arguments
158 """
159 wrapper = self.GetWrapper()
160 if which == VAR_CROSS_COMPILE:
161 return wrapper + os.path.join(self.path, self.cross)
162 elif which == VAR_PATH:
163 return self.path
164 elif which == VAR_ARCH:
165 return self.arch
166 elif which == VAR_MAKE_ARGS:
167 args = self.MakeArgs()
168 if args:
169 return ' '.join(args)
170 return ''
171 else:
172 raise ValueError('Unknown arg to GetEnvArgs (%d)' % which)
173
bb1501f2 174 def MakeEnvironment(self, full_path):
fc3fe1c2
SG
175 """Returns an environment for using the toolchain.
176
bb1501f2 177 Thie takes the current environment and adds CROSS_COMPILE so that
b0e994c2
DS
178 the tool chain will operate correctly. This also disables localized
179 output and possibly unicode encoded output of all build tools by
180 adding LC_ALL=C.
bb1501f2 181
f1a83abe
SG
182 Note that os.environb is used to obtain the environment, since in some
183 cases the environment many contain non-ASCII characters and we see
184 errors like:
185
186 UnicodeEncodeError: 'utf-8' codec can't encode characters in position
187 569-570: surrogates not allowed
188
bb1501f2
SG
189 Args:
190 full_path: Return the full path in CROSS_COMPILE and don't set
191 PATH
00beb248 192 Returns:
f1a83abe
SG
193 Dict containing the (bytes) environment to use. This is based on the
194 current environment, with changes as needed to CROSS_COMPILE, PATH
195 and LC_ALL.
fc3fe1c2 196 """
f1a83abe 197 env = dict(os.environb)
d5fe013c
YS
198 wrapper = self.GetWrapper()
199
00beb248
SG
200 if self.override_toolchain:
201 # We'll use MakeArgs() to provide this
202 pass
203 elif full_path:
f1a83abe
SG
204 env[b'CROSS_COMPILE'] = tools.ToBytes(
205 wrapper + os.path.join(self.path, self.cross))
bb1501f2 206 else:
f1a83abe
SG
207 env[b'CROSS_COMPILE'] = tools.ToBytes(wrapper + self.cross)
208 env[b'PATH'] = tools.ToBytes(self.path) + b':' + env[b'PATH']
bb1501f2 209
f1a83abe 210 env[b'LC_ALL'] = b'C'
b0e994c2 211
fc3fe1c2
SG
212 return env
213
00beb248
SG
214 def MakeArgs(self):
215 """Create the 'make' arguments for a toolchain
216
217 This is only used when the toolchain is being overridden. Since the
218 U-Boot Makefile sets CC and HOSTCC explicitly we cannot rely on the
219 environment (and MakeEnvironment()) to override these values. This
220 function returns the arguments to accomplish this.
221
222 Returns:
223 List of arguments to pass to 'make'
224 """
225 if self.override_toolchain:
226 return ['HOSTCC=%s' % self.override_toolchain,
227 'CC=%s' % self.override_toolchain]
228 return []
229
fc3fe1c2
SG
230
231class Toolchains:
232 """Manage a list of toolchains for building U-Boot
233
234 We select one toolchain for each architecture type
235
236 Public members:
237 toolchains: Dict of Toolchain objects, keyed by architecture name
17bce66c
SG
238 prefixes: Dict of prefixes to check, keyed by architecture. This can
239 be a full path and toolchain prefix, for example
240 {'x86', 'opt/i386-linux/bin/i386-linux-'}, or the name of
241 something on the search path, for example
242 {'arm', 'arm-linux-gnueabihf-'}. Wildcards are not supported.
fc3fe1c2
SG
243 paths: List of paths to check for toolchains (may contain wildcards)
244 """
245
00beb248 246 def __init__(self, override_toolchain=None):
fc3fe1c2 247 self.toolchains = {}
17bce66c 248 self.prefixes = {}
fc3fe1c2 249 self.paths = []
00beb248 250 self.override_toolchain = override_toolchain
d4144e45
SG
251 self._make_flags = dict(bsettings.GetItems('make-flags'))
252
80e6a487 253 def GetPathList(self, show_warning=True):
827e37b5
SG
254 """Get a list of available toolchain paths
255
80e6a487
SG
256 Args:
257 show_warning: True to show a warning if there are no tool chains.
258
827e37b5
SG
259 Returns:
260 List of strings, each a path to a toolchain mentioned in the
261 [toolchain] section of the settings file.
262 """
4281ad8e 263 toolchains = bsettings.GetItems('toolchain')
80e6a487 264 if show_warning and not toolchains:
c05aa036 265 print(("Warning: No tool chains. Please run 'buildman "
713bea38
SG
266 "--fetch-arch all' to download all available toolchains, or "
267 "add a [toolchain] section to your buildman config file "
268 "%s. See README for details" %
c05aa036 269 bsettings.config_fname))
4281ad8e 270
827e37b5 271 paths = []
4281ad8e 272 for name, value in toolchains:
fc3fe1c2 273 if '*' in value:
827e37b5 274 paths += glob.glob(value)
fc3fe1c2 275 else:
827e37b5
SG
276 paths.append(value)
277 return paths
278
80e6a487
SG
279 def GetSettings(self, show_warning=True):
280 """Get toolchain settings from the settings file.
281
282 Args:
283 show_warning: True to show a warning if there are no tool chains.
284 """
285 self.prefixes = bsettings.GetItems('toolchain-prefix')
286 self.paths += self.GetPathList(show_warning)
fc3fe1c2 287
608e399f
SG
288 def Add(self, fname, test=True, verbose=False, priority=PRIORITY_CALC,
289 arch=None):
fc3fe1c2
SG
290 """Add a toolchain to our list
291
292 We select the given toolchain as our preferred one for its
293 architecture if it is a higher priority than the others.
294
295 Args:
296 fname: Filename of toolchain's gcc driver
297 test: True to run the toolchain to test it
ff690df9 298 priority: Priority to use for this toolchain
608e399f 299 arch: Toolchain architecture, or None if not known
fc3fe1c2 300 """
00beb248
SG
301 toolchain = Toolchain(fname, test, verbose, priority, arch,
302 self.override_toolchain)
fc3fe1c2
SG
303 add_it = toolchain.ok
304 if toolchain.arch in self.toolchains:
305 add_it = (toolchain.priority <
306 self.toolchains[toolchain.arch].priority)
307 if add_it:
308 self.toolchains[toolchain.arch] = toolchain
ff690df9 309 elif verbose:
c05aa036 310 print(("Toolchain '%s' at priority %d will be ignored because "
ff690df9
SG
311 "another toolchain for arch '%s' has priority %d" %
312 (toolchain.gcc, toolchain.priority, toolchain.arch,
c05aa036 313 self.toolchains[toolchain.arch].priority)))
fc3fe1c2 314
827e37b5
SG
315 def ScanPath(self, path, verbose):
316 """Scan a path for a valid toolchain
317
318 Args:
319 path: Path to scan
320 verbose: True to print out progress information
321 Returns:
322 Filename of C compiler if found, else None
323 """
d9088983 324 fnames = []
827e37b5
SG
325 for subdir in ['.', 'bin', 'usr/bin']:
326 dirname = os.path.join(path, subdir)
c05aa036 327 if verbose: print(" - looking in '%s'" % dirname)
827e37b5 328 for fname in glob.glob(dirname + '/*gcc'):
c05aa036 329 if verbose: print(" - found '%s'" % fname)
d9088983
AA
330 fnames.append(fname)
331 return fnames
827e37b5 332
17bce66c
SG
333 def ScanPathEnv(self, fname):
334 """Scan the PATH environment variable for a given filename.
335
336 Args:
337 fname: Filename to scan for
338 Returns:
339 List of matching pathanames, or [] if none
340 """
341 pathname_list = []
342 for path in os.environ["PATH"].split(os.pathsep):
343 path = path.strip('"')
344 pathname = os.path.join(path, fname)
345 if os.path.exists(pathname):
346 pathname_list.append(pathname)
347 return pathname_list
827e37b5 348
fc3fe1c2
SG
349 def Scan(self, verbose):
350 """Scan for available toolchains and select the best for each arch.
351
352 We look for all the toolchains we can file, figure out the
353 architecture for each, and whether it works. Then we select the
354 highest priority toolchain for each arch.
355
356 Args:
357 verbose: True to print out progress information
358 """
c05aa036 359 if verbose: print('Scanning for tool chains')
17bce66c 360 for name, value in self.prefixes:
c05aa036 361 if verbose: print(" - scanning prefix '%s'" % value)
17bce66c
SG
362 if os.path.exists(value):
363 self.Add(value, True, verbose, PRIORITY_FULL_PREFIX, name)
364 continue
365 fname = value + 'gcc'
366 if os.path.exists(fname):
367 self.Add(fname, True, verbose, PRIORITY_PREFIX_GCC, name)
368 continue
369 fname_list = self.ScanPathEnv(fname)
370 for f in fname_list:
371 self.Add(f, True, verbose, PRIORITY_PREFIX_GCC_PATH, name)
372 if not fname_list:
c05aa036 373 raise ValueError("No tool chain found for prefix '%s'" %
17bce66c 374 value)
fc3fe1c2 375 for path in self.paths:
c05aa036 376 if verbose: print(" - scanning path '%s'" % path)
d9088983
AA
377 fnames = self.ScanPath(path, verbose)
378 for fname in fnames:
827e37b5 379 self.Add(fname, True, verbose)
fc3fe1c2
SG
380
381 def List(self):
382 """List out the selected toolchains for each architecture"""
713bea38 383 col = terminal.Color()
c05aa036
SG
384 print(col.Color(col.BLUE, 'List of available toolchains (%d):' %
385 len(self.toolchains)))
fc3fe1c2 386 if len(self.toolchains):
c05aa036
SG
387 for key, value in sorted(self.toolchains.items()):
388 print('%-10s: %s' % (key, value.gcc))
fc3fe1c2 389 else:
c05aa036 390 print('None')
fc3fe1c2
SG
391
392 def Select(self, arch):
393 """Returns the toolchain for a given architecture
394
395 Args:
396 args: Name of architecture (e.g. 'arm', 'ppc_8xx')
397
398 returns:
399 toolchain object, or None if none found
400 """
9b83bfdc
SG
401 for tag, value in bsettings.GetItems('toolchain-alias'):
402 if arch == tag:
403 for alias in value.split():
404 if alias in self.toolchains:
405 return self.toolchains[alias]
fc3fe1c2
SG
406
407 if not arch in self.toolchains:
c05aa036 408 raise ValueError("No tool chain found for arch '%s'" % arch)
fc3fe1c2 409 return self.toolchains[arch]
4281ad8e
SG
410
411 def ResolveReferences(self, var_dict, args):
412 """Resolve variable references in a string
413
414 This converts ${blah} within the string to the value of blah.
415 This function works recursively.
416
417 Args:
418 var_dict: Dictionary containing variables and their values
419 args: String containing make arguments
420 Returns:
421 Resolved string
422
423 >>> bsettings.Setup()
424 >>> tcs = Toolchains()
425 >>> tcs.Add('fred', False)
426 >>> var_dict = {'oblique' : 'OBLIQUE', 'first' : 'fi${second}rst', \
427 'second' : '2nd'}
428 >>> tcs.ResolveReferences(var_dict, 'this=${oblique}_set')
429 'this=OBLIQUE_set'
430 >>> tcs.ResolveReferences(var_dict, 'this=${oblique}_set${first}nd')
431 'this=OBLIQUE_setfi2ndrstnd'
432 """
f60c9d4f 433 re_var = re.compile('(\$\{[-_a-z0-9A-Z]{1,}\})')
4281ad8e
SG
434
435 while True:
436 m = re_var.search(args)
437 if not m:
438 break
439 lookup = m.group(0)[2:-1]
440 value = var_dict.get(lookup, '')
441 args = args[:m.start(0)] + value + args[m.end(0):]
442 return args
443
444 def GetMakeArguments(self, board):
445 """Returns 'make' arguments for a given board
446
447 The flags are in a section called 'make-flags'. Flags are named
448 after the target they represent, for example snapper9260=TESTING=1
449 will pass TESTING=1 to make when building the snapper9260 board.
450
451 References to other boards can be added in the string also. For
452 example:
453
454 [make-flags]
455 at91-boards=ENABLE_AT91_TEST=1
456 snapper9260=${at91-boards} BUILD_TAG=442
457 snapper9g45=${at91-boards} BUILD_TAG=443
458
459 This will return 'ENABLE_AT91_TEST=1 BUILD_TAG=442' for snapper9260
460 and 'ENABLE_AT91_TEST=1 BUILD_TAG=443' for snapper9g45.
461
462 A special 'target' variable is set to the board target.
463
464 Args:
465 board: Board object for the board to check.
466 Returns:
467 'make' flags for that board, or '' if none
468 """
469 self._make_flags['target'] = board.target
470 arg_str = self.ResolveReferences(self._make_flags,
471 self._make_flags.get(board.target, ''))
4251fbc6 472 args = re.findall("(?:\".*?\"|\S)+", arg_str)
4281ad8e
SG
473 i = 0
474 while i < len(args):
4251fbc6 475 args[i] = args[i].replace('"', '')
4281ad8e
SG
476 if not args[i]:
477 del args[i]
478 else:
479 i += 1
480 return args
827e37b5
SG
481
482 def LocateArchUrl(self, fetch_arch):
483 """Find a toolchain available online
484
485 Look in standard places for available toolchains. At present the
486 only standard place is at kernel.org.
487
488 Args:
489 arch: Architecture to look for, or 'list' for all
490 Returns:
491 If fetch_arch is 'list', a tuple:
492 Machine architecture (e.g. x86_64)
493 List of toolchains
494 else
495 URL containing this toolchain, if avaialble, else None
496 """
497 arch = command.OutputOneLine('uname', '-m')
2f7c53cb
MB
498 if arch == 'aarch64':
499 arch = 'arm64'
827e37b5 500 base = 'https://www.kernel.org/pub/tools/crosstool/files/bin'
f7832ee5 501 versions = ['11.1.0', '9.2.0', '7.3.0', '6.4.0', '4.9.4']
827e37b5
SG
502 links = []
503 for version in versions:
504 url = '%s/%s/%s/' % (base, arch, version)
c05aa036
SG
505 print('Checking: %s' % url)
506 response = urllib.request.urlopen(url)
507 html = tools.ToString(response.read())
827e37b5
SG
508 parser = MyHTMLParser(fetch_arch)
509 parser.feed(html)
510 if fetch_arch == 'list':
511 links += parser.links
512 elif parser.arch_link:
513 return url + parser.arch_link
514 if fetch_arch == 'list':
515 return arch, links
516 return None
517
518 def Download(self, url):
519 """Download a file to a temporary directory
520
521 Args:
522 url: URL to download
523 Returns:
524 Tuple:
525 Temporary directory name
526 Full path to the downloaded archive file in that directory,
527 or None if there was an error while downloading
528 """
c05aa036 529 print('Downloading: %s' % url)
827e37b5
SG
530 leaf = url.split('/')[-1]
531 tmpdir = tempfile.mkdtemp('.buildman')
c05aa036 532 response = urllib.request.urlopen(url)
827e37b5
SG
533 fname = os.path.join(tmpdir, leaf)
534 fd = open(fname, 'wb')
535 meta = response.info()
c05aa036 536 size = int(meta.get('Content-Length'))
827e37b5
SG
537 done = 0
538 block_size = 1 << 16
539 status = ''
540
541 # Read the file in chunks and show progress as we go
542 while True:
543 buffer = response.read(block_size)
544 if not buffer:
c05aa036 545 print(chr(8) * (len(status) + 1), '\r', end=' ')
827e37b5
SG
546 break
547
548 done += len(buffer)
549 fd.write(buffer)
c05aa036
SG
550 status = r'%10d MiB [%3d%%]' % (done // 1024 // 1024,
551 done * 100 // size)
827e37b5 552 status = status + chr(8) * (len(status) + 1)
c05aa036 553 print(status, end=' ')
827e37b5
SG
554 sys.stdout.flush()
555 fd.close()
556 if done != size:
c05aa036 557 print('Error, failed to download')
827e37b5
SG
558 os.remove(fname)
559 fname = None
560 return tmpdir, fname
561
562 def Unpack(self, fname, dest):
563 """Unpack a tar file
564
565 Args:
566 fname: Filename to unpack
567 dest: Destination directory
568 Returns:
569 Directory name of the first entry in the archive, without the
570 trailing /
571 """
572 stdout = command.Output('tar', 'xvfJ', fname, '-C', dest)
d82f539a
TW
573 dirs = stdout.splitlines()[1].split('/')[:2]
574 return '/'.join(dirs)
827e37b5
SG
575
576 def TestSettingsHasPath(self, path):
2289b276 577 """Check if buildman will find this toolchain
827e37b5
SG
578
579 Returns:
580 True if the path is in settings, False if not
581 """
80e6a487 582 paths = self.GetPathList(False)
827e37b5
SG
583 return path in paths
584
585 def ListArchs(self):
586 """List architectures with available toolchains to download"""
587 host_arch, archives = self.LocateArchUrl('list')
b11f1264 588 re_arch = re.compile('[-a-z0-9.]*[-_]([^-]*)-.*')
827e37b5
SG
589 arch_set = set()
590 for archive in archives:
591 # Remove the host architecture from the start
592 arch = re_arch.match(archive[len(host_arch):])
593 if arch:
b11f1264
TW
594 if arch.group(1) != '2.0' and arch.group(1) != '64':
595 arch_set.add(arch.group(1))
827e37b5
SG
596 return sorted(arch_set)
597
598 def FetchAndInstall(self, arch):
599 """Fetch and install a new toolchain
600
601 arch:
602 Architecture to fetch, or 'list' to list
603 """
604 # Fist get the URL for this architecture
713bea38 605 col = terminal.Color()
c05aa036 606 print(col.Color(col.BLUE, "Downloading toolchain for arch '%s'" % arch))
827e37b5
SG
607 url = self.LocateArchUrl(arch)
608 if not url:
c05aa036
SG
609 print(("Cannot find toolchain for arch '%s' - use 'list' to list" %
610 arch))
827e37b5
SG
611 return 2
612 home = os.environ['HOME']
613 dest = os.path.join(home, '.buildman-toolchains')
614 if not os.path.exists(dest):
615 os.mkdir(dest)
616
617 # Download the tar file for this toolchain and unpack it
618 tmpdir, tarfile = self.Download(url)
619 if not tarfile:
620 return 1
c05aa036 621 print(col.Color(col.GREEN, 'Unpacking to: %s' % dest), end=' ')
827e37b5
SG
622 sys.stdout.flush()
623 path = self.Unpack(tarfile, dest)
624 os.remove(tarfile)
625 os.rmdir(tmpdir)
c05aa036 626 print()
827e37b5
SG
627
628 # Check that the toolchain works
c05aa036 629 print(col.Color(col.GREEN, 'Testing'))
827e37b5 630 dirpath = os.path.join(dest, path)
2a76a649
SG
631 compiler_fname_list = self.ScanPath(dirpath, True)
632 if not compiler_fname_list:
c05aa036 633 print('Could not locate C compiler - fetch failed.')
827e37b5 634 return 1
2a76a649 635 if len(compiler_fname_list) != 1:
c05aa036
SG
636 print(col.Color(col.RED, 'Warning, ambiguous toolchains: %s' %
637 ', '.join(compiler_fname_list)))
2a76a649 638 toolchain = Toolchain(compiler_fname_list[0], True, True)
827e37b5
SG
639
640 # Make sure that it will be found by buildman
641 if not self.TestSettingsHasPath(dirpath):
c05aa036
SG
642 print(("Adding 'download' to config file '%s'" %
643 bsettings.config_fname))
c8785c5b 644 bsettings.SetItem('toolchain', 'download', '%s/*/*' % dest)
827e37b5 645 return 0
This page took 0.433372 seconds and 4 git commands to generate.