BBR 1 Ebene

Committer:
borlanic
Date:
Mon May 14 11:29:06 2018 +0000
Revision:
0:fbdae7e6d805
BBR

Who changed what in which revision?

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