Clone of official tools

Committer:
screamer
Date:
Thu May 19 19:44:41 2016 +0100
Revision:
0:66f3b5499f7f
Child:
1:a99c8e460c5c
Initial revision

Who changed what in which revision?

UserRevisionLine numberNew contents of line
screamer 0:66f3b5499f7f 1 """
screamer 0:66f3b5499f7f 2 mbed SDK
screamer 0:66f3b5499f7f 3 Copyright (c) 2011-2013 ARM Limited
screamer 0:66f3b5499f7f 4
screamer 0:66f3b5499f7f 5 Licensed under the Apache License, Version 2.0 (the "License");
screamer 0:66f3b5499f7f 6 you may not use this file except in compliance with the License.
screamer 0:66f3b5499f7f 7 You may obtain a copy of the License at
screamer 0:66f3b5499f7f 8
screamer 0:66f3b5499f7f 9 http://www.apache.org/licenses/LICENSE-2.0
screamer 0:66f3b5499f7f 10
screamer 0:66f3b5499f7f 11 Unless required by applicable law or agreed to in writing, software
screamer 0:66f3b5499f7f 12 distributed under the License is distributed on an "AS IS" BASIS,
screamer 0:66f3b5499f7f 13 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
screamer 0:66f3b5499f7f 14 See the License for the specific language governing permissions and
screamer 0:66f3b5499f7f 15 limitations under the License.
screamer 0:66f3b5499f7f 16 """
screamer 0:66f3b5499f7f 17
screamer 0:66f3b5499f7f 18 import re
screamer 0:66f3b5499f7f 19 import tempfile
screamer 0:66f3b5499f7f 20 import colorama
screamer 0:66f3b5499f7f 21
screamer 0:66f3b5499f7f 22
screamer 0:66f3b5499f7f 23 from types import ListType
screamer 0:66f3b5499f7f 24 from shutil import rmtree
screamer 0:66f3b5499f7f 25 from os.path import join, exists, basename, abspath
screamer 0:66f3b5499f7f 26 from os import getcwd
screamer 0:66f3b5499f7f 27 from time import time
screamer 0:66f3b5499f7f 28
screamer 0:66f3b5499f7f 29 from tools.utils import mkdir, run_cmd, run_cmd_ext, NotSupportedException
screamer 0:66f3b5499f7f 30 from tools.paths import MBED_TARGETS_PATH, MBED_LIBRARIES, MBED_API, MBED_HAL, MBED_COMMON
screamer 0:66f3b5499f7f 31 from tools.targets import TARGET_NAMES, TARGET_MAP
screamer 0:66f3b5499f7f 32 from tools.libraries import Library
screamer 0:66f3b5499f7f 33 from tools.toolchains import TOOLCHAIN_CLASSES
screamer 0:66f3b5499f7f 34 from jinja2 import FileSystemLoader
screamer 0:66f3b5499f7f 35 from jinja2.environment import Environment
screamer 0:66f3b5499f7f 36
screamer 0:66f3b5499f7f 37
screamer 0:66f3b5499f7f 38 def prep_report(report, target_name, toolchain_name, id_name):
screamer 0:66f3b5499f7f 39 # Setup report keys
screamer 0:66f3b5499f7f 40 if not target_name in report:
screamer 0:66f3b5499f7f 41 report[target_name] = {}
screamer 0:66f3b5499f7f 42
screamer 0:66f3b5499f7f 43 if not toolchain_name in report[target_name]:
screamer 0:66f3b5499f7f 44 report[target_name][toolchain_name] = {}
screamer 0:66f3b5499f7f 45
screamer 0:66f3b5499f7f 46 if not id_name in report[target_name][toolchain_name]:
screamer 0:66f3b5499f7f 47 report[target_name][toolchain_name][id_name] = []
screamer 0:66f3b5499f7f 48
screamer 0:66f3b5499f7f 49 def prep_properties(properties, target_name, toolchain_name, vendor_label):
screamer 0:66f3b5499f7f 50 # Setup test properties
screamer 0:66f3b5499f7f 51 if not target_name in properties:
screamer 0:66f3b5499f7f 52 properties[target_name] = {}
screamer 0:66f3b5499f7f 53
screamer 0:66f3b5499f7f 54 if not toolchain_name in properties[target_name]:
screamer 0:66f3b5499f7f 55 properties[target_name][toolchain_name] = {}
screamer 0:66f3b5499f7f 56
screamer 0:66f3b5499f7f 57 properties[target_name][toolchain_name]["target"] = target_name
screamer 0:66f3b5499f7f 58 properties[target_name][toolchain_name]["vendor"] = vendor_label
screamer 0:66f3b5499f7f 59 properties[target_name][toolchain_name]["toolchain"] = toolchain_name
screamer 0:66f3b5499f7f 60
screamer 0:66f3b5499f7f 61 def create_result(target_name, toolchain_name, id_name, description):
screamer 0:66f3b5499f7f 62 cur_result = {}
screamer 0:66f3b5499f7f 63 cur_result["target_name"] = target_name
screamer 0:66f3b5499f7f 64 cur_result["toolchain_name"] = toolchain_name
screamer 0:66f3b5499f7f 65 cur_result["id"] = id_name
screamer 0:66f3b5499f7f 66 cur_result["description"] = description
screamer 0:66f3b5499f7f 67 cur_result["elapsed_time"] = 0
screamer 0:66f3b5499f7f 68 cur_result["output"] = ""
screamer 0:66f3b5499f7f 69
screamer 0:66f3b5499f7f 70 return cur_result
screamer 0:66f3b5499f7f 71
screamer 0:66f3b5499f7f 72 def add_result_to_report(report, result):
screamer 0:66f3b5499f7f 73 target = result["target_name"]
screamer 0:66f3b5499f7f 74 toolchain = result["toolchain_name"]
screamer 0:66f3b5499f7f 75 id_name = result['id']
screamer 0:66f3b5499f7f 76 result_wrap = { 0: result }
screamer 0:66f3b5499f7f 77 report[target][toolchain][id_name].append(result_wrap)
screamer 0:66f3b5499f7f 78
screamer 0:66f3b5499f7f 79 def build_project(src_path, build_path, target, toolchain_name,
screamer 0:66f3b5499f7f 80 libraries_paths=None, options=None, linker_script=None,
screamer 0:66f3b5499f7f 81 clean=False, notify=None, verbose=False, name=None, macros=None, inc_dirs=None,
screamer 0:66f3b5499f7f 82 jobs=1, silent=False, report=None, properties=None, project_id=None, project_description=None, extra_verbose=False):
screamer 0:66f3b5499f7f 83 """ This function builds project. Project can be for example one test / UT
screamer 0:66f3b5499f7f 84 """
screamer 0:66f3b5499f7f 85 # Toolchain instance
screamer 0:66f3b5499f7f 86 try:
screamer 0:66f3b5499f7f 87 toolchain = TOOLCHAIN_CLASSES[toolchain_name](target, options, notify, macros, silent, extra_verbose=extra_verbose)
screamer 0:66f3b5499f7f 88 except KeyError as e:
screamer 0:66f3b5499f7f 89 raise KeyError("Toolchain %s not supported" % toolchain_name)
screamer 0:66f3b5499f7f 90
screamer 0:66f3b5499f7f 91 toolchain.VERBOSE = verbose
screamer 0:66f3b5499f7f 92 toolchain.jobs = jobs
screamer 0:66f3b5499f7f 93 toolchain.build_all = clean
screamer 0:66f3b5499f7f 94 src_paths = [src_path] if type(src_path) != ListType else src_path
screamer 0:66f3b5499f7f 95
screamer 0:66f3b5499f7f 96 # We need to remove all paths which are repeated to avoid
screamer 0:66f3b5499f7f 97 # multiple compilations and linking with the same objects
screamer 0:66f3b5499f7f 98 src_paths = [src_paths[0]] + list(set(src_paths[1:]))
screamer 0:66f3b5499f7f 99 project_name = basename(abspath(src_paths[0] if src_paths[0] != "." and src_paths[0] != "./" else getcwd()))
screamer 0:66f3b5499f7f 100
screamer 0:66f3b5499f7f 101 if name is None:
screamer 0:66f3b5499f7f 102 # We will use default project name based on project folder name
screamer 0:66f3b5499f7f 103 name = project_name
screamer 0:66f3b5499f7f 104 toolchain.info("Building project %s (%s, %s)" % (project_name, target.name, toolchain_name))
screamer 0:66f3b5499f7f 105 else:
screamer 0:66f3b5499f7f 106 # User used custom global project name to have the same name for the
screamer 0:66f3b5499f7f 107 toolchain.info("Building project %s to %s (%s, %s)" % (project_name, name, target.name, toolchain_name))
screamer 0:66f3b5499f7f 108
screamer 0:66f3b5499f7f 109
screamer 0:66f3b5499f7f 110 if report != None:
screamer 0:66f3b5499f7f 111 start = time()
screamer 0:66f3b5499f7f 112 id_name = project_id.upper()
screamer 0:66f3b5499f7f 113 description = project_description
screamer 0:66f3b5499f7f 114 vendor_label = target.extra_labels[0]
screamer 0:66f3b5499f7f 115 cur_result = None
screamer 0:66f3b5499f7f 116 prep_report(report, target.name, toolchain_name, id_name)
screamer 0:66f3b5499f7f 117 cur_result = create_result(target.name, toolchain_name, id_name, description)
screamer 0:66f3b5499f7f 118
screamer 0:66f3b5499f7f 119 if properties != None:
screamer 0:66f3b5499f7f 120 prep_properties(properties, target.name, toolchain_name, vendor_label)
screamer 0:66f3b5499f7f 121
screamer 0:66f3b5499f7f 122 try:
screamer 0:66f3b5499f7f 123 # Scan src_path and libraries_paths for resources
screamer 0:66f3b5499f7f 124 resources = toolchain.scan_resources(src_paths[0])
screamer 0:66f3b5499f7f 125 for path in src_paths[1:]:
screamer 0:66f3b5499f7f 126 resources.add(toolchain.scan_resources(path))
screamer 0:66f3b5499f7f 127 if libraries_paths is not None:
screamer 0:66f3b5499f7f 128 src_paths.extend(libraries_paths)
screamer 0:66f3b5499f7f 129 for path in libraries_paths:
screamer 0:66f3b5499f7f 130 resources.add(toolchain.scan_resources(path))
screamer 0:66f3b5499f7f 131
screamer 0:66f3b5499f7f 132 if linker_script is not None:
screamer 0:66f3b5499f7f 133 resources.linker_script = linker_script
screamer 0:66f3b5499f7f 134
screamer 0:66f3b5499f7f 135 # Build Directory
screamer 0:66f3b5499f7f 136 if clean:
screamer 0:66f3b5499f7f 137 if exists(build_path):
screamer 0:66f3b5499f7f 138 rmtree(build_path)
screamer 0:66f3b5499f7f 139 mkdir(build_path)
screamer 0:66f3b5499f7f 140
screamer 0:66f3b5499f7f 141 # We need to add if necessary additional include directories
screamer 0:66f3b5499f7f 142 if inc_dirs:
screamer 0:66f3b5499f7f 143 if type(inc_dirs) == ListType:
screamer 0:66f3b5499f7f 144 resources.inc_dirs.extend(inc_dirs)
screamer 0:66f3b5499f7f 145 else:
screamer 0:66f3b5499f7f 146 resources.inc_dirs.append(inc_dirs)
screamer 0:66f3b5499f7f 147 # Compile Sources
screamer 0:66f3b5499f7f 148 for path in src_paths:
screamer 0:66f3b5499f7f 149 src = toolchain.scan_resources(path)
screamer 0:66f3b5499f7f 150 objects = toolchain.compile_sources(src, build_path, resources.inc_dirs)
screamer 0:66f3b5499f7f 151 resources.objects.extend(objects)
screamer 0:66f3b5499f7f 152
screamer 0:66f3b5499f7f 153
screamer 0:66f3b5499f7f 154 # Link Program
screamer 0:66f3b5499f7f 155 res, needed_update = toolchain.link_program(resources, build_path, name)
screamer 0:66f3b5499f7f 156
screamer 0:66f3b5499f7f 157 if report != None and needed_update:
screamer 0:66f3b5499f7f 158 end = time()
screamer 0:66f3b5499f7f 159 cur_result["elapsed_time"] = end - start
screamer 0:66f3b5499f7f 160 cur_result["output"] = toolchain.get_output()
screamer 0:66f3b5499f7f 161 cur_result["result"] = "OK"
screamer 0:66f3b5499f7f 162
screamer 0:66f3b5499f7f 163 add_result_to_report(report, cur_result)
screamer 0:66f3b5499f7f 164
screamer 0:66f3b5499f7f 165 return res
screamer 0:66f3b5499f7f 166
screamer 0:66f3b5499f7f 167 except Exception, e:
screamer 0:66f3b5499f7f 168 if report != None:
screamer 0:66f3b5499f7f 169 end = time()
screamer 0:66f3b5499f7f 170
screamer 0:66f3b5499f7f 171 if isinstance(e, NotSupportedException):
screamer 0:66f3b5499f7f 172 cur_result["result"] = "NOT_SUPPORTED"
screamer 0:66f3b5499f7f 173 else:
screamer 0:66f3b5499f7f 174 cur_result["result"] = "FAIL"
screamer 0:66f3b5499f7f 175
screamer 0:66f3b5499f7f 176 cur_result["elapsed_time"] = end - start
screamer 0:66f3b5499f7f 177
screamer 0:66f3b5499f7f 178 toolchain_output = toolchain.get_output()
screamer 0:66f3b5499f7f 179 if toolchain_output:
screamer 0:66f3b5499f7f 180 cur_result["output"] += toolchain_output
screamer 0:66f3b5499f7f 181
screamer 0:66f3b5499f7f 182 cur_result["output"] += str(e)
screamer 0:66f3b5499f7f 183
screamer 0:66f3b5499f7f 184 add_result_to_report(report, cur_result)
screamer 0:66f3b5499f7f 185
screamer 0:66f3b5499f7f 186 # Let Exception propagate
screamer 0:66f3b5499f7f 187 raise e
screamer 0:66f3b5499f7f 188
screamer 0:66f3b5499f7f 189
screamer 0:66f3b5499f7f 190 def build_library(src_paths, build_path, target, toolchain_name,
screamer 0:66f3b5499f7f 191 dependencies_paths=None, options=None, name=None, clean=False, archive=True,
screamer 0:66f3b5499f7f 192 notify=None, verbose=False, macros=None, inc_dirs=None, inc_dirs_ext=None,
screamer 0:66f3b5499f7f 193 jobs=1, silent=False, report=None, properties=None, extra_verbose=False):
screamer 0:66f3b5499f7f 194 """ src_path: the path of the source directory
screamer 0:66f3b5499f7f 195 build_path: the path of the build directory
screamer 0:66f3b5499f7f 196 target: ['LPC1768', 'LPC11U24', 'LPC2368']
screamer 0:66f3b5499f7f 197 toolchain: ['ARM', 'uARM', 'GCC_ARM', 'GCC_CR']
screamer 0:66f3b5499f7f 198 library_paths: List of paths to additional libraries
screamer 0:66f3b5499f7f 199 clean: Rebuild everything if True
screamer 0:66f3b5499f7f 200 notify: Notify function for logs
screamer 0:66f3b5499f7f 201 verbose: Write the actual tools command lines if True
screamer 0:66f3b5499f7f 202 inc_dirs: additional include directories which should be included in build
screamer 0:66f3b5499f7f 203 inc_dirs_ext: additional include directories which should be copied to library directory
screamer 0:66f3b5499f7f 204 """
screamer 0:66f3b5499f7f 205 if type(src_paths) != ListType:
screamer 0:66f3b5499f7f 206 src_paths = [src_paths]
screamer 0:66f3b5499f7f 207
screamer 0:66f3b5499f7f 208 # The first path will give the name to the library
screamer 0:66f3b5499f7f 209 project_name = basename(abspath(absrc_paths[0] if src_paths[0] != "." and src_paths[0] != "./" else getcwd()))
screamer 0:66f3b5499f7f 210 if name is None:
screamer 0:66f3b5499f7f 211 # We will use default project name based on project folder name
screamer 0:66f3b5499f7f 212 name = project_name
screamer 0:66f3b5499f7f 213
screamer 0:66f3b5499f7f 214 if report != None:
screamer 0:66f3b5499f7f 215 start = time()
screamer 0:66f3b5499f7f 216 id_name = name.upper()
screamer 0:66f3b5499f7f 217 description = name
screamer 0:66f3b5499f7f 218 vendor_label = target.extra_labels[0]
screamer 0:66f3b5499f7f 219 cur_result = None
screamer 0:66f3b5499f7f 220 prep_report(report, target.name, toolchain_name, id_name)
screamer 0:66f3b5499f7f 221 cur_result = create_result(target.name, toolchain_name, id_name, description)
screamer 0:66f3b5499f7f 222
screamer 0:66f3b5499f7f 223 if properties != None:
screamer 0:66f3b5499f7f 224 prep_properties(properties, target.name, toolchain_name, vendor_label)
screamer 0:66f3b5499f7f 225
screamer 0:66f3b5499f7f 226 for src_path in src_paths:
screamer 0:66f3b5499f7f 227 if not exists(src_path):
screamer 0:66f3b5499f7f 228 error_msg = "The library source folder does not exist: %s", src_path
screamer 0:66f3b5499f7f 229
screamer 0:66f3b5499f7f 230 if report != None:
screamer 0:66f3b5499f7f 231 cur_result["output"] = error_msg
screamer 0:66f3b5499f7f 232 cur_result["result"] = "FAIL"
screamer 0:66f3b5499f7f 233 add_result_to_report(report, cur_result)
screamer 0:66f3b5499f7f 234
screamer 0:66f3b5499f7f 235 raise Exception(error_msg)
screamer 0:66f3b5499f7f 236
screamer 0:66f3b5499f7f 237 try:
screamer 0:66f3b5499f7f 238 # Toolchain instance
screamer 0:66f3b5499f7f 239 toolchain = TOOLCHAIN_CLASSES[toolchain_name](target, options, macros=macros, notify=notify, silent=silent, extra_verbose=extra_verbose)
screamer 0:66f3b5499f7f 240 toolchain.VERBOSE = verbose
screamer 0:66f3b5499f7f 241 toolchain.jobs = jobs
screamer 0:66f3b5499f7f 242 toolchain.build_all = clean
screamer 0:66f3b5499f7f 243
screamer 0:66f3b5499f7f 244 toolchain.info("Building library %s (%s, %s)" % (name, target.name, toolchain_name))
screamer 0:66f3b5499f7f 245
screamer 0:66f3b5499f7f 246 # Scan Resources
screamer 0:66f3b5499f7f 247 resources = []
screamer 0:66f3b5499f7f 248 for src_path in src_paths:
screamer 0:66f3b5499f7f 249 resources.append(toolchain.scan_resources(src_path))
screamer 0:66f3b5499f7f 250
screamer 0:66f3b5499f7f 251 # Add extra include directories / files which are required by library
screamer 0:66f3b5499f7f 252 # This files usually are not in the same directory as source files so
screamer 0:66f3b5499f7f 253 # previous scan will not include them
screamer 0:66f3b5499f7f 254 if inc_dirs_ext is not None:
screamer 0:66f3b5499f7f 255 for inc_ext in inc_dirs_ext:
screamer 0:66f3b5499f7f 256 resources.append(toolchain.scan_resources(inc_ext))
screamer 0:66f3b5499f7f 257
screamer 0:66f3b5499f7f 258 # Dependencies Include Paths
screamer 0:66f3b5499f7f 259 dependencies_include_dir = []
screamer 0:66f3b5499f7f 260 if dependencies_paths is not None:
screamer 0:66f3b5499f7f 261 for path in dependencies_paths:
screamer 0:66f3b5499f7f 262 lib_resources = toolchain.scan_resources(path)
screamer 0:66f3b5499f7f 263 dependencies_include_dir.extend(lib_resources.inc_dirs)
screamer 0:66f3b5499f7f 264
screamer 0:66f3b5499f7f 265 if inc_dirs:
screamer 0:66f3b5499f7f 266 dependencies_include_dir.extend(inc_dirs)
screamer 0:66f3b5499f7f 267
screamer 0:66f3b5499f7f 268 if archive:
screamer 0:66f3b5499f7f 269 # Use temp path when building archive
screamer 0:66f3b5499f7f 270 tmp_path = join(build_path, '.temp')
screamer 0:66f3b5499f7f 271 mkdir(tmp_path)
screamer 0:66f3b5499f7f 272 else:
screamer 0:66f3b5499f7f 273 tmp_path = build_path
screamer 0:66f3b5499f7f 274
screamer 0:66f3b5499f7f 275 # Copy headers, objects and static libraries
screamer 0:66f3b5499f7f 276 for resource in resources:
screamer 0:66f3b5499f7f 277 toolchain.copy_files(resource.headers, build_path, rel_path=resource.base_path)
screamer 0:66f3b5499f7f 278 toolchain.copy_files(resource.objects, build_path, rel_path=resource.base_path)
screamer 0:66f3b5499f7f 279 toolchain.copy_files(resource.libraries, build_path, rel_path=resource.base_path)
screamer 0:66f3b5499f7f 280 if resource.linker_script:
screamer 0:66f3b5499f7f 281 toolchain.copy_files(resource.linker_script, build_path, rel_path=resource.base_path)
screamer 0:66f3b5499f7f 282
screamer 0:66f3b5499f7f 283 # Compile Sources
screamer 0:66f3b5499f7f 284 objects = []
screamer 0:66f3b5499f7f 285 for resource in resources:
screamer 0:66f3b5499f7f 286 objects.extend(toolchain.compile_sources(resource, abspath(tmp_path), dependencies_include_dir))
screamer 0:66f3b5499f7f 287
screamer 0:66f3b5499f7f 288 if archive:
screamer 0:66f3b5499f7f 289 needed_update = toolchain.build_library(objects, build_path, name)
screamer 0:66f3b5499f7f 290 else:
screamer 0:66f3b5499f7f 291 needed_update = True
screamer 0:66f3b5499f7f 292
screamer 0:66f3b5499f7f 293 if report != None and needed_update:
screamer 0:66f3b5499f7f 294 end = time()
screamer 0:66f3b5499f7f 295 cur_result["elapsed_time"] = end - start
screamer 0:66f3b5499f7f 296 cur_result["output"] = toolchain.get_output()
screamer 0:66f3b5499f7f 297 cur_result["result"] = "OK"
screamer 0:66f3b5499f7f 298
screamer 0:66f3b5499f7f 299 add_result_to_report(report, cur_result)
screamer 0:66f3b5499f7f 300
screamer 0:66f3b5499f7f 301 except Exception, e:
screamer 0:66f3b5499f7f 302 if report != None:
screamer 0:66f3b5499f7f 303 end = time()
screamer 0:66f3b5499f7f 304 cur_result["result"] = "FAIL"
screamer 0:66f3b5499f7f 305 cur_result["elapsed_time"] = end - start
screamer 0:66f3b5499f7f 306
screamer 0:66f3b5499f7f 307 toolchain_output = toolchain.get_output()
screamer 0:66f3b5499f7f 308 if toolchain_output:
screamer 0:66f3b5499f7f 309 cur_result["output"] += toolchain_output
screamer 0:66f3b5499f7f 310
screamer 0:66f3b5499f7f 311 cur_result["output"] += str(e)
screamer 0:66f3b5499f7f 312
screamer 0:66f3b5499f7f 313 add_result_to_report(report, cur_result)
screamer 0:66f3b5499f7f 314
screamer 0:66f3b5499f7f 315 # Let Exception propagate
screamer 0:66f3b5499f7f 316 raise e
screamer 0:66f3b5499f7f 317
screamer 0:66f3b5499f7f 318 def build_lib(lib_id, target, toolchain, options=None, verbose=False, clean=False, macros=None, notify=None, jobs=1, silent=False, report=None, properties=None, extra_verbose=False):
screamer 0:66f3b5499f7f 319 """ Wrapper for build_library function.
screamer 0:66f3b5499f7f 320 Function builds library in proper directory using all dependencies and macros defined by user.
screamer 0:66f3b5499f7f 321 """
screamer 0:66f3b5499f7f 322 lib = Library(lib_id)
screamer 0:66f3b5499f7f 323 if lib.is_supported(target, toolchain):
screamer 0:66f3b5499f7f 324 # We need to combine macros from parameter list with macros from library definition
screamer 0:66f3b5499f7f 325 MACROS = lib.macros if lib.macros else []
screamer 0:66f3b5499f7f 326 if macros:
screamer 0:66f3b5499f7f 327 MACROS.extend(macros)
screamer 0:66f3b5499f7f 328
screamer 0:66f3b5499f7f 329 return build_library(lib.source_dir, lib.build_dir, target, toolchain, lib.dependencies, options,
screamer 0:66f3b5499f7f 330 verbose=verbose,
screamer 0:66f3b5499f7f 331 silent=silent,
screamer 0:66f3b5499f7f 332 clean=clean,
screamer 0:66f3b5499f7f 333 macros=MACROS,
screamer 0:66f3b5499f7f 334 notify=notify,
screamer 0:66f3b5499f7f 335 inc_dirs=lib.inc_dirs,
screamer 0:66f3b5499f7f 336 inc_dirs_ext=lib.inc_dirs_ext,
screamer 0:66f3b5499f7f 337 jobs=jobs,
screamer 0:66f3b5499f7f 338 report=report,
screamer 0:66f3b5499f7f 339 properties=properties,
screamer 0:66f3b5499f7f 340 extra_verbose=extra_verbose)
screamer 0:66f3b5499f7f 341 else:
screamer 0:66f3b5499f7f 342 print 'Library "%s" is not yet supported on target %s with toolchain %s' % (lib_id, target.name, toolchain)
screamer 0:66f3b5499f7f 343 return False
screamer 0:66f3b5499f7f 344
screamer 0:66f3b5499f7f 345
screamer 0:66f3b5499f7f 346 # We do have unique legacy conventions about how we build and package the mbed library
screamer 0:66f3b5499f7f 347 def build_mbed_libs(target, toolchain_name, options=None, verbose=False, clean=False, macros=None, notify=None, jobs=1, silent=False, report=None, properties=None, extra_verbose=False):
screamer 0:66f3b5499f7f 348 """ Function returns True is library was built and false if building was skipped """
screamer 0:66f3b5499f7f 349
screamer 0:66f3b5499f7f 350 if report != None:
screamer 0:66f3b5499f7f 351 start = time()
screamer 0:66f3b5499f7f 352 id_name = "MBED"
screamer 0:66f3b5499f7f 353 description = "mbed SDK"
screamer 0:66f3b5499f7f 354 vendor_label = target.extra_labels[0]
screamer 0:66f3b5499f7f 355 cur_result = None
screamer 0:66f3b5499f7f 356 prep_report(report, target.name, toolchain_name, id_name)
screamer 0:66f3b5499f7f 357 cur_result = create_result(target.name, toolchain_name, id_name, description)
screamer 0:66f3b5499f7f 358
screamer 0:66f3b5499f7f 359 if properties != None:
screamer 0:66f3b5499f7f 360 prep_properties(properties, target.name, toolchain_name, vendor_label)
screamer 0:66f3b5499f7f 361
screamer 0:66f3b5499f7f 362 # Check toolchain support
screamer 0:66f3b5499f7f 363 if toolchain_name not in target.supported_toolchains:
screamer 0:66f3b5499f7f 364 supported_toolchains_text = ", ".join(target.supported_toolchains)
screamer 0:66f3b5499f7f 365 print '%s target is not yet supported by toolchain %s' % (target.name, toolchain_name)
screamer 0:66f3b5499f7f 366 print '%s target supports %s toolchain%s' % (target.name, supported_toolchains_text, 's' if len(target.supported_toolchains) > 1 else '')
screamer 0:66f3b5499f7f 367
screamer 0:66f3b5499f7f 368 if report != None:
screamer 0:66f3b5499f7f 369 cur_result["result"] = "SKIP"
screamer 0:66f3b5499f7f 370 add_result_to_report(report, cur_result)
screamer 0:66f3b5499f7f 371
screamer 0:66f3b5499f7f 372 return False
screamer 0:66f3b5499f7f 373
screamer 0:66f3b5499f7f 374 try:
screamer 0:66f3b5499f7f 375 # Toolchain
screamer 0:66f3b5499f7f 376 toolchain = TOOLCHAIN_CLASSES[toolchain_name](target, options, macros=macros, notify=notify, silent=silent, extra_verbose=extra_verbose)
screamer 0:66f3b5499f7f 377 toolchain.VERBOSE = verbose
screamer 0:66f3b5499f7f 378 toolchain.jobs = jobs
screamer 0:66f3b5499f7f 379 toolchain.build_all = clean
screamer 0:66f3b5499f7f 380
screamer 0:66f3b5499f7f 381 # Source and Build Paths
screamer 0:66f3b5499f7f 382 BUILD_TARGET = join(MBED_LIBRARIES, "TARGET_" + target.name)
screamer 0:66f3b5499f7f 383 BUILD_TOOLCHAIN = join(BUILD_TARGET, "TOOLCHAIN_" + toolchain.name)
screamer 0:66f3b5499f7f 384 mkdir(BUILD_TOOLCHAIN)
screamer 0:66f3b5499f7f 385
screamer 0:66f3b5499f7f 386 TMP_PATH = join(MBED_LIBRARIES, '.temp', toolchain.obj_path)
screamer 0:66f3b5499f7f 387 mkdir(TMP_PATH)
screamer 0:66f3b5499f7f 388
screamer 0:66f3b5499f7f 389 # CMSIS
screamer 0:66f3b5499f7f 390 toolchain.info("Building library %s (%s, %s)"% ('CMSIS', target.name, toolchain_name))
screamer 0:66f3b5499f7f 391 cmsis_src = join(MBED_TARGETS_PATH, "cmsis")
screamer 0:66f3b5499f7f 392 resources = toolchain.scan_resources(cmsis_src)
screamer 0:66f3b5499f7f 393
screamer 0:66f3b5499f7f 394 toolchain.copy_files(resources.headers, BUILD_TARGET)
screamer 0:66f3b5499f7f 395 toolchain.copy_files(resources.linker_script, BUILD_TOOLCHAIN)
screamer 0:66f3b5499f7f 396 toolchain.copy_files(resources.bin_files, BUILD_TOOLCHAIN)
screamer 0:66f3b5499f7f 397
screamer 0:66f3b5499f7f 398 objects = toolchain.compile_sources(resources, TMP_PATH)
screamer 0:66f3b5499f7f 399 toolchain.copy_files(objects, BUILD_TOOLCHAIN)
screamer 0:66f3b5499f7f 400
screamer 0:66f3b5499f7f 401 # mbed
screamer 0:66f3b5499f7f 402 toolchain.info("Building library %s (%s, %s)" % ('MBED', target.name, toolchain_name))
screamer 0:66f3b5499f7f 403
screamer 0:66f3b5499f7f 404 # Common Headers
screamer 0:66f3b5499f7f 405 toolchain.copy_files(toolchain.scan_resources(MBED_API).headers, MBED_LIBRARIES)
screamer 0:66f3b5499f7f 406 toolchain.copy_files(toolchain.scan_resources(MBED_HAL).headers, MBED_LIBRARIES)
screamer 0:66f3b5499f7f 407
screamer 0:66f3b5499f7f 408 # Target specific sources
screamer 0:66f3b5499f7f 409 HAL_SRC = join(MBED_TARGETS_PATH, "hal")
screamer 0:66f3b5499f7f 410 hal_implementation = toolchain.scan_resources(HAL_SRC)
screamer 0:66f3b5499f7f 411 toolchain.copy_files(hal_implementation.headers + hal_implementation.hex_files + hal_implementation.libraries, BUILD_TARGET, HAL_SRC)
screamer 0:66f3b5499f7f 412 incdirs = toolchain.scan_resources(BUILD_TARGET).inc_dirs
screamer 0:66f3b5499f7f 413 objects = toolchain.compile_sources(hal_implementation, TMP_PATH, [MBED_LIBRARIES] + incdirs)
screamer 0:66f3b5499f7f 414
screamer 0:66f3b5499f7f 415 # Common Sources
screamer 0:66f3b5499f7f 416 mbed_resources = toolchain.scan_resources(MBED_COMMON)
screamer 0:66f3b5499f7f 417 objects += toolchain.compile_sources(mbed_resources, TMP_PATH, [MBED_LIBRARIES] + incdirs)
screamer 0:66f3b5499f7f 418
screamer 0:66f3b5499f7f 419 # A number of compiled files need to be copied as objects as opposed to
screamer 0:66f3b5499f7f 420 # being part of the mbed library, for reasons that have to do with the way
screamer 0:66f3b5499f7f 421 # the linker search for symbols in archives. These are:
screamer 0:66f3b5499f7f 422 # - retarget.o: to make sure that the C standard lib symbols get overridden
screamer 0:66f3b5499f7f 423 # - board.o: mbed_die is weak
screamer 0:66f3b5499f7f 424 # - mbed_overrides.o: this contains platform overrides of various weak SDK functions
screamer 0:66f3b5499f7f 425 separate_names, separate_objects = ['retarget.o', 'board.o', 'mbed_overrides.o'], []
screamer 0:66f3b5499f7f 426
screamer 0:66f3b5499f7f 427 for o in objects:
screamer 0:66f3b5499f7f 428 for name in separate_names:
screamer 0:66f3b5499f7f 429 if o.endswith(name):
screamer 0:66f3b5499f7f 430 separate_objects.append(o)
screamer 0:66f3b5499f7f 431
screamer 0:66f3b5499f7f 432 for o in separate_objects:
screamer 0:66f3b5499f7f 433 objects.remove(o)
screamer 0:66f3b5499f7f 434
screamer 0:66f3b5499f7f 435 needed_update = toolchain.build_library(objects, BUILD_TOOLCHAIN, "mbed")
screamer 0:66f3b5499f7f 436
screamer 0:66f3b5499f7f 437 for o in separate_objects:
screamer 0:66f3b5499f7f 438 toolchain.copy_files(o, BUILD_TOOLCHAIN)
screamer 0:66f3b5499f7f 439
screamer 0:66f3b5499f7f 440 if report != None and needed_update:
screamer 0:66f3b5499f7f 441 end = time()
screamer 0:66f3b5499f7f 442 cur_result["elapsed_time"] = end - start
screamer 0:66f3b5499f7f 443 cur_result["output"] = toolchain.get_output()
screamer 0:66f3b5499f7f 444 cur_result["result"] = "OK"
screamer 0:66f3b5499f7f 445
screamer 0:66f3b5499f7f 446 add_result_to_report(report, cur_result)
screamer 0:66f3b5499f7f 447
screamer 0:66f3b5499f7f 448 return True
screamer 0:66f3b5499f7f 449
screamer 0:66f3b5499f7f 450 except Exception, e:
screamer 0:66f3b5499f7f 451 if report != None:
screamer 0:66f3b5499f7f 452 end = time()
screamer 0:66f3b5499f7f 453 cur_result["result"] = "FAIL"
screamer 0:66f3b5499f7f 454 cur_result["elapsed_time"] = end - start
screamer 0:66f3b5499f7f 455
screamer 0:66f3b5499f7f 456 toolchain_output = toolchain.get_output()
screamer 0:66f3b5499f7f 457 if toolchain_output:
screamer 0:66f3b5499f7f 458 cur_result["output"] += toolchain_output
screamer 0:66f3b5499f7f 459
screamer 0:66f3b5499f7f 460 cur_result["output"] += str(e)
screamer 0:66f3b5499f7f 461
screamer 0:66f3b5499f7f 462 add_result_to_report(report, cur_result)
screamer 0:66f3b5499f7f 463
screamer 0:66f3b5499f7f 464 # Let Exception propagate
screamer 0:66f3b5499f7f 465 raise e
screamer 0:66f3b5499f7f 466
screamer 0:66f3b5499f7f 467 def get_unique_supported_toolchains():
screamer 0:66f3b5499f7f 468 """ Get list of all unique toolchains supported by targets """
screamer 0:66f3b5499f7f 469 unique_supported_toolchains = []
screamer 0:66f3b5499f7f 470 for target in TARGET_NAMES:
screamer 0:66f3b5499f7f 471 for toolchain in TARGET_MAP[target].supported_toolchains:
screamer 0:66f3b5499f7f 472 if toolchain not in unique_supported_toolchains:
screamer 0:66f3b5499f7f 473 unique_supported_toolchains.append(toolchain)
screamer 0:66f3b5499f7f 474 return unique_supported_toolchains
screamer 0:66f3b5499f7f 475
screamer 0:66f3b5499f7f 476
screamer 0:66f3b5499f7f 477 def mcu_toolchain_matrix(verbose_html=False, platform_filter=None):
screamer 0:66f3b5499f7f 478 """ Shows target map using prettytable """
screamer 0:66f3b5499f7f 479 unique_supported_toolchains = get_unique_supported_toolchains()
screamer 0:66f3b5499f7f 480 from prettytable import PrettyTable # Only use it in this function so building works without extra modules
screamer 0:66f3b5499f7f 481
screamer 0:66f3b5499f7f 482 # All tests status table print
screamer 0:66f3b5499f7f 483 columns = ["Platform"] + unique_supported_toolchains
screamer 0:66f3b5499f7f 484 pt = PrettyTable(["Platform"] + unique_supported_toolchains)
screamer 0:66f3b5499f7f 485 # Align table
screamer 0:66f3b5499f7f 486 for col in columns:
screamer 0:66f3b5499f7f 487 pt.align[col] = "c"
screamer 0:66f3b5499f7f 488 pt.align["Platform"] = "l"
screamer 0:66f3b5499f7f 489
screamer 0:66f3b5499f7f 490 perm_counter = 0
screamer 0:66f3b5499f7f 491 target_counter = 0
screamer 0:66f3b5499f7f 492 for target in sorted(TARGET_NAMES):
screamer 0:66f3b5499f7f 493 if platform_filter is not None:
screamer 0:66f3b5499f7f 494 # FIlter out platforms using regex
screamer 0:66f3b5499f7f 495 if re.search(platform_filter, target) is None:
screamer 0:66f3b5499f7f 496 continue
screamer 0:66f3b5499f7f 497 target_counter += 1
screamer 0:66f3b5499f7f 498
screamer 0:66f3b5499f7f 499 row = [target] # First column is platform name
screamer 0:66f3b5499f7f 500 default_toolchain = TARGET_MAP[target].default_toolchain
screamer 0:66f3b5499f7f 501 for unique_toolchain in unique_supported_toolchains:
screamer 0:66f3b5499f7f 502 text = "-"
screamer 0:66f3b5499f7f 503 if default_toolchain == unique_toolchain:
screamer 0:66f3b5499f7f 504 text = "Default"
screamer 0:66f3b5499f7f 505 perm_counter += 1
screamer 0:66f3b5499f7f 506 elif unique_toolchain in TARGET_MAP[target].supported_toolchains:
screamer 0:66f3b5499f7f 507 text = "Supported"
screamer 0:66f3b5499f7f 508 perm_counter += 1
screamer 0:66f3b5499f7f 509 row.append(text)
screamer 0:66f3b5499f7f 510 pt.add_row(row)
screamer 0:66f3b5499f7f 511
screamer 0:66f3b5499f7f 512 result = pt.get_html_string() if verbose_html else pt.get_string()
screamer 0:66f3b5499f7f 513 result += "\n"
screamer 0:66f3b5499f7f 514 result += "*Default - default on-line compiler\n"
screamer 0:66f3b5499f7f 515 result += "*Supported - supported off-line compiler\n"
screamer 0:66f3b5499f7f 516 result += "\n"
screamer 0:66f3b5499f7f 517 result += "Total platforms: %d\n"% (target_counter)
screamer 0:66f3b5499f7f 518 result += "Total permutations: %d"% (perm_counter)
screamer 0:66f3b5499f7f 519 return result
screamer 0:66f3b5499f7f 520
screamer 0:66f3b5499f7f 521
screamer 0:66f3b5499f7f 522 def get_target_supported_toolchains(target):
screamer 0:66f3b5499f7f 523 """ Returns target supported toolchains list """
screamer 0:66f3b5499f7f 524 return TARGET_MAP[target].supported_toolchains if target in TARGET_MAP else None
screamer 0:66f3b5499f7f 525
screamer 0:66f3b5499f7f 526
screamer 0:66f3b5499f7f 527 def static_analysis_scan(target, toolchain_name, CPPCHECK_CMD, CPPCHECK_MSG_FORMAT, options=None, verbose=False, clean=False, macros=None, notify=None, jobs=1, extra_verbose=False):
screamer 0:66f3b5499f7f 528 # Toolchain
screamer 0:66f3b5499f7f 529 toolchain = TOOLCHAIN_CLASSES[toolchain_name](target, options, macros=macros, notify=notify, extra_verbose=extra_verbose)
screamer 0:66f3b5499f7f 530 toolchain.VERBOSE = verbose
screamer 0:66f3b5499f7f 531 toolchain.jobs = jobs
screamer 0:66f3b5499f7f 532 toolchain.build_all = clean
screamer 0:66f3b5499f7f 533
screamer 0:66f3b5499f7f 534 # Source and Build Paths
screamer 0:66f3b5499f7f 535 BUILD_TARGET = join(MBED_LIBRARIES, "TARGET_" + target.name)
screamer 0:66f3b5499f7f 536 BUILD_TOOLCHAIN = join(BUILD_TARGET, "TOOLCHAIN_" + toolchain.name)
screamer 0:66f3b5499f7f 537 mkdir(BUILD_TOOLCHAIN)
screamer 0:66f3b5499f7f 538
screamer 0:66f3b5499f7f 539 TMP_PATH = join(MBED_LIBRARIES, '.temp', toolchain.obj_path)
screamer 0:66f3b5499f7f 540 mkdir(TMP_PATH)
screamer 0:66f3b5499f7f 541
screamer 0:66f3b5499f7f 542 # CMSIS
screamer 0:66f3b5499f7f 543 toolchain.info("Static analysis for %s (%s, %s)" % ('CMSIS', target.name, toolchain_name))
screamer 0:66f3b5499f7f 544 cmsis_src = join(MBED_TARGETS_PATH, "cmsis")
screamer 0:66f3b5499f7f 545 resources = toolchain.scan_resources(cmsis_src)
screamer 0:66f3b5499f7f 546
screamer 0:66f3b5499f7f 547 # Copy files before analysis
screamer 0:66f3b5499f7f 548 toolchain.copy_files(resources.headers, BUILD_TARGET)
screamer 0:66f3b5499f7f 549 toolchain.copy_files(resources.linker_script, BUILD_TOOLCHAIN)
screamer 0:66f3b5499f7f 550
screamer 0:66f3b5499f7f 551 # Gather include paths, c, cpp sources and macros to transfer to cppcheck command line
screamer 0:66f3b5499f7f 552 includes = ["-I%s"% i for i in resources.inc_dirs]
screamer 0:66f3b5499f7f 553 includes.append("-I%s"% str(BUILD_TARGET))
screamer 0:66f3b5499f7f 554 c_sources = " ".join(resources.c_sources)
screamer 0:66f3b5499f7f 555 cpp_sources = " ".join(resources.cpp_sources)
screamer 0:66f3b5499f7f 556 macros = ["-D%s"% s for s in toolchain.get_symbols() + toolchain.macros]
screamer 0:66f3b5499f7f 557
screamer 0:66f3b5499f7f 558 includes = map(str.strip, includes)
screamer 0:66f3b5499f7f 559 macros = map(str.strip, macros)
screamer 0:66f3b5499f7f 560
screamer 0:66f3b5499f7f 561 check_cmd = CPPCHECK_CMD
screamer 0:66f3b5499f7f 562 check_cmd += CPPCHECK_MSG_FORMAT
screamer 0:66f3b5499f7f 563 check_cmd += includes
screamer 0:66f3b5499f7f 564 check_cmd += macros
screamer 0:66f3b5499f7f 565
screamer 0:66f3b5499f7f 566 # We need to pass some params via file to avoid "command line too long in some OSs"
screamer 0:66f3b5499f7f 567 tmp_file = tempfile.NamedTemporaryFile(delete=False)
screamer 0:66f3b5499f7f 568 tmp_file.writelines(line + '\n' for line in c_sources.split())
screamer 0:66f3b5499f7f 569 tmp_file.writelines(line + '\n' for line in cpp_sources.split())
screamer 0:66f3b5499f7f 570 tmp_file.close()
screamer 0:66f3b5499f7f 571 check_cmd += ["--file-list=%s"% tmp_file.name]
screamer 0:66f3b5499f7f 572
screamer 0:66f3b5499f7f 573 _stdout, _stderr, _rc = run_cmd(check_cmd)
screamer 0:66f3b5499f7f 574 if verbose:
screamer 0:66f3b5499f7f 575 print _stdout
screamer 0:66f3b5499f7f 576 print _stderr
screamer 0:66f3b5499f7f 577
screamer 0:66f3b5499f7f 578 # =========================================================================
screamer 0:66f3b5499f7f 579
screamer 0:66f3b5499f7f 580 # MBED
screamer 0:66f3b5499f7f 581 toolchain.info("Static analysis for %s (%s, %s)" % ('MBED', target.name, toolchain_name))
screamer 0:66f3b5499f7f 582
screamer 0:66f3b5499f7f 583 # Common Headers
screamer 0:66f3b5499f7f 584 toolchain.copy_files(toolchain.scan_resources(MBED_API).headers, MBED_LIBRARIES)
screamer 0:66f3b5499f7f 585 toolchain.copy_files(toolchain.scan_resources(MBED_HAL).headers, MBED_LIBRARIES)
screamer 0:66f3b5499f7f 586
screamer 0:66f3b5499f7f 587 # Target specific sources
screamer 0:66f3b5499f7f 588 HAL_SRC = join(MBED_TARGETS_PATH, "hal")
screamer 0:66f3b5499f7f 589 hal_implementation = toolchain.scan_resources(HAL_SRC)
screamer 0:66f3b5499f7f 590
screamer 0:66f3b5499f7f 591 # Copy files before analysis
screamer 0:66f3b5499f7f 592 toolchain.copy_files(hal_implementation.headers + hal_implementation.hex_files, BUILD_TARGET, HAL_SRC)
screamer 0:66f3b5499f7f 593 incdirs = toolchain.scan_resources(BUILD_TARGET)
screamer 0:66f3b5499f7f 594
screamer 0:66f3b5499f7f 595 target_includes = ["-I%s" % i for i in incdirs.inc_dirs]
screamer 0:66f3b5499f7f 596 target_includes.append("-I%s"% str(BUILD_TARGET))
screamer 0:66f3b5499f7f 597 target_includes.append("-I%s"% str(HAL_SRC))
screamer 0:66f3b5499f7f 598 target_c_sources = " ".join(incdirs.c_sources)
screamer 0:66f3b5499f7f 599 target_cpp_sources = " ".join(incdirs.cpp_sources)
screamer 0:66f3b5499f7f 600 target_macros = ["-D%s"% s for s in toolchain.get_symbols() + toolchain.macros]
screamer 0:66f3b5499f7f 601
screamer 0:66f3b5499f7f 602 # Common Sources
screamer 0:66f3b5499f7f 603 mbed_resources = toolchain.scan_resources(MBED_COMMON)
screamer 0:66f3b5499f7f 604
screamer 0:66f3b5499f7f 605 # Gather include paths, c, cpp sources and macros to transfer to cppcheck command line
screamer 0:66f3b5499f7f 606 mbed_includes = ["-I%s" % i for i in mbed_resources.inc_dirs]
screamer 0:66f3b5499f7f 607 mbed_includes.append("-I%s"% str(BUILD_TARGET))
screamer 0:66f3b5499f7f 608 mbed_includes.append("-I%s"% str(MBED_COMMON))
screamer 0:66f3b5499f7f 609 mbed_includes.append("-I%s"% str(MBED_API))
screamer 0:66f3b5499f7f 610 mbed_includes.append("-I%s"% str(MBED_HAL))
screamer 0:66f3b5499f7f 611 mbed_c_sources = " ".join(mbed_resources.c_sources)
screamer 0:66f3b5499f7f 612 mbed_cpp_sources = " ".join(mbed_resources.cpp_sources)
screamer 0:66f3b5499f7f 613
screamer 0:66f3b5499f7f 614 target_includes = map(str.strip, target_includes)
screamer 0:66f3b5499f7f 615 mbed_includes = map(str.strip, mbed_includes)
screamer 0:66f3b5499f7f 616 target_macros = map(str.strip, target_macros)
screamer 0:66f3b5499f7f 617
screamer 0:66f3b5499f7f 618 check_cmd = CPPCHECK_CMD
screamer 0:66f3b5499f7f 619 check_cmd += CPPCHECK_MSG_FORMAT
screamer 0:66f3b5499f7f 620 check_cmd += target_includes
screamer 0:66f3b5499f7f 621 check_cmd += mbed_includes
screamer 0:66f3b5499f7f 622 check_cmd += target_macros
screamer 0:66f3b5499f7f 623
screamer 0:66f3b5499f7f 624 # We need to pass some parames via file to avoid "command line too long in some OSs"
screamer 0:66f3b5499f7f 625 tmp_file = tempfile.NamedTemporaryFile(delete=False)
screamer 0:66f3b5499f7f 626 tmp_file.writelines(line + '\n' for line in target_c_sources.split())
screamer 0:66f3b5499f7f 627 tmp_file.writelines(line + '\n' for line in target_cpp_sources.split())
screamer 0:66f3b5499f7f 628 tmp_file.writelines(line + '\n' for line in mbed_c_sources.split())
screamer 0:66f3b5499f7f 629 tmp_file.writelines(line + '\n' for line in mbed_cpp_sources.split())
screamer 0:66f3b5499f7f 630 tmp_file.close()
screamer 0:66f3b5499f7f 631 check_cmd += ["--file-list=%s"% tmp_file.name]
screamer 0:66f3b5499f7f 632
screamer 0:66f3b5499f7f 633 _stdout, _stderr, _rc = run_cmd_ext(check_cmd)
screamer 0:66f3b5499f7f 634 if verbose:
screamer 0:66f3b5499f7f 635 print _stdout
screamer 0:66f3b5499f7f 636 print _stderr
screamer 0:66f3b5499f7f 637
screamer 0:66f3b5499f7f 638
screamer 0:66f3b5499f7f 639 def static_analysis_scan_lib(lib_id, target, toolchain, cppcheck_cmd, cppcheck_msg_format,
screamer 0:66f3b5499f7f 640 options=None, verbose=False, clean=False, macros=None, notify=None, jobs=1, extra_verbose=False):
screamer 0:66f3b5499f7f 641 lib = Library(lib_id)
screamer 0:66f3b5499f7f 642 if lib.is_supported(target, toolchain):
screamer 0:66f3b5499f7f 643 static_analysis_scan_library(lib.source_dir, lib.build_dir, target, toolchain, cppcheck_cmd, cppcheck_msg_format,
screamer 0:66f3b5499f7f 644 lib.dependencies, options,
screamer 0:66f3b5499f7f 645 verbose=verbose, clean=clean, macros=macros, notify=notify, jobs=jobs, extra_verbose=extra_verbose)
screamer 0:66f3b5499f7f 646 else:
screamer 0:66f3b5499f7f 647 print 'Library "%s" is not yet supported on target %s with toolchain %s'% (lib_id, target.name, toolchain)
screamer 0:66f3b5499f7f 648
screamer 0:66f3b5499f7f 649
screamer 0:66f3b5499f7f 650 def static_analysis_scan_library(src_paths, build_path, target, toolchain_name, cppcheck_cmd, cppcheck_msg_format,
screamer 0:66f3b5499f7f 651 dependencies_paths=None, options=None, name=None, clean=False,
screamer 0:66f3b5499f7f 652 notify=None, verbose=False, macros=None, jobs=1, extra_verbose=False):
screamer 0:66f3b5499f7f 653 """ Function scans library (or just some set of sources/headers) for staticly detectable defects """
screamer 0:66f3b5499f7f 654 if type(src_paths) != ListType:
screamer 0:66f3b5499f7f 655 src_paths = [src_paths]
screamer 0:66f3b5499f7f 656
screamer 0:66f3b5499f7f 657 for src_path in src_paths:
screamer 0:66f3b5499f7f 658 if not exists(src_path):
screamer 0:66f3b5499f7f 659 raise Exception("The library source folder does not exist: %s", src_path)
screamer 0:66f3b5499f7f 660
screamer 0:66f3b5499f7f 661 # Toolchain instance
screamer 0:66f3b5499f7f 662 toolchain = TOOLCHAIN_CLASSES[toolchain_name](target, options, macros=macros, notify=notify, extra_verbose=extra_verbose)
screamer 0:66f3b5499f7f 663 toolchain.VERBOSE = verbose
screamer 0:66f3b5499f7f 664 toolchain.jobs = jobs
screamer 0:66f3b5499f7f 665
screamer 0:66f3b5499f7f 666 # The first path will give the name to the library
screamer 0:66f3b5499f7f 667 name = basename(src_paths[0])
screamer 0:66f3b5499f7f 668 toolchain.info("Static analysis for library %s (%s, %s)" % (name.upper(), target.name, toolchain_name))
screamer 0:66f3b5499f7f 669
screamer 0:66f3b5499f7f 670 # Scan Resources
screamer 0:66f3b5499f7f 671 resources = []
screamer 0:66f3b5499f7f 672 for src_path in src_paths:
screamer 0:66f3b5499f7f 673 resources.append(toolchain.scan_resources(src_path))
screamer 0:66f3b5499f7f 674
screamer 0:66f3b5499f7f 675 # Dependencies Include Paths
screamer 0:66f3b5499f7f 676 dependencies_include_dir = []
screamer 0:66f3b5499f7f 677 if dependencies_paths is not None:
screamer 0:66f3b5499f7f 678 for path in dependencies_paths:
screamer 0:66f3b5499f7f 679 lib_resources = toolchain.scan_resources(path)
screamer 0:66f3b5499f7f 680 dependencies_include_dir.extend(lib_resources.inc_dirs)
screamer 0:66f3b5499f7f 681
screamer 0:66f3b5499f7f 682 # Create the desired build directory structure
screamer 0:66f3b5499f7f 683 bin_path = join(build_path, toolchain.obj_path)
screamer 0:66f3b5499f7f 684 mkdir(bin_path)
screamer 0:66f3b5499f7f 685 tmp_path = join(build_path, '.temp', toolchain.obj_path)
screamer 0:66f3b5499f7f 686 mkdir(tmp_path)
screamer 0:66f3b5499f7f 687
screamer 0:66f3b5499f7f 688 # Gather include paths, c, cpp sources and macros to transfer to cppcheck command line
screamer 0:66f3b5499f7f 689 includes = ["-I%s" % i for i in dependencies_include_dir + src_paths]
screamer 0:66f3b5499f7f 690 c_sources = " "
screamer 0:66f3b5499f7f 691 cpp_sources = " "
screamer 0:66f3b5499f7f 692 macros = ['-D%s' % s for s in toolchain.get_symbols() + toolchain.macros]
screamer 0:66f3b5499f7f 693
screamer 0:66f3b5499f7f 694 # Copy Headers
screamer 0:66f3b5499f7f 695 for resource in resources:
screamer 0:66f3b5499f7f 696 toolchain.copy_files(resource.headers, build_path, rel_path=resource.base_path)
screamer 0:66f3b5499f7f 697 includes += ["-I%s" % i for i in resource.inc_dirs]
screamer 0:66f3b5499f7f 698 c_sources += " ".join(resource.c_sources) + " "
screamer 0:66f3b5499f7f 699 cpp_sources += " ".join(resource.cpp_sources) + " "
screamer 0:66f3b5499f7f 700
screamer 0:66f3b5499f7f 701 dependencies_include_dir.extend(toolchain.scan_resources(build_path).inc_dirs)
screamer 0:66f3b5499f7f 702
screamer 0:66f3b5499f7f 703 includes = map(str.strip, includes)
screamer 0:66f3b5499f7f 704 macros = map(str.strip, macros)
screamer 0:66f3b5499f7f 705
screamer 0:66f3b5499f7f 706 check_cmd = cppcheck_cmd
screamer 0:66f3b5499f7f 707 check_cmd += cppcheck_msg_format
screamer 0:66f3b5499f7f 708 check_cmd += includes
screamer 0:66f3b5499f7f 709 check_cmd += macros
screamer 0:66f3b5499f7f 710
screamer 0:66f3b5499f7f 711 # We need to pass some parameters via file to avoid "command line too long in some OSs"
screamer 0:66f3b5499f7f 712 # Temporary file is created to store e.g. cppcheck list of files for command line
screamer 0:66f3b5499f7f 713 tmp_file = tempfile.NamedTemporaryFile(delete=False)
screamer 0:66f3b5499f7f 714 tmp_file.writelines(line + '\n' for line in c_sources.split())
screamer 0:66f3b5499f7f 715 tmp_file.writelines(line + '\n' for line in cpp_sources.split())
screamer 0:66f3b5499f7f 716 tmp_file.close()
screamer 0:66f3b5499f7f 717 check_cmd += ["--file-list=%s"% tmp_file.name]
screamer 0:66f3b5499f7f 718
screamer 0:66f3b5499f7f 719 # This will allow us to grab result from both stdio and stderr outputs (so we can show them)
screamer 0:66f3b5499f7f 720 # We assume static code analysis tool is outputting defects on STDERR
screamer 0:66f3b5499f7f 721 _stdout, _stderr, _rc = run_cmd_ext(check_cmd)
screamer 0:66f3b5499f7f 722 if verbose:
screamer 0:66f3b5499f7f 723 print _stdout
screamer 0:66f3b5499f7f 724 print _stderr
screamer 0:66f3b5499f7f 725
screamer 0:66f3b5499f7f 726
screamer 0:66f3b5499f7f 727 def print_build_results(result_list, build_name):
screamer 0:66f3b5499f7f 728 """ Generate result string for build results """
screamer 0:66f3b5499f7f 729 result = ""
screamer 0:66f3b5499f7f 730 if len(result_list) > 0:
screamer 0:66f3b5499f7f 731 result += build_name + "\n"
screamer 0:66f3b5499f7f 732 result += "\n".join([" * %s" % f for f in result_list])
screamer 0:66f3b5499f7f 733 result += "\n"
screamer 0:66f3b5499f7f 734 return result
screamer 0:66f3b5499f7f 735
screamer 0:66f3b5499f7f 736 def write_build_report(build_report, template_filename, filename):
screamer 0:66f3b5499f7f 737 build_report_failing = []
screamer 0:66f3b5499f7f 738 build_report_passing = []
screamer 0:66f3b5499f7f 739
screamer 0:66f3b5499f7f 740 for report in build_report:
screamer 0:66f3b5499f7f 741 if len(report["failing"]) > 0:
screamer 0:66f3b5499f7f 742 build_report_failing.append(report)
screamer 0:66f3b5499f7f 743 else:
screamer 0:66f3b5499f7f 744 build_report_passing.append(report)
screamer 0:66f3b5499f7f 745
screamer 0:66f3b5499f7f 746 env = Environment(extensions=['jinja2.ext.with_'])
screamer 0:66f3b5499f7f 747 env.loader = FileSystemLoader('ci_templates')
screamer 0:66f3b5499f7f 748 template = env.get_template(template_filename)
screamer 0:66f3b5499f7f 749
screamer 0:66f3b5499f7f 750 with open(filename, 'w+') as f:
screamer 0:66f3b5499f7f 751 f.write(template.render(failing_builds=build_report_failing, passing_builds=build_report_passing))