Backup 1

Committer:
borlanic
Date:
Tue Apr 24 11:45:18 2018 +0000
Revision:
0:02dd72d1d465
BaBoRo_test2 - backup 1

Who changed what in which revision?

UserRevisionLine numberNew contents of line
borlanic 0:02dd72d1d465 1 """
borlanic 0:02dd72d1d465 2 mbed SDK
borlanic 0:02dd72d1d465 3 Copyright (c) 2011-2013 ARM Limited
borlanic 0:02dd72d1d465 4
borlanic 0:02dd72d1d465 5 Licensed under the Apache License, Version 2.0 (the "License");
borlanic 0:02dd72d1d465 6 you may not use this file except in compliance with the License.
borlanic 0:02dd72d1d465 7 You may obtain a copy of the License at
borlanic 0:02dd72d1d465 8
borlanic 0:02dd72d1d465 9 http://www.apache.org/licenses/LICENSE-2.0
borlanic 0:02dd72d1d465 10
borlanic 0:02dd72d1d465 11 Unless required by applicable law or agreed to in writing, software
borlanic 0:02dd72d1d465 12 distributed under the License is distributed on an "AS IS" BASIS,
borlanic 0:02dd72d1d465 13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
borlanic 0:02dd72d1d465 14 See the License for the specific language governing permissions and
borlanic 0:02dd72d1d465 15 limitations under the License.
borlanic 0:02dd72d1d465 16 """
borlanic 0:02dd72d1d465 17 from __future__ import print_function, division, absolute_import
borlanic 0:02dd72d1d465 18
borlanic 0:02dd72d1d465 19 import re
borlanic 0:02dd72d1d465 20 import sys
borlanic 0:02dd72d1d465 21 from os import stat, walk, getcwd, sep, remove
borlanic 0:02dd72d1d465 22 from copy import copy
borlanic 0:02dd72d1d465 23 from time import time, sleep
borlanic 0:02dd72d1d465 24 from shutil import copyfile
borlanic 0:02dd72d1d465 25 from os.path import (join, splitext, exists, relpath, dirname, basename, split,
borlanic 0:02dd72d1d465 26 abspath, isfile, isdir, normcase)
borlanic 0:02dd72d1d465 27 from itertools import chain
borlanic 0:02dd72d1d465 28 from inspect import getmro
borlanic 0:02dd72d1d465 29 from copy import deepcopy
borlanic 0:02dd72d1d465 30 from abc import ABCMeta, abstractmethod
borlanic 0:02dd72d1d465 31 from distutils.spawn import find_executable
borlanic 0:02dd72d1d465 32 from multiprocessing import Pool, cpu_count
borlanic 0:02dd72d1d465 33 from hashlib import md5
borlanic 0:02dd72d1d465 34 import fnmatch
borlanic 0:02dd72d1d465 35
borlanic 0:02dd72d1d465 36 from ..utils import (run_cmd, mkdir, rel_path, ToolException,
borlanic 0:02dd72d1d465 37 NotSupportedException, split_path, compile_worker)
borlanic 0:02dd72d1d465 38 from ..settings import MBED_ORG_USER, PRINT_COMPILER_OUTPUT_AS_LINK
borlanic 0:02dd72d1d465 39 from .. import hooks
borlanic 0:02dd72d1d465 40 from ..memap import MemapParser
borlanic 0:02dd72d1d465 41
borlanic 0:02dd72d1d465 42
borlanic 0:02dd72d1d465 43 #Disables multiprocessing if set to higher number than the host machine CPUs
borlanic 0:02dd72d1d465 44 CPU_COUNT_MIN = 1
borlanic 0:02dd72d1d465 45 CPU_COEF = 1
borlanic 0:02dd72d1d465 46
borlanic 0:02dd72d1d465 47 class LazyDict(dict):
borlanic 0:02dd72d1d465 48 def __init__(self):
borlanic 0:02dd72d1d465 49 self.eager = {}
borlanic 0:02dd72d1d465 50 self.lazy = {}
borlanic 0:02dd72d1d465 51
borlanic 0:02dd72d1d465 52 def add_lazy(self, key, thunk):
borlanic 0:02dd72d1d465 53 if key in self.eager:
borlanic 0:02dd72d1d465 54 del self.eager[key]
borlanic 0:02dd72d1d465 55 self.lazy[key] = thunk
borlanic 0:02dd72d1d465 56
borlanic 0:02dd72d1d465 57 def __getitem__(self, key):
borlanic 0:02dd72d1d465 58 if (key not in self.eager
borlanic 0:02dd72d1d465 59 and key in self.lazy):
borlanic 0:02dd72d1d465 60 self.eager[key] = self.lazy[key]()
borlanic 0:02dd72d1d465 61 del self.lazy[key]
borlanic 0:02dd72d1d465 62 return self.eager[key]
borlanic 0:02dd72d1d465 63
borlanic 0:02dd72d1d465 64 def __setitem__(self, key, value):
borlanic 0:02dd72d1d465 65 self.eager[key] = value
borlanic 0:02dd72d1d465 66
borlanic 0:02dd72d1d465 67 def __delitem__(self, key):
borlanic 0:02dd72d1d465 68 if key in self.eager:
borlanic 0:02dd72d1d465 69 del self.eager[key]
borlanic 0:02dd72d1d465 70 else:
borlanic 0:02dd72d1d465 71 del self.lazy[key]
borlanic 0:02dd72d1d465 72
borlanic 0:02dd72d1d465 73 def __contains__(self, key):
borlanic 0:02dd72d1d465 74 return key in self.eager or key in self.lazy
borlanic 0:02dd72d1d465 75
borlanic 0:02dd72d1d465 76 def __iter__(self):
borlanic 0:02dd72d1d465 77 return chain(iter(self.eager), iter(self.lazy))
borlanic 0:02dd72d1d465 78
borlanic 0:02dd72d1d465 79 def __len__(self):
borlanic 0:02dd72d1d465 80 return len(self.eager) + len(self.lazy)
borlanic 0:02dd72d1d465 81
borlanic 0:02dd72d1d465 82 def __str__(self):
borlanic 0:02dd72d1d465 83 return "Lazy{%s}" % (
borlanic 0:02dd72d1d465 84 ", ".join("%r: %r" % (k, v) for k, v in
borlanic 0:02dd72d1d465 85 chain(self.eager.items(), ((k, "not evaluated")
borlanic 0:02dd72d1d465 86 for k in self.lazy))))
borlanic 0:02dd72d1d465 87
borlanic 0:02dd72d1d465 88 def update(self, other):
borlanic 0:02dd72d1d465 89 if isinstance(other, LazyDict):
borlanic 0:02dd72d1d465 90 self.eager.update(other.eager)
borlanic 0:02dd72d1d465 91 self.lazy.update(other.lazy)
borlanic 0:02dd72d1d465 92 else:
borlanic 0:02dd72d1d465 93 self.eager.update(other)
borlanic 0:02dd72d1d465 94
borlanic 0:02dd72d1d465 95 def items(self):
borlanic 0:02dd72d1d465 96 """Warning: This forces the evaluation all of the items in this LazyDict
borlanic 0:02dd72d1d465 97 that are iterated over."""
borlanic 0:02dd72d1d465 98 for k, v in self.eager.items():
borlanic 0:02dd72d1d465 99 yield k, v
borlanic 0:02dd72d1d465 100 for k in self.lazy.keys():
borlanic 0:02dd72d1d465 101 yield k, self[k]
borlanic 0:02dd72d1d465 102
borlanic 0:02dd72d1d465 103 def apply(self, fn):
borlanic 0:02dd72d1d465 104 """Delay the application of a computation to all items of the lazy dict.
borlanic 0:02dd72d1d465 105 Does no computation now. Instead the comuptation is performed when a
borlanic 0:02dd72d1d465 106 consumer attempts to access a value in this LazyDict"""
borlanic 0:02dd72d1d465 107 new_lazy = {}
borlanic 0:02dd72d1d465 108 for k, f in self.lazy.items():
borlanic 0:02dd72d1d465 109 def closure(f=f):
borlanic 0:02dd72d1d465 110 return fn(f())
borlanic 0:02dd72d1d465 111 new_lazy[k] = closure
borlanic 0:02dd72d1d465 112 for k, v in self.eager.items():
borlanic 0:02dd72d1d465 113 def closure(v=v):
borlanic 0:02dd72d1d465 114 return fn(v)
borlanic 0:02dd72d1d465 115 new_lazy[k] = closure
borlanic 0:02dd72d1d465 116 self.lazy = new_lazy
borlanic 0:02dd72d1d465 117 self.eager = {}
borlanic 0:02dd72d1d465 118
borlanic 0:02dd72d1d465 119 class Resources:
borlanic 0:02dd72d1d465 120 def __init__(self, base_path=None, collect_ignores=False):
borlanic 0:02dd72d1d465 121 self.base_path = base_path
borlanic 0:02dd72d1d465 122 self.collect_ignores = collect_ignores
borlanic 0:02dd72d1d465 123
borlanic 0:02dd72d1d465 124 self.file_basepath = {}
borlanic 0:02dd72d1d465 125
borlanic 0:02dd72d1d465 126 self.inc_dirs = []
borlanic 0:02dd72d1d465 127 self.headers = []
borlanic 0:02dd72d1d465 128
borlanic 0:02dd72d1d465 129 self.s_sources = []
borlanic 0:02dd72d1d465 130 self.c_sources = []
borlanic 0:02dd72d1d465 131 self.cpp_sources = []
borlanic 0:02dd72d1d465 132
borlanic 0:02dd72d1d465 133 self.lib_dirs = set([])
borlanic 0:02dd72d1d465 134 self.objects = []
borlanic 0:02dd72d1d465 135 self.libraries = []
borlanic 0:02dd72d1d465 136
borlanic 0:02dd72d1d465 137 # mbed special files
borlanic 0:02dd72d1d465 138 self.lib_builds = []
borlanic 0:02dd72d1d465 139 self.lib_refs = []
borlanic 0:02dd72d1d465 140
borlanic 0:02dd72d1d465 141 self.repo_dirs = []
borlanic 0:02dd72d1d465 142 self.repo_files = []
borlanic 0:02dd72d1d465 143
borlanic 0:02dd72d1d465 144 self.linker_script = None
borlanic 0:02dd72d1d465 145
borlanic 0:02dd72d1d465 146 # Other files
borlanic 0:02dd72d1d465 147 self.hex_files = []
borlanic 0:02dd72d1d465 148 self.bin_files = []
borlanic 0:02dd72d1d465 149 self.json_files = []
borlanic 0:02dd72d1d465 150
borlanic 0:02dd72d1d465 151 # Features
borlanic 0:02dd72d1d465 152 self.features = LazyDict()
borlanic 0:02dd72d1d465 153 self.ignored_dirs = []
borlanic 0:02dd72d1d465 154
borlanic 0:02dd72d1d465 155 def __add__(self, resources):
borlanic 0:02dd72d1d465 156 if resources is None:
borlanic 0:02dd72d1d465 157 return self
borlanic 0:02dd72d1d465 158 else:
borlanic 0:02dd72d1d465 159 return self.add(resources)
borlanic 0:02dd72d1d465 160
borlanic 0:02dd72d1d465 161 def __radd__(self, resources):
borlanic 0:02dd72d1d465 162 if resources is None:
borlanic 0:02dd72d1d465 163 return self
borlanic 0:02dd72d1d465 164 else:
borlanic 0:02dd72d1d465 165 return self.add(resources)
borlanic 0:02dd72d1d465 166
borlanic 0:02dd72d1d465 167 def ignore_dir(self, directory):
borlanic 0:02dd72d1d465 168 if self.collect_ignores:
borlanic 0:02dd72d1d465 169 self.ignored_dirs.append(directory)
borlanic 0:02dd72d1d465 170
borlanic 0:02dd72d1d465 171 def add(self, resources):
borlanic 0:02dd72d1d465 172 for f,p in resources.file_basepath.items():
borlanic 0:02dd72d1d465 173 self.file_basepath[f] = p
borlanic 0:02dd72d1d465 174
borlanic 0:02dd72d1d465 175 self.inc_dirs += resources.inc_dirs
borlanic 0:02dd72d1d465 176 self.headers += resources.headers
borlanic 0:02dd72d1d465 177
borlanic 0:02dd72d1d465 178 self.s_sources += resources.s_sources
borlanic 0:02dd72d1d465 179 self.c_sources += resources.c_sources
borlanic 0:02dd72d1d465 180 self.cpp_sources += resources.cpp_sources
borlanic 0:02dd72d1d465 181
borlanic 0:02dd72d1d465 182 self.lib_dirs |= resources.lib_dirs
borlanic 0:02dd72d1d465 183 self.objects += resources.objects
borlanic 0:02dd72d1d465 184 self.libraries += resources.libraries
borlanic 0:02dd72d1d465 185
borlanic 0:02dd72d1d465 186 self.lib_builds += resources.lib_builds
borlanic 0:02dd72d1d465 187 self.lib_refs += resources.lib_refs
borlanic 0:02dd72d1d465 188
borlanic 0:02dd72d1d465 189 self.repo_dirs += resources.repo_dirs
borlanic 0:02dd72d1d465 190 self.repo_files += resources.repo_files
borlanic 0:02dd72d1d465 191
borlanic 0:02dd72d1d465 192 if resources.linker_script is not None:
borlanic 0:02dd72d1d465 193 self.linker_script = resources.linker_script
borlanic 0:02dd72d1d465 194
borlanic 0:02dd72d1d465 195 self.hex_files += resources.hex_files
borlanic 0:02dd72d1d465 196 self.bin_files += resources.bin_files
borlanic 0:02dd72d1d465 197 self.json_files += resources.json_files
borlanic 0:02dd72d1d465 198
borlanic 0:02dd72d1d465 199 self.features.update(resources.features)
borlanic 0:02dd72d1d465 200 self.ignored_dirs += resources.ignored_dirs
borlanic 0:02dd72d1d465 201
borlanic 0:02dd72d1d465 202 return self
borlanic 0:02dd72d1d465 203
borlanic 0:02dd72d1d465 204 def _collect_duplicates(self, dupe_dict, dupe_headers):
borlanic 0:02dd72d1d465 205 for filename in self.s_sources + self.c_sources + self.cpp_sources:
borlanic 0:02dd72d1d465 206 objname, _ = splitext(basename(filename))
borlanic 0:02dd72d1d465 207 dupe_dict.setdefault(objname, set())
borlanic 0:02dd72d1d465 208 dupe_dict[objname] |= set([filename])
borlanic 0:02dd72d1d465 209 for filename in self.headers:
borlanic 0:02dd72d1d465 210 headername = basename(filename)
borlanic 0:02dd72d1d465 211 dupe_headers.setdefault(headername, set())
borlanic 0:02dd72d1d465 212 dupe_headers[headername] |= set([headername])
borlanic 0:02dd72d1d465 213 for res in self.features.values():
borlanic 0:02dd72d1d465 214 res._collect_duplicates(dupe_dict, dupe_headers)
borlanic 0:02dd72d1d465 215 return dupe_dict, dupe_headers
borlanic 0:02dd72d1d465 216
borlanic 0:02dd72d1d465 217 def detect_duplicates(self, toolchain):
borlanic 0:02dd72d1d465 218 """Detect all potential ambiguities in filenames and report them with
borlanic 0:02dd72d1d465 219 a toolchain notification
borlanic 0:02dd72d1d465 220
borlanic 0:02dd72d1d465 221 Positional Arguments:
borlanic 0:02dd72d1d465 222 toolchain - used for notifications
borlanic 0:02dd72d1d465 223 """
borlanic 0:02dd72d1d465 224 count = 0
borlanic 0:02dd72d1d465 225 dupe_dict, dupe_headers = self._collect_duplicates(dict(), dict())
borlanic 0:02dd72d1d465 226 for objname, filenames in dupe_dict.items():
borlanic 0:02dd72d1d465 227 if len(filenames) > 1:
borlanic 0:02dd72d1d465 228 count+=1
borlanic 0:02dd72d1d465 229 toolchain.tool_error(
borlanic 0:02dd72d1d465 230 "Object file %s.o is not unique! It could be made from: %s"\
borlanic 0:02dd72d1d465 231 % (objname, " ".join(filenames)))
borlanic 0:02dd72d1d465 232 for headername, locations in dupe_headers.items():
borlanic 0:02dd72d1d465 233 if len(locations) > 1:
borlanic 0:02dd72d1d465 234 count+=1
borlanic 0:02dd72d1d465 235 toolchain.tool_error(
borlanic 0:02dd72d1d465 236 "Header file %s is not unique! It could be: %s" %\
borlanic 0:02dd72d1d465 237 (headername, " ".join(locations)))
borlanic 0:02dd72d1d465 238 return count
borlanic 0:02dd72d1d465 239
borlanic 0:02dd72d1d465 240
borlanic 0:02dd72d1d465 241 def relative_to(self, base, dot=False):
borlanic 0:02dd72d1d465 242 for field in ['inc_dirs', 'headers', 's_sources', 'c_sources',
borlanic 0:02dd72d1d465 243 'cpp_sources', 'lib_dirs', 'objects', 'libraries',
borlanic 0:02dd72d1d465 244 'lib_builds', 'lib_refs', 'repo_dirs', 'repo_files',
borlanic 0:02dd72d1d465 245 'hex_files', 'bin_files', 'json_files']:
borlanic 0:02dd72d1d465 246 v = [rel_path(f, base, dot) for f in getattr(self, field)]
borlanic 0:02dd72d1d465 247 setattr(self, field, v)
borlanic 0:02dd72d1d465 248
borlanic 0:02dd72d1d465 249 def to_apply(feature, base=base, dot=dot):
borlanic 0:02dd72d1d465 250 feature.relative_to(base, dot)
borlanic 0:02dd72d1d465 251 self.features.apply(to_apply)
borlanic 0:02dd72d1d465 252
borlanic 0:02dd72d1d465 253 if self.linker_script is not None:
borlanic 0:02dd72d1d465 254 self.linker_script = rel_path(self.linker_script, base, dot)
borlanic 0:02dd72d1d465 255
borlanic 0:02dd72d1d465 256 def win_to_unix(self):
borlanic 0:02dd72d1d465 257 for field in ['inc_dirs', 'headers', 's_sources', 'c_sources',
borlanic 0:02dd72d1d465 258 'cpp_sources', 'lib_dirs', 'objects', 'libraries',
borlanic 0:02dd72d1d465 259 'lib_builds', 'lib_refs', 'repo_dirs', 'repo_files',
borlanic 0:02dd72d1d465 260 'hex_files', 'bin_files', 'json_files']:
borlanic 0:02dd72d1d465 261 v = [f.replace('\\', '/') for f in getattr(self, field)]
borlanic 0:02dd72d1d465 262 setattr(self, field, v)
borlanic 0:02dd72d1d465 263
borlanic 0:02dd72d1d465 264 def to_apply(feature):
borlanic 0:02dd72d1d465 265 feature.win_to_unix()
borlanic 0:02dd72d1d465 266 self.features.apply(to_apply)
borlanic 0:02dd72d1d465 267
borlanic 0:02dd72d1d465 268 if self.linker_script is not None:
borlanic 0:02dd72d1d465 269 self.linker_script = self.linker_script.replace('\\', '/')
borlanic 0:02dd72d1d465 270
borlanic 0:02dd72d1d465 271 def __str__(self):
borlanic 0:02dd72d1d465 272 s = []
borlanic 0:02dd72d1d465 273
borlanic 0:02dd72d1d465 274 for (label, resources) in (
borlanic 0:02dd72d1d465 275 ('Include Directories', self.inc_dirs),
borlanic 0:02dd72d1d465 276 ('Headers', self.headers),
borlanic 0:02dd72d1d465 277
borlanic 0:02dd72d1d465 278 ('Assembly sources', self.s_sources),
borlanic 0:02dd72d1d465 279 ('C sources', self.c_sources),
borlanic 0:02dd72d1d465 280 ('C++ sources', self.cpp_sources),
borlanic 0:02dd72d1d465 281
borlanic 0:02dd72d1d465 282 ('Library directories', self.lib_dirs),
borlanic 0:02dd72d1d465 283 ('Objects', self.objects),
borlanic 0:02dd72d1d465 284 ('Libraries', self.libraries),
borlanic 0:02dd72d1d465 285
borlanic 0:02dd72d1d465 286 ('Hex files', self.hex_files),
borlanic 0:02dd72d1d465 287 ('Bin files', self.bin_files),
borlanic 0:02dd72d1d465 288
borlanic 0:02dd72d1d465 289 ('Features', self.features),
borlanic 0:02dd72d1d465 290 ):
borlanic 0:02dd72d1d465 291 if resources:
borlanic 0:02dd72d1d465 292 s.append('%s:\n ' % label + '\n '.join(resources))
borlanic 0:02dd72d1d465 293
borlanic 0:02dd72d1d465 294 if self.linker_script:
borlanic 0:02dd72d1d465 295 s.append('Linker Script: ' + self.linker_script)
borlanic 0:02dd72d1d465 296
borlanic 0:02dd72d1d465 297 return '\n'.join(s)
borlanic 0:02dd72d1d465 298
borlanic 0:02dd72d1d465 299 # Support legacy build conventions: the original mbed build system did not have
borlanic 0:02dd72d1d465 300 # standard labels for the "TARGET_" and "TOOLCHAIN_" specific directories, but
borlanic 0:02dd72d1d465 301 # had the knowledge of a list of these directories to be ignored.
borlanic 0:02dd72d1d465 302 LEGACY_IGNORE_DIRS = set([
borlanic 0:02dd72d1d465 303 'LPC11U24', 'LPC1768', 'LPC2368', 'LPC4088', 'LPC812', 'KL25Z',
borlanic 0:02dd72d1d465 304 'ARM', 'uARM', 'IAR',
borlanic 0:02dd72d1d465 305 'GCC_ARM', 'GCC_CS', 'GCC_CR', 'GCC_CW', 'GCC_CW_EWL', 'GCC_CW_NEWLIB',
borlanic 0:02dd72d1d465 306 'ARMC6'
borlanic 0:02dd72d1d465 307 ])
borlanic 0:02dd72d1d465 308 LEGACY_TOOLCHAIN_NAMES = {
borlanic 0:02dd72d1d465 309 'ARM_STD':'ARM', 'ARM_MICRO': 'uARM',
borlanic 0:02dd72d1d465 310 'GCC_ARM': 'GCC_ARM', 'GCC_CR': 'GCC_CR',
borlanic 0:02dd72d1d465 311 'IAR': 'IAR',
borlanic 0:02dd72d1d465 312 'ARMC6': 'ARMC6',
borlanic 0:02dd72d1d465 313 }
borlanic 0:02dd72d1d465 314
borlanic 0:02dd72d1d465 315
borlanic 0:02dd72d1d465 316 class mbedToolchain:
borlanic 0:02dd72d1d465 317 # Verbose logging
borlanic 0:02dd72d1d465 318 VERBOSE = True
borlanic 0:02dd72d1d465 319
borlanic 0:02dd72d1d465 320 # Compile C files as CPP
borlanic 0:02dd72d1d465 321 COMPILE_C_AS_CPP = False
borlanic 0:02dd72d1d465 322
borlanic 0:02dd72d1d465 323 # Response files for compiling, includes, linking and archiving.
borlanic 0:02dd72d1d465 324 # Not needed on posix systems where the typical arg limit is 2 megabytes
borlanic 0:02dd72d1d465 325 RESPONSE_FILES = True
borlanic 0:02dd72d1d465 326
borlanic 0:02dd72d1d465 327 CORTEX_SYMBOLS = {
borlanic 0:02dd72d1d465 328 "Cortex-M0" : ["__CORTEX_M0", "ARM_MATH_CM0", "__CMSIS_RTOS", "__MBED_CMSIS_RTOS_CM"],
borlanic 0:02dd72d1d465 329 "Cortex-M0+": ["__CORTEX_M0PLUS", "ARM_MATH_CM0PLUS", "__CMSIS_RTOS", "__MBED_CMSIS_RTOS_CM"],
borlanic 0:02dd72d1d465 330 "Cortex-M1" : ["__CORTEX_M3", "ARM_MATH_CM1", "__CMSIS_RTOS", "__MBED_CMSIS_RTOS_CM"],
borlanic 0:02dd72d1d465 331 "Cortex-M3" : ["__CORTEX_M3", "ARM_MATH_CM3", "__CMSIS_RTOS", "__MBED_CMSIS_RTOS_CM"],
borlanic 0:02dd72d1d465 332 "Cortex-M4" : ["__CORTEX_M4", "ARM_MATH_CM4", "__CMSIS_RTOS", "__MBED_CMSIS_RTOS_CM"],
borlanic 0:02dd72d1d465 333 "Cortex-M4F" : ["__CORTEX_M4", "ARM_MATH_CM4", "__FPU_PRESENT=1", "__CMSIS_RTOS", "__MBED_CMSIS_RTOS_CM"],
borlanic 0:02dd72d1d465 334 "Cortex-M7" : ["__CORTEX_M7", "ARM_MATH_CM7", "__CMSIS_RTOS", "__MBED_CMSIS_RTOS_CM"],
borlanic 0:02dd72d1d465 335 "Cortex-M7F" : ["__CORTEX_M7", "ARM_MATH_CM7", "__FPU_PRESENT=1", "__CMSIS_RTOS", "__MBED_CMSIS_RTOS_CM"],
borlanic 0:02dd72d1d465 336 "Cortex-M7FD" : ["__CORTEX_M7", "ARM_MATH_CM7", "__FPU_PRESENT=1", "__CMSIS_RTOS", "__MBED_CMSIS_RTOS_CM"],
borlanic 0:02dd72d1d465 337 "Cortex-A9" : ["__CORTEX_A9", "ARM_MATH_CA9", "__FPU_PRESENT", "__CMSIS_RTOS", "__EVAL", "__MBED_CMSIS_RTOS_CA9"],
borlanic 0:02dd72d1d465 338 "Cortex-M23-NS": ["__CORTEX_M23", "ARM_MATH_ARMV8MBL", "__DOMAIN_NS=1", "__CMSIS_RTOS", "__MBED_CMSIS_RTOS_CM"],
borlanic 0:02dd72d1d465 339 "Cortex-M23": ["__CORTEX_M23", "ARM_MATH_ARMV8MBL", "__CMSIS_RTOS", "__MBED_CMSIS_RTOS_CM"],
borlanic 0:02dd72d1d465 340 "Cortex-M33-NS": ["__CORTEX_M33", "ARM_MATH_ARMV8MML", "__DOMAIN_NS=1", "__CMSIS_RTOS", "__MBED_CMSIS_RTOS_CM"],
borlanic 0:02dd72d1d465 341 "Cortex-M33": ["__CORTEX_M33", "ARM_MATH_ARMV8MML", "__CMSIS_RTOS", "__MBED_CMSIS_RTOS_CM"],
borlanic 0:02dd72d1d465 342 "Cortex-M33F-NS": ["__CORTEX_M33", "ARM_MATH_ARMV8MML", "__DOMAIN_NS=1", "__FPU_PRESENT", "__CMSIS_RTOS", "__MBED_CMSIS_RTOS_CM"],
borlanic 0:02dd72d1d465 343 "Cortex-M33F": ["__CORTEX_M33", "ARM_MATH_ARMV8MML", "__FPU_PRESENT", "__CMSIS_RTOS", "__MBED_CMSIS_RTOS_CM"],
borlanic 0:02dd72d1d465 344 }
borlanic 0:02dd72d1d465 345
borlanic 0:02dd72d1d465 346 MBED_CONFIG_FILE_NAME="mbed_config.h"
borlanic 0:02dd72d1d465 347
borlanic 0:02dd72d1d465 348 PROFILE_FILE_NAME = ".profile"
borlanic 0:02dd72d1d465 349
borlanic 0:02dd72d1d465 350 __metaclass__ = ABCMeta
borlanic 0:02dd72d1d465 351
borlanic 0:02dd72d1d465 352 profile_template = {'common':[], 'c':[], 'cxx':[], 'asm':[], 'ld':[]}
borlanic 0:02dd72d1d465 353
borlanic 0:02dd72d1d465 354 def __init__(self, target, notify=None, macros=None, silent=False,
borlanic 0:02dd72d1d465 355 extra_verbose=False, build_profile=None, build_dir=None):
borlanic 0:02dd72d1d465 356 self.target = target
borlanic 0:02dd72d1d465 357 self.name = self.__class__.__name__
borlanic 0:02dd72d1d465 358
borlanic 0:02dd72d1d465 359 # compile/assemble/link/binary hooks
borlanic 0:02dd72d1d465 360 self.hook = hooks.Hook(target, self)
borlanic 0:02dd72d1d465 361
borlanic 0:02dd72d1d465 362 # Toolchain flags
borlanic 0:02dd72d1d465 363 self.flags = deepcopy(build_profile or self.profile_template)
borlanic 0:02dd72d1d465 364
borlanic 0:02dd72d1d465 365 # System libraries provided by the toolchain
borlanic 0:02dd72d1d465 366 self.sys_libs = []
borlanic 0:02dd72d1d465 367
borlanic 0:02dd72d1d465 368 # User-defined macros
borlanic 0:02dd72d1d465 369 self.macros = macros or []
borlanic 0:02dd72d1d465 370
borlanic 0:02dd72d1d465 371 # Macros generated from toolchain and target rules/features
borlanic 0:02dd72d1d465 372 self.asm_symbols = None
borlanic 0:02dd72d1d465 373 self.cxx_symbols = None
borlanic 0:02dd72d1d465 374
borlanic 0:02dd72d1d465 375 # Labels generated from toolchain and target rules/features (used for selective build)
borlanic 0:02dd72d1d465 376 self.labels = None
borlanic 0:02dd72d1d465 377
borlanic 0:02dd72d1d465 378 # This will hold the initialized config object
borlanic 0:02dd72d1d465 379 self.config = None
borlanic 0:02dd72d1d465 380
borlanic 0:02dd72d1d465 381 # This will hold the configuration data (as returned by Config.get_config_data())
borlanic 0:02dd72d1d465 382 self.config_data = None
borlanic 0:02dd72d1d465 383
borlanic 0:02dd72d1d465 384 # This will hold the location of the configuration file or None if there's no configuration available
borlanic 0:02dd72d1d465 385 self.config_file = None
borlanic 0:02dd72d1d465 386
borlanic 0:02dd72d1d465 387 # Call guard for "get_config_data" (see the comments of get_config_data for details)
borlanic 0:02dd72d1d465 388 self.config_processed = False
borlanic 0:02dd72d1d465 389
borlanic 0:02dd72d1d465 390 # Non-incremental compile
borlanic 0:02dd72d1d465 391 self.build_all = False
borlanic 0:02dd72d1d465 392
borlanic 0:02dd72d1d465 393 # Build output dir
borlanic 0:02dd72d1d465 394 self.build_dir = build_dir
borlanic 0:02dd72d1d465 395 self.timestamp = time()
borlanic 0:02dd72d1d465 396
borlanic 0:02dd72d1d465 397 # Number of concurrent build jobs. 0 means auto (based on host system cores)
borlanic 0:02dd72d1d465 398 self.jobs = 0
borlanic 0:02dd72d1d465 399
borlanic 0:02dd72d1d465 400 # Ignore patterns from .mbedignore files
borlanic 0:02dd72d1d465 401 self.ignore_patterns = []
borlanic 0:02dd72d1d465 402 self._ignore_regex = re.compile("$^")
borlanic 0:02dd72d1d465 403
borlanic 0:02dd72d1d465 404 # Pre-mbed 2.0 ignore dirs
borlanic 0:02dd72d1d465 405 self.legacy_ignore_dirs = (LEGACY_IGNORE_DIRS | TOOLCHAINS) - set([target.name, LEGACY_TOOLCHAIN_NAMES[self.name]])
borlanic 0:02dd72d1d465 406
borlanic 0:02dd72d1d465 407 # Output notify function
borlanic 0:02dd72d1d465 408 # This function is passed all events, and expected to handle notification of the
borlanic 0:02dd72d1d465 409 # user, emit the events to a log, etc.
borlanic 0:02dd72d1d465 410 # The API for all notify methods passed into the notify parameter is as follows:
borlanic 0:02dd72d1d465 411 # def notify(Event, Silent)
borlanic 0:02dd72d1d465 412 # Where *Event* is a dict representing the toolchain event that was generated
borlanic 0:02dd72d1d465 413 # e.g.: a compile succeeded, or a warning was emitted by the compiler
borlanic 0:02dd72d1d465 414 # or an application was linked
borlanic 0:02dd72d1d465 415 # *Silent* is a boolean
borlanic 0:02dd72d1d465 416 if notify:
borlanic 0:02dd72d1d465 417 self.notify_fun = notify
borlanic 0:02dd72d1d465 418 elif extra_verbose:
borlanic 0:02dd72d1d465 419 self.notify_fun = self.print_notify_verbose
borlanic 0:02dd72d1d465 420 else:
borlanic 0:02dd72d1d465 421 self.notify_fun = self.print_notify
borlanic 0:02dd72d1d465 422
borlanic 0:02dd72d1d465 423 # Silent builds (no output)
borlanic 0:02dd72d1d465 424 self.silent = silent
borlanic 0:02dd72d1d465 425
borlanic 0:02dd72d1d465 426 # Print output buffer
borlanic 0:02dd72d1d465 427 self.output = str()
borlanic 0:02dd72d1d465 428
borlanic 0:02dd72d1d465 429 # uVisor spepcific rules
borlanic 0:02dd72d1d465 430 if 'UVISOR' in self.target.features and 'UVISOR_SUPPORTED' in self.target.extra_labels:
borlanic 0:02dd72d1d465 431 self.target.core = re.sub(r"F$", '', self.target.core)
borlanic 0:02dd72d1d465 432
borlanic 0:02dd72d1d465 433 # Stats cache is used to reduce the amount of IO requests to stat
borlanic 0:02dd72d1d465 434 # header files during dependency change. See need_update()
borlanic 0:02dd72d1d465 435 self.stat_cache = {}
borlanic 0:02dd72d1d465 436
borlanic 0:02dd72d1d465 437 # Used by the mbed Online Build System to build in chrooted environment
borlanic 0:02dd72d1d465 438 self.CHROOT = None
borlanic 0:02dd72d1d465 439
borlanic 0:02dd72d1d465 440 # Call post __init__() hooks before the ARM/GCC_ARM/IAR toolchain __init__() takes over
borlanic 0:02dd72d1d465 441 self.init()
borlanic 0:02dd72d1d465 442
borlanic 0:02dd72d1d465 443 # Used for post __init__() hooks
borlanic 0:02dd72d1d465 444 # THIS METHOD IS BEING OVERRIDDEN BY THE MBED ONLINE BUILD SYSTEM
borlanic 0:02dd72d1d465 445 # ANY CHANGE OF PARAMETERS OR RETURN VALUES WILL BREAK COMPATIBILITY
borlanic 0:02dd72d1d465 446 def init(self):
borlanic 0:02dd72d1d465 447 return True
borlanic 0:02dd72d1d465 448
borlanic 0:02dd72d1d465 449 def get_output(self):
borlanic 0:02dd72d1d465 450 return self.output
borlanic 0:02dd72d1d465 451
borlanic 0:02dd72d1d465 452 def print_notify(self, event, silent=False):
borlanic 0:02dd72d1d465 453 """ Default command line notification
borlanic 0:02dd72d1d465 454 """
borlanic 0:02dd72d1d465 455 msg = None
borlanic 0:02dd72d1d465 456
borlanic 0:02dd72d1d465 457 if not self.VERBOSE and event['type'] == 'tool_error':
borlanic 0:02dd72d1d465 458 msg = event['message']
borlanic 0:02dd72d1d465 459
borlanic 0:02dd72d1d465 460 elif event['type'] in ['info', 'debug']:
borlanic 0:02dd72d1d465 461 msg = event['message']
borlanic 0:02dd72d1d465 462
borlanic 0:02dd72d1d465 463 elif event['type'] == 'cc':
borlanic 0:02dd72d1d465 464 event['severity'] = event['severity'].title()
borlanic 0:02dd72d1d465 465
borlanic 0:02dd72d1d465 466 if PRINT_COMPILER_OUTPUT_AS_LINK:
borlanic 0:02dd72d1d465 467 event['file'] = getcwd() + event['file'].strip('.')
borlanic 0:02dd72d1d465 468 msg = '[%(severity)s] %(file)s:%(line)s:%(col)s: %(message)s' % event
borlanic 0:02dd72d1d465 469 else:
borlanic 0:02dd72d1d465 470 event['file'] = basename(event['file'])
borlanic 0:02dd72d1d465 471 msg = '[%(severity)s] %(file)s@%(line)s,%(col)s: %(message)s' % event
borlanic 0:02dd72d1d465 472
borlanic 0:02dd72d1d465 473 elif event['type'] == 'progress':
borlanic 0:02dd72d1d465 474 if 'percent' in event:
borlanic 0:02dd72d1d465 475 msg = '{} [{:>5.1f}%]: {}'.format(event['action'].title(),
borlanic 0:02dd72d1d465 476 event['percent'],
borlanic 0:02dd72d1d465 477 basename(event['file']))
borlanic 0:02dd72d1d465 478 else:
borlanic 0:02dd72d1d465 479 msg = '{}: {}'.format(event['action'].title(),
borlanic 0:02dd72d1d465 480 basename(event['file']))
borlanic 0:02dd72d1d465 481
borlanic 0:02dd72d1d465 482 if msg:
borlanic 0:02dd72d1d465 483 if not silent:
borlanic 0:02dd72d1d465 484 print(msg)
borlanic 0:02dd72d1d465 485 self.output += msg + "\n"
borlanic 0:02dd72d1d465 486
borlanic 0:02dd72d1d465 487 def print_notify_verbose(self, event, silent=False):
borlanic 0:02dd72d1d465 488 """ Default command line notification with more verbose mode
borlanic 0:02dd72d1d465 489 """
borlanic 0:02dd72d1d465 490 if event['type'] in ['info', 'debug']:
borlanic 0:02dd72d1d465 491 self.print_notify(event, silent=silent) # standard handle
borlanic 0:02dd72d1d465 492
borlanic 0:02dd72d1d465 493 elif event['type'] == 'cc':
borlanic 0:02dd72d1d465 494 event['severity'] = event['severity'].title()
borlanic 0:02dd72d1d465 495 event['file'] = basename(event['file'])
borlanic 0:02dd72d1d465 496 event['mcu_name'] = "None"
borlanic 0:02dd72d1d465 497 event['target_name'] = event['target_name'].upper() if event['target_name'] else "Unknown"
borlanic 0:02dd72d1d465 498 event['toolchain_name'] = event['toolchain_name'].upper() if event['toolchain_name'] else "Unknown"
borlanic 0:02dd72d1d465 499 msg = '[%(severity)s] %(target_name)s::%(toolchain_name)s::%(file)s@%(line)s: %(message)s' % event
borlanic 0:02dd72d1d465 500 if not silent:
borlanic 0:02dd72d1d465 501 print(msg)
borlanic 0:02dd72d1d465 502 self.output += msg + "\n"
borlanic 0:02dd72d1d465 503
borlanic 0:02dd72d1d465 504 elif event['type'] == 'progress':
borlanic 0:02dd72d1d465 505 self.print_notify(event) # standard handle
borlanic 0:02dd72d1d465 506
borlanic 0:02dd72d1d465 507 # THIS METHOD IS BEING OVERRIDDEN BY THE MBED ONLINE BUILD SYSTEM
borlanic 0:02dd72d1d465 508 # ANY CHANGE OF PARAMETERS OR RETURN VALUES WILL BREAK COMPATIBILITY
borlanic 0:02dd72d1d465 509 def notify(self, event):
borlanic 0:02dd72d1d465 510 """ Little closure for notify functions
borlanic 0:02dd72d1d465 511 """
borlanic 0:02dd72d1d465 512 event['toolchain'] = self
borlanic 0:02dd72d1d465 513 return self.notify_fun(event, self.silent)
borlanic 0:02dd72d1d465 514
borlanic 0:02dd72d1d465 515 def get_symbols(self, for_asm=False):
borlanic 0:02dd72d1d465 516 if for_asm:
borlanic 0:02dd72d1d465 517 if self.asm_symbols is None:
borlanic 0:02dd72d1d465 518 self.asm_symbols = []
borlanic 0:02dd72d1d465 519
borlanic 0:02dd72d1d465 520 # Cortex CPU symbols
borlanic 0:02dd72d1d465 521 if self.target.core in mbedToolchain.CORTEX_SYMBOLS:
borlanic 0:02dd72d1d465 522 self.asm_symbols.extend(mbedToolchain.CORTEX_SYMBOLS[self.target.core])
borlanic 0:02dd72d1d465 523
borlanic 0:02dd72d1d465 524 # Add target's symbols
borlanic 0:02dd72d1d465 525 self.asm_symbols += self.target.macros
borlanic 0:02dd72d1d465 526 # Add extra symbols passed via 'macros' parameter
borlanic 0:02dd72d1d465 527 self.asm_symbols += self.macros
borlanic 0:02dd72d1d465 528 return list(set(self.asm_symbols)) # Return only unique symbols
borlanic 0:02dd72d1d465 529 else:
borlanic 0:02dd72d1d465 530 if self.cxx_symbols is None:
borlanic 0:02dd72d1d465 531 # Target and Toolchain symbols
borlanic 0:02dd72d1d465 532 labels = self.get_labels()
borlanic 0:02dd72d1d465 533 self.cxx_symbols = ["TARGET_%s" % t for t in labels['TARGET']]
borlanic 0:02dd72d1d465 534 self.cxx_symbols.extend(["TOOLCHAIN_%s" % t for t in labels['TOOLCHAIN']])
borlanic 0:02dd72d1d465 535
borlanic 0:02dd72d1d465 536 # Cortex CPU symbols
borlanic 0:02dd72d1d465 537 if self.target.core in mbedToolchain.CORTEX_SYMBOLS:
borlanic 0:02dd72d1d465 538 self.cxx_symbols.extend(mbedToolchain.CORTEX_SYMBOLS[self.target.core])
borlanic 0:02dd72d1d465 539
borlanic 0:02dd72d1d465 540 # Symbols defined by the on-line build.system
borlanic 0:02dd72d1d465 541 self.cxx_symbols.extend(['MBED_BUILD_TIMESTAMP=%s' % self.timestamp, 'TARGET_LIKE_MBED', '__MBED__=1'])
borlanic 0:02dd72d1d465 542 if MBED_ORG_USER:
borlanic 0:02dd72d1d465 543 self.cxx_symbols.append('MBED_USERNAME=' + MBED_ORG_USER)
borlanic 0:02dd72d1d465 544
borlanic 0:02dd72d1d465 545 # Add target's symbols
borlanic 0:02dd72d1d465 546 self.cxx_symbols += self.target.macros
borlanic 0:02dd72d1d465 547 # Add target's hardware
borlanic 0:02dd72d1d465 548 self.cxx_symbols += ["DEVICE_" + data + "=1" for data in self.target.device_has]
borlanic 0:02dd72d1d465 549 # Add target's features
borlanic 0:02dd72d1d465 550 self.cxx_symbols += ["FEATURE_" + data + "=1" for data in self.target.features]
borlanic 0:02dd72d1d465 551 # Add extra symbols passed via 'macros' parameter
borlanic 0:02dd72d1d465 552 self.cxx_symbols += self.macros
borlanic 0:02dd72d1d465 553
borlanic 0:02dd72d1d465 554 # Form factor variables
borlanic 0:02dd72d1d465 555 if hasattr(self.target, 'supported_form_factors'):
borlanic 0:02dd72d1d465 556 self.cxx_symbols.extend(["TARGET_FF_%s" % t for t in self.target.supported_form_factors])
borlanic 0:02dd72d1d465 557
borlanic 0:02dd72d1d465 558 return list(set(self.cxx_symbols)) # Return only unique symbols
borlanic 0:02dd72d1d465 559
borlanic 0:02dd72d1d465 560 # Extend the internal list of macros
borlanic 0:02dd72d1d465 561 def add_macros(self, new_macros):
borlanic 0:02dd72d1d465 562 self.macros.extend(new_macros)
borlanic 0:02dd72d1d465 563
borlanic 0:02dd72d1d465 564 def get_labels(self):
borlanic 0:02dd72d1d465 565 if self.labels is None:
borlanic 0:02dd72d1d465 566 toolchain_labels = [c.__name__ for c in getmro(self.__class__)]
borlanic 0:02dd72d1d465 567 toolchain_labels.remove('mbedToolchain')
borlanic 0:02dd72d1d465 568 self.labels = {
borlanic 0:02dd72d1d465 569 'TARGET': self.target.labels,
borlanic 0:02dd72d1d465 570 'FEATURE': self.target.features,
borlanic 0:02dd72d1d465 571 'TOOLCHAIN': toolchain_labels
borlanic 0:02dd72d1d465 572 }
borlanic 0:02dd72d1d465 573
borlanic 0:02dd72d1d465 574 # This is a policy decision and it should /really/ be in the config system
borlanic 0:02dd72d1d465 575 # ATM it's here for backward compatibility
borlanic 0:02dd72d1d465 576 if ((("-g" in self.flags['common'] or "-g3" in self.flags['common']) and
borlanic 0:02dd72d1d465 577 "-O0" in self.flags['common']) or
borlanic 0:02dd72d1d465 578 ("-r" in self.flags['common'] and
borlanic 0:02dd72d1d465 579 "-On" in self.flags['common'])):
borlanic 0:02dd72d1d465 580 self.labels['TARGET'].append("DEBUG")
borlanic 0:02dd72d1d465 581 else:
borlanic 0:02dd72d1d465 582 self.labels['TARGET'].append("RELEASE")
borlanic 0:02dd72d1d465 583 return self.labels
borlanic 0:02dd72d1d465 584
borlanic 0:02dd72d1d465 585
borlanic 0:02dd72d1d465 586 # Determine whether a source file needs updating/compiling
borlanic 0:02dd72d1d465 587 def need_update(self, target, dependencies):
borlanic 0:02dd72d1d465 588 if self.build_all:
borlanic 0:02dd72d1d465 589 return True
borlanic 0:02dd72d1d465 590
borlanic 0:02dd72d1d465 591 if not exists(target):
borlanic 0:02dd72d1d465 592 return True
borlanic 0:02dd72d1d465 593
borlanic 0:02dd72d1d465 594 target_mod_time = stat(target).st_mtime
borlanic 0:02dd72d1d465 595
borlanic 0:02dd72d1d465 596 for d in dependencies:
borlanic 0:02dd72d1d465 597 # Some objects are not provided with full path and here we do not have
borlanic 0:02dd72d1d465 598 # information about the library paths. Safe option: assume an update
borlanic 0:02dd72d1d465 599 if not d or not exists(d):
borlanic 0:02dd72d1d465 600 return True
borlanic 0:02dd72d1d465 601
borlanic 0:02dd72d1d465 602 if d not in self.stat_cache:
borlanic 0:02dd72d1d465 603 self.stat_cache[d] = stat(d).st_mtime
borlanic 0:02dd72d1d465 604
borlanic 0:02dd72d1d465 605 if self.stat_cache[d] >= target_mod_time:
borlanic 0:02dd72d1d465 606 return True
borlanic 0:02dd72d1d465 607
borlanic 0:02dd72d1d465 608 return False
borlanic 0:02dd72d1d465 609
borlanic 0:02dd72d1d465 610 def is_ignored(self, file_path):
borlanic 0:02dd72d1d465 611 """Check if file path is ignored by any .mbedignore thus far"""
borlanic 0:02dd72d1d465 612 return self._ignore_regex.match(normcase(file_path))
borlanic 0:02dd72d1d465 613
borlanic 0:02dd72d1d465 614 def add_ignore_patterns(self, root, base_path, patterns):
borlanic 0:02dd72d1d465 615 """Add a series of patterns to the ignored paths
borlanic 0:02dd72d1d465 616
borlanic 0:02dd72d1d465 617 Positional arguments:
borlanic 0:02dd72d1d465 618 root - the directory containing the ignore file
borlanic 0:02dd72d1d465 619 base_path - the location that the scan started from
borlanic 0:02dd72d1d465 620 patterns - the list of patterns we will ignore in the future
borlanic 0:02dd72d1d465 621 """
borlanic 0:02dd72d1d465 622 real_base = relpath(root, base_path)
borlanic 0:02dd72d1d465 623 if real_base == ".":
borlanic 0:02dd72d1d465 624 self.ignore_patterns.extend(normcase(p) for p in patterns)
borlanic 0:02dd72d1d465 625 else:
borlanic 0:02dd72d1d465 626 self.ignore_patterns.extend(normcase(join(real_base, pat)) for pat in patterns)
borlanic 0:02dd72d1d465 627 if self.ignore_patterns:
borlanic 0:02dd72d1d465 628 self._ignore_regex = re.compile("|".join(fnmatch.translate(p) for p in self.ignore_patterns))
borlanic 0:02dd72d1d465 629
borlanic 0:02dd72d1d465 630 # Create a Resources object from the path pointed to by *path* by either traversing a
borlanic 0:02dd72d1d465 631 # a directory structure, when *path* is a directory, or adding *path* to the resources,
borlanic 0:02dd72d1d465 632 # when *path* is a file.
borlanic 0:02dd72d1d465 633 # The parameter *base_path* is used to set the base_path attribute of the Resources
borlanic 0:02dd72d1d465 634 # object and the parameter *exclude_paths* is used by the directory traversal to
borlanic 0:02dd72d1d465 635 # exclude certain paths from the traversal.
borlanic 0:02dd72d1d465 636 def scan_resources(self, path, exclude_paths=None, base_path=None,
borlanic 0:02dd72d1d465 637 collect_ignores=False):
borlanic 0:02dd72d1d465 638 self.progress("scan", path)
borlanic 0:02dd72d1d465 639
borlanic 0:02dd72d1d465 640 resources = Resources(path, collect_ignores=collect_ignores)
borlanic 0:02dd72d1d465 641 if not base_path:
borlanic 0:02dd72d1d465 642 if isfile(path):
borlanic 0:02dd72d1d465 643 base_path = dirname(path)
borlanic 0:02dd72d1d465 644 else:
borlanic 0:02dd72d1d465 645 base_path = path
borlanic 0:02dd72d1d465 646 resources.base_path = base_path
borlanic 0:02dd72d1d465 647
borlanic 0:02dd72d1d465 648 if isfile(path):
borlanic 0:02dd72d1d465 649 self._add_file(path, resources, base_path, exclude_paths=exclude_paths)
borlanic 0:02dd72d1d465 650 else:
borlanic 0:02dd72d1d465 651 self._add_dir(path, resources, base_path, exclude_paths=exclude_paths)
borlanic 0:02dd72d1d465 652 return resources
borlanic 0:02dd72d1d465 653
borlanic 0:02dd72d1d465 654 # A helper function for scan_resources. _add_dir traverses *path* (assumed to be a
borlanic 0:02dd72d1d465 655 # directory) and heeds the ".mbedignore" files along the way. _add_dir calls _add_file
borlanic 0:02dd72d1d465 656 # on every file it considers adding to the resources object.
borlanic 0:02dd72d1d465 657 def _add_dir(self, path, resources, base_path, exclude_paths=None):
borlanic 0:02dd72d1d465 658 """ os.walk(top[, topdown=True[, onerror=None[, followlinks=False]]])
borlanic 0:02dd72d1d465 659 When topdown is True, the caller can modify the dirnames list in-place
borlanic 0:02dd72d1d465 660 (perhaps using del or slice assignment), and walk() will only recurse into
borlanic 0:02dd72d1d465 661 the subdirectories whose names remain in dirnames; this can be used to prune
borlanic 0:02dd72d1d465 662 the search, impose a specific order of visiting, or even to inform walk()
borlanic 0:02dd72d1d465 663 about directories the caller creates or renames before it resumes walk()
borlanic 0:02dd72d1d465 664 again. Modifying dirnames when topdown is False is ineffective, because in
borlanic 0:02dd72d1d465 665 bottom-up mode the directories in dirnames are generated before dirpath
borlanic 0:02dd72d1d465 666 itself is generated.
borlanic 0:02dd72d1d465 667 """
borlanic 0:02dd72d1d465 668 labels = self.get_labels()
borlanic 0:02dd72d1d465 669 for root, dirs, files in walk(path, followlinks=True):
borlanic 0:02dd72d1d465 670 # Check if folder contains .mbedignore
borlanic 0:02dd72d1d465 671 if ".mbedignore" in files:
borlanic 0:02dd72d1d465 672 with open (join(root,".mbedignore"), "r") as f:
borlanic 0:02dd72d1d465 673 lines=f.readlines()
borlanic 0:02dd72d1d465 674 lines = [l.strip() for l in lines] # Strip whitespaces
borlanic 0:02dd72d1d465 675 lines = [l for l in lines if l != ""] # Strip empty lines
borlanic 0:02dd72d1d465 676 lines = [l for l in lines if not re.match("^#",l)] # Strip comment lines
borlanic 0:02dd72d1d465 677 # Append root path to glob patterns and append patterns to ignore_patterns
borlanic 0:02dd72d1d465 678 self.add_ignore_patterns(root, base_path, lines)
borlanic 0:02dd72d1d465 679
borlanic 0:02dd72d1d465 680 # Skip the whole folder if ignored, e.g. .mbedignore containing '*'
borlanic 0:02dd72d1d465 681 root_path =join(relpath(root, base_path))
borlanic 0:02dd72d1d465 682 if (self.is_ignored(join(root_path,"")) or
borlanic 0:02dd72d1d465 683 self.build_dir == root_path):
borlanic 0:02dd72d1d465 684 resources.ignore_dir(root_path)
borlanic 0:02dd72d1d465 685 dirs[:] = []
borlanic 0:02dd72d1d465 686 continue
borlanic 0:02dd72d1d465 687
borlanic 0:02dd72d1d465 688 for d in copy(dirs):
borlanic 0:02dd72d1d465 689 dir_path = join(root, d)
borlanic 0:02dd72d1d465 690 # Add internal repo folders/files. This is needed for exporters
borlanic 0:02dd72d1d465 691 if d == '.hg' or d == '.git':
borlanic 0:02dd72d1d465 692 resources.repo_dirs.append(dir_path)
borlanic 0:02dd72d1d465 693
borlanic 0:02dd72d1d465 694 if ((d.startswith('.') or d in self.legacy_ignore_dirs) or
borlanic 0:02dd72d1d465 695 # Ignore targets that do not match the TARGET in extra_labels list
borlanic 0:02dd72d1d465 696 (d.startswith('TARGET_') and d[7:] not in labels['TARGET']) or
borlanic 0:02dd72d1d465 697 # Ignore toolchain that do not match the current TOOLCHAIN
borlanic 0:02dd72d1d465 698 (d.startswith('TOOLCHAIN_') and d[10:] not in labels['TOOLCHAIN']) or
borlanic 0:02dd72d1d465 699 # Ignore .mbedignore files
borlanic 0:02dd72d1d465 700 self.is_ignored(join(relpath(root, base_path), d,"")) or
borlanic 0:02dd72d1d465 701 # Ignore TESTS dir
borlanic 0:02dd72d1d465 702 (d == 'TESTS')):
borlanic 0:02dd72d1d465 703 resources.ignore_dir(dir_path)
borlanic 0:02dd72d1d465 704 dirs.remove(d)
borlanic 0:02dd72d1d465 705 elif d.startswith('FEATURE_'):
borlanic 0:02dd72d1d465 706 # Recursively scan features but ignore them in the current scan.
borlanic 0:02dd72d1d465 707 # These are dynamically added by the config system if the conditions are matched
borlanic 0:02dd72d1d465 708 def closure (dir_path=dir_path, base_path=base_path):
borlanic 0:02dd72d1d465 709 return self.scan_resources(dir_path, base_path=base_path,
borlanic 0:02dd72d1d465 710 collect_ignores=resources.collect_ignores)
borlanic 0:02dd72d1d465 711 resources.features.add_lazy(d[8:], closure)
borlanic 0:02dd72d1d465 712 resources.ignore_dir(dir_path)
borlanic 0:02dd72d1d465 713 dirs.remove(d)
borlanic 0:02dd72d1d465 714 elif exclude_paths:
borlanic 0:02dd72d1d465 715 for exclude_path in exclude_paths:
borlanic 0:02dd72d1d465 716 rel_path = relpath(dir_path, exclude_path)
borlanic 0:02dd72d1d465 717 if not (rel_path.startswith('..')):
borlanic 0:02dd72d1d465 718 resources.ignore_dir(dir_path)
borlanic 0:02dd72d1d465 719 dirs.remove(d)
borlanic 0:02dd72d1d465 720 break
borlanic 0:02dd72d1d465 721
borlanic 0:02dd72d1d465 722 # Add root to include paths
borlanic 0:02dd72d1d465 723 root = root.rstrip("/")
borlanic 0:02dd72d1d465 724 resources.inc_dirs.append(root)
borlanic 0:02dd72d1d465 725 resources.file_basepath[root] = base_path
borlanic 0:02dd72d1d465 726
borlanic 0:02dd72d1d465 727 for file in files:
borlanic 0:02dd72d1d465 728 file_path = join(root, file)
borlanic 0:02dd72d1d465 729 self._add_file(file_path, resources, base_path)
borlanic 0:02dd72d1d465 730
borlanic 0:02dd72d1d465 731 # A helper function for both scan_resources and _add_dir. _add_file adds one file
borlanic 0:02dd72d1d465 732 # (*file_path*) to the resources object based on the file type.
borlanic 0:02dd72d1d465 733 def _add_file(self, file_path, resources, base_path, exclude_paths=None):
borlanic 0:02dd72d1d465 734
borlanic 0:02dd72d1d465 735 if (self.is_ignored(relpath(file_path, base_path)) or
borlanic 0:02dd72d1d465 736 basename(file_path).startswith(".")):
borlanic 0:02dd72d1d465 737 resources.ignore_dir(relpath(file_path, base_path))
borlanic 0:02dd72d1d465 738 return
borlanic 0:02dd72d1d465 739
borlanic 0:02dd72d1d465 740 resources.file_basepath[file_path] = base_path
borlanic 0:02dd72d1d465 741 _, ext = splitext(file_path)
borlanic 0:02dd72d1d465 742 ext = ext.lower()
borlanic 0:02dd72d1d465 743
borlanic 0:02dd72d1d465 744 if ext == '.s':
borlanic 0:02dd72d1d465 745 resources.s_sources.append(file_path)
borlanic 0:02dd72d1d465 746
borlanic 0:02dd72d1d465 747 elif ext == '.c':
borlanic 0:02dd72d1d465 748 resources.c_sources.append(file_path)
borlanic 0:02dd72d1d465 749
borlanic 0:02dd72d1d465 750 elif ext == '.cpp':
borlanic 0:02dd72d1d465 751 resources.cpp_sources.append(file_path)
borlanic 0:02dd72d1d465 752
borlanic 0:02dd72d1d465 753 elif ext == '.h' or ext == '.hpp':
borlanic 0:02dd72d1d465 754 resources.headers.append(file_path)
borlanic 0:02dd72d1d465 755
borlanic 0:02dd72d1d465 756 elif ext == '.o':
borlanic 0:02dd72d1d465 757 resources.objects.append(file_path)
borlanic 0:02dd72d1d465 758
borlanic 0:02dd72d1d465 759 elif ext == self.LIBRARY_EXT:
borlanic 0:02dd72d1d465 760 resources.libraries.append(file_path)
borlanic 0:02dd72d1d465 761 resources.lib_dirs.add(dirname(file_path))
borlanic 0:02dd72d1d465 762
borlanic 0:02dd72d1d465 763 elif ext == self.LINKER_EXT:
borlanic 0:02dd72d1d465 764 if resources.linker_script is not None:
borlanic 0:02dd72d1d465 765 self.info("Warning: Multiple linker scripts detected: %s -> %s" % (resources.linker_script, file_path))
borlanic 0:02dd72d1d465 766 resources.linker_script = file_path
borlanic 0:02dd72d1d465 767
borlanic 0:02dd72d1d465 768 elif ext == '.lib':
borlanic 0:02dd72d1d465 769 resources.lib_refs.append(file_path)
borlanic 0:02dd72d1d465 770
borlanic 0:02dd72d1d465 771 elif ext == '.bld':
borlanic 0:02dd72d1d465 772 resources.lib_builds.append(file_path)
borlanic 0:02dd72d1d465 773
borlanic 0:02dd72d1d465 774 elif basename(file_path) == '.hgignore':
borlanic 0:02dd72d1d465 775 resources.repo_files.append(file_path)
borlanic 0:02dd72d1d465 776
borlanic 0:02dd72d1d465 777 elif basename(file_path) == '.gitignore':
borlanic 0:02dd72d1d465 778 resources.repo_files.append(file_path)
borlanic 0:02dd72d1d465 779
borlanic 0:02dd72d1d465 780 elif ext == '.hex':
borlanic 0:02dd72d1d465 781 resources.hex_files.append(file_path)
borlanic 0:02dd72d1d465 782
borlanic 0:02dd72d1d465 783 elif ext == '.bin':
borlanic 0:02dd72d1d465 784 resources.bin_files.append(file_path)
borlanic 0:02dd72d1d465 785
borlanic 0:02dd72d1d465 786 elif ext == '.json':
borlanic 0:02dd72d1d465 787 resources.json_files.append(file_path)
borlanic 0:02dd72d1d465 788
borlanic 0:02dd72d1d465 789
borlanic 0:02dd72d1d465 790 def scan_repository(self, path):
borlanic 0:02dd72d1d465 791 resources = []
borlanic 0:02dd72d1d465 792
borlanic 0:02dd72d1d465 793 for root, dirs, files in walk(path):
borlanic 0:02dd72d1d465 794 # Remove ignored directories
borlanic 0:02dd72d1d465 795 for d in copy(dirs):
borlanic 0:02dd72d1d465 796 if d == '.' or d == '..':
borlanic 0:02dd72d1d465 797 dirs.remove(d)
borlanic 0:02dd72d1d465 798
borlanic 0:02dd72d1d465 799 for file in files:
borlanic 0:02dd72d1d465 800 file_path = join(root, file)
borlanic 0:02dd72d1d465 801 resources.append(file_path)
borlanic 0:02dd72d1d465 802
borlanic 0:02dd72d1d465 803 return resources
borlanic 0:02dd72d1d465 804
borlanic 0:02dd72d1d465 805 def copy_files(self, files_paths, trg_path, resources=None, rel_path=None):
borlanic 0:02dd72d1d465 806 # Handle a single file
borlanic 0:02dd72d1d465 807 if not isinstance(files_paths, list):
borlanic 0:02dd72d1d465 808 files_paths = [files_paths]
borlanic 0:02dd72d1d465 809
borlanic 0:02dd72d1d465 810 for source in files_paths:
borlanic 0:02dd72d1d465 811 if source is None:
borlanic 0:02dd72d1d465 812 files_paths.remove(source)
borlanic 0:02dd72d1d465 813
borlanic 0:02dd72d1d465 814 for source in files_paths:
borlanic 0:02dd72d1d465 815 if resources is not None and source in resources.file_basepath:
borlanic 0:02dd72d1d465 816 relative_path = relpath(source, resources.file_basepath[source])
borlanic 0:02dd72d1d465 817 elif rel_path is not None:
borlanic 0:02dd72d1d465 818 relative_path = relpath(source, rel_path)
borlanic 0:02dd72d1d465 819 else:
borlanic 0:02dd72d1d465 820 _, relative_path = split(source)
borlanic 0:02dd72d1d465 821
borlanic 0:02dd72d1d465 822 target = join(trg_path, relative_path)
borlanic 0:02dd72d1d465 823
borlanic 0:02dd72d1d465 824 if (target != source) and (self.need_update(target, [source])):
borlanic 0:02dd72d1d465 825 self.progress("copy", relative_path)
borlanic 0:02dd72d1d465 826 mkdir(dirname(target))
borlanic 0:02dd72d1d465 827 copyfile(source, target)
borlanic 0:02dd72d1d465 828
borlanic 0:02dd72d1d465 829 # THIS METHOD IS BEING OVERRIDDEN BY THE MBED ONLINE BUILD SYSTEM
borlanic 0:02dd72d1d465 830 # ANY CHANGE OF PARAMETERS OR RETURN VALUES WILL BREAK COMPATIBILITY
borlanic 0:02dd72d1d465 831 def relative_object_path(self, build_path, base_dir, source):
borlanic 0:02dd72d1d465 832 source_dir, name, _ = split_path(source)
borlanic 0:02dd72d1d465 833
borlanic 0:02dd72d1d465 834 obj_dir = relpath(join(build_path, relpath(source_dir, base_dir)))
borlanic 0:02dd72d1d465 835 if obj_dir is not self.prev_dir:
borlanic 0:02dd72d1d465 836 self.prev_dir = obj_dir
borlanic 0:02dd72d1d465 837 mkdir(obj_dir)
borlanic 0:02dd72d1d465 838 return join(obj_dir, name + '.o')
borlanic 0:02dd72d1d465 839
borlanic 0:02dd72d1d465 840 # Generate response file for all includes.
borlanic 0:02dd72d1d465 841 # ARM, GCC, IAR cross compatible
borlanic 0:02dd72d1d465 842 def get_inc_file(self, includes):
borlanic 0:02dd72d1d465 843 include_file = join(self.build_dir, ".includes_%s.txt" % self.inc_md5)
borlanic 0:02dd72d1d465 844 if not exists(include_file):
borlanic 0:02dd72d1d465 845 with open(include_file, "w") as f:
borlanic 0:02dd72d1d465 846 cmd_list = []
borlanic 0:02dd72d1d465 847 for c in includes:
borlanic 0:02dd72d1d465 848 if c:
borlanic 0:02dd72d1d465 849 c = c.replace("\\", "/")
borlanic 0:02dd72d1d465 850 if self.CHROOT:
borlanic 0:02dd72d1d465 851 c = c.replace(self.CHROOT, '')
borlanic 0:02dd72d1d465 852 cmd_list.append('"-I%s"' % c)
borlanic 0:02dd72d1d465 853 string = " ".join(cmd_list)
borlanic 0:02dd72d1d465 854 f.write(string)
borlanic 0:02dd72d1d465 855 return include_file
borlanic 0:02dd72d1d465 856
borlanic 0:02dd72d1d465 857 # Generate response file for all objects when linking.
borlanic 0:02dd72d1d465 858 # ARM, GCC, IAR cross compatible
borlanic 0:02dd72d1d465 859 def get_link_file(self, cmd):
borlanic 0:02dd72d1d465 860 link_file = join(self.build_dir, ".link_files.txt")
borlanic 0:02dd72d1d465 861 with open(link_file, "w") as f:
borlanic 0:02dd72d1d465 862 cmd_list = []
borlanic 0:02dd72d1d465 863 for c in cmd:
borlanic 0:02dd72d1d465 864 if c:
borlanic 0:02dd72d1d465 865 c = c.replace("\\", "/")
borlanic 0:02dd72d1d465 866 if self.CHROOT:
borlanic 0:02dd72d1d465 867 c = c.replace(self.CHROOT, '')
borlanic 0:02dd72d1d465 868 cmd_list.append(('"%s"' % c) if not c.startswith('-') else c)
borlanic 0:02dd72d1d465 869 string = " ".join(cmd_list)
borlanic 0:02dd72d1d465 870 f.write(string)
borlanic 0:02dd72d1d465 871 return link_file
borlanic 0:02dd72d1d465 872
borlanic 0:02dd72d1d465 873 # Generate response file for all objects when archiving.
borlanic 0:02dd72d1d465 874 # ARM, GCC, IAR cross compatible
borlanic 0:02dd72d1d465 875 def get_arch_file(self, objects):
borlanic 0:02dd72d1d465 876 archive_file = join(self.build_dir, ".archive_files.txt")
borlanic 0:02dd72d1d465 877 with open(archive_file, "w") as f:
borlanic 0:02dd72d1d465 878 o_list = []
borlanic 0:02dd72d1d465 879 for o in objects:
borlanic 0:02dd72d1d465 880 o_list.append('"%s"' % o)
borlanic 0:02dd72d1d465 881 string = " ".join(o_list).replace("\\", "/")
borlanic 0:02dd72d1d465 882 f.write(string)
borlanic 0:02dd72d1d465 883 return archive_file
borlanic 0:02dd72d1d465 884
borlanic 0:02dd72d1d465 885 # THIS METHOD IS BEING CALLED BY THE MBED ONLINE BUILD SYSTEM
borlanic 0:02dd72d1d465 886 # ANY CHANGE OF PARAMETERS OR RETURN VALUES WILL BREAK COMPATIBILITY
borlanic 0:02dd72d1d465 887 def compile_sources(self, resources, inc_dirs=None):
borlanic 0:02dd72d1d465 888 # Web IDE progress bar for project build
borlanic 0:02dd72d1d465 889 files_to_compile = resources.s_sources + resources.c_sources + resources.cpp_sources
borlanic 0:02dd72d1d465 890 self.to_be_compiled = len(files_to_compile)
borlanic 0:02dd72d1d465 891 self.compiled = 0
borlanic 0:02dd72d1d465 892
borlanic 0:02dd72d1d465 893 self.cc_verbose("Macros: "+' '.join(['-D%s' % s for s in self.get_symbols()]))
borlanic 0:02dd72d1d465 894
borlanic 0:02dd72d1d465 895 inc_paths = resources.inc_dirs
borlanic 0:02dd72d1d465 896 if inc_dirs is not None:
borlanic 0:02dd72d1d465 897 if isinstance(inc_dirs, list):
borlanic 0:02dd72d1d465 898 inc_paths.extend(inc_dirs)
borlanic 0:02dd72d1d465 899 else:
borlanic 0:02dd72d1d465 900 inc_paths.append(inc_dirs)
borlanic 0:02dd72d1d465 901 # De-duplicate include paths
borlanic 0:02dd72d1d465 902 inc_paths = set(inc_paths)
borlanic 0:02dd72d1d465 903 # Sort include paths for consistency
borlanic 0:02dd72d1d465 904 inc_paths = sorted(set(inc_paths))
borlanic 0:02dd72d1d465 905 # Unique id of all include paths
borlanic 0:02dd72d1d465 906 self.inc_md5 = md5(' '.join(inc_paths).encode('utf-8')).hexdigest()
borlanic 0:02dd72d1d465 907
borlanic 0:02dd72d1d465 908 objects = []
borlanic 0:02dd72d1d465 909 queue = []
borlanic 0:02dd72d1d465 910 work_dir = getcwd()
borlanic 0:02dd72d1d465 911 self.prev_dir = None
borlanic 0:02dd72d1d465 912
borlanic 0:02dd72d1d465 913 # Generate configuration header (this will update self.build_all if needed)
borlanic 0:02dd72d1d465 914 self.get_config_header()
borlanic 0:02dd72d1d465 915 self.dump_build_profile()
borlanic 0:02dd72d1d465 916
borlanic 0:02dd72d1d465 917 # Sort compile queue for consistency
borlanic 0:02dd72d1d465 918 files_to_compile.sort()
borlanic 0:02dd72d1d465 919 for source in files_to_compile:
borlanic 0:02dd72d1d465 920 object = self.relative_object_path(
borlanic 0:02dd72d1d465 921 self.build_dir, resources.file_basepath[source], source)
borlanic 0:02dd72d1d465 922
borlanic 0:02dd72d1d465 923 # Queue mode (multiprocessing)
borlanic 0:02dd72d1d465 924 commands = self.compile_command(source, object, inc_paths)
borlanic 0:02dd72d1d465 925 if commands is not None:
borlanic 0:02dd72d1d465 926 queue.append({
borlanic 0:02dd72d1d465 927 'source': source,
borlanic 0:02dd72d1d465 928 'object': object,
borlanic 0:02dd72d1d465 929 'commands': commands,
borlanic 0:02dd72d1d465 930 'work_dir': work_dir,
borlanic 0:02dd72d1d465 931 'chroot': self.CHROOT
borlanic 0:02dd72d1d465 932 })
borlanic 0:02dd72d1d465 933 else:
borlanic 0:02dd72d1d465 934 self.compiled += 1
borlanic 0:02dd72d1d465 935 objects.append(object)
borlanic 0:02dd72d1d465 936
borlanic 0:02dd72d1d465 937 # Use queues/multiprocessing if cpu count is higher than setting
borlanic 0:02dd72d1d465 938 jobs = self.jobs if self.jobs else cpu_count()
borlanic 0:02dd72d1d465 939 if jobs > CPU_COUNT_MIN and len(queue) > jobs:
borlanic 0:02dd72d1d465 940 return self.compile_queue(queue, objects)
borlanic 0:02dd72d1d465 941 else:
borlanic 0:02dd72d1d465 942 return self.compile_seq(queue, objects)
borlanic 0:02dd72d1d465 943
borlanic 0:02dd72d1d465 944 # Compile source files queue in sequential order
borlanic 0:02dd72d1d465 945 def compile_seq(self, queue, objects):
borlanic 0:02dd72d1d465 946 for item in queue:
borlanic 0:02dd72d1d465 947 result = compile_worker(item)
borlanic 0:02dd72d1d465 948
borlanic 0:02dd72d1d465 949 self.compiled += 1
borlanic 0:02dd72d1d465 950 self.progress("compile", item['source'], build_update=True)
borlanic 0:02dd72d1d465 951 for res in result['results']:
borlanic 0:02dd72d1d465 952 self.cc_verbose("Compile: %s" % ' '.join(res['command']), result['source'])
borlanic 0:02dd72d1d465 953 self.compile_output([
borlanic 0:02dd72d1d465 954 res['code'],
borlanic 0:02dd72d1d465 955 res['output'],
borlanic 0:02dd72d1d465 956 res['command']
borlanic 0:02dd72d1d465 957 ])
borlanic 0:02dd72d1d465 958 objects.append(result['object'])
borlanic 0:02dd72d1d465 959 return objects
borlanic 0:02dd72d1d465 960
borlanic 0:02dd72d1d465 961 # Compile source files queue in parallel by creating pool of worker threads
borlanic 0:02dd72d1d465 962 def compile_queue(self, queue, objects):
borlanic 0:02dd72d1d465 963 jobs_count = int(self.jobs if self.jobs else cpu_count() * CPU_COEF)
borlanic 0:02dd72d1d465 964 p = Pool(processes=jobs_count)
borlanic 0:02dd72d1d465 965
borlanic 0:02dd72d1d465 966 results = []
borlanic 0:02dd72d1d465 967 for i in range(len(queue)):
borlanic 0:02dd72d1d465 968 results.append(p.apply_async(compile_worker, [queue[i]]))
borlanic 0:02dd72d1d465 969 p.close()
borlanic 0:02dd72d1d465 970
borlanic 0:02dd72d1d465 971 itr = 0
borlanic 0:02dd72d1d465 972 while len(results):
borlanic 0:02dd72d1d465 973 itr += 1
borlanic 0:02dd72d1d465 974 if itr > 180000:
borlanic 0:02dd72d1d465 975 p.terminate()
borlanic 0:02dd72d1d465 976 p.join()
borlanic 0:02dd72d1d465 977 raise ToolException("Compile did not finish in 5 minutes")
borlanic 0:02dd72d1d465 978
borlanic 0:02dd72d1d465 979 sleep(0.01)
borlanic 0:02dd72d1d465 980 pending = 0
borlanic 0:02dd72d1d465 981 for r in results:
borlanic 0:02dd72d1d465 982 if r.ready():
borlanic 0:02dd72d1d465 983 try:
borlanic 0:02dd72d1d465 984 result = r.get()
borlanic 0:02dd72d1d465 985 results.remove(r)
borlanic 0:02dd72d1d465 986
borlanic 0:02dd72d1d465 987 self.compiled += 1
borlanic 0:02dd72d1d465 988 self.progress("compile", result['source'], build_update=True)
borlanic 0:02dd72d1d465 989 for res in result['results']:
borlanic 0:02dd72d1d465 990 self.cc_verbose("Compile: %s" % ' '.join(res['command']), result['source'])
borlanic 0:02dd72d1d465 991 self.compile_output([
borlanic 0:02dd72d1d465 992 res['code'],
borlanic 0:02dd72d1d465 993 res['output'],
borlanic 0:02dd72d1d465 994 res['command']
borlanic 0:02dd72d1d465 995 ])
borlanic 0:02dd72d1d465 996 objects.append(result['object'])
borlanic 0:02dd72d1d465 997 except ToolException as err:
borlanic 0:02dd72d1d465 998 if p._taskqueue.queue:
borlanic 0:02dd72d1d465 999 p._taskqueue.queue.clear()
borlanic 0:02dd72d1d465 1000 sleep(0.5)
borlanic 0:02dd72d1d465 1001 p.terminate()
borlanic 0:02dd72d1d465 1002 p.join()
borlanic 0:02dd72d1d465 1003 raise ToolException(err)
borlanic 0:02dd72d1d465 1004 else:
borlanic 0:02dd72d1d465 1005 pending += 1
borlanic 0:02dd72d1d465 1006 if pending >= jobs_count:
borlanic 0:02dd72d1d465 1007 break
borlanic 0:02dd72d1d465 1008
borlanic 0:02dd72d1d465 1009 results = None
borlanic 0:02dd72d1d465 1010 p.join()
borlanic 0:02dd72d1d465 1011
borlanic 0:02dd72d1d465 1012 return objects
borlanic 0:02dd72d1d465 1013
borlanic 0:02dd72d1d465 1014 # Determine the compile command based on type of source file
borlanic 0:02dd72d1d465 1015 def compile_command(self, source, object, includes):
borlanic 0:02dd72d1d465 1016 # Check dependencies
borlanic 0:02dd72d1d465 1017 _, ext = splitext(source)
borlanic 0:02dd72d1d465 1018 ext = ext.lower()
borlanic 0:02dd72d1d465 1019
borlanic 0:02dd72d1d465 1020 if ext == '.c' or ext == '.cpp':
borlanic 0:02dd72d1d465 1021 base, _ = splitext(object)
borlanic 0:02dd72d1d465 1022 dep_path = base + '.d'
borlanic 0:02dd72d1d465 1023 try:
borlanic 0:02dd72d1d465 1024 deps = self.parse_dependencies(dep_path) if (exists(dep_path)) else []
borlanic 0:02dd72d1d465 1025 except (IOError, IndexError):
borlanic 0:02dd72d1d465 1026 deps = []
borlanic 0:02dd72d1d465 1027 config_file = ([self.config.app_config_location]
borlanic 0:02dd72d1d465 1028 if self.config.app_config_location else [])
borlanic 0:02dd72d1d465 1029 deps.extend(config_file)
borlanic 0:02dd72d1d465 1030 if ext == '.cpp' or self.COMPILE_C_AS_CPP:
borlanic 0:02dd72d1d465 1031 deps.append(join(self.build_dir, self.PROFILE_FILE_NAME + "-cxx"))
borlanic 0:02dd72d1d465 1032 else:
borlanic 0:02dd72d1d465 1033 deps.append(join(self.build_dir, self.PROFILE_FILE_NAME + "-c"))
borlanic 0:02dd72d1d465 1034 if len(deps) == 0 or self.need_update(object, deps):
borlanic 0:02dd72d1d465 1035 if ext == '.cpp' or self.COMPILE_C_AS_CPP:
borlanic 0:02dd72d1d465 1036 return self.compile_cpp(source, object, includes)
borlanic 0:02dd72d1d465 1037 else:
borlanic 0:02dd72d1d465 1038 return self.compile_c(source, object, includes)
borlanic 0:02dd72d1d465 1039 elif ext == '.s':
borlanic 0:02dd72d1d465 1040 deps = [source]
borlanic 0:02dd72d1d465 1041 deps.append(join(self.build_dir, self.PROFILE_FILE_NAME + "-asm"))
borlanic 0:02dd72d1d465 1042 if self.need_update(object, deps):
borlanic 0:02dd72d1d465 1043 return self.assemble(source, object, includes)
borlanic 0:02dd72d1d465 1044 else:
borlanic 0:02dd72d1d465 1045 return False
borlanic 0:02dd72d1d465 1046
borlanic 0:02dd72d1d465 1047 return None
borlanic 0:02dd72d1d465 1048
borlanic 0:02dd72d1d465 1049 def parse_dependencies(self, dep_path):
borlanic 0:02dd72d1d465 1050 """Parse the dependency information generated by the compiler.
borlanic 0:02dd72d1d465 1051
borlanic 0:02dd72d1d465 1052 Positional arguments:
borlanic 0:02dd72d1d465 1053 dep_path -- the path to a file generated by a previous run of the compiler
borlanic 0:02dd72d1d465 1054
borlanic 0:02dd72d1d465 1055 Return value:
borlanic 0:02dd72d1d465 1056 A list of all source files that the dependency file indicated were dependencies
borlanic 0:02dd72d1d465 1057
borlanic 0:02dd72d1d465 1058 Side effects:
borlanic 0:02dd72d1d465 1059 None
borlanic 0:02dd72d1d465 1060
borlanic 0:02dd72d1d465 1061 Note: A default implementation is provided for make-like file formats
borlanic 0:02dd72d1d465 1062 """
borlanic 0:02dd72d1d465 1063 dependencies = []
borlanic 0:02dd72d1d465 1064 buff = open(dep_path).readlines()
borlanic 0:02dd72d1d465 1065 if buff:
borlanic 0:02dd72d1d465 1066 buff[0] = re.sub('^(.*?)\: ', '', buff[0])
borlanic 0:02dd72d1d465 1067 for line in buff:
borlanic 0:02dd72d1d465 1068 filename = line.replace('\\\n', '').strip()
borlanic 0:02dd72d1d465 1069 if filename:
borlanic 0:02dd72d1d465 1070 filename = filename.replace('\\ ', '\a')
borlanic 0:02dd72d1d465 1071 dependencies.extend(((self.CHROOT if self.CHROOT else '') +
borlanic 0:02dd72d1d465 1072 f.replace('\a', ' '))
borlanic 0:02dd72d1d465 1073 for f in filename.split(" "))
borlanic 0:02dd72d1d465 1074 return list(filter(None, dependencies))
borlanic 0:02dd72d1d465 1075
borlanic 0:02dd72d1d465 1076 def is_not_supported_error(self, output):
borlanic 0:02dd72d1d465 1077 return "#error directive: [NOT_SUPPORTED]" in output
borlanic 0:02dd72d1d465 1078
borlanic 0:02dd72d1d465 1079 @abstractmethod
borlanic 0:02dd72d1d465 1080 def parse_output(self, output):
borlanic 0:02dd72d1d465 1081 """Take in compiler output and extract sinlge line warnings and errors from it.
borlanic 0:02dd72d1d465 1082
borlanic 0:02dd72d1d465 1083 Positional arguments:
borlanic 0:02dd72d1d465 1084 output -- a string of all the messages emitted by a run of the compiler
borlanic 0:02dd72d1d465 1085
borlanic 0:02dd72d1d465 1086 Return value:
borlanic 0:02dd72d1d465 1087 None
borlanic 0:02dd72d1d465 1088
borlanic 0:02dd72d1d465 1089 Side effects:
borlanic 0:02dd72d1d465 1090 call self.cc_info or self.notify with a description of the event generated by the compiler
borlanic 0:02dd72d1d465 1091 """
borlanic 0:02dd72d1d465 1092 raise NotImplemented
borlanic 0:02dd72d1d465 1093
borlanic 0:02dd72d1d465 1094 def compile_output(self, output=[]):
borlanic 0:02dd72d1d465 1095 _rc = output[0]
borlanic 0:02dd72d1d465 1096 _stderr = output[1].decode("utf-8")
borlanic 0:02dd72d1d465 1097 command = output[2]
borlanic 0:02dd72d1d465 1098
borlanic 0:02dd72d1d465 1099 # Parse output for Warnings and Errors
borlanic 0:02dd72d1d465 1100 self.parse_output(_stderr)
borlanic 0:02dd72d1d465 1101 self.debug("Return: %s"% _rc)
borlanic 0:02dd72d1d465 1102 for error_line in _stderr.splitlines():
borlanic 0:02dd72d1d465 1103 self.debug("Output: %s"% error_line)
borlanic 0:02dd72d1d465 1104
borlanic 0:02dd72d1d465 1105 # Check return code
borlanic 0:02dd72d1d465 1106 if _rc != 0:
borlanic 0:02dd72d1d465 1107 if self.is_not_supported_error(_stderr):
borlanic 0:02dd72d1d465 1108 raise NotSupportedException(_stderr)
borlanic 0:02dd72d1d465 1109 else:
borlanic 0:02dd72d1d465 1110 raise ToolException(_stderr)
borlanic 0:02dd72d1d465 1111
borlanic 0:02dd72d1d465 1112 def build_library(self, objects, dir, name):
borlanic 0:02dd72d1d465 1113 needed_update = False
borlanic 0:02dd72d1d465 1114 lib = self.STD_LIB_NAME % name
borlanic 0:02dd72d1d465 1115 fout = join(dir, lib)
borlanic 0:02dd72d1d465 1116 if self.need_update(fout, objects):
borlanic 0:02dd72d1d465 1117 self.info("Library: %s" % lib)
borlanic 0:02dd72d1d465 1118 self.archive(objects, fout)
borlanic 0:02dd72d1d465 1119 needed_update = True
borlanic 0:02dd72d1d465 1120
borlanic 0:02dd72d1d465 1121 return needed_update
borlanic 0:02dd72d1d465 1122
borlanic 0:02dd72d1d465 1123 def link_program(self, r, tmp_path, name):
borlanic 0:02dd72d1d465 1124 needed_update = False
borlanic 0:02dd72d1d465 1125 ext = 'bin'
borlanic 0:02dd72d1d465 1126 if hasattr(self.target, 'OUTPUT_EXT'):
borlanic 0:02dd72d1d465 1127 ext = self.target.OUTPUT_EXT
borlanic 0:02dd72d1d465 1128
borlanic 0:02dd72d1d465 1129 if hasattr(self.target, 'OUTPUT_NAMING'):
borlanic 0:02dd72d1d465 1130 self.var("binary_naming", self.target.OUTPUT_NAMING)
borlanic 0:02dd72d1d465 1131 if self.target.OUTPUT_NAMING == "8.3":
borlanic 0:02dd72d1d465 1132 name = name[0:8]
borlanic 0:02dd72d1d465 1133 ext = ext[0:3]
borlanic 0:02dd72d1d465 1134
borlanic 0:02dd72d1d465 1135 # Create destination directory
borlanic 0:02dd72d1d465 1136 head, tail = split(name)
borlanic 0:02dd72d1d465 1137 new_path = join(tmp_path, head)
borlanic 0:02dd72d1d465 1138 mkdir(new_path)
borlanic 0:02dd72d1d465 1139
borlanic 0:02dd72d1d465 1140 filename = name+'.'+ext
borlanic 0:02dd72d1d465 1141 # Absolute path of the final linked file
borlanic 0:02dd72d1d465 1142 full_path = join(tmp_path, filename)
borlanic 0:02dd72d1d465 1143 elf = join(tmp_path, name + '.elf')
borlanic 0:02dd72d1d465 1144 bin = None if ext == 'elf' else full_path
borlanic 0:02dd72d1d465 1145 map = join(tmp_path, name + '.map')
borlanic 0:02dd72d1d465 1146
borlanic 0:02dd72d1d465 1147 r.objects = sorted(set(r.objects))
borlanic 0:02dd72d1d465 1148 config_file = ([self.config.app_config_location]
borlanic 0:02dd72d1d465 1149 if self.config.app_config_location else [])
borlanic 0:02dd72d1d465 1150 dependencies = r.objects + r.libraries + [r.linker_script] + config_file
borlanic 0:02dd72d1d465 1151 dependencies.append(join(self.build_dir, self.PROFILE_FILE_NAME + "-ld"))
borlanic 0:02dd72d1d465 1152 if self.need_update(elf, dependencies):
borlanic 0:02dd72d1d465 1153 needed_update = True
borlanic 0:02dd72d1d465 1154 self.progress("link", name)
borlanic 0:02dd72d1d465 1155 self.link(elf, r.objects, r.libraries, r.lib_dirs, r.linker_script)
borlanic 0:02dd72d1d465 1156
borlanic 0:02dd72d1d465 1157 if bin and self.need_update(bin, [elf]):
borlanic 0:02dd72d1d465 1158 needed_update = True
borlanic 0:02dd72d1d465 1159 self.progress("elf2bin", name)
borlanic 0:02dd72d1d465 1160 self.binary(r, elf, bin)
borlanic 0:02dd72d1d465 1161
borlanic 0:02dd72d1d465 1162 # Initialize memap and process map file. This doesn't generate output.
borlanic 0:02dd72d1d465 1163 self.mem_stats(map)
borlanic 0:02dd72d1d465 1164
borlanic 0:02dd72d1d465 1165 self.var("compile_succeded", True)
borlanic 0:02dd72d1d465 1166 self.var("binary", filename)
borlanic 0:02dd72d1d465 1167
borlanic 0:02dd72d1d465 1168 return full_path, needed_update
borlanic 0:02dd72d1d465 1169
borlanic 0:02dd72d1d465 1170 # THIS METHOD IS BEING OVERRIDDEN BY THE MBED ONLINE BUILD SYSTEM
borlanic 0:02dd72d1d465 1171 # ANY CHANGE OF PARAMETERS OR RETURN VALUES WILL BREAK COMPATIBILITY
borlanic 0:02dd72d1d465 1172 def default_cmd(self, command):
borlanic 0:02dd72d1d465 1173 _stdout, _stderr, _rc = run_cmd(command, work_dir=getcwd(), chroot=self.CHROOT)
borlanic 0:02dd72d1d465 1174 self.debug("Return: %s"% _rc)
borlanic 0:02dd72d1d465 1175
borlanic 0:02dd72d1d465 1176 for output_line in _stdout.splitlines():
borlanic 0:02dd72d1d465 1177 self.debug("Output: %s"% output_line)
borlanic 0:02dd72d1d465 1178 for error_line in _stderr.splitlines():
borlanic 0:02dd72d1d465 1179 self.debug("Errors: %s"% error_line)
borlanic 0:02dd72d1d465 1180
borlanic 0:02dd72d1d465 1181 if _rc != 0:
borlanic 0:02dd72d1d465 1182 for line in _stderr.splitlines():
borlanic 0:02dd72d1d465 1183 self.tool_error(line)
borlanic 0:02dd72d1d465 1184 raise ToolException(_stderr)
borlanic 0:02dd72d1d465 1185
borlanic 0:02dd72d1d465 1186 ### NOTIFICATIONS ###
borlanic 0:02dd72d1d465 1187 def info(self, message):
borlanic 0:02dd72d1d465 1188 self.notify({'type': 'info', 'message': message})
borlanic 0:02dd72d1d465 1189
borlanic 0:02dd72d1d465 1190 # THIS METHOD IS BEING OVERRIDDEN BY THE MBED ONLINE BUILD SYSTEM
borlanic 0:02dd72d1d465 1191 # ANY CHANGE OF PARAMETERS OR RETURN VALUES WILL BREAK COMPATIBILITY
borlanic 0:02dd72d1d465 1192 def debug(self, message):
borlanic 0:02dd72d1d465 1193 if self.VERBOSE:
borlanic 0:02dd72d1d465 1194 if isinstance(message, list):
borlanic 0:02dd72d1d465 1195 message = ' '.join(message)
borlanic 0:02dd72d1d465 1196 message = "[DEBUG] " + message
borlanic 0:02dd72d1d465 1197 self.notify({'type': 'debug', 'message': message})
borlanic 0:02dd72d1d465 1198
borlanic 0:02dd72d1d465 1199 # THIS METHOD IS BEING OVERRIDDEN BY THE MBED ONLINE BUILD SYSTEM
borlanic 0:02dd72d1d465 1200 # ANY CHANGE OF PARAMETERS OR RETURN VALUES WILL BREAK COMPATIBILITY
borlanic 0:02dd72d1d465 1201 def cc_info(self, info=None):
borlanic 0:02dd72d1d465 1202 if info is not None:
borlanic 0:02dd72d1d465 1203 info['type'] = 'cc'
borlanic 0:02dd72d1d465 1204 self.notify(info)
borlanic 0:02dd72d1d465 1205
borlanic 0:02dd72d1d465 1206 # THIS METHOD IS BEING OVERRIDDEN BY THE MBED ONLINE BUILD SYSTEM
borlanic 0:02dd72d1d465 1207 # ANY CHANGE OF PARAMETERS OR RETURN VALUES WILL BREAK COMPATIBILITY
borlanic 0:02dd72d1d465 1208 def cc_verbose(self, message, file=""):
borlanic 0:02dd72d1d465 1209 self.debug(message)
borlanic 0:02dd72d1d465 1210
borlanic 0:02dd72d1d465 1211 def progress(self, action, file, build_update=False):
borlanic 0:02dd72d1d465 1212 msg = {'type': 'progress', 'action': action, 'file': file}
borlanic 0:02dd72d1d465 1213 if build_update:
borlanic 0:02dd72d1d465 1214 msg['percent'] = 100. * float(self.compiled) / float(self.to_be_compiled)
borlanic 0:02dd72d1d465 1215 self.notify(msg)
borlanic 0:02dd72d1d465 1216
borlanic 0:02dd72d1d465 1217 def tool_error(self, message):
borlanic 0:02dd72d1d465 1218 self.notify({'type': 'tool_error', 'message': message})
borlanic 0:02dd72d1d465 1219
borlanic 0:02dd72d1d465 1220 def var(self, key, value):
borlanic 0:02dd72d1d465 1221 self.notify({'type': 'var', 'key': key, 'val': value})
borlanic 0:02dd72d1d465 1222
borlanic 0:02dd72d1d465 1223 # THIS METHOD IS BEING OVERRIDDEN BY THE MBED ONLINE BUILD SYSTEM
borlanic 0:02dd72d1d465 1224 # ANY CHANGE OF PARAMETERS OR RETURN VALUES WILL BREAK COMPATIBILITY
borlanic 0:02dd72d1d465 1225 def mem_stats(self, map):
borlanic 0:02dd72d1d465 1226 """! Creates parser object
borlanic 0:02dd72d1d465 1227 @param map Path to linker map file to parse and decode
borlanic 0:02dd72d1d465 1228 @return None
borlanic 0:02dd72d1d465 1229 """
borlanic 0:02dd72d1d465 1230 toolchain = self.__class__.__name__
borlanic 0:02dd72d1d465 1231
borlanic 0:02dd72d1d465 1232 # Create memap object
borlanic 0:02dd72d1d465 1233 memap = MemapParser()
borlanic 0:02dd72d1d465 1234
borlanic 0:02dd72d1d465 1235 # Parse and decode a map file
borlanic 0:02dd72d1d465 1236 if memap.parse(abspath(map), toolchain) is False:
borlanic 0:02dd72d1d465 1237 self.info("Unknown toolchain for memory statistics %s" % toolchain)
borlanic 0:02dd72d1d465 1238 return None
borlanic 0:02dd72d1d465 1239
borlanic 0:02dd72d1d465 1240 # Store the memap instance for later use
borlanic 0:02dd72d1d465 1241 self.memap_instance = memap
borlanic 0:02dd72d1d465 1242
borlanic 0:02dd72d1d465 1243 # Note: memory statistics are not returned.
borlanic 0:02dd72d1d465 1244 # Need call to generate_output later (depends on depth & output format)
borlanic 0:02dd72d1d465 1245
borlanic 0:02dd72d1d465 1246 return None
borlanic 0:02dd72d1d465 1247
borlanic 0:02dd72d1d465 1248 def add_regions(self):
borlanic 0:02dd72d1d465 1249 """Add regions to the build profile, if there are any.
borlanic 0:02dd72d1d465 1250 """
borlanic 0:02dd72d1d465 1251 print("Using regions in this build:")
borlanic 0:02dd72d1d465 1252 for region in self.config.regions:
borlanic 0:02dd72d1d465 1253 for define in [(region.name.upper() + "_ADDR", region.start),
borlanic 0:02dd72d1d465 1254 (region.name.upper() + "_SIZE", region.size)]:
borlanic 0:02dd72d1d465 1255 define_string = "-D%s=0x%x" % define
borlanic 0:02dd72d1d465 1256 self.cc.append(define_string)
borlanic 0:02dd72d1d465 1257 self.cppc.append(define_string)
borlanic 0:02dd72d1d465 1258 self.flags["common"].append(define_string)
borlanic 0:02dd72d1d465 1259 if region.active:
borlanic 0:02dd72d1d465 1260 for define in [("MBED_APP_START", region.start),
borlanic 0:02dd72d1d465 1261 ("MBED_APP_SIZE", region.size)]:
borlanic 0:02dd72d1d465 1262 define_string = self.make_ld_define(*define)
borlanic 0:02dd72d1d465 1263 self.ld.append(define_string)
borlanic 0:02dd72d1d465 1264 self.flags["ld"].append(define_string)
borlanic 0:02dd72d1d465 1265 print(" Region %s size 0x%x, offset 0x%x"
borlanic 0:02dd72d1d465 1266 % (region.name, region.size, region.start))
borlanic 0:02dd72d1d465 1267
borlanic 0:02dd72d1d465 1268 # Set the configuration data
borlanic 0:02dd72d1d465 1269 def set_config_data(self, config_data):
borlanic 0:02dd72d1d465 1270 self.config_data = config_data
borlanic 0:02dd72d1d465 1271 if self.config.has_regions:
borlanic 0:02dd72d1d465 1272 self.add_regions()
borlanic 0:02dd72d1d465 1273
borlanic 0:02dd72d1d465 1274 # Creates the configuration header if needed:
borlanic 0:02dd72d1d465 1275 # - if there is no configuration data, "mbed_config.h" is not create (or deleted if it exists).
borlanic 0:02dd72d1d465 1276 # - if there is configuration data and "mbed_config.h" does not exist, it is created.
borlanic 0:02dd72d1d465 1277 # - if there is configuration data similar to the previous configuration data,
borlanic 0:02dd72d1d465 1278 # "mbed_config.h" is left untouched.
borlanic 0:02dd72d1d465 1279 # - if there is new configuration data, "mbed_config.h" is overriden.
borlanic 0:02dd72d1d465 1280 # The function needs to be called exactly once for the lifetime of this toolchain instance.
borlanic 0:02dd72d1d465 1281 # The "config_processed" variable (below) ensures this behaviour.
borlanic 0:02dd72d1d465 1282 # The function returns the location of the configuration file, or None if there is no
borlanic 0:02dd72d1d465 1283 # configuration data available (and thus no configuration file)
borlanic 0:02dd72d1d465 1284 def get_config_header(self):
borlanic 0:02dd72d1d465 1285 if self.config_processed: # this function was already called, return its result
borlanic 0:02dd72d1d465 1286 return self.config_file
borlanic 0:02dd72d1d465 1287 # The config file is located in the build directory
borlanic 0:02dd72d1d465 1288 self.config_file = join(self.build_dir, self.MBED_CONFIG_FILE_NAME)
borlanic 0:02dd72d1d465 1289 # If the file exists, read its current content in prev_data
borlanic 0:02dd72d1d465 1290 if exists(self.config_file):
borlanic 0:02dd72d1d465 1291 with open(self.config_file, "r") as f:
borlanic 0:02dd72d1d465 1292 prev_data = f.read()
borlanic 0:02dd72d1d465 1293 else:
borlanic 0:02dd72d1d465 1294 prev_data = None
borlanic 0:02dd72d1d465 1295 # Get the current configuration data
borlanic 0:02dd72d1d465 1296 crt_data = self.config.config_to_header(self.config_data) if self.config_data else None
borlanic 0:02dd72d1d465 1297 # "changed" indicates if a configuration change was detected
borlanic 0:02dd72d1d465 1298 changed = False
borlanic 0:02dd72d1d465 1299 if prev_data is not None: # a previous mbed_config.h exists
borlanic 0:02dd72d1d465 1300 if crt_data is None: # no configuration data, so "mbed_config.h" needs to be removed
borlanic 0:02dd72d1d465 1301 remove(self.config_file)
borlanic 0:02dd72d1d465 1302 self.config_file = None # this means "config file not present"
borlanic 0:02dd72d1d465 1303 changed = True
borlanic 0:02dd72d1d465 1304 elif crt_data != prev_data: # different content of config file
borlanic 0:02dd72d1d465 1305 with open(self.config_file, "w") as f:
borlanic 0:02dd72d1d465 1306 f.write(crt_data)
borlanic 0:02dd72d1d465 1307 changed = True
borlanic 0:02dd72d1d465 1308 else: # a previous mbed_config.h does not exist
borlanic 0:02dd72d1d465 1309 if crt_data is not None: # there's configuration data available
borlanic 0:02dd72d1d465 1310 with open(self.config_file, "w") as f:
borlanic 0:02dd72d1d465 1311 f.write(crt_data)
borlanic 0:02dd72d1d465 1312 changed = True
borlanic 0:02dd72d1d465 1313 else:
borlanic 0:02dd72d1d465 1314 self.config_file = None # this means "config file not present"
borlanic 0:02dd72d1d465 1315 # If there was a change in configuration, rebuild everything
borlanic 0:02dd72d1d465 1316 self.build_all = changed
borlanic 0:02dd72d1d465 1317 # Make sure that this function will only return the location of the configuration
borlanic 0:02dd72d1d465 1318 # file for subsequent calls, without trying to manipulate its content in any way.
borlanic 0:02dd72d1d465 1319 self.config_processed = True
borlanic 0:02dd72d1d465 1320 return self.config_file
borlanic 0:02dd72d1d465 1321
borlanic 0:02dd72d1d465 1322 def dump_build_profile(self):
borlanic 0:02dd72d1d465 1323 """Dump the current build profile and macros into the `.profile` file
borlanic 0:02dd72d1d465 1324 in the build directory"""
borlanic 0:02dd72d1d465 1325 for key in ["cxx", "c", "asm", "ld"]:
borlanic 0:02dd72d1d465 1326 to_dump = (str(self.flags[key]) + str(sorted(self.macros)))
borlanic 0:02dd72d1d465 1327 if key in ["cxx", "c"]:
borlanic 0:02dd72d1d465 1328 to_dump += str(self.flags['common'])
borlanic 0:02dd72d1d465 1329 where = join(self.build_dir, self.PROFILE_FILE_NAME + "-" + key)
borlanic 0:02dd72d1d465 1330 self._overwrite_when_not_equal(where, to_dump)
borlanic 0:02dd72d1d465 1331
borlanic 0:02dd72d1d465 1332 @staticmethod
borlanic 0:02dd72d1d465 1333 def _overwrite_when_not_equal(filename, content):
borlanic 0:02dd72d1d465 1334 if not exists(filename) or content != open(filename).read():
borlanic 0:02dd72d1d465 1335 with open(filename, "w") as out:
borlanic 0:02dd72d1d465 1336 out.write(content)
borlanic 0:02dd72d1d465 1337
borlanic 0:02dd72d1d465 1338 @staticmethod
borlanic 0:02dd72d1d465 1339 def generic_check_executable(tool_key, executable_name, levels_up,
borlanic 0:02dd72d1d465 1340 nested_dir=None):
borlanic 0:02dd72d1d465 1341 """
borlanic 0:02dd72d1d465 1342 Positional args:
borlanic 0:02dd72d1d465 1343 tool_key: the key to index TOOLCHAIN_PATHS
borlanic 0:02dd72d1d465 1344 executable_name: the toolchain's named executable (ex. armcc)
borlanic 0:02dd72d1d465 1345 levels_up: each toolchain joins the toolchain_path, some
borlanic 0:02dd72d1d465 1346 variable directories (bin, include), and the executable name,
borlanic 0:02dd72d1d465 1347 so the TOOLCHAIN_PATH value must be appropriately distanced
borlanic 0:02dd72d1d465 1348
borlanic 0:02dd72d1d465 1349 Keyword args:
borlanic 0:02dd72d1d465 1350 nested_dir: the directory within TOOLCHAIN_PATHS where the executable
borlanic 0:02dd72d1d465 1351 is found (ex: 'bin' for ARM\bin\armcc (necessary to check for path
borlanic 0:02dd72d1d465 1352 that will be used by toolchain's compile)
borlanic 0:02dd72d1d465 1353
borlanic 0:02dd72d1d465 1354 Returns True if the executable location specified by the user
borlanic 0:02dd72d1d465 1355 exists and is valid OR the executable can be found on the PATH.
borlanic 0:02dd72d1d465 1356 Returns False otherwise.
borlanic 0:02dd72d1d465 1357 """
borlanic 0:02dd72d1d465 1358 # Search PATH if user did not specify a path or specified path doesn't
borlanic 0:02dd72d1d465 1359 # exist.
borlanic 0:02dd72d1d465 1360 if not TOOLCHAIN_PATHS[tool_key] or not exists(TOOLCHAIN_PATHS[tool_key]):
borlanic 0:02dd72d1d465 1361 exe = find_executable(executable_name)
borlanic 0:02dd72d1d465 1362 if not exe:
borlanic 0:02dd72d1d465 1363 return False
borlanic 0:02dd72d1d465 1364 for level in range(levels_up):
borlanic 0:02dd72d1d465 1365 # move up the specified number of directories
borlanic 0:02dd72d1d465 1366 exe = dirname(exe)
borlanic 0:02dd72d1d465 1367 TOOLCHAIN_PATHS[tool_key] = exe
borlanic 0:02dd72d1d465 1368 if nested_dir:
borlanic 0:02dd72d1d465 1369 subdir = join(TOOLCHAIN_PATHS[tool_key], nested_dir,
borlanic 0:02dd72d1d465 1370 executable_name)
borlanic 0:02dd72d1d465 1371 else:
borlanic 0:02dd72d1d465 1372 subdir = join(TOOLCHAIN_PATHS[tool_key],executable_name)
borlanic 0:02dd72d1d465 1373 # User could have specified a path that exists but does not contain exe
borlanic 0:02dd72d1d465 1374 return exists(subdir) or exists(subdir +'.exe')
borlanic 0:02dd72d1d465 1375
borlanic 0:02dd72d1d465 1376 @abstractmethod
borlanic 0:02dd72d1d465 1377 def check_executable(self):
borlanic 0:02dd72d1d465 1378 """Returns True if the executable (armcc) location specified by the
borlanic 0:02dd72d1d465 1379 user exists OR the executable can be found on the PATH.
borlanic 0:02dd72d1d465 1380 Returns False otherwise."""
borlanic 0:02dd72d1d465 1381 raise NotImplemented
borlanic 0:02dd72d1d465 1382
borlanic 0:02dd72d1d465 1383 @abstractmethod
borlanic 0:02dd72d1d465 1384 def get_config_option(self, config_header):
borlanic 0:02dd72d1d465 1385 """Generate the compiler option that forces the inclusion of the configuration
borlanic 0:02dd72d1d465 1386 header file.
borlanic 0:02dd72d1d465 1387
borlanic 0:02dd72d1d465 1388 Positional arguments:
borlanic 0:02dd72d1d465 1389 config_header -- The configuration header that will be included within all source files
borlanic 0:02dd72d1d465 1390
borlanic 0:02dd72d1d465 1391 Return value:
borlanic 0:02dd72d1d465 1392 A list of the command line arguments that will force the inclusion the specified header
borlanic 0:02dd72d1d465 1393
borlanic 0:02dd72d1d465 1394 Side effects:
borlanic 0:02dd72d1d465 1395 None
borlanic 0:02dd72d1d465 1396 """
borlanic 0:02dd72d1d465 1397 raise NotImplemented
borlanic 0:02dd72d1d465 1398
borlanic 0:02dd72d1d465 1399 @abstractmethod
borlanic 0:02dd72d1d465 1400 def get_compile_options(self, defines, includes, for_asm=False):
borlanic 0:02dd72d1d465 1401 """Generate the compiler options from the defines and includes
borlanic 0:02dd72d1d465 1402
borlanic 0:02dd72d1d465 1403 Positional arguments:
borlanic 0:02dd72d1d465 1404 defines -- The preprocessor macros defined on the command line
borlanic 0:02dd72d1d465 1405 includes -- The include file search paths
borlanic 0:02dd72d1d465 1406
borlanic 0:02dd72d1d465 1407 Keyword arguments:
borlanic 0:02dd72d1d465 1408 for_asm -- generate the assembler options instead of the compiler options
borlanic 0:02dd72d1d465 1409
borlanic 0:02dd72d1d465 1410 Return value:
borlanic 0:02dd72d1d465 1411 A list of the command line arguments that will force the inclusion the specified header
borlanic 0:02dd72d1d465 1412
borlanic 0:02dd72d1d465 1413 Side effects:
borlanic 0:02dd72d1d465 1414 None
borlanic 0:02dd72d1d465 1415 """
borlanic 0:02dd72d1d465 1416 raise NotImplemented
borlanic 0:02dd72d1d465 1417
borlanic 0:02dd72d1d465 1418 @abstractmethod
borlanic 0:02dd72d1d465 1419 def assemble(self, source, object, includes):
borlanic 0:02dd72d1d465 1420 """Generate the command line that assembles.
borlanic 0:02dd72d1d465 1421
borlanic 0:02dd72d1d465 1422 Positional arguments:
borlanic 0:02dd72d1d465 1423 source -- a file path that is the file to assemble
borlanic 0:02dd72d1d465 1424 object -- a file path that is the destination object
borlanic 0:02dd72d1d465 1425 includes -- a list of all directories where header files may be found
borlanic 0:02dd72d1d465 1426
borlanic 0:02dd72d1d465 1427 Return value:
borlanic 0:02dd72d1d465 1428 The complete command line, as a list, that would invoke the assembler
borlanic 0:02dd72d1d465 1429 on the source file, include all the include paths, and generate
borlanic 0:02dd72d1d465 1430 the specified object file.
borlanic 0:02dd72d1d465 1431
borlanic 0:02dd72d1d465 1432 Side effects:
borlanic 0:02dd72d1d465 1433 None
borlanic 0:02dd72d1d465 1434
borlanic 0:02dd72d1d465 1435 Note:
borlanic 0:02dd72d1d465 1436 This method should be decorated with @hook_tool.
borlanic 0:02dd72d1d465 1437 """
borlanic 0:02dd72d1d465 1438 raise NotImplemented
borlanic 0:02dd72d1d465 1439
borlanic 0:02dd72d1d465 1440 @abstractmethod
borlanic 0:02dd72d1d465 1441 def compile_c(self, source, object, includes):
borlanic 0:02dd72d1d465 1442 """Generate the command line that compiles a C source file.
borlanic 0:02dd72d1d465 1443
borlanic 0:02dd72d1d465 1444 Positional arguments:
borlanic 0:02dd72d1d465 1445 source -- the C source file to compile
borlanic 0:02dd72d1d465 1446 object -- the destination object file
borlanic 0:02dd72d1d465 1447 includes -- a list of all the directories where header files may be found
borlanic 0:02dd72d1d465 1448
borlanic 0:02dd72d1d465 1449 Return value:
borlanic 0:02dd72d1d465 1450 The complete command line, as a list, that would invoke the C compiler
borlanic 0:02dd72d1d465 1451 on the source file, include all the include paths, and generate the
borlanic 0:02dd72d1d465 1452 specified object file.
borlanic 0:02dd72d1d465 1453
borlanic 0:02dd72d1d465 1454 Side effects:
borlanic 0:02dd72d1d465 1455 None
borlanic 0:02dd72d1d465 1456
borlanic 0:02dd72d1d465 1457 Note:
borlanic 0:02dd72d1d465 1458 This method should be decorated with @hook_tool.
borlanic 0:02dd72d1d465 1459 """
borlanic 0:02dd72d1d465 1460 raise NotImplemented
borlanic 0:02dd72d1d465 1461
borlanic 0:02dd72d1d465 1462 @abstractmethod
borlanic 0:02dd72d1d465 1463 def compile_cpp(self, source, object, includes):
borlanic 0:02dd72d1d465 1464 """Generate the command line that compiles a C++ source file.
borlanic 0:02dd72d1d465 1465
borlanic 0:02dd72d1d465 1466 Positional arguments:
borlanic 0:02dd72d1d465 1467 source -- the C++ source file to compile
borlanic 0:02dd72d1d465 1468 object -- the destination object file
borlanic 0:02dd72d1d465 1469 includes -- a list of all the directories where header files may be found
borlanic 0:02dd72d1d465 1470
borlanic 0:02dd72d1d465 1471 Return value:
borlanic 0:02dd72d1d465 1472 The complete command line, as a list, that would invoke the C++ compiler
borlanic 0:02dd72d1d465 1473 on the source file, include all the include paths, and generate the
borlanic 0:02dd72d1d465 1474 specified object file.
borlanic 0:02dd72d1d465 1475
borlanic 0:02dd72d1d465 1476 Side effects:
borlanic 0:02dd72d1d465 1477 None
borlanic 0:02dd72d1d465 1478
borlanic 0:02dd72d1d465 1479 Note:
borlanic 0:02dd72d1d465 1480 This method should be decorated with @hook_tool.
borlanic 0:02dd72d1d465 1481 """
borlanic 0:02dd72d1d465 1482 raise NotImplemented
borlanic 0:02dd72d1d465 1483
borlanic 0:02dd72d1d465 1484 @abstractmethod
borlanic 0:02dd72d1d465 1485 def link(self, output, objects, libraries, lib_dirs, mem_map):
borlanic 0:02dd72d1d465 1486 """Run the linker to create an executable and memory map.
borlanic 0:02dd72d1d465 1487
borlanic 0:02dd72d1d465 1488 Positional arguments:
borlanic 0:02dd72d1d465 1489 output -- the file name to place the executable in
borlanic 0:02dd72d1d465 1490 objects -- all of the object files to link
borlanic 0:02dd72d1d465 1491 libraries -- all of the required libraries
borlanic 0:02dd72d1d465 1492 lib_dirs -- where the required libraries are located
borlanic 0:02dd72d1d465 1493 mem_map -- the location where the memory map file should be stored
borlanic 0:02dd72d1d465 1494
borlanic 0:02dd72d1d465 1495 Return value:
borlanic 0:02dd72d1d465 1496 None
borlanic 0:02dd72d1d465 1497
borlanic 0:02dd72d1d465 1498 Side effect:
borlanic 0:02dd72d1d465 1499 Runs the linker to produce the executable.
borlanic 0:02dd72d1d465 1500
borlanic 0:02dd72d1d465 1501 Note:
borlanic 0:02dd72d1d465 1502 This method should be decorated with @hook_tool.
borlanic 0:02dd72d1d465 1503 """
borlanic 0:02dd72d1d465 1504 raise NotImplemented
borlanic 0:02dd72d1d465 1505
borlanic 0:02dd72d1d465 1506 @abstractmethod
borlanic 0:02dd72d1d465 1507 def archive(self, objects, lib_path):
borlanic 0:02dd72d1d465 1508 """Run the command line that creates an archive.
borlanic 0:02dd72d1d465 1509
borlanic 0:02dd72d1d465 1510 Positional arguhments:
borlanic 0:02dd72d1d465 1511 objects -- a list of all the object files that should be archived
borlanic 0:02dd72d1d465 1512 lib_path -- the file name of the resulting library file
borlanic 0:02dd72d1d465 1513
borlanic 0:02dd72d1d465 1514 Return value:
borlanic 0:02dd72d1d465 1515 None
borlanic 0:02dd72d1d465 1516
borlanic 0:02dd72d1d465 1517 Side effect:
borlanic 0:02dd72d1d465 1518 Runs the archiving tool to produce the library file.
borlanic 0:02dd72d1d465 1519
borlanic 0:02dd72d1d465 1520 Note:
borlanic 0:02dd72d1d465 1521 This method should be decorated with @hook_tool.
borlanic 0:02dd72d1d465 1522 """
borlanic 0:02dd72d1d465 1523 raise NotImplemented
borlanic 0:02dd72d1d465 1524
borlanic 0:02dd72d1d465 1525 @abstractmethod
borlanic 0:02dd72d1d465 1526 def binary(self, resources, elf, bin):
borlanic 0:02dd72d1d465 1527 """Run the command line that will Extract a simplified binary file.
borlanic 0:02dd72d1d465 1528
borlanic 0:02dd72d1d465 1529 Positional arguments:
borlanic 0:02dd72d1d465 1530 resources -- A resources object (Is not used in any of the toolchains)
borlanic 0:02dd72d1d465 1531 elf -- the executable file that is to be converted
borlanic 0:02dd72d1d465 1532 bin -- the file name of the to be created simplified binary file
borlanic 0:02dd72d1d465 1533
borlanic 0:02dd72d1d465 1534 Return value:
borlanic 0:02dd72d1d465 1535 None
borlanic 0:02dd72d1d465 1536
borlanic 0:02dd72d1d465 1537 Side effect:
borlanic 0:02dd72d1d465 1538 Runs the elf2bin tool to produce the simplified binary file.
borlanic 0:02dd72d1d465 1539
borlanic 0:02dd72d1d465 1540 Note:
borlanic 0:02dd72d1d465 1541 This method should be decorated with @hook_tool.
borlanic 0:02dd72d1d465 1542 """
borlanic 0:02dd72d1d465 1543 raise NotImplemented
borlanic 0:02dd72d1d465 1544
borlanic 0:02dd72d1d465 1545 @staticmethod
borlanic 0:02dd72d1d465 1546 @abstractmethod
borlanic 0:02dd72d1d465 1547 def name_mangle(name):
borlanic 0:02dd72d1d465 1548 """Mangle a name based on the conventional name mangling of this toolchain
borlanic 0:02dd72d1d465 1549
borlanic 0:02dd72d1d465 1550 Positional arguments:
borlanic 0:02dd72d1d465 1551 name -- the name to mangle
borlanic 0:02dd72d1d465 1552
borlanic 0:02dd72d1d465 1553 Return:
borlanic 0:02dd72d1d465 1554 the mangled name as a string
borlanic 0:02dd72d1d465 1555 """
borlanic 0:02dd72d1d465 1556 raise NotImplemented
borlanic 0:02dd72d1d465 1557
borlanic 0:02dd72d1d465 1558 @staticmethod
borlanic 0:02dd72d1d465 1559 @abstractmethod
borlanic 0:02dd72d1d465 1560 def make_ld_define(name, value):
borlanic 0:02dd72d1d465 1561 """Create an argument to the linker that would define a symbol
borlanic 0:02dd72d1d465 1562
borlanic 0:02dd72d1d465 1563 Positional arguments:
borlanic 0:02dd72d1d465 1564 name -- the symbol to define
borlanic 0:02dd72d1d465 1565 value -- the value to give the symbol
borlanic 0:02dd72d1d465 1566
borlanic 0:02dd72d1d465 1567 Return:
borlanic 0:02dd72d1d465 1568 The linker flag as a string
borlanic 0:02dd72d1d465 1569 """
borlanic 0:02dd72d1d465 1570 raise NotImplemented
borlanic 0:02dd72d1d465 1571
borlanic 0:02dd72d1d465 1572 @staticmethod
borlanic 0:02dd72d1d465 1573 @abstractmethod
borlanic 0:02dd72d1d465 1574 def redirect_symbol(source, sync, build_dir):
borlanic 0:02dd72d1d465 1575 """Redirect a symbol at link time to point at somewhere else
borlanic 0:02dd72d1d465 1576
borlanic 0:02dd72d1d465 1577 Positional arguments:
borlanic 0:02dd72d1d465 1578 source -- the symbol doing the pointing
borlanic 0:02dd72d1d465 1579 sync -- the symbol being pointed to
borlanic 0:02dd72d1d465 1580 build_dir -- the directory to put "response files" if needed by the toolchain
borlanic 0:02dd72d1d465 1581
borlanic 0:02dd72d1d465 1582 Side Effects:
borlanic 0:02dd72d1d465 1583 Possibly create a file in the build directory
borlanic 0:02dd72d1d465 1584
borlanic 0:02dd72d1d465 1585 Return:
borlanic 0:02dd72d1d465 1586 The linker flag to redirect the symbol, as a string
borlanic 0:02dd72d1d465 1587 """
borlanic 0:02dd72d1d465 1588 raise NotImplemented
borlanic 0:02dd72d1d465 1589
borlanic 0:02dd72d1d465 1590 # Return the list of macros geenrated by the build system
borlanic 0:02dd72d1d465 1591 def get_config_macros(self):
borlanic 0:02dd72d1d465 1592 return self.config.config_to_macros(self.config_data) if self.config_data else []
borlanic 0:02dd72d1d465 1593
borlanic 0:02dd72d1d465 1594 @property
borlanic 0:02dd72d1d465 1595 def report(self):
borlanic 0:02dd72d1d465 1596 to_ret = {}
borlanic 0:02dd72d1d465 1597 to_ret['c_compiler'] = {'flags': copy(self.flags['c']),
borlanic 0:02dd72d1d465 1598 'symbols': self.get_symbols()}
borlanic 0:02dd72d1d465 1599 to_ret['cxx_compiler'] = {'flags': copy(self.flags['cxx']),
borlanic 0:02dd72d1d465 1600 'symbols': self.get_symbols()}
borlanic 0:02dd72d1d465 1601 to_ret['assembler'] = {'flags': copy(self.flags['asm']),
borlanic 0:02dd72d1d465 1602 'symbols': self.get_symbols(True)}
borlanic 0:02dd72d1d465 1603 to_ret['linker'] = {'flags': copy(self.flags['ld'])}
borlanic 0:02dd72d1d465 1604 to_ret.update(self.config.report)
borlanic 0:02dd72d1d465 1605 return to_ret
borlanic 0:02dd72d1d465 1606
borlanic 0:02dd72d1d465 1607 from tools.settings import ARM_PATH, ARMC6_PATH, GCC_ARM_PATH, IAR_PATH
borlanic 0:02dd72d1d465 1608
borlanic 0:02dd72d1d465 1609 TOOLCHAIN_PATHS = {
borlanic 0:02dd72d1d465 1610 'ARM': ARM_PATH,
borlanic 0:02dd72d1d465 1611 'uARM': ARM_PATH,
borlanic 0:02dd72d1d465 1612 'ARMC6': ARMC6_PATH,
borlanic 0:02dd72d1d465 1613 'GCC_ARM': GCC_ARM_PATH,
borlanic 0:02dd72d1d465 1614 'IAR': IAR_PATH
borlanic 0:02dd72d1d465 1615 }
borlanic 0:02dd72d1d465 1616
borlanic 0:02dd72d1d465 1617 from tools.toolchains.arm import ARM_STD, ARM_MICRO, ARMC6
borlanic 0:02dd72d1d465 1618 from tools.toolchains.gcc import GCC_ARM
borlanic 0:02dd72d1d465 1619 from tools.toolchains.iar import IAR
borlanic 0:02dd72d1d465 1620
borlanic 0:02dd72d1d465 1621 TOOLCHAIN_CLASSES = {
borlanic 0:02dd72d1d465 1622 u'ARM': ARM_STD,
borlanic 0:02dd72d1d465 1623 u'uARM': ARM_MICRO,
borlanic 0:02dd72d1d465 1624 u'ARMC6': ARMC6,
borlanic 0:02dd72d1d465 1625 u'GCC_ARM': GCC_ARM,
borlanic 0:02dd72d1d465 1626 u'IAR': IAR
borlanic 0:02dd72d1d465 1627 }
borlanic 0:02dd72d1d465 1628
borlanic 0:02dd72d1d465 1629 TOOLCHAINS = set(TOOLCHAIN_CLASSES.keys())