Clone of official tools

Committer:
screamer
Date:
Sat Jul 16 00:34:03 2016 +0100
Revision:
22:9e85236d8716
Parent:
17:04753e1e329d
Child:
24:25bff2709c20
Sync with the mbedmicro/mbed tools

Who changed what in which revision?

UserRevisionLine numberNew contents of line
screamer 0:66f3b5499f7f 1 """
screamer 0:66f3b5499f7f 2 mbed SDK
screamer 0:66f3b5499f7f 3 Copyright (c) 2011-2013 ARM Limited
screamer 0:66f3b5499f7f 4
screamer 0:66f3b5499f7f 5 Licensed under the Apache License, Version 2.0 (the "License");
screamer 0:66f3b5499f7f 6 you may not use this file except in compliance with the License.
screamer 0:66f3b5499f7f 7 You may obtain a copy of the License at
screamer 0:66f3b5499f7f 8
screamer 0:66f3b5499f7f 9 http://www.apache.org/licenses/LICENSE-2.0
screamer 0:66f3b5499f7f 10
screamer 0:66f3b5499f7f 11 Unless required by applicable law or agreed to in writing, software
screamer 0:66f3b5499f7f 12 distributed under the License is distributed on an "AS IS" BASIS,
screamer 0:66f3b5499f7f 13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
screamer 0:66f3b5499f7f 14 See the License for the specific language governing permissions and
screamer 0:66f3b5499f7f 15 limitations under the License.
screamer 0:66f3b5499f7f 16 """
screamer 0:66f3b5499f7f 17
screamer 0:66f3b5499f7f 18 import re
screamer 0:66f3b5499f7f 19 import tempfile
screamer 0:66f3b5499f7f 20 import colorama
screamer 0:66f3b5499f7f 21
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 22 from copy import copy
screamer 0:66f3b5499f7f 23 from types import ListType
screamer 0:66f3b5499f7f 24 from shutil import rmtree
screamer 7:5af61d55adbe 25 from os.path import join, exists, basename, abspath, normpath
screamer 8:a8ac6ed29081 26 from os import getcwd, walk
screamer 0:66f3b5499f7f 27 from time import time
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 28 import fnmatch
screamer 0:66f3b5499f7f 29
screamer 7:5af61d55adbe 30 from tools.utils import mkdir, run_cmd, run_cmd_ext, NotSupportedException, ToolException
screamer 0:66f3b5499f7f 31 from tools.paths import MBED_TARGETS_PATH, MBED_LIBRARIES, MBED_API, MBED_HAL, MBED_COMMON
screamer 0:66f3b5499f7f 32 from tools.targets import TARGET_NAMES, TARGET_MAP
screamer 0:66f3b5499f7f 33 from tools.libraries import Library
screamer 14:ee1b877e6839 34 from tools.toolchains import TOOLCHAIN_CLASSES, mbedToolchain
screamer 14:ee1b877e6839 35 from tools.build_profiles import find_build_profile, get_toolchain_profile
screamer 0:66f3b5499f7f 36 from jinja2 import FileSystemLoader
screamer 0:66f3b5499f7f 37 from jinja2.environment import Environment
screamer 7:5af61d55adbe 38 from tools.config import Config
screamer 0:66f3b5499f7f 39
screamer 0:66f3b5499f7f 40 def prep_report(report, target_name, toolchain_name, id_name):
screamer 0:66f3b5499f7f 41 # Setup report keys
screamer 0:66f3b5499f7f 42 if not target_name in report:
screamer 0:66f3b5499f7f 43 report[target_name] = {}
screamer 0:66f3b5499f7f 44
screamer 0:66f3b5499f7f 45 if not toolchain_name in report[target_name]:
screamer 0:66f3b5499f7f 46 report[target_name][toolchain_name] = {}
screamer 0:66f3b5499f7f 47
screamer 0:66f3b5499f7f 48 if not id_name in report[target_name][toolchain_name]:
screamer 0:66f3b5499f7f 49 report[target_name][toolchain_name][id_name] = []
screamer 0:66f3b5499f7f 50
screamer 0:66f3b5499f7f 51 def prep_properties(properties, target_name, toolchain_name, vendor_label):
screamer 0:66f3b5499f7f 52 # Setup test properties
screamer 0:66f3b5499f7f 53 if not target_name in properties:
screamer 0:66f3b5499f7f 54 properties[target_name] = {}
screamer 0:66f3b5499f7f 55
screamer 0:66f3b5499f7f 56 if not toolchain_name in properties[target_name]:
screamer 0:66f3b5499f7f 57 properties[target_name][toolchain_name] = {}
screamer 0:66f3b5499f7f 58
screamer 0:66f3b5499f7f 59 properties[target_name][toolchain_name]["target"] = target_name
screamer 0:66f3b5499f7f 60 properties[target_name][toolchain_name]["vendor"] = vendor_label
screamer 0:66f3b5499f7f 61 properties[target_name][toolchain_name]["toolchain"] = toolchain_name
screamer 0:66f3b5499f7f 62
screamer 0:66f3b5499f7f 63 def create_result(target_name, toolchain_name, id_name, description):
screamer 0:66f3b5499f7f 64 cur_result = {}
screamer 0:66f3b5499f7f 65 cur_result["target_name"] = target_name
screamer 0:66f3b5499f7f 66 cur_result["toolchain_name"] = toolchain_name
screamer 0:66f3b5499f7f 67 cur_result["id"] = id_name
screamer 0:66f3b5499f7f 68 cur_result["description"] = description
screamer 0:66f3b5499f7f 69 cur_result["elapsed_time"] = 0
screamer 0:66f3b5499f7f 70 cur_result["output"] = ""
screamer 0:66f3b5499f7f 71
screamer 0:66f3b5499f7f 72 return cur_result
screamer 0:66f3b5499f7f 73
screamer 0:66f3b5499f7f 74 def add_result_to_report(report, result):
screamer 0:66f3b5499f7f 75 target = result["target_name"]
screamer 0:66f3b5499f7f 76 toolchain = result["toolchain_name"]
screamer 0:66f3b5499f7f 77 id_name = result['id']
screamer 0:66f3b5499f7f 78 result_wrap = { 0: result }
screamer 0:66f3b5499f7f 79 report[target][toolchain][id_name].append(result_wrap)
screamer 0:66f3b5499f7f 80
screamer 7:5af61d55adbe 81 def get_config(src_path, target, toolchain_name):
screamer 7:5af61d55adbe 82 # Convert src_path to a list if needed
screamer 1:a99c8e460c5c 83 src_paths = [src_path] if type(src_path) != ListType else src_path
screamer 1:a99c8e460c5c 84 # We need to remove all paths which are repeated to avoid
screamer 1:a99c8e460c5c 85 # multiple compilations and linking with the same objects
screamer 1:a99c8e460c5c 86 src_paths = [src_paths[0]] + list(set(src_paths[1:]))
screamer 7:5af61d55adbe 87
screamer 7:5af61d55adbe 88 # Create configuration object
screamer 7:5af61d55adbe 89 config = Config(target, src_paths)
screamer 1:a99c8e460c5c 90
screamer 7:5af61d55adbe 91 # If the 'target' argument is a string, convert it to a target instance
screamer 13:ab47a20b66f0 92 if isinstance(target, basestring):
screamer 7:5af61d55adbe 93 try:
screamer 7:5af61d55adbe 94 target = TARGET_MAP[target]
screamer 7:5af61d55adbe 95 except KeyError:
screamer 7:5af61d55adbe 96 raise KeyError("Target '%s' not found" % target)
screamer 2:07730b0f452c 97
screamer 0:66f3b5499f7f 98 # Toolchain instance
screamer 0:66f3b5499f7f 99 try:
screamer 7:5af61d55adbe 100 toolchain = TOOLCHAIN_CLASSES[toolchain_name](target, options=None, notify=None, macros=None, silent=True, extra_verbose=False)
screamer 7:5af61d55adbe 101 except KeyError as e:
screamer 7:5af61d55adbe 102 raise KeyError("Toolchain %s not supported" % toolchain_name)
screamer 7:5af61d55adbe 103
screamer 7:5af61d55adbe 104 # Scan src_path for config files
screamer 7:5af61d55adbe 105 resources = toolchain.scan_resources(src_paths[0])
screamer 7:5af61d55adbe 106 for path in src_paths[1:]:
screamer 7:5af61d55adbe 107 resources.add(toolchain.scan_resources(path))
screamer 7:5af61d55adbe 108
screamer 13:ab47a20b66f0 109 # Update configuration files until added features creates no changes
screamer 13:ab47a20b66f0 110 prev_features = set()
screamer 13:ab47a20b66f0 111 while True:
screamer 13:ab47a20b66f0 112 # Update the configuration with any .json files found while scanning
screamer 13:ab47a20b66f0 113 config.add_config_files(resources.json_files)
screamer 13:ab47a20b66f0 114
screamer 13:ab47a20b66f0 115 # Add features while we find new ones
screamer 13:ab47a20b66f0 116 features = config.get_features()
screamer 13:ab47a20b66f0 117 if features == prev_features:
screamer 13:ab47a20b66f0 118 break
screamer 13:ab47a20b66f0 119
screamer 13:ab47a20b66f0 120 for feature in features:
screamer 13:ab47a20b66f0 121 if feature in resources.features:
screamer 13:ab47a20b66f0 122 resources += resources.features[feature]
screamer 13:ab47a20b66f0 123
screamer 13:ab47a20b66f0 124 prev_features = features
screamer 13:ab47a20b66f0 125 config.validate_config()
screamer 13:ab47a20b66f0 126
screamer 13:ab47a20b66f0 127 cfg, macros = config.get_config_data()
screamer 13:ab47a20b66f0 128 features = config.get_features()
screamer 13:ab47a20b66f0 129 return cfg, macros, features
screamer 7:5af61d55adbe 130
screamer 7:5af61d55adbe 131 def build_project(src_path, build_path, target, toolchain_name,
screamer 7:5af61d55adbe 132 libraries_paths=None, options=None, linker_script=None,
screamer 7:5af61d55adbe 133 clean=False, notify=None, verbose=False, name=None, macros=None, inc_dirs=None,
screamer 7:5af61d55adbe 134 jobs=1, silent=False, report=None, properties=None, project_id=None, project_description=None,
screamer 7:5af61d55adbe 135 extra_verbose=False, config=None):
screamer 7:5af61d55adbe 136 """ This function builds project. Project can be for example one test / UT
screamer 7:5af61d55adbe 137 """
screamer 7:5af61d55adbe 138
screamer 7:5af61d55adbe 139 # Convert src_path to a list if needed
screamer 7:5af61d55adbe 140 src_paths = [src_path] if type(src_path) != ListType else src_path
screamer 7:5af61d55adbe 141
screamer 7:5af61d55adbe 142 # We need to remove all paths which are repeated to avoid
screamer 7:5af61d55adbe 143 # multiple compilations and linking with the same objects
screamer 7:5af61d55adbe 144 src_paths = [src_paths[0]] + list(set(src_paths[1:]))
screamer 7:5af61d55adbe 145 first_src_path = src_paths[0] if src_paths[0] != "." and src_paths[0] != "./" else getcwd()
screamer 7:5af61d55adbe 146 abs_path = abspath(first_src_path)
screamer 7:5af61d55adbe 147 project_name = basename(normpath(abs_path))
screamer 7:5af61d55adbe 148
screamer 7:5af61d55adbe 149 # If the configuration object was not yet created, create it now
screamer 7:5af61d55adbe 150 config = config or Config(target, src_paths)
screamer 7:5af61d55adbe 151
screamer 7:5af61d55adbe 152 # If the 'target' argument is a string, convert it to a target instance
screamer 13:ab47a20b66f0 153 if isinstance(target, basestring):
screamer 7:5af61d55adbe 154 try:
screamer 7:5af61d55adbe 155 target = TARGET_MAP[target]
screamer 7:5af61d55adbe 156 except KeyError:
screamer 7:5af61d55adbe 157 raise KeyError("Target '%s' not found" % target)
screamer 7:5af61d55adbe 158
screamer 14:ee1b877e6839 159 # Find build system profile
screamer 14:ee1b877e6839 160 profile = None
screamer 14:ee1b877e6839 161 for path in src_paths:
screamer 14:ee1b877e6839 162 profile = find_build_profile(path) or profile
screamer 14:ee1b877e6839 163
screamer 14:ee1b877e6839 164 if profile:
screamer 14:ee1b877e6839 165 def init_hook(self):
screamer 14:ee1b877e6839 166 profile_data = get_toolchain_profile(self.name, profile)
screamer 14:ee1b877e6839 167 if not profile_data:
screamer 14:ee1b877e6839 168 return
screamer 14:ee1b877e6839 169 self.info("Using toolchain %s profile %s" % (self.name, profile))
screamer 14:ee1b877e6839 170
screamer 14:ee1b877e6839 171 for k,v in profile_data.items():
screamer 14:ee1b877e6839 172 if self.flags.has_key(k):
screamer 14:ee1b877e6839 173 self.flags[k] = v
screamer 14:ee1b877e6839 174 else:
screamer 14:ee1b877e6839 175 setattr(self, k, v)
screamer 14:ee1b877e6839 176
screamer 14:ee1b877e6839 177 mbedToolchain.init = init_hook
screamer 14:ee1b877e6839 178
screamer 7:5af61d55adbe 179 # Toolchain instance
screamer 7:5af61d55adbe 180 try:
screamer 13:ab47a20b66f0 181 toolchain = TOOLCHAIN_CLASSES[toolchain_name](target, options, notify, macros, silent, extra_verbose=extra_verbose)
screamer 0:66f3b5499f7f 182 except KeyError as e:
screamer 0:66f3b5499f7f 183 raise KeyError("Toolchain %s not supported" % toolchain_name)
screamer 0:66f3b5499f7f 184
screamer 0:66f3b5499f7f 185 toolchain.VERBOSE = verbose
screamer 0:66f3b5499f7f 186 toolchain.jobs = jobs
screamer 0:66f3b5499f7f 187 toolchain.build_all = clean
screamer 0:66f3b5499f7f 188
screamer 0:66f3b5499f7f 189 if name is None:
screamer 0:66f3b5499f7f 190 # We will use default project name based on project folder name
screamer 0:66f3b5499f7f 191 name = project_name
screamer 0:66f3b5499f7f 192 toolchain.info("Building project %s (%s, %s)" % (project_name, target.name, toolchain_name))
screamer 0:66f3b5499f7f 193 else:
screamer 0:66f3b5499f7f 194 # User used custom global project name to have the same name for the
screamer 0:66f3b5499f7f 195 toolchain.info("Building project %s to %s (%s, %s)" % (project_name, name, target.name, toolchain_name))
screamer 0:66f3b5499f7f 196
screamer 0:66f3b5499f7f 197
screamer 0:66f3b5499f7f 198 if report != None:
screamer 0:66f3b5499f7f 199 start = time()
screamer 22:9e85236d8716 200
screamer 7:5af61d55adbe 201 # If project_id is specified, use that over the default name
screamer 7:5af61d55adbe 202 id_name = project_id.upper() if project_id else name.upper()
screamer 7:5af61d55adbe 203 description = project_description if project_description else name
screamer 0:66f3b5499f7f 204 vendor_label = target.extra_labels[0]
screamer 0:66f3b5499f7f 205 cur_result = None
screamer 0:66f3b5499f7f 206 prep_report(report, target.name, toolchain_name, id_name)
screamer 0:66f3b5499f7f 207 cur_result = create_result(target.name, toolchain_name, id_name, description)
screamer 0:66f3b5499f7f 208
screamer 0:66f3b5499f7f 209 if properties != None:
screamer 0:66f3b5499f7f 210 prep_properties(properties, target.name, toolchain_name, vendor_label)
screamer 0:66f3b5499f7f 211
screamer 0:66f3b5499f7f 212 try:
screamer 0:66f3b5499f7f 213 # Scan src_path and libraries_paths for resources
screamer 0:66f3b5499f7f 214 resources = toolchain.scan_resources(src_paths[0])
screamer 0:66f3b5499f7f 215 for path in src_paths[1:]:
screamer 0:66f3b5499f7f 216 resources.add(toolchain.scan_resources(path))
screamer 0:66f3b5499f7f 217 if libraries_paths is not None:
screamer 0:66f3b5499f7f 218 src_paths.extend(libraries_paths)
screamer 0:66f3b5499f7f 219 for path in libraries_paths:
screamer 0:66f3b5499f7f 220 resources.add(toolchain.scan_resources(path))
screamer 0:66f3b5499f7f 221
screamer 0:66f3b5499f7f 222 if linker_script is not None:
screamer 0:66f3b5499f7f 223 resources.linker_script = linker_script
screamer 0:66f3b5499f7f 224
screamer 0:66f3b5499f7f 225 # Build Directory
screamer 0:66f3b5499f7f 226 if clean:
screamer 0:66f3b5499f7f 227 if exists(build_path):
screamer 0:66f3b5499f7f 228 rmtree(build_path)
screamer 0:66f3b5499f7f 229 mkdir(build_path)
screamer 0:66f3b5499f7f 230
screamer 0:66f3b5499f7f 231 # We need to add if necessary additional include directories
screamer 0:66f3b5499f7f 232 if inc_dirs:
screamer 0:66f3b5499f7f 233 if type(inc_dirs) == ListType:
screamer 0:66f3b5499f7f 234 resources.inc_dirs.extend(inc_dirs)
screamer 0:66f3b5499f7f 235 else:
screamer 0:66f3b5499f7f 236 resources.inc_dirs.append(inc_dirs)
screamer 7:5af61d55adbe 237
screamer 13:ab47a20b66f0 238 # Load resources into the config system which might expand/modify resources based on config data
screamer 13:ab47a20b66f0 239 resources = config.load_resources(resources)
screamer 13:ab47a20b66f0 240
screamer 13:ab47a20b66f0 241 # Set the toolchain's configuration data
screamer 13:ab47a20b66f0 242 toolchain.set_config_data(config.get_config_data())
screamer 7:5af61d55adbe 243
screamer 0:66f3b5499f7f 244 # Compile Sources
screamer 13:ab47a20b66f0 245 objects = toolchain.compile_sources(resources, build_path, resources.inc_dirs)
screamer 13:ab47a20b66f0 246 resources.objects.extend(objects)
screamer 0:66f3b5499f7f 247
screamer 0:66f3b5499f7f 248 # Link Program
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 249 res, _ = toolchain.link_program(resources, build_path, name)
screamer 0:66f3b5499f7f 250
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 251 if report != None:
screamer 0:66f3b5499f7f 252 end = time()
screamer 0:66f3b5499f7f 253 cur_result["elapsed_time"] = end - start
screamer 0:66f3b5499f7f 254 cur_result["output"] = toolchain.get_output()
screamer 0:66f3b5499f7f 255 cur_result["result"] = "OK"
screamer 22:9e85236d8716 256 cur_result["memory_usage"] = toolchain.map_outputs
screamer 0:66f3b5499f7f 257
screamer 0:66f3b5499f7f 258 add_result_to_report(report, cur_result)
screamer 0:66f3b5499f7f 259
screamer 0:66f3b5499f7f 260 return res
screamer 0:66f3b5499f7f 261
screamer 0:66f3b5499f7f 262 except Exception, e:
screamer 0:66f3b5499f7f 263 if report != None:
screamer 0:66f3b5499f7f 264 end = time()
screamer 0:66f3b5499f7f 265
screamer 0:66f3b5499f7f 266 if isinstance(e, NotSupportedException):
screamer 0:66f3b5499f7f 267 cur_result["result"] = "NOT_SUPPORTED"
screamer 0:66f3b5499f7f 268 else:
screamer 0:66f3b5499f7f 269 cur_result["result"] = "FAIL"
screamer 0:66f3b5499f7f 270
screamer 0:66f3b5499f7f 271 cur_result["elapsed_time"] = end - start
screamer 0:66f3b5499f7f 272
screamer 0:66f3b5499f7f 273 toolchain_output = toolchain.get_output()
screamer 0:66f3b5499f7f 274 if toolchain_output:
screamer 0:66f3b5499f7f 275 cur_result["output"] += toolchain_output
screamer 0:66f3b5499f7f 276
screamer 0:66f3b5499f7f 277 add_result_to_report(report, cur_result)
screamer 0:66f3b5499f7f 278
screamer 0:66f3b5499f7f 279 # Let Exception propagate
screamer 13:ab47a20b66f0 280 raise
screamer 0:66f3b5499f7f 281
screamer 0:66f3b5499f7f 282 def build_library(src_paths, build_path, target, toolchain_name,
screamer 0:66f3b5499f7f 283 dependencies_paths=None, options=None, name=None, clean=False, archive=True,
screamer 0:66f3b5499f7f 284 notify=None, verbose=False, macros=None, inc_dirs=None, inc_dirs_ext=None,
screamer 7:5af61d55adbe 285 jobs=1, silent=False, report=None, properties=None, extra_verbose=False,
screamer 7:5af61d55adbe 286 project_id=None):
screamer 0:66f3b5499f7f 287 """ src_path: the path of the source directory
screamer 0:66f3b5499f7f 288 build_path: the path of the build directory
screamer 0:66f3b5499f7f 289 target: ['LPC1768', 'LPC11U24', 'LPC2368']
screamer 0:66f3b5499f7f 290 toolchain: ['ARM', 'uARM', 'GCC_ARM', 'GCC_CR']
screamer 0:66f3b5499f7f 291 library_paths: List of paths to additional libraries
screamer 0:66f3b5499f7f 292 clean: Rebuild everything if True
screamer 0:66f3b5499f7f 293 notify: Notify function for logs
screamer 0:66f3b5499f7f 294 verbose: Write the actual tools command lines if True
screamer 0:66f3b5499f7f 295 inc_dirs: additional include directories which should be included in build
screamer 0:66f3b5499f7f 296 inc_dirs_ext: additional include directories which should be copied to library directory
screamer 0:66f3b5499f7f 297 """
screamer 0:66f3b5499f7f 298 if type(src_paths) != ListType:
screamer 0:66f3b5499f7f 299 src_paths = [src_paths]
screamer 0:66f3b5499f7f 300
screamer 0:66f3b5499f7f 301 # The first path will give the name to the library
screamer 7:5af61d55adbe 302 project_name = basename(src_paths[0] if src_paths[0] != "." and src_paths[0] != "./" else getcwd())
screamer 0:66f3b5499f7f 303 if name is None:
screamer 0:66f3b5499f7f 304 # We will use default project name based on project folder name
screamer 0:66f3b5499f7f 305 name = project_name
screamer 0:66f3b5499f7f 306
screamer 13:ab47a20b66f0 307 # If the configuration object was not yet created, create it now
screamer 13:ab47a20b66f0 308 config = Config(target, src_paths)
screamer 13:ab47a20b66f0 309
screamer 13:ab47a20b66f0 310 # If the 'target' argument is a string, convert it to a target instance
screamer 13:ab47a20b66f0 311 if isinstance(target, basestring):
screamer 13:ab47a20b66f0 312 try:
screamer 13:ab47a20b66f0 313 target = TARGET_MAP[target]
screamer 13:ab47a20b66f0 314 except KeyError:
screamer 13:ab47a20b66f0 315 raise KeyError("Target '%s' not found" % target)
screamer 13:ab47a20b66f0 316
screamer 0:66f3b5499f7f 317 if report != None:
screamer 0:66f3b5499f7f 318 start = time()
screamer 22:9e85236d8716 319
screamer 7:5af61d55adbe 320 # If project_id is specified, use that over the default name
screamer 7:5af61d55adbe 321 id_name = project_id.upper() if project_id else name.upper()
screamer 0:66f3b5499f7f 322 description = name
screamer 0:66f3b5499f7f 323 vendor_label = target.extra_labels[0]
screamer 0:66f3b5499f7f 324 cur_result = None
screamer 0:66f3b5499f7f 325 prep_report(report, target.name, toolchain_name, id_name)
screamer 0:66f3b5499f7f 326 cur_result = create_result(target.name, toolchain_name, id_name, description)
screamer 0:66f3b5499f7f 327
screamer 0:66f3b5499f7f 328 if properties != None:
screamer 0:66f3b5499f7f 329 prep_properties(properties, target.name, toolchain_name, vendor_label)
screamer 0:66f3b5499f7f 330
screamer 0:66f3b5499f7f 331 for src_path in src_paths:
screamer 0:66f3b5499f7f 332 if not exists(src_path):
screamer 0:66f3b5499f7f 333 error_msg = "The library source folder does not exist: %s", src_path
screamer 0:66f3b5499f7f 334
screamer 0:66f3b5499f7f 335 if report != None:
screamer 0:66f3b5499f7f 336 cur_result["output"] = error_msg
screamer 0:66f3b5499f7f 337 cur_result["result"] = "FAIL"
screamer 0:66f3b5499f7f 338 add_result_to_report(report, cur_result)
screamer 0:66f3b5499f7f 339
screamer 0:66f3b5499f7f 340 raise Exception(error_msg)
screamer 0:66f3b5499f7f 341
screamer 0:66f3b5499f7f 342 try:
screamer 0:66f3b5499f7f 343 # Toolchain instance
screamer 13:ab47a20b66f0 344 toolchain = TOOLCHAIN_CLASSES[toolchain_name](target, options, macros=macros, notify=notify, silent=silent, extra_verbose=extra_verbose)
screamer 0:66f3b5499f7f 345 toolchain.VERBOSE = verbose
screamer 0:66f3b5499f7f 346 toolchain.jobs = jobs
screamer 0:66f3b5499f7f 347 toolchain.build_all = clean
screamer 0:66f3b5499f7f 348
screamer 0:66f3b5499f7f 349 toolchain.info("Building library %s (%s, %s)" % (name, target.name, toolchain_name))
screamer 0:66f3b5499f7f 350
screamer 0:66f3b5499f7f 351 # Scan Resources
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 352 resources = None
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 353 for path in src_paths:
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 354 # Scan resources
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 355 resource = toolchain.scan_resources(path)
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 356
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 357 # Extend resources collection
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 358 if not resources:
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 359 resources = resource
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 360 else:
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 361 resources.add(resource)
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 362
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 363 # We need to add if necessary additional include directories
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 364 if inc_dirs:
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 365 if type(inc_dirs) == ListType:
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 366 resources.inc_dirs.extend(inc_dirs)
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 367 else:
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 368 resources.inc_dirs.append(inc_dirs)
screamer 0:66f3b5499f7f 369
screamer 0:66f3b5499f7f 370 # Add extra include directories / files which are required by library
screamer 0:66f3b5499f7f 371 # This files usually are not in the same directory as source files so
screamer 0:66f3b5499f7f 372 # previous scan will not include them
screamer 0:66f3b5499f7f 373 if inc_dirs_ext is not None:
screamer 0:66f3b5499f7f 374 for inc_ext in inc_dirs_ext:
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 375 resources.add(toolchain.scan_resources(inc_ext))
screamer 0:66f3b5499f7f 376
screamer 0:66f3b5499f7f 377 # Dependencies Include Paths
screamer 0:66f3b5499f7f 378 if dependencies_paths is not None:
screamer 0:66f3b5499f7f 379 for path in dependencies_paths:
screamer 0:66f3b5499f7f 380 lib_resources = toolchain.scan_resources(path)
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 381 resources.inc_dirs.extend(lib_resources.inc_dirs)
screamer 0:66f3b5499f7f 382
screamer 0:66f3b5499f7f 383 if archive:
screamer 0:66f3b5499f7f 384 # Use temp path when building archive
screamer 0:66f3b5499f7f 385 tmp_path = join(build_path, '.temp')
screamer 0:66f3b5499f7f 386 mkdir(tmp_path)
screamer 0:66f3b5499f7f 387 else:
screamer 0:66f3b5499f7f 388 tmp_path = build_path
screamer 0:66f3b5499f7f 389
screamer 13:ab47a20b66f0 390 # Load resources into the config system which might expand/modify resources based on config data
screamer 13:ab47a20b66f0 391 resources = config.load_resources(resources)
screamer 13:ab47a20b66f0 392
screamer 13:ab47a20b66f0 393 # Set the toolchain's configuration data
screamer 13:ab47a20b66f0 394 toolchain.set_config_data(config.get_config_data())
screamer 13:ab47a20b66f0 395
screamer 13:ab47a20b66f0 396 # Copy headers, objects and static libraries - all files needed for static lib
screamer 13:ab47a20b66f0 397 toolchain.copy_files(resources.headers, build_path, resources=resources)
screamer 13:ab47a20b66f0 398 toolchain.copy_files(resources.objects, build_path, resources=resources)
screamer 13:ab47a20b66f0 399 toolchain.copy_files(resources.libraries, build_path, resources=resources)
screamer 13:ab47a20b66f0 400 if resources.linker_script:
screamer 13:ab47a20b66f0 401 toolchain.copy_files(resources.linker_script, build_path, resources=resources)
screamer 22:9e85236d8716 402
screamer 13:ab47a20b66f0 403 if resource.hex_files:
screamer 13:ab47a20b66f0 404 toolchain.copy_files(resources.hex_files, build_path, resources=resources)
screamer 0:66f3b5499f7f 405
screamer 0:66f3b5499f7f 406 # Compile Sources
screamer 13:ab47a20b66f0 407 objects = toolchain.compile_sources(resources, abspath(tmp_path), resources.inc_dirs)
screamer 13:ab47a20b66f0 408 resources.objects.extend(objects)
screamer 0:66f3b5499f7f 409
screamer 0:66f3b5499f7f 410 if archive:
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 411 toolchain.build_library(objects, build_path, name)
screamer 0:66f3b5499f7f 412
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 413 if report != None:
screamer 0:66f3b5499f7f 414 end = time()
screamer 0:66f3b5499f7f 415 cur_result["elapsed_time"] = end - start
screamer 0:66f3b5499f7f 416 cur_result["output"] = toolchain.get_output()
screamer 0:66f3b5499f7f 417 cur_result["result"] = "OK"
screamer 0:66f3b5499f7f 418
screamer 0:66f3b5499f7f 419 add_result_to_report(report, cur_result)
screamer 22:9e85236d8716 420 return True
screamer 0:66f3b5499f7f 421
screamer 0:66f3b5499f7f 422 except Exception, e:
screamer 0:66f3b5499f7f 423 if report != None:
screamer 0:66f3b5499f7f 424 end = time()
screamer 22:9e85236d8716 425
screamer 7:5af61d55adbe 426 if isinstance(e, ToolException):
screamer 7:5af61d55adbe 427 cur_result["result"] = "FAIL"
screamer 7:5af61d55adbe 428 elif isinstance(e, NotSupportedException):
screamer 7:5af61d55adbe 429 cur_result["result"] = "NOT_SUPPORTED"
screamer 22:9e85236d8716 430
screamer 0:66f3b5499f7f 431 cur_result["elapsed_time"] = end - start
screamer 0:66f3b5499f7f 432
screamer 0:66f3b5499f7f 433 toolchain_output = toolchain.get_output()
screamer 0:66f3b5499f7f 434 if toolchain_output:
screamer 0:66f3b5499f7f 435 cur_result["output"] += toolchain_output
screamer 0:66f3b5499f7f 436
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 437 add_result_to_report(report, cur_result)
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 438
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 439 # Let Exception propagate
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 440 raise e
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 441
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 442 ######################
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 443 ### Legacy methods ###
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 444 ######################
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 445
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 446 def build_lib(lib_id, target, toolchain_name, options=None, verbose=False, clean=False, macros=None, notify=None, jobs=1, silent=False, report=None, properties=None, extra_verbose=False):
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 447 """ Legacy method for building mbed libraries
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 448 Function builds library in proper directory using all dependencies and macros defined by user.
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 449 """
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 450 lib = Library(lib_id)
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 451 if not lib.is_supported(target, toolchain_name):
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 452 print 'Library "%s" is not yet supported on target %s with toolchain %s' % (lib_id, target.name, toolchain)
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 453 return False
screamer 22:9e85236d8716 454
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 455 # We need to combine macros from parameter list with macros from library definition
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 456 MACROS = lib.macros if lib.macros else []
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 457 if macros:
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 458 macros.extend(MACROS)
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 459 else:
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 460 macros = MACROS
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 461
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 462 src_paths = lib.source_dir
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 463 build_path = lib.build_dir
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 464 dependencies_paths = lib.dependencies
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 465 inc_dirs = lib.inc_dirs
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 466 inc_dirs_ext = lib.inc_dirs_ext
screamer 22:9e85236d8716 467
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 468 """ src_path: the path of the source directory
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 469 build_path: the path of the build directory
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 470 target: ['LPC1768', 'LPC11U24', 'LPC2368']
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 471 toolchain: ['ARM', 'uARM', 'GCC_ARM', 'GCC_CR']
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 472 library_paths: List of paths to additional libraries
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 473 clean: Rebuild everything if True
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 474 notify: Notify function for logs
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 475 verbose: Write the actual tools command lines if True
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 476 inc_dirs: additional include directories which should be included in build
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 477 inc_dirs_ext: additional include directories which should be copied to library directory
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 478 """
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 479 if type(src_paths) != ListType:
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 480 src_paths = [src_paths]
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 481
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 482 # The first path will give the name to the library
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 483 name = basename(src_paths[0])
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 484
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 485 if report != None:
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 486 start = time()
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 487 id_name = name.upper()
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 488 description = name
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 489 vendor_label = target.extra_labels[0]
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 490 cur_result = None
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 491 prep_report(report, target.name, toolchain_name, id_name)
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 492 cur_result = create_result(target.name, toolchain_name, id_name, description)
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 493
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 494 if properties != None:
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 495 prep_properties(properties, target.name, toolchain_name, vendor_label)
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 496
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 497 for src_path in src_paths:
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 498 if not exists(src_path):
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 499 error_msg = "The library source folder does not exist: %s", src_path
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 500
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 501 if report != None:
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 502 cur_result["output"] = error_msg
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 503 cur_result["result"] = "FAIL"
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 504 add_result_to_report(report, cur_result)
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 505
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 506 raise Exception(error_msg)
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 507
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 508 try:
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 509 # Toolchain instance
screamer 13:ab47a20b66f0 510 toolchain = TOOLCHAIN_CLASSES[toolchain_name](target, options, macros=macros, notify=notify, silent=silent, extra_verbose=extra_verbose)
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 511 toolchain.VERBOSE = verbose
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 512 toolchain.jobs = jobs
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 513 toolchain.build_all = clean
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 514
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 515 toolchain.info("Building library %s (%s, %s)" % (name.upper(), target.name, toolchain_name))
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 516
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 517 # Scan Resources
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 518 resources = []
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 519 for src_path in src_paths:
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 520 resources.append(toolchain.scan_resources(src_path))
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 521
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 522 # Add extra include directories / files which are required by library
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 523 # This files usually are not in the same directory as source files so
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 524 # previous scan will not include them
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 525 if inc_dirs_ext is not None:
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 526 for inc_ext in inc_dirs_ext:
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 527 resources.append(toolchain.scan_resources(inc_ext))
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 528
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 529 # Dependencies Include Paths
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 530 dependencies_include_dir = []
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 531 if dependencies_paths is not None:
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 532 for path in dependencies_paths:
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 533 lib_resources = toolchain.scan_resources(path)
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 534 dependencies_include_dir.extend(lib_resources.inc_dirs)
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 535
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 536 if inc_dirs:
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 537 dependencies_include_dir.extend(inc_dirs)
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 538
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 539 # Create the desired build directory structure
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 540 bin_path = join(build_path, toolchain.obj_path)
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 541 mkdir(bin_path)
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 542 tmp_path = join(build_path, '.temp', toolchain.obj_path)
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 543 mkdir(tmp_path)
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 544
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 545 # Copy Headers
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 546 for resource in resources:
screamer 13:ab47a20b66f0 547 toolchain.copy_files(resource.headers, build_path, resources=resource)
screamer 22:9e85236d8716 548
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 549 dependencies_include_dir.extend(toolchain.scan_resources(build_path).inc_dirs)
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 550
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 551 # Compile Sources
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 552 objects = []
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 553 for resource in resources:
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 554 objects.extend(toolchain.compile_sources(resource, tmp_path, dependencies_include_dir))
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 555
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 556 needed_update = toolchain.build_library(objects, bin_path, name)
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 557
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 558 if report != None and needed_update:
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 559 end = time()
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 560 cur_result["elapsed_time"] = end - start
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 561 cur_result["output"] = toolchain.get_output()
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 562 cur_result["result"] = "OK"
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 563
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 564 add_result_to_report(report, cur_result)
screamer 22:9e85236d8716 565 return True
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 566
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 567 except Exception, e:
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 568 if report != None:
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 569 end = time()
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 570 cur_result["result"] = "FAIL"
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 571 cur_result["elapsed_time"] = end - start
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 572
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 573 toolchain_output = toolchain.get_output()
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 574 if toolchain_output:
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 575 cur_result["output"] += toolchain_output
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 576
screamer 0:66f3b5499f7f 577 add_result_to_report(report, cur_result)
screamer 0:66f3b5499f7f 578
screamer 0:66f3b5499f7f 579 # Let Exception propagate
screamer 0:66f3b5499f7f 580 raise e
screamer 0:66f3b5499f7f 581
screamer 0:66f3b5499f7f 582 # We do have unique legacy conventions about how we build and package the mbed library
screamer 0:66f3b5499f7f 583 def build_mbed_libs(target, toolchain_name, options=None, verbose=False, clean=False, macros=None, notify=None, jobs=1, silent=False, report=None, properties=None, extra_verbose=False):
screamer 0:66f3b5499f7f 584 """ Function returns True is library was built and false if building was skipped """
screamer 0:66f3b5499f7f 585
screamer 0:66f3b5499f7f 586 if report != None:
screamer 0:66f3b5499f7f 587 start = time()
screamer 0:66f3b5499f7f 588 id_name = "MBED"
screamer 0:66f3b5499f7f 589 description = "mbed SDK"
screamer 0:66f3b5499f7f 590 vendor_label = target.extra_labels[0]
screamer 0:66f3b5499f7f 591 cur_result = None
screamer 0:66f3b5499f7f 592 prep_report(report, target.name, toolchain_name, id_name)
screamer 0:66f3b5499f7f 593 cur_result = create_result(target.name, toolchain_name, id_name, description)
screamer 0:66f3b5499f7f 594
screamer 0:66f3b5499f7f 595 if properties != None:
screamer 0:66f3b5499f7f 596 prep_properties(properties, target.name, toolchain_name, vendor_label)
screamer 0:66f3b5499f7f 597
screamer 0:66f3b5499f7f 598 # Check toolchain support
screamer 0:66f3b5499f7f 599 if toolchain_name not in target.supported_toolchains:
screamer 0:66f3b5499f7f 600 supported_toolchains_text = ", ".join(target.supported_toolchains)
screamer 0:66f3b5499f7f 601 print '%s target is not yet supported by toolchain %s' % (target.name, toolchain_name)
screamer 0:66f3b5499f7f 602 print '%s target supports %s toolchain%s' % (target.name, supported_toolchains_text, 's' if len(target.supported_toolchains) > 1 else '')
screamer 0:66f3b5499f7f 603
screamer 0:66f3b5499f7f 604 if report != None:
screamer 0:66f3b5499f7f 605 cur_result["result"] = "SKIP"
screamer 0:66f3b5499f7f 606 add_result_to_report(report, cur_result)
screamer 0:66f3b5499f7f 607
screamer 0:66f3b5499f7f 608 return False
screamer 0:66f3b5499f7f 609
screamer 0:66f3b5499f7f 610 try:
screamer 0:66f3b5499f7f 611 # Toolchain
screamer 0:66f3b5499f7f 612 toolchain = TOOLCHAIN_CLASSES[toolchain_name](target, options, macros=macros, notify=notify, silent=silent, extra_verbose=extra_verbose)
screamer 0:66f3b5499f7f 613 toolchain.VERBOSE = verbose
screamer 0:66f3b5499f7f 614 toolchain.jobs = jobs
screamer 0:66f3b5499f7f 615 toolchain.build_all = clean
screamer 0:66f3b5499f7f 616
screamer 0:66f3b5499f7f 617 # Source and Build Paths
screamer 0:66f3b5499f7f 618 BUILD_TARGET = join(MBED_LIBRARIES, "TARGET_" + target.name)
screamer 0:66f3b5499f7f 619 BUILD_TOOLCHAIN = join(BUILD_TARGET, "TOOLCHAIN_" + toolchain.name)
screamer 0:66f3b5499f7f 620 mkdir(BUILD_TOOLCHAIN)
screamer 0:66f3b5499f7f 621
screamer 0:66f3b5499f7f 622 TMP_PATH = join(MBED_LIBRARIES, '.temp', toolchain.obj_path)
screamer 0:66f3b5499f7f 623 mkdir(TMP_PATH)
screamer 0:66f3b5499f7f 624
screamer 0:66f3b5499f7f 625 # CMSIS
screamer 0:66f3b5499f7f 626 toolchain.info("Building library %s (%s, %s)"% ('CMSIS', target.name, toolchain_name))
screamer 0:66f3b5499f7f 627 cmsis_src = join(MBED_TARGETS_PATH, "cmsis")
screamer 0:66f3b5499f7f 628 resources = toolchain.scan_resources(cmsis_src)
screamer 0:66f3b5499f7f 629
screamer 0:66f3b5499f7f 630 toolchain.copy_files(resources.headers, BUILD_TARGET)
screamer 0:66f3b5499f7f 631 toolchain.copy_files(resources.linker_script, BUILD_TOOLCHAIN)
screamer 0:66f3b5499f7f 632 toolchain.copy_files(resources.bin_files, BUILD_TOOLCHAIN)
screamer 0:66f3b5499f7f 633
screamer 0:66f3b5499f7f 634 objects = toolchain.compile_sources(resources, TMP_PATH)
screamer 0:66f3b5499f7f 635 toolchain.copy_files(objects, BUILD_TOOLCHAIN)
screamer 0:66f3b5499f7f 636
screamer 0:66f3b5499f7f 637 # mbed
screamer 0:66f3b5499f7f 638 toolchain.info("Building library %s (%s, %s)" % ('MBED', target.name, toolchain_name))
screamer 0:66f3b5499f7f 639
screamer 0:66f3b5499f7f 640 # Common Headers
screamer 0:66f3b5499f7f 641 toolchain.copy_files(toolchain.scan_resources(MBED_API).headers, MBED_LIBRARIES)
screamer 0:66f3b5499f7f 642 toolchain.copy_files(toolchain.scan_resources(MBED_HAL).headers, MBED_LIBRARIES)
screamer 0:66f3b5499f7f 643
screamer 0:66f3b5499f7f 644 # Target specific sources
screamer 0:66f3b5499f7f 645 HAL_SRC = join(MBED_TARGETS_PATH, "hal")
screamer 0:66f3b5499f7f 646 hal_implementation = toolchain.scan_resources(HAL_SRC)
screamer 13:ab47a20b66f0 647 toolchain.copy_files(hal_implementation.headers + hal_implementation.hex_files + hal_implementation.libraries, BUILD_TARGET, resources=hal_implementation)
screamer 0:66f3b5499f7f 648 incdirs = toolchain.scan_resources(BUILD_TARGET).inc_dirs
screamer 0:66f3b5499f7f 649 objects = toolchain.compile_sources(hal_implementation, TMP_PATH, [MBED_LIBRARIES] + incdirs)
screamer 0:66f3b5499f7f 650
screamer 0:66f3b5499f7f 651 # Common Sources
screamer 0:66f3b5499f7f 652 mbed_resources = toolchain.scan_resources(MBED_COMMON)
screamer 0:66f3b5499f7f 653 objects += toolchain.compile_sources(mbed_resources, TMP_PATH, [MBED_LIBRARIES] + incdirs)
screamer 0:66f3b5499f7f 654
screamer 0:66f3b5499f7f 655 # A number of compiled files need to be copied as objects as opposed to
screamer 0:66f3b5499f7f 656 # being part of the mbed library, for reasons that have to do with the way
screamer 0:66f3b5499f7f 657 # the linker search for symbols in archives. These are:
screamer 0:66f3b5499f7f 658 # - retarget.o: to make sure that the C standard lib symbols get overridden
screamer 0:66f3b5499f7f 659 # - board.o: mbed_die is weak
screamer 0:66f3b5499f7f 660 # - mbed_overrides.o: this contains platform overrides of various weak SDK functions
screamer 0:66f3b5499f7f 661 separate_names, separate_objects = ['retarget.o', 'board.o', 'mbed_overrides.o'], []
screamer 0:66f3b5499f7f 662
screamer 0:66f3b5499f7f 663 for o in objects:
screamer 0:66f3b5499f7f 664 for name in separate_names:
screamer 0:66f3b5499f7f 665 if o.endswith(name):
screamer 0:66f3b5499f7f 666 separate_objects.append(o)
screamer 0:66f3b5499f7f 667
screamer 0:66f3b5499f7f 668 for o in separate_objects:
screamer 0:66f3b5499f7f 669 objects.remove(o)
screamer 0:66f3b5499f7f 670
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 671 toolchain.build_library(objects, BUILD_TOOLCHAIN, "mbed")
screamer 0:66f3b5499f7f 672
screamer 0:66f3b5499f7f 673 for o in separate_objects:
screamer 0:66f3b5499f7f 674 toolchain.copy_files(o, BUILD_TOOLCHAIN)
screamer 0:66f3b5499f7f 675
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 676 if report != None:
screamer 0:66f3b5499f7f 677 end = time()
screamer 0:66f3b5499f7f 678 cur_result["elapsed_time"] = end - start
screamer 0:66f3b5499f7f 679 cur_result["output"] = toolchain.get_output()
screamer 0:66f3b5499f7f 680 cur_result["result"] = "OK"
screamer 0:66f3b5499f7f 681
screamer 0:66f3b5499f7f 682 add_result_to_report(report, cur_result)
screamer 0:66f3b5499f7f 683
screamer 0:66f3b5499f7f 684 return True
screamer 0:66f3b5499f7f 685
screamer 0:66f3b5499f7f 686 except Exception, e:
screamer 0:66f3b5499f7f 687 if report != None:
screamer 0:66f3b5499f7f 688 end = time()
screamer 0:66f3b5499f7f 689 cur_result["result"] = "FAIL"
screamer 0:66f3b5499f7f 690 cur_result["elapsed_time"] = end - start
screamer 0:66f3b5499f7f 691
screamer 0:66f3b5499f7f 692 toolchain_output = toolchain.get_output()
screamer 0:66f3b5499f7f 693 if toolchain_output:
screamer 0:66f3b5499f7f 694 cur_result["output"] += toolchain_output
screamer 0:66f3b5499f7f 695
screamer 0:66f3b5499f7f 696 cur_result["output"] += str(e)
screamer 0:66f3b5499f7f 697
screamer 0:66f3b5499f7f 698 add_result_to_report(report, cur_result)
screamer 0:66f3b5499f7f 699
screamer 0:66f3b5499f7f 700 # Let Exception propagate
screamer 0:66f3b5499f7f 701 raise e
screamer 0:66f3b5499f7f 702
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 703
screamer 0:66f3b5499f7f 704 def get_unique_supported_toolchains():
screamer 0:66f3b5499f7f 705 """ Get list of all unique toolchains supported by targets """
screamer 0:66f3b5499f7f 706 unique_supported_toolchains = []
screamer 0:66f3b5499f7f 707 for target in TARGET_NAMES:
screamer 0:66f3b5499f7f 708 for toolchain in TARGET_MAP[target].supported_toolchains:
screamer 0:66f3b5499f7f 709 if toolchain not in unique_supported_toolchains:
screamer 0:66f3b5499f7f 710 unique_supported_toolchains.append(toolchain)
screamer 0:66f3b5499f7f 711 return unique_supported_toolchains
screamer 0:66f3b5499f7f 712
screamer 0:66f3b5499f7f 713
screamer 0:66f3b5499f7f 714 def mcu_toolchain_matrix(verbose_html=False, platform_filter=None):
screamer 0:66f3b5499f7f 715 """ Shows target map using prettytable """
screamer 0:66f3b5499f7f 716 unique_supported_toolchains = get_unique_supported_toolchains()
screamer 0:66f3b5499f7f 717 from prettytable import PrettyTable # Only use it in this function so building works without extra modules
screamer 0:66f3b5499f7f 718
screamer 0:66f3b5499f7f 719 # All tests status table print
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 720 columns = ["Target"] + unique_supported_toolchains
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 721 pt = PrettyTable(["Target"] + unique_supported_toolchains)
screamer 0:66f3b5499f7f 722 # Align table
screamer 0:66f3b5499f7f 723 for col in columns:
screamer 0:66f3b5499f7f 724 pt.align[col] = "c"
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 725 pt.align["Target"] = "l"
screamer 0:66f3b5499f7f 726
screamer 0:66f3b5499f7f 727 perm_counter = 0
screamer 0:66f3b5499f7f 728 target_counter = 0
screamer 0:66f3b5499f7f 729 for target in sorted(TARGET_NAMES):
screamer 0:66f3b5499f7f 730 if platform_filter is not None:
screamer 0:66f3b5499f7f 731 # FIlter out platforms using regex
screamer 0:66f3b5499f7f 732 if re.search(platform_filter, target) is None:
screamer 0:66f3b5499f7f 733 continue
screamer 0:66f3b5499f7f 734 target_counter += 1
screamer 0:66f3b5499f7f 735
screamer 0:66f3b5499f7f 736 row = [target] # First column is platform name
screamer 0:66f3b5499f7f 737 for unique_toolchain in unique_supported_toolchains:
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 738 if unique_toolchain in TARGET_MAP[target].supported_toolchains:
screamer 0:66f3b5499f7f 739 text = "Supported"
screamer 0:66f3b5499f7f 740 perm_counter += 1
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 741 else:
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 742 text = "-"
screamer 22:9e85236d8716 743
screamer 0:66f3b5499f7f 744 row.append(text)
screamer 0:66f3b5499f7f 745 pt.add_row(row)
screamer 0:66f3b5499f7f 746
screamer 0:66f3b5499f7f 747 result = pt.get_html_string() if verbose_html else pt.get_string()
screamer 0:66f3b5499f7f 748 result += "\n"
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 749 result += "Supported targets: %d\n"% (target_counter)
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 750 if target_counter == 1:
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 751 result += "Supported toolchains: %d"% (perm_counter)
screamer 0:66f3b5499f7f 752 return result
screamer 0:66f3b5499f7f 753
screamer 0:66f3b5499f7f 754
screamer 0:66f3b5499f7f 755 def get_target_supported_toolchains(target):
screamer 0:66f3b5499f7f 756 """ Returns target supported toolchains list """
screamer 0:66f3b5499f7f 757 return TARGET_MAP[target].supported_toolchains if target in TARGET_MAP else None
screamer 0:66f3b5499f7f 758
screamer 0:66f3b5499f7f 759
screamer 0:66f3b5499f7f 760 def static_analysis_scan(target, toolchain_name, CPPCHECK_CMD, CPPCHECK_MSG_FORMAT, options=None, verbose=False, clean=False, macros=None, notify=None, jobs=1, extra_verbose=False):
screamer 0:66f3b5499f7f 761 # Toolchain
screamer 0:66f3b5499f7f 762 toolchain = TOOLCHAIN_CLASSES[toolchain_name](target, options, macros=macros, notify=notify, extra_verbose=extra_verbose)
screamer 0:66f3b5499f7f 763 toolchain.VERBOSE = verbose
screamer 0:66f3b5499f7f 764 toolchain.jobs = jobs
screamer 0:66f3b5499f7f 765 toolchain.build_all = clean
screamer 0:66f3b5499f7f 766
screamer 0:66f3b5499f7f 767 # Source and Build Paths
screamer 0:66f3b5499f7f 768 BUILD_TARGET = join(MBED_LIBRARIES, "TARGET_" + target.name)
screamer 0:66f3b5499f7f 769 BUILD_TOOLCHAIN = join(BUILD_TARGET, "TOOLCHAIN_" + toolchain.name)
screamer 0:66f3b5499f7f 770 mkdir(BUILD_TOOLCHAIN)
screamer 0:66f3b5499f7f 771
screamer 0:66f3b5499f7f 772 TMP_PATH = join(MBED_LIBRARIES, '.temp', toolchain.obj_path)
screamer 0:66f3b5499f7f 773 mkdir(TMP_PATH)
screamer 0:66f3b5499f7f 774
screamer 0:66f3b5499f7f 775 # CMSIS
screamer 0:66f3b5499f7f 776 toolchain.info("Static analysis for %s (%s, %s)" % ('CMSIS', target.name, toolchain_name))
screamer 0:66f3b5499f7f 777 cmsis_src = join(MBED_TARGETS_PATH, "cmsis")
screamer 0:66f3b5499f7f 778 resources = toolchain.scan_resources(cmsis_src)
screamer 0:66f3b5499f7f 779
screamer 0:66f3b5499f7f 780 # Copy files before analysis
screamer 0:66f3b5499f7f 781 toolchain.copy_files(resources.headers, BUILD_TARGET)
screamer 0:66f3b5499f7f 782 toolchain.copy_files(resources.linker_script, BUILD_TOOLCHAIN)
screamer 0:66f3b5499f7f 783
screamer 0:66f3b5499f7f 784 # Gather include paths, c, cpp sources and macros to transfer to cppcheck command line
screamer 0:66f3b5499f7f 785 includes = ["-I%s"% i for i in resources.inc_dirs]
screamer 0:66f3b5499f7f 786 includes.append("-I%s"% str(BUILD_TARGET))
screamer 0:66f3b5499f7f 787 c_sources = " ".join(resources.c_sources)
screamer 0:66f3b5499f7f 788 cpp_sources = " ".join(resources.cpp_sources)
screamer 0:66f3b5499f7f 789 macros = ["-D%s"% s for s in toolchain.get_symbols() + toolchain.macros]
screamer 0:66f3b5499f7f 790
screamer 0:66f3b5499f7f 791 includes = map(str.strip, includes)
screamer 0:66f3b5499f7f 792 macros = map(str.strip, macros)
screamer 0:66f3b5499f7f 793
screamer 0:66f3b5499f7f 794 check_cmd = CPPCHECK_CMD
screamer 0:66f3b5499f7f 795 check_cmd += CPPCHECK_MSG_FORMAT
screamer 0:66f3b5499f7f 796 check_cmd += includes
screamer 0:66f3b5499f7f 797 check_cmd += macros
screamer 0:66f3b5499f7f 798
screamer 0:66f3b5499f7f 799 # We need to pass some params via file to avoid "command line too long in some OSs"
screamer 0:66f3b5499f7f 800 tmp_file = tempfile.NamedTemporaryFile(delete=False)
screamer 0:66f3b5499f7f 801 tmp_file.writelines(line + '\n' for line in c_sources.split())
screamer 0:66f3b5499f7f 802 tmp_file.writelines(line + '\n' for line in cpp_sources.split())
screamer 0:66f3b5499f7f 803 tmp_file.close()
screamer 0:66f3b5499f7f 804 check_cmd += ["--file-list=%s"% tmp_file.name]
screamer 0:66f3b5499f7f 805
screamer 0:66f3b5499f7f 806 _stdout, _stderr, _rc = run_cmd(check_cmd)
screamer 0:66f3b5499f7f 807 if verbose:
screamer 0:66f3b5499f7f 808 print _stdout
screamer 0:66f3b5499f7f 809 print _stderr
screamer 0:66f3b5499f7f 810
screamer 0:66f3b5499f7f 811 # =========================================================================
screamer 0:66f3b5499f7f 812
screamer 0:66f3b5499f7f 813 # MBED
screamer 0:66f3b5499f7f 814 toolchain.info("Static analysis for %s (%s, %s)" % ('MBED', target.name, toolchain_name))
screamer 0:66f3b5499f7f 815
screamer 0:66f3b5499f7f 816 # Common Headers
screamer 0:66f3b5499f7f 817 toolchain.copy_files(toolchain.scan_resources(MBED_API).headers, MBED_LIBRARIES)
screamer 0:66f3b5499f7f 818 toolchain.copy_files(toolchain.scan_resources(MBED_HAL).headers, MBED_LIBRARIES)
screamer 0:66f3b5499f7f 819
screamer 0:66f3b5499f7f 820 # Target specific sources
screamer 0:66f3b5499f7f 821 HAL_SRC = join(MBED_TARGETS_PATH, "hal")
screamer 0:66f3b5499f7f 822 hal_implementation = toolchain.scan_resources(HAL_SRC)
screamer 0:66f3b5499f7f 823
screamer 0:66f3b5499f7f 824 # Copy files before analysis
screamer 13:ab47a20b66f0 825 toolchain.copy_files(hal_implementation.headers + hal_implementation.hex_files, BUILD_TARGET, resources=hal_implementation)
screamer 0:66f3b5499f7f 826 incdirs = toolchain.scan_resources(BUILD_TARGET)
screamer 0:66f3b5499f7f 827
screamer 0:66f3b5499f7f 828 target_includes = ["-I%s" % i for i in incdirs.inc_dirs]
screamer 0:66f3b5499f7f 829 target_includes.append("-I%s"% str(BUILD_TARGET))
screamer 0:66f3b5499f7f 830 target_includes.append("-I%s"% str(HAL_SRC))
screamer 0:66f3b5499f7f 831 target_c_sources = " ".join(incdirs.c_sources)
screamer 0:66f3b5499f7f 832 target_cpp_sources = " ".join(incdirs.cpp_sources)
screamer 0:66f3b5499f7f 833 target_macros = ["-D%s"% s for s in toolchain.get_symbols() + toolchain.macros]
screamer 0:66f3b5499f7f 834
screamer 0:66f3b5499f7f 835 # Common Sources
screamer 0:66f3b5499f7f 836 mbed_resources = toolchain.scan_resources(MBED_COMMON)
screamer 0:66f3b5499f7f 837
screamer 0:66f3b5499f7f 838 # Gather include paths, c, cpp sources and macros to transfer to cppcheck command line
screamer 0:66f3b5499f7f 839 mbed_includes = ["-I%s" % i for i in mbed_resources.inc_dirs]
screamer 0:66f3b5499f7f 840 mbed_includes.append("-I%s"% str(BUILD_TARGET))
screamer 0:66f3b5499f7f 841 mbed_includes.append("-I%s"% str(MBED_COMMON))
screamer 0:66f3b5499f7f 842 mbed_includes.append("-I%s"% str(MBED_API))
screamer 0:66f3b5499f7f 843 mbed_includes.append("-I%s"% str(MBED_HAL))
screamer 0:66f3b5499f7f 844 mbed_c_sources = " ".join(mbed_resources.c_sources)
screamer 0:66f3b5499f7f 845 mbed_cpp_sources = " ".join(mbed_resources.cpp_sources)
screamer 0:66f3b5499f7f 846
screamer 0:66f3b5499f7f 847 target_includes = map(str.strip, target_includes)
screamer 0:66f3b5499f7f 848 mbed_includes = map(str.strip, mbed_includes)
screamer 0:66f3b5499f7f 849 target_macros = map(str.strip, target_macros)
screamer 0:66f3b5499f7f 850
screamer 0:66f3b5499f7f 851 check_cmd = CPPCHECK_CMD
screamer 0:66f3b5499f7f 852 check_cmd += CPPCHECK_MSG_FORMAT
screamer 0:66f3b5499f7f 853 check_cmd += target_includes
screamer 0:66f3b5499f7f 854 check_cmd += mbed_includes
screamer 0:66f3b5499f7f 855 check_cmd += target_macros
screamer 0:66f3b5499f7f 856
screamer 0:66f3b5499f7f 857 # We need to pass some parames via file to avoid "command line too long in some OSs"
screamer 0:66f3b5499f7f 858 tmp_file = tempfile.NamedTemporaryFile(delete=False)
screamer 0:66f3b5499f7f 859 tmp_file.writelines(line + '\n' for line in target_c_sources.split())
screamer 0:66f3b5499f7f 860 tmp_file.writelines(line + '\n' for line in target_cpp_sources.split())
screamer 0:66f3b5499f7f 861 tmp_file.writelines(line + '\n' for line in mbed_c_sources.split())
screamer 0:66f3b5499f7f 862 tmp_file.writelines(line + '\n' for line in mbed_cpp_sources.split())
screamer 0:66f3b5499f7f 863 tmp_file.close()
screamer 0:66f3b5499f7f 864 check_cmd += ["--file-list=%s"% tmp_file.name]
screamer 0:66f3b5499f7f 865
screamer 0:66f3b5499f7f 866 _stdout, _stderr, _rc = run_cmd_ext(check_cmd)
screamer 0:66f3b5499f7f 867 if verbose:
screamer 0:66f3b5499f7f 868 print _stdout
screamer 0:66f3b5499f7f 869 print _stderr
screamer 0:66f3b5499f7f 870
screamer 0:66f3b5499f7f 871
screamer 0:66f3b5499f7f 872 def static_analysis_scan_lib(lib_id, target, toolchain, cppcheck_cmd, cppcheck_msg_format,
screamer 0:66f3b5499f7f 873 options=None, verbose=False, clean=False, macros=None, notify=None, jobs=1, extra_verbose=False):
screamer 0:66f3b5499f7f 874 lib = Library(lib_id)
screamer 0:66f3b5499f7f 875 if lib.is_supported(target, toolchain):
screamer 0:66f3b5499f7f 876 static_analysis_scan_library(lib.source_dir, lib.build_dir, target, toolchain, cppcheck_cmd, cppcheck_msg_format,
screamer 0:66f3b5499f7f 877 lib.dependencies, options,
screamer 0:66f3b5499f7f 878 verbose=verbose, clean=clean, macros=macros, notify=notify, jobs=jobs, extra_verbose=extra_verbose)
screamer 0:66f3b5499f7f 879 else:
screamer 0:66f3b5499f7f 880 print 'Library "%s" is not yet supported on target %s with toolchain %s'% (lib_id, target.name, toolchain)
screamer 0:66f3b5499f7f 881
screamer 0:66f3b5499f7f 882
screamer 0:66f3b5499f7f 883 def static_analysis_scan_library(src_paths, build_path, target, toolchain_name, cppcheck_cmd, cppcheck_msg_format,
screamer 0:66f3b5499f7f 884 dependencies_paths=None, options=None, name=None, clean=False,
screamer 0:66f3b5499f7f 885 notify=None, verbose=False, macros=None, jobs=1, extra_verbose=False):
screamer 0:66f3b5499f7f 886 """ Function scans library (or just some set of sources/headers) for staticly detectable defects """
screamer 0:66f3b5499f7f 887 if type(src_paths) != ListType:
screamer 0:66f3b5499f7f 888 src_paths = [src_paths]
screamer 0:66f3b5499f7f 889
screamer 0:66f3b5499f7f 890 for src_path in src_paths:
screamer 0:66f3b5499f7f 891 if not exists(src_path):
screamer 0:66f3b5499f7f 892 raise Exception("The library source folder does not exist: %s", src_path)
screamer 0:66f3b5499f7f 893
screamer 0:66f3b5499f7f 894 # Toolchain instance
screamer 0:66f3b5499f7f 895 toolchain = TOOLCHAIN_CLASSES[toolchain_name](target, options, macros=macros, notify=notify, extra_verbose=extra_verbose)
screamer 0:66f3b5499f7f 896 toolchain.VERBOSE = verbose
screamer 0:66f3b5499f7f 897 toolchain.jobs = jobs
screamer 0:66f3b5499f7f 898
screamer 0:66f3b5499f7f 899 # The first path will give the name to the library
screamer 0:66f3b5499f7f 900 name = basename(src_paths[0])
screamer 0:66f3b5499f7f 901 toolchain.info("Static analysis for library %s (%s, %s)" % (name.upper(), target.name, toolchain_name))
screamer 0:66f3b5499f7f 902
screamer 0:66f3b5499f7f 903 # Scan Resources
screamer 0:66f3b5499f7f 904 resources = []
screamer 0:66f3b5499f7f 905 for src_path in src_paths:
screamer 0:66f3b5499f7f 906 resources.append(toolchain.scan_resources(src_path))
screamer 0:66f3b5499f7f 907
screamer 0:66f3b5499f7f 908 # Dependencies Include Paths
screamer 0:66f3b5499f7f 909 dependencies_include_dir = []
screamer 0:66f3b5499f7f 910 if dependencies_paths is not None:
screamer 0:66f3b5499f7f 911 for path in dependencies_paths:
screamer 0:66f3b5499f7f 912 lib_resources = toolchain.scan_resources(path)
screamer 0:66f3b5499f7f 913 dependencies_include_dir.extend(lib_resources.inc_dirs)
screamer 0:66f3b5499f7f 914
screamer 0:66f3b5499f7f 915 # Create the desired build directory structure
screamer 0:66f3b5499f7f 916 bin_path = join(build_path, toolchain.obj_path)
screamer 0:66f3b5499f7f 917 mkdir(bin_path)
screamer 0:66f3b5499f7f 918 tmp_path = join(build_path, '.temp', toolchain.obj_path)
screamer 0:66f3b5499f7f 919 mkdir(tmp_path)
screamer 0:66f3b5499f7f 920
screamer 0:66f3b5499f7f 921 # Gather include paths, c, cpp sources and macros to transfer to cppcheck command line
screamer 0:66f3b5499f7f 922 includes = ["-I%s" % i for i in dependencies_include_dir + src_paths]
screamer 0:66f3b5499f7f 923 c_sources = " "
screamer 0:66f3b5499f7f 924 cpp_sources = " "
screamer 0:66f3b5499f7f 925 macros = ['-D%s' % s for s in toolchain.get_symbols() + toolchain.macros]
screamer 0:66f3b5499f7f 926
screamer 0:66f3b5499f7f 927 # Copy Headers
screamer 0:66f3b5499f7f 928 for resource in resources:
screamer 13:ab47a20b66f0 929 toolchain.copy_files(resource.headers, build_path, resources=resource)
screamer 0:66f3b5499f7f 930 includes += ["-I%s" % i for i in resource.inc_dirs]
screamer 0:66f3b5499f7f 931 c_sources += " ".join(resource.c_sources) + " "
screamer 0:66f3b5499f7f 932 cpp_sources += " ".join(resource.cpp_sources) + " "
screamer 0:66f3b5499f7f 933
screamer 0:66f3b5499f7f 934 dependencies_include_dir.extend(toolchain.scan_resources(build_path).inc_dirs)
screamer 0:66f3b5499f7f 935
screamer 0:66f3b5499f7f 936 includes = map(str.strip, includes)
screamer 0:66f3b5499f7f 937 macros = map(str.strip, macros)
screamer 0:66f3b5499f7f 938
screamer 0:66f3b5499f7f 939 check_cmd = cppcheck_cmd
screamer 0:66f3b5499f7f 940 check_cmd += cppcheck_msg_format
screamer 0:66f3b5499f7f 941 check_cmd += includes
screamer 0:66f3b5499f7f 942 check_cmd += macros
screamer 0:66f3b5499f7f 943
screamer 0:66f3b5499f7f 944 # We need to pass some parameters via file to avoid "command line too long in some OSs"
screamer 0:66f3b5499f7f 945 # Temporary file is created to store e.g. cppcheck list of files for command line
screamer 0:66f3b5499f7f 946 tmp_file = tempfile.NamedTemporaryFile(delete=False)
screamer 0:66f3b5499f7f 947 tmp_file.writelines(line + '\n' for line in c_sources.split())
screamer 0:66f3b5499f7f 948 tmp_file.writelines(line + '\n' for line in cpp_sources.split())
screamer 0:66f3b5499f7f 949 tmp_file.close()
screamer 0:66f3b5499f7f 950 check_cmd += ["--file-list=%s"% tmp_file.name]
screamer 0:66f3b5499f7f 951
screamer 0:66f3b5499f7f 952 # This will allow us to grab result from both stdio and stderr outputs (so we can show them)
screamer 0:66f3b5499f7f 953 # We assume static code analysis tool is outputting defects on STDERR
screamer 0:66f3b5499f7f 954 _stdout, _stderr, _rc = run_cmd_ext(check_cmd)
screamer 0:66f3b5499f7f 955 if verbose:
screamer 0:66f3b5499f7f 956 print _stdout
screamer 0:66f3b5499f7f 957 print _stderr
screamer 0:66f3b5499f7f 958
screamer 0:66f3b5499f7f 959
screamer 0:66f3b5499f7f 960 def print_build_results(result_list, build_name):
screamer 0:66f3b5499f7f 961 """ Generate result string for build results """
screamer 0:66f3b5499f7f 962 result = ""
screamer 0:66f3b5499f7f 963 if len(result_list) > 0:
screamer 0:66f3b5499f7f 964 result += build_name + "\n"
screamer 0:66f3b5499f7f 965 result += "\n".join([" * %s" % f for f in result_list])
screamer 0:66f3b5499f7f 966 result += "\n"
screamer 0:66f3b5499f7f 967 return result
screamer 0:66f3b5499f7f 968
screamer 22:9e85236d8716 969 def print_build_memory_usage_results(report):
screamer 22:9e85236d8716 970 """ Generate result table with memory usage values for build results
screamer 22:9e85236d8716 971 Agregates (puts together) reports obtained from self.get_memory_summary()
screamer 22:9e85236d8716 972 @param report Report generated during build procedure. See
screamer 22:9e85236d8716 973 """
screamer 22:9e85236d8716 974 from prettytable import PrettyTable
screamer 22:9e85236d8716 975 columns_text = ['name', 'target', 'toolchain']
screamer 22:9e85236d8716 976 columns_int = ['static_ram', 'stack', 'heap', 'total_ram', 'total_flash']
screamer 22:9e85236d8716 977 table = PrettyTable(columns_text + columns_int)
screamer 22:9e85236d8716 978
screamer 22:9e85236d8716 979 for col in columns_text:
screamer 22:9e85236d8716 980 table.align[col] = 'l'
screamer 22:9e85236d8716 981
screamer 22:9e85236d8716 982 for col in columns_int:
screamer 22:9e85236d8716 983 table.align[col] = 'r'
screamer 22:9e85236d8716 984
screamer 22:9e85236d8716 985 for target in report:
screamer 22:9e85236d8716 986 for toolchain in report[target]:
screamer 22:9e85236d8716 987 for name in report[target][toolchain]:
screamer 22:9e85236d8716 988 for dlist in report[target][toolchain][name]:
screamer 22:9e85236d8716 989 for dlistelem in dlist:
screamer 22:9e85236d8716 990 # Get 'memory_usage' record and build table with statistics
screamer 22:9e85236d8716 991 record = dlist[dlistelem]
screamer 22:9e85236d8716 992 if 'memory_usage' in record and record['memory_usage']:
screamer 22:9e85236d8716 993 # Note that summary should be in the last record of
screamer 22:9e85236d8716 994 # 'memory_usage' section. This is why we are grabbing
screamer 22:9e85236d8716 995 # last "[-1]" record.
screamer 22:9e85236d8716 996 row = [
screamer 22:9e85236d8716 997 record['description'],
screamer 22:9e85236d8716 998 record['target_name'],
screamer 22:9e85236d8716 999 record['toolchain_name'],
screamer 22:9e85236d8716 1000 record['memory_usage'][-1]['summary']['static_ram'],
screamer 22:9e85236d8716 1001 record['memory_usage'][-1]['summary']['stack'],
screamer 22:9e85236d8716 1002 record['memory_usage'][-1]['summary']['heap'],
screamer 22:9e85236d8716 1003 record['memory_usage'][-1]['summary']['total_ram'],
screamer 22:9e85236d8716 1004 record['memory_usage'][-1]['summary']['total_flash'],
screamer 22:9e85236d8716 1005 ]
screamer 22:9e85236d8716 1006 table.add_row(row)
screamer 22:9e85236d8716 1007
screamer 22:9e85236d8716 1008 result = "Memory map breakdown for built projects (values in Bytes):\n"
screamer 22:9e85236d8716 1009 result += table.get_string(sortby='name')
screamer 22:9e85236d8716 1010 return result
screamer 22:9e85236d8716 1011
screamer 0:66f3b5499f7f 1012 def write_build_report(build_report, template_filename, filename):
screamer 0:66f3b5499f7f 1013 build_report_failing = []
screamer 0:66f3b5499f7f 1014 build_report_passing = []
screamer 0:66f3b5499f7f 1015
screamer 0:66f3b5499f7f 1016 for report in build_report:
screamer 0:66f3b5499f7f 1017 if len(report["failing"]) > 0:
screamer 0:66f3b5499f7f 1018 build_report_failing.append(report)
screamer 0:66f3b5499f7f 1019 else:
screamer 0:66f3b5499f7f 1020 build_report_passing.append(report)
screamer 0:66f3b5499f7f 1021
screamer 0:66f3b5499f7f 1022 env = Environment(extensions=['jinja2.ext.with_'])
screamer 0:66f3b5499f7f 1023 env.loader = FileSystemLoader('ci_templates')
screamer 0:66f3b5499f7f 1024 template = env.get_template(template_filename)
screamer 0:66f3b5499f7f 1025
screamer 0:66f3b5499f7f 1026 with open(filename, 'w+') as f:
screamer 0:66f3b5499f7f 1027 f.write(template.render(failing_builds=build_report_failing, passing_builds=build_report_passing))
screamer 1:a99c8e460c5c 1028
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 1029
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 1030 def scan_for_source_paths(path, exclude_paths=None):
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 1031 ignorepatterns = []
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 1032 paths = []
screamer 22:9e85236d8716 1033
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 1034 def is_ignored(file_path):
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 1035 for pattern in ignorepatterns:
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 1036 if fnmatch.fnmatch(file_path, pattern):
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 1037 return True
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 1038 return False
screamer 22:9e85236d8716 1039
screamer 22:9e85236d8716 1040
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 1041 """ os.walk(top[, topdown=True[, onerror=None[, followlinks=False]]])
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 1042 When topdown is True, the caller can modify the dirnames list in-place
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 1043 (perhaps using del or slice assignment), and walk() will only recurse into
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 1044 the subdirectories whose names remain in dirnames; this can be used to prune
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 1045 the search, impose a specific order of visiting, or even to inform walk()
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 1046 about directories the caller creates or renames before it resumes walk()
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 1047 again. Modifying dirnames when topdown is False is ineffective, because in
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 1048 bottom-up mode the directories in dirnames are generated before dirpath
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 1049 itself is generated.
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 1050 """
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 1051 for root, dirs, files in walk(path, followlinks=True):
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 1052 # Remove ignored directories
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 1053 # Check if folder contains .mbedignore
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 1054 if ".mbedignore" in files :
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 1055 with open (join(root,".mbedignore"), "r") as f:
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 1056 lines=f.readlines()
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 1057 lines = [l.strip() for l in lines] # Strip whitespaces
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 1058 lines = [l for l in lines if l != ""] # Strip empty lines
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 1059 lines = [l for l in lines if not re.match("^#",l)] # Strip comment lines
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 1060 # Append root path to glob patterns
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 1061 # and append patterns to ignorepatterns
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 1062 ignorepatterns.extend([join(root,line.strip()) for line in lines])
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 1063
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 1064 for d in copy(dirs):
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 1065 dir_path = join(root, d)
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 1066
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 1067 # Always ignore hidden directories
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 1068 if d.startswith('.'):
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 1069 dirs.remove(d)
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 1070
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 1071 # Remove dirs that already match the ignorepatterns
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 1072 # to avoid travelling into them and to prevent them
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 1073 # on appearing in include path.
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 1074 if is_ignored(join(dir_path,"")):
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 1075 dirs.remove(d)
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 1076
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 1077 if exclude_paths:
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 1078 for exclude_path in exclude_paths:
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 1079 rel_path = relpath(dir_path, exclude_path)
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 1080 if not (rel_path.startswith('..')):
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 1081 dirs.remove(d)
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 1082 break
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 1083
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 1084 # Add root to include paths
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 1085 paths.append(root)
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 1086
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 1087 return paths