Clone of official tools
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