Backup 1

Committer:
borlanic
Date:
Tue Apr 24 11:45:18 2018 +0000
Revision:
0:02dd72d1d465
BaBoRo_test2 - backup 1

Who changed what in which revision?

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