]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - tools/buildman/toolchain.py
dfa1d00ce27a3d58dcb9eb2bce1d7c666e01c740
[karo-tx-uboot.git] / tools / buildman / toolchain.py
1 # Copyright (c) 2012 The Chromium OS Authors.
2 #
3 # SPDX-License-Identifier:      GPL-2.0+
4 #
5
6 import glob
7 import os
8
9 import bsettings
10 import command
11
12 class Toolchain:
13     """A single toolchain
14
15     Public members:
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
21     """
22
23     def __init__(self, fname, test, verbose=False):
24         """Create a new toolchain object.
25
26         Args:
27             fname: Filename of the gcc component
28             test: True to run the toolchain to test it
29         """
30         self.gcc = fname
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'
35
36         env = self.MakeEnvironment()
37
38         # As a basic sanity check, run the C compiler with --version
39         cmd = [fname, '--version']
40         if test:
41             result = command.RunPipe([cmd], capture=True, env=env)
42             self.ok = result.return_code == 0
43             if verbose:
44                 print 'Tool chain test: ',
45                 if self.ok:
46                     print 'OK'
47                 else:
48                     print 'BAD'
49                     print 'Command: ', cmd
50                     print result.stdout
51                     print result.stderr
52         else:
53             self.ok = True
54         self.priority = self.GetPriority(fname)
55
56     def GetPriority(self, fname):
57         """Return the priority of the toolchain.
58
59         Toolchains are ranked according to their suitability by their
60         filename prefix.
61
62         Args:
63             fname: Filename of toolchain
64         Returns:
65             Priority of toolchain, 0=highest, 20=lowest.
66         """
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:
72                 return prio
73         return prio
74
75     def MakeEnvironment(self):
76         """Returns an environment for using the toolchain.
77
78         Thie takes the current environment, adds CROSS_COMPILE and
79         augments PATH so that the toolchain will operate correctly.
80         """
81         env = dict(os.environ)
82         env['CROSS_COMPILE'] = self.cross
83         env['PATH'] += (':' + self.path)
84         return env
85
86
87 class Toolchains:
88     """Manage a list of toolchains for building U-Boot
89
90     We select one toolchain for each architecture type
91
92     Public members:
93         toolchains: Dict of Toolchain objects, keyed by architecture name
94         paths: List of paths to check for toolchains (may contain wildcards)
95     """
96
97     def __init__(self):
98         self.toolchains = {}
99         self.paths = []
100         for name, value in bsettings.GetItems('toolchain'):
101             if '*' in value:
102                 self.paths += glob.glob(value)
103             else:
104                 self.paths.append(value)
105
106
107     def Add(self, fname, test=True, verbose=False):
108         """Add a toolchain to our list
109
110         We select the given toolchain as our preferred one for its
111         architecture if it is a higher priority than the others.
112
113         Args:
114             fname: Filename of toolchain's gcc driver
115             test: True to run the toolchain to test it
116         """
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)
122         if add_it:
123             self.toolchains[toolchain.arch] = toolchain
124
125     def Scan(self, verbose):
126         """Scan for available toolchains and select the best for each arch.
127
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.
131
132         Args:
133             verbose: True to print out progress information
134         """
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)
144
145     def List(self):
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)
151         else:
152             print 'None'
153
154     def Select(self, arch):
155         """Returns the toolchain for a given architecture
156
157         Args:
158             args: Name of architecture (e.g. 'arm', 'ppc_8xx')
159
160         returns:
161             toolchain object, or None if none found
162         """
163         for name, value in bsettings.GetItems('toolchain-alias'):
164             if arch == name:
165                 arch = value
166
167         if not arch in self.toolchains:
168             raise ValueError, ("No tool chain found for arch '%s'" % arch)
169         return self.toolchains[arch]