Clone of official tools

Committer:
The Other Jimmy
Date:
Wed Feb 15 13:53:18 2017 -0600
Revision:
35:da9c89f8be7d
Parent:
31:8ea194f6145b
Child:
36:96847d42f010
Update tools to mbed-os 5.3.5

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