Clone of official tools

Committer:
screamer
Date:
Mon Aug 29 10:55:24 2016 +0100
Revision:
27:5461402c33f8
Parent:
24:25bff2709c20
Child:
29:1210849dba19
Differentiate legacy targets.json (rev <= 121) and post mbed 5.0

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 27:5461402c33f8 329 if profile:
screamer 27:5461402c33f8 330 targets_json = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'legacy_targets.json')
screamer 27:5461402c33f8 331 else:
screamer 27:5461402c33f8 332 targets_json = find_targets_json(path) or targets_json
screamer 14:ee1b877e6839 333
screamer 24:25bff2709c20 334 # Apply targets.json to active targets
screamer 24:25bff2709c20 335 if targets_json:
screamer 24:25bff2709c20 336 if verbose:
screamer 24:25bff2709c20 337 print("Using targets from %s" % targets_json)
screamer 24:25bff2709c20 338 set_targets_json_location(targets_json)
screamer 24:25bff2709c20 339
screamer 24:25bff2709c20 340 # Apply profile to toolchains
screamer 14:ee1b877e6839 341 if profile:
screamer 14:ee1b877e6839 342 def init_hook(self):
screamer 14:ee1b877e6839 343 profile_data = get_toolchain_profile(self.name, profile)
screamer 14:ee1b877e6839 344 if not profile_data:
screamer 14:ee1b877e6839 345 return
screamer 24:25bff2709c20 346 if verbose:
screamer 24:25bff2709c20 347 self.info("Using toolchain %s profile %s" % (self.name, profile))
screamer 14:ee1b877e6839 348
screamer 14:ee1b877e6839 349 for k,v in profile_data.items():
screamer 14:ee1b877e6839 350 if self.flags.has_key(k):
screamer 14:ee1b877e6839 351 self.flags[k] = v
screamer 14:ee1b877e6839 352 else:
screamer 14:ee1b877e6839 353 setattr(self, k, v)
screamer 14:ee1b877e6839 354
screamer 14:ee1b877e6839 355 mbedToolchain.init = init_hook
screamer 14:ee1b877e6839 356
screamer 24:25bff2709c20 357 # Pass all params to the unified prepare_toolchain()
screamer 24:25bff2709c20 358 toolchain = prepare_toolchain(src_paths, target, toolchain_name,
screamer 24:25bff2709c20 359 macros=macros, options=options, clean=clean, jobs=jobs,
screamer 24:25bff2709c20 360 notify=notify, silent=silent, verbose=verbose, extra_verbose=extra_verbose, config=config)
screamer 0:66f3b5499f7f 361
screamer 24:25bff2709c20 362 # The first path will give the name to the library
screamer 0:66f3b5499f7f 363 if name is None:
screamer 24:25bff2709c20 364 name = basename(normpath(abspath(src_paths[0])))
screamer 24:25bff2709c20 365 toolchain.info("Building project %s (%s, %s)" % (name, toolchain.target.name, toolchain_name))
screamer 0:66f3b5499f7f 366
screamer 24:25bff2709c20 367 # Initialize reporting
screamer 0:66f3b5499f7f 368 if report != None:
screamer 0:66f3b5499f7f 369 start = time()
screamer 7:5af61d55adbe 370 # If project_id is specified, use that over the default name
screamer 7:5af61d55adbe 371 id_name = project_id.upper() if project_id else name.upper()
screamer 7:5af61d55adbe 372 description = project_description if project_description else name
screamer 24:25bff2709c20 373 vendor_label = toolchain.target.extra_labels[0]
screamer 24:25bff2709c20 374 prep_report(report, toolchain.target.name, toolchain_name, id_name)
screamer 24:25bff2709c20 375 cur_result = create_result(toolchain.target.name, toolchain_name, id_name, description)
screamer 0:66f3b5499f7f 376 if properties != None:
screamer 24:25bff2709c20 377 prep_properties(properties, toolchain.target.name, toolchain_name, vendor_label)
screamer 0:66f3b5499f7f 378
screamer 0:66f3b5499f7f 379 try:
screamer 24:25bff2709c20 380 # Call unified scan_resources
screamer 24:25bff2709c20 381 resources = scan_resources(src_paths, toolchain, inc_dirs=inc_dirs)
screamer 0:66f3b5499f7f 382
screamer 24:25bff2709c20 383 # Change linker script if specified
screamer 0:66f3b5499f7f 384 if linker_script is not None:
screamer 0:66f3b5499f7f 385 resources.linker_script = linker_script
screamer 0:66f3b5499f7f 386
screamer 0:66f3b5499f7f 387 # Compile Sources
screamer 13:ab47a20b66f0 388 objects = toolchain.compile_sources(resources, build_path, resources.inc_dirs)
screamer 13:ab47a20b66f0 389 resources.objects.extend(objects)
screamer 0:66f3b5499f7f 390
screamer 0:66f3b5499f7f 391 # Link Program
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 392 res, _ = toolchain.link_program(resources, build_path, name)
screamer 0:66f3b5499f7f 393
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 394 if report != None:
screamer 0:66f3b5499f7f 395 end = time()
screamer 0:66f3b5499f7f 396 cur_result["elapsed_time"] = end - start
screamer 0:66f3b5499f7f 397 cur_result["output"] = toolchain.get_output()
screamer 0:66f3b5499f7f 398 cur_result["result"] = "OK"
screamer 22:9e85236d8716 399 cur_result["memory_usage"] = toolchain.map_outputs
screamer 0:66f3b5499f7f 400
screamer 0:66f3b5499f7f 401 add_result_to_report(report, cur_result)
screamer 0:66f3b5499f7f 402
screamer 0:66f3b5499f7f 403 return res
screamer 0:66f3b5499f7f 404
screamer 0:66f3b5499f7f 405 except Exception, e:
screamer 0:66f3b5499f7f 406 if report != None:
screamer 0:66f3b5499f7f 407 end = time()
screamer 0:66f3b5499f7f 408
screamer 0:66f3b5499f7f 409 if isinstance(e, NotSupportedException):
screamer 0:66f3b5499f7f 410 cur_result["result"] = "NOT_SUPPORTED"
screamer 0:66f3b5499f7f 411 else:
screamer 0:66f3b5499f7f 412 cur_result["result"] = "FAIL"
screamer 0:66f3b5499f7f 413
screamer 0:66f3b5499f7f 414 cur_result["elapsed_time"] = end - start
screamer 0:66f3b5499f7f 415
screamer 0:66f3b5499f7f 416 toolchain_output = toolchain.get_output()
screamer 0:66f3b5499f7f 417 if toolchain_output:
screamer 0:66f3b5499f7f 418 cur_result["output"] += toolchain_output
screamer 0:66f3b5499f7f 419
screamer 0:66f3b5499f7f 420 add_result_to_report(report, cur_result)
screamer 0:66f3b5499f7f 421
screamer 0:66f3b5499f7f 422 # Let Exception propagate
screamer 13:ab47a20b66f0 423 raise
screamer 0:66f3b5499f7f 424
screamer 0:66f3b5499f7f 425 def build_library(src_paths, build_path, target, toolchain_name,
screamer 0:66f3b5499f7f 426 dependencies_paths=None, options=None, name=None, clean=False, archive=True,
screamer 24:25bff2709c20 427 notify=None, verbose=False, macros=None, inc_dirs=None,
screamer 7:5af61d55adbe 428 jobs=1, silent=False, report=None, properties=None, extra_verbose=False,
screamer 7:5af61d55adbe 429 project_id=None):
screamer 24:25bff2709c20 430 """ Prepares resource related objects - toolchain, target, config
screamer 24:25bff2709c20 431 src_paths: the paths to source directories
screamer 0:66f3b5499f7f 432 build_path: the path of the build directory
screamer 0:66f3b5499f7f 433 target: ['LPC1768', 'LPC11U24', 'LPC2368']
screamer 24:25bff2709c20 434 toolchain_name: ['ARM', 'uARM', 'GCC_ARM', 'GCC_CR']
screamer 0:66f3b5499f7f 435 clean: Rebuild everything if True
screamer 0:66f3b5499f7f 436 notify: Notify function for logs
screamer 0:66f3b5499f7f 437 verbose: Write the actual tools command lines if True
screamer 0:66f3b5499f7f 438 inc_dirs: additional include directories which should be included in build
screamer 0:66f3b5499f7f 439 """
screamer 24:25bff2709c20 440
screamer 24:25bff2709c20 441 # Convert src_path to a list if needed
screamer 0:66f3b5499f7f 442 if type(src_paths) != ListType:
screamer 0:66f3b5499f7f 443 src_paths = [src_paths]
screamer 0:66f3b5499f7f 444
screamer 24:25bff2709c20 445 # Build path
screamer 24:25bff2709c20 446 if archive:
screamer 24:25bff2709c20 447 # Use temp path when building archive
screamer 24:25bff2709c20 448 tmp_path = join(build_path, '.temp')
screamer 24:25bff2709c20 449 mkdir(tmp_path)
screamer 24:25bff2709c20 450 else:
screamer 24:25bff2709c20 451 tmp_path = build_path
screamer 0:66f3b5499f7f 452
screamer 24:25bff2709c20 453 # Pass all params to the unified prepare_toolchain()
screamer 24:25bff2709c20 454 toolchain = prepare_toolchain(src_paths, target, toolchain_name,
screamer 24:25bff2709c20 455 macros=macros, options=options, clean=clean, jobs=jobs,
screamer 24:25bff2709c20 456 notify=notify, silent=silent, verbose=verbose, extra_verbose=extra_verbose)
screamer 13:ab47a20b66f0 457
screamer 24:25bff2709c20 458 # The first path will give the name to the library
screamer 24:25bff2709c20 459 if name is None:
screamer 24:25bff2709c20 460 name = basename(normpath(abspath(src_paths[0])))
screamer 24:25bff2709c20 461 toolchain.info("Building library %s (%s, %s)" % (name, toolchain.target.name, toolchain_name))
screamer 13:ab47a20b66f0 462
screamer 24:25bff2709c20 463 # Initialize reporting
screamer 0:66f3b5499f7f 464 if report != None:
screamer 0:66f3b5499f7f 465 start = time()
screamer 7:5af61d55adbe 466 # If project_id is specified, use that over the default name
screamer 7:5af61d55adbe 467 id_name = project_id.upper() if project_id else name.upper()
screamer 0:66f3b5499f7f 468 description = name
screamer 24:25bff2709c20 469 vendor_label = toolchain.target.extra_labels[0]
screamer 24:25bff2709c20 470 prep_report(report, toolchain.target.name, toolchain_name, id_name)
screamer 24:25bff2709c20 471 cur_result = create_result(toolchain.target.name, toolchain_name, id_name, description)
screamer 0:66f3b5499f7f 472 if properties != None:
screamer 24:25bff2709c20 473 prep_properties(properties, toolchain.target.name, toolchain_name, vendor_label)
screamer 0:66f3b5499f7f 474
screamer 0:66f3b5499f7f 475 for src_path in src_paths:
screamer 0:66f3b5499f7f 476 if not exists(src_path):
screamer 0:66f3b5499f7f 477 error_msg = "The library source folder does not exist: %s", src_path
screamer 0:66f3b5499f7f 478 if report != None:
screamer 0:66f3b5499f7f 479 cur_result["output"] = error_msg
screamer 0:66f3b5499f7f 480 cur_result["result"] = "FAIL"
screamer 0:66f3b5499f7f 481 add_result_to_report(report, cur_result)
screamer 0:66f3b5499f7f 482 raise Exception(error_msg)
screamer 0:66f3b5499f7f 483
screamer 0:66f3b5499f7f 484 try:
screamer 24:25bff2709c20 485 # Call unified scan_resources
screamer 24:25bff2709c20 486 resources = scan_resources(src_paths, toolchain, dependencies_paths=dependencies_paths, inc_dirs=inc_dirs)
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 487
screamer 13:ab47a20b66f0 488
screamer 13:ab47a20b66f0 489 # Copy headers, objects and static libraries - all files needed for static lib
screamer 13:ab47a20b66f0 490 toolchain.copy_files(resources.headers, build_path, resources=resources)
screamer 13:ab47a20b66f0 491 toolchain.copy_files(resources.objects, build_path, resources=resources)
screamer 13:ab47a20b66f0 492 toolchain.copy_files(resources.libraries, build_path, resources=resources)
screamer 13:ab47a20b66f0 493 if resources.linker_script:
screamer 13:ab47a20b66f0 494 toolchain.copy_files(resources.linker_script, build_path, resources=resources)
screamer 22:9e85236d8716 495
screamer 24:25bff2709c20 496 if resources.hex_files:
screamer 13:ab47a20b66f0 497 toolchain.copy_files(resources.hex_files, build_path, resources=resources)
screamer 0:66f3b5499f7f 498
screamer 0:66f3b5499f7f 499 # Compile Sources
screamer 13:ab47a20b66f0 500 objects = toolchain.compile_sources(resources, abspath(tmp_path), resources.inc_dirs)
screamer 13:ab47a20b66f0 501 resources.objects.extend(objects)
screamer 0:66f3b5499f7f 502
screamer 0:66f3b5499f7f 503 if archive:
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 504 toolchain.build_library(objects, build_path, name)
screamer 0:66f3b5499f7f 505
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 506 if report != None:
screamer 0:66f3b5499f7f 507 end = time()
screamer 0:66f3b5499f7f 508 cur_result["elapsed_time"] = end - start
screamer 0:66f3b5499f7f 509 cur_result["output"] = toolchain.get_output()
screamer 0:66f3b5499f7f 510 cur_result["result"] = "OK"
screamer 0:66f3b5499f7f 511
screamer 0:66f3b5499f7f 512 add_result_to_report(report, cur_result)
screamer 22:9e85236d8716 513 return True
screamer 0:66f3b5499f7f 514
screamer 0:66f3b5499f7f 515 except Exception, e:
screamer 0:66f3b5499f7f 516 if report != None:
screamer 0:66f3b5499f7f 517 end = time()
screamer 22:9e85236d8716 518
screamer 7:5af61d55adbe 519 if isinstance(e, ToolException):
screamer 7:5af61d55adbe 520 cur_result["result"] = "FAIL"
screamer 7:5af61d55adbe 521 elif isinstance(e, NotSupportedException):
screamer 7:5af61d55adbe 522 cur_result["result"] = "NOT_SUPPORTED"
screamer 22:9e85236d8716 523
screamer 0:66f3b5499f7f 524 cur_result["elapsed_time"] = end - start
screamer 0:66f3b5499f7f 525
screamer 0:66f3b5499f7f 526 toolchain_output = toolchain.get_output()
screamer 0:66f3b5499f7f 527 if toolchain_output:
screamer 0:66f3b5499f7f 528 cur_result["output"] += toolchain_output
screamer 0:66f3b5499f7f 529
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 530 add_result_to_report(report, cur_result)
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 531
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 532 # Let Exception propagate
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 533 raise e
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 534
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 535 ######################
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 536 ### Legacy methods ###
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 537 ######################
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 538
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 539 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 540 """ Legacy method for building mbed libraries
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 541 Function builds library in proper directory using all dependencies and macros defined by user.
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 542 """
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 543 lib = Library(lib_id)
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 544 if not lib.is_supported(target, toolchain_name):
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 545 print 'Library "%s" is not yet supported on target %s with toolchain %s' % (lib_id, target.name, toolchain)
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 546 return False
screamer 22:9e85236d8716 547
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 548 # We need to combine macros from parameter list with macros from library definition
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 549 MACROS = lib.macros if lib.macros else []
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 550 if macros:
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 551 macros.extend(MACROS)
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 552 else:
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 553 macros = MACROS
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 554
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 555 src_paths = lib.source_dir
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 556 build_path = lib.build_dir
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 557 dependencies_paths = lib.dependencies
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 558 inc_dirs = lib.inc_dirs
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 559 inc_dirs_ext = lib.inc_dirs_ext
screamer 22:9e85236d8716 560
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 561 """ src_path: the path of the source directory
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 562 build_path: the path of the build directory
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 563 target: ['LPC1768', 'LPC11U24', 'LPC2368']
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 564 toolchain: ['ARM', 'uARM', 'GCC_ARM', 'GCC_CR']
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 565 library_paths: List of paths to additional libraries
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 566 clean: Rebuild everything if True
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 567 notify: Notify function for logs
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 568 verbose: Write the actual tools command lines if True
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 569 inc_dirs: additional include directories which should be included in build
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 570 inc_dirs_ext: additional include directories which should be copied to library directory
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 571 """
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 572 if type(src_paths) != ListType:
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 573 src_paths = [src_paths]
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 574
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 575 # The first path will give the name to the library
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 576 name = basename(src_paths[0])
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 577
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 578 if report != None:
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 579 start = time()
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 580 id_name = name.upper()
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 581 description = name
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 582 vendor_label = target.extra_labels[0]
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 583 cur_result = None
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 584 prep_report(report, target.name, toolchain_name, id_name)
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 585 cur_result = create_result(target.name, toolchain_name, id_name, description)
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 586
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 587 if properties != None:
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 588 prep_properties(properties, target.name, toolchain_name, vendor_label)
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 589
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 590 for src_path in src_paths:
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 591 if not exists(src_path):
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 592 error_msg = "The library source folder does not exist: %s", src_path
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 593
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 594 if report != None:
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 595 cur_result["output"] = error_msg
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 596 cur_result["result"] = "FAIL"
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 597 add_result_to_report(report, cur_result)
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 598
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 599 raise Exception(error_msg)
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 600
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 601 try:
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 602 # Toolchain instance
screamer 13:ab47a20b66f0 603 toolchain = TOOLCHAIN_CLASSES[toolchain_name](target, options, macros=macros, notify=notify, silent=silent, extra_verbose=extra_verbose)
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 604 toolchain.VERBOSE = verbose
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 605 toolchain.jobs = jobs
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 606 toolchain.build_all = clean
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 607
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 608 toolchain.info("Building library %s (%s, %s)" % (name.upper(), target.name, toolchain_name))
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 609
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 610 # Scan Resources
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 611 resources = []
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 612 for src_path in src_paths:
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 613 resources.append(toolchain.scan_resources(src_path))
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 614
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 615 # Add extra include directories / files which are required by library
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 616 # This files usually are not in the same directory as source files so
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 617 # previous scan will not include them
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 618 if inc_dirs_ext is not None:
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 619 for inc_ext in inc_dirs_ext:
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 620 resources.append(toolchain.scan_resources(inc_ext))
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 621
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 622 # Dependencies Include Paths
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 623 dependencies_include_dir = []
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 624 if dependencies_paths is not None:
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 625 for path in dependencies_paths:
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 626 lib_resources = toolchain.scan_resources(path)
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 627 dependencies_include_dir.extend(lib_resources.inc_dirs)
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 628
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 629 if inc_dirs:
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 630 dependencies_include_dir.extend(inc_dirs)
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 631
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 632 # Create the desired build directory structure
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 633 bin_path = join(build_path, toolchain.obj_path)
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 634 mkdir(bin_path)
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 635 tmp_path = join(build_path, '.temp', toolchain.obj_path)
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 636 mkdir(tmp_path)
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 637
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 638 # Copy Headers
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 639 for resource in resources:
screamer 13:ab47a20b66f0 640 toolchain.copy_files(resource.headers, build_path, resources=resource)
screamer 22:9e85236d8716 641
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 642 dependencies_include_dir.extend(toolchain.scan_resources(build_path).inc_dirs)
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 643
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 644 # Compile Sources
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 645 objects = []
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 646 for resource in resources:
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 647 objects.extend(toolchain.compile_sources(resource, tmp_path, dependencies_include_dir))
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 648
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 649 needed_update = toolchain.build_library(objects, bin_path, name)
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 650
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 651 if report != None and needed_update:
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 652 end = time()
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 653 cur_result["elapsed_time"] = end - start
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 654 cur_result["output"] = toolchain.get_output()
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 655 cur_result["result"] = "OK"
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 656
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 657 add_result_to_report(report, cur_result)
screamer 22:9e85236d8716 658 return True
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 659
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 660 except Exception, e:
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 661 if report != None:
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 662 end = time()
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 663 cur_result["result"] = "FAIL"
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 664 cur_result["elapsed_time"] = end - start
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 665
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 666 toolchain_output = toolchain.get_output()
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 667 if toolchain_output:
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 668 cur_result["output"] += toolchain_output
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 669
screamer 0:66f3b5499f7f 670 add_result_to_report(report, cur_result)
screamer 0:66f3b5499f7f 671
screamer 0:66f3b5499f7f 672 # Let Exception propagate
screamer 0:66f3b5499f7f 673 raise e
screamer 0:66f3b5499f7f 674
screamer 0:66f3b5499f7f 675 # We do have unique legacy conventions about how we build and package the mbed library
screamer 0:66f3b5499f7f 676 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 677 """ Function returns True is library was built and false if building was skipped """
screamer 0:66f3b5499f7f 678
screamer 0:66f3b5499f7f 679 if report != None:
screamer 0:66f3b5499f7f 680 start = time()
screamer 0:66f3b5499f7f 681 id_name = "MBED"
screamer 0:66f3b5499f7f 682 description = "mbed SDK"
screamer 0:66f3b5499f7f 683 vendor_label = target.extra_labels[0]
screamer 0:66f3b5499f7f 684 cur_result = None
screamer 0:66f3b5499f7f 685 prep_report(report, target.name, toolchain_name, id_name)
screamer 0:66f3b5499f7f 686 cur_result = create_result(target.name, toolchain_name, id_name, description)
screamer 0:66f3b5499f7f 687
screamer 0:66f3b5499f7f 688 if properties != None:
screamer 0:66f3b5499f7f 689 prep_properties(properties, target.name, toolchain_name, vendor_label)
screamer 0:66f3b5499f7f 690
screamer 0:66f3b5499f7f 691 # Check toolchain support
screamer 0:66f3b5499f7f 692 if toolchain_name not in target.supported_toolchains:
screamer 0:66f3b5499f7f 693 supported_toolchains_text = ", ".join(target.supported_toolchains)
screamer 0:66f3b5499f7f 694 print '%s target is not yet supported by toolchain %s' % (target.name, toolchain_name)
screamer 0:66f3b5499f7f 695 print '%s target supports %s toolchain%s' % (target.name, supported_toolchains_text, 's' if len(target.supported_toolchains) > 1 else '')
screamer 0:66f3b5499f7f 696
screamer 0:66f3b5499f7f 697 if report != None:
screamer 0:66f3b5499f7f 698 cur_result["result"] = "SKIP"
screamer 0:66f3b5499f7f 699 add_result_to_report(report, cur_result)
screamer 0:66f3b5499f7f 700
screamer 0:66f3b5499f7f 701 return False
screamer 0:66f3b5499f7f 702
screamer 0:66f3b5499f7f 703 try:
screamer 0:66f3b5499f7f 704 # Toolchain
screamer 0:66f3b5499f7f 705 toolchain = TOOLCHAIN_CLASSES[toolchain_name](target, options, macros=macros, notify=notify, silent=silent, extra_verbose=extra_verbose)
screamer 0:66f3b5499f7f 706 toolchain.VERBOSE = verbose
screamer 0:66f3b5499f7f 707 toolchain.jobs = jobs
screamer 0:66f3b5499f7f 708 toolchain.build_all = clean
screamer 0:66f3b5499f7f 709
screamer 0:66f3b5499f7f 710 # Source and Build Paths
screamer 0:66f3b5499f7f 711 BUILD_TARGET = join(MBED_LIBRARIES, "TARGET_" + target.name)
screamer 0:66f3b5499f7f 712 BUILD_TOOLCHAIN = join(BUILD_TARGET, "TOOLCHAIN_" + toolchain.name)
screamer 0:66f3b5499f7f 713 mkdir(BUILD_TOOLCHAIN)
screamer 0:66f3b5499f7f 714
screamer 0:66f3b5499f7f 715 TMP_PATH = join(MBED_LIBRARIES, '.temp', toolchain.obj_path)
screamer 0:66f3b5499f7f 716 mkdir(TMP_PATH)
screamer 0:66f3b5499f7f 717
screamer 0:66f3b5499f7f 718 # CMSIS
screamer 0:66f3b5499f7f 719 toolchain.info("Building library %s (%s, %s)"% ('CMSIS', target.name, toolchain_name))
screamer 0:66f3b5499f7f 720 cmsis_src = join(MBED_TARGETS_PATH, "cmsis")
screamer 0:66f3b5499f7f 721 resources = toolchain.scan_resources(cmsis_src)
screamer 0:66f3b5499f7f 722
screamer 0:66f3b5499f7f 723 toolchain.copy_files(resources.headers, BUILD_TARGET)
screamer 0:66f3b5499f7f 724 toolchain.copy_files(resources.linker_script, BUILD_TOOLCHAIN)
screamer 0:66f3b5499f7f 725 toolchain.copy_files(resources.bin_files, BUILD_TOOLCHAIN)
screamer 0:66f3b5499f7f 726
screamer 0:66f3b5499f7f 727 objects = toolchain.compile_sources(resources, TMP_PATH)
screamer 0:66f3b5499f7f 728 toolchain.copy_files(objects, BUILD_TOOLCHAIN)
screamer 0:66f3b5499f7f 729
screamer 0:66f3b5499f7f 730 # mbed
screamer 0:66f3b5499f7f 731 toolchain.info("Building library %s (%s, %s)" % ('MBED', target.name, toolchain_name))
screamer 0:66f3b5499f7f 732
screamer 0:66f3b5499f7f 733 # Common Headers
screamer 0:66f3b5499f7f 734 toolchain.copy_files(toolchain.scan_resources(MBED_API).headers, MBED_LIBRARIES)
screamer 0:66f3b5499f7f 735 toolchain.copy_files(toolchain.scan_resources(MBED_HAL).headers, MBED_LIBRARIES)
screamer 0:66f3b5499f7f 736
screamer 0:66f3b5499f7f 737 # Target specific sources
screamer 0:66f3b5499f7f 738 HAL_SRC = join(MBED_TARGETS_PATH, "hal")
screamer 0:66f3b5499f7f 739 hal_implementation = toolchain.scan_resources(HAL_SRC)
screamer 13:ab47a20b66f0 740 toolchain.copy_files(hal_implementation.headers + hal_implementation.hex_files + hal_implementation.libraries, BUILD_TARGET, resources=hal_implementation)
screamer 0:66f3b5499f7f 741 incdirs = toolchain.scan_resources(BUILD_TARGET).inc_dirs
screamer 0:66f3b5499f7f 742 objects = toolchain.compile_sources(hal_implementation, TMP_PATH, [MBED_LIBRARIES] + incdirs)
screamer 0:66f3b5499f7f 743
screamer 0:66f3b5499f7f 744 # Common Sources
screamer 0:66f3b5499f7f 745 mbed_resources = toolchain.scan_resources(MBED_COMMON)
screamer 0:66f3b5499f7f 746 objects += toolchain.compile_sources(mbed_resources, TMP_PATH, [MBED_LIBRARIES] + incdirs)
screamer 0:66f3b5499f7f 747
screamer 0:66f3b5499f7f 748 # A number of compiled files need to be copied as objects as opposed to
screamer 0:66f3b5499f7f 749 # being part of the mbed library, for reasons that have to do with the way
screamer 0:66f3b5499f7f 750 # the linker search for symbols in archives. These are:
screamer 0:66f3b5499f7f 751 # - retarget.o: to make sure that the C standard lib symbols get overridden
screamer 0:66f3b5499f7f 752 # - board.o: mbed_die is weak
screamer 0:66f3b5499f7f 753 # - mbed_overrides.o: this contains platform overrides of various weak SDK functions
screamer 0:66f3b5499f7f 754 separate_names, separate_objects = ['retarget.o', 'board.o', 'mbed_overrides.o'], []
screamer 0:66f3b5499f7f 755
screamer 0:66f3b5499f7f 756 for o in objects:
screamer 0:66f3b5499f7f 757 for name in separate_names:
screamer 0:66f3b5499f7f 758 if o.endswith(name):
screamer 0:66f3b5499f7f 759 separate_objects.append(o)
screamer 0:66f3b5499f7f 760
screamer 0:66f3b5499f7f 761 for o in separate_objects:
screamer 0:66f3b5499f7f 762 objects.remove(o)
screamer 0:66f3b5499f7f 763
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 764 toolchain.build_library(objects, BUILD_TOOLCHAIN, "mbed")
screamer 0:66f3b5499f7f 765
screamer 0:66f3b5499f7f 766 for o in separate_objects:
screamer 0:66f3b5499f7f 767 toolchain.copy_files(o, BUILD_TOOLCHAIN)
screamer 0:66f3b5499f7f 768
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 769 if report != None:
screamer 0:66f3b5499f7f 770 end = time()
screamer 0:66f3b5499f7f 771 cur_result["elapsed_time"] = end - start
screamer 0:66f3b5499f7f 772 cur_result["output"] = toolchain.get_output()
screamer 0:66f3b5499f7f 773 cur_result["result"] = "OK"
screamer 0:66f3b5499f7f 774
screamer 0:66f3b5499f7f 775 add_result_to_report(report, cur_result)
screamer 0:66f3b5499f7f 776
screamer 0:66f3b5499f7f 777 return True
screamer 0:66f3b5499f7f 778
screamer 0:66f3b5499f7f 779 except Exception, e:
screamer 0:66f3b5499f7f 780 if report != None:
screamer 0:66f3b5499f7f 781 end = time()
screamer 0:66f3b5499f7f 782 cur_result["result"] = "FAIL"
screamer 0:66f3b5499f7f 783 cur_result["elapsed_time"] = end - start
screamer 0:66f3b5499f7f 784
screamer 0:66f3b5499f7f 785 toolchain_output = toolchain.get_output()
screamer 0:66f3b5499f7f 786 if toolchain_output:
screamer 0:66f3b5499f7f 787 cur_result["output"] += toolchain_output
screamer 0:66f3b5499f7f 788
screamer 0:66f3b5499f7f 789 cur_result["output"] += str(e)
screamer 0:66f3b5499f7f 790
screamer 0:66f3b5499f7f 791 add_result_to_report(report, cur_result)
screamer 0:66f3b5499f7f 792
screamer 0:66f3b5499f7f 793 # Let Exception propagate
screamer 0:66f3b5499f7f 794 raise e
screamer 0:66f3b5499f7f 795
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 796
screamer 24:25bff2709c20 797 def get_unique_supported_toolchains(release_targets=None):
screamer 24:25bff2709c20 798 """ Get list of all unique toolchains supported by targets
screamer 24:25bff2709c20 799 If release_targets is not specified, then it queries all known targets
screamer 24:25bff2709c20 800 release_targets: tuple structure returned from get_mbed_official_release()
screamer 24:25bff2709c20 801 """
screamer 0:66f3b5499f7f 802 unique_supported_toolchains = []
screamer 24:25bff2709c20 803
screamer 24:25bff2709c20 804 if not release_targets:
screamer 24:25bff2709c20 805 for target in TARGET_NAMES:
screamer 24:25bff2709c20 806 for toolchain in TARGET_MAP[target].supported_toolchains:
screamer 24:25bff2709c20 807 if toolchain not in unique_supported_toolchains:
screamer 24:25bff2709c20 808 unique_supported_toolchains.append(toolchain)
screamer 24:25bff2709c20 809 else:
screamer 24:25bff2709c20 810 for target in release_targets:
screamer 24:25bff2709c20 811 for toolchain in target[1]:
screamer 24:25bff2709c20 812 if toolchain not in unique_supported_toolchains:
screamer 24:25bff2709c20 813 unique_supported_toolchains.append(toolchain)
screamer 24:25bff2709c20 814
screamer 0:66f3b5499f7f 815 return unique_supported_toolchains
screamer 0:66f3b5499f7f 816
screamer 0:66f3b5499f7f 817
screamer 24:25bff2709c20 818 def mcu_toolchain_matrix(verbose_html=False, platform_filter=None, release_version='5'):
screamer 0:66f3b5499f7f 819 """ Shows target map using prettytable """
screamer 0:66f3b5499f7f 820 from prettytable import PrettyTable # Only use it in this function so building works without extra modules
screamer 0:66f3b5499f7f 821
screamer 24:25bff2709c20 822 if isinstance(release_version, basestring):
screamer 24:25bff2709c20 823 # Force release_version to lowercase if it is a string
screamer 24:25bff2709c20 824 release_version = release_version.lower()
screamer 24:25bff2709c20 825 else:
screamer 24:25bff2709c20 826 # Otherwise default to printing all known targets and toolchains
screamer 24:25bff2709c20 827 release_version = 'all'
screamer 24:25bff2709c20 828
screamer 24:25bff2709c20 829
screamer 24:25bff2709c20 830 version_release_targets = {}
screamer 24:25bff2709c20 831 version_release_target_names = {}
screamer 24:25bff2709c20 832
screamer 24:25bff2709c20 833 for version in RELEASE_VERSIONS:
screamer 24:25bff2709c20 834 version_release_targets[version] = get_mbed_official_release(version)
screamer 24:25bff2709c20 835 version_release_target_names[version] = [x[0] for x in version_release_targets[version]]
screamer 24:25bff2709c20 836
screamer 24:25bff2709c20 837 if release_version in RELEASE_VERSIONS:
screamer 24:25bff2709c20 838 release_targets = version_release_targets[release_version]
screamer 24:25bff2709c20 839 else:
screamer 24:25bff2709c20 840 release_targets = None
screamer 24:25bff2709c20 841
screamer 24:25bff2709c20 842 unique_supported_toolchains = get_unique_supported_toolchains(release_targets)
screamer 24:25bff2709c20 843 prepend_columns = ["Target"] + ["mbed OS %s" % x for x in RELEASE_VERSIONS]
screamer 24:25bff2709c20 844
screamer 0:66f3b5499f7f 845 # All tests status table print
screamer 24:25bff2709c20 846 columns = prepend_columns + unique_supported_toolchains
screamer 24:25bff2709c20 847 pt = PrettyTable(columns)
screamer 0:66f3b5499f7f 848 # Align table
screamer 0:66f3b5499f7f 849 for col in columns:
screamer 0:66f3b5499f7f 850 pt.align[col] = "c"
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 851 pt.align["Target"] = "l"
screamer 0:66f3b5499f7f 852
screamer 0:66f3b5499f7f 853 perm_counter = 0
screamer 0:66f3b5499f7f 854 target_counter = 0
screamer 24:25bff2709c20 855
screamer 24:25bff2709c20 856 target_names = []
screamer 24:25bff2709c20 857
screamer 24:25bff2709c20 858 if release_targets:
screamer 24:25bff2709c20 859 target_names = [x[0] for x in release_targets]
screamer 24:25bff2709c20 860 else:
screamer 24:25bff2709c20 861 target_names = TARGET_NAMES
screamer 24:25bff2709c20 862
screamer 24:25bff2709c20 863 for target in sorted(target_names):
screamer 0:66f3b5499f7f 864 if platform_filter is not None:
screamer 0:66f3b5499f7f 865 # FIlter out platforms using regex
screamer 0:66f3b5499f7f 866 if re.search(platform_filter, target) is None:
screamer 0:66f3b5499f7f 867 continue
screamer 0:66f3b5499f7f 868 target_counter += 1
screamer 0:66f3b5499f7f 869
screamer 0:66f3b5499f7f 870 row = [target] # First column is platform name
screamer 24:25bff2709c20 871
screamer 24:25bff2709c20 872 for version in RELEASE_VERSIONS:
screamer 24:25bff2709c20 873 if target in version_release_target_names[version]:
screamer 24:25bff2709c20 874 text = "Supported"
screamer 24:25bff2709c20 875 else:
screamer 24:25bff2709c20 876 text = "-"
screamer 24:25bff2709c20 877 row.append(text)
screamer 24:25bff2709c20 878
screamer 0:66f3b5499f7f 879 for unique_toolchain in unique_supported_toolchains:
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 880 if unique_toolchain in TARGET_MAP[target].supported_toolchains:
screamer 0:66f3b5499f7f 881 text = "Supported"
screamer 0:66f3b5499f7f 882 perm_counter += 1
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 883 else:
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 884 text = "-"
screamer 22:9e85236d8716 885
screamer 0:66f3b5499f7f 886 row.append(text)
screamer 0:66f3b5499f7f 887 pt.add_row(row)
screamer 0:66f3b5499f7f 888
screamer 0:66f3b5499f7f 889 result = pt.get_html_string() if verbose_html else pt.get_string()
screamer 0:66f3b5499f7f 890 result += "\n"
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 891 result += "Supported targets: %d\n"% (target_counter)
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 892 if target_counter == 1:
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 893 result += "Supported toolchains: %d"% (perm_counter)
screamer 0:66f3b5499f7f 894 return result
screamer 0:66f3b5499f7f 895
screamer 0:66f3b5499f7f 896
screamer 0:66f3b5499f7f 897 def get_target_supported_toolchains(target):
screamer 0:66f3b5499f7f 898 """ Returns target supported toolchains list """
screamer 0:66f3b5499f7f 899 return TARGET_MAP[target].supported_toolchains if target in TARGET_MAP else None
screamer 0:66f3b5499f7f 900
screamer 0:66f3b5499f7f 901
screamer 0:66f3b5499f7f 902 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 903 # Toolchain
screamer 0:66f3b5499f7f 904 toolchain = TOOLCHAIN_CLASSES[toolchain_name](target, options, macros=macros, notify=notify, extra_verbose=extra_verbose)
screamer 0:66f3b5499f7f 905 toolchain.VERBOSE = verbose
screamer 0:66f3b5499f7f 906 toolchain.jobs = jobs
screamer 0:66f3b5499f7f 907 toolchain.build_all = clean
screamer 0:66f3b5499f7f 908
screamer 0:66f3b5499f7f 909 # Source and Build Paths
screamer 0:66f3b5499f7f 910 BUILD_TARGET = join(MBED_LIBRARIES, "TARGET_" + target.name)
screamer 0:66f3b5499f7f 911 BUILD_TOOLCHAIN = join(BUILD_TARGET, "TOOLCHAIN_" + toolchain.name)
screamer 0:66f3b5499f7f 912 mkdir(BUILD_TOOLCHAIN)
screamer 0:66f3b5499f7f 913
screamer 0:66f3b5499f7f 914 TMP_PATH = join(MBED_LIBRARIES, '.temp', toolchain.obj_path)
screamer 0:66f3b5499f7f 915 mkdir(TMP_PATH)
screamer 0:66f3b5499f7f 916
screamer 0:66f3b5499f7f 917 # CMSIS
screamer 0:66f3b5499f7f 918 toolchain.info("Static analysis for %s (%s, %s)" % ('CMSIS', target.name, toolchain_name))
screamer 0:66f3b5499f7f 919 cmsis_src = join(MBED_TARGETS_PATH, "cmsis")
screamer 0:66f3b5499f7f 920 resources = toolchain.scan_resources(cmsis_src)
screamer 0:66f3b5499f7f 921
screamer 0:66f3b5499f7f 922 # Copy files before analysis
screamer 0:66f3b5499f7f 923 toolchain.copy_files(resources.headers, BUILD_TARGET)
screamer 0:66f3b5499f7f 924 toolchain.copy_files(resources.linker_script, BUILD_TOOLCHAIN)
screamer 0:66f3b5499f7f 925
screamer 0:66f3b5499f7f 926 # Gather include paths, c, cpp sources and macros to transfer to cppcheck command line
screamer 0:66f3b5499f7f 927 includes = ["-I%s"% i for i in resources.inc_dirs]
screamer 0:66f3b5499f7f 928 includes.append("-I%s"% str(BUILD_TARGET))
screamer 0:66f3b5499f7f 929 c_sources = " ".join(resources.c_sources)
screamer 0:66f3b5499f7f 930 cpp_sources = " ".join(resources.cpp_sources)
screamer 0:66f3b5499f7f 931 macros = ["-D%s"% s for s in toolchain.get_symbols() + toolchain.macros]
screamer 0:66f3b5499f7f 932
screamer 0:66f3b5499f7f 933 includes = map(str.strip, includes)
screamer 0:66f3b5499f7f 934 macros = map(str.strip, macros)
screamer 0:66f3b5499f7f 935
screamer 0:66f3b5499f7f 936 check_cmd = CPPCHECK_CMD
screamer 0:66f3b5499f7f 937 check_cmd += CPPCHECK_MSG_FORMAT
screamer 0:66f3b5499f7f 938 check_cmd += includes
screamer 0:66f3b5499f7f 939 check_cmd += macros
screamer 0:66f3b5499f7f 940
screamer 0:66f3b5499f7f 941 # We need to pass some params via file to avoid "command line too long in some OSs"
screamer 0:66f3b5499f7f 942 tmp_file = tempfile.NamedTemporaryFile(delete=False)
screamer 0:66f3b5499f7f 943 tmp_file.writelines(line + '\n' for line in c_sources.split())
screamer 0:66f3b5499f7f 944 tmp_file.writelines(line + '\n' for line in cpp_sources.split())
screamer 0:66f3b5499f7f 945 tmp_file.close()
screamer 0:66f3b5499f7f 946 check_cmd += ["--file-list=%s"% tmp_file.name]
screamer 0:66f3b5499f7f 947
screamer 0:66f3b5499f7f 948 _stdout, _stderr, _rc = run_cmd(check_cmd)
screamer 0:66f3b5499f7f 949 if verbose:
screamer 0:66f3b5499f7f 950 print _stdout
screamer 0:66f3b5499f7f 951 print _stderr
screamer 0:66f3b5499f7f 952
screamer 0:66f3b5499f7f 953 # =========================================================================
screamer 0:66f3b5499f7f 954
screamer 0:66f3b5499f7f 955 # MBED
screamer 0:66f3b5499f7f 956 toolchain.info("Static analysis for %s (%s, %s)" % ('MBED', target.name, toolchain_name))
screamer 0:66f3b5499f7f 957
screamer 0:66f3b5499f7f 958 # Common Headers
screamer 0:66f3b5499f7f 959 toolchain.copy_files(toolchain.scan_resources(MBED_API).headers, MBED_LIBRARIES)
screamer 0:66f3b5499f7f 960 toolchain.copy_files(toolchain.scan_resources(MBED_HAL).headers, MBED_LIBRARIES)
screamer 0:66f3b5499f7f 961
screamer 0:66f3b5499f7f 962 # Target specific sources
screamer 0:66f3b5499f7f 963 HAL_SRC = join(MBED_TARGETS_PATH, "hal")
screamer 0:66f3b5499f7f 964 hal_implementation = toolchain.scan_resources(HAL_SRC)
screamer 0:66f3b5499f7f 965
screamer 0:66f3b5499f7f 966 # Copy files before analysis
screamer 13:ab47a20b66f0 967 toolchain.copy_files(hal_implementation.headers + hal_implementation.hex_files, BUILD_TARGET, resources=hal_implementation)
screamer 0:66f3b5499f7f 968 incdirs = toolchain.scan_resources(BUILD_TARGET)
screamer 0:66f3b5499f7f 969
screamer 0:66f3b5499f7f 970 target_includes = ["-I%s" % i for i in incdirs.inc_dirs]
screamer 0:66f3b5499f7f 971 target_includes.append("-I%s"% str(BUILD_TARGET))
screamer 0:66f3b5499f7f 972 target_includes.append("-I%s"% str(HAL_SRC))
screamer 0:66f3b5499f7f 973 target_c_sources = " ".join(incdirs.c_sources)
screamer 0:66f3b5499f7f 974 target_cpp_sources = " ".join(incdirs.cpp_sources)
screamer 0:66f3b5499f7f 975 target_macros = ["-D%s"% s for s in toolchain.get_symbols() + toolchain.macros]
screamer 0:66f3b5499f7f 976
screamer 0:66f3b5499f7f 977 # Common Sources
screamer 0:66f3b5499f7f 978 mbed_resources = toolchain.scan_resources(MBED_COMMON)
screamer 0:66f3b5499f7f 979
screamer 0:66f3b5499f7f 980 # Gather include paths, c, cpp sources and macros to transfer to cppcheck command line
screamer 0:66f3b5499f7f 981 mbed_includes = ["-I%s" % i for i in mbed_resources.inc_dirs]
screamer 0:66f3b5499f7f 982 mbed_includes.append("-I%s"% str(BUILD_TARGET))
screamer 0:66f3b5499f7f 983 mbed_includes.append("-I%s"% str(MBED_COMMON))
screamer 0:66f3b5499f7f 984 mbed_includes.append("-I%s"% str(MBED_API))
screamer 0:66f3b5499f7f 985 mbed_includes.append("-I%s"% str(MBED_HAL))
screamer 0:66f3b5499f7f 986 mbed_c_sources = " ".join(mbed_resources.c_sources)
screamer 0:66f3b5499f7f 987 mbed_cpp_sources = " ".join(mbed_resources.cpp_sources)
screamer 0:66f3b5499f7f 988
screamer 0:66f3b5499f7f 989 target_includes = map(str.strip, target_includes)
screamer 0:66f3b5499f7f 990 mbed_includes = map(str.strip, mbed_includes)
screamer 0:66f3b5499f7f 991 target_macros = map(str.strip, target_macros)
screamer 0:66f3b5499f7f 992
screamer 0:66f3b5499f7f 993 check_cmd = CPPCHECK_CMD
screamer 0:66f3b5499f7f 994 check_cmd += CPPCHECK_MSG_FORMAT
screamer 0:66f3b5499f7f 995 check_cmd += target_includes
screamer 0:66f3b5499f7f 996 check_cmd += mbed_includes
screamer 0:66f3b5499f7f 997 check_cmd += target_macros
screamer 0:66f3b5499f7f 998
screamer 0:66f3b5499f7f 999 # We need to pass some parames via file to avoid "command line too long in some OSs"
screamer 0:66f3b5499f7f 1000 tmp_file = tempfile.NamedTemporaryFile(delete=False)
screamer 0:66f3b5499f7f 1001 tmp_file.writelines(line + '\n' for line in target_c_sources.split())
screamer 0:66f3b5499f7f 1002 tmp_file.writelines(line + '\n' for line in target_cpp_sources.split())
screamer 0:66f3b5499f7f 1003 tmp_file.writelines(line + '\n' for line in mbed_c_sources.split())
screamer 0:66f3b5499f7f 1004 tmp_file.writelines(line + '\n' for line in mbed_cpp_sources.split())
screamer 0:66f3b5499f7f 1005 tmp_file.close()
screamer 0:66f3b5499f7f 1006 check_cmd += ["--file-list=%s"% tmp_file.name]
screamer 0:66f3b5499f7f 1007
screamer 0:66f3b5499f7f 1008 _stdout, _stderr, _rc = run_cmd_ext(check_cmd)
screamer 0:66f3b5499f7f 1009 if verbose:
screamer 0:66f3b5499f7f 1010 print _stdout
screamer 0:66f3b5499f7f 1011 print _stderr
screamer 0:66f3b5499f7f 1012
screamer 0:66f3b5499f7f 1013
screamer 0:66f3b5499f7f 1014 def static_analysis_scan_lib(lib_id, target, toolchain, cppcheck_cmd, cppcheck_msg_format,
screamer 0:66f3b5499f7f 1015 options=None, verbose=False, clean=False, macros=None, notify=None, jobs=1, extra_verbose=False):
screamer 0:66f3b5499f7f 1016 lib = Library(lib_id)
screamer 0:66f3b5499f7f 1017 if lib.is_supported(target, toolchain):
screamer 0:66f3b5499f7f 1018 static_analysis_scan_library(lib.source_dir, lib.build_dir, target, toolchain, cppcheck_cmd, cppcheck_msg_format,
screamer 0:66f3b5499f7f 1019 lib.dependencies, options,
screamer 0:66f3b5499f7f 1020 verbose=verbose, clean=clean, macros=macros, notify=notify, jobs=jobs, extra_verbose=extra_verbose)
screamer 0:66f3b5499f7f 1021 else:
screamer 0:66f3b5499f7f 1022 print 'Library "%s" is not yet supported on target %s with toolchain %s'% (lib_id, target.name, toolchain)
screamer 0:66f3b5499f7f 1023
screamer 0:66f3b5499f7f 1024
screamer 0:66f3b5499f7f 1025 def static_analysis_scan_library(src_paths, build_path, target, toolchain_name, cppcheck_cmd, cppcheck_msg_format,
screamer 0:66f3b5499f7f 1026 dependencies_paths=None, options=None, name=None, clean=False,
screamer 0:66f3b5499f7f 1027 notify=None, verbose=False, macros=None, jobs=1, extra_verbose=False):
screamer 0:66f3b5499f7f 1028 """ Function scans library (or just some set of sources/headers) for staticly detectable defects """
screamer 0:66f3b5499f7f 1029 if type(src_paths) != ListType:
screamer 0:66f3b5499f7f 1030 src_paths = [src_paths]
screamer 0:66f3b5499f7f 1031
screamer 0:66f3b5499f7f 1032 for src_path in src_paths:
screamer 0:66f3b5499f7f 1033 if not exists(src_path):
screamer 0:66f3b5499f7f 1034 raise Exception("The library source folder does not exist: %s", src_path)
screamer 0:66f3b5499f7f 1035
screamer 0:66f3b5499f7f 1036 # Toolchain instance
screamer 0:66f3b5499f7f 1037 toolchain = TOOLCHAIN_CLASSES[toolchain_name](target, options, macros=macros, notify=notify, extra_verbose=extra_verbose)
screamer 0:66f3b5499f7f 1038 toolchain.VERBOSE = verbose
screamer 0:66f3b5499f7f 1039 toolchain.jobs = jobs
screamer 0:66f3b5499f7f 1040
screamer 0:66f3b5499f7f 1041 # The first path will give the name to the library
screamer 0:66f3b5499f7f 1042 name = basename(src_paths[0])
screamer 0:66f3b5499f7f 1043 toolchain.info("Static analysis for library %s (%s, %s)" % (name.upper(), target.name, toolchain_name))
screamer 0:66f3b5499f7f 1044
screamer 0:66f3b5499f7f 1045 # Scan Resources
screamer 0:66f3b5499f7f 1046 resources = []
screamer 0:66f3b5499f7f 1047 for src_path in src_paths:
screamer 0:66f3b5499f7f 1048 resources.append(toolchain.scan_resources(src_path))
screamer 0:66f3b5499f7f 1049
screamer 0:66f3b5499f7f 1050 # Dependencies Include Paths
screamer 0:66f3b5499f7f 1051 dependencies_include_dir = []
screamer 0:66f3b5499f7f 1052 if dependencies_paths is not None:
screamer 0:66f3b5499f7f 1053 for path in dependencies_paths:
screamer 0:66f3b5499f7f 1054 lib_resources = toolchain.scan_resources(path)
screamer 0:66f3b5499f7f 1055 dependencies_include_dir.extend(lib_resources.inc_dirs)
screamer 0:66f3b5499f7f 1056
screamer 0:66f3b5499f7f 1057 # Create the desired build directory structure
screamer 0:66f3b5499f7f 1058 bin_path = join(build_path, toolchain.obj_path)
screamer 0:66f3b5499f7f 1059 mkdir(bin_path)
screamer 0:66f3b5499f7f 1060 tmp_path = join(build_path, '.temp', toolchain.obj_path)
screamer 0:66f3b5499f7f 1061 mkdir(tmp_path)
screamer 0:66f3b5499f7f 1062
screamer 0:66f3b5499f7f 1063 # Gather include paths, c, cpp sources and macros to transfer to cppcheck command line
screamer 0:66f3b5499f7f 1064 includes = ["-I%s" % i for i in dependencies_include_dir + src_paths]
screamer 0:66f3b5499f7f 1065 c_sources = " "
screamer 0:66f3b5499f7f 1066 cpp_sources = " "
screamer 0:66f3b5499f7f 1067 macros = ['-D%s' % s for s in toolchain.get_symbols() + toolchain.macros]
screamer 0:66f3b5499f7f 1068
screamer 0:66f3b5499f7f 1069 # Copy Headers
screamer 0:66f3b5499f7f 1070 for resource in resources:
screamer 13:ab47a20b66f0 1071 toolchain.copy_files(resource.headers, build_path, resources=resource)
screamer 0:66f3b5499f7f 1072 includes += ["-I%s" % i for i in resource.inc_dirs]
screamer 0:66f3b5499f7f 1073 c_sources += " ".join(resource.c_sources) + " "
screamer 0:66f3b5499f7f 1074 cpp_sources += " ".join(resource.cpp_sources) + " "
screamer 0:66f3b5499f7f 1075
screamer 0:66f3b5499f7f 1076 dependencies_include_dir.extend(toolchain.scan_resources(build_path).inc_dirs)
screamer 0:66f3b5499f7f 1077
screamer 0:66f3b5499f7f 1078 includes = map(str.strip, includes)
screamer 0:66f3b5499f7f 1079 macros = map(str.strip, macros)
screamer 0:66f3b5499f7f 1080
screamer 0:66f3b5499f7f 1081 check_cmd = cppcheck_cmd
screamer 0:66f3b5499f7f 1082 check_cmd += cppcheck_msg_format
screamer 0:66f3b5499f7f 1083 check_cmd += includes
screamer 0:66f3b5499f7f 1084 check_cmd += macros
screamer 0:66f3b5499f7f 1085
screamer 0:66f3b5499f7f 1086 # We need to pass some parameters via file to avoid "command line too long in some OSs"
screamer 0:66f3b5499f7f 1087 # Temporary file is created to store e.g. cppcheck list of files for command line
screamer 0:66f3b5499f7f 1088 tmp_file = tempfile.NamedTemporaryFile(delete=False)
screamer 0:66f3b5499f7f 1089 tmp_file.writelines(line + '\n' for line in c_sources.split())
screamer 0:66f3b5499f7f 1090 tmp_file.writelines(line + '\n' for line in cpp_sources.split())
screamer 0:66f3b5499f7f 1091 tmp_file.close()
screamer 0:66f3b5499f7f 1092 check_cmd += ["--file-list=%s"% tmp_file.name]
screamer 0:66f3b5499f7f 1093
screamer 0:66f3b5499f7f 1094 # This will allow us to grab result from both stdio and stderr outputs (so we can show them)
screamer 0:66f3b5499f7f 1095 # We assume static code analysis tool is outputting defects on STDERR
screamer 0:66f3b5499f7f 1096 _stdout, _stderr, _rc = run_cmd_ext(check_cmd)
screamer 0:66f3b5499f7f 1097 if verbose:
screamer 0:66f3b5499f7f 1098 print _stdout
screamer 0:66f3b5499f7f 1099 print _stderr
screamer 0:66f3b5499f7f 1100
screamer 0:66f3b5499f7f 1101
screamer 0:66f3b5499f7f 1102 def print_build_results(result_list, build_name):
screamer 0:66f3b5499f7f 1103 """ Generate result string for build results """
screamer 0:66f3b5499f7f 1104 result = ""
screamer 0:66f3b5499f7f 1105 if len(result_list) > 0:
screamer 0:66f3b5499f7f 1106 result += build_name + "\n"
screamer 0:66f3b5499f7f 1107 result += "\n".join([" * %s" % f for f in result_list])
screamer 0:66f3b5499f7f 1108 result += "\n"
screamer 0:66f3b5499f7f 1109 return result
screamer 0:66f3b5499f7f 1110
screamer 22:9e85236d8716 1111 def print_build_memory_usage_results(report):
screamer 22:9e85236d8716 1112 """ Generate result table with memory usage values for build results
screamer 22:9e85236d8716 1113 Agregates (puts together) reports obtained from self.get_memory_summary()
screamer 22:9e85236d8716 1114 @param report Report generated during build procedure. See
screamer 22:9e85236d8716 1115 """
screamer 22:9e85236d8716 1116 from prettytable import PrettyTable
screamer 22:9e85236d8716 1117 columns_text = ['name', 'target', 'toolchain']
screamer 22:9e85236d8716 1118 columns_int = ['static_ram', 'stack', 'heap', 'total_ram', 'total_flash']
screamer 22:9e85236d8716 1119 table = PrettyTable(columns_text + columns_int)
screamer 22:9e85236d8716 1120
screamer 22:9e85236d8716 1121 for col in columns_text:
screamer 22:9e85236d8716 1122 table.align[col] = 'l'
screamer 22:9e85236d8716 1123
screamer 22:9e85236d8716 1124 for col in columns_int:
screamer 22:9e85236d8716 1125 table.align[col] = 'r'
screamer 22:9e85236d8716 1126
screamer 22:9e85236d8716 1127 for target in report:
screamer 22:9e85236d8716 1128 for toolchain in report[target]:
screamer 22:9e85236d8716 1129 for name in report[target][toolchain]:
screamer 22:9e85236d8716 1130 for dlist in report[target][toolchain][name]:
screamer 22:9e85236d8716 1131 for dlistelem in dlist:
screamer 22:9e85236d8716 1132 # Get 'memory_usage' record and build table with statistics
screamer 22:9e85236d8716 1133 record = dlist[dlistelem]
screamer 22:9e85236d8716 1134 if 'memory_usage' in record and record['memory_usage']:
screamer 22:9e85236d8716 1135 # Note that summary should be in the last record of
screamer 22:9e85236d8716 1136 # 'memory_usage' section. This is why we are grabbing
screamer 22:9e85236d8716 1137 # last "[-1]" record.
screamer 22:9e85236d8716 1138 row = [
screamer 22:9e85236d8716 1139 record['description'],
screamer 22:9e85236d8716 1140 record['target_name'],
screamer 22:9e85236d8716 1141 record['toolchain_name'],
screamer 22:9e85236d8716 1142 record['memory_usage'][-1]['summary']['static_ram'],
screamer 22:9e85236d8716 1143 record['memory_usage'][-1]['summary']['stack'],
screamer 22:9e85236d8716 1144 record['memory_usage'][-1]['summary']['heap'],
screamer 22:9e85236d8716 1145 record['memory_usage'][-1]['summary']['total_ram'],
screamer 22:9e85236d8716 1146 record['memory_usage'][-1]['summary']['total_flash'],
screamer 22:9e85236d8716 1147 ]
screamer 22:9e85236d8716 1148 table.add_row(row)
screamer 22:9e85236d8716 1149
screamer 22:9e85236d8716 1150 result = "Memory map breakdown for built projects (values in Bytes):\n"
screamer 22:9e85236d8716 1151 result += table.get_string(sortby='name')
screamer 22:9e85236d8716 1152 return result
screamer 22:9e85236d8716 1153
screamer 0:66f3b5499f7f 1154 def write_build_report(build_report, template_filename, filename):
screamer 0:66f3b5499f7f 1155 build_report_failing = []
screamer 0:66f3b5499f7f 1156 build_report_passing = []
screamer 0:66f3b5499f7f 1157
screamer 0:66f3b5499f7f 1158 for report in build_report:
screamer 0:66f3b5499f7f 1159 if len(report["failing"]) > 0:
screamer 0:66f3b5499f7f 1160 build_report_failing.append(report)
screamer 0:66f3b5499f7f 1161 else:
screamer 0:66f3b5499f7f 1162 build_report_passing.append(report)
screamer 0:66f3b5499f7f 1163
screamer 0:66f3b5499f7f 1164 env = Environment(extensions=['jinja2.ext.with_'])
screamer 0:66f3b5499f7f 1165 env.loader = FileSystemLoader('ci_templates')
screamer 0:66f3b5499f7f 1166 template = env.get_template(template_filename)
screamer 0:66f3b5499f7f 1167
screamer 0:66f3b5499f7f 1168 with open(filename, 'w+') as f:
screamer 0:66f3b5499f7f 1169 f.write(template.render(failing_builds=build_report_failing, passing_builds=build_report_passing))