Clone of official tools

Committer:
theotherjimmy
Date:
Tue Sep 25 13:43:09 2018 -0500
Revision:
43:2a7da56ebd24
Parent:
41:2a77626a4c21
Child:
45:c4a728429846
Release 5.10.0

Who changed what in which revision?

UserRevisionLine numberNew contents of line
screamer 0:66f3b5499f7f 1 """
screamer 0:66f3b5499f7f 2 mbed SDK
The Other Jimmy 31:8ea194f6145b 3 Copyright (c) 2011-2016 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 """
theotherjimmy 43:2a7da56ebd24 17 from __future__ import print_function, division, absolute_import
screamer 0:66f3b5499f7f 18
screamer 0:66f3b5499f7f 19 import re
screamer 0:66f3b5499f7f 20 import tempfile
The Other Jimmy 36:96847d42f010 21 import datetime
The Other Jimmy 36:96847d42f010 22 import uuid
theotherjimmy 43:2a7da56ebd24 23 import struct
theotherjimmy 43:2a7da56ebd24 24 import zlib
theotherjimmy 43:2a7da56ebd24 25 import hashlib
screamer 0:66f3b5499f7f 26 from shutil import rmtree
The Other Jimmy 36:96847d42f010 27 from os.path import join, exists, dirname, basename, abspath, normpath, splitext
The Other Jimmy 36:96847d42f010 28 from os.path import relpath
The Other Jimmy 36:96847d42f010 29 from os import linesep, remove, makedirs
screamer 0:66f3b5499f7f 30 from time import time
The Other Jimmy 36:96847d42f010 31 from intelhex import IntelHex
The Other Jimmy 36:96847d42f010 32 from json import load, dump
screamer 0:66f3b5499f7f 33 from jinja2 import FileSystemLoader
screamer 0:66f3b5499f7f 34 from jinja2.environment import Environment
theotherjimmy 43:2a7da56ebd24 35
theotherjimmy 43:2a7da56ebd24 36 from .arm_pack_manager import Cache
theotherjimmy 43:2a7da56ebd24 37 from .utils import (mkdir, run_cmd, run_cmd_ext, NotSupportedException,
theotherjimmy 43:2a7da56ebd24 38 ToolException, InvalidReleaseTargetException,
theotherjimmy 43:2a7da56ebd24 39 intelhex_offset, integer)
theotherjimmy 43:2a7da56ebd24 40 from .paths import (MBED_CMSIS_PATH, MBED_TARGETS_PATH, MBED_LIBRARIES,
theotherjimmy 43:2a7da56ebd24 41 MBED_HEADER, MBED_DRIVERS, MBED_PLATFORM, MBED_HAL,
theotherjimmy 43:2a7da56ebd24 42 MBED_CONFIG_FILE, MBED_LIBRARIES_DRIVERS,
theotherjimmy 43:2a7da56ebd24 43 MBED_LIBRARIES_PLATFORM, MBED_LIBRARIES_HAL,
theotherjimmy 43:2a7da56ebd24 44 BUILD_DIR)
theotherjimmy 43:2a7da56ebd24 45 from .resources import Resources, FileType, FileRef
theotherjimmy 43:2a7da56ebd24 46 from .notifier.mock import MockNotifier
theotherjimmy 43:2a7da56ebd24 47 from .targets import TARGET_NAMES, TARGET_MAP, CORE_ARCH, set_targets_json_location
theotherjimmy 43:2a7da56ebd24 48 from .libraries import Library
theotherjimmy 43:2a7da56ebd24 49 from .toolchains import TOOLCHAIN_CLASSES, mbedToolchain
theotherjimmy 43:2a7da56ebd24 50 from .config import Config
theotherjimmy 43:2a7da56ebd24 51 from .build_profiles import find_build_profile, get_toolchain_profile, find_targets_json
screamer 0:66f3b5499f7f 52
screamer 24:25bff2709c20 53 RELEASE_VERSIONS = ['2', '5']
screamer 24:25bff2709c20 54
screamer 0:66f3b5499f7f 55 def prep_report(report, target_name, toolchain_name, id_name):
screamer 29:1210849dba19 56 """Setup report keys
screamer 29:1210849dba19 57
screamer 29:1210849dba19 58 Positional arguments:
screamer 29:1210849dba19 59 report - the report to fill
screamer 29:1210849dba19 60 target_name - the target being used
screamer 29:1210849dba19 61 toolchain_name - the toolchain being used
screamer 29:1210849dba19 62 id_name - the name of the executable or library being built
screamer 29:1210849dba19 63 """
screamer 0:66f3b5499f7f 64 if not target_name in report:
screamer 0:66f3b5499f7f 65 report[target_name] = {}
screamer 0:66f3b5499f7f 66
screamer 0:66f3b5499f7f 67 if not toolchain_name in report[target_name]:
screamer 0:66f3b5499f7f 68 report[target_name][toolchain_name] = {}
screamer 0:66f3b5499f7f 69
screamer 0:66f3b5499f7f 70 if not id_name in report[target_name][toolchain_name]:
screamer 0:66f3b5499f7f 71 report[target_name][toolchain_name][id_name] = []
screamer 0:66f3b5499f7f 72
screamer 0:66f3b5499f7f 73 def prep_properties(properties, target_name, toolchain_name, vendor_label):
screamer 29:1210849dba19 74 """Setup test properties
screamer 29:1210849dba19 75
screamer 29:1210849dba19 76 Positional arguments:
screamer 29:1210849dba19 77 properties - the dict to fill
screamer 29:1210849dba19 78 target_name - the target the test is targeting
screamer 29:1210849dba19 79 toolchain_name - the toolchain that will compile the test
screamer 29:1210849dba19 80 vendor_label - the vendor
screamer 29:1210849dba19 81 """
screamer 0:66f3b5499f7f 82 if not target_name in properties:
screamer 0:66f3b5499f7f 83 properties[target_name] = {}
screamer 0:66f3b5499f7f 84
screamer 0:66f3b5499f7f 85 if not toolchain_name in properties[target_name]:
screamer 0:66f3b5499f7f 86 properties[target_name][toolchain_name] = {}
screamer 0:66f3b5499f7f 87
screamer 0:66f3b5499f7f 88 properties[target_name][toolchain_name]["target"] = target_name
screamer 0:66f3b5499f7f 89 properties[target_name][toolchain_name]["vendor"] = vendor_label
screamer 0:66f3b5499f7f 90 properties[target_name][toolchain_name]["toolchain"] = toolchain_name
screamer 0:66f3b5499f7f 91
screamer 0:66f3b5499f7f 92 def create_result(target_name, toolchain_name, id_name, description):
screamer 29:1210849dba19 93 """Create a result dictionary
screamer 29:1210849dba19 94
screamer 29:1210849dba19 95 Positional arguments:
screamer 29:1210849dba19 96 target_name - the target being built for
screamer 29:1210849dba19 97 toolchain_name - the toolchain doing the building
screamer 29:1210849dba19 98 id_name - the name of the executable or library being built
screamer 29:1210849dba19 99 description - a human readable description of what's going on
screamer 29:1210849dba19 100 """
screamer 0:66f3b5499f7f 101 cur_result = {}
screamer 0:66f3b5499f7f 102 cur_result["target_name"] = target_name
screamer 0:66f3b5499f7f 103 cur_result["toolchain_name"] = toolchain_name
screamer 0:66f3b5499f7f 104 cur_result["id"] = id_name
screamer 0:66f3b5499f7f 105 cur_result["description"] = description
screamer 0:66f3b5499f7f 106 cur_result["elapsed_time"] = 0
screamer 0:66f3b5499f7f 107 cur_result["output"] = ""
screamer 0:66f3b5499f7f 108
screamer 0:66f3b5499f7f 109 return cur_result
screamer 0:66f3b5499f7f 110
screamer 0:66f3b5499f7f 111 def add_result_to_report(report, result):
screamer 29:1210849dba19 112 """Add a single result to a report dictionary
screamer 29:1210849dba19 113
screamer 29:1210849dba19 114 Positional arguments:
screamer 29:1210849dba19 115 report - the report to append to
screamer 29:1210849dba19 116 result - the result to append
screamer 29:1210849dba19 117 """
The Other Jimmy 36:96847d42f010 118 result["date"] = datetime.datetime.utcnow().isoformat()
The Other Jimmy 36:96847d42f010 119 result["uuid"] = str(uuid.uuid1())
screamer 0:66f3b5499f7f 120 target = result["target_name"]
screamer 0:66f3b5499f7f 121 toolchain = result["toolchain_name"]
screamer 0:66f3b5499f7f 122 id_name = result['id']
screamer 29:1210849dba19 123 result_wrap = {0: result}
screamer 0:66f3b5499f7f 124 report[target][toolchain][id_name].append(result_wrap)
screamer 0:66f3b5499f7f 125
theotherjimmy 43:2a7da56ebd24 126 def get_config(src_paths, target, toolchain_name=None, app_config=None):
screamer 29:1210849dba19 127 """Get the configuration object for a target-toolchain combination
screamer 29:1210849dba19 128
screamer 29:1210849dba19 129 Positional arguments:
screamer 29:1210849dba19 130 src_paths - paths to scan for the configuration files
screamer 29:1210849dba19 131 target - the device we are building for
screamer 29:1210849dba19 132 toolchain_name - the string that identifies the build tools
screamer 29:1210849dba19 133 """
screamer 24:25bff2709c20 134 # Convert src_paths to a list if needed
theotherjimmy 43:2a7da56ebd24 135 if not isinstance(src_paths, list):
screamer 24:25bff2709c20 136 src_paths = [src_paths]
screamer 1:a99c8e460c5c 137
theotherjimmy 43:2a7da56ebd24 138 res = Resources(MockNotifier())
theotherjimmy 43:2a7da56ebd24 139 if toolchain_name:
theotherjimmy 43:2a7da56ebd24 140 toolchain = prepare_toolchain(src_paths, None, target, toolchain_name,
theotherjimmy 43:2a7da56ebd24 141 app_config=app_config)
theotherjimmy 43:2a7da56ebd24 142 config = toolchain.config
theotherjimmy 43:2a7da56ebd24 143 res.scan_with_toolchain(src_paths, toolchain, exclude=False)
theotherjimmy 43:2a7da56ebd24 144 else:
theotherjimmy 43:2a7da56ebd24 145 config = Config(target, src_paths, app_config=app_config)
theotherjimmy 43:2a7da56ebd24 146 res.scan_with_config(src_paths, config)
theotherjimmy 43:2a7da56ebd24 147 if config.has_regions:
theotherjimmy 43:2a7da56ebd24 148 _ = list(config.regions)
screamer 13:ab47a20b66f0 149
theotherjimmy 43:2a7da56ebd24 150 cfg, macros = config.get_config_data()
theotherjimmy 43:2a7da56ebd24 151 features = config.get_features()
screamer 13:ab47a20b66f0 152 return cfg, macros, features
screamer 7:5af61d55adbe 153
screamer 24:25bff2709c20 154 def is_official_target(target_name, version):
screamer 24:25bff2709c20 155 """ Returns True, None if a target is part of the official release for the
screamer 24:25bff2709c20 156 given version. Return False, 'reason' if a target is not part of the
screamer 24:25bff2709c20 157 official release for the given version.
screamer 24:25bff2709c20 158
screamer 29:1210849dba19 159 Positional arguments:
screamer 29:1210849dba19 160 target_name - Name if the target (ex. 'K64F')
screamer 29:1210849dba19 161 version - The release version string. Should be a string contained within
screamer 29:1210849dba19 162 RELEASE_VERSIONS
screamer 24:25bff2709c20 163 """
screamer 29:1210849dba19 164
screamer 24:25bff2709c20 165 result = True
screamer 24:25bff2709c20 166 reason = None
screamer 24:25bff2709c20 167 target = TARGET_MAP[target_name]
screamer 29:1210849dba19 168
screamer 29:1210849dba19 169 if hasattr(target, 'release_versions') \
screamer 29:1210849dba19 170 and version in target.release_versions:
screamer 24:25bff2709c20 171 if version == '2':
screamer 24:25bff2709c20 172 # For version 2, either ARM or uARM toolchain support is required
screamer 24:25bff2709c20 173 required_toolchains = set(['ARM', 'uARM'])
screamer 29:1210849dba19 174
screamer 29:1210849dba19 175 if not len(required_toolchains.intersection(
screamer 29:1210849dba19 176 set(target.supported_toolchains))) > 0:
screamer 29:1210849dba19 177 result = False
screamer 24:25bff2709c20 178 reason = ("Target '%s' must support " % target.name) + \
screamer 29:1210849dba19 179 ("one of the folowing toolchains to be included in the") + \
screamer 29:1210849dba19 180 ((" mbed 2.0 official release: %s" + linesep) %
screamer 29:1210849dba19 181 ", ".join(required_toolchains)) + \
screamer 24:25bff2709c20 182 ("Currently it is only configured to support the ") + \
screamer 29:1210849dba19 183 ("following toolchains: %s" %
screamer 29:1210849dba19 184 ", ".join(target.supported_toolchains))
screamer 29:1210849dba19 185
screamer 24:25bff2709c20 186 elif version == '5':
screamer 24:25bff2709c20 187 # For version 5, ARM, GCC_ARM, and IAR toolchain support is required
theotherjimmy 43:2a7da56ebd24 188 required_toolchains = [
theotherjimmy 43:2a7da56ebd24 189 set(['ARM', 'GCC_ARM', 'IAR']),
theotherjimmy 43:2a7da56ebd24 190 set(['ARMC6'])
theotherjimmy 43:2a7da56ebd24 191 ]
screamer 24:25bff2709c20 192 supported_toolchains = set(target.supported_toolchains)
screamer 29:1210849dba19 193
theotherjimmy 43:2a7da56ebd24 194 if not any(r.issubset(supported_toolchains)
theotherjimmy 43:2a7da56ebd24 195 for r in required_toolchains):
screamer 24:25bff2709c20 196 result = False
screamer 24:25bff2709c20 197 reason = ("Target '%s' must support " % target.name) + \
screamer 29:1210849dba19 198 ("ALL of the folowing toolchains to be included in the") + \
screamer 29:1210849dba19 199 ((" mbed OS 5.0 official release: %s" + linesep) %
theotherjimmy 43:2a7da56ebd24 200 ", ".join(sorted(required_toolchains[0]))) + \
screamer 24:25bff2709c20 201 ("Currently it is only configured to support the ") + \
screamer 29:1210849dba19 202 ("following toolchains: %s" %
theotherjimmy 43:2a7da56ebd24 203 ", ".join(sorted(supported_toolchains)))
screamer 24:25bff2709c20 204
The Other Jimmy 31:8ea194f6145b 205 elif not target.default_lib == 'std':
screamer 24:25bff2709c20 206 result = False
screamer 29:1210849dba19 207 reason = ("Target '%s' must set the " % target.name) + \
The Other Jimmy 31:8ea194f6145b 208 ("'default_lib' to 'std' to be included in the ") + \
screamer 29:1210849dba19 209 ("mbed OS 5.0 official release." + linesep) + \
The Other Jimmy 31:8ea194f6145b 210 ("Currently it is set to '%s'" % target.default_lib)
screamer 24:25bff2709c20 211
screamer 24:25bff2709c20 212 else:
screamer 24:25bff2709c20 213 result = False
screamer 29:1210849dba19 214 reason = ("Target '%s' has set an invalid release version of '%s'" %
screamer 29:1210849dba19 215 version) + \
screamer 29:1210849dba19 216 ("Please choose from the following release versions: %s" %
screamer 29:1210849dba19 217 ', '.join(RELEASE_VERSIONS))
screamer 24:25bff2709c20 218
screamer 24:25bff2709c20 219 else:
screamer 24:25bff2709c20 220 result = False
screamer 24:25bff2709c20 221 if not hasattr(target, 'release_versions'):
screamer 29:1210849dba19 222 reason = "Target '%s' " % target.name
screamer 29:1210849dba19 223 reason += "does not have the 'release_versions' key set"
screamer 24:25bff2709c20 224 elif not version in target.release_versions:
screamer 29:1210849dba19 225 reason = "Target '%s' does not contain the version '%s' " % \
screamer 29:1210849dba19 226 (target.name, version)
screamer 29:1210849dba19 227 reason += "in its 'release_versions' key"
screamer 29:1210849dba19 228
screamer 24:25bff2709c20 229 return result, reason
screamer 24:25bff2709c20 230
screamer 24:25bff2709c20 231 def transform_release_toolchains(toolchains, version):
screamer 24:25bff2709c20 232 """ Given a list of toolchains and a release version, return a list of
screamer 24:25bff2709c20 233 only the supported toolchains for that release
screamer 24:25bff2709c20 234
screamer 29:1210849dba19 235 Positional arguments:
screamer 29:1210849dba19 236 toolchains - The list of toolchains
screamer 29:1210849dba19 237 version - The release version string. Should be a string contained within
screamer 29:1210849dba19 238 RELEASE_VERSIONS
screamer 24:25bff2709c20 239 """
screamer 24:25bff2709c20 240 if version == '5':
screamer 24:25bff2709c20 241 return ['ARM', 'GCC_ARM', 'IAR']
screamer 24:25bff2709c20 242 else:
screamer 24:25bff2709c20 243 return toolchains
screamer 24:25bff2709c20 244
screamer 24:25bff2709c20 245
screamer 24:25bff2709c20 246 def get_mbed_official_release(version):
screamer 24:25bff2709c20 247 """ Given a release version string, return a tuple that contains a target
screamer 24:25bff2709c20 248 and the supported toolchains for that release.
screamer 29:1210849dba19 249 Ex. Given '2', return (('LPC1768', ('ARM', 'GCC_ARM')),
screamer 29:1210849dba19 250 ('K64F', ('ARM', 'GCC_ARM')), ...)
screamer 24:25bff2709c20 251
screamer 29:1210849dba19 252 Positional arguments:
screamer 29:1210849dba19 253 version - The version string. Should be a string contained within
screamer 29:1210849dba19 254 RELEASE_VERSIONS
screamer 7:5af61d55adbe 255 """
screamer 7:5af61d55adbe 256
screamer 29:1210849dba19 257 mbed_official_release = (
screamer 24:25bff2709c20 258 tuple(
screamer 24:25bff2709c20 259 tuple(
screamer 24:25bff2709c20 260 [
screamer 24:25bff2709c20 261 TARGET_MAP[target].name,
screamer 29:1210849dba19 262 tuple(transform_release_toolchains(
screamer 29:1210849dba19 263 TARGET_MAP[target].supported_toolchains, version))
screamer 24:25bff2709c20 264 ]
screamer 29:1210849dba19 265 ) for target in TARGET_NAMES \
screamer 29:1210849dba19 266 if (hasattr(TARGET_MAP[target], 'release_versions')
screamer 29:1210849dba19 267 and version in TARGET_MAP[target].release_versions)
screamer 24:25bff2709c20 268 )
screamer 24:25bff2709c20 269 )
screamer 29:1210849dba19 270
screamer 29:1210849dba19 271 for target in mbed_official_release:
screamer 24:25bff2709c20 272 is_official, reason = is_official_target(target[0], version)
screamer 29:1210849dba19 273
screamer 24:25bff2709c20 274 if not is_official:
screamer 24:25bff2709c20 275 raise InvalidReleaseTargetException(reason)
screamer 29:1210849dba19 276
screamer 29:1210849dba19 277 return mbed_official_release
screamer 24:25bff2709c20 278
theotherjimmy 43:2a7da56ebd24 279 ARM_COMPILERS = ("ARM", "ARMC6", "uARM")
theotherjimmy 43:2a7da56ebd24 280 def target_supports_toolchain(target, toolchain_name):
theotherjimmy 43:2a7da56ebd24 281 if toolchain_name in ARM_COMPILERS:
theotherjimmy 43:2a7da56ebd24 282 return any(tc in target.supported_toolchains for tc in ARM_COMPILERS)
theotherjimmy 43:2a7da56ebd24 283 else:
theotherjimmy 43:2a7da56ebd24 284 return toolchain_name in target.supported_toolchains
The Other Jimmy 36:96847d42f010 285
The Other Jimmy 36:96847d42f010 286
The Other Jimmy 36:96847d42f010 287 def prepare_toolchain(src_paths, build_dir, target, toolchain_name,
The Other Jimmy 31:8ea194f6145b 288 macros=None, clean=False, jobs=1,
theotherjimmy 43:2a7da56ebd24 289 notify=None, config=None, app_config=None,
theotherjimmy 43:2a7da56ebd24 290 build_profile=None, ignore=None):
screamer 24:25bff2709c20 291 """ Prepares resource related objects - toolchain, target, config
screamer 29:1210849dba19 292
screamer 29:1210849dba19 293 Positional arguments:
screamer 29:1210849dba19 294 src_paths - the paths to source directories
The Other Jimmy 36:96847d42f010 295 target - ['LPC1768', 'LPC11U24', etc.]
screamer 29:1210849dba19 296 toolchain_name - ['ARM', 'uARM', 'GCC_ARM', 'GCC_CR']
screamer 29:1210849dba19 297
screamer 29:1210849dba19 298 Keyword arguments:
screamer 29:1210849dba19 299 macros - additional macros
screamer 29:1210849dba19 300 clean - Rebuild everything if True
screamer 29:1210849dba19 301 jobs - how many compilers we can run at once
screamer 29:1210849dba19 302 notify - Notify function for logs
screamer 29:1210849dba19 303 config - a Config object to use instead of creating one
The Other Jimmy 31:8ea194f6145b 304 app_config - location of a chosen mbed_app.json file
The Other Jimmy 36:96847d42f010 305 build_profile - a list of mergeable build profiles
theotherjimmy 43:2a7da56ebd24 306 ignore - list of paths to add to mbedignore
screamer 24:25bff2709c20 307 """
screamer 7:5af61d55adbe 308
screamer 7:5af61d55adbe 309 # We need to remove all paths which are repeated to avoid
screamer 7:5af61d55adbe 310 # multiple compilations and linking with the same objects
screamer 7:5af61d55adbe 311 src_paths = [src_paths[0]] + list(set(src_paths[1:]))
screamer 7:5af61d55adbe 312
screamer 7:5af61d55adbe 313 # If the configuration object was not yet created, create it now
The Other Jimmy 31:8ea194f6145b 314 config = config or Config(target, src_paths, app_config=app_config)
The Other Jimmy 31:8ea194f6145b 315 target = config.target
theotherjimmy 43:2a7da56ebd24 316 if not target_supports_toolchain(target, toolchain_name):
theotherjimmy 43:2a7da56ebd24 317 raise NotSupportedException(
theotherjimmy 43:2a7da56ebd24 318 "Target {} is not supported by toolchain {}".format(
theotherjimmy 43:2a7da56ebd24 319 target.name, toolchain_name))
theotherjimmy 43:2a7da56ebd24 320 if (toolchain_name == "ARM" and CORE_ARCH[target.core] == 8):
theotherjimmy 43:2a7da56ebd24 321 toolchain_name = "ARMC6"
theotherjimmy 43:2a7da56ebd24 322
screamer 24:25bff2709c20 323 try:
The Other Jimmy 36:96847d42f010 324 cur_tc = TOOLCHAIN_CLASSES[toolchain_name]
screamer 29:1210849dba19 325 except KeyError:
screamer 24:25bff2709c20 326 raise KeyError("Toolchain %s not supported" % toolchain_name)
screamer 24:25bff2709c20 327
The Other Jimmy 36:96847d42f010 328 profile = {'c': [], 'cxx': [], 'common': [], 'asm': [], 'ld': []}
The Other Jimmy 36:96847d42f010 329 for contents in build_profile or []:
The Other Jimmy 36:96847d42f010 330 for key in profile:
theotherjimmy 43:2a7da56ebd24 331 profile[key].extend(contents[toolchain_name].get(key, []))
The Other Jimmy 36:96847d42f010 332
theotherjimmy 43:2a7da56ebd24 333 toolchain = cur_tc(
theotherjimmy 43:2a7da56ebd24 334 target, notify, macros, build_dir=build_dir, build_profile=profile)
The Other Jimmy 36:96847d42f010 335
screamer 24:25bff2709c20 336 toolchain.config = config
screamer 24:25bff2709c20 337 toolchain.jobs = jobs
screamer 24:25bff2709c20 338 toolchain.build_all = clean
theotherjimmy 43:2a7da56ebd24 339
theotherjimmy 43:2a7da56ebd24 340 if ignore:
theotherjimmy 43:2a7da56ebd24 341 toolchain.add_ignore_patterns(root=".", base_path=".", patterns=ignore)
screamer 24:25bff2709c20 342
screamer 24:25bff2709c20 343 return toolchain
screamer 24:25bff2709c20 344
theotherjimmy 43:2a7da56ebd24 345 def _printihex(ihex):
theotherjimmy 43:2a7da56ebd24 346 import pprint
theotherjimmy 43:2a7da56ebd24 347 pprint.PrettyPrinter().pprint(ihex.todict())
theotherjimmy 43:2a7da56ebd24 348
theotherjimmy 43:2a7da56ebd24 349 def _real_region_size(region):
theotherjimmy 43:2a7da56ebd24 350 try:
theotherjimmy 43:2a7da56ebd24 351 part = intelhex_offset(region.filename, offset=region.start)
theotherjimmy 43:2a7da56ebd24 352 return (part.maxaddr() - part.minaddr()) + 1
theotherjimmy 43:2a7da56ebd24 353 except AttributeError:
theotherjimmy 43:2a7da56ebd24 354 return region.size
theotherjimmy 43:2a7da56ebd24 355
theotherjimmy 43:2a7da56ebd24 356
theotherjimmy 43:2a7da56ebd24 357 def _fill_header(region_list, current_region):
theotherjimmy 43:2a7da56ebd24 358 """Fill an application header region
theotherjimmy 43:2a7da56ebd24 359
theotherjimmy 43:2a7da56ebd24 360 This is done it three steps:
theotherjimmy 43:2a7da56ebd24 361 * Fill the whole region with zeros
theotherjimmy 43:2a7da56ebd24 362 * Fill const, timestamp and size entries with their data
theotherjimmy 43:2a7da56ebd24 363 * Fill the digests using this header as the header region
theotherjimmy 43:2a7da56ebd24 364 """
theotherjimmy 43:2a7da56ebd24 365 region_dict = {r.name: r for r in region_list}
theotherjimmy 43:2a7da56ebd24 366 header = IntelHex()
theotherjimmy 43:2a7da56ebd24 367 header.puts(current_region.start, b'\x00' * current_region.size)
theotherjimmy 43:2a7da56ebd24 368 start = current_region.start
theotherjimmy 43:2a7da56ebd24 369 for member in current_region.filename:
theotherjimmy 43:2a7da56ebd24 370 _, type, subtype, data = member
theotherjimmy 43:2a7da56ebd24 371 member_size = Config.header_member_size(member)
theotherjimmy 43:2a7da56ebd24 372 if type == "const":
theotherjimmy 43:2a7da56ebd24 373 fmt = {
theotherjimmy 43:2a7da56ebd24 374 "8le": ">B", "16le": "<H", "32le": "<L", "64le": "<Q",
theotherjimmy 43:2a7da56ebd24 375 "8be": "<B", "16be": ">H", "32be": ">L", "64be": ">Q"
theotherjimmy 43:2a7da56ebd24 376 }[subtype]
theotherjimmy 43:2a7da56ebd24 377 header.puts(start, struct.pack(fmt, integer(data, 0)))
theotherjimmy 43:2a7da56ebd24 378 elif type == "timestamp":
theotherjimmy 43:2a7da56ebd24 379 fmt = {"32le": "<L", "64le": "<Q",
theotherjimmy 43:2a7da56ebd24 380 "32be": ">L", "64be": ">Q"}[subtype]
theotherjimmy 43:2a7da56ebd24 381 header.puts(start, struct.pack(fmt, time()))
theotherjimmy 43:2a7da56ebd24 382 elif type == "size":
theotherjimmy 43:2a7da56ebd24 383 fmt = {"32le": "<L", "64le": "<Q",
theotherjimmy 43:2a7da56ebd24 384 "32be": ">L", "64be": ">Q"}[subtype]
theotherjimmy 43:2a7da56ebd24 385 size = sum(_real_region_size(region_dict[r]) for r in data)
theotherjimmy 43:2a7da56ebd24 386 header.puts(start, struct.pack(fmt, size))
theotherjimmy 43:2a7da56ebd24 387 elif type == "digest":
theotherjimmy 43:2a7da56ebd24 388 if data == "header":
theotherjimmy 43:2a7da56ebd24 389 ih = header[:start]
theotherjimmy 43:2a7da56ebd24 390 else:
theotherjimmy 43:2a7da56ebd24 391 ih = intelhex_offset(region_dict[data].filename, offset=region_dict[data].start)
theotherjimmy 43:2a7da56ebd24 392 if subtype.startswith("CRCITT32"):
theotherjimmy 43:2a7da56ebd24 393 fmt = {"CRCITT32be": ">l", "CRCITT32le": "<l"}[subtype]
theotherjimmy 43:2a7da56ebd24 394 header.puts(start, struct.pack(fmt, zlib.crc32(ih.tobinarray())))
theotherjimmy 43:2a7da56ebd24 395 elif subtype.startswith("SHA"):
theotherjimmy 43:2a7da56ebd24 396 if subtype == "SHA256":
theotherjimmy 43:2a7da56ebd24 397 hash = hashlib.sha256()
theotherjimmy 43:2a7da56ebd24 398 elif subtype == "SHA512":
theotherjimmy 43:2a7da56ebd24 399 hash = hashlib.sha512()
theotherjimmy 43:2a7da56ebd24 400 hash.update(ih.tobinarray())
theotherjimmy 43:2a7da56ebd24 401 header.puts(start, hash.digest())
theotherjimmy 43:2a7da56ebd24 402 start += Config.header_member_size(member)
theotherjimmy 43:2a7da56ebd24 403 return header
theotherjimmy 43:2a7da56ebd24 404
theotherjimmy 43:2a7da56ebd24 405 def merge_region_list(region_list, destination, notify, padding=b'\xFF'):
theotherjimmy 43:2a7da56ebd24 406 """Merge the region_list into a single image
The Other Jimmy 36:96847d42f010 407
The Other Jimmy 36:96847d42f010 408 Positional Arguments:
The Other Jimmy 36:96847d42f010 409 region_list - list of regions, which should contain filenames
The Other Jimmy 36:96847d42f010 410 destination - file name to write all regions to
The Other Jimmy 36:96847d42f010 411 padding - bytes to fill gapps with
The Other Jimmy 36:96847d42f010 412 """
The Other Jimmy 36:96847d42f010 413 merged = IntelHex()
theotherjimmy 43:2a7da56ebd24 414 _, format = splitext(destination)
The Other Jimmy 36:96847d42f010 415
theotherjimmy 43:2a7da56ebd24 416 notify.info("Merging Regions")
The Other Jimmy 36:96847d42f010 417
The Other Jimmy 36:96847d42f010 418 for region in region_list:
The Other Jimmy 36:96847d42f010 419 if region.active and not region.filename:
The Other Jimmy 36:96847d42f010 420 raise ToolException("Active region has no contents: No file found.")
theotherjimmy 43:2a7da56ebd24 421 if isinstance(region.filename, list):
theotherjimmy 43:2a7da56ebd24 422 header_basename, _ = splitext(destination)
theotherjimmy 43:2a7da56ebd24 423 header_filename = header_basename + "_header.hex"
theotherjimmy 43:2a7da56ebd24 424 _fill_header(region_list, region).tofile(header_filename, format='hex')
theotherjimmy 43:2a7da56ebd24 425 region = region._replace(filename=header_filename)
The Other Jimmy 36:96847d42f010 426 if region.filename:
theotherjimmy 43:2a7da56ebd24 427 notify.info(" Filling region %s with %s" % (region.name, region.filename))
The Other Jimmy 36:96847d42f010 428 part = intelhex_offset(region.filename, offset=region.start)
theotherjimmy 43:2a7da56ebd24 429 part.start_addr = None
The Other Jimmy 36:96847d42f010 430 part_size = (part.maxaddr() - part.minaddr()) + 1
The Other Jimmy 36:96847d42f010 431 if part_size > region.size:
The Other Jimmy 36:96847d42f010 432 raise ToolException("Contents of region %s does not fit"
The Other Jimmy 36:96847d42f010 433 % region.name)
The Other Jimmy 36:96847d42f010 434 merged.merge(part)
The Other Jimmy 36:96847d42f010 435 pad_size = region.size - part_size
The Other Jimmy 36:96847d42f010 436 if pad_size > 0 and region != region_list[-1]:
theotherjimmy 43:2a7da56ebd24 437 notify.info(" Padding region %s with 0x%x bytes" %
theotherjimmy 43:2a7da56ebd24 438 (region.name, pad_size))
theotherjimmy 43:2a7da56ebd24 439 if format is ".hex":
theotherjimmy 43:2a7da56ebd24 440 """The offset will be in the hex file generated when we're done,
theotherjimmy 43:2a7da56ebd24 441 so we can skip padding here"""
theotherjimmy 43:2a7da56ebd24 442 else:
theotherjimmy 43:2a7da56ebd24 443 merged.puts(merged.maxaddr() + 1, padding * pad_size)
The Other Jimmy 36:96847d42f010 444
The Other Jimmy 36:96847d42f010 445 if not exists(dirname(destination)):
The Other Jimmy 36:96847d42f010 446 makedirs(dirname(destination))
theotherjimmy 43:2a7da56ebd24 447 notify.info("Space used after regions merged: 0x%x" %
theotherjimmy 43:2a7da56ebd24 448 (merged.maxaddr() - merged.minaddr() + 1))
theotherjimmy 43:2a7da56ebd24 449 merged.tofile(destination, format=format.strip("."))
screamer 29:1210849dba19 450
screamer 24:25bff2709c20 451
theotherjimmy 43:2a7da56ebd24 452 UPDATE_WHITELIST = (
theotherjimmy 43:2a7da56ebd24 453 "application",
theotherjimmy 43:2a7da56ebd24 454 )
screamer 24:25bff2709c20 455
screamer 24:25bff2709c20 456
screamer 24:25bff2709c20 457 def build_project(src_paths, build_path, target, toolchain_name,
theotherjimmy 43:2a7da56ebd24 458 libraries_paths=None, linker_script=None, clean=False,
theotherjimmy 43:2a7da56ebd24 459 notify=None, name=None, macros=None, inc_dirs=None, jobs=1,
screamer 29:1210849dba19 460 report=None, properties=None, project_id=None,
theotherjimmy 43:2a7da56ebd24 461 project_description=None, config=None,
theotherjimmy 43:2a7da56ebd24 462 app_config=None, build_profile=None, stats_depth=None, ignore=None):
screamer 29:1210849dba19 463 """ Build a project. A project may be a test or a user program.
screamer 29:1210849dba19 464
screamer 29:1210849dba19 465 Positional arguments:
screamer 29:1210849dba19 466 src_paths - a path or list of paths that contain all files needed to build
screamer 29:1210849dba19 467 the project
screamer 29:1210849dba19 468 build_path - the directory where all of the object files will be placed
screamer 29:1210849dba19 469 target - the MCU or board that the project will compile for
screamer 29:1210849dba19 470 toolchain_name - the name of the build tools
screamer 29:1210849dba19 471
screamer 29:1210849dba19 472 Keyword arguments:
screamer 29:1210849dba19 473 libraries_paths - The location of libraries to include when linking
screamer 29:1210849dba19 474 linker_script - the file that drives the linker to do it's job
screamer 29:1210849dba19 475 clean - Rebuild everything if True
screamer 29:1210849dba19 476 notify - Notify function for logs
screamer 29:1210849dba19 477 name - the name of the project
screamer 29:1210849dba19 478 macros - additional macros
screamer 29:1210849dba19 479 inc_dirs - additional directories where include files may be found
screamer 29:1210849dba19 480 jobs - how many compilers we can run at once
screamer 29:1210849dba19 481 report - a dict where a result may be appended
screamer 29:1210849dba19 482 properties - UUUUHHHHH beats me
screamer 29:1210849dba19 483 project_id - the name put in the report
screamer 29:1210849dba19 484 project_description - the human-readable version of what this thing does
screamer 29:1210849dba19 485 config - a Config object to use instead of creating one
The Other Jimmy 31:8ea194f6145b 486 app_config - location of a chosen mbed_app.json file
The Other Jimmy 31:8ea194f6145b 487 build_profile - a dict of flags that will be passed to the compiler
theotherjimmy 40:7d3fa6b99b2b 488 stats_depth - depth level for memap to display file/dirs
theotherjimmy 43:2a7da56ebd24 489 ignore - list of paths to add to mbedignore
screamer 24:25bff2709c20 490 """
screamer 24:25bff2709c20 491 # Convert src_path to a list if needed
theotherjimmy 43:2a7da56ebd24 492 if not isinstance(src_paths, list):
screamer 24:25bff2709c20 493 src_paths = [src_paths]
screamer 24:25bff2709c20 494 # Extend src_paths wiht libraries_paths
screamer 24:25bff2709c20 495 if libraries_paths is not None:
screamer 24:25bff2709c20 496 src_paths.extend(libraries_paths)
The Other Jimmy 31:8ea194f6145b 497 inc_dirs.extend(map(dirname, libraries_paths))
screamer 24:25bff2709c20 498
screamer 29:1210849dba19 499 if clean and exists(build_path):
screamer 29:1210849dba19 500 rmtree(build_path)
screamer 24:25bff2709c20 501 mkdir(build_path)
screamer 24:25bff2709c20 502
screamer 24:25bff2709c20 503 ###################################
screamer 24:25bff2709c20 504 # mbed Classic/2.0/libary support #
screamer 24:25bff2709c20 505
screamer 14:ee1b877e6839 506 # Find build system profile
screamer 14:ee1b877e6839 507 profile = None
screamer 24:25bff2709c20 508 targets_json = None
screamer 14:ee1b877e6839 509 for path in src_paths:
screamer 14:ee1b877e6839 510 profile = find_build_profile(path) or profile
screamer 27:5461402c33f8 511 if profile:
screamer 29:1210849dba19 512 targets_json = join(dirname(abspath(__file__)), 'legacy_targets.json')
screamer 27:5461402c33f8 513 else:
screamer 27:5461402c33f8 514 targets_json = find_targets_json(path) or targets_json
screamer 14:ee1b877e6839 515
screamer 24:25bff2709c20 516 # Apply targets.json to active targets
screamer 24:25bff2709c20 517 if targets_json:
screamer 24:25bff2709c20 518 if verbose:
screamer 24:25bff2709c20 519 print("Using targets from %s" % targets_json)
screamer 24:25bff2709c20 520 set_targets_json_location(targets_json)
screamer 24:25bff2709c20 521
screamer 24:25bff2709c20 522 # Apply profile to toolchains
screamer 14:ee1b877e6839 523 if profile:
screamer 14:ee1b877e6839 524 def init_hook(self):
screamer 14:ee1b877e6839 525 profile_data = get_toolchain_profile(self.name, profile)
screamer 14:ee1b877e6839 526 if not profile_data:
screamer 14:ee1b877e6839 527 return
theotherjimmy 43:2a7da56ebd24 528 notify.info("Using toolchain %s profile %s" % (self.name, profile))
screamer 14:ee1b877e6839 529
screamer 14:ee1b877e6839 530 for k,v in profile_data.items():
screamer 14:ee1b877e6839 531 if self.flags.has_key(k):
screamer 14:ee1b877e6839 532 self.flags[k] = v
screamer 14:ee1b877e6839 533 else:
screamer 14:ee1b877e6839 534 setattr(self, k, v)
screamer 14:ee1b877e6839 535
screamer 14:ee1b877e6839 536 mbedToolchain.init = init_hook
screamer 14:ee1b877e6839 537
The Other Jimmy 31:8ea194f6145b 538 # mbed Classic/2.0/libary support #
The Other Jimmy 31:8ea194f6145b 539 ###################################
The Other Jimmy 31:8ea194f6145b 540
screamer 29:1210849dba19 541 toolchain = prepare_toolchain(
The Other Jimmy 36:96847d42f010 542 src_paths, build_path, target, toolchain_name, macros=macros,
theotherjimmy 43:2a7da56ebd24 543 clean=clean, jobs=jobs, notify=notify, config=config,
theotherjimmy 43:2a7da56ebd24 544 app_config=app_config, build_profile=build_profile, ignore=ignore)
theotherjimmy 43:2a7da56ebd24 545 toolchain.version_check()
screamer 0:66f3b5499f7f 546
screamer 24:25bff2709c20 547 # The first path will give the name to the library
The Other Jimmy 36:96847d42f010 548 name = (name or toolchain.config.name or
The Other Jimmy 36:96847d42f010 549 basename(normpath(abspath(src_paths[0]))))
theotherjimmy 43:2a7da56ebd24 550 notify.info("Building project %s (%s, %s)" %
theotherjimmy 43:2a7da56ebd24 551 (name, toolchain.target.name, toolchain_name))
screamer 0:66f3b5499f7f 552
screamer 24:25bff2709c20 553 # Initialize reporting
screamer 0:66f3b5499f7f 554 if report != None:
screamer 0:66f3b5499f7f 555 start = time()
screamer 7:5af61d55adbe 556 # If project_id is specified, use that over the default name
screamer 7:5af61d55adbe 557 id_name = project_id.upper() if project_id else name.upper()
screamer 7:5af61d55adbe 558 description = project_description if project_description else name
screamer 24:25bff2709c20 559 vendor_label = toolchain.target.extra_labels[0]
screamer 24:25bff2709c20 560 prep_report(report, toolchain.target.name, toolchain_name, id_name)
screamer 29:1210849dba19 561 cur_result = create_result(toolchain.target.name, toolchain_name,
screamer 29:1210849dba19 562 id_name, description)
screamer 0:66f3b5499f7f 563 if properties != None:
screamer 29:1210849dba19 564 prep_properties(properties, toolchain.target.name, toolchain_name,
screamer 29:1210849dba19 565 vendor_label)
screamer 0:66f3b5499f7f 566
screamer 0:66f3b5499f7f 567 try:
theotherjimmy 43:2a7da56ebd24 568 resources = Resources(notify).scan_with_toolchain(
theotherjimmy 43:2a7da56ebd24 569 src_paths, toolchain, inc_dirs=inc_dirs)
screamer 0:66f3b5499f7f 570
screamer 24:25bff2709c20 571 # Change linker script if specified
screamer 0:66f3b5499f7f 572 if linker_script is not None:
theotherjimmy 43:2a7da56ebd24 573 resources.add_file_ref(linker_script, linker_script)
screamer 0:66f3b5499f7f 574
screamer 0:66f3b5499f7f 575 # Compile Sources
theotherjimmy 43:2a7da56ebd24 576 objects = toolchain.compile_sources(resources, sorted(resources.get_file_paths(FileType.INC_DIR)))
theotherjimmy 43:2a7da56ebd24 577 resources.add_files_to_type(FileType.OBJECT, objects)
screamer 0:66f3b5499f7f 578
screamer 0:66f3b5499f7f 579 # Link Program
The Other Jimmy 36:96847d42f010 580 if toolchain.config.has_regions:
theotherjimmy 43:2a7da56ebd24 581 binary, _ = toolchain.link_program(resources, build_path, name + "_application")
The Other Jimmy 36:96847d42f010 582 region_list = list(toolchain.config.regions)
theotherjimmy 43:2a7da56ebd24 583 region_list = [r._replace(filename=binary) if r.active else r
The Other Jimmy 36:96847d42f010 584 for r in region_list]
theotherjimmy 43:2a7da56ebd24 585 res = "%s.%s" % (join(build_path, name),
theotherjimmy 43:2a7da56ebd24 586 getattr(toolchain.target, "OUTPUT_EXT", "bin"))
theotherjimmy 43:2a7da56ebd24 587 merge_region_list(region_list, res, notify)
theotherjimmy 43:2a7da56ebd24 588 update_regions = [
theotherjimmy 43:2a7da56ebd24 589 r for r in region_list if r.name in UPDATE_WHITELIST
theotherjimmy 43:2a7da56ebd24 590 ]
theotherjimmy 43:2a7da56ebd24 591 if update_regions:
theotherjimmy 43:2a7da56ebd24 592 update_res = "%s_update.%s" % (
theotherjimmy 43:2a7da56ebd24 593 join(build_path, name),
theotherjimmy 43:2a7da56ebd24 594 getattr(toolchain.target, "OUTPUT_EXT", "bin")
theotherjimmy 43:2a7da56ebd24 595 )
theotherjimmy 43:2a7da56ebd24 596 merge_region_list(update_regions, update_res, notify)
theotherjimmy 43:2a7da56ebd24 597 res = (res, update_res)
theotherjimmy 43:2a7da56ebd24 598 else:
theotherjimmy 43:2a7da56ebd24 599 res = (res, None)
The Other Jimmy 36:96847d42f010 600 else:
The Other Jimmy 36:96847d42f010 601 res, _ = toolchain.link_program(resources, build_path, name)
theotherjimmy 43:2a7da56ebd24 602 res = (res, None)
screamer 0:66f3b5499f7f 603
The Other Jimmy 31:8ea194f6145b 604 memap_instance = getattr(toolchain, 'memap_instance', None)
The Other Jimmy 31:8ea194f6145b 605 memap_table = ''
The Other Jimmy 31:8ea194f6145b 606 if memap_instance:
The Other Jimmy 31:8ea194f6145b 607 # Write output to stdout in text (pretty table) format
theotherjimmy 40:7d3fa6b99b2b 608 memap_table = memap_instance.generate_output('table', stats_depth)
theotherjimmy 43:2a7da56ebd24 609 notify.info(memap_table)
The Other Jimmy 31:8ea194f6145b 610
The Other Jimmy 31:8ea194f6145b 611 # Write output to file in JSON format
The Other Jimmy 31:8ea194f6145b 612 map_out = join(build_path, name + "_map.json")
theotherjimmy 40:7d3fa6b99b2b 613 memap_instance.generate_output('json', stats_depth, map_out)
The Other Jimmy 31:8ea194f6145b 614
The Other Jimmy 31:8ea194f6145b 615 # Write output to file in CSV format for the CI
The Other Jimmy 31:8ea194f6145b 616 map_csv = join(build_path, name + "_map.csv")
theotherjimmy 40:7d3fa6b99b2b 617 memap_instance.generate_output('csv-ci', stats_depth, map_csv)
The Other Jimmy 31:8ea194f6145b 618
theotherjimmy 43:2a7da56ebd24 619 map_html = join(build_path, name + "_map.html")
theotherjimmy 43:2a7da56ebd24 620 memap_instance.generate_output('html', stats_depth, map_html)
theotherjimmy 43:2a7da56ebd24 621
theotherjimmy 43:2a7da56ebd24 622 resources.detect_duplicates()
The Other Jimmy 31:8ea194f6145b 623
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 624 if report != None:
screamer 0:66f3b5499f7f 625 end = time()
screamer 0:66f3b5499f7f 626 cur_result["elapsed_time"] = end - start
screamer 0:66f3b5499f7f 627 cur_result["result"] = "OK"
theotherjimmy 43:2a7da56ebd24 628 cur_result["memory_usage"] = (memap_instance.mem_report
theotherjimmy 43:2a7da56ebd24 629 if memap_instance is not None else None)
theotherjimmy 43:2a7da56ebd24 630 cur_result["bin"] = res[0]
theotherjimmy 43:2a7da56ebd24 631 cur_result["elf"] = splitext(res[0])[0] + ".elf"
The Other Jimmy 36:96847d42f010 632 cur_result.update(toolchain.report)
screamer 0:66f3b5499f7f 633
screamer 0:66f3b5499f7f 634 add_result_to_report(report, cur_result)
screamer 0:66f3b5499f7f 635
screamer 0:66f3b5499f7f 636 return res
screamer 0:66f3b5499f7f 637
screamer 29:1210849dba19 638 except Exception as exc:
screamer 0:66f3b5499f7f 639 if report != None:
screamer 0:66f3b5499f7f 640 end = time()
screamer 0:66f3b5499f7f 641
screamer 29:1210849dba19 642 if isinstance(exc, NotSupportedException):
screamer 0:66f3b5499f7f 643 cur_result["result"] = "NOT_SUPPORTED"
screamer 0:66f3b5499f7f 644 else:
screamer 0:66f3b5499f7f 645 cur_result["result"] = "FAIL"
screamer 0:66f3b5499f7f 646
screamer 0:66f3b5499f7f 647 cur_result["elapsed_time"] = end - start
screamer 0:66f3b5499f7f 648
screamer 0:66f3b5499f7f 649 add_result_to_report(report, cur_result)
screamer 0:66f3b5499f7f 650 # Let Exception propagate
screamer 13:ab47a20b66f0 651 raise
screamer 0:66f3b5499f7f 652
screamer 0:66f3b5499f7f 653 def build_library(src_paths, build_path, target, toolchain_name,
The Other Jimmy 31:8ea194f6145b 654 dependencies_paths=None, name=None, clean=False,
theotherjimmy 43:2a7da56ebd24 655 archive=True, notify=None, macros=None, inc_dirs=None, jobs=1,
theotherjimmy 43:2a7da56ebd24 656 report=None, properties=None, project_id=None,
The Other Jimmy 31:8ea194f6145b 657 remove_config_header_file=False, app_config=None,
theotherjimmy 43:2a7da56ebd24 658 build_profile=None, ignore=None):
screamer 29:1210849dba19 659 """ Build a library
screamer 29:1210849dba19 660
screamer 29:1210849dba19 661 Positional arguments:
screamer 29:1210849dba19 662 src_paths - a path or list of paths that contain all files needed to build
screamer 29:1210849dba19 663 the library
screamer 29:1210849dba19 664 build_path - the directory where all of the object files will be placed
screamer 29:1210849dba19 665 target - the MCU or board that the project will compile for
screamer 29:1210849dba19 666 toolchain_name - the name of the build tools
screamer 29:1210849dba19 667
screamer 29:1210849dba19 668 Keyword arguments:
screamer 29:1210849dba19 669 dependencies_paths - The location of libraries to include when linking
screamer 29:1210849dba19 670 name - the name of the library
screamer 29:1210849dba19 671 clean - Rebuild everything if True
screamer 29:1210849dba19 672 archive - whether the library will create an archive file
screamer 29:1210849dba19 673 notify - Notify function for logs
screamer 29:1210849dba19 674 macros - additional macros
screamer 29:1210849dba19 675 inc_dirs - additional directories where include files may be found
screamer 29:1210849dba19 676 jobs - how many compilers we can run at once
screamer 29:1210849dba19 677 report - a dict where a result may be appended
screamer 29:1210849dba19 678 properties - UUUUHHHHH beats me
screamer 29:1210849dba19 679 project_id - the name that goes in the report
The Other Jimmy 31:8ea194f6145b 680 remove_config_header_file - delete config header file when done building
The Other Jimmy 31:8ea194f6145b 681 app_config - location of a chosen mbed_app.json file
The Other Jimmy 31:8ea194f6145b 682 build_profile - a dict of flags that will be passed to the compiler
theotherjimmy 43:2a7da56ebd24 683 ignore - list of paths to add to mbedignore
screamer 0:66f3b5499f7f 684 """
screamer 24:25bff2709c20 685
screamer 24:25bff2709c20 686 # Convert src_path to a list if needed
theotherjimmy 43:2a7da56ebd24 687 if not isinstance(src_paths, list):
screamer 0:66f3b5499f7f 688 src_paths = [src_paths]
theotherjimmy 43:2a7da56ebd24 689 src_paths = [relpath(s) for s in src_paths]
screamer 0:66f3b5499f7f 690
screamer 24:25bff2709c20 691 # Build path
screamer 24:25bff2709c20 692 if archive:
screamer 24:25bff2709c20 693 # Use temp path when building archive
screamer 24:25bff2709c20 694 tmp_path = join(build_path, '.temp')
screamer 24:25bff2709c20 695 mkdir(tmp_path)
screamer 24:25bff2709c20 696 else:
screamer 24:25bff2709c20 697 tmp_path = build_path
screamer 0:66f3b5499f7f 698
screamer 29:1210849dba19 699 # Clean the build directory
screamer 29:1210849dba19 700 if clean and exists(tmp_path):
screamer 29:1210849dba19 701 rmtree(tmp_path)
screamer 29:1210849dba19 702 mkdir(tmp_path)
screamer 29:1210849dba19 703
screamer 24:25bff2709c20 704 # Pass all params to the unified prepare_toolchain()
screamer 29:1210849dba19 705 toolchain = prepare_toolchain(
The Other Jimmy 36:96847d42f010 706 src_paths, build_path, target, toolchain_name, macros=macros,
theotherjimmy 43:2a7da56ebd24 707 clean=clean, jobs=jobs, notify=notify, app_config=app_config,
theotherjimmy 43:2a7da56ebd24 708 build_profile=build_profile, ignore=ignore)
screamer 13:ab47a20b66f0 709
screamer 24:25bff2709c20 710 # The first path will give the name to the library
screamer 24:25bff2709c20 711 if name is None:
screamer 24:25bff2709c20 712 name = basename(normpath(abspath(src_paths[0])))
theotherjimmy 43:2a7da56ebd24 713 notify.info("Building library %s (%s, %s)" %
screamer 29:1210849dba19 714 (name, toolchain.target.name, toolchain_name))
screamer 13:ab47a20b66f0 715
screamer 24:25bff2709c20 716 # Initialize reporting
screamer 0:66f3b5499f7f 717 if report != None:
screamer 0:66f3b5499f7f 718 start = time()
screamer 7:5af61d55adbe 719 # If project_id is specified, use that over the default name
screamer 7:5af61d55adbe 720 id_name = project_id.upper() if project_id else name.upper()
screamer 0:66f3b5499f7f 721 description = name
screamer 24:25bff2709c20 722 vendor_label = toolchain.target.extra_labels[0]
screamer 24:25bff2709c20 723 prep_report(report, toolchain.target.name, toolchain_name, id_name)
screamer 29:1210849dba19 724 cur_result = create_result(toolchain.target.name, toolchain_name,
screamer 29:1210849dba19 725 id_name, description)
The Other Jimmy 36:96847d42f010 726 cur_result['type'] = 'library'
screamer 0:66f3b5499f7f 727 if properties != None:
screamer 29:1210849dba19 728 prep_properties(properties, toolchain.target.name, toolchain_name,
screamer 29:1210849dba19 729 vendor_label)
screamer 0:66f3b5499f7f 730
screamer 0:66f3b5499f7f 731 for src_path in src_paths:
screamer 0:66f3b5499f7f 732 if not exists(src_path):
screamer 0:66f3b5499f7f 733 error_msg = "The library source folder does not exist: %s", src_path
screamer 0:66f3b5499f7f 734 if report != None:
screamer 0:66f3b5499f7f 735 cur_result["output"] = error_msg
screamer 0:66f3b5499f7f 736 cur_result["result"] = "FAIL"
screamer 0:66f3b5499f7f 737 add_result_to_report(report, cur_result)
screamer 0:66f3b5499f7f 738 raise Exception(error_msg)
screamer 0:66f3b5499f7f 739
screamer 0:66f3b5499f7f 740 try:
theotherjimmy 43:2a7da56ebd24 741 res = Resources(notify).scan_with_toolchain(
theotherjimmy 43:2a7da56ebd24 742 src_paths, toolchain, dependencies_paths, inc_dirs=inc_dirs)
screamer 13:ab47a20b66f0 743
screamer 29:1210849dba19 744 # Copy headers, objects and static libraries - all files needed for
screamer 29:1210849dba19 745 # static lib
theotherjimmy 43:2a7da56ebd24 746 to_copy = (
theotherjimmy 43:2a7da56ebd24 747 res.get_file_refs(FileType.HEADER) +
theotherjimmy 43:2a7da56ebd24 748 res.get_file_refs(FileType.OBJECT) +
theotherjimmy 43:2a7da56ebd24 749 res.get_file_refs(FileType.LIB) +
theotherjimmy 43:2a7da56ebd24 750 res.get_file_refs(FileType.JSON) +
theotherjimmy 43:2a7da56ebd24 751 res.get_file_refs(FileType.LD_SCRIPT) +
theotherjimmy 43:2a7da56ebd24 752 res.get_file_refs(FileType.HEX) +
theotherjimmy 43:2a7da56ebd24 753 res.get_file_refs(FileType.BIN)
theotherjimmy 43:2a7da56ebd24 754 )
theotherjimmy 43:2a7da56ebd24 755 toolchain.copy_files(to_copy, build_path)
screamer 0:66f3b5499f7f 756 # Compile Sources
theotherjimmy 43:2a7da56ebd24 757 objects = toolchain.compile_sources(
theotherjimmy 43:2a7da56ebd24 758 res, res.get_file_paths(FileType.INC_DIR))
theotherjimmy 43:2a7da56ebd24 759 res.add_files_to_type(FileType.OBJECT, objects)
screamer 0:66f3b5499f7f 760
screamer 0:66f3b5499f7f 761 if archive:
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 762 toolchain.build_library(objects, build_path, name)
screamer 0:66f3b5499f7f 763
The Other Jimmy 31:8ea194f6145b 764 if remove_config_header_file:
The Other Jimmy 31:8ea194f6145b 765 config_header_path = toolchain.get_config_header()
The Other Jimmy 31:8ea194f6145b 766 if config_header_path:
The Other Jimmy 31:8ea194f6145b 767 remove(config_header_path)
The Other Jimmy 31:8ea194f6145b 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["result"] = "OK"
screamer 0:66f3b5499f7f 773 add_result_to_report(report, cur_result)
screamer 22:9e85236d8716 774 return True
screamer 0:66f3b5499f7f 775
screamer 29:1210849dba19 776 except Exception as exc:
screamer 0:66f3b5499f7f 777 if report != None:
screamer 0:66f3b5499f7f 778 end = time()
screamer 22:9e85236d8716 779
screamer 29:1210849dba19 780 if isinstance(exc, ToolException):
screamer 7:5af61d55adbe 781 cur_result["result"] = "FAIL"
screamer 29:1210849dba19 782 elif isinstance(exc, NotSupportedException):
screamer 7:5af61d55adbe 783 cur_result["result"] = "NOT_SUPPORTED"
screamer 22:9e85236d8716 784
screamer 0:66f3b5499f7f 785 cur_result["elapsed_time"] = end - start
screamer 0:66f3b5499f7f 786
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 787 add_result_to_report(report, cur_result)
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 788
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 789 # Let Exception propagate
screamer 29:1210849dba19 790 raise
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 791
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 792 ######################
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 793 ### Legacy methods ###
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 794 ######################
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 795
The Other Jimmy 36:96847d42f010 796 def mbed2_obj_path(target_name, toolchain_name):
The Other Jimmy 36:96847d42f010 797 real_tc_name = TOOLCHAIN_CLASSES[toolchain_name].__name__
The Other Jimmy 36:96847d42f010 798 return join("TARGET_" + target_name, "TOOLCHAIN_" + real_tc_name)
The Other Jimmy 36:96847d42f010 799
theotherjimmy 43:2a7da56ebd24 800 def build_lib(lib_id, target, toolchain_name, clean=False, macros=None,
theotherjimmy 43:2a7da56ebd24 801 notify=None, jobs=1, report=None, properties=None,
theotherjimmy 43:2a7da56ebd24 802 build_profile=None, ignore=None):
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 803 """ Legacy method for building mbed libraries
screamer 29:1210849dba19 804
screamer 29:1210849dba19 805 Positional arguments:
screamer 29:1210849dba19 806 lib_id - the library's unique identifier
screamer 29:1210849dba19 807 target - the MCU or board that the project will compile for
screamer 29:1210849dba19 808 toolchain_name - the name of the build tools
screamer 29:1210849dba19 809
screamer 29:1210849dba19 810 Keyword arguments:
screamer 29:1210849dba19 811 clean - Rebuild everything if True
screamer 29:1210849dba19 812 macros - additional macros
screamer 29:1210849dba19 813 notify - Notify function for logs
screamer 29:1210849dba19 814 jobs - how many compilers we can run at once
screamer 29:1210849dba19 815 report - a dict where a result may be appended
screamer 29:1210849dba19 816 properties - UUUUHHHHH beats me
The Other Jimmy 31:8ea194f6145b 817 build_profile - a dict of flags that will be passed to the compiler
theotherjimmy 43:2a7da56ebd24 818 ignore - list of paths to add to mbedignore
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 819 """
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 820 lib = Library(lib_id)
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 821 if not lib.is_supported(target, toolchain_name):
screamer 29:1210849dba19 822 print('Library "%s" is not yet supported on target %s with toolchain %s'
screamer 29:1210849dba19 823 % (lib_id, target.name, toolchain_name))
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 824 return False
screamer 22:9e85236d8716 825
screamer 29:1210849dba19 826 # We need to combine macros from parameter list with macros from library
screamer 29:1210849dba19 827 # definition
screamer 29:1210849dba19 828 lib_macros = lib.macros if lib.macros else []
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 829 if macros:
screamer 29:1210849dba19 830 macros.extend(lib_macros)
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 831 else:
screamer 29:1210849dba19 832 macros = lib_macros
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 833
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 834 src_paths = lib.source_dir
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 835 build_path = lib.build_dir
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 836 dependencies_paths = lib.dependencies
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 837 inc_dirs = lib.inc_dirs
screamer 22:9e85236d8716 838
theotherjimmy 43:2a7da56ebd24 839 if not isinstance(src_paths, list):
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 840 src_paths = [src_paths]
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 841
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 842 # The first path will give the name to the library
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 843 name = basename(src_paths[0])
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 844
theotherjimmy 43:2a7da56ebd24 845 if report is not None:
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 846 start = time()
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 847 id_name = name.upper()
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 848 description = name
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 849 vendor_label = target.extra_labels[0]
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 850 cur_result = None
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 851 prep_report(report, target.name, toolchain_name, id_name)
screamer 29:1210849dba19 852 cur_result = create_result(target.name, toolchain_name, id_name,
screamer 29:1210849dba19 853 description)
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 854
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 855 if properties != None:
screamer 29:1210849dba19 856 prep_properties(properties, target.name, toolchain_name,
screamer 29:1210849dba19 857 vendor_label)
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 858
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 859 for src_path in src_paths:
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 860 if not exists(src_path):
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 861 error_msg = "The library source folder does not exist: %s", src_path
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 862
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 863 if report != None:
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 864 cur_result["output"] = error_msg
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 865 cur_result["result"] = "FAIL"
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 866 add_result_to_report(report, cur_result)
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 867
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 868 raise Exception(error_msg)
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 869
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 870 try:
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 871 # Toolchain instance
The Other Jimmy 36:96847d42f010 872 # Create the desired build directory structure
The Other Jimmy 36:96847d42f010 873 bin_path = join(build_path, mbed2_obj_path(target.name, toolchain_name))
The Other Jimmy 36:96847d42f010 874 mkdir(bin_path)
The Other Jimmy 36:96847d42f010 875 tmp_path = join(build_path, '.temp', mbed2_obj_path(target.name,
The Other Jimmy 36:96847d42f010 876 toolchain_name))
The Other Jimmy 36:96847d42f010 877 mkdir(tmp_path)
The Other Jimmy 36:96847d42f010 878
The Other Jimmy 36:96847d42f010 879 toolchain = prepare_toolchain(
The Other Jimmy 36:96847d42f010 880 src_paths, tmp_path, target, toolchain_name, macros=macros,
theotherjimmy 43:2a7da56ebd24 881 notify=notify, build_profile=build_profile, jobs=jobs, clean=clean,
theotherjimmy 43:2a7da56ebd24 882 ignore=ignore)
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 883
theotherjimmy 43:2a7da56ebd24 884 notify.info("Building library %s (%s, %s)" %
theotherjimmy 43:2a7da56ebd24 885 (name.upper(), target.name, toolchain_name))
screamer 29:1210849dba19 886
screamer 29:1210849dba19 887 # Take into account the library configuration (MBED_CONFIG_FILE)
The Other Jimmy 36:96847d42f010 888 config = toolchain.config
screamer 29:1210849dba19 889 config.add_config_files([MBED_CONFIG_FILE])
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 890
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 891 # Scan Resources
theotherjimmy 43:2a7da56ebd24 892 resources = Resources(notify).scan_with_toolchain(
theotherjimmy 43:2a7da56ebd24 893 src_paths + (lib.inc_dirs_ext or []), toolchain,
theotherjimmy 43:2a7da56ebd24 894 inc_dirs=inc_dirs, dependencies_paths=dependencies_paths)
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 895
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 896 # Copy Headers
theotherjimmy 43:2a7da56ebd24 897 toolchain.copy_files(
theotherjimmy 43:2a7da56ebd24 898 resources.get_file_refs(FileType.HEADER), build_path)
screamer 22:9e85236d8716 899
theotherjimmy 43:2a7da56ebd24 900 dependencies_include_dir = Resources(notify).sacn_with_toolchain([build_path], toolchain).inc_dirs
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 901
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 902 # Compile Sources
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 903 objects = []
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 904 for resource in resources:
The Other Jimmy 36:96847d42f010 905 objects.extend(toolchain.compile_sources(resource, dependencies_include_dir))
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 906
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 907 needed_update = toolchain.build_library(objects, bin_path, name)
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 908
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 909 if report != None and needed_update:
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 910 end = time()
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 911 cur_result["elapsed_time"] = end - start
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 912 cur_result["result"] = "OK"
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 913
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 914 add_result_to_report(report, cur_result)
screamer 22:9e85236d8716 915 return True
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 916
screamer 29:1210849dba19 917 except Exception:
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 918 if report != None:
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 919 end = time()
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 920 cur_result["result"] = "FAIL"
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 921 cur_result["elapsed_time"] = end - start
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 922
screamer 0:66f3b5499f7f 923 add_result_to_report(report, cur_result)
screamer 0:66f3b5499f7f 924
screamer 0:66f3b5499f7f 925 # Let Exception propagate
screamer 29:1210849dba19 926 raise
screamer 29:1210849dba19 927
theotherjimmy 43:2a7da56ebd24 928
theotherjimmy 43:2a7da56ebd24 929 # A number of compiled files need to be copied as objects as the linker
theotherjimmy 43:2a7da56ebd24 930 # will not search for weak symbol overrides in archives. These are:
theotherjimmy 43:2a7da56ebd24 931 # - mbed_retarget.o: to make sure that the C standard lib symbols get
theotherjimmy 43:2a7da56ebd24 932 # overridden
theotherjimmy 43:2a7da56ebd24 933 # - mbed_board.o: `mbed_die` is weak
theotherjimmy 43:2a7da56ebd24 934 # - mbed_overrides.o: this contains platform overrides of various
theotherjimmy 43:2a7da56ebd24 935 # weak SDK functions
theotherjimmy 43:2a7da56ebd24 936 # - mbed_main.o: this contains main redirection
theotherjimmy 43:2a7da56ebd24 937 # - mbed_sdk_boot.o: this contains the main boot code in
theotherjimmy 43:2a7da56ebd24 938 # - PeripheralPins.o: PinMap can be weak
theotherjimmy 43:2a7da56ebd24 939 SEPARATE_NAMES = [
theotherjimmy 43:2a7da56ebd24 940 'PeripheralPins.o',
theotherjimmy 43:2a7da56ebd24 941 'mbed_retarget.o',
theotherjimmy 43:2a7da56ebd24 942 'mbed_board.o',
theotherjimmy 43:2a7da56ebd24 943 'mbed_overrides.o',
theotherjimmy 43:2a7da56ebd24 944 'mbed_main.o',
theotherjimmy 43:2a7da56ebd24 945 'mbed_sdk_boot.o',
theotherjimmy 43:2a7da56ebd24 946 ]
theotherjimmy 43:2a7da56ebd24 947
theotherjimmy 43:2a7da56ebd24 948
theotherjimmy 43:2a7da56ebd24 949 def build_mbed_libs(target, toolchain_name, clean=False, macros=None,
theotherjimmy 43:2a7da56ebd24 950 notify=None, jobs=1, report=None, properties=None,
theotherjimmy 43:2a7da56ebd24 951 build_profile=None, ignore=None):
theotherjimmy 43:2a7da56ebd24 952 """ Build legacy libraries for a target and toolchain pair
screamer 0:66f3b5499f7f 953
screamer 29:1210849dba19 954 Positional arguments:
screamer 29:1210849dba19 955 target - the MCU or board that the project will compile for
screamer 29:1210849dba19 956 toolchain_name - the name of the build tools
screamer 29:1210849dba19 957
screamer 29:1210849dba19 958 Keyword arguments:
screamer 29:1210849dba19 959 clean - Rebuild everything if True
screamer 29:1210849dba19 960 macros - additional macros
screamer 29:1210849dba19 961 notify - Notify function for logs
screamer 29:1210849dba19 962 jobs - how many compilers we can run at once
screamer 29:1210849dba19 963 report - a dict where a result may be appended
screamer 29:1210849dba19 964 properties - UUUUHHHHH beats me
The Other Jimmy 31:8ea194f6145b 965 build_profile - a dict of flags that will be passed to the compiler
theotherjimmy 43:2a7da56ebd24 966 ignore - list of paths to add to mbedignore
theotherjimmy 43:2a7da56ebd24 967
theotherjimmy 43:2a7da56ebd24 968 Return - True if target + toolchain built correctly, False if not supported
screamer 29:1210849dba19 969 """
screamer 0:66f3b5499f7f 970
theotherjimmy 43:2a7da56ebd24 971 if report is not None:
screamer 0:66f3b5499f7f 972 start = time()
screamer 0:66f3b5499f7f 973 id_name = "MBED"
screamer 0:66f3b5499f7f 974 description = "mbed SDK"
screamer 0:66f3b5499f7f 975 vendor_label = target.extra_labels[0]
screamer 0:66f3b5499f7f 976 cur_result = None
screamer 0:66f3b5499f7f 977 prep_report(report, target.name, toolchain_name, id_name)
theotherjimmy 43:2a7da56ebd24 978 cur_result = create_result(
theotherjimmy 43:2a7da56ebd24 979 target.name, toolchain_name, id_name, description)
theotherjimmy 43:2a7da56ebd24 980 if properties is not None:
theotherjimmy 43:2a7da56ebd24 981 prep_properties(
theotherjimmy 43:2a7da56ebd24 982 properties, target.name, toolchain_name, vendor_label)
screamer 0:66f3b5499f7f 983
screamer 0:66f3b5499f7f 984 if toolchain_name not in target.supported_toolchains:
screamer 0:66f3b5499f7f 985 supported_toolchains_text = ", ".join(target.supported_toolchains)
theotherjimmy 43:2a7da56ebd24 986 notify.info('The target {} does not support the toolchain {}'.format(
theotherjimmy 43:2a7da56ebd24 987 target.name,
theotherjimmy 43:2a7da56ebd24 988 toolchain_name
theotherjimmy 43:2a7da56ebd24 989 ))
theotherjimmy 43:2a7da56ebd24 990 notify.info('{} supports {} toolchain{}'.format(
theotherjimmy 43:2a7da56ebd24 991 target.name,
theotherjimmy 43:2a7da56ebd24 992 supported_toolchains_text,
theotherjimmy 43:2a7da56ebd24 993 's' if len(target.supported_toolchains) > 1 else ''
theotherjimmy 43:2a7da56ebd24 994 ))
screamer 0:66f3b5499f7f 995
theotherjimmy 43:2a7da56ebd24 996 if report is not None:
screamer 0:66f3b5499f7f 997 cur_result["result"] = "SKIP"
screamer 0:66f3b5499f7f 998 add_result_to_report(report, cur_result)
screamer 0:66f3b5499f7f 999
screamer 0:66f3b5499f7f 1000 return False
screamer 0:66f3b5499f7f 1001
screamer 0:66f3b5499f7f 1002 try:
The Other Jimmy 36:96847d42f010 1003 # Source and Build Paths
theotherjimmy 43:2a7da56ebd24 1004 build_toolchain = join(
theotherjimmy 43:2a7da56ebd24 1005 MBED_LIBRARIES, mbed2_obj_path(target.name, toolchain_name))
The Other Jimmy 36:96847d42f010 1006 mkdir(build_toolchain)
The Other Jimmy 36:96847d42f010 1007
theotherjimmy 43:2a7da56ebd24 1008 tmp_path = join(
theotherjimmy 43:2a7da56ebd24 1009 MBED_LIBRARIES,
theotherjimmy 43:2a7da56ebd24 1010 '.temp',
theotherjimmy 43:2a7da56ebd24 1011 mbed2_obj_path(target.name, toolchain_name)
theotherjimmy 43:2a7da56ebd24 1012 )
The Other Jimmy 36:96847d42f010 1013 mkdir(tmp_path)
The Other Jimmy 36:96847d42f010 1014
theotherjimmy 43:2a7da56ebd24 1015 # Toolchain and config
The Other Jimmy 36:96847d42f010 1016 toolchain = prepare_toolchain(
theotherjimmy 43:2a7da56ebd24 1017 [""], tmp_path, target, toolchain_name, macros=macros, notify=notify,
theotherjimmy 43:2a7da56ebd24 1018 build_profile=build_profile, jobs=jobs, clean=clean, ignore=ignore)
screamer 0:66f3b5499f7f 1019
The Other Jimmy 36:96847d42f010 1020 config = toolchain.config
screamer 29:1210849dba19 1021 config.add_config_files([MBED_CONFIG_FILE])
screamer 29:1210849dba19 1022 toolchain.set_config_data(toolchain.config.get_config_data())
screamer 29:1210849dba19 1023
theotherjimmy 43:2a7da56ebd24 1024 # distribute header files
theotherjimmy 43:2a7da56ebd24 1025 toolchain.copy_files(
theotherjimmy 43:2a7da56ebd24 1026 [FileRef(basename(MBED_HEADER),MBED_HEADER)], MBED_LIBRARIES)
The Other Jimmy 31:8ea194f6145b 1027 library_incdirs = [dirname(MBED_LIBRARIES), MBED_LIBRARIES]
The Other Jimmy 31:8ea194f6145b 1028
The Other Jimmy 31:8ea194f6145b 1029 for dir, dest in [(MBED_DRIVERS, MBED_LIBRARIES_DRIVERS),
The Other Jimmy 31:8ea194f6145b 1030 (MBED_PLATFORM, MBED_LIBRARIES_PLATFORM),
The Other Jimmy 31:8ea194f6145b 1031 (MBED_HAL, MBED_LIBRARIES_HAL)]:
theotherjimmy 43:2a7da56ebd24 1032 resources = Resources(notify).scan_with_toolchain([dir], toolchain)
theotherjimmy 43:2a7da56ebd24 1033 toolchain.copy_files(
theotherjimmy 43:2a7da56ebd24 1034 [FileRef(basename(p), p) for p
theotherjimmy 43:2a7da56ebd24 1035 in resources.get_file_paths(FileType.HEADER)] ,
theotherjimmy 43:2a7da56ebd24 1036 dest)
The Other Jimmy 31:8ea194f6145b 1037 library_incdirs.append(dest)
screamer 0:66f3b5499f7f 1038
theotherjimmy 43:2a7da56ebd24 1039 # collect resources of the libs to compile
theotherjimmy 43:2a7da56ebd24 1040 cmsis_res = Resources(notify).scan_with_toolchain(
theotherjimmy 43:2a7da56ebd24 1041 [MBED_CMSIS_PATH], toolchain)
theotherjimmy 43:2a7da56ebd24 1042 hal_res = Resources(notify).scan_with_toolchain(
theotherjimmy 43:2a7da56ebd24 1043 [MBED_TARGETS_PATH], toolchain)
theotherjimmy 43:2a7da56ebd24 1044 mbed_resources = Resources(notify).scan_with_toolchain(
theotherjimmy 43:2a7da56ebd24 1045 [MBED_DRIVERS, MBED_PLATFORM, MBED_HAL], toolchain)
screamer 0:66f3b5499f7f 1046
theotherjimmy 43:2a7da56ebd24 1047 incdirs = cmsis_res.inc_dirs + hal_res.inc_dirs + library_incdirs
screamer 0:66f3b5499f7f 1048
theotherjimmy 43:2a7da56ebd24 1049 # Build Things
theotherjimmy 43:2a7da56ebd24 1050 notify.info("Building library %s (%s, %s)" %
theotherjimmy 43:2a7da56ebd24 1051 ('MBED', target.name, toolchain_name))
theotherjimmy 43:2a7da56ebd24 1052 objects = toolchain.compile_sources(mbed_resources, incdirs)
theotherjimmy 43:2a7da56ebd24 1053 separate_objects = []
screamer 0:66f3b5499f7f 1054
screamer 29:1210849dba19 1055 for obj in objects:
theotherjimmy 43:2a7da56ebd24 1056 for name in SEPARATE_NAMES:
screamer 29:1210849dba19 1057 if obj.endswith(name):
screamer 29:1210849dba19 1058 separate_objects.append(obj)
screamer 0:66f3b5499f7f 1059
screamer 29:1210849dba19 1060 for obj in separate_objects:
screamer 29:1210849dba19 1061 objects.remove(obj)
screamer 0:66f3b5499f7f 1062
screamer 29:1210849dba19 1063 toolchain.build_library(objects, build_toolchain, "mbed")
theotherjimmy 43:2a7da56ebd24 1064 notify.info("Building library %s (%s, %s)" %
theotherjimmy 43:2a7da56ebd24 1065 ('CMSIS', target.name, toolchain_name))
theotherjimmy 43:2a7da56ebd24 1066 cmsis_objects = toolchain.compile_sources(cmsis_res, incdirs + [tmp_path])
theotherjimmy 43:2a7da56ebd24 1067 notify.info("Building library %s (%s, %s)" %
theotherjimmy 43:2a7da56ebd24 1068 ('HAL', target.name, toolchain_name))
theotherjimmy 43:2a7da56ebd24 1069 hal_objects = toolchain.compile_sources(hal_res, incdirs + [tmp_path])
screamer 0:66f3b5499f7f 1070
theotherjimmy 43:2a7da56ebd24 1071 # Copy everything into the build directory
theotherjimmy 43:2a7da56ebd24 1072 to_copy_paths = [
theotherjimmy 43:2a7da56ebd24 1073 hal_res.get_file_paths(FileType.HEADER),
theotherjimmy 43:2a7da56ebd24 1074 hal_res.get_file_paths(FileType.HEX),
theotherjimmy 43:2a7da56ebd24 1075 hal_res.get_file_paths(FileType.BIN),
theotherjimmy 43:2a7da56ebd24 1076 hal_res.get_file_paths(FileType.LIB),
theotherjimmy 43:2a7da56ebd24 1077 cmsis_res.get_file_paths(FileType.HEADER),
theotherjimmy 43:2a7da56ebd24 1078 cmsis_res.get_file_paths(FileType.BIN),
theotherjimmy 43:2a7da56ebd24 1079 cmsis_res.get_file_paths(FileType.LD_SCRIPT),
theotherjimmy 43:2a7da56ebd24 1080 hal_res.get_file_paths(FileType.LD_SCRIPT),
theotherjimmy 43:2a7da56ebd24 1081 [MBED_CONFIG_FILE],
theotherjimmy 43:2a7da56ebd24 1082 cmsis_objects,
theotherjimmy 43:2a7da56ebd24 1083 hal_objects,
theotherjimmy 43:2a7da56ebd24 1084 separate_objects,
theotherjimmy 43:2a7da56ebd24 1085 ]
theotherjimmy 43:2a7da56ebd24 1086 to_copy = [FileRef(basename(p), p) for p in sum(to_copy_paths, [])]
theotherjimmy 43:2a7da56ebd24 1087 toolchain.copy_files(to_copy, build_toolchain)
screamer 0:66f3b5499f7f 1088
theotherjimmy 43:2a7da56ebd24 1089 if report is not None:
screamer 0:66f3b5499f7f 1090 end = time()
screamer 0:66f3b5499f7f 1091 cur_result["elapsed_time"] = end - start
screamer 0:66f3b5499f7f 1092 cur_result["result"] = "OK"
screamer 0:66f3b5499f7f 1093 add_result_to_report(report, cur_result)
screamer 0:66f3b5499f7f 1094
screamer 0:66f3b5499f7f 1095 return True
screamer 0:66f3b5499f7f 1096
screamer 29:1210849dba19 1097 except Exception as exc:
theotherjimmy 43:2a7da56ebd24 1098 if report is not None:
screamer 0:66f3b5499f7f 1099 end = time()
screamer 0:66f3b5499f7f 1100 cur_result["result"] = "FAIL"
screamer 0:66f3b5499f7f 1101 cur_result["elapsed_time"] = end - start
screamer 0:66f3b5499f7f 1102
screamer 29:1210849dba19 1103 cur_result["output"] += str(exc)
screamer 0:66f3b5499f7f 1104
screamer 0:66f3b5499f7f 1105 add_result_to_report(report, cur_result)
screamer 29:1210849dba19 1106 raise
screamer 0:66f3b5499f7f 1107
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 1108
screamer 24:25bff2709c20 1109 def get_unique_supported_toolchains(release_targets=None):
screamer 24:25bff2709c20 1110 """ Get list of all unique toolchains supported by targets
screamer 29:1210849dba19 1111
screamer 29:1210849dba19 1112 Keyword arguments:
screamer 29:1210849dba19 1113 release_targets - tuple structure returned from get_mbed_official_release().
screamer 29:1210849dba19 1114 If release_targets is not specified, then it queries all
screamer 29:1210849dba19 1115 known targets
screamer 24:25bff2709c20 1116 """
screamer 0:66f3b5499f7f 1117 unique_supported_toolchains = []
screamer 24:25bff2709c20 1118
screamer 24:25bff2709c20 1119 if not release_targets:
screamer 24:25bff2709c20 1120 for target in TARGET_NAMES:
screamer 24:25bff2709c20 1121 for toolchain in TARGET_MAP[target].supported_toolchains:
screamer 24:25bff2709c20 1122 if toolchain not in unique_supported_toolchains:
screamer 24:25bff2709c20 1123 unique_supported_toolchains.append(toolchain)
screamer 24:25bff2709c20 1124 else:
screamer 24:25bff2709c20 1125 for target in release_targets:
screamer 24:25bff2709c20 1126 for toolchain in target[1]:
screamer 24:25bff2709c20 1127 if toolchain not in unique_supported_toolchains:
screamer 24:25bff2709c20 1128 unique_supported_toolchains.append(toolchain)
screamer 24:25bff2709c20 1129
theotherjimmy 43:2a7da56ebd24 1130 return unique_supported_toolchains
theotherjimmy 43:2a7da56ebd24 1131
theotherjimmy 40:7d3fa6b99b2b 1132
theotherjimmy 43:2a7da56ebd24 1133 def _lowercase_release_version(release_version):
theotherjimmy 43:2a7da56ebd24 1134 try:
theotherjimmy 43:2a7da56ebd24 1135 return release_version.lower()
theotherjimmy 43:2a7da56ebd24 1136 except AttributeError:
theotherjimmy 43:2a7da56ebd24 1137 return 'all'
screamer 0:66f3b5499f7f 1138
The Other Jimmy 36:96847d42f010 1139 def mcu_toolchain_list(release_version='5'):
The Other Jimmy 36:96847d42f010 1140 """ Shows list of toolchains
The Other Jimmy 36:96847d42f010 1141
The Other Jimmy 36:96847d42f010 1142 """
theotherjimmy 43:2a7da56ebd24 1143 release_version = _lowercase_release_version(release_version)
The Other Jimmy 36:96847d42f010 1144 version_release_targets = {}
The Other Jimmy 36:96847d42f010 1145 version_release_target_names = {}
The Other Jimmy 36:96847d42f010 1146
The Other Jimmy 36:96847d42f010 1147 for version in RELEASE_VERSIONS:
The Other Jimmy 36:96847d42f010 1148 version_release_targets[version] = get_mbed_official_release(version)
The Other Jimmy 36:96847d42f010 1149 version_release_target_names[version] = [x[0] for x in
The Other Jimmy 36:96847d42f010 1150 version_release_targets[
The Other Jimmy 36:96847d42f010 1151 version]]
The Other Jimmy 36:96847d42f010 1152
The Other Jimmy 36:96847d42f010 1153 if release_version in RELEASE_VERSIONS:
The Other Jimmy 36:96847d42f010 1154 release_targets = version_release_targets[release_version]
The Other Jimmy 36:96847d42f010 1155 else:
The Other Jimmy 36:96847d42f010 1156 release_targets = None
The Other Jimmy 36:96847d42f010 1157
The Other Jimmy 36:96847d42f010 1158 unique_supported_toolchains = get_unique_supported_toolchains(
The Other Jimmy 36:96847d42f010 1159 release_targets)
The Other Jimmy 36:96847d42f010 1160 columns = ["mbed OS %s" % x for x in RELEASE_VERSIONS] + unique_supported_toolchains
The Other Jimmy 36:96847d42f010 1161 return "\n".join(columns)
The Other Jimmy 36:96847d42f010 1162
The Other Jimmy 36:96847d42f010 1163
The Other Jimmy 36:96847d42f010 1164 def mcu_target_list(release_version='5'):
theotherjimmy 40:7d3fa6b99b2b 1165 """ Shows target list
The Other Jimmy 36:96847d42f010 1166
The Other Jimmy 36:96847d42f010 1167 """
theotherjimmy 43:2a7da56ebd24 1168 release_version = _lowercase_release_version(release_version)
The Other Jimmy 36:96847d42f010 1169 version_release_targets = {}
The Other Jimmy 36:96847d42f010 1170 version_release_target_names = {}
The Other Jimmy 36:96847d42f010 1171
The Other Jimmy 36:96847d42f010 1172 for version in RELEASE_VERSIONS:
The Other Jimmy 36:96847d42f010 1173 version_release_targets[version] = get_mbed_official_release(version)
The Other Jimmy 36:96847d42f010 1174 version_release_target_names[version] = [x[0] for x in
The Other Jimmy 36:96847d42f010 1175 version_release_targets[
The Other Jimmy 36:96847d42f010 1176 version]]
The Other Jimmy 36:96847d42f010 1177
The Other Jimmy 36:96847d42f010 1178 if release_version in RELEASE_VERSIONS:
The Other Jimmy 36:96847d42f010 1179 release_targets = version_release_targets[release_version]
The Other Jimmy 36:96847d42f010 1180 else:
The Other Jimmy 36:96847d42f010 1181 release_targets = None
The Other Jimmy 36:96847d42f010 1182
The Other Jimmy 36:96847d42f010 1183 target_names = []
The Other Jimmy 36:96847d42f010 1184
The Other Jimmy 36:96847d42f010 1185 if release_targets:
The Other Jimmy 36:96847d42f010 1186 target_names = [x[0] for x in release_targets]
The Other Jimmy 36:96847d42f010 1187 else:
The Other Jimmy 36:96847d42f010 1188 target_names = TARGET_NAMES
The Other Jimmy 36:96847d42f010 1189
The Other Jimmy 36:96847d42f010 1190 return "\n".join(target_names)
The Other Jimmy 36:96847d42f010 1191
screamer 0:66f3b5499f7f 1192
screamer 29:1210849dba19 1193 def mcu_toolchain_matrix(verbose_html=False, platform_filter=None,
screamer 29:1210849dba19 1194 release_version='5'):
screamer 29:1210849dba19 1195 """ Shows target map using prettytable
screamer 29:1210849dba19 1196
screamer 29:1210849dba19 1197 Keyword arguments:
screamer 29:1210849dba19 1198 verbose_html - emit html instead of a simple table
screamer 29:1210849dba19 1199 platform_filter - remove results that match the string
screamer 29:1210849dba19 1200 release_version - get the matrix for this major version number
screamer 29:1210849dba19 1201 """
screamer 29:1210849dba19 1202 # Only use it in this function so building works without extra modules
theotherjimmy 43:2a7da56ebd24 1203 from prettytable import PrettyTable, HEADER
theotherjimmy 43:2a7da56ebd24 1204 release_version = _lowercase_release_version(release_version)
screamer 24:25bff2709c20 1205 version_release_targets = {}
screamer 24:25bff2709c20 1206 version_release_target_names = {}
screamer 24:25bff2709c20 1207
screamer 24:25bff2709c20 1208 for version in RELEASE_VERSIONS:
screamer 24:25bff2709c20 1209 version_release_targets[version] = get_mbed_official_release(version)
screamer 29:1210849dba19 1210 version_release_target_names[version] = [x[0] for x in
screamer 29:1210849dba19 1211 version_release_targets[
screamer 29:1210849dba19 1212 version]]
screamer 24:25bff2709c20 1213
screamer 24:25bff2709c20 1214 if release_version in RELEASE_VERSIONS:
screamer 24:25bff2709c20 1215 release_targets = version_release_targets[release_version]
screamer 24:25bff2709c20 1216 else:
screamer 24:25bff2709c20 1217 release_targets = None
screamer 24:25bff2709c20 1218
screamer 29:1210849dba19 1219 unique_supported_toolchains = get_unique_supported_toolchains(
screamer 29:1210849dba19 1220 release_targets)
screamer 24:25bff2709c20 1221 prepend_columns = ["Target"] + ["mbed OS %s" % x for x in RELEASE_VERSIONS]
screamer 24:25bff2709c20 1222
screamer 0:66f3b5499f7f 1223 # All tests status table print
screamer 24:25bff2709c20 1224 columns = prepend_columns + unique_supported_toolchains
theotherjimmy 43:2a7da56ebd24 1225 table_printer = PrettyTable(columns, junction_char="|", hrules=HEADER)
screamer 0:66f3b5499f7f 1226 # Align table
screamer 0:66f3b5499f7f 1227 for col in columns:
screamer 29:1210849dba19 1228 table_printer.align[col] = "c"
screamer 29:1210849dba19 1229 table_printer.align["Target"] = "l"
screamer 0:66f3b5499f7f 1230
screamer 0:66f3b5499f7f 1231 perm_counter = 0
screamer 0:66f3b5499f7f 1232 target_counter = 0
screamer 24:25bff2709c20 1233
screamer 24:25bff2709c20 1234 target_names = []
screamer 24:25bff2709c20 1235
screamer 24:25bff2709c20 1236 if release_targets:
screamer 24:25bff2709c20 1237 target_names = [x[0] for x in release_targets]
screamer 24:25bff2709c20 1238 else:
screamer 24:25bff2709c20 1239 target_names = TARGET_NAMES
screamer 24:25bff2709c20 1240
screamer 24:25bff2709c20 1241 for target in sorted(target_names):
screamer 0:66f3b5499f7f 1242 if platform_filter is not None:
screamer 0:66f3b5499f7f 1243 # FIlter out platforms using regex
screamer 0:66f3b5499f7f 1244 if re.search(platform_filter, target) is None:
screamer 0:66f3b5499f7f 1245 continue
screamer 0:66f3b5499f7f 1246 target_counter += 1
screamer 0:66f3b5499f7f 1247
screamer 0:66f3b5499f7f 1248 row = [target] # First column is platform name
screamer 24:25bff2709c20 1249
screamer 24:25bff2709c20 1250 for version in RELEASE_VERSIONS:
screamer 24:25bff2709c20 1251 if target in version_release_target_names[version]:
screamer 24:25bff2709c20 1252 text = "Supported"
screamer 24:25bff2709c20 1253 else:
screamer 24:25bff2709c20 1254 text = "-"
screamer 24:25bff2709c20 1255 row.append(text)
screamer 24:25bff2709c20 1256
screamer 0:66f3b5499f7f 1257 for unique_toolchain in unique_supported_toolchains:
theotherjimmy 43:2a7da56ebd24 1258 tgt_obj = TARGET_MAP[target]
theotherjimmy 43:2a7da56ebd24 1259 if (unique_toolchain in tgt_obj.supported_toolchains or
theotherjimmy 40:7d3fa6b99b2b 1260 (unique_toolchain == "ARMC6" and
theotherjimmy 43:2a7da56ebd24 1261 "ARM" in tgt_obj.supported_toolchains) or
theotherjimmy 43:2a7da56ebd24 1262 (unique_toolchain == "ARM" and
theotherjimmy 43:2a7da56ebd24 1263 "ARMC6" in tgt_obj.supported_toolchains and
theotherjimmy 43:2a7da56ebd24 1264 CORE_ARCH[tgt_obj.core] == 8)):
screamer 0:66f3b5499f7f 1265 text = "Supported"
screamer 0:66f3b5499f7f 1266 perm_counter += 1
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 1267 else:
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 1268 text = "-"
screamer 22:9e85236d8716 1269
screamer 0:66f3b5499f7f 1270 row.append(text)
screamer 29:1210849dba19 1271 table_printer.add_row(row)
screamer 0:66f3b5499f7f 1272
screamer 29:1210849dba19 1273 result = table_printer.get_html_string() if verbose_html \
screamer 29:1210849dba19 1274 else table_printer.get_string()
screamer 0:66f3b5499f7f 1275 result += "\n"
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 1276 result += "Supported targets: %d\n"% (target_counter)
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 1277 if target_counter == 1:
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 1278 result += "Supported toolchains: %d"% (perm_counter)
screamer 0:66f3b5499f7f 1279 return result
screamer 0:66f3b5499f7f 1280
screamer 0:66f3b5499f7f 1281
screamer 0:66f3b5499f7f 1282 def get_target_supported_toolchains(target):
screamer 29:1210849dba19 1283 """ Returns target supported toolchains list
screamer 29:1210849dba19 1284
screamer 29:1210849dba19 1285 Positional arguments:
screamer 29:1210849dba19 1286 target - the target to get the supported toolchains of
screamer 29:1210849dba19 1287 """
screamer 29:1210849dba19 1288 return TARGET_MAP[target].supported_toolchains if target in TARGET_MAP \
screamer 29:1210849dba19 1289 else None
screamer 0:66f3b5499f7f 1290
screamer 0:66f3b5499f7f 1291
screamer 0:66f3b5499f7f 1292 def print_build_results(result_list, build_name):
screamer 29:1210849dba19 1293 """ Generate result string for build results
screamer 29:1210849dba19 1294
screamer 29:1210849dba19 1295 Positional arguments:
screamer 29:1210849dba19 1296 result_list - the list of results to print
screamer 29:1210849dba19 1297 build_name - the name of the build we are printing result for
screamer 29:1210849dba19 1298 """
screamer 0:66f3b5499f7f 1299 result = ""
screamer 0:66f3b5499f7f 1300 if len(result_list) > 0:
screamer 0:66f3b5499f7f 1301 result += build_name + "\n"
screamer 0:66f3b5499f7f 1302 result += "\n".join([" * %s" % f for f in result_list])
screamer 0:66f3b5499f7f 1303 result += "\n"
screamer 0:66f3b5499f7f 1304 return result
screamer 0:66f3b5499f7f 1305
screamer 29:1210849dba19 1306 def print_build_memory_usage(report):
screamer 22:9e85236d8716 1307 """ Generate result table with memory usage values for build results
screamer 29:1210849dba19 1308 Aggregates (puts together) reports obtained from self.get_memory_summary()
screamer 29:1210849dba19 1309
screamer 29:1210849dba19 1310 Positional arguments:
screamer 29:1210849dba19 1311 report - Report generated during build procedure.
screamer 22:9e85236d8716 1312 """
theotherjimmy 43:2a7da56ebd24 1313 from prettytable import PrettyTable, HEADER
screamer 22:9e85236d8716 1314 columns_text = ['name', 'target', 'toolchain']
theotherjimmy 40:7d3fa6b99b2b 1315 columns_int = ['static_ram', 'total_flash']
theotherjimmy 43:2a7da56ebd24 1316 table = PrettyTable(columns_text + columns_int, junction_char="|", hrules=HEADER)
screamer 22:9e85236d8716 1317
screamer 22:9e85236d8716 1318 for col in columns_text:
screamer 22:9e85236d8716 1319 table.align[col] = 'l'
screamer 22:9e85236d8716 1320
screamer 22:9e85236d8716 1321 for col in columns_int:
screamer 22:9e85236d8716 1322 table.align[col] = 'r'
screamer 22:9e85236d8716 1323
screamer 22:9e85236d8716 1324 for target in report:
screamer 22:9e85236d8716 1325 for toolchain in report[target]:
screamer 22:9e85236d8716 1326 for name in report[target][toolchain]:
screamer 22:9e85236d8716 1327 for dlist in report[target][toolchain][name]:
screamer 22:9e85236d8716 1328 for dlistelem in dlist:
screamer 29:1210849dba19 1329 # Get 'memory_usage' record and build table with
screamer 29:1210849dba19 1330 # statistics
screamer 22:9e85236d8716 1331 record = dlist[dlistelem]
screamer 22:9e85236d8716 1332 if 'memory_usage' in record and record['memory_usage']:
screamer 22:9e85236d8716 1333 # Note that summary should be in the last record of
screamer 29:1210849dba19 1334 # 'memory_usage' section. This is why we are
screamer 29:1210849dba19 1335 # grabbing last "[-1]" record.
screamer 22:9e85236d8716 1336 row = [
screamer 22:9e85236d8716 1337 record['description'],
screamer 22:9e85236d8716 1338 record['target_name'],
screamer 22:9e85236d8716 1339 record['toolchain_name'],
screamer 29:1210849dba19 1340 record['memory_usage'][-1]['summary'][
screamer 29:1210849dba19 1341 'static_ram'],
screamer 29:1210849dba19 1342 record['memory_usage'][-1]['summary'][
screamer 29:1210849dba19 1343 'total_flash'],
screamer 22:9e85236d8716 1344 ]
screamer 22:9e85236d8716 1345 table.add_row(row)
screamer 22:9e85236d8716 1346
screamer 22:9e85236d8716 1347 result = "Memory map breakdown for built projects (values in Bytes):\n"
screamer 22:9e85236d8716 1348 result += table.get_string(sortby='name')
screamer 22:9e85236d8716 1349 return result
screamer 22:9e85236d8716 1350
screamer 0:66f3b5499f7f 1351 def write_build_report(build_report, template_filename, filename):
screamer 29:1210849dba19 1352 """Write a build report to disk using a template file
screamer 29:1210849dba19 1353
screamer 29:1210849dba19 1354 Positional arguments:
screamer 29:1210849dba19 1355 build_report - a report generated by the build system
screamer 29:1210849dba19 1356 template_filename - a file that contains the template for the style of build
screamer 29:1210849dba19 1357 report
screamer 29:1210849dba19 1358 filename - the location on disk to write the file to
screamer 29:1210849dba19 1359 """
screamer 0:66f3b5499f7f 1360 build_report_failing = []
screamer 0:66f3b5499f7f 1361 build_report_passing = []
screamer 0:66f3b5499f7f 1362
screamer 0:66f3b5499f7f 1363 for report in build_report:
screamer 0:66f3b5499f7f 1364 if len(report["failing"]) > 0:
screamer 0:66f3b5499f7f 1365 build_report_failing.append(report)
screamer 0:66f3b5499f7f 1366 else:
screamer 0:66f3b5499f7f 1367 build_report_passing.append(report)
screamer 0:66f3b5499f7f 1368
screamer 0:66f3b5499f7f 1369 env = Environment(extensions=['jinja2.ext.with_'])
screamer 0:66f3b5499f7f 1370 env.loader = FileSystemLoader('ci_templates')
screamer 0:66f3b5499f7f 1371 template = env.get_template(template_filename)
screamer 0:66f3b5499f7f 1372
screamer 29:1210849dba19 1373 with open(filename, 'w+') as placeholder:
screamer 29:1210849dba19 1374 placeholder.write(template.render(
screamer 29:1210849dba19 1375 failing_builds=build_report_failing,
screamer 29:1210849dba19 1376 passing_builds=build_report_passing))
The Other Jimmy 36:96847d42f010 1377
The Other Jimmy 36:96847d42f010 1378
The Other Jimmy 36:96847d42f010 1379 def merge_build_data(filename, toolchain_report, app_type):
The Other Jimmy 36:96847d42f010 1380 path_to_file = dirname(abspath(filename))
The Other Jimmy 36:96847d42f010 1381 try:
The Other Jimmy 36:96847d42f010 1382 build_data = load(open(filename))
The Other Jimmy 36:96847d42f010 1383 except (IOError, ValueError):
The Other Jimmy 36:96847d42f010 1384 build_data = {'builds': []}
The Other Jimmy 36:96847d42f010 1385 for tgt in toolchain_report.values():
The Other Jimmy 36:96847d42f010 1386 for tc in tgt.values():
The Other Jimmy 36:96847d42f010 1387 for project in tc.values():
The Other Jimmy 36:96847d42f010 1388 for build in project:
The Other Jimmy 36:96847d42f010 1389 try:
theotherjimmy 43:2a7da56ebd24 1390 build[0]['bin_fullpath'] = build[0]['bin']
theotherjimmy 43:2a7da56ebd24 1391 build[0]['elf_fullpath'] = build[0]['elf']
The Other Jimmy 36:96847d42f010 1392 build[0]['elf'] = relpath(build[0]['elf'], path_to_file)
The Other Jimmy 36:96847d42f010 1393 build[0]['bin'] = relpath(build[0]['bin'], path_to_file)
The Other Jimmy 36:96847d42f010 1394 except KeyError:
The Other Jimmy 36:96847d42f010 1395 pass
The Other Jimmy 36:96847d42f010 1396 if 'type' not in build[0]:
The Other Jimmy 36:96847d42f010 1397 build[0]['type'] = app_type
theotherjimmy 43:2a7da56ebd24 1398 build_data['builds'].insert(0, build[0])
The Other Jimmy 36:96847d42f010 1399 dump(build_data, open(filename, "wb"), indent=4, separators=(',', ': '))