Brian Daniels / mbed-tools

Fork of mbed-tools by Morpheus

Committer:
screamer
Date:
Wed Mar 30 16:23:44 2016 +0000
Revision:
0:4a2e5f0422d6
Child:
2:5f044fef8f98
Initial revision

Who changed what in which revision?

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