Clone of official tools

Committer:
screamer
Date:
Mon Aug 01 09:10:17 2016 +0100
Revision:
24:25bff2709c20
Parent:
22:9e85236d8716
Child:
27:5461402c33f8
Major update to tools from ARMmbed/mbed-os

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