Brian Daniels / mbed-tools

Fork of mbed-tools by Morpheus

Committer:
Kojto
Date:
Mon Apr 04 15:41:15 2016 +0100
Revision:
10:f0b21961f610
Parent:
9:042963870f7a
Cortex-M - add new CMSIS RTOS definitions

To capture the changes in the RTX, we shall use __MBED_CMSIS_RTOS_CM macro. This
should be backward compatible with the previous rtos (using these new symbols should
not break anything).

Who changed what in which revision?

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