]> git.donarmstrong.com Git - qmk_firmware.git/blob - tool/mbed/mbed-sdk/workspace_tools/toolchains/__init__.py
Squashed 'tmk_core/' changes from 7967731..b9e0ea0
[qmk_firmware.git] / tool / mbed / mbed-sdk / workspace_tools / toolchains / __init__.py
1 """
2 mbed SDK
3 Copyright (c) 2011-2013 ARM Limited
4
5 Licensed under the Apache License, Version 2.0 (the "License");
6 you may not use this file except in compliance with the License.
7 You may obtain a copy of the License at
8
9     http://www.apache.org/licenses/LICENSE-2.0
10
11 Unless required by applicable law or agreed to in writing, software
12 distributed under the License is distributed on an "AS IS" BASIS,
13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 See the License for the specific language governing permissions and
15 limitations under the License.
16 """
17
18 import re
19 import sys
20 from os import stat, walk
21 from copy import copy
22 from time import time, sleep
23 from types import ListType
24 from shutil import copyfile
25 from os.path import join, splitext, exists, relpath, dirname, basename, split
26 from inspect import getmro
27
28 from multiprocessing import Pool, cpu_count
29 from workspace_tools.utils import run_cmd, mkdir, rel_path, ToolException, split_path
30 from workspace_tools.settings import BUILD_OPTIONS, MBED_ORG_USER
31 import workspace_tools.hooks as hooks
32
33
34 #Disables multiprocessing if set to higher number than the host machine CPUs
35 CPU_COUNT_MIN = 1
36
37 def print_notify(event, silent=False):
38     """ Default command line notification
39     """
40     if event['type'] in ['info', 'debug']:
41         print event['message']
42
43     elif event['type'] == 'cc':
44         event['severity'] = event['severity'].title()
45         event['file'] = basename(event['file'])
46         print '[%(severity)s] %(file)s@%(line)s: %(message)s' % event
47
48     elif event['type'] == 'progress':
49         if not silent:
50             print '%s: %s' % (event['action'].title(), basename(event['file']))
51
52 def print_notify_verbose(event, silent=False):
53     """ Default command line notification with more verbose mode
54     """
55     if event['type'] in ['info', 'debug']:
56         print_notify(event) # standard handle
57
58     elif event['type'] == 'cc':
59         event['severity'] = event['severity'].title()
60         event['file'] = basename(event['file'])
61         event['mcu_name'] = "None"
62         event['toolchain'] = "None"
63         event['target_name'] = event['target_name'].upper() if event['target_name'] else "Unknown"
64         event['toolchain_name'] = event['toolchain_name'].upper() if event['toolchain_name'] else "Unknown"
65         print '[%(severity)s] %(target_name)s::%(toolchain_name)s::%(file)s@%(line)s: %(message)s' % event
66
67     elif event['type'] == 'progress':
68         print_notify(event) # standard handle
69
70 def compile_worker(job):
71     results = []
72     for command in job['commands']:
73         _, _stderr, _rc = run_cmd(command, job['work_dir'])
74         results.append({
75             'code': _rc,
76             'output': _stderr,
77             'command': command
78         })
79
80     return {
81         'source': job['source'],
82         'object': job['object'],
83         'commands': job['commands'],
84         'results': results
85     }
86
87 class Resources:
88     def __init__(self, base_path=None):
89         self.base_path = base_path
90
91         self.inc_dirs = []
92         self.headers = []
93
94         self.s_sources = []
95         self.c_sources = []
96         self.cpp_sources = []
97
98         self.lib_dirs = set([])
99         self.objects = []
100         self.libraries = []
101
102         # mbed special files
103         self.lib_builds = []
104         self.lib_refs = []
105
106         self.repo_dirs = []
107         self.repo_files = []
108
109         self.linker_script = None
110
111         # Other files
112         self.hex_files = []
113         self.bin_files = []
114
115     def add(self, resources):
116         self.inc_dirs += resources.inc_dirs
117         self.headers += resources.headers
118
119         self.s_sources += resources.s_sources
120         self.c_sources += resources.c_sources
121         self.cpp_sources += resources.cpp_sources
122
123         self.lib_dirs |= resources.lib_dirs
124         self.objects += resources.objects
125         self.libraries += resources.libraries
126
127         self.lib_builds += resources.lib_builds
128         self.lib_refs += resources.lib_refs
129
130         self.repo_dirs += resources.repo_dirs
131         self.repo_files += resources.repo_files
132
133         if resources.linker_script is not None:
134             self.linker_script = resources.linker_script
135
136         self.hex_files += resources.hex_files
137         self.bin_files += resources.bin_files
138
139     def relative_to(self, base, dot=False):
140         for field in ['inc_dirs', 'headers', 's_sources', 'c_sources',
141                       'cpp_sources', 'lib_dirs', 'objects', 'libraries',
142                       'lib_builds', 'lib_refs', 'repo_dirs', 'repo_files', 'hex_files', 'bin_files']:
143             v = [rel_path(f, base, dot) for f in getattr(self, field)]
144             setattr(self, field, v)
145         if self.linker_script is not None:
146             self.linker_script = rel_path(self.linker_script, base, dot)
147
148     def win_to_unix(self):
149         for field in ['inc_dirs', 'headers', 's_sources', 'c_sources',
150                       'cpp_sources', 'lib_dirs', 'objects', 'libraries',
151                       'lib_builds', 'lib_refs', 'repo_dirs', 'repo_files', 'hex_files', 'bin_files']:
152             v = [f.replace('\\', '/') for f in getattr(self, field)]
153             setattr(self, field, v)
154         if self.linker_script is not None:
155             self.linker_script = self.linker_script.replace('\\', '/')
156
157     def __str__(self):
158         s = []
159
160         for (label, resources) in (
161                 ('Include Directories', self.inc_dirs),
162                 ('Headers', self.headers),
163
164                 ('Assembly sources', self.s_sources),
165                 ('C sources', self.c_sources),
166                 ('C++ sources', self.cpp_sources),
167
168                 ('Library directories', self.lib_dirs),
169                 ('Objects', self.objects),
170                 ('Libraries', self.libraries),
171
172                 ('Hex files', self.hex_files),
173                 ('Bin files', self.bin_files),
174             ):
175             if resources:
176                 s.append('%s:\n  ' % label + '\n  '.join(resources))
177
178         if self.linker_script:
179             s.append('Linker Script: ' + self.linker_script)
180
181         return '\n'.join(s)
182
183
184 # Support legacy build conventions: the original mbed build system did not have
185 # standard labels for the "TARGET_" and "TOOLCHAIN_" specific directories, but
186 # had the knowledge of a list of these directories to be ignored.
187 LEGACY_IGNORE_DIRS = set([
188     'LPC11U24', 'LPC1768', 'LPC2368', 'LPC4088', 'LPC812', 'KL25Z',
189     'ARM', 'GCC_ARM', 'GCC_CR', 'GCC_CS', 'IAR', 'uARM'
190 ])
191 LEGACY_TOOLCHAIN_NAMES = {
192     'ARM_STD':'ARM', 'ARM_MICRO': 'uARM',
193     'GCC_ARM': 'GCC_ARM', 'GCC_CR': 'GCC_CR', 'GCC_CS': 'GCC_CS',
194     'IAR': 'IAR',
195 }
196
197
198 class mbedToolchain:
199     VERBOSE = True
200
201     CORTEX_SYMBOLS = {
202         "Cortex-M0" : ["__CORTEX_M0", "ARM_MATH_CM0"],
203         "Cortex-M0+": ["__CORTEX_M0PLUS", "ARM_MATH_CM0PLUS"],
204         "Cortex-M1" : ["__CORTEX_M3", "ARM_MATH_CM1"],
205         "Cortex-M3" : ["__CORTEX_M3", "ARM_MATH_CM3"],
206         "Cortex-M4" : ["__CORTEX_M4", "ARM_MATH_CM4"],
207         "Cortex-M4F" : ["__CORTEX_M4", "ARM_MATH_CM4", "__FPU_PRESENT=1"],
208         "Cortex-M7" : ["__CORTEX_M7", "ARM_MATH_CM7"],
209         "Cortex-M7F" : ["__CORTEX_M7", "ARM_MATH_CM7", "__FPU_PRESENT=1"],
210         "Cortex-A9" : ["__CORTEX_A9", "ARM_MATH_CA9", "__FPU_PRESENT", "__CMSIS_RTOS", "__EVAL", "__MBED_CMSIS_RTOS_CA9"],
211     }
212
213     GOANNA_FORMAT = "[Goanna] warning [%FILENAME%:%LINENO%] - [%CHECKNAME%(%SEVERITY%)] %MESSAGE%"
214     GOANNA_DIAGNOSTIC_PATTERN = re.compile(r'"\[Goanna\] (?P<severity>warning) \[(?P<file>[^:]+):(?P<line>\d+)\] \- (?P<message>.*)"')
215
216     def __init__(self, target, options=None, notify=None, macros=None, silent=False):
217         self.target = target
218         self.name = self.__class__.__name__
219         self.hook = hooks.Hook(target, self)
220         self.silent = silent
221
222         self.legacy_ignore_dirs = LEGACY_IGNORE_DIRS - set([target.name, LEGACY_TOOLCHAIN_NAMES[self.name]])
223
224         self.notify_fun = notify if notify is not None else print_notify
225         self.options = options if options is not None else []
226
227         self.macros = macros or []
228         self.options.extend(BUILD_OPTIONS)
229         if self.options:
230             self.info("Build Options: %s" % (', '.join(self.options)))
231
232         self.obj_path = join("TARGET_"+target.name, "TOOLCHAIN_"+self.name)
233
234         self.symbols = None
235         self.labels = None
236         self.has_config = False
237
238         self.build_all = False
239         self.timestamp = time()
240         self.jobs = 1
241
242         self.CHROOT = None
243
244         self.mp_pool = None
245
246     def notify(self, event):
247         """ Little closure for notify functions
248         """
249         return self.notify_fun(event, self.silent)
250
251     def __exit__(self):
252         if self.mp_pool is not None:
253             self.mp_pool.terminate()
254
255     def goanna_parse_line(self, line):
256         if "analyze" in self.options:
257             return self.GOANNA_DIAGNOSTIC_PATTERN.match(line)
258         else:
259             return None
260
261     def get_symbols(self):
262         if self.symbols is None:
263             # Target and Toolchain symbols
264             labels = self.get_labels()
265             self.symbols = ["TARGET_%s" % t for t in labels['TARGET']]
266             self.symbols.extend(["TOOLCHAIN_%s" % t for t in labels['TOOLCHAIN']])
267
268             # Config support
269             if self.has_config:
270                 self.symbols.append('HAVE_MBED_CONFIG_H')
271
272             # Cortex CPU symbols
273             if self.target.core in mbedToolchain.CORTEX_SYMBOLS:
274                 self.symbols.extend(mbedToolchain.CORTEX_SYMBOLS[self.target.core])
275
276             # Symbols defined by the on-line build.system
277             self.symbols.extend(['MBED_BUILD_TIMESTAMP=%s' % self.timestamp, '__MBED__=1'])
278             if MBED_ORG_USER:
279                 self.symbols.append('MBED_USERNAME=' + MBED_ORG_USER)
280
281             # Add target's symbols
282             self.symbols += self.target.macros
283             # Add extra symbols passed via 'macros' parameter
284             self.symbols += self.macros
285
286             # Form factor variables
287             if hasattr(self.target, 'supported_form_factors'):
288                 self.symbols.extend(["TARGET_FF_%s" % t for t in self.target.supported_form_factors])
289
290         return self.symbols
291
292     def get_labels(self):
293         if self.labels is None:
294             toolchain_labels = [c.__name__ for c in getmro(self.__class__)]
295             toolchain_labels.remove('mbedToolchain')
296             self.labels = {
297                 'TARGET': self.target.get_labels(),
298                 'TOOLCHAIN': toolchain_labels
299             }
300         return self.labels
301
302     def need_update(self, target, dependencies):
303         if self.build_all:
304             return True
305
306         if not exists(target):
307             return True
308
309         target_mod_time = stat(target).st_mtime
310
311         for d in dependencies:
312
313             # Some objects are not provided with full path and here we do not have
314             # information about the library paths. Safe option: assume an update
315             if not d or not exists(d):
316                 return True
317
318             if stat(d).st_mtime >= target_mod_time:
319                 return True
320
321         return False
322
323     def scan_resources(self, path):
324         labels = self.get_labels()
325         resources = Resources(path)
326         self.has_config = False
327
328         """ os.walk(top[, topdown=True[, onerror=None[, followlinks=False]]])
329         When topdown is True, the caller can modify the dirnames list in-place
330         (perhaps using del or slice assignment), and walk() will only recurse into
331         the subdirectories whose names remain in dirnames; this can be used to prune
332         the search, impose a specific order of visiting, or even to inform walk()
333         about directories the caller creates or renames before it resumes walk()
334         again. Modifying dirnames when topdown is False is ineffective, because in
335         bottom-up mode the directories in dirnames are generated before dirpath
336         itself is generated.
337         """
338         for root, dirs, files in walk(path):
339             # Remove ignored directories
340             for d in copy(dirs):
341                 if d == '.hg':
342                     dir_path = join(root, d)
343                     resources.repo_dirs.append(dir_path)
344                     resources.repo_files.extend(self.scan_repository(dir_path))
345
346                 if ((d.startswith('.') or d in self.legacy_ignore_dirs) or
347                     (d.startswith('TARGET_') and d[7:] not in labels['TARGET']) or
348                     (d.startswith('TOOLCHAIN_') and d[10:] not in labels['TOOLCHAIN'])):
349                     dirs.remove(d)
350
351             # Add root to include paths
352             resources.inc_dirs.append(root)
353
354             for file in files:
355                 file_path = join(root, file)
356                 _, ext = splitext(file)
357                 ext = ext.lower()
358
359                 if   ext == '.s':
360                     resources.s_sources.append(file_path)
361
362                 elif ext == '.c':
363                     resources.c_sources.append(file_path)
364
365                 elif ext == '.cpp':
366                     resources.cpp_sources.append(file_path)
367
368                 elif ext == '.h' or ext == '.hpp':
369                     if basename(file_path) == "mbed_config.h":
370                         self.has_config = True
371                     resources.headers.append(file_path)
372
373                 elif ext == '.o':
374                     resources.objects.append(file_path)
375
376                 elif ext == self.LIBRARY_EXT:
377                     resources.libraries.append(file_path)
378                     resources.lib_dirs.add(root)
379
380                 elif ext == self.LINKER_EXT:
381                     if resources.linker_script is not None:
382                         self.info("Warning: Multiple linker scripts detected: %s -> %s" % (resources.linker_script, file_path))
383                     resources.linker_script = file_path
384
385                 elif ext == '.lib':
386                     resources.lib_refs.append(file_path)
387
388                 elif ext == '.bld':
389                     resources.lib_builds.append(file_path)
390
391                 elif file == '.hgignore':
392                     resources.repo_files.append(file_path)
393
394                 elif ext == '.hex':
395                     resources.hex_files.append(file_path)
396                 
397                 elif ext == '.bin':
398                     resources.bin_files.append(file_path)
399
400         return resources
401
402     def scan_repository(self, path):
403         resources = []
404
405         for root, dirs, files in walk(path):
406             # Remove ignored directories
407             for d in copy(dirs):
408                 if d == '.' or d == '..':
409                     dirs.remove(d)
410
411             for file in files:
412                 file_path = join(root, file)
413                 resources.append(file_path)
414
415         return resources
416
417     def copy_files(self, files_paths, trg_path, rel_path=None):
418         # Handle a single file
419         if type(files_paths) != ListType: files_paths = [files_paths]
420
421         for source in files_paths:
422             if source is None:
423                 files_paths.remove(source)
424
425         for source in files_paths:
426             if rel_path is not None:
427                 relative_path = relpath(source, rel_path)
428             else:
429                 _, relative_path = split(source)
430
431             target = join(trg_path, relative_path)
432
433             if (target != source) and (self.need_update(target, [source])):
434                 self.progress("copy", relative_path)
435                 mkdir(dirname(target))
436                 copyfile(source, target)
437
438     def relative_object_path(self, build_path, base_dir, source):
439         source_dir, name, _ = split_path(source)
440         obj_dir = join(build_path, relpath(source_dir, base_dir))
441         mkdir(obj_dir)
442         return join(obj_dir, name + '.o')
443
444     def compile_sources(self, resources, build_path, inc_dirs=None):
445         # Web IDE progress bar for project build
446         files_to_compile = resources.s_sources + resources.c_sources + resources.cpp_sources
447         self.to_be_compiled = len(files_to_compile)
448         self.compiled = 0
449
450         #for i in self.build_params:
451         #    self.debug(i)
452         #    self.debug("%s" % self.build_params[i])
453
454         inc_paths = resources.inc_dirs
455         if inc_dirs is not None:
456             inc_paths.extend(inc_dirs)
457
458         objects = []
459         queue = []
460         prev_dir = None
461
462         # The dependency checking for C/C++ is delegated to the compiler
463         base_path = resources.base_path
464         files_to_compile.sort()
465         for source in files_to_compile:
466             _, name, _ = split_path(source)
467             object = self.relative_object_path(build_path, base_path, source)
468
469             # Avoid multiple mkdir() calls on same work directory
470             work_dir = dirname(object)
471             if work_dir is not prev_dir:
472                 prev_dir = work_dir
473                 mkdir(work_dir)
474
475             # Queue mode (multiprocessing)
476             commands = self.compile_command(source, object, inc_paths)
477             if commands is not None:
478                 queue.append({
479                     'source': source,
480                     'object': object,
481                     'commands': commands,
482                     'work_dir': work_dir,
483                     'chroot': self.CHROOT
484                 })
485             else:
486                 objects.append(object)
487
488         # Use queues/multiprocessing if cpu count is higher than setting
489         jobs = self.jobs if self.jobs else cpu_count()
490         if jobs > CPU_COUNT_MIN and len(queue) > jobs:
491             return self.compile_queue(queue, objects)
492         else:
493             return self.compile_seq(queue, objects)
494
495     def compile_seq(self, queue, objects):
496         for item in queue:
497             result = compile_worker(item)
498
499             self.compiled += 1
500             self.progress("compile", item['source'], build_update=True)
501             for res in result['results']:
502                 self.debug("Command: %s" % ' '.join(res['command']))
503                 self.compile_output([
504                     res['code'],
505                     res['output'],
506                     res['command']
507                 ])
508             objects.append(result['object'])
509         return objects
510
511     def compile_queue(self, queue, objects):
512         jobs_count = int(self.jobs if self.jobs else cpu_count())
513         p = Pool(processes=jobs_count)
514
515         results = []
516         for i in range(len(queue)):
517             results.append(p.apply_async(compile_worker, [queue[i]]))
518
519         itr = 0
520         while True:
521             itr += 1
522             if itr > 30000:
523                 p.terminate()
524                 p.join()
525                 raise ToolException("Compile did not finish in 5 minutes")
526
527             pending = 0
528             for r in results:
529                 if r._ready is True:
530                     try:
531                         result = r.get()
532                         results.remove(r)
533
534                         self.compiled += 1
535                         self.progress("compile", result['source'], build_update=True)
536                         for res in result['results']:
537                             self.debug("Command: %s" % ' '.join(res['command']))
538                             self.compile_output([
539                                 res['code'],
540                                 res['output'],
541                                 res['command']
542                             ])
543                         objects.append(result['object'])
544                     except ToolException, err:
545                         p.terminate()
546                         p.join()
547                         raise ToolException(err)
548                 else:
549                     pending += 1
550                     if pending > jobs_count:
551                         break
552
553
554             if len(results) == 0:
555                 break
556
557             sleep(0.01)
558
559         results = None
560         p.terminate()
561         p.join()
562
563         return objects
564
565     def compile_command(self, source, object, includes):
566         # Check dependencies
567         _, ext = splitext(source)
568         ext = ext.lower()
569
570         if ext == '.c' or  ext == '.cpp':
571             base, _ = splitext(object)
572             dep_path = base + '.d'
573             deps = self.parse_dependencies(dep_path) if (exists(dep_path)) else []
574             if len(deps) == 0 or self.need_update(object, deps):
575                 if ext == '.c':
576                     return self.compile_c(source, object, includes)
577                 else:
578                     return self.compile_cpp(source, object, includes)
579         elif ext == '.s':
580             deps = [source]
581             if self.need_update(object, deps):
582                 return self.assemble(source, object, includes)
583         else:
584             return False
585
586         return None
587
588     def compile_output(self, output=[]):
589         _rc = output[0]
590         _stderr = output[1]
591         command = output[2]
592
593         # Parse output for Warnings and Errors
594         self.parse_output(_stderr)
595         self.debug("Return: %s"% _rc)
596         for error_line in _stderr.splitlines():
597             self.debug("Output: %s"% error_line)
598
599         # Check return code
600         if _rc != 0:
601             for line in _stderr.splitlines():
602                 self.tool_error(line)
603             raise ToolException(_stderr)
604
605     def compile(self, cc, source, object, includes):
606         _, ext = splitext(source)
607         ext = ext.lower()
608
609         command = cc + ['-D%s' % s for s in self.get_symbols()] + ["-I%s" % i for i in includes] + ["-o", object, source]
610
611         if hasattr(self, "get_dep_opt"):
612             base, _ = splitext(object)
613             dep_path = base + '.d'
614             command.extend(self.get_dep_opt(dep_path))
615
616         if hasattr(self, "cc_extra"):
617             command.extend(self.cc_extra(base))
618
619         return [command]
620
621     def compile_c(self, source, object, includes):
622         return self.compile(self.cc, source, object, includes)
623
624     def compile_cpp(self, source, object, includes):
625         return self.compile(self.cppc, source, object, includes)
626
627     def build_library(self, objects, dir, name):
628         lib = self.STD_LIB_NAME % name
629         fout = join(dir, lib)
630         if self.need_update(fout, objects):
631             self.info("Library: %s" % lib)
632             self.archive(objects, fout)
633
634     def link_program(self, r, tmp_path, name):
635         ext = 'bin'
636         if hasattr(self.target, 'OUTPUT_EXT'):
637             ext = self.target.OUTPUT_EXT
638
639         if hasattr(self.target, 'OUTPUT_NAMING'):
640             self.var("binary_naming", self.target.OUTPUT_NAMING)
641             if self.target.OUTPUT_NAMING == "8.3":
642                 name = name[0:8]
643                 ext = ext[0:3]
644
645         filename = name+'.'+ext
646         elf = join(tmp_path, name + '.elf')
647         bin = join(tmp_path, filename)
648
649         if self.need_update(elf, r.objects + r.libraries + [r.linker_script]):
650             self.progress("link", name)
651             self.link(elf, r.objects, r.libraries, r.lib_dirs, r.linker_script)
652
653         if self.need_update(bin, [elf]):
654             self.progress("elf2bin", name)
655
656             self.binary(r, elf, bin)
657
658         self.var("compile_succeded", True)
659         self.var("binary", filename)
660
661         return bin
662
663     def default_cmd(self, command):
664         _stdout, _stderr, _rc = run_cmd(command)
665         # Print all warning / erros from stderr to console output
666         for error_line in _stderr.splitlines():
667             print error_line
668
669         self.debug("Command: %s"% ' '.join(command))
670         self.debug("Return: %s"% _rc)
671
672         for output_line in _stdout.splitlines():
673             self.debug("Output: %s"% output_line)
674         for error_line in _stderr.splitlines():
675             self.debug("Errors: %s"% error_line)
676
677         if _rc != 0:
678             for line in _stderr.splitlines():
679                 self.tool_error(line)
680             raise ToolException(_stderr)
681
682     ### NOTIFICATIONS ###
683     def info(self, message):
684         self.notify({'type': 'info', 'message': message})
685
686     def debug(self, message):
687         if self.VERBOSE:
688             if type(message) is ListType:
689                 message = ' '.join(message)
690             message = "[DEBUG] " + message
691             self.notify({'type': 'debug', 'message': message})
692
693     def cc_info(self, severity, file, line, message, target_name=None, toolchain_name=None):
694         self.notify({'type': 'cc',
695                      'severity': severity,
696                      'file': file,
697                      'line': line,
698                      'message': message,
699                      'target_name': target_name,
700                      'toolchain_name': toolchain_name})
701
702     def progress(self, action, file, build_update=False):
703         msg = {'type': 'progress', 'action': action, 'file': file}
704         if build_update:
705             msg['percent'] = 100. * float(self.compiled) / float(self.to_be_compiled)
706         self.notify(msg)
707
708     def tool_error(self, message):
709         self.notify({'type': 'tool_error', 'message': message})
710
711     def var(self, key, value):
712         self.notify({'type': 'var', 'key': key, 'val': value})
713
714 from workspace_tools.settings import ARM_BIN
715 from workspace_tools.settings import GCC_ARM_PATH, GCC_CR_PATH, GCC_CS_PATH, CW_EWL_PATH, CW_GCC_PATH
716 from workspace_tools.settings import IAR_PATH
717
718 TOOLCHAIN_BIN_PATH = {
719     'ARM': ARM_BIN,
720     'uARM': ARM_BIN,
721     'GCC_ARM': GCC_ARM_PATH,
722     'GCC_CS': GCC_CS_PATH,
723     'GCC_CR': GCC_CR_PATH,
724     'GCC_CW_EWL': CW_EWL_PATH,
725     'GCC_CW_NEWLIB': CW_GCC_PATH,
726     'IAR': IAR_PATH
727 }
728
729 from workspace_tools.toolchains.arm import ARM_STD, ARM_MICRO
730 from workspace_tools.toolchains.gcc import GCC_ARM, GCC_CS, GCC_CR
731 from workspace_tools.toolchains.gcc import GCC_CW_EWL, GCC_CW_NEWLIB
732 from workspace_tools.toolchains.iar import IAR
733
734 TOOLCHAIN_CLASSES = {
735     'ARM': ARM_STD,
736     'uARM': ARM_MICRO,
737     'GCC_ARM': GCC_ARM,
738     'GCC_CS': GCC_CS,
739     'GCC_CR': GCC_CR,
740     'GCC_CW_EWL': GCC_CW_EWL,
741     'GCC_CW_NEWLIB': GCC_CW_NEWLIB,
742     'IAR': IAR
743 }
744
745 TOOLCHAINS = set(TOOLCHAIN_CLASSES.keys())