Clone of official tools

Committer:
Anders Blomdell
Date:
Thu Feb 04 17:17:13 2021 +0100
Revision:
47:21ae3e5a7128
Parent:
45:c4a728429846
Add a few normpath calls

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:
theotherjimmy 45:c4a728429846 518 notify.info("Using targets from %s" % targets_json)
screamer 24:25bff2709c20 519 set_targets_json_location(targets_json)
screamer 24:25bff2709c20 520
screamer 24:25bff2709c20 521 # Apply profile to toolchains
screamer 14:ee1b877e6839 522 if profile:
screamer 14:ee1b877e6839 523 def init_hook(self):
screamer 14:ee1b877e6839 524 profile_data = get_toolchain_profile(self.name, profile)
screamer 14:ee1b877e6839 525 if not profile_data:
screamer 14:ee1b877e6839 526 return
theotherjimmy 43:2a7da56ebd24 527 notify.info("Using toolchain %s profile %s" % (self.name, profile))
screamer 14:ee1b877e6839 528
screamer 14:ee1b877e6839 529 for k,v in profile_data.items():
screamer 14:ee1b877e6839 530 if self.flags.has_key(k):
screamer 14:ee1b877e6839 531 self.flags[k] = v
screamer 14:ee1b877e6839 532 else:
screamer 14:ee1b877e6839 533 setattr(self, k, v)
screamer 14:ee1b877e6839 534
screamer 14:ee1b877e6839 535 mbedToolchain.init = init_hook
screamer 14:ee1b877e6839 536
The Other Jimmy 31:8ea194f6145b 537 # mbed Classic/2.0/libary support #
The Other Jimmy 31:8ea194f6145b 538 ###################################
The Other Jimmy 31:8ea194f6145b 539
screamer 29:1210849dba19 540 toolchain = prepare_toolchain(
The Other Jimmy 36:96847d42f010 541 src_paths, build_path, target, toolchain_name, macros=macros,
theotherjimmy 43:2a7da56ebd24 542 clean=clean, jobs=jobs, notify=notify, config=config,
theotherjimmy 43:2a7da56ebd24 543 app_config=app_config, build_profile=build_profile, ignore=ignore)
theotherjimmy 43:2a7da56ebd24 544 toolchain.version_check()
screamer 0:66f3b5499f7f 545
screamer 24:25bff2709c20 546 # The first path will give the name to the library
The Other Jimmy 36:96847d42f010 547 name = (name or toolchain.config.name or
The Other Jimmy 36:96847d42f010 548 basename(normpath(abspath(src_paths[0]))))
theotherjimmy 43:2a7da56ebd24 549 notify.info("Building project %s (%s, %s)" %
theotherjimmy 43:2a7da56ebd24 550 (name, toolchain.target.name, toolchain_name))
screamer 0:66f3b5499f7f 551
screamer 24:25bff2709c20 552 # Initialize reporting
screamer 0:66f3b5499f7f 553 if report != None:
screamer 0:66f3b5499f7f 554 start = time()
screamer 7:5af61d55adbe 555 # If project_id is specified, use that over the default name
screamer 7:5af61d55adbe 556 id_name = project_id.upper() if project_id else name.upper()
screamer 7:5af61d55adbe 557 description = project_description if project_description else name
screamer 24:25bff2709c20 558 vendor_label = toolchain.target.extra_labels[0]
screamer 24:25bff2709c20 559 prep_report(report, toolchain.target.name, toolchain_name, id_name)
screamer 29:1210849dba19 560 cur_result = create_result(toolchain.target.name, toolchain_name,
screamer 29:1210849dba19 561 id_name, description)
screamer 0:66f3b5499f7f 562 if properties != None:
screamer 29:1210849dba19 563 prep_properties(properties, toolchain.target.name, toolchain_name,
screamer 29:1210849dba19 564 vendor_label)
screamer 0:66f3b5499f7f 565
screamer 0:66f3b5499f7f 566 try:
theotherjimmy 43:2a7da56ebd24 567 resources = Resources(notify).scan_with_toolchain(
theotherjimmy 43:2a7da56ebd24 568 src_paths, toolchain, inc_dirs=inc_dirs)
screamer 0:66f3b5499f7f 569
screamer 24:25bff2709c20 570 # Change linker script if specified
screamer 0:66f3b5499f7f 571 if linker_script is not None:
theotherjimmy 43:2a7da56ebd24 572 resources.add_file_ref(linker_script, linker_script)
screamer 0:66f3b5499f7f 573
screamer 0:66f3b5499f7f 574 # Compile Sources
theotherjimmy 43:2a7da56ebd24 575 objects = toolchain.compile_sources(resources, sorted(resources.get_file_paths(FileType.INC_DIR)))
theotherjimmy 43:2a7da56ebd24 576 resources.add_files_to_type(FileType.OBJECT, objects)
screamer 0:66f3b5499f7f 577
screamer 0:66f3b5499f7f 578 # Link Program
The Other Jimmy 36:96847d42f010 579 if toolchain.config.has_regions:
theotherjimmy 43:2a7da56ebd24 580 binary, _ = toolchain.link_program(resources, build_path, name + "_application")
The Other Jimmy 36:96847d42f010 581 region_list = list(toolchain.config.regions)
theotherjimmy 43:2a7da56ebd24 582 region_list = [r._replace(filename=binary) if r.active else r
The Other Jimmy 36:96847d42f010 583 for r in region_list]
theotherjimmy 43:2a7da56ebd24 584 res = "%s.%s" % (join(build_path, name),
theotherjimmy 43:2a7da56ebd24 585 getattr(toolchain.target, "OUTPUT_EXT", "bin"))
theotherjimmy 43:2a7da56ebd24 586 merge_region_list(region_list, res, notify)
theotherjimmy 43:2a7da56ebd24 587 update_regions = [
theotherjimmy 43:2a7da56ebd24 588 r for r in region_list if r.name in UPDATE_WHITELIST
theotherjimmy 43:2a7da56ebd24 589 ]
theotherjimmy 43:2a7da56ebd24 590 if update_regions:
theotherjimmy 43:2a7da56ebd24 591 update_res = "%s_update.%s" % (
theotherjimmy 43:2a7da56ebd24 592 join(build_path, name),
theotherjimmy 43:2a7da56ebd24 593 getattr(toolchain.target, "OUTPUT_EXT", "bin")
theotherjimmy 43:2a7da56ebd24 594 )
theotherjimmy 43:2a7da56ebd24 595 merge_region_list(update_regions, update_res, notify)
theotherjimmy 43:2a7da56ebd24 596 res = (res, update_res)
theotherjimmy 43:2a7da56ebd24 597 else:
theotherjimmy 43:2a7da56ebd24 598 res = (res, None)
The Other Jimmy 36:96847d42f010 599 else:
The Other Jimmy 36:96847d42f010 600 res, _ = toolchain.link_program(resources, build_path, name)
theotherjimmy 43:2a7da56ebd24 601 res = (res, None)
screamer 0:66f3b5499f7f 602
The Other Jimmy 31:8ea194f6145b 603 memap_instance = getattr(toolchain, 'memap_instance', None)
The Other Jimmy 31:8ea194f6145b 604 memap_table = ''
The Other Jimmy 31:8ea194f6145b 605 if memap_instance:
The Other Jimmy 31:8ea194f6145b 606 # Write output to stdout in text (pretty table) format
theotherjimmy 40:7d3fa6b99b2b 607 memap_table = memap_instance.generate_output('table', stats_depth)
theotherjimmy 43:2a7da56ebd24 608 notify.info(memap_table)
The Other Jimmy 31:8ea194f6145b 609
The Other Jimmy 31:8ea194f6145b 610 # Write output to file in JSON format
The Other Jimmy 31:8ea194f6145b 611 map_out = join(build_path, name + "_map.json")
theotherjimmy 40:7d3fa6b99b2b 612 memap_instance.generate_output('json', stats_depth, map_out)
The Other Jimmy 31:8ea194f6145b 613
The Other Jimmy 31:8ea194f6145b 614 # Write output to file in CSV format for the CI
The Other Jimmy 31:8ea194f6145b 615 map_csv = join(build_path, name + "_map.csv")
theotherjimmy 40:7d3fa6b99b2b 616 memap_instance.generate_output('csv-ci', stats_depth, map_csv)
The Other Jimmy 31:8ea194f6145b 617
theotherjimmy 43:2a7da56ebd24 618 map_html = join(build_path, name + "_map.html")
theotherjimmy 43:2a7da56ebd24 619 memap_instance.generate_output('html', stats_depth, map_html)
theotherjimmy 43:2a7da56ebd24 620
theotherjimmy 43:2a7da56ebd24 621 resources.detect_duplicates()
The Other Jimmy 31:8ea194f6145b 622
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 623 if report != None:
screamer 0:66f3b5499f7f 624 end = time()
screamer 0:66f3b5499f7f 625 cur_result["elapsed_time"] = end - start
screamer 0:66f3b5499f7f 626 cur_result["result"] = "OK"
theotherjimmy 43:2a7da56ebd24 627 cur_result["memory_usage"] = (memap_instance.mem_report
theotherjimmy 43:2a7da56ebd24 628 if memap_instance is not None else None)
theotherjimmy 43:2a7da56ebd24 629 cur_result["bin"] = res[0]
theotherjimmy 43:2a7da56ebd24 630 cur_result["elf"] = splitext(res[0])[0] + ".elf"
The Other Jimmy 36:96847d42f010 631 cur_result.update(toolchain.report)
screamer 0:66f3b5499f7f 632
screamer 0:66f3b5499f7f 633 add_result_to_report(report, cur_result)
screamer 0:66f3b5499f7f 634
screamer 0:66f3b5499f7f 635 return res
screamer 0:66f3b5499f7f 636
screamer 29:1210849dba19 637 except Exception as exc:
screamer 0:66f3b5499f7f 638 if report != None:
screamer 0:66f3b5499f7f 639 end = time()
screamer 0:66f3b5499f7f 640
screamer 29:1210849dba19 641 if isinstance(exc, NotSupportedException):
screamer 0:66f3b5499f7f 642 cur_result["result"] = "NOT_SUPPORTED"
screamer 0:66f3b5499f7f 643 else:
screamer 0:66f3b5499f7f 644 cur_result["result"] = "FAIL"
screamer 0:66f3b5499f7f 645
screamer 0:66f3b5499f7f 646 cur_result["elapsed_time"] = end - start
screamer 0:66f3b5499f7f 647
screamer 0:66f3b5499f7f 648 add_result_to_report(report, cur_result)
screamer 0:66f3b5499f7f 649 # Let Exception propagate
screamer 13:ab47a20b66f0 650 raise
screamer 0:66f3b5499f7f 651
screamer 0:66f3b5499f7f 652 def build_library(src_paths, build_path, target, toolchain_name,
The Other Jimmy 31:8ea194f6145b 653 dependencies_paths=None, name=None, clean=False,
theotherjimmy 43:2a7da56ebd24 654 archive=True, notify=None, macros=None, inc_dirs=None, jobs=1,
theotherjimmy 43:2a7da56ebd24 655 report=None, properties=None, project_id=None,
The Other Jimmy 31:8ea194f6145b 656 remove_config_header_file=False, app_config=None,
theotherjimmy 43:2a7da56ebd24 657 build_profile=None, ignore=None):
screamer 29:1210849dba19 658 """ Build a library
screamer 29:1210849dba19 659
screamer 29:1210849dba19 660 Positional arguments:
screamer 29:1210849dba19 661 src_paths - a path or list of paths that contain all files needed to build
screamer 29:1210849dba19 662 the library
screamer 29:1210849dba19 663 build_path - the directory where all of the object files will be placed
screamer 29:1210849dba19 664 target - the MCU or board that the project will compile for
screamer 29:1210849dba19 665 toolchain_name - the name of the build tools
screamer 29:1210849dba19 666
screamer 29:1210849dba19 667 Keyword arguments:
screamer 29:1210849dba19 668 dependencies_paths - The location of libraries to include when linking
screamer 29:1210849dba19 669 name - the name of the library
screamer 29:1210849dba19 670 clean - Rebuild everything if True
screamer 29:1210849dba19 671 archive - whether the library will create an archive file
screamer 29:1210849dba19 672 notify - Notify function for logs
screamer 29:1210849dba19 673 macros - additional macros
screamer 29:1210849dba19 674 inc_dirs - additional directories where include files may be found
screamer 29:1210849dba19 675 jobs - how many compilers we can run at once
screamer 29:1210849dba19 676 report - a dict where a result may be appended
screamer 29:1210849dba19 677 properties - UUUUHHHHH beats me
screamer 29:1210849dba19 678 project_id - the name that goes in the report
The Other Jimmy 31:8ea194f6145b 679 remove_config_header_file - delete config header file when done building
The Other Jimmy 31:8ea194f6145b 680 app_config - location of a chosen mbed_app.json file
The Other Jimmy 31:8ea194f6145b 681 build_profile - a dict of flags that will be passed to the compiler
theotherjimmy 43:2a7da56ebd24 682 ignore - list of paths to add to mbedignore
screamer 0:66f3b5499f7f 683 """
screamer 24:25bff2709c20 684
screamer 24:25bff2709c20 685 # Convert src_path to a list if needed
theotherjimmy 43:2a7da56ebd24 686 if not isinstance(src_paths, list):
screamer 0:66f3b5499f7f 687 src_paths = [src_paths]
theotherjimmy 43:2a7da56ebd24 688 src_paths = [relpath(s) for s in src_paths]
screamer 0:66f3b5499f7f 689
screamer 24:25bff2709c20 690 # Build path
screamer 24:25bff2709c20 691 if archive:
screamer 24:25bff2709c20 692 # Use temp path when building archive
screamer 24:25bff2709c20 693 tmp_path = join(build_path, '.temp')
screamer 24:25bff2709c20 694 mkdir(tmp_path)
screamer 24:25bff2709c20 695 else:
screamer 24:25bff2709c20 696 tmp_path = build_path
screamer 0:66f3b5499f7f 697
screamer 29:1210849dba19 698 # Clean the build directory
screamer 29:1210849dba19 699 if clean and exists(tmp_path):
screamer 29:1210849dba19 700 rmtree(tmp_path)
screamer 29:1210849dba19 701 mkdir(tmp_path)
screamer 29:1210849dba19 702
screamer 24:25bff2709c20 703 # Pass all params to the unified prepare_toolchain()
screamer 29:1210849dba19 704 toolchain = prepare_toolchain(
The Other Jimmy 36:96847d42f010 705 src_paths, build_path, target, toolchain_name, macros=macros,
theotherjimmy 43:2a7da56ebd24 706 clean=clean, jobs=jobs, notify=notify, app_config=app_config,
theotherjimmy 43:2a7da56ebd24 707 build_profile=build_profile, ignore=ignore)
screamer 13:ab47a20b66f0 708
screamer 24:25bff2709c20 709 # The first path will give the name to the library
screamer 24:25bff2709c20 710 if name is None:
screamer 24:25bff2709c20 711 name = basename(normpath(abspath(src_paths[0])))
theotherjimmy 43:2a7da56ebd24 712 notify.info("Building library %s (%s, %s)" %
screamer 29:1210849dba19 713 (name, toolchain.target.name, toolchain_name))
screamer 13:ab47a20b66f0 714
screamer 24:25bff2709c20 715 # Initialize reporting
screamer 0:66f3b5499f7f 716 if report != None:
screamer 0:66f3b5499f7f 717 start = time()
screamer 7:5af61d55adbe 718 # If project_id is specified, use that over the default name
screamer 7:5af61d55adbe 719 id_name = project_id.upper() if project_id else name.upper()
screamer 0:66f3b5499f7f 720 description = name
screamer 24:25bff2709c20 721 vendor_label = toolchain.target.extra_labels[0]
screamer 24:25bff2709c20 722 prep_report(report, toolchain.target.name, toolchain_name, id_name)
screamer 29:1210849dba19 723 cur_result = create_result(toolchain.target.name, toolchain_name,
screamer 29:1210849dba19 724 id_name, description)
The Other Jimmy 36:96847d42f010 725 cur_result['type'] = 'library'
screamer 0:66f3b5499f7f 726 if properties != None:
screamer 29:1210849dba19 727 prep_properties(properties, toolchain.target.name, toolchain_name,
screamer 29:1210849dba19 728 vendor_label)
screamer 0:66f3b5499f7f 729
screamer 0:66f3b5499f7f 730 for src_path in src_paths:
screamer 0:66f3b5499f7f 731 if not exists(src_path):
screamer 0:66f3b5499f7f 732 error_msg = "The library source folder does not exist: %s", src_path
screamer 0:66f3b5499f7f 733 if report != None:
screamer 0:66f3b5499f7f 734 cur_result["output"] = error_msg
screamer 0:66f3b5499f7f 735 cur_result["result"] = "FAIL"
screamer 0:66f3b5499f7f 736 add_result_to_report(report, cur_result)
screamer 0:66f3b5499f7f 737 raise Exception(error_msg)
screamer 0:66f3b5499f7f 738
screamer 0:66f3b5499f7f 739 try:
theotherjimmy 43:2a7da56ebd24 740 res = Resources(notify).scan_with_toolchain(
theotherjimmy 43:2a7da56ebd24 741 src_paths, toolchain, dependencies_paths, inc_dirs=inc_dirs)
screamer 13:ab47a20b66f0 742
screamer 29:1210849dba19 743 # Copy headers, objects and static libraries - all files needed for
screamer 29:1210849dba19 744 # static lib
theotherjimmy 43:2a7da56ebd24 745 to_copy = (
theotherjimmy 43:2a7da56ebd24 746 res.get_file_refs(FileType.HEADER) +
theotherjimmy 43:2a7da56ebd24 747 res.get_file_refs(FileType.OBJECT) +
theotherjimmy 43:2a7da56ebd24 748 res.get_file_refs(FileType.LIB) +
theotherjimmy 43:2a7da56ebd24 749 res.get_file_refs(FileType.JSON) +
theotherjimmy 43:2a7da56ebd24 750 res.get_file_refs(FileType.LD_SCRIPT) +
theotherjimmy 43:2a7da56ebd24 751 res.get_file_refs(FileType.HEX) +
theotherjimmy 43:2a7da56ebd24 752 res.get_file_refs(FileType.BIN)
theotherjimmy 43:2a7da56ebd24 753 )
theotherjimmy 43:2a7da56ebd24 754 toolchain.copy_files(to_copy, build_path)
screamer 0:66f3b5499f7f 755 # Compile Sources
theotherjimmy 43:2a7da56ebd24 756 objects = toolchain.compile_sources(
theotherjimmy 43:2a7da56ebd24 757 res, res.get_file_paths(FileType.INC_DIR))
theotherjimmy 43:2a7da56ebd24 758 res.add_files_to_type(FileType.OBJECT, objects)
screamer 0:66f3b5499f7f 759
screamer 0:66f3b5499f7f 760 if archive:
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 761 toolchain.build_library(objects, build_path, name)
screamer 0:66f3b5499f7f 762
The Other Jimmy 31:8ea194f6145b 763 if remove_config_header_file:
The Other Jimmy 31:8ea194f6145b 764 config_header_path = toolchain.get_config_header()
The Other Jimmy 31:8ea194f6145b 765 if config_header_path:
The Other Jimmy 31:8ea194f6145b 766 remove(config_header_path)
The Other Jimmy 31:8ea194f6145b 767
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 768 if report != None:
screamer 0:66f3b5499f7f 769 end = time()
screamer 0:66f3b5499f7f 770 cur_result["elapsed_time"] = end - start
screamer 0:66f3b5499f7f 771 cur_result["result"] = "OK"
screamer 0:66f3b5499f7f 772 add_result_to_report(report, cur_result)
screamer 22:9e85236d8716 773 return True
screamer 0:66f3b5499f7f 774
screamer 29:1210849dba19 775 except Exception as exc:
screamer 0:66f3b5499f7f 776 if report != None:
screamer 0:66f3b5499f7f 777 end = time()
screamer 22:9e85236d8716 778
screamer 29:1210849dba19 779 if isinstance(exc, ToolException):
screamer 7:5af61d55adbe 780 cur_result["result"] = "FAIL"
screamer 29:1210849dba19 781 elif isinstance(exc, NotSupportedException):
screamer 7:5af61d55adbe 782 cur_result["result"] = "NOT_SUPPORTED"
screamer 22:9e85236d8716 783
screamer 0:66f3b5499f7f 784 cur_result["elapsed_time"] = end - start
screamer 0:66f3b5499f7f 785
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 786 add_result_to_report(report, cur_result)
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 787
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 788 # Let Exception propagate
screamer 29:1210849dba19 789 raise
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 790
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 791 ######################
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 792 ### Legacy methods ###
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 793 ######################
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 794
The Other Jimmy 36:96847d42f010 795 def mbed2_obj_path(target_name, toolchain_name):
The Other Jimmy 36:96847d42f010 796 real_tc_name = TOOLCHAIN_CLASSES[toolchain_name].__name__
The Other Jimmy 36:96847d42f010 797 return join("TARGET_" + target_name, "TOOLCHAIN_" + real_tc_name)
The Other Jimmy 36:96847d42f010 798
theotherjimmy 43:2a7da56ebd24 799 def build_lib(lib_id, target, toolchain_name, clean=False, macros=None,
theotherjimmy 43:2a7da56ebd24 800 notify=None, jobs=1, report=None, properties=None,
theotherjimmy 43:2a7da56ebd24 801 build_profile=None, ignore=None):
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 802 """ Legacy method for building mbed libraries
screamer 29:1210849dba19 803
screamer 29:1210849dba19 804 Positional arguments:
screamer 29:1210849dba19 805 lib_id - the library's unique identifier
screamer 29:1210849dba19 806 target - the MCU or board that the project will compile for
screamer 29:1210849dba19 807 toolchain_name - the name of the build tools
screamer 29:1210849dba19 808
screamer 29:1210849dba19 809 Keyword arguments:
screamer 29:1210849dba19 810 clean - Rebuild everything if True
screamer 29:1210849dba19 811 macros - additional macros
screamer 29:1210849dba19 812 notify - Notify function for logs
screamer 29:1210849dba19 813 jobs - how many compilers we can run at once
screamer 29:1210849dba19 814 report - a dict where a result may be appended
screamer 29:1210849dba19 815 properties - UUUUHHHHH beats me
The Other Jimmy 31:8ea194f6145b 816 build_profile - a dict of flags that will be passed to the compiler
theotherjimmy 43:2a7da56ebd24 817 ignore - list of paths to add to mbedignore
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 818 """
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 819 lib = Library(lib_id)
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 820 if not lib.is_supported(target, toolchain_name):
screamer 29:1210849dba19 821 print('Library "%s" is not yet supported on target %s with toolchain %s'
screamer 29:1210849dba19 822 % (lib_id, target.name, toolchain_name))
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 823 return False
screamer 22:9e85236d8716 824
screamer 29:1210849dba19 825 # We need to combine macros from parameter list with macros from library
screamer 29:1210849dba19 826 # definition
screamer 29:1210849dba19 827 lib_macros = lib.macros if lib.macros else []
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 828 if macros:
screamer 29:1210849dba19 829 macros.extend(lib_macros)
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 830 else:
screamer 29:1210849dba19 831 macros = lib_macros
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 832
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 833 src_paths = lib.source_dir
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 834 build_path = lib.build_dir
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 835 dependencies_paths = lib.dependencies
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 836 inc_dirs = lib.inc_dirs
screamer 22:9e85236d8716 837
theotherjimmy 43:2a7da56ebd24 838 if not isinstance(src_paths, list):
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 839 src_paths = [src_paths]
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 840
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 841 # The first path will give the name to the library
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 842 name = basename(src_paths[0])
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 843
theotherjimmy 43:2a7da56ebd24 844 if report is not None:
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 845 start = time()
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 846 id_name = name.upper()
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 847 description = name
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 848 vendor_label = target.extra_labels[0]
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 849 cur_result = None
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 850 prep_report(report, target.name, toolchain_name, id_name)
screamer 29:1210849dba19 851 cur_result = create_result(target.name, toolchain_name, id_name,
screamer 29:1210849dba19 852 description)
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 853
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 854 if properties != None:
screamer 29:1210849dba19 855 prep_properties(properties, target.name, toolchain_name,
screamer 29:1210849dba19 856 vendor_label)
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 857
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 858 for src_path in src_paths:
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 859 if not exists(src_path):
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 860 error_msg = "The library source folder does not exist: %s", src_path
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 861
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 862 if report != None:
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 863 cur_result["output"] = error_msg
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 864 cur_result["result"] = "FAIL"
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 865 add_result_to_report(report, cur_result)
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 866
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 867 raise Exception(error_msg)
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 868
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 869 try:
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 870 # Toolchain instance
The Other Jimmy 36:96847d42f010 871 # Create the desired build directory structure
The Other Jimmy 36:96847d42f010 872 bin_path = join(build_path, mbed2_obj_path(target.name, toolchain_name))
The Other Jimmy 36:96847d42f010 873 mkdir(bin_path)
The Other Jimmy 36:96847d42f010 874 tmp_path = join(build_path, '.temp', mbed2_obj_path(target.name,
The Other Jimmy 36:96847d42f010 875 toolchain_name))
The Other Jimmy 36:96847d42f010 876 mkdir(tmp_path)
The Other Jimmy 36:96847d42f010 877
The Other Jimmy 36:96847d42f010 878 toolchain = prepare_toolchain(
The Other Jimmy 36:96847d42f010 879 src_paths, tmp_path, target, toolchain_name, macros=macros,
theotherjimmy 43:2a7da56ebd24 880 notify=notify, build_profile=build_profile, jobs=jobs, clean=clean,
theotherjimmy 43:2a7da56ebd24 881 ignore=ignore)
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 882
theotherjimmy 43:2a7da56ebd24 883 notify.info("Building library %s (%s, %s)" %
theotherjimmy 43:2a7da56ebd24 884 (name.upper(), target.name, toolchain_name))
screamer 29:1210849dba19 885
screamer 29:1210849dba19 886 # Take into account the library configuration (MBED_CONFIG_FILE)
The Other Jimmy 36:96847d42f010 887 config = toolchain.config
screamer 29:1210849dba19 888 config.add_config_files([MBED_CONFIG_FILE])
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 889
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 890 # Scan Resources
theotherjimmy 43:2a7da56ebd24 891 resources = Resources(notify).scan_with_toolchain(
theotherjimmy 43:2a7da56ebd24 892 src_paths + (lib.inc_dirs_ext or []), toolchain,
theotherjimmy 43:2a7da56ebd24 893 inc_dirs=inc_dirs, dependencies_paths=dependencies_paths)
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 894
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 895 # Copy Headers
theotherjimmy 43:2a7da56ebd24 896 toolchain.copy_files(
theotherjimmy 43:2a7da56ebd24 897 resources.get_file_refs(FileType.HEADER), build_path)
screamer 22:9e85236d8716 898
theotherjimmy 43:2a7da56ebd24 899 dependencies_include_dir = Resources(notify).sacn_with_toolchain([build_path], toolchain).inc_dirs
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 900
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 901 # Compile Sources
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 902 objects = []
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 903 for resource in resources:
The Other Jimmy 36:96847d42f010 904 objects.extend(toolchain.compile_sources(resource, dependencies_include_dir))
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 905
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 906 needed_update = toolchain.build_library(objects, bin_path, name)
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 907
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 908 if report != None and needed_update:
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 909 end = time()
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 910 cur_result["elapsed_time"] = end - start
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 911 cur_result["result"] = "OK"
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 912
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 913 add_result_to_report(report, cur_result)
screamer 22:9e85236d8716 914 return True
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 915
screamer 29:1210849dba19 916 except Exception:
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 917 if report != None:
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 918 end = time()
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 919 cur_result["result"] = "FAIL"
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 920 cur_result["elapsed_time"] = end - start
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 921
screamer 0:66f3b5499f7f 922 add_result_to_report(report, cur_result)
screamer 0:66f3b5499f7f 923
screamer 0:66f3b5499f7f 924 # Let Exception propagate
screamer 29:1210849dba19 925 raise
screamer 29:1210849dba19 926
theotherjimmy 43:2a7da56ebd24 927
theotherjimmy 43:2a7da56ebd24 928 # A number of compiled files need to be copied as objects as the linker
theotherjimmy 43:2a7da56ebd24 929 # will not search for weak symbol overrides in archives. These are:
theotherjimmy 43:2a7da56ebd24 930 # - mbed_retarget.o: to make sure that the C standard lib symbols get
theotherjimmy 43:2a7da56ebd24 931 # overridden
theotherjimmy 43:2a7da56ebd24 932 # - mbed_board.o: `mbed_die` is weak
theotherjimmy 43:2a7da56ebd24 933 # - mbed_overrides.o: this contains platform overrides of various
theotherjimmy 43:2a7da56ebd24 934 # weak SDK functions
theotherjimmy 43:2a7da56ebd24 935 # - mbed_main.o: this contains main redirection
theotherjimmy 43:2a7da56ebd24 936 # - mbed_sdk_boot.o: this contains the main boot code in
theotherjimmy 43:2a7da56ebd24 937 # - PeripheralPins.o: PinMap can be weak
theotherjimmy 43:2a7da56ebd24 938 SEPARATE_NAMES = [
theotherjimmy 43:2a7da56ebd24 939 'PeripheralPins.o',
theotherjimmy 43:2a7da56ebd24 940 'mbed_retarget.o',
theotherjimmy 43:2a7da56ebd24 941 'mbed_board.o',
theotherjimmy 43:2a7da56ebd24 942 'mbed_overrides.o',
theotherjimmy 43:2a7da56ebd24 943 'mbed_main.o',
theotherjimmy 43:2a7da56ebd24 944 'mbed_sdk_boot.o',
theotherjimmy 43:2a7da56ebd24 945 ]
theotherjimmy 43:2a7da56ebd24 946
theotherjimmy 43:2a7da56ebd24 947
theotherjimmy 43:2a7da56ebd24 948 def build_mbed_libs(target, toolchain_name, clean=False, macros=None,
theotherjimmy 43:2a7da56ebd24 949 notify=None, jobs=1, report=None, properties=None,
theotherjimmy 43:2a7da56ebd24 950 build_profile=None, ignore=None):
theotherjimmy 43:2a7da56ebd24 951 """ Build legacy libraries for a target and toolchain pair
screamer 0:66f3b5499f7f 952
screamer 29:1210849dba19 953 Positional arguments:
screamer 29:1210849dba19 954 target - the MCU or board that the project will compile for
screamer 29:1210849dba19 955 toolchain_name - the name of the build tools
screamer 29:1210849dba19 956
screamer 29:1210849dba19 957 Keyword arguments:
screamer 29:1210849dba19 958 clean - Rebuild everything if True
screamer 29:1210849dba19 959 macros - additional macros
screamer 29:1210849dba19 960 notify - Notify function for logs
screamer 29:1210849dba19 961 jobs - how many compilers we can run at once
screamer 29:1210849dba19 962 report - a dict where a result may be appended
screamer 29:1210849dba19 963 properties - UUUUHHHHH beats me
The Other Jimmy 31:8ea194f6145b 964 build_profile - a dict of flags that will be passed to the compiler
theotherjimmy 43:2a7da56ebd24 965 ignore - list of paths to add to mbedignore
theotherjimmy 43:2a7da56ebd24 966
theotherjimmy 43:2a7da56ebd24 967 Return - True if target + toolchain built correctly, False if not supported
screamer 29:1210849dba19 968 """
screamer 0:66f3b5499f7f 969
theotherjimmy 43:2a7da56ebd24 970 if report is not None:
screamer 0:66f3b5499f7f 971 start = time()
screamer 0:66f3b5499f7f 972 id_name = "MBED"
screamer 0:66f3b5499f7f 973 description = "mbed SDK"
screamer 0:66f3b5499f7f 974 vendor_label = target.extra_labels[0]
screamer 0:66f3b5499f7f 975 cur_result = None
screamer 0:66f3b5499f7f 976 prep_report(report, target.name, toolchain_name, id_name)
theotherjimmy 43:2a7da56ebd24 977 cur_result = create_result(
theotherjimmy 43:2a7da56ebd24 978 target.name, toolchain_name, id_name, description)
theotherjimmy 43:2a7da56ebd24 979 if properties is not None:
theotherjimmy 43:2a7da56ebd24 980 prep_properties(
theotherjimmy 43:2a7da56ebd24 981 properties, target.name, toolchain_name, vendor_label)
screamer 0:66f3b5499f7f 982
screamer 0:66f3b5499f7f 983 if toolchain_name not in target.supported_toolchains:
screamer 0:66f3b5499f7f 984 supported_toolchains_text = ", ".join(target.supported_toolchains)
theotherjimmy 43:2a7da56ebd24 985 notify.info('The target {} does not support the toolchain {}'.format(
theotherjimmy 43:2a7da56ebd24 986 target.name,
theotherjimmy 43:2a7da56ebd24 987 toolchain_name
theotherjimmy 43:2a7da56ebd24 988 ))
theotherjimmy 43:2a7da56ebd24 989 notify.info('{} supports {} toolchain{}'.format(
theotherjimmy 43:2a7da56ebd24 990 target.name,
theotherjimmy 43:2a7da56ebd24 991 supported_toolchains_text,
theotherjimmy 43:2a7da56ebd24 992 's' if len(target.supported_toolchains) > 1 else ''
theotherjimmy 43:2a7da56ebd24 993 ))
screamer 0:66f3b5499f7f 994
theotherjimmy 43:2a7da56ebd24 995 if report is not None:
screamer 0:66f3b5499f7f 996 cur_result["result"] = "SKIP"
screamer 0:66f3b5499f7f 997 add_result_to_report(report, cur_result)
screamer 0:66f3b5499f7f 998
screamer 0:66f3b5499f7f 999 return False
screamer 0:66f3b5499f7f 1000
screamer 0:66f3b5499f7f 1001 try:
The Other Jimmy 36:96847d42f010 1002 # Source and Build Paths
theotherjimmy 43:2a7da56ebd24 1003 build_toolchain = join(
theotherjimmy 43:2a7da56ebd24 1004 MBED_LIBRARIES, mbed2_obj_path(target.name, toolchain_name))
The Other Jimmy 36:96847d42f010 1005 mkdir(build_toolchain)
The Other Jimmy 36:96847d42f010 1006
theotherjimmy 43:2a7da56ebd24 1007 tmp_path = join(
theotherjimmy 43:2a7da56ebd24 1008 MBED_LIBRARIES,
theotherjimmy 43:2a7da56ebd24 1009 '.temp',
theotherjimmy 43:2a7da56ebd24 1010 mbed2_obj_path(target.name, toolchain_name)
theotherjimmy 43:2a7da56ebd24 1011 )
The Other Jimmy 36:96847d42f010 1012 mkdir(tmp_path)
The Other Jimmy 36:96847d42f010 1013
theotherjimmy 43:2a7da56ebd24 1014 # Toolchain and config
The Other Jimmy 36:96847d42f010 1015 toolchain = prepare_toolchain(
theotherjimmy 43:2a7da56ebd24 1016 [""], tmp_path, target, toolchain_name, macros=macros, notify=notify,
theotherjimmy 43:2a7da56ebd24 1017 build_profile=build_profile, jobs=jobs, clean=clean, ignore=ignore)
screamer 0:66f3b5499f7f 1018
The Other Jimmy 36:96847d42f010 1019 config = toolchain.config
screamer 29:1210849dba19 1020 config.add_config_files([MBED_CONFIG_FILE])
screamer 29:1210849dba19 1021 toolchain.set_config_data(toolchain.config.get_config_data())
screamer 29:1210849dba19 1022
theotherjimmy 43:2a7da56ebd24 1023 # distribute header files
theotherjimmy 43:2a7da56ebd24 1024 toolchain.copy_files(
theotherjimmy 43:2a7da56ebd24 1025 [FileRef(basename(MBED_HEADER),MBED_HEADER)], MBED_LIBRARIES)
The Other Jimmy 31:8ea194f6145b 1026 library_incdirs = [dirname(MBED_LIBRARIES), MBED_LIBRARIES]
The Other Jimmy 31:8ea194f6145b 1027
The Other Jimmy 31:8ea194f6145b 1028 for dir, dest in [(MBED_DRIVERS, MBED_LIBRARIES_DRIVERS),
The Other Jimmy 31:8ea194f6145b 1029 (MBED_PLATFORM, MBED_LIBRARIES_PLATFORM),
The Other Jimmy 31:8ea194f6145b 1030 (MBED_HAL, MBED_LIBRARIES_HAL)]:
theotherjimmy 43:2a7da56ebd24 1031 resources = Resources(notify).scan_with_toolchain([dir], toolchain)
theotherjimmy 43:2a7da56ebd24 1032 toolchain.copy_files(
theotherjimmy 43:2a7da56ebd24 1033 [FileRef(basename(p), p) for p
theotherjimmy 43:2a7da56ebd24 1034 in resources.get_file_paths(FileType.HEADER)] ,
theotherjimmy 43:2a7da56ebd24 1035 dest)
The Other Jimmy 31:8ea194f6145b 1036 library_incdirs.append(dest)
screamer 0:66f3b5499f7f 1037
theotherjimmy 43:2a7da56ebd24 1038 # collect resources of the libs to compile
theotherjimmy 43:2a7da56ebd24 1039 cmsis_res = Resources(notify).scan_with_toolchain(
theotherjimmy 43:2a7da56ebd24 1040 [MBED_CMSIS_PATH], toolchain)
theotherjimmy 43:2a7da56ebd24 1041 hal_res = Resources(notify).scan_with_toolchain(
theotherjimmy 43:2a7da56ebd24 1042 [MBED_TARGETS_PATH], toolchain)
theotherjimmy 43:2a7da56ebd24 1043 mbed_resources = Resources(notify).scan_with_toolchain(
theotherjimmy 43:2a7da56ebd24 1044 [MBED_DRIVERS, MBED_PLATFORM, MBED_HAL], toolchain)
screamer 0:66f3b5499f7f 1045
theotherjimmy 43:2a7da56ebd24 1046 incdirs = cmsis_res.inc_dirs + hal_res.inc_dirs + library_incdirs
screamer 0:66f3b5499f7f 1047
theotherjimmy 43:2a7da56ebd24 1048 # Build Things
theotherjimmy 43:2a7da56ebd24 1049 notify.info("Building library %s (%s, %s)" %
theotherjimmy 43:2a7da56ebd24 1050 ('MBED', target.name, toolchain_name))
theotherjimmy 43:2a7da56ebd24 1051 objects = toolchain.compile_sources(mbed_resources, incdirs)
theotherjimmy 43:2a7da56ebd24 1052 separate_objects = []
screamer 0:66f3b5499f7f 1053
screamer 29:1210849dba19 1054 for obj in objects:
theotherjimmy 43:2a7da56ebd24 1055 for name in SEPARATE_NAMES:
screamer 29:1210849dba19 1056 if obj.endswith(name):
screamer 29:1210849dba19 1057 separate_objects.append(obj)
screamer 0:66f3b5499f7f 1058
screamer 29:1210849dba19 1059 for obj in separate_objects:
screamer 29:1210849dba19 1060 objects.remove(obj)
screamer 0:66f3b5499f7f 1061
screamer 29:1210849dba19 1062 toolchain.build_library(objects, build_toolchain, "mbed")
theotherjimmy 43:2a7da56ebd24 1063 notify.info("Building library %s (%s, %s)" %
theotherjimmy 43:2a7da56ebd24 1064 ('CMSIS', target.name, toolchain_name))
theotherjimmy 43:2a7da56ebd24 1065 cmsis_objects = toolchain.compile_sources(cmsis_res, incdirs + [tmp_path])
theotherjimmy 43:2a7da56ebd24 1066 notify.info("Building library %s (%s, %s)" %
theotherjimmy 43:2a7da56ebd24 1067 ('HAL', target.name, toolchain_name))
theotherjimmy 43:2a7da56ebd24 1068 hal_objects = toolchain.compile_sources(hal_res, incdirs + [tmp_path])
screamer 0:66f3b5499f7f 1069
theotherjimmy 43:2a7da56ebd24 1070 # Copy everything into the build directory
theotherjimmy 43:2a7da56ebd24 1071 to_copy_paths = [
theotherjimmy 43:2a7da56ebd24 1072 hal_res.get_file_paths(FileType.HEADER),
theotherjimmy 43:2a7da56ebd24 1073 hal_res.get_file_paths(FileType.HEX),
theotherjimmy 43:2a7da56ebd24 1074 hal_res.get_file_paths(FileType.BIN),
theotherjimmy 43:2a7da56ebd24 1075 hal_res.get_file_paths(FileType.LIB),
theotherjimmy 43:2a7da56ebd24 1076 cmsis_res.get_file_paths(FileType.HEADER),
theotherjimmy 43:2a7da56ebd24 1077 cmsis_res.get_file_paths(FileType.BIN),
theotherjimmy 43:2a7da56ebd24 1078 cmsis_res.get_file_paths(FileType.LD_SCRIPT),
theotherjimmy 43:2a7da56ebd24 1079 hal_res.get_file_paths(FileType.LD_SCRIPT),
theotherjimmy 43:2a7da56ebd24 1080 [MBED_CONFIG_FILE],
theotherjimmy 43:2a7da56ebd24 1081 cmsis_objects,
theotherjimmy 43:2a7da56ebd24 1082 hal_objects,
theotherjimmy 43:2a7da56ebd24 1083 separate_objects,
theotherjimmy 43:2a7da56ebd24 1084 ]
theotherjimmy 43:2a7da56ebd24 1085 to_copy = [FileRef(basename(p), p) for p in sum(to_copy_paths, [])]
theotherjimmy 43:2a7da56ebd24 1086 toolchain.copy_files(to_copy, build_toolchain)
screamer 0:66f3b5499f7f 1087
theotherjimmy 43:2a7da56ebd24 1088 if report is not None:
screamer 0:66f3b5499f7f 1089 end = time()
screamer 0:66f3b5499f7f 1090 cur_result["elapsed_time"] = end - start
screamer 0:66f3b5499f7f 1091 cur_result["result"] = "OK"
screamer 0:66f3b5499f7f 1092 add_result_to_report(report, cur_result)
screamer 0:66f3b5499f7f 1093
screamer 0:66f3b5499f7f 1094 return True
screamer 0:66f3b5499f7f 1095
screamer 29:1210849dba19 1096 except Exception as exc:
theotherjimmy 43:2a7da56ebd24 1097 if report is not None:
screamer 0:66f3b5499f7f 1098 end = time()
screamer 0:66f3b5499f7f 1099 cur_result["result"] = "FAIL"
screamer 0:66f3b5499f7f 1100 cur_result["elapsed_time"] = end - start
screamer 0:66f3b5499f7f 1101
screamer 29:1210849dba19 1102 cur_result["output"] += str(exc)
screamer 0:66f3b5499f7f 1103
screamer 0:66f3b5499f7f 1104 add_result_to_report(report, cur_result)
screamer 29:1210849dba19 1105 raise
screamer 0:66f3b5499f7f 1106
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 1107
screamer 24:25bff2709c20 1108 def get_unique_supported_toolchains(release_targets=None):
screamer 24:25bff2709c20 1109 """ Get list of all unique toolchains supported by targets
screamer 29:1210849dba19 1110
screamer 29:1210849dba19 1111 Keyword arguments:
screamer 29:1210849dba19 1112 release_targets - tuple structure returned from get_mbed_official_release().
screamer 29:1210849dba19 1113 If release_targets is not specified, then it queries all
screamer 29:1210849dba19 1114 known targets
screamer 24:25bff2709c20 1115 """
screamer 0:66f3b5499f7f 1116 unique_supported_toolchains = []
screamer 24:25bff2709c20 1117
screamer 24:25bff2709c20 1118 if not release_targets:
screamer 24:25bff2709c20 1119 for target in TARGET_NAMES:
screamer 24:25bff2709c20 1120 for toolchain in TARGET_MAP[target].supported_toolchains:
screamer 24:25bff2709c20 1121 if toolchain not in unique_supported_toolchains:
screamer 24:25bff2709c20 1122 unique_supported_toolchains.append(toolchain)
screamer 24:25bff2709c20 1123 else:
screamer 24:25bff2709c20 1124 for target in release_targets:
screamer 24:25bff2709c20 1125 for toolchain in target[1]:
screamer 24:25bff2709c20 1126 if toolchain not in unique_supported_toolchains:
screamer 24:25bff2709c20 1127 unique_supported_toolchains.append(toolchain)
screamer 24:25bff2709c20 1128
theotherjimmy 43:2a7da56ebd24 1129 return unique_supported_toolchains
theotherjimmy 43:2a7da56ebd24 1130
theotherjimmy 40:7d3fa6b99b2b 1131
theotherjimmy 43:2a7da56ebd24 1132 def _lowercase_release_version(release_version):
theotherjimmy 43:2a7da56ebd24 1133 try:
theotherjimmy 43:2a7da56ebd24 1134 return release_version.lower()
theotherjimmy 43:2a7da56ebd24 1135 except AttributeError:
theotherjimmy 43:2a7da56ebd24 1136 return 'all'
screamer 0:66f3b5499f7f 1137
The Other Jimmy 36:96847d42f010 1138 def mcu_toolchain_list(release_version='5'):
The Other Jimmy 36:96847d42f010 1139 """ Shows list of toolchains
The Other Jimmy 36:96847d42f010 1140
The Other Jimmy 36:96847d42f010 1141 """
theotherjimmy 43:2a7da56ebd24 1142 release_version = _lowercase_release_version(release_version)
The Other Jimmy 36:96847d42f010 1143 version_release_targets = {}
The Other Jimmy 36:96847d42f010 1144 version_release_target_names = {}
The Other Jimmy 36:96847d42f010 1145
The Other Jimmy 36:96847d42f010 1146 for version in RELEASE_VERSIONS:
The Other Jimmy 36:96847d42f010 1147 version_release_targets[version] = get_mbed_official_release(version)
The Other Jimmy 36:96847d42f010 1148 version_release_target_names[version] = [x[0] for x in
The Other Jimmy 36:96847d42f010 1149 version_release_targets[
The Other Jimmy 36:96847d42f010 1150 version]]
The Other Jimmy 36:96847d42f010 1151
The Other Jimmy 36:96847d42f010 1152 if release_version in RELEASE_VERSIONS:
The Other Jimmy 36:96847d42f010 1153 release_targets = version_release_targets[release_version]
The Other Jimmy 36:96847d42f010 1154 else:
The Other Jimmy 36:96847d42f010 1155 release_targets = None
The Other Jimmy 36:96847d42f010 1156
The Other Jimmy 36:96847d42f010 1157 unique_supported_toolchains = get_unique_supported_toolchains(
The Other Jimmy 36:96847d42f010 1158 release_targets)
The Other Jimmy 36:96847d42f010 1159 columns = ["mbed OS %s" % x for x in RELEASE_VERSIONS] + unique_supported_toolchains
The Other Jimmy 36:96847d42f010 1160 return "\n".join(columns)
The Other Jimmy 36:96847d42f010 1161
The Other Jimmy 36:96847d42f010 1162
The Other Jimmy 36:96847d42f010 1163 def mcu_target_list(release_version='5'):
theotherjimmy 40:7d3fa6b99b2b 1164 """ Shows target list
The Other Jimmy 36:96847d42f010 1165
The Other Jimmy 36:96847d42f010 1166 """
theotherjimmy 43:2a7da56ebd24 1167 release_version = _lowercase_release_version(release_version)
The Other Jimmy 36:96847d42f010 1168 version_release_targets = {}
The Other Jimmy 36:96847d42f010 1169 version_release_target_names = {}
The Other Jimmy 36:96847d42f010 1170
The Other Jimmy 36:96847d42f010 1171 for version in RELEASE_VERSIONS:
The Other Jimmy 36:96847d42f010 1172 version_release_targets[version] = get_mbed_official_release(version)
The Other Jimmy 36:96847d42f010 1173 version_release_target_names[version] = [x[0] for x in
The Other Jimmy 36:96847d42f010 1174 version_release_targets[
The Other Jimmy 36:96847d42f010 1175 version]]
The Other Jimmy 36:96847d42f010 1176
The Other Jimmy 36:96847d42f010 1177 if release_version in RELEASE_VERSIONS:
The Other Jimmy 36:96847d42f010 1178 release_targets = version_release_targets[release_version]
The Other Jimmy 36:96847d42f010 1179 else:
The Other Jimmy 36:96847d42f010 1180 release_targets = None
The Other Jimmy 36:96847d42f010 1181
The Other Jimmy 36:96847d42f010 1182 target_names = []
The Other Jimmy 36:96847d42f010 1183
The Other Jimmy 36:96847d42f010 1184 if release_targets:
The Other Jimmy 36:96847d42f010 1185 target_names = [x[0] for x in release_targets]
The Other Jimmy 36:96847d42f010 1186 else:
The Other Jimmy 36:96847d42f010 1187 target_names = TARGET_NAMES
The Other Jimmy 36:96847d42f010 1188
The Other Jimmy 36:96847d42f010 1189 return "\n".join(target_names)
The Other Jimmy 36:96847d42f010 1190
screamer 0:66f3b5499f7f 1191
screamer 29:1210849dba19 1192 def mcu_toolchain_matrix(verbose_html=False, platform_filter=None,
screamer 29:1210849dba19 1193 release_version='5'):
screamer 29:1210849dba19 1194 """ Shows target map using prettytable
screamer 29:1210849dba19 1195
screamer 29:1210849dba19 1196 Keyword arguments:
screamer 29:1210849dba19 1197 verbose_html - emit html instead of a simple table
screamer 29:1210849dba19 1198 platform_filter - remove results that match the string
screamer 29:1210849dba19 1199 release_version - get the matrix for this major version number
screamer 29:1210849dba19 1200 """
screamer 29:1210849dba19 1201 # Only use it in this function so building works without extra modules
theotherjimmy 43:2a7da56ebd24 1202 from prettytable import PrettyTable, HEADER
theotherjimmy 43:2a7da56ebd24 1203 release_version = _lowercase_release_version(release_version)
screamer 24:25bff2709c20 1204 version_release_targets = {}
screamer 24:25bff2709c20 1205 version_release_target_names = {}
screamer 24:25bff2709c20 1206
screamer 24:25bff2709c20 1207 for version in RELEASE_VERSIONS:
screamer 24:25bff2709c20 1208 version_release_targets[version] = get_mbed_official_release(version)
screamer 29:1210849dba19 1209 version_release_target_names[version] = [x[0] for x in
screamer 29:1210849dba19 1210 version_release_targets[
screamer 29:1210849dba19 1211 version]]
screamer 24:25bff2709c20 1212
screamer 24:25bff2709c20 1213 if release_version in RELEASE_VERSIONS:
screamer 24:25bff2709c20 1214 release_targets = version_release_targets[release_version]
screamer 24:25bff2709c20 1215 else:
screamer 24:25bff2709c20 1216 release_targets = None
screamer 24:25bff2709c20 1217
screamer 29:1210849dba19 1218 unique_supported_toolchains = get_unique_supported_toolchains(
screamer 29:1210849dba19 1219 release_targets)
screamer 24:25bff2709c20 1220 prepend_columns = ["Target"] + ["mbed OS %s" % x for x in RELEASE_VERSIONS]
screamer 24:25bff2709c20 1221
screamer 0:66f3b5499f7f 1222 # All tests status table print
screamer 24:25bff2709c20 1223 columns = prepend_columns + unique_supported_toolchains
theotherjimmy 43:2a7da56ebd24 1224 table_printer = PrettyTable(columns, junction_char="|", hrules=HEADER)
screamer 0:66f3b5499f7f 1225 # Align table
screamer 0:66f3b5499f7f 1226 for col in columns:
screamer 29:1210849dba19 1227 table_printer.align[col] = "c"
screamer 29:1210849dba19 1228 table_printer.align["Target"] = "l"
screamer 0:66f3b5499f7f 1229
screamer 0:66f3b5499f7f 1230 perm_counter = 0
screamer 0:66f3b5499f7f 1231 target_counter = 0
screamer 24:25bff2709c20 1232
screamer 24:25bff2709c20 1233 target_names = []
screamer 24:25bff2709c20 1234
screamer 24:25bff2709c20 1235 if release_targets:
screamer 24:25bff2709c20 1236 target_names = [x[0] for x in release_targets]
screamer 24:25bff2709c20 1237 else:
screamer 24:25bff2709c20 1238 target_names = TARGET_NAMES
screamer 24:25bff2709c20 1239
screamer 24:25bff2709c20 1240 for target in sorted(target_names):
screamer 0:66f3b5499f7f 1241 if platform_filter is not None:
screamer 0:66f3b5499f7f 1242 # FIlter out platforms using regex
screamer 0:66f3b5499f7f 1243 if re.search(platform_filter, target) is None:
screamer 0:66f3b5499f7f 1244 continue
screamer 0:66f3b5499f7f 1245 target_counter += 1
screamer 0:66f3b5499f7f 1246
screamer 0:66f3b5499f7f 1247 row = [target] # First column is platform name
screamer 24:25bff2709c20 1248
screamer 24:25bff2709c20 1249 for version in RELEASE_VERSIONS:
screamer 24:25bff2709c20 1250 if target in version_release_target_names[version]:
screamer 24:25bff2709c20 1251 text = "Supported"
screamer 24:25bff2709c20 1252 else:
screamer 24:25bff2709c20 1253 text = "-"
screamer 24:25bff2709c20 1254 row.append(text)
screamer 24:25bff2709c20 1255
screamer 0:66f3b5499f7f 1256 for unique_toolchain in unique_supported_toolchains:
theotherjimmy 43:2a7da56ebd24 1257 tgt_obj = TARGET_MAP[target]
theotherjimmy 43:2a7da56ebd24 1258 if (unique_toolchain in tgt_obj.supported_toolchains or
theotherjimmy 40:7d3fa6b99b2b 1259 (unique_toolchain == "ARMC6" and
theotherjimmy 43:2a7da56ebd24 1260 "ARM" in tgt_obj.supported_toolchains) or
theotherjimmy 43:2a7da56ebd24 1261 (unique_toolchain == "ARM" and
theotherjimmy 43:2a7da56ebd24 1262 "ARMC6" in tgt_obj.supported_toolchains and
theotherjimmy 43:2a7da56ebd24 1263 CORE_ARCH[tgt_obj.core] == 8)):
screamer 0:66f3b5499f7f 1264 text = "Supported"
screamer 0:66f3b5499f7f 1265 perm_counter += 1
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 1266 else:
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 1267 text = "-"
screamer 22:9e85236d8716 1268
screamer 0:66f3b5499f7f 1269 row.append(text)
screamer 29:1210849dba19 1270 table_printer.add_row(row)
screamer 0:66f3b5499f7f 1271
screamer 29:1210849dba19 1272 result = table_printer.get_html_string() if verbose_html \
screamer 29:1210849dba19 1273 else table_printer.get_string()
screamer 0:66f3b5499f7f 1274 result += "\n"
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 1275 result += "Supported targets: %d\n"% (target_counter)
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 1276 if target_counter == 1:
Screamer@Y5070-M.virtuoso 9:2d27d77ada5c 1277 result += "Supported toolchains: %d"% (perm_counter)
screamer 0:66f3b5499f7f 1278 return result
screamer 0:66f3b5499f7f 1279
screamer 0:66f3b5499f7f 1280
screamer 0:66f3b5499f7f 1281 def get_target_supported_toolchains(target):
screamer 29:1210849dba19 1282 """ Returns target supported toolchains list
screamer 29:1210849dba19 1283
screamer 29:1210849dba19 1284 Positional arguments:
screamer 29:1210849dba19 1285 target - the target to get the supported toolchains of
screamer 29:1210849dba19 1286 """
screamer 29:1210849dba19 1287 return TARGET_MAP[target].supported_toolchains if target in TARGET_MAP \
screamer 29:1210849dba19 1288 else None
screamer 0:66f3b5499f7f 1289
screamer 0:66f3b5499f7f 1290
screamer 0:66f3b5499f7f 1291 def print_build_results(result_list, build_name):
screamer 29:1210849dba19 1292 """ Generate result string for build results
screamer 29:1210849dba19 1293
screamer 29:1210849dba19 1294 Positional arguments:
screamer 29:1210849dba19 1295 result_list - the list of results to print
screamer 29:1210849dba19 1296 build_name - the name of the build we are printing result for
screamer 29:1210849dba19 1297 """
screamer 0:66f3b5499f7f 1298 result = ""
screamer 0:66f3b5499f7f 1299 if len(result_list) > 0:
screamer 0:66f3b5499f7f 1300 result += build_name + "\n"
screamer 0:66f3b5499f7f 1301 result += "\n".join([" * %s" % f for f in result_list])
screamer 0:66f3b5499f7f 1302 result += "\n"
screamer 0:66f3b5499f7f 1303 return result
screamer 0:66f3b5499f7f 1304
screamer 29:1210849dba19 1305 def print_build_memory_usage(report):
screamer 22:9e85236d8716 1306 """ Generate result table with memory usage values for build results
screamer 29:1210849dba19 1307 Aggregates (puts together) reports obtained from self.get_memory_summary()
screamer 29:1210849dba19 1308
screamer 29:1210849dba19 1309 Positional arguments:
screamer 29:1210849dba19 1310 report - Report generated during build procedure.
screamer 22:9e85236d8716 1311 """
theotherjimmy 43:2a7da56ebd24 1312 from prettytable import PrettyTable, HEADER
screamer 22:9e85236d8716 1313 columns_text = ['name', 'target', 'toolchain']
theotherjimmy 40:7d3fa6b99b2b 1314 columns_int = ['static_ram', 'total_flash']
theotherjimmy 43:2a7da56ebd24 1315 table = PrettyTable(columns_text + columns_int, junction_char="|", hrules=HEADER)
screamer 22:9e85236d8716 1316
screamer 22:9e85236d8716 1317 for col in columns_text:
screamer 22:9e85236d8716 1318 table.align[col] = 'l'
screamer 22:9e85236d8716 1319
screamer 22:9e85236d8716 1320 for col in columns_int:
screamer 22:9e85236d8716 1321 table.align[col] = 'r'
screamer 22:9e85236d8716 1322
screamer 22:9e85236d8716 1323 for target in report:
screamer 22:9e85236d8716 1324 for toolchain in report[target]:
screamer 22:9e85236d8716 1325 for name in report[target][toolchain]:
screamer 22:9e85236d8716 1326 for dlist in report[target][toolchain][name]:
screamer 22:9e85236d8716 1327 for dlistelem in dlist:
screamer 29:1210849dba19 1328 # Get 'memory_usage' record and build table with
screamer 29:1210849dba19 1329 # statistics
screamer 22:9e85236d8716 1330 record = dlist[dlistelem]
screamer 22:9e85236d8716 1331 if 'memory_usage' in record and record['memory_usage']:
screamer 22:9e85236d8716 1332 # Note that summary should be in the last record of
screamer 29:1210849dba19 1333 # 'memory_usage' section. This is why we are
screamer 29:1210849dba19 1334 # grabbing last "[-1]" record.
screamer 22:9e85236d8716 1335 row = [
screamer 22:9e85236d8716 1336 record['description'],
screamer 22:9e85236d8716 1337 record['target_name'],
screamer 22:9e85236d8716 1338 record['toolchain_name'],
screamer 29:1210849dba19 1339 record['memory_usage'][-1]['summary'][
screamer 29:1210849dba19 1340 'static_ram'],
screamer 29:1210849dba19 1341 record['memory_usage'][-1]['summary'][
screamer 29:1210849dba19 1342 'total_flash'],
screamer 22:9e85236d8716 1343 ]
screamer 22:9e85236d8716 1344 table.add_row(row)
screamer 22:9e85236d8716 1345
screamer 22:9e85236d8716 1346 result = "Memory map breakdown for built projects (values in Bytes):\n"
screamer 22:9e85236d8716 1347 result += table.get_string(sortby='name')
screamer 22:9e85236d8716 1348 return result
screamer 22:9e85236d8716 1349
screamer 0:66f3b5499f7f 1350 def write_build_report(build_report, template_filename, filename):
screamer 29:1210849dba19 1351 """Write a build report to disk using a template file
screamer 29:1210849dba19 1352
screamer 29:1210849dba19 1353 Positional arguments:
screamer 29:1210849dba19 1354 build_report - a report generated by the build system
screamer 29:1210849dba19 1355 template_filename - a file that contains the template for the style of build
screamer 29:1210849dba19 1356 report
screamer 29:1210849dba19 1357 filename - the location on disk to write the file to
screamer 29:1210849dba19 1358 """
screamer 0:66f3b5499f7f 1359 build_report_failing = []
screamer 0:66f3b5499f7f 1360 build_report_passing = []
screamer 0:66f3b5499f7f 1361
screamer 0:66f3b5499f7f 1362 for report in build_report:
screamer 0:66f3b5499f7f 1363 if len(report["failing"]) > 0:
screamer 0:66f3b5499f7f 1364 build_report_failing.append(report)
screamer 0:66f3b5499f7f 1365 else:
screamer 0:66f3b5499f7f 1366 build_report_passing.append(report)
screamer 0:66f3b5499f7f 1367
screamer 0:66f3b5499f7f 1368 env = Environment(extensions=['jinja2.ext.with_'])
screamer 0:66f3b5499f7f 1369 env.loader = FileSystemLoader('ci_templates')
screamer 0:66f3b5499f7f 1370 template = env.get_template(template_filename)
screamer 0:66f3b5499f7f 1371
screamer 29:1210849dba19 1372 with open(filename, 'w+') as placeholder:
screamer 29:1210849dba19 1373 placeholder.write(template.render(
screamer 29:1210849dba19 1374 failing_builds=build_report_failing,
screamer 29:1210849dba19 1375 passing_builds=build_report_passing))
The Other Jimmy 36:96847d42f010 1376
The Other Jimmy 36:96847d42f010 1377
The Other Jimmy 36:96847d42f010 1378 def merge_build_data(filename, toolchain_report, app_type):
The Other Jimmy 36:96847d42f010 1379 path_to_file = dirname(abspath(filename))
The Other Jimmy 36:96847d42f010 1380 try:
The Other Jimmy 36:96847d42f010 1381 build_data = load(open(filename))
The Other Jimmy 36:96847d42f010 1382 except (IOError, ValueError):
The Other Jimmy 36:96847d42f010 1383 build_data = {'builds': []}
The Other Jimmy 36:96847d42f010 1384 for tgt in toolchain_report.values():
The Other Jimmy 36:96847d42f010 1385 for tc in tgt.values():
The Other Jimmy 36:96847d42f010 1386 for project in tc.values():
The Other Jimmy 36:96847d42f010 1387 for build in project:
The Other Jimmy 36:96847d42f010 1388 try:
theotherjimmy 43:2a7da56ebd24 1389 build[0]['bin_fullpath'] = build[0]['bin']
theotherjimmy 43:2a7da56ebd24 1390 build[0]['elf_fullpath'] = build[0]['elf']
The Other Jimmy 36:96847d42f010 1391 build[0]['elf'] = relpath(build[0]['elf'], path_to_file)
The Other Jimmy 36:96847d42f010 1392 build[0]['bin'] = relpath(build[0]['bin'], path_to_file)
The Other Jimmy 36:96847d42f010 1393 except KeyError:
The Other Jimmy 36:96847d42f010 1394 pass
The Other Jimmy 36:96847d42f010 1395 if 'type' not in build[0]:
The Other Jimmy 36:96847d42f010 1396 build[0]['type'] = app_type
theotherjimmy 43:2a7da56ebd24 1397 build_data['builds'].insert(0, build[0])
The Other Jimmy 36:96847d42f010 1398 dump(build_data, open(filename, "wb"), indent=4, separators=(',', ': '))