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:
- 31:8ea194f6145b
- Parent:
- 30:f12ce67666d0
- Child:
- 35:da9c89f8be7d
--- a/build_api.py Mon Aug 29 11:56:59 2016 +0100
+++ b/build_api.py Wed Jan 04 11:58:24 2017 -0600
@@ -1,6 +1,6 @@
"""
mbed SDK
-Copyright (c) 2011-2013 ARM Limited
+Copyright (c) 2011-2016 ARM Limited
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -17,25 +17,26 @@
import re
import tempfile
-
from types import ListType
from shutil import rmtree
-from os.path import join, exists, basename, abspath, normpath, dirname
-from os import linesep
+from os.path import join, exists, dirname, basename, abspath, normpath
+from os import linesep, remove
from time import time
from tools.utils import mkdir, run_cmd, run_cmd_ext, NotSupportedException,\
ToolException, InvalidReleaseTargetException
-from tools.paths import MBED_TARGETS_PATH, MBED_LIBRARIES, MBED_API, MBED_HAL,\
- MBED_COMMON, MBED_CONFIG_FILE
+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,\
+ BUILD_DIR
from tools.targets import TARGET_NAMES, TARGET_MAP
from tools.libraries import Library
from tools.toolchains import TOOLCHAIN_CLASSES, mbedToolchain
-from tools.targets import set_targets_json_location
-from tools.build_profiles import find_build_profile, get_toolchain_profile, find_targets_json
from jinja2 import FileSystemLoader
from jinja2.environment import Environment
from tools.config import Config
+from tools.build_profiles import find_build_profile, get_toolchain_profile, find_targets_json
+from tools.targets import set_targets_json_location
RELEASE_VERSIONS = ['2', '5']
@@ -135,7 +136,7 @@
toolchain.config.add_config_files(resources.json_files)
# Add features while we find new ones
- features = toolchain.config.get_features()
+ features = set(toolchain.config.get_features())
if features == prev_features:
break
@@ -201,12 +202,12 @@
("following toolchains: %s" %
", ".join(supported_toolchains_sorted))
- elif not target.default_build == 'standard':
+ elif not target.default_lib == 'std':
result = False
reason = ("Target '%s' must set the " % target.name) + \
- ("'default_build' to 'standard' to be included in the ") + \
+ ("'default_lib' to 'std' to be included in the ") + \
("mbed OS 5.0 official release." + linesep) + \
- ("Currently it is set to '%s'" % target.default_build)
+ ("Currently it is set to '%s'" % target.default_lib)
else:
result = False
@@ -277,9 +278,10 @@
def prepare_toolchain(src_paths, target, toolchain_name,
- macros=None, options=None, clean=False, jobs=1,
+ macros=None, clean=False, jobs=1,
notify=None, silent=False, verbose=False,
- extra_verbose=False, config=None):
+ extra_verbose=False, config=None,
+ app_config=None, build_profile=None):
""" Prepares resource related objects - toolchain, target, config
Positional arguments:
@@ -289,7 +291,6 @@
Keyword arguments:
macros - additional macros
- options - general compiler options like debug-symbols or small-build
clean - Rebuild everything if True
jobs - how many compilers we can run at once
notify - Notify function for logs
@@ -297,6 +298,8 @@
verbose - Write the actual tools command lines used if True
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
"""
# We need to remove all paths which are repeated to avoid
@@ -304,20 +307,14 @@
src_paths = [src_paths[0]] + list(set(src_paths[1:]))
# If the configuration object was not yet created, create it now
- config = config or Config(target, src_paths)
-
- # If the 'target' argument is a string, convert it to a target instance
- if isinstance(target, basestring):
- try:
- target = TARGET_MAP[target]
- except KeyError:
- raise KeyError("Target '%s' not found" % target)
+ config = config or Config(target, src_paths, app_config=app_config)
+ target = config.target
# Toolchain instance
try:
toolchain = TOOLCHAIN_CLASSES[toolchain_name](
- target, options, notify, macros, silent,
- extra_verbose=extra_verbose)
+ target, notify, macros, silent,
+ extra_verbose=extra_verbose, build_profile=build_profile)
except KeyError:
raise KeyError("Toolchain %s not supported" % toolchain_name)
@@ -329,7 +326,7 @@
return toolchain
def scan_resources(src_paths, toolchain, dependencies_paths=None,
- inc_dirs=None):
+ inc_dirs=None, base_path=None):
""" Scan resources using initialized toolcain
Positional arguments
@@ -341,9 +338,9 @@
"""
# Scan src_path
- resources = toolchain.scan_resources(src_paths[0])
+ resources = toolchain.scan_resources(src_paths[0], base_path=base_path)
for path in src_paths[1:]:
- resources.add(toolchain.scan_resources(path))
+ resources.add(toolchain.scan_resources(path, base_path=base_path))
# Scan dependency paths for include dirs
if dependencies_paths is not None:
@@ -368,11 +365,12 @@
return resources
def build_project(src_paths, build_path, target, toolchain_name,
- libraries_paths=None, options=None, linker_script=None,
+ libraries_paths=None, linker_script=None,
clean=False, notify=None, verbose=False, name=None,
macros=None, inc_dirs=None, jobs=1, silent=False,
report=None, properties=None, project_id=None,
- project_description=None, extra_verbose=False, config=None):
+ project_description=None, extra_verbose=False, config=None,
+ app_config=None, build_profile=None):
""" Build a project. A project may be a test or a user program.
Positional arguments:
@@ -384,7 +382,6 @@
Keyword arguments:
libraries_paths - The location of libraries to include when linking
- options - general compiler options like debug-symbols or small-build
linker_script - the file that drives the linker to do it's job
clean - Rebuild everything if True
notify - Notify function for logs
@@ -400,6 +397,8 @@
project_description - the human-readable version of what this thing does
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
"""
# Convert src_path to a list if needed
@@ -408,16 +407,15 @@
# Extend src_paths wiht libraries_paths
if libraries_paths is not None:
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)
-
###################################
# mbed Classic/2.0/libary support #
- ###################################
# Find build system profile
profile = None
@@ -452,11 +450,15 @@
mbedToolchain.init = init_hook
+ # mbed Classic/2.0/libary support #
+ ###################################
+
# Pass all params to the unified prepare_toolchain()
toolchain = prepare_toolchain(
- src_paths, target, toolchain_name, macros=macros, options=options,
- clean=clean, jobs=jobs, notify=notify, silent=silent, verbose=verbose,
- extra_verbose=extra_verbose, config=config)
+ src_paths, 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:
@@ -494,10 +496,29 @@
# Link Program
res, _ = toolchain.link_program(resources, build_path, name)
+ memap_instance = getattr(toolchain, 'memap_instance', None)
+ memap_table = ''
+ if memap_instance:
+ # Write output to stdout in text (pretty table) format
+ memap_table = memap_instance.generate_output('table')
+
+ if not silent:
+ print memap_table
+
+ # Write output to file in JSON format
+ map_out = join(build_path, name + "_map.json")
+ memap_instance.generate_output('json', map_out)
+
+ # Write output to file in CSV format for the CI
+ map_csv = join(build_path, name + "_map.csv")
+ memap_instance.generate_output('csv-ci', map_csv)
+
+ resources.detect_duplicates(toolchain)
+
if report != None:
end = time()
cur_result["elapsed_time"] = end - start
- cur_result["output"] = toolchain.get_output()
+ cur_result["output"] = toolchain.get_output() + memap_table
cur_result["result"] = "OK"
cur_result["memory_usage"] = toolchain.map_outputs
@@ -526,10 +547,12 @@
raise
def build_library(src_paths, build_path, target, toolchain_name,
- dependencies_paths=None, options=None, name=None, clean=False,
+ dependencies_paths=None, name=None, clean=False,
archive=True, notify=None, verbose=False, macros=None,
inc_dirs=None, jobs=1, silent=False, report=None,
- properties=None, extra_verbose=False, project_id=None):
+ properties=None, extra_verbose=False, project_id=None,
+ remove_config_header_file=False, app_config=None,
+ build_profile=None):
""" Build a library
Positional arguments:
@@ -541,7 +564,6 @@
Keyword arguments:
dependencies_paths - The location of libraries to include when linking
- options - general compiler options like debug-symbols or small-build
name - the name of the library
clean - Rebuild everything if True
archive - whether the library will create an archive file
@@ -555,6 +577,9 @@
properties - UUUUHHHHH beats me
extra_verbose - even more output!
project_id - the name that goes in the report
+ remove_config_header_file - delete config header file when done building
+ app_config - location of a chosen mbed_app.json file
+ build_profile - a dict of flags that will be passed to the compiler
"""
# Convert src_path to a list if needed
@@ -576,9 +601,10 @@
# Pass all params to the unified prepare_toolchain()
toolchain = prepare_toolchain(
- src_paths, target, toolchain_name, macros=macros, options=options,
- clean=clean, jobs=jobs, notify=notify, silent=silent, verbose=verbose,
- extra_verbose=extra_verbose)
+ 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,
+ build_profile=build_profile)
# The first path will give the name to the library
if name is None:
@@ -622,6 +648,8 @@
toolchain.copy_files(resources.objects, build_path, resources=resources)
toolchain.copy_files(resources.libraries, build_path,
resources=resources)
+ toolchain.copy_files(resources.json_files, build_path,
+ resources=resources)
if resources.linker_script:
toolchain.copy_files(resources.linker_script, build_path,
resources=resources)
@@ -638,6 +666,11 @@
if archive:
toolchain.build_library(objects, build_path, name)
+ if remove_config_header_file:
+ config_header_path = toolchain.get_config_header()
+ if config_header_path:
+ remove(config_header_path)
+
if report != None:
end = time()
cur_result["elapsed_time"] = end - start
@@ -672,9 +705,10 @@
### Legacy methods ###
######################
-def build_lib(lib_id, target, toolchain_name, options=None, verbose=False,
+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):
+ report=None, properties=None, extra_verbose=False,
+ build_profile=None):
""" Legacy method for building mbed libraries
Positional arguments:
@@ -683,7 +717,6 @@
toolchain_name - the name of the build tools
Keyword arguments:
- options - general compiler options like debug-symbols or small-build
clean - Rebuild everything if True
verbose - Write the actual tools command lines used if True
macros - additional macros
@@ -693,6 +726,7 @@
report - a dict where a result may be appended
properties - UUUUHHHHH beats me
extra_verbose - even more output!
+ build_profile - a dict of flags that will be passed to the compiler
"""
lib = Library(lib_id)
if not lib.is_supported(target, toolchain_name):
@@ -748,8 +782,8 @@
try:
# Toolchain instance
toolchain = TOOLCHAIN_CLASSES[toolchain_name](
- target, options, macros=macros, notify=notify, silent=silent,
- extra_verbose=extra_verbose)
+ 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
@@ -780,6 +814,7 @@
for path in dependencies_paths:
lib_resources = toolchain.scan_resources(path)
dependencies_include_dir.extend(lib_resources.inc_dirs)
+ dependencies_include_dir.extend(map(dirname, lib_resources.inc_dirs))
if inc_dirs:
dependencies_include_dir.extend(inc_dirs)
@@ -837,9 +872,10 @@
# We do have unique legacy conventions about how we build and package the mbed
# library
-def build_mbed_libs(target, toolchain_name, options=None, verbose=False,
+def build_mbed_libs(target, toolchain_name, verbose=False,
clean=False, macros=None, notify=None, jobs=1, silent=False,
- report=None, properties=None, extra_verbose=False):
+ report=None, properties=None, extra_verbose=False,
+ build_profile=None):
""" Function returns True is library was built and false if building was
skipped
@@ -848,7 +884,6 @@
toolchain_name - the name of the build tools
Keyword arguments:
- options - general compiler options like debug-symbols or small-build
verbose - Write the actual tools command lines used if True
clean - Rebuild everything if True
macros - additional macros
@@ -858,6 +893,7 @@
report - a dict where a result may be appended
properties - UUUUHHHHH beats me
extra_verbose - even more output!
+ build_profile - a dict of flags that will be passed to the compiler
"""
if report != None:
@@ -892,8 +928,8 @@
try:
# Toolchain
toolchain = TOOLCHAIN_CLASSES[toolchain_name](
- target, options, macros=macros, notify=notify, silent=silent,
- extra_verbose=extra_verbose)
+ 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
@@ -915,7 +951,7 @@
# CMSIS
toolchain.info("Building library %s (%s, %s)" %
('CMSIS', target.name, toolchain_name))
- cmsis_src = join(MBED_TARGETS_PATH, "cmsis")
+ cmsis_src = MBED_CMSIS_PATH
resources = toolchain.scan_resources(cmsis_src)
toolchain.copy_files(resources.headers, build_target)
@@ -930,29 +966,40 @@
('MBED', target.name, toolchain_name))
# Common Headers
- toolchain.copy_files(toolchain.scan_resources(MBED_API).headers,
- MBED_LIBRARIES)
- toolchain.copy_files(toolchain.scan_resources(MBED_HAL).headers,
- MBED_LIBRARIES)
+ toolchain.copy_files([MBED_HEADER], MBED_LIBRARIES)
+ library_incdirs = [dirname(MBED_LIBRARIES), MBED_LIBRARIES]
+
+ for dir, dest in [(MBED_DRIVERS, MBED_LIBRARIES_DRIVERS),
+ (MBED_PLATFORM, MBED_LIBRARIES_PLATFORM),
+ (MBED_HAL, MBED_LIBRARIES_HAL)]:
+ resources = toolchain.scan_resources(dir)
+ toolchain.copy_files(resources.headers, dest)
+ library_incdirs.append(dest)
# Target specific sources
- hal_src = join(MBED_TARGETS_PATH, "hal")
+ hal_src = MBED_TARGETS_PATH
hal_implementation = toolchain.scan_resources(hal_src)
toolchain.copy_files(hal_implementation.headers +
hal_implementation.hex_files +
- hal_implementation.libraries,
+ hal_implementation.libraries +
+ [MBED_CONFIG_FILE],
build_target, resources=hal_implementation)
+ 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,
- [MBED_LIBRARIES] + incdirs)
+ library_incdirs + incdirs)
+ toolchain.copy_files(objects, build_toolchain)
# Common Sources
- mbed_resources = toolchain.scan_resources(MBED_COMMON)
- objects += toolchain.compile_sources(mbed_resources, tmp_path,
- [MBED_LIBRARIES] + incdirs)
+ mbed_resources = None
+ for dir in [MBED_DRIVERS, MBED_PLATFORM, MBED_HAL]:
+ mbed_resources += toolchain.scan_resources(dir)
+
+ objects = toolchain.compile_sources(mbed_resources, tmp_path,
+ library_incdirs + incdirs)
# A number of compiled files need to be copied as objects as opposed to
- # being part of the mbed library, for reasons that have to do with the
# way the linker search for symbols in archives. These are:
# - retarget.o: to make sure that the C standard lib symbols get
# overridden
@@ -1129,9 +1176,9 @@
def static_analysis_scan(target, toolchain_name, cppcheck_cmd,
- cppcheck_msg_format, options=None, verbose=False,
+ cppcheck_msg_format, verbose=False,
clean=False, macros=None, notify=None, jobs=1,
- extra_verbose=False):
+ extra_verbose=False, build_profile=None):
"""Perform static analysis on a target and toolchain combination
Positional arguments:
@@ -1141,18 +1188,19 @@
cppcheck_msg_format - the format of the check messages
Keyword arguments:
- options - things like debug-symbols, or small-build, etc.
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, options,
- macros=macros, notify=notify,
- extra_verbose=extra_verbose)
+ 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
@@ -1168,7 +1216,7 @@
# CMSIS
toolchain.info("Static analysis for %s (%s, %s)" %
('CMSIS', target.name, toolchain_name))
- cmsis_src = join(MBED_TARGETS_PATH, "cmsis")
+ cmsis_src = MBED_CMSIS_PATH
resources = toolchain.scan_resources(cmsis_src)
# Copy files before analysis
@@ -1211,7 +1259,10 @@
('MBED', target.name, toolchain_name))
# Common Headers
- toolchain.copy_files(toolchain.scan_resources(MBED_API).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)
@@ -1241,8 +1292,8 @@
# 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_COMMON))
- mbed_includes.append("-I%s"% str(MBED_API))
+ 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)
@@ -1274,9 +1325,9 @@
def static_analysis_scan_lib(lib_id, target, toolchain, cppcheck_cmd,
- cppcheck_msg_format, options=None, verbose=False,
+ cppcheck_msg_format, verbose=False,
clean=False, macros=None, notify=None, jobs=1,
- extra_verbose=False):
+ 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
"""
@@ -1284,9 +1335,9 @@
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, options, verbose=verbose,
+ cppcheck_msg_format, lib.dependencies, verbose=verbose,
clean=clean, macros=macros, notify=notify, jobs=jobs,
- extra_verbose=extra_verbose)
+ 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))
@@ -1294,10 +1345,10 @@
def static_analysis_scan_library(src_paths, build_path, target, toolchain_name,
cppcheck_cmd, cppcheck_msg_format,
- dependencies_paths=None, options=None,
+ dependencies_paths=None,
name=None, clean=False, notify=None,
verbose=False, macros=None, jobs=1,
- extra_verbose=False):
+ extra_verbose=False, build_profile=None):
""" Function scans library for statically detectable defects
Positional arguments:
@@ -1310,7 +1361,6 @@
Keyword arguments:
dependencies_paths - the paths to sources that this library depends on
- options - things like debug-symbols, or small-build, etc.
name - the name of this library
clean - start from a clean slate
notify - the notification event handling function
@@ -1318,6 +1368,7 @@
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]
@@ -1328,9 +1379,10 @@
src_path)
# Toolchain instance
- toolchain = TOOLCHAIN_CLASSES[toolchain_name](target, options,
- macros=macros, notify=notify,
- extra_verbose=extra_verbose)
+ toolchain = TOOLCHAIN_CLASSES[toolchain_name](target, macros=macros,
+ notify=notify,
+ extra_verbose=extra_verbose,
+ build_profile=build_profile)
toolchain.VERBOSE = verbose
toolchain.jobs = jobs
