Clone of official tools

Committer:
screamer
Date:
Mon Aug 29 11:18:36 2016 +0100
Revision:
29:1210849dba19
Parent:
27:5461402c33f8
Child:
30:f12ce67666d0
Port the latest tools patches from https://github.com/ARMmbed/mbed-os

Who changed what in which revision?

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