Includes library modifications to allow access to AIN_4 (AIN_0 / 5)

Committer:
bryantaylor
Date:
Tue Sep 20 21:26:12 2016 +0000
Revision:
0:eafc3fd41f75
hackathon

Who changed what in which revision?

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