]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - tools/buildman/toolchain.py
Merge branch 'u-boot-imx/master' into 'u-boot-arm/master'
[karo-tx-uboot.git] / tools / buildman / toolchain.py
1 # Copyright (c) 2012 The Chromium OS Authors.
2 #
3 # See file CREDITS for list of people who contributed to this
4 # project.
5 #
6 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU General Public License as
8 # published by the Free Software Foundation; either version 2 of
9 # the License, or (at your option) any later version.
10 #
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 # GNU General Public License for more details.
15 #
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 59 Temple Place, Suite 330, Boston,
19 # MA 02111-1307 USA
20 #
21
22 import glob
23 import os
24
25 import bsettings
26 import command
27
28 class Toolchain:
29     """A single toolchain
30
31     Public members:
32         gcc: Full path to C compiler
33         path: Directory path containing C compiler
34         cross: Cross compile string, e.g. 'arm-linux-'
35         arch: Architecture of toolchain as determined from the first
36                 component of the filename. E.g. arm-linux-gcc becomes arm
37     """
38
39     def __init__(self, fname, test, verbose=False):
40         """Create a new toolchain object.
41
42         Args:
43             fname: Filename of the gcc component
44             test: True to run the toolchain to test it
45         """
46         self.gcc = fname
47         self.path = os.path.dirname(fname)
48         self.cross = os.path.basename(fname)[:-3]
49         pos = self.cross.find('-')
50         self.arch = self.cross[:pos] if pos != -1 else 'sandbox'
51
52         env = self.MakeEnvironment()
53
54         # As a basic sanity check, run the C compiler with --version
55         cmd = [fname, '--version']
56         if test:
57             result = command.RunPipe([cmd], capture=True, env=env)
58             self.ok = result.return_code == 0
59             if verbose:
60                 print 'Tool chain test: ',
61                 if self.ok:
62                     print 'OK'
63                 else:
64                     print 'BAD'
65                     print 'Command: ', cmd
66                     print result.stdout
67                     print result.stderr
68         else:
69             self.ok = True
70         self.priority = self.GetPriority(fname)
71
72     def GetPriority(self, fname):
73         """Return the priority of the toolchain.
74
75         Toolchains are ranked according to their suitability by their
76         filename prefix.
77
78         Args:
79             fname: Filename of toolchain
80         Returns:
81             Priority of toolchain, 0=highest, 20=lowest.
82         """
83         priority_list = ['-elf', '-unknown-linux-gnu', '-linux', '-elf',
84             '-none-linux-gnueabi', '-uclinux', '-none-eabi',
85             '-gentoo-linux-gnu', '-linux-gnueabi', '-le-linux', '-uclinux']
86         for prio in range(len(priority_list)):
87             if priority_list[prio] in fname:
88                 return prio
89         return prio
90
91     def MakeEnvironment(self):
92         """Returns an environment for using the toolchain.
93
94         Thie takes the current environment, adds CROSS_COMPILE and
95         augments PATH so that the toolchain will operate correctly.
96         """
97         env = dict(os.environ)
98         env['CROSS_COMPILE'] = self.cross
99         env['PATH'] += (':' + self.path)
100         return env
101
102
103 class Toolchains:
104     """Manage a list of toolchains for building U-Boot
105
106     We select one toolchain for each architecture type
107
108     Public members:
109         toolchains: Dict of Toolchain objects, keyed by architecture name
110         paths: List of paths to check for toolchains (may contain wildcards)
111     """
112
113     def __init__(self):
114         self.toolchains = {}
115         self.paths = []
116         for name, value in bsettings.GetItems('toolchain'):
117             if '*' in value:
118                 self.paths += glob.glob(value)
119             else:
120                 self.paths.append(value)
121
122
123     def Add(self, fname, test=True, verbose=False):
124         """Add a toolchain to our list
125
126         We select the given toolchain as our preferred one for its
127         architecture if it is a higher priority than the others.
128
129         Args:
130             fname: Filename of toolchain's gcc driver
131             test: True to run the toolchain to test it
132         """
133         toolchain = Toolchain(fname, test, verbose)
134         add_it = toolchain.ok
135         if toolchain.arch in self.toolchains:
136             add_it = (toolchain.priority <
137                         self.toolchains[toolchain.arch].priority)
138         if add_it:
139             self.toolchains[toolchain.arch] = toolchain
140
141     def Scan(self, verbose):
142         """Scan for available toolchains and select the best for each arch.
143
144         We look for all the toolchains we can file, figure out the
145         architecture for each, and whether it works. Then we select the
146         highest priority toolchain for each arch.
147
148         Args:
149             verbose: True to print out progress information
150         """
151         if verbose: print 'Scanning for tool chains'
152         for path in self.paths:
153             if verbose: print "   - scanning path '%s'" % path
154             for subdir in ['.', 'bin', 'usr/bin']:
155                 dirname = os.path.join(path, subdir)
156                 if verbose: print "      - looking in '%s'" % dirname
157                 for fname in glob.glob(dirname + '/*gcc'):
158                     if verbose: print "         - found '%s'" % fname
159                     self.Add(fname, True, verbose)
160
161     def List(self):
162         """List out the selected toolchains for each architecture"""
163         print 'List of available toolchains (%d):' % len(self.toolchains)
164         if len(self.toolchains):
165             for key, value in sorted(self.toolchains.iteritems()):
166                 print '%-10s: %s' % (key, value.gcc)
167         else:
168             print 'None'
169
170     def Select(self, arch):
171         """Returns the toolchain for a given architecture
172
173         Args:
174             args: Name of architecture (e.g. 'arm', 'ppc_8xx')
175
176         returns:
177             toolchain object, or None if none found
178         """
179         for name, value in bsettings.GetItems('toolchain-alias'):
180             if arch == name:
181                 arch = value
182
183         if not arch in self.toolchains:
184             raise ValueError, ("No tool chain found for arch '%s'" % arch)
185         return self.toolchains[arch]