Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Diff: build_api.py
- Revision:
- 36:96847d42f010
- Parent:
- 35:da9c89f8be7d
- Child:
- 40:7d3fa6b99b2b
--- a/build_api.py Wed Feb 15 13:53:18 2017 -0600
+++ b/build_api.py Thu Jun 22 11:12:28 2017 -0500
@@ -17,14 +17,19 @@
import re
import tempfile
+import datetime
+import uuid
from types import ListType
from shutil import rmtree
-from os.path import join, exists, dirname, basename, abspath, normpath
-from os import linesep, remove
+from os.path import join, exists, dirname, basename, abspath, normpath, splitext
+from os.path import relpath
+from os import linesep, remove, makedirs
from time import time
+from intelhex import IntelHex
+from json import load, dump
from tools.utils import mkdir, run_cmd, run_cmd_ext, NotSupportedException,\
- ToolException, InvalidReleaseTargetException
+ ToolException, InvalidReleaseTargetException, intelhex_offset
from tools.paths import MBED_CMSIS_PATH, MBED_TARGETS_PATH, MBED_LIBRARIES,\
MBED_HEADER, MBED_DRIVERS, MBED_PLATFORM, MBED_HAL, MBED_CONFIG_FILE,\
MBED_LIBRARIES_DRIVERS, MBED_LIBRARIES_PLATFORM, MBED_LIBRARIES_HAL,\
@@ -102,6 +107,8 @@
report - the report to append to
result - the result to append
"""
+ result["date"] = datetime.datetime.utcnow().isoformat()
+ result["uuid"] = str(uuid.uuid1())
target = result["target_name"]
toolchain = result["toolchain_name"]
id_name = result['id']
@@ -121,7 +128,7 @@
src_paths = [src_paths]
# Pass all params to the unified prepare_resources()
- toolchain = prepare_toolchain(src_paths, target, toolchain_name)
+ toolchain = prepare_toolchain(src_paths, None, target, toolchain_name)
# Scan src_path for config files
resources = toolchain.scan_resources(src_paths[0])
@@ -145,6 +152,8 @@
prev_features = features
toolchain.config.validate_config()
+ if toolchain.config.has_regions:
+ _ = list(toolchain.config.regions)
cfg, macros = toolchain.config.get_config_data()
features = toolchain.config.get_features()
@@ -275,8 +284,33 @@
return mbed_official_release
+def add_regions_to_profile(profile, config, toolchain_class):
+ """Add regions to the build profile, if there are any.
-def prepare_toolchain(src_paths, target, toolchain_name,
+ Positional Arguments:
+ profile - the profile to update
+ config - the configuration object that owns the region
+ toolchain_class - the class of the toolchain being used
+ """
+ if not profile:
+ return
+ regions = list(config.regions)
+ for region in regions:
+ for define in [(region.name.upper() + "_ADDR", region.start),
+ (region.name.upper() + "_SIZE", region.size)]:
+ profile["common"].append("-D%s=0x%x" % define)
+ active_region = [r for r in regions if r.active][0]
+ for define in [("MBED_APP_START", active_region.start),
+ ("MBED_APP_SIZE", active_region.size)]:
+ profile["ld"].append(toolchain_class.make_ld_define(*define))
+
+ print("Using regions in this build:")
+ for region in regions:
+ print(" Region %s size 0x%x, offset 0x%x"
+ % (region.name, region.size, region.start))
+
+
+def prepare_toolchain(src_paths, build_dir, target, toolchain_name,
macros=None, clean=False, jobs=1,
notify=None, silent=False, verbose=False,
extra_verbose=False, config=None,
@@ -285,7 +319,7 @@
Positional arguments:
src_paths - the paths to source directories
- target - ['LPC1768', 'LPC11U24', 'LPC2368', etc.]
+ target - ['LPC1768', 'LPC11U24', etc.]
toolchain_name - ['ARM', 'uARM', 'GCC_ARM', 'GCC_CR']
Keyword arguments:
@@ -298,7 +332,7 @@
extra_verbose - even more output!
config - a Config object to use instead of creating one
app_config - location of a chosen mbed_app.json file
- build_profile - a dict of flags that will be passed to the compiler
+ build_profile - a list of mergeable build profiles
"""
# We need to remove all paths which are repeated to avoid
@@ -308,15 +342,22 @@
# If the configuration object was not yet created, create it now
config = config or Config(target, src_paths, app_config=app_config)
target = config.target
-
- # Toolchain instance
try:
- toolchain = TOOLCHAIN_CLASSES[toolchain_name](
- target, notify, macros, silent,
- extra_verbose=extra_verbose, build_profile=build_profile)
+ cur_tc = TOOLCHAIN_CLASSES[toolchain_name]
except KeyError:
raise KeyError("Toolchain %s not supported" % toolchain_name)
+ profile = {'c': [], 'cxx': [], 'common': [], 'asm': [], 'ld': []}
+ for contents in build_profile or []:
+ for key in profile:
+ profile[key].extend(contents[toolchain_name][key])
+
+ if config.has_regions:
+ add_regions_to_profile(profile, config, cur_tc)
+
+ toolchain = cur_tc(target, notify, macros, silent, build_dir=build_dir,
+ extra_verbose=extra_verbose, build_profile=profile)
+
toolchain.config = config
toolchain.jobs = jobs
toolchain.build_all = clean
@@ -324,6 +365,41 @@
return toolchain
+def merge_region_list(region_list, destination, padding=b'\xFF'):
+ """Merege the region_list into a single image
+
+ Positional Arguments:
+ region_list - list of regions, which should contain filenames
+ destination - file name to write all regions to
+ padding - bytes to fill gapps with
+ """
+ merged = IntelHex()
+
+ print("Merging Regions:")
+
+ for region in region_list:
+ if region.active and not region.filename:
+ raise ToolException("Active region has no contents: No file found.")
+ if region.filename:
+ print(" Filling region %s with %s" % (region.name, region.filename))
+ part = intelhex_offset(region.filename, offset=region.start)
+ part_size = (part.maxaddr() - part.minaddr()) + 1
+ if part_size > region.size:
+ raise ToolException("Contents of region %s does not fit"
+ % region.name)
+ merged.merge(part)
+ pad_size = region.size - part_size
+ if pad_size > 0 and region != region_list[-1]:
+ print(" Padding region %s with 0x%x bytes" % (region.name, pad_size))
+ merged.puts(merged.maxaddr() + 1, padding * pad_size)
+
+ if not exists(dirname(destination)):
+ makedirs(dirname(destination))
+ print("Space used after regions merged: 0x%x" %
+ (merged.maxaddr() - merged.minaddr() + 1))
+ with open(destination, "wb+") as output:
+ merged.tofile(output, format='bin')
+
def scan_resources(src_paths, toolchain, dependencies_paths=None,
inc_dirs=None, base_path=None):
""" Scan resources using initialized toolcain
@@ -408,7 +484,6 @@
src_paths.extend(libraries_paths)
inc_dirs.extend(map(dirname, libraries_paths))
- # Build Directory
if clean and exists(build_path):
rmtree(build_path)
mkdir(build_path)
@@ -452,16 +527,15 @@
# mbed Classic/2.0/libary support #
###################################
- # Pass all params to the unified prepare_toolchain()
toolchain = prepare_toolchain(
- src_paths, target, toolchain_name, macros=macros, clean=clean,
- jobs=jobs, notify=notify, silent=silent, verbose=verbose,
+ src_paths, build_path, target, toolchain_name, macros=macros,
+ clean=clean, jobs=jobs, notify=notify, silent=silent, verbose=verbose,
extra_verbose=extra_verbose, config=config, app_config=app_config,
build_profile=build_profile)
# The first path will give the name to the library
- if name is None:
- name = basename(normpath(abspath(src_paths[0])))
+ name = (name or toolchain.config.name or
+ basename(normpath(abspath(src_paths[0]))))
toolchain.info("Building project %s (%s, %s)" %
(name, toolchain.target.name, toolchain_name))
@@ -482,18 +556,36 @@
try:
# Call unified scan_resources
resources = scan_resources(src_paths, toolchain, inc_dirs=inc_dirs)
+ if (hasattr(toolchain.target, "release_versions") and
+ "5" not in toolchain.target.release_versions and
+ "rtos" in toolchain.config.lib_config_data):
+ if "Cortex-A" in toolchain.target.core:
+ raise NotSupportedException(
+ ("%s Will be supported in mbed OS 5.6. "
+ "To use the %s, please checkout the mbed OS 5.4 release branch. "
+ "See https://developer.mbed.org/platforms/Renesas-GR-PEACH/#important-notice "
+ "for more information") % (toolchain.target.name, toolchain.target.name))
+ else:
+ raise NotSupportedException("Target does not support mbed OS 5")
# Change linker script if specified
if linker_script is not None:
resources.linker_script = linker_script
# Compile Sources
- objects = toolchain.compile_sources(resources, build_path,
- resources.inc_dirs)
+ objects = toolchain.compile_sources(resources, resources.inc_dirs)
resources.objects.extend(objects)
# Link Program
- res, _ = toolchain.link_program(resources, build_path, name)
+ if toolchain.config.has_regions:
+ res, _ = toolchain.link_program(resources, build_path, name + "_application")
+ region_list = list(toolchain.config.regions)
+ region_list = [r._replace(filename=res) if r.active else r
+ for r in region_list]
+ res = join(build_path, name) + ".bin"
+ merge_region_list(region_list, res)
+ else:
+ res, _ = toolchain.link_program(resources, build_path, name)
memap_instance = getattr(toolchain, 'memap_instance', None)
memap_table = ''
@@ -520,6 +612,9 @@
cur_result["output"] = toolchain.get_output() + memap_table
cur_result["result"] = "OK"
cur_result["memory_usage"] = toolchain.map_outputs
+ cur_result["bin"] = res
+ cur_result["elf"] = splitext(res)[0] + ".elf"
+ cur_result.update(toolchain.report)
add_result_to_report(report, cur_result)
@@ -600,9 +695,9 @@
# Pass all params to the unified prepare_toolchain()
toolchain = prepare_toolchain(
- src_paths, target, toolchain_name, macros=macros, clean=clean,
- jobs=jobs, notify=notify, silent=silent, verbose=verbose,
- extra_verbose=extra_verbose, app_config=app_config,
+ src_paths, build_path, target, toolchain_name, macros=macros,
+ clean=clean, jobs=jobs, notify=notify, silent=silent,
+ verbose=verbose, extra_verbose=extra_verbose, app_config=app_config,
build_profile=build_profile)
# The first path will give the name to the library
@@ -621,6 +716,7 @@
prep_report(report, toolchain.target.name, toolchain_name, id_name)
cur_result = create_result(toolchain.target.name, toolchain_name,
id_name, description)
+ cur_result['type'] = 'library'
if properties != None:
prep_properties(properties, toolchain.target.name, toolchain_name,
vendor_label)
@@ -658,8 +754,7 @@
resources=resources)
# Compile Sources
- objects = toolchain.compile_sources(resources, abspath(tmp_path),
- resources.inc_dirs)
+ objects = toolchain.compile_sources(resources, resources.inc_dirs)
resources.objects.extend(objects)
if archive:
@@ -704,6 +799,10 @@
### Legacy methods ###
######################
+def mbed2_obj_path(target_name, toolchain_name):
+ real_tc_name = TOOLCHAIN_CLASSES[toolchain_name].__name__
+ return join("TARGET_" + target_name, "TOOLCHAIN_" + real_tc_name)
+
def build_lib(lib_id, target, toolchain_name, verbose=False,
clean=False, macros=None, notify=None, jobs=1, silent=False,
report=None, properties=None, extra_verbose=False,
@@ -780,19 +879,23 @@
try:
# Toolchain instance
- toolchain = TOOLCHAIN_CLASSES[toolchain_name](
- target, macros=macros, notify=notify, silent=silent,
- extra_verbose=extra_verbose, build_profile=build_profile)
- toolchain.VERBOSE = verbose
- toolchain.jobs = jobs
- toolchain.build_all = clean
+ # Create the desired build directory structure
+ bin_path = join(build_path, mbed2_obj_path(target.name, toolchain_name))
+ mkdir(bin_path)
+ tmp_path = join(build_path, '.temp', mbed2_obj_path(target.name,
+ toolchain_name))
+ mkdir(tmp_path)
+
+ toolchain = prepare_toolchain(
+ src_paths, tmp_path, target, toolchain_name, macros=macros,
+ notify=notify, silent=silent, extra_verbose=extra_verbose,
+ build_profile=build_profile, jobs=jobs, clean=clean)
toolchain.info("Building library %s (%s, %s)" %
(name.upper(), target.name, toolchain_name))
# Take into account the library configuration (MBED_CONFIG_FILE)
- config = Config(target)
- toolchain.config = config
+ config = toolchain.config
config.add_config_files([MBED_CONFIG_FILE])
# Scan Resources
@@ -823,11 +926,6 @@
config.load_resources(res)
toolchain.set_config_data(toolchain.config.get_config_data())
- # Create the desired build directory structure
- bin_path = join(build_path, toolchain.obj_path)
- mkdir(bin_path)
- tmp_path = join(build_path, '.temp', toolchain.obj_path)
- mkdir(tmp_path)
# Copy Headers
for resource in resources:
@@ -840,8 +938,7 @@
# Compile Sources
objects = []
for resource in resources:
- objects.extend(toolchain.compile_sources(resource, tmp_path,
- dependencies_include_dir))
+ objects.extend(toolchain.compile_sources(resource, dependencies_include_dir))
needed_update = toolchain.build_library(objects, bin_path, name)
@@ -925,28 +1022,25 @@
return False
try:
+ # Source and Build Paths
+ build_target = join(MBED_LIBRARIES, "TARGET_" + target.name)
+ build_toolchain = join(MBED_LIBRARIES, mbed2_obj_path(target.name, toolchain_name))
+ mkdir(build_toolchain)
+
# Toolchain
- toolchain = TOOLCHAIN_CLASSES[toolchain_name](
- target, macros=macros, notify=notify, silent=silent,
- extra_verbose=extra_verbose, build_profile=build_profile)
- toolchain.VERBOSE = verbose
- toolchain.jobs = jobs
- toolchain.build_all = clean
+ tmp_path = join(MBED_LIBRARIES, '.temp', mbed2_obj_path(target.name, toolchain_name))
+ mkdir(tmp_path)
+
+ toolchain = prepare_toolchain(
+ [""], tmp_path, target, toolchain_name, macros=macros,
+ notify=notify, silent=silent, extra_verbose=extra_verbose,
+ build_profile=build_profile, jobs=jobs, clean=clean)
# Take into account the library configuration (MBED_CONFIG_FILE)
- config = Config(target)
- toolchain.config = config
+ config = toolchain.config
config.add_config_files([MBED_CONFIG_FILE])
toolchain.set_config_data(toolchain.config.get_config_data())
- # Source and Build Paths
- build_target = join(MBED_LIBRARIES, "TARGET_" + target.name)
- build_toolchain = join(build_target, "TOOLCHAIN_" + toolchain.name)
- mkdir(build_toolchain)
-
- tmp_path = join(MBED_LIBRARIES, '.temp', toolchain.obj_path)
- mkdir(tmp_path)
-
# CMSIS
toolchain.info("Building library %s (%s, %s)" %
('CMSIS', target.name, toolchain_name))
@@ -986,7 +1080,7 @@
toolchain.copy_files(hal_implementation.linker_script, build_toolchain)
toolchain.copy_files(hal_implementation.bin_files, build_toolchain)
incdirs = toolchain.scan_resources(build_target).inc_dirs
- objects = toolchain.compile_sources(hal_implementation, tmp_path,
+ objects = toolchain.compile_sources(hal_implementation,
library_incdirs + incdirs)
toolchain.copy_files(objects, build_toolchain)
@@ -995,18 +1089,19 @@
for dir in [MBED_DRIVERS, MBED_PLATFORM, MBED_HAL]:
mbed_resources += toolchain.scan_resources(dir)
- objects = toolchain.compile_sources(mbed_resources, tmp_path,
+ objects = toolchain.compile_sources(mbed_resources,
library_incdirs + incdirs)
# A number of compiled files need to be copied as objects as opposed to
# way the linker search for symbols in archives. These are:
- # - retarget.o: to make sure that the C standard lib symbols get
+ # - mbed_retarget.o: to make sure that the C standard lib symbols get
# overridden
- # - board.o: mbed_die is weak
+ # - mbed_board.o: mbed_die is weak
# - mbed_overrides.o: this contains platform overrides of various
# weak SDK functions
- separate_names, separate_objects = ['retarget.o', 'board.o',
- 'mbed_overrides.o'], []
+ # - mbed_main.o: this contains main redirection
+ separate_names, separate_objects = ['mbed_retarget.o', 'mbed_board.o',
+ 'mbed_overrides.o', 'mbed_main.o', 'mbed_sdk_boot.o'], []
for obj in objects:
for name in separate_names:
@@ -1072,6 +1167,75 @@
return unique_supported_toolchains
+def mcu_toolchain_list(release_version='5'):
+ """ Shows list of toolchains
+
+ """
+
+ if isinstance(release_version, basestring):
+ # Force release_version to lowercase if it is a string
+ release_version = release_version.lower()
+ else:
+ # Otherwise default to printing all known targets and toolchains
+ release_version = 'all'
+
+
+ version_release_targets = {}
+ version_release_target_names = {}
+
+ for version in RELEASE_VERSIONS:
+ version_release_targets[version] = get_mbed_official_release(version)
+ version_release_target_names[version] = [x[0] for x in
+ version_release_targets[
+ version]]
+
+ if release_version in RELEASE_VERSIONS:
+ release_targets = version_release_targets[release_version]
+ else:
+ release_targets = None
+
+ unique_supported_toolchains = get_unique_supported_toolchains(
+ release_targets)
+ columns = ["mbed OS %s" % x for x in RELEASE_VERSIONS] + unique_supported_toolchains
+ return "\n".join(columns)
+
+
+def mcu_target_list(release_version='5'):
+ """ Shows target list
+
+ """
+
+ if isinstance(release_version, basestring):
+ # Force release_version to lowercase if it is a string
+ release_version = release_version.lower()
+ else:
+ # Otherwise default to printing all known targets and toolchains
+ release_version = 'all'
+
+
+ version_release_targets = {}
+ version_release_target_names = {}
+
+ for version in RELEASE_VERSIONS:
+ version_release_targets[version] = get_mbed_official_release(version)
+ version_release_target_names[version] = [x[0] for x in
+ version_release_targets[
+ version]]
+
+ if release_version in RELEASE_VERSIONS:
+ release_targets = version_release_targets[release_version]
+ else:
+ release_targets = None
+
+ target_names = []
+
+ if release_targets:
+ target_names = [x[0] for x in release_targets]
+ else:
+ target_names = TARGET_NAMES
+
+ return "\n".join(target_names)
+
def mcu_toolchain_matrix(verbose_html=False, platform_filter=None,
release_version='5'):
@@ -1174,283 +1338,6 @@
else None
-def static_analysis_scan(target, toolchain_name, cppcheck_cmd,
- cppcheck_msg_format, verbose=False,
- clean=False, macros=None, notify=None, jobs=1,
- extra_verbose=False, build_profile=None):
- """Perform static analysis on a target and toolchain combination
-
- Positional arguments:
- target - the target to fake the build for
- toolchain_name - pretend you would compile with this toolchain
- cppcheck_cmd - the command used to do static analysis
- cppcheck_msg_format - the format of the check messages
-
- Keyword arguments:
- verbose - more printing!
- clean - start from a clean slate
- macros - extra macros to compile with
- notify - the notification event handling function
- jobs - number of commands to run at once
- extra_verbose - even moar printing
- build_profile - a dict of flags that will be passed to the compiler
- """
- # Toolchain
- toolchain = TOOLCHAIN_CLASSES[toolchain_name](target, macros=macros,
- notify=notify,
- extra_verbose=extra_verbose,
- build_profile=build_profile)
- toolchain.VERBOSE = verbose
- toolchain.jobs = jobs
- toolchain.build_all = clean
-
- # Source and Build Paths
- build_target = join(MBED_LIBRARIES, "TARGET_" + target.name)
- build_toolchain = join(build_target, "TOOLCHAIN_" + toolchain.name)
- mkdir(build_toolchain)
-
- tmp_path = join(MBED_LIBRARIES, '.temp', toolchain.obj_path)
- mkdir(tmp_path)
-
- # CMSIS
- toolchain.info("Static analysis for %s (%s, %s)" %
- ('CMSIS', target.name, toolchain_name))
- cmsis_src = MBED_CMSIS_PATH
- resources = toolchain.scan_resources(cmsis_src)
-
- # Copy files before analysis
- toolchain.copy_files(resources.headers, build_target)
- toolchain.copy_files(resources.linker_script, build_toolchain)
-
- # Gather include paths, c, cpp sources and macros to transfer to cppcheck
- # command line
- includes = ["-I%s"% i for i in resources.inc_dirs]
- includes.append("-I%s"% str(build_target))
- c_sources = " ".join(resources.c_sources)
- cpp_sources = " ".join(resources.cpp_sources)
- macros = ["-D%s"% s for s in toolchain.get_symbols() + toolchain.macros]
-
- includes = [inc.strip() for inc in includes]
- macros = [mac.strip() for mac in macros]
-
- check_cmd = cppcheck_cmd
- check_cmd += cppcheck_msg_format
- check_cmd += includes
- check_cmd += macros
-
- # We need to pass some params via file to avoid "command line too long in
- # some OSs"
- tmp_file = tempfile.NamedTemporaryFile(delete=False)
- tmp_file.writelines(line + '\n' for line in c_sources.split())
- tmp_file.writelines(line + '\n' for line in cpp_sources.split())
- tmp_file.close()
- check_cmd += ["--file-list=%s"% tmp_file.name]
-
- _stdout, _stderr, _ = run_cmd(check_cmd)
- if verbose:
- print _stdout
- print _stderr
-
- # =========================================================================
-
- # MBED
- toolchain.info("Static analysis for %s (%s, %s)" %
- ('MBED', target.name, toolchain_name))
-
- # Common Headers
- toolchain.copy_files([MBED_HEADER], MBED_LIBRARIES)
- toolchain.copy_files(toolchain.scan_resources(MBED_DRIVERS).headers,
- MBED_LIBRARIES)
- toolchain.copy_files(toolchain.scan_resources(MBED_PLATFORM).headers,
- MBED_LIBRARIES)
- toolchain.copy_files(toolchain.scan_resources(MBED_HAL).headers,
- MBED_LIBRARIES)
-
- # Target specific sources
- hal_src = join(MBED_TARGETS_PATH, "hal")
- hal_implementation = toolchain.scan_resources(hal_src)
-
- # Copy files before analysis
- toolchain.copy_files(hal_implementation.headers +
- hal_implementation.hex_files, build_target,
- resources=hal_implementation)
- incdirs = toolchain.scan_resources(build_target)
-
- target_includes = ["-I%s" % i for i in incdirs.inc_dirs]
- target_includes.append("-I%s"% str(build_target))
- target_includes.append("-I%s"% str(hal_src))
- target_c_sources = " ".join(incdirs.c_sources)
- target_cpp_sources = " ".join(incdirs.cpp_sources)
- target_macros = ["-D%s"% s for s in
- toolchain.get_symbols() + toolchain.macros]
-
- # Common Sources
- mbed_resources = toolchain.scan_resources(MBED_COMMON)
-
- # Gather include paths, c, cpp sources and macros to transfer to cppcheck
- # command line
- mbed_includes = ["-I%s" % i for i in mbed_resources.inc_dirs]
- mbed_includes.append("-I%s"% str(build_target))
- mbed_includes.append("-I%s"% str(MBED_DRIVERS))
- mbed_includes.append("-I%s"% str(MBED_PLATFORM))
- mbed_includes.append("-I%s"% str(MBED_HAL))
- mbed_c_sources = " ".join(mbed_resources.c_sources)
- mbed_cpp_sources = " ".join(mbed_resources.cpp_sources)
-
- target_includes = [inc.strip() for inc in target_includes]
- mbed_includes = [inc.strip() for inc in mbed_includes]
- target_macros = [mac.strip() for mac in target_macros]
-
- check_cmd = cppcheck_cmd
- check_cmd += cppcheck_msg_format
- check_cmd += target_includes
- check_cmd += mbed_includes
- check_cmd += target_macros
-
- # We need to pass some parames via file to avoid "command line too long in
- # some OSs"
- tmp_file = tempfile.NamedTemporaryFile(delete=False)
- tmp_file.writelines(line + '\n' for line in target_c_sources.split())
- tmp_file.writelines(line + '\n' for line in target_cpp_sources.split())
- tmp_file.writelines(line + '\n' for line in mbed_c_sources.split())
- tmp_file.writelines(line + '\n' for line in mbed_cpp_sources.split())
- tmp_file.close()
- check_cmd += ["--file-list=%s"% tmp_file.name]
-
- _stdout, _stderr, _ = run_cmd_ext(check_cmd)
- if verbose:
- print _stdout
- print _stderr
-
-
-def static_analysis_scan_lib(lib_id, target, toolchain, cppcheck_cmd,
- cppcheck_msg_format, verbose=False,
- clean=False, macros=None, notify=None, jobs=1,
- extra_verbose=False, build_profile=None):
- """Perform static analysis on a library as if it were to be compiled for a
- particular target and toolchain combination
- """
- lib = Library(lib_id)
- if lib.is_supported(target, toolchain):
- static_analysis_scan_library(
- lib.source_dir, lib.build_dir, target, toolchain, cppcheck_cmd,
- cppcheck_msg_format, lib.dependencies, verbose=verbose,
- clean=clean, macros=macros, notify=notify, jobs=jobs,
- extra_verbose=extra_verbose, build_profile=build_profile)
- else:
- print('Library "%s" is not yet supported on target %s with toolchain %s'
- % (lib_id, target.name, toolchain))
-
-
-def static_analysis_scan_library(src_paths, build_path, target, toolchain_name,
- cppcheck_cmd, cppcheck_msg_format,
- dependencies_paths=None,
- name=None, clean=False, notify=None,
- verbose=False, macros=None, jobs=1,
- extra_verbose=False, build_profile=None):
- """ Function scans library for statically detectable defects
-
- Positional arguments:
- src_paths - the list of library paths to scan
- build_path - the location directory of result files
- target - the target to fake the build for
- toolchain_name - pretend you would compile with this toolchain
- cppcheck_cmd - the command used to do static analysis
- cppcheck_msg_format - the format of the check messages
-
- Keyword arguments:
- dependencies_paths - the paths to sources that this library depends on
- name - the name of this library
- clean - start from a clean slate
- notify - the notification event handling function
- verbose - more printing!
- macros - extra macros to compile with
- jobs - number of commands to run at once
- extra_verbose - even moar printing
- build_profile - a dict of flags that will be passed to the compiler
- """
- if type(src_paths) != ListType:
- src_paths = [src_paths]
-
- for src_path in src_paths:
- if not exists(src_path):
- raise Exception("The library source folder does not exist: %s",
- src_path)
-
- # Toolchain instance
- toolchain = TOOLCHAIN_CLASSES[toolchain_name](target, macros=macros,
- notify=notify,
- extra_verbose=extra_verbose,
- build_profile=build_profile)
- toolchain.VERBOSE = verbose
- toolchain.jobs = jobs
-
- # The first path will give the name to the library
- name = basename(src_paths[0])
- toolchain.info("Static analysis for library %s (%s, %s)" %
- (name.upper(), target.name, toolchain_name))
-
- # Scan Resources
- resources = []
- for src_path in src_paths:
- resources.append(toolchain.scan_resources(src_path))
-
- # Dependencies Include Paths
- dependencies_include_dir = []
- if dependencies_paths is not None:
- for path in dependencies_paths:
- lib_resources = toolchain.scan_resources(path)
- dependencies_include_dir.extend(lib_resources.inc_dirs)
-
- # Create the desired build directory structure
- bin_path = join(build_path, toolchain.obj_path)
- mkdir(bin_path)
- tmp_path = join(build_path, '.temp', toolchain.obj_path)
- mkdir(tmp_path)
-
- # Gather include paths, c, cpp sources and macros to transfer to cppcheck
- # command line
- includes = ["-I%s" % i for i in dependencies_include_dir + src_paths]
- c_sources = " "
- cpp_sources = " "
- macros = ['-D%s' % s for s in toolchain.get_symbols() + toolchain.macros]
-
- # Copy Headers
- for resource in resources:
- toolchain.copy_files(resource.headers, build_path, resources=resource)
- includes += ["-I%s" % i for i in resource.inc_dirs]
- c_sources += " ".join(resource.c_sources) + " "
- cpp_sources += " ".join(resource.cpp_sources) + " "
-
- dependencies_include_dir.extend(
- toolchain.scan_resources(build_path).inc_dirs)
-
- includes = [inc.strip() for inc in includes]
- macros = [mac.strip() for mac in macros]
-
- check_cmd = cppcheck_cmd
- check_cmd += cppcheck_msg_format
- check_cmd += includes
- check_cmd += macros
-
- # We need to pass some parameters via file to avoid "command line too long
- # in some OSs". A temporary file is created to store e.g. cppcheck list of
- # files for command line
- tmp_file = tempfile.NamedTemporaryFile(delete=False)
- tmp_file.writelines(line + '\n' for line in c_sources.split())
- tmp_file.writelines(line + '\n' for line in cpp_sources.split())
- tmp_file.close()
- check_cmd += ["--file-list=%s"% tmp_file.name]
-
- # This will allow us to grab result from both stdio and stderr outputs (so
- # we can show them) We assume static code analysis tool is outputting
- # defects on STDERR
- _stdout, _stderr, _ = run_cmd_ext(check_cmd)
- if verbose:
- print _stdout
- print _stderr
-
-
def print_build_results(result_list, build_name):
""" Generate result string for build results
@@ -1540,3 +1427,24 @@
placeholder.write(template.render(
failing_builds=build_report_failing,
passing_builds=build_report_passing))
+
+
+def merge_build_data(filename, toolchain_report, app_type):
+ path_to_file = dirname(abspath(filename))
+ try:
+ build_data = load(open(filename))
+ except (IOError, ValueError):
+ build_data = {'builds': []}
+ for tgt in toolchain_report.values():
+ for tc in tgt.values():
+ for project in tc.values():
+ for build in project:
+ try:
+ build[0]['elf'] = relpath(build[0]['elf'], path_to_file)
+ build[0]['bin'] = relpath(build[0]['bin'], path_to_file)
+ except KeyError:
+ pass
+ if 'type' not in build[0]:
+ build[0]['type'] = app_type
+ build_data['builds'].append(build[0])
+ dump(build_data, open(filename, "wb"), indent=4, separators=(',', ': '))
