Clone of official tools

Committer:
The Other Jimmy
Date:
Wed Jan 04 11:58:24 2017 -0600
Revision:
31:8ea194f6145b
Parent:
30:f12ce67666d0
Child:
35:da9c89f8be7d
Update tools to follow mbed-os tools release 5.3.1

Who changed what in which revision?

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