diff --git a/.travis.yml b/.travis.yml index eb45b7c6383..d4174f2d105 100644 --- a/.travis.yml +++ b/.travis.yml @@ -19,3 +19,4 @@ install: - sudo pip install jinja2 - sudo pip install pytest - sudo pip install pylint + - sudo pip install hypothesis diff --git a/docs/Toolchain_Profiles.md b/docs/Toolchain_Profiles.md new file mode 100644 index 00000000000..c310b8c19f2 --- /dev/null +++ b/docs/Toolchain_Profiles.md @@ -0,0 +1,72 @@ +# Toolchain Profiles User Perspective + +A Toolchain or build system Profile is a set of flags that is garenteed to be passed to the underlieing compiler suite. +These flags are stored in a JSON file that may be merged with other JSON files of the same structure. + +## JSON Toolchain Profile Format + +The JSON object that represents a Toolchain Profile is a dict mapping from Toolchains, like `GCC_ARM`, to their flags, like `-O3`. +The structure is as follows: Each toolchain supported by a Toolchain Profile has an dict in the root dict. +This dict contains a mapping from a flag type to a list of flags that should be passed the corresponding part of the compiler suite. +The required flag types are: + +| Key | Description | +|:---------|:--------------------------------------| +| `c` | Flags for the C Compiler | +| `cxx` | Flags for the C++ Compiler | +| `common` | Flags for both the C and C++ Compilers| +| `asm` | Flags for the Assembler | + +## Example + +An example of a Toolchain Profile is given below: +```json +{ + "GCC_ARM": { + "common": ["-c", "-Wall", "-Wextra", + "-Wno-unused-parameter", "-Wno-missing-field-initializers", + "-fmessage-length=0", "-fno-exceptions", "-fno-builtin", + "-ffunction-sections", "-fdata-sections", "-funsigned-char", + "-MMD", "-fno-delete-null-pointer-checks", + "-fomit-frame-pointer", "-Os"], + "asm": ["-x", "assembler-with-cpp"], + "c": ["-std=gnu99"], + "cxx": ["-std=gnu++98", "-fno-rtti", "-Wvla"], + "ld": ["-Wl,--gc-sections", "-Wl,--wrap,main", "-Wl,--wrap,_malloc_r", + "-Wl,--wrap,_free_r", "-Wl,--wrap,_realloc_r", + "-Wl,--wrap,_calloc_r", "-Wl,--wrap,exit", "-Wl,--wrap,atexit"] + }, + "ARM": { + "common": ["-c", "--gnu", "-Otime", "--split_sections", + "--apcs=interwork", "--brief_diagnostics", "--restrict", + "--multibyte_chars", "-O3"], + "asm": [], + "c": ["--md", "--no_depend_system_headers", "--c99", "-D__ASSERT_MSG"], + "cxx": ["--cpp", "--no_rtti", "--no_vla"], + "ld": [] + }, + "IAR": { + "common": [ + "--no_wrap_diagnostics", "non-native end of line sequence", "-e", + "--diag_suppress=Pa050,Pa084,Pa093,Pa082", "-Oh"], + "asm": [], + "c": ["--vla"], + "cxx": ["--guard_calls", "--no_static_destruction"], + "ld": ["--skip_dynamic_initialization", "--threaded_lib"] + } +} +``` + +From this Toolchain profile, we can tell that: + - `GCC_ARM`, `ARM`, and `IAR` compiler suites are supported. + - The `ARM` C and C++ Compilers will be using optimization level `-O3` + - The `IAR` linker will skip dynamic initialization + - etc. + +# Toolchain Profile API Perspective + +The Toolchains no longer take in an optional argument, `build_profile`, that will contain a map from flag types to lists of flags. +This looks exactly the same in python as it does in the JSON format above. +The meaning of the flags, and which ones are required is the same as the User Perspective +A developer using the API must parse the User provided files themselves and extract the appropriate sub-dict from the file afterwards. +A convienence function that does this for a developer is `tools.options.extract_profile` and will call args_error when a Toolchain Profile JSON file does not provide flags for the selected Toolchain. diff --git a/tools/build.py b/tools/build.py index 7915ed03a41..2749776a08f 100644 --- a/tools/build.py +++ b/tools/build.py @@ -31,6 +31,7 @@ from tools.toolchains import mbedToolchain from tools.targets import TARGET_NAMES, TARGET_MAP from tools.options import get_default_options_parser +from tools.options import extract_profile from tools.build_api import build_library, build_mbed_libs, build_lib from tools.build_api import mcu_toolchain_matrix from tools.build_api import static_analysis_scan, static_analysis_scan_lib, static_analysis_scan_library @@ -222,13 +223,20 @@ try: mcu = TARGET_MAP[target] # CMSIS and MBED libs analysis - static_analysis_scan(mcu, toolchain, CPPCHECK_CMD, CPPCHECK_MSG_FORMAT, verbose=options.verbose, jobs=options.jobs) + profile = extract_profile(parser, options, toolchain) + static_analysis_scan( + mcu, toolchain, CPPCHECK_CMD, CPPCHECK_MSG_FORMAT, + verbose=options.verbose, jobs=options.jobs, + build_profile=profile) for lib_id in libraries: # Static check for library - static_analysis_scan_lib(lib_id, mcu, toolchain, CPPCHECK_CMD, CPPCHECK_MSG_FORMAT, - options=options.options, - extra_verbose=options.extra_verbose_notify, verbose=options.verbose, jobs=options.jobs, clean=options.clean, - macros=options.macros) + static_analysis_scan_lib( + lib_id, mcu, toolchain, CPPCHECK_CMD, + CPPCHECK_MSG_FORMAT, + extra_verbose=options.extra_verbose_notify, + verbose=options.verbose, jobs=options.jobs, + clean=options.clean, macros=options.macros, + build_profile=profile) pass except Exception, e: if options.verbose: @@ -248,9 +256,9 @@ else: try: mcu = TARGET_MAP[target] + profile = extract_profile(parser, options, toolchain) if options.source_dir: lib_build_res = build_library(options.source_dir, options.build_dir, mcu, toolchain, - options=options.options, extra_verbose=options.extra_verbose_notify, verbose=options.verbose, silent=options.silent, @@ -258,26 +266,27 @@ clean=options.clean, archive=(not options.no_archive), macros=options.macros, - name=options.artifact_name) + name=options.artifact_name, + build_profile=profile) else: lib_build_res = build_mbed_libs(mcu, toolchain, - options=options.options, extra_verbose=options.extra_verbose_notify, verbose=options.verbose, silent=options.silent, jobs=options.jobs, clean=options.clean, - macros=options.macros) + macros=options.macros, + build_profile=profile) for lib_id in libraries: build_lib(lib_id, mcu, toolchain, - options=options.options, extra_verbose=options.extra_verbose_notify, verbose=options.verbose, silent=options.silent, clean=options.clean, macros=options.macros, - jobs=options.jobs) + jobs=options.jobs, + build_profile=profile) if lib_build_res: successes.append(tt_id) else: diff --git a/tools/build_api.py b/tools/build_api.py index 4718e8da090..36755f6a4c8 100644 --- a/tools/build_api.py +++ b/tools/build_api.py @@ -274,10 +274,10 @@ def get_mbed_official_release(version): 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, - app_config=None): + app_config=None, build_profile=None): """ Prepares resource related objects - toolchain, target, config Positional arguments: @@ -287,7 +287,6 @@ def prepare_toolchain(src_paths, target, toolchain_name, 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 @@ -296,6 +295,7 @@ def prepare_toolchain(src_paths, target, toolchain_name, 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 @@ -309,8 +309,8 @@ def prepare_toolchain(src_paths, target, toolchain_name, # 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) @@ -361,12 +361,12 @@ def scan_resources(src_paths, toolchain, dependencies_paths=None, 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, - app_config=None): + app_config=None, build_profile=None): """ Build a project. A project may be a test or a user program. Positional arguments: @@ -378,7 +378,6 @@ def build_project(src_paths, build_path, target, toolchain_name, 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 @@ -395,6 +394,7 @@ def build_project(src_paths, build_path, target, toolchain_name, 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 @@ -411,9 +411,10 @@ def build_project(src_paths, build_path, target, toolchain_name, # 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, app_config=app_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: @@ -483,11 +484,12 @@ def build_project(src_paths, build_path, target, toolchain_name, 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, - remove_config_header_file=False, app_config=None): + remove_config_header_file=False, app_config=None, + build_profile=None): """ Build a library Positional arguments: @@ -499,7 +501,6 @@ def build_library(src_paths, build_path, target, toolchain_name, 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 @@ -515,6 +516,7 @@ def build_library(src_paths, build_path, target, toolchain_name, 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 @@ -536,9 +538,10 @@ def build_library(src_paths, build_path, target, toolchain_name, # 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, app_config=app_config) + 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: @@ -639,9 +642,10 @@ def build_library(src_paths, build_path, target, toolchain_name, ### 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: @@ -650,7 +654,6 @@ def build_lib(lib_id, target, toolchain_name, options=None, verbose=False, 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 @@ -660,6 +663,7 @@ def build_lib(lib_id, target, toolchain_name, options=None, verbose=False, 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): @@ -715,8 +719,8 @@ def build_lib(lib_id, target, toolchain_name, options=None, verbose=False, 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 @@ -804,9 +808,10 @@ def build_lib(lib_id, target, toolchain_name, options=None, verbose=False, # 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 @@ -815,7 +820,6 @@ def build_mbed_libs(target, toolchain_name, options=None, verbose=False, 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 @@ -825,6 +829,7 @@ def build_mbed_libs(target, toolchain_name, options=None, verbose=False, 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: @@ -859,8 +864,8 @@ def build_mbed_libs(target, toolchain_name, options=None, verbose=False, 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 @@ -1096,9 +1101,9 @@ def get_target_supported_toolchains(target): 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: @@ -1108,18 +1113,19 @@ def static_analysis_scan(target, toolchain_name, cppcheck_cmd, 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 @@ -1241,9 +1247,9 @@ def static_analysis_scan(target, toolchain_name, cppcheck_cmd, 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 """ @@ -1251,9 +1257,9 @@ def static_analysis_scan_lib(lib_id, target, toolchain, cppcheck_cmd, 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)) @@ -1261,10 +1267,10 @@ def static_analysis_scan_lib(lib_id, target, toolchain, cppcheck_cmd, 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: @@ -1277,7 +1283,6 @@ def static_analysis_scan_library(src_paths, build_path, target, toolchain_name, 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 @@ -1285,6 +1290,7 @@ def static_analysis_scan_library(src_paths, build_path, target, toolchain_name, 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] @@ -1295,9 +1301,10 @@ def static_analysis_scan_library(src_paths, build_path, target, toolchain_name, 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 diff --git a/tools/make.py b/tools/make.py index 4434931f8e4..ea4da69b92b 100644 --- a/tools/make.py +++ b/tools/make.py @@ -19,6 +19,7 @@ TEST BUILD & RUN """ import sys +import json from time import sleep from shutil import copy from os.path import join, abspath, dirname @@ -41,6 +42,7 @@ from tools.tests import test_known, test_name_known from tools.targets import TARGET_MAP from tools.options import get_default_options_parser +from tools.options import extract_profile from tools.build_api import build_project from tools.build_api import mcu_toolchain_matrix from utils import argparse_filestring_type @@ -220,6 +222,7 @@ if options.source_dir and not options.build_dir: args_error(parser, "argument --build is required when argument --source is provided") + if options.color: # This import happens late to prevent initializing colorization when we don't need it import colorize @@ -271,7 +274,8 @@ build_dir = options.build_dir try: - bin_file = build_project(test.source_dir, build_dir, mcu, toolchain, test.dependencies, options.options, + bin_file = build_project(test.source_dir, build_dir, mcu, toolchain, + test.dependencies, linker_script=options.linker_script, clean=options.clean, verbose=options.verbose, @@ -280,7 +284,10 @@ macros=options.macros, jobs=options.jobs, name=options.artifact_name, - app_config=options.app_config) + app_config=options.app_config, + build_profile=extract_profile(parser, + options, + toolchain)) print 'Image: %s'% bin_file if options.disk: diff --git a/tools/options.py b/tools/options.py index 45f3cfb0160..0c3b016d95e 100644 --- a/tools/options.py +++ b/tools/options.py @@ -14,12 +14,14 @@ See the License for the specific language governing permissions and limitations under the License. """ +from json import load +from os.path import join, dirname from argparse import ArgumentParser from tools.toolchains import TOOLCHAINS from tools.targets import TARGET_NAMES from tools.utils import argparse_force_uppercase_type, \ argparse_lowercase_hyphen_type, argparse_many, \ - argparse_filestring_type + argparse_filestring_type, args_error def get_default_options_parser(add_clean=True, add_options=True, add_app_config=False): @@ -70,21 +72,35 @@ def get_default_options_parser(add_clean=True, add_options=True, help="clean the build directory") if add_options: - parser.add_argument("-o", "--options", action="append", - help=('Add a build argument ("save-asm": save the ' - 'asm generated by the compiler, "debug-info":' - ' generate debugging information, "analyze": ' - 'run Goanna static code analyzer")'), - type=argparse_lowercase_hyphen_type(['save-asm', - 'debug-info', - 'analyze', - 'small-lib', - 'std-lib'], - "build option")) - + parser.add_argument("--profile", dest="profile", action="append", + type=argparse_filestring_type, + default=[]) if add_app_config: parser.add_argument("--app-config", default=None, dest="app_config", type=argparse_filestring_type, help="Path of an app configuration file (Default is to look for 'mbed_app.json')") return parser + + +def extract_profile(parser, options, toolchain): + """Extract a Toolchain profile from parsed options + + Positional arguments: + parser - parser used to parse the command line arguments + options - The parsed command line arguments + toolchain - the toolchain that the profile should be extracted for + """ + profile = {'c': [], 'cxx': [], 'ld': [], 'common': [], 'asm': []} + filenames = options.profile or [join(dirname(__file__), "profiles", + "default.json")] + for filename in filenames: + contents = load(open(filename)) + try: + for key in profile.iterkeys(): + profile[key] += contents[toolchain][key] + except KeyError: + args_error(parser, ("argument --profile: toolchain {} is not" + " supported by profile {}").format(toolchain, + filename)) + return profile diff --git a/tools/profiles/all-warnings.json b/tools/profiles/all-warnings.json new file mode 100644 index 00000000000..a7e8cb71edc --- /dev/null +++ b/tools/profiles/all-warnings.json @@ -0,0 +1,9 @@ +{ + "GCC_ARM": { + "common": ["-pedantic"], + "asm": [], + "c": [], + "cxx": [], + "ld": [] + } +} diff --git a/tools/profiles/debug.json b/tools/profiles/debug.json new file mode 100644 index 00000000000..5aced11431a --- /dev/null +++ b/tools/profiles/debug.json @@ -0,0 +1,34 @@ +{ + "GCC_ARM": { + "common": ["-c", "-Wall", "-Wextra", + "-Wno-unused-parameter", "-Wno-missing-field-initializers", + "-fmessage-length=0", "-fno-exceptions", "-fno-builtin", + "-ffunction-sections", "-fdata-sections", "-funsigned-char", + "-MMD", "-fno-delete-null-pointer-checks", + "-fomit-frame-pointer", "-O0", "-g"], + "asm": ["-x", "assembler-with-cpp"], + "c": ["-std=gnu99"], + "cxx": ["-std=gnu++98", "-fno-rtti", "-Wvla"], + "ld": ["-Wl,--gc-sections", "-Wl,--wrap,main", "-Wl,--wrap,_malloc_r", + "-Wl,--wrap,_free_r", "-Wl,--wrap,_realloc_r", + "-Wl,--wrap,_calloc_r", "-Wl,--wrap,exit", "-Wl,--wrap,atexit"] + }, + "ARM": { + "common": ["-c", "--gnu", "-Otime", "--split_sections", + "--apcs=interwork", "--brief_diagnostics", "--restrict", + "--multibyte_chars", "-O0", "-g"], + "asm": [], + "c": ["--md", "--no_depend_system_headers", "--c99", "-D__ASSERT_MSG"], + "cxx": ["--cpp", "--no_rtti", "--no_vla"], + "ld": [] + }, + "IAR": { + "common": [ + "--no_wrap_diagnostics", "non-native end of line sequence", "-e", + "--diag_suppress=Pa050,Pa084,Pa093,Pa082", "-On", "-r"], + "asm": [], + "c": ["--vla"], + "cxx": ["--guard_calls", "--no_static_destruction"], + "ld": ["--skip_dynamic_initialization", "--threaded_lib"] + } +} diff --git a/tools/profiles/default.json b/tools/profiles/default.json new file mode 100644 index 00000000000..49c7c95286b --- /dev/null +++ b/tools/profiles/default.json @@ -0,0 +1,34 @@ +{ + "GCC_ARM": { + "common": ["-c", "-Wall", "-Wextra", + "-Wno-unused-parameter", "-Wno-missing-field-initializers", + "-fmessage-length=0", "-fno-exceptions", "-fno-builtin", + "-ffunction-sections", "-fdata-sections", "-funsigned-char", + "-MMD", "-fno-delete-null-pointer-checks", + "-fomit-frame-pointer", "-Os"], + "asm": ["-x", "assembler-with-cpp"], + "c": ["-std=gnu99"], + "cxx": ["-std=gnu++98", "-fno-rtti", "-Wvla"], + "ld": ["-Wl,--gc-sections", "-Wl,--wrap,main", "-Wl,--wrap,_malloc_r", + "-Wl,--wrap,_free_r", "-Wl,--wrap,_realloc_r", + "-Wl,--wrap,_calloc_r", "-Wl,--wrap,exit", "-Wl,--wrap,atexit"] + }, + "ARM": { + "common": ["-c", "--gnu", "-Otime", "--split_sections", + "--apcs=interwork", "--brief_diagnostics", "--restrict", + "--multibyte_chars", "-O3"], + "asm": [], + "c": ["--md", "--no_depend_system_headers", "--c99", "-D__ASSERT_MSG"], + "cxx": ["--cpp", "--no_rtti", "--no_vla"], + "ld": [] + }, + "IAR": { + "common": [ + "--no_wrap_diagnostics", "-e", + "--diag_suppress=Pa050,Pa084,Pa093,Pa082", "-Oh"], + "asm": [], + "c": ["--vla"], + "cxx": ["--guard_calls", "--no_static_destruction"], + "ld": ["--skip_dynamic_initialization", "--threaded_lib"] + } +} diff --git a/tools/profiles/nanolib.json b/tools/profiles/nanolib.json new file mode 100644 index 00000000000..545120d0ac4 --- /dev/null +++ b/tools/profiles/nanolib.json @@ -0,0 +1,9 @@ +{ + "GCC_ARM": { + "common": [ "-DMBED_RTOS_SINGLE_THREAD"], + "asm": [], + "c": [], + "cxx": [], + "ld": [ "--specs=nano.specs"] + } +} diff --git a/tools/profiles/save-asm.json b/tools/profiles/save-asm.json new file mode 100644 index 00000000000..fe4c0c8efd2 --- /dev/null +++ b/tools/profiles/save-asm.json @@ -0,0 +1,16 @@ +{ + "GCC_ARM": { + "common": ["-save-temps"], + "asm": [], + "c": [], + "cxx": [], + "ld": [] + }, + "ARM": { + "common": ["--asm", "--interleave"], + "asm": [], + "c": [], + "cxx": [], + "ld": [] + } +} diff --git a/tools/project.py b/tools/project.py index 399faa7413d..1b7cd885b82 100644 --- a/tools/project.py +++ b/tools/project.py @@ -19,6 +19,7 @@ from tools.utils import argparse_force_lowercase_type from tools.utils import argparse_force_uppercase_type from tools.project_api import export_project +from tools.options import extract_profile def setup_project(ide, target, program=None, source_dir=None, build=None, export_path=None): @@ -63,7 +64,8 @@ def setup_project(ide, target, program=None, source_dir=None, build=None, export def export(target, ide, build=None, src=None, macros=None, project_id=None, - clean=False, zip_proj=False, options=None, export_path=None, silent=False): + clean=False, zip_proj=False, build_profile=None, export_path=None, + silent=False): """Do an export of a project. Positional arguments: @@ -87,7 +89,7 @@ def export(target, ide, build=None, src=None, macros=None, project_id=None, return export_project(src, project_dir, target, ide, clean=clean, name=name, macros=macros, libraries_paths=lib, zip_proj=zip_name, - options=options, silent=silent) + build_profile=build_profile, silent=silent) def main(): @@ -167,11 +169,10 @@ def main(): dest="macros", help="Add a macro definition") - parser.add_argument("-o", - type=argparse_many(str), - dest="opts", - default=["debug-info"], - help="Toolchain options") + parser.add_argument("--profile", + type=argparse_filestring_type, + default=[], + help="Toolchain profile") options = parser.parse_args() @@ -220,10 +221,12 @@ def main(): if (options.program is None) and (not options.source_dir): args_error(parser, "one of -p, -n, or --source is required") # Export to selected toolchain + _, toolchain_name = get_exporter_toolchain(options.ide) + profile = extract_profile(parser, options, toolchain_name) export(options.mcu, options.ide, build=options.build, src=options.source_dir, macros=options.macros, project_id=options.program, clean=options.clean, - zip_proj=zip_proj, options=options.opts) + zip_proj=zip_proj, build_profile=profile) if __name__ == "__main__": diff --git a/tools/project_api.py b/tools/project_api.py index 0a64df0fc5b..dc5871f217f 100644 --- a/tools/project_api.py +++ b/tools/project_api.py @@ -135,10 +135,11 @@ def zip_export(file_name, prefix, resources, project_files, inc_repos): def export_project(src_paths, export_path, target, ide, - libraries_paths=None, options=None, linker_script=None, - clean=False, notify=None, verbose=False, name=None, - inc_dirs=None, jobs=1, silent=False, extra_verbose=False, - config=None, macros=None, zip_proj=None, inc_repos=False): + libraries_paths=None, linker_script=None, clean=False, + notify=None, verbose=False, name=None, inc_dirs=None, + jobs=1, silent=False, extra_verbose=False, config=None, + macros=None, zip_proj=None, inc_repos=False, + build_profile=None): """Generates a project file and creates a zip archive if specified Positional Arguments: @@ -149,7 +150,6 @@ def export_project(src_paths, export_path, target, ide, Keyword Arguments: libraries_paths - paths to additional libraries - options - build options passed by -o flag linker_script - path to the linker script for the specified target clean - removes the export_path if it exists notify - function is passed all events, and expected to handle notification @@ -192,10 +192,10 @@ def export_project(src_paths, export_path, target, ide, # Pass all params to the unified prepare_resources() toolchain = prepare_toolchain(paths, target, toolchain_name, - macros=macros, options=options, clean=clean, - jobs=jobs, notify=notify, silent=silent, - verbose=verbose, extra_verbose=extra_verbose, - config=config) + macros=macros, clean=clean, jobs=jobs, + notify=notify, silent=silent, verbose=verbose, + extra_verbose=extra_verbose, config=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]))) diff --git a/tools/test.py b/tools/test.py index 851cb055380..9e520d59b29 100644 --- a/tools/test.py +++ b/tools/test.py @@ -27,7 +27,7 @@ sys.path.insert(0, ROOT) from tools.test_api import test_path_to_name, find_tests, print_tests, build_tests, test_spec_from_test_builds -from tools.options import get_default_options_parser +from tools.options import get_default_options_parser, extract_profile from tools.build_api import build_project, build_library from tools.build_api import print_build_memory_usage from tools.targets import TARGET_MAP @@ -132,7 +132,7 @@ # Find all tests in the relevant paths for path in all_paths: - all_tests.update(find_tests(path, mcu, toolchain, options.options, + all_tests.update(find_tests(path, mcu, toolchain, app_config=options.app_config)) # Filter tests by name if specified @@ -180,10 +180,10 @@ build_properties = {} library_build_success = False + profile = extract_profile(parser, options, toolchain) try: # Build sources build_library(base_source_paths, options.build_dir, mcu, toolchain, - options=options.options, jobs=options.jobs, clean=options.clean, report=build_report, @@ -193,7 +193,8 @@ verbose=options.verbose, notify=notify, archive=False, - app_config=options.app_config) + app_config=options.app_config, + build_profile=profile) library_build_success = True except ToolException, e: @@ -212,7 +213,6 @@ # Build all the tests test_build_success, test_build = build_tests(tests, [options.build_dir], options.build_dir, mcu, toolchain, - options=options.options, clean=options.clean, report=build_report, properties=build_properties, @@ -221,7 +221,8 @@ notify=notify, jobs=options.jobs, continue_on_build_fail=options.continue_on_build_fail, - app_config=options.app_config) + app_config=options.app_config, + build_profile=profile) # If a path to a test spec is provided, write it to a file if options.test_spec: diff --git a/tools/test/toolchains/api.py b/tools/test/toolchains/api.py index 1452f58c01b..ae9a5ea071d 100644 --- a/tools/test/toolchains/api.py +++ b/tools/test/toolchains/api.py @@ -1,13 +1,98 @@ +"""Tests for the toolchain sub-system""" import sys import os +from string import printable +from copy import deepcopy +from hypothesis import given +from hypothesis.strategies import text, lists, fixed_dictionaries -ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", "..")) +ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", + "..")) sys.path.insert(0, ROOT) from tools.toolchains import TOOLCHAIN_CLASSES, LEGACY_TOOLCHAIN_NAMES from tools.targets import TARGET_MAP def test_instantiation(): - for name, Class in TOOLCHAIN_CLASSES.items(): - CLS = Class(TARGET_MAP["K64F"]) - assert name == CLS.name or name == LEGACY_TOOLCHAIN_NAMES[CLS.name] + """Test that all exported toolchain may be instantiated""" + for name, tc_class in TOOLCHAIN_CLASSES.items(): + cls = tc_class(TARGET_MAP["K64F"]) + assert name == cls.name or\ + name == LEGACY_TOOLCHAIN_NAMES[cls.name] + +ALPHABET = [char for char in printable if char not in [u'.', u'/']] + +@given(fixed_dictionaries({ + 'common': lists(text()), + 'c': lists(text()), + 'cxx': lists(text()), + 'asm': lists(text()), + 'ld': lists(text())}), + lists(text(min_size=1, alphabet=ALPHABET), min_size=1)) +def test_toolchain_profile_c(profile, source_file): + """Test that the appropriate profile parameters are passed to the + C compiler""" + filename = deepcopy(source_file) + filename[-1] += ".c" + to_compile = os.path.join(*filename) + for _, tc_class in TOOLCHAIN_CLASSES.items(): + toolchain = tc_class(TARGET_MAP["K64F"], build_profile=profile) + toolchain.inc_md5 = "" + toolchain.build_dir = "" + compile_command = toolchain.compile_command(to_compile, + to_compile + ".o", []) + for parameter in profile['c'] + profile['common']: + assert any(parameter in cmd for cmd in compile_command), \ + "Toolchain %s did not propigate arg %s" % (toolchain.name, + parameter) + +@given(fixed_dictionaries({ + 'common': lists(text()), + 'c': lists(text()), + 'cxx': lists(text()), + 'asm': lists(text()), + 'ld': lists(text())}), + lists(text(min_size=1, alphabet=ALPHABET), min_size=1)) +def test_toolchain_profile_cpp(profile, source_file): + """Test that the appropriate profile parameters are passed to the + C++ compiler""" + filename = deepcopy(source_file) + filename[-1] += ".cpp" + to_compile = os.path.join(*filename) + for _, tc_class in TOOLCHAIN_CLASSES.items(): + toolchain = tc_class(TARGET_MAP["K64F"], build_profile=profile) + toolchain.inc_md5 = "" + toolchain.build_dir = "" + compile_command = toolchain.compile_command(to_compile, + to_compile + ".o", []) + for parameter in profile['cxx'] + profile['common']: + assert any(parameter in cmd for cmd in compile_command), \ + "Toolchain %s did not propigate arg %s" % (toolchain.name, + parameter) + +@given(fixed_dictionaries({ + 'common': lists(text()), + 'c': lists(text()), + 'cxx': lists(text()), + 'asm': lists(text()), + 'ld': lists(text())}), + lists(text(min_size=1, alphabet=ALPHABET), min_size=1)) +def test_toolchain_profile_asm(profile, source_file): + """Test that the appropriate profile parameters are passed to the + Assembler""" + filename = deepcopy(source_file) + filename[-1] += ".s" + to_compile = os.path.join(*filename) + for _, tc_class in TOOLCHAIN_CLASSES.items(): + toolchain = tc_class(TARGET_MAP["K64F"], build_profile=profile) + toolchain.inc_md5 = "" + toolchain.build_dir = "" + compile_command = toolchain.compile_command(to_compile, + to_compile + ".o", []) + if not compile_command: + assert compile_command, to_compile + for parameter in profile['asm']: + assert any(parameter in cmd for cmd in compile_command), \ + "Toolchain %s did not propigate arg %s" % (toolchain.name, + parameter) + diff --git a/tools/test_api.py b/tools/test_api.py index 3c05788e2b4..6556df0fb22 100644 --- a/tools/test_api.py +++ b/tools/test_api.py @@ -355,14 +355,12 @@ def execute_thread_slice(self, q, target, toolchains, clean, test_ids, build_rep print self.logger.log_line(self.logger.LogType.NOTIF, 'Skipped tests for %s target. Target platform not found'% (target)) continue - build_mbed_libs_options = ["analyze"] if self.opts_goanna_for_mbed_sdk else None clean_mbed_libs_options = True if self.opts_goanna_for_mbed_sdk or clean or self.opts_clean else None try: build_mbed_libs_result = build_mbed_libs(T, toolchain, - options=build_mbed_libs_options, clean=clean_mbed_libs_options, verbose=self.opts_verbose, jobs=self.opts_jobs, @@ -423,7 +421,6 @@ def execute_thread_slice(self, q, target, toolchains, clean, test_ids, build_rep libraries.append(lib['id']) - build_project_options = ["analyze"] if self.opts_goanna_for_tests else None clean_project_options = True if self.opts_goanna_for_tests or clean or self.opts_clean else None # Build all required libraries @@ -432,7 +429,6 @@ def execute_thread_slice(self, q, target, toolchains, clean, test_ids, build_rep build_lib(lib_id, T, toolchain, - options=build_project_options, verbose=self.opts_verbose, clean=clean_mbed_libs_options, jobs=self.opts_jobs, @@ -479,7 +475,6 @@ def execute_thread_slice(self, q, target, toolchains, clean, test_ids, build_rep T, toolchain, test.dependencies, - options=build_project_options, clean=clean_project_options, verbose=self.opts_verbose, name=project_name, @@ -1990,7 +1985,7 @@ def test_path_to_name(path, base): return "-".join(name_parts).lower() -def find_tests(base_dir, target_name, toolchain_name, options=None, app_config=None): +def find_tests(base_dir, target_name, toolchain_name, app_config=None): """ Finds all tests in a directory recursively base_dir: path to the directory to scan for tests (ex. 'path/to/project') target_name: name of the target to use for scanning (ex. 'K64F') @@ -2002,7 +1997,7 @@ def find_tests(base_dir, target_name, toolchain_name, options=None, app_config=N tests = {} # Prepare the toolchain - toolchain = prepare_toolchain([base_dir], target_name, toolchain_name, options=options, + toolchain = prepare_toolchain([base_dir], target_name, toolchain_name, silent=True, app_config=app_config) # Scan the directory for paths to probe for 'TESTS' folders @@ -2060,9 +2055,10 @@ def norm_relative_path(path, start): return path def build_tests(tests, base_source_paths, build_path, target, toolchain_name, - options=None, clean=False, notify=None, verbose=False, jobs=1, - macros=None, silent=False, report=None, properties=None, - continue_on_build_fail=False, app_config=None): + clean=False, notify=None, verbose=False, jobs=1, macros=None, + silent=False, report=None, properties=None, + continue_on_build_fail=False, app_config=None, + build_profile=None): """Given the data structure from 'find_tests' and the typical build parameters, build all the tests @@ -2095,7 +2091,6 @@ def build_tests(tests, base_source_paths, build_path, target, toolchain_name, try: bin_file = build_project(src_path, test_build_path, target, toolchain_name, - options=options, jobs=jobs, clean=clean, macros=macros, @@ -2104,7 +2099,8 @@ def build_tests(tests, base_source_paths, build_path, target, toolchain_name, report=report, properties=properties, verbose=verbose, - app_config=app_config) + app_config=app_config, + build_profile=build_profile) except Exception, e: if not isinstance(e, NotSupportedException): diff --git a/tools/toolchains/__init__.py b/tools/toolchains/__init__.py index 9b56649f9c9..516ba82423d 100644 --- a/tools/toolchains/__init__.py +++ b/tools/toolchains/__init__.py @@ -31,7 +31,7 @@ from multiprocessing import Pool, cpu_count from tools.utils import run_cmd, mkdir, rel_path, ToolException, NotSupportedException, split_path, compile_worker -from tools.settings import BUILD_OPTIONS, MBED_ORG_USER +from tools.settings import MBED_ORG_USER import tools.hooks as hooks from tools.memap import MemapParser from hashlib import md5 @@ -217,7 +217,9 @@ class mbedToolchain: __metaclass__ = ABCMeta - def __init__(self, target, options=None, notify=None, macros=None, silent=False, extra_verbose=False): + profile_template = {'common':[], 'c':[], 'cxx':[], 'asm':[], 'ld':[]} + + def __init__(self, target, notify=None, macros=None, silent=False, extra_verbose=False, build_profile=None): self.target = target self.name = self.__class__.__name__ @@ -225,7 +227,7 @@ def __init__(self, target, options=None, notify=None, macros=None, silent=False, self.hook = hooks.Hook(target, self) # Toolchain flags - self.flags = deepcopy(self.DEFAULT_FLAGS) + self.flags = deepcopy(build_profile or self.profile_template) # User-defined macros self.macros = macros or [] @@ -291,15 +293,6 @@ def __init__(self, target, options=None, notify=None, macros=None, silent=False, self.output = str() self.map_outputs = list() # Place to store memmap scan results in JSON like data structures - # Build options passed by -o flag - self.options = options if options is not None else [] - - # Build options passed by settings.py or mbed_settings.py - self.options.extend(BUILD_OPTIONS) - - if self.options: - self.info("Build Options: %s" % (', '.join(self.options))) - # uVisor spepcific rules if 'UVISOR' in self.target.features and 'UVISOR_SUPPORTED' in self.target.extra_labels: self.target.core = re.sub(r"F$", '', self.target.core) @@ -434,10 +427,20 @@ def get_labels(self): toolchain_labels = [c.__name__ for c in getmro(self.__class__)] toolchain_labels.remove('mbedToolchain') self.labels = { - 'TARGET': self.target.labels + ["DEBUG" if "debug-info" in self.options else "RELEASE"], + 'TARGET': self.target.labels, 'FEATURE': self.target.features, 'TOOLCHAIN': toolchain_labels } + + # This is a policy decision and it should /really/ be in the config system + # ATM it's here for backward compatibility + if (("-g" in self.flags['common'] and + "-O0") in self.flags['common'] or + ("-r" in self.flags['common'] and + "-On" in self.flags['common'])): + self.labels['TARGET'].append("DEBUG") + else: + self.labels['TARGET'].append("RELEASE") return self.labels diff --git a/tools/toolchains/arm.py b/tools/toolchains/arm.py index f294edb5f54..bd948283da2 100644 --- a/tools/toolchains/arm.py +++ b/tools/toolchains/arm.py @@ -30,20 +30,6 @@ class ARM(mbedToolchain): INDEX_PATTERN = re.compile('(?P\s*)\^') DEP_PATTERN = re.compile('\S+:\s(?P.+)\n') - - # ANY changes to these default flags is backwards incompatible and require - # an update to the mbed-sdk-tools and website that introduces a profile - # for the previous version of these flags - DEFAULT_FLAGS = { - 'common': ["-c", "--gnu", - "-Otime", "--split_sections", "--apcs=interwork", - "--brief_diagnostics", "--restrict", "--multibyte_chars"], - 'asm': [], - 'c': ["--md", "--no_depend_system_headers", "--c99", "-D__ASSERT_MSG"], - 'cxx': ["--cpp", "--no_rtti", "--no_vla"], - 'ld': [], - } - @staticmethod def check_executable(): """Returns True if the executable (armcc) location specified by the @@ -51,8 +37,11 @@ def check_executable(): Returns False otherwise.""" return mbedToolchain.generic_check_executable("ARM", 'armcc', 2, 'bin') - def __init__(self, target, options=None, notify=None, macros=None, silent=False, extra_verbose=False): - mbedToolchain.__init__(self, target, options, notify, macros, silent, extra_verbose=extra_verbose) + def __init__(self, target, notify=None, macros=None, + silent=False, extra_verbose=False, build_profile=None): + mbedToolchain.__init__(self, target, notify, macros, silent, + extra_verbose=extra_verbose, + build_profile=build_profile) if target.core == "Cortex-M0+": cpu = "Cortex-M0" @@ -71,14 +60,6 @@ def __init__(self, target, options=None, notify=None, macros=None, silent=False, main_cc = join(ARM_BIN, "armcc") self.flags['common'] += ["--cpu=%s" % cpu] - if "save-asm" in self.options: - self.flags['common'].extend(["--asm", "--interleave"]) - - if "debug-info" in self.options: - self.flags['common'].append("-g") - self.flags['c'].append("-O0") - else: - self.flags['c'].append("-O3") self.asm = [main_cc] + self.flags['common'] + self.flags['asm'] + ["-I \""+ARM_INC+"\""] self.cc = [main_cc] + self.flags['common'] + self.flags['c'] + ["-I \""+ARM_INC+"\""] @@ -241,8 +222,10 @@ def binary(self, resources, elf, bin): class ARM_STD(ARM): - def __init__(self, target, options=None, notify=None, macros=None, silent=False, extra_verbose=False): - ARM.__init__(self, target, options, notify, macros, silent, extra_verbose=extra_verbose) + def __init__(self, target, notify=None, macros=None, + silent=False, extra_verbose=False, build_profile=None): + ARM.__init__(self, target, notify, macros, silent, + extra_verbose=extra_verbose, build_profile=build_profile) # Run-time values self.ld.extend(["--libpath", join(TOOLCHAIN_PATHS['ARM'], "lib")]) @@ -251,8 +234,10 @@ def __init__(self, target, options=None, notify=None, macros=None, silent=False, class ARM_MICRO(ARM): PATCHED_LIBRARY = False - def __init__(self, target, options=None, notify=None, macros=None, silent=False, extra_verbose=False): - ARM.__init__(self, target, options, notify, macros, silent, extra_verbose=extra_verbose) + def __init__(self, target, notify=None, macros=None, + silent=False, extra_verbose=False, build_profile=None): + ARM.__init__(self, target, notify, macros, silent, + extra_verbose=extra_verbose, build_profile=build_profile) # Extend flags self.flags['common'].extend(["-D__MICROLIB"]) diff --git a/tools/toolchains/gcc.py b/tools/toolchains/gcc.py index dbbe2c62bcb..41db27116ad 100644 --- a/tools/toolchains/gcc.py +++ b/tools/toolchains/gcc.py @@ -28,26 +28,12 @@ class GCC(mbedToolchain): DIAGNOSTIC_PATTERN = re.compile('((?P[^:]+):(?P\d+):)(\d+:)? (?Pwarning|error): (?P.+)') INDEX_PATTERN = re.compile('(?P\s*)\^') - # ANY changes to these default flags is backwards incompatible and require - # an update to the mbed-sdk-tools and website that introduces a profile - # for the previous version of these flags - DEFAULT_FLAGS = { - 'common': ["-c", "-Wall", "-Wextra", - "-Wno-unused-parameter", "-Wno-missing-field-initializers", - "-fmessage-length=0", "-fno-exceptions", "-fno-builtin", - "-ffunction-sections", "-fdata-sections", "-funsigned-char", - "-MMD", "-fno-delete-null-pointer-checks", "-fomit-frame-pointer" - ], - 'asm': ["-x", "assembler-with-cpp"], - 'c': ["-std=gnu99"], - 'cxx': ["-std=gnu++98", "-fno-rtti", "-Wvla"], - 'ld': ["-Wl,--gc-sections", "-Wl,--wrap,main", - "-Wl,--wrap,_malloc_r", "-Wl,--wrap,_free_r", "-Wl,--wrap,_realloc_r", "-Wl,--wrap,_calloc_r", - "-Wl,--wrap,exit", "-Wl,--wrap,atexit"], - } - - def __init__(self, target, options=None, notify=None, macros=None, silent=False, tool_path="", extra_verbose=False): - mbedToolchain.__init__(self, target, options, notify, macros, silent, extra_verbose=extra_verbose) + def __init__(self, target, notify=None, macros=None, + silent=False, tool_path="", extra_verbose=False, + build_profile=None): + mbedToolchain.__init__(self, target, notify, macros, silent, + extra_verbose=extra_verbose, + build_profile=build_profile) if target.core == "Cortex-M0+": cpu = "cortex-m0plus" @@ -75,8 +61,6 @@ def __init__(self, target, options=None, notify=None, macros=None, silent=False, self.cpu.append("-mfpu=fpv5-d16") self.cpu.append("-mfloat-abi=softfp") - - if target.core == "Cortex-A9": self.cpu.append("-mthumb-interwork") self.cpu.append("-marm") @@ -85,20 +69,8 @@ def __init__(self, target, options=None, notify=None, macros=None, silent=False, self.cpu.append("-mfloat-abi=hard") self.cpu.append("-mno-unaligned-access") - - # Note: We are using "-O2" instead of "-Os" to avoid this known GCC bug: - # http://gcc.gnu.org/bugzilla/show_bug.cgi?id=46762 self.flags["common"] += self.cpu - if "save-asm" in self.options: - self.flags["common"].append("-save-temps") - - if "debug-info" in self.options: - self.flags["common"].append("-g") - self.flags["common"].append("-O0") - else: - self.flags["common"].append("-Os") - main_cc = join(tool_path, "arm-none-eabi-gcc") main_cppc = join(tool_path, "arm-none-eabi-g++") self.asm = [main_cc] + self.flags['asm'] + self.flags["common"] @@ -280,27 +252,12 @@ def check_executable(): Returns False otherwise.""" return mbedToolchain.generic_check_executable("GCC_ARM", 'arm-none-eabi-gcc', 1) - def __init__(self, target, options=None, notify=None, macros=None, silent=False, extra_verbose=False): - GCC.__init__(self, target, options, notify, macros, silent, TOOLCHAIN_PATHS['GCC_ARM'], extra_verbose=extra_verbose) + def __init__(self, target, notify=None, macros=None, + silent=False, extra_verbose=False, build_profile=None): + GCC.__init__(self, target, notify, macros, silent, + TOOLCHAIN_PATHS['GCC_ARM'], extra_verbose=extra_verbose, + build_profile=build_profile) - # Use latest gcc nanolib - if "std-lib" in self.options: - use_nano = False - elif "small-lib" in self.options: - use_nano = True - elif target.default_lib == "std": - use_nano = False - elif target.default_lib == "small": - use_nano = True - else: - use_nano = False - - if use_nano: - self.ld.append("--specs=nano.specs") - self.flags['ld'].append("--specs=nano.specs") - self.cc += ["-DMBED_RTOS_SINGLE_THREAD"] - self.cppc += ["-DMBED_RTOS_SINGLE_THREAD"] - self.macros.extend(["MBED_RTOS_SINGLE_THREAD"]) self.sys_libs.append("nosys") @@ -312,8 +269,11 @@ def check_executable(): Returns False otherwise.""" return mbedToolchain.generic_check_executable("GCC_CR", 'arm-none-eabi-gcc', 1) - def __init__(self, target, options=None, notify=None, macros=None, silent=False, extra_verbose=False): - GCC.__init__(self, target, options, notify, macros, silent, TOOLCHAIN_PATHS['GCC_CR'], extra_verbose=extra_verbose) + def __init__(self, target, notify=None, macros=None, + silent=False, extra_verbose=False, build_profile=None): + GCC.__init__(self, target, notify, macros, silent, + TOOLCHAIN_PATHS['GCC_CR'], extra_verbose=extra_verbose, + build_profile=build_profile) additional_compiler_flags = [ "-D__NEWLIB__", "-D__CODE_RED", "-D__USE_CMSIS", "-DCPP_USE_HEAP", diff --git a/tools/toolchains/iar.py b/tools/toolchains/iar.py index b712c2a158d..51b310ca519 100644 --- a/tools/toolchains/iar.py +++ b/tools/toolchains/iar.py @@ -29,24 +29,6 @@ class IAR(mbedToolchain): DIAGNOSTIC_PATTERN = re.compile('"(?P[^"]+)",(?P[\d]+)\s+(?PWarning|Error)(?P.+)') INDEX_PATTERN = re.compile('(?P\s*)\^') - # ANY changes to these default flags is backwards incompatible and require - # an update to the mbed-sdk-tools and website that introduces a profile - # for the previous version of these flags - DEFAULT_FLAGS = { - 'common': [ - "--no_wrap_diagnostics", - # Pa050: No need to be notified about "non-native end of line sequence" - # Pa084: Pointless integer comparison -> checks for the values of an enum, but we use values outside of the enum to notify errors (ie: NC). - # Pa093: Implicit conversion from float to integer (ie: wait_ms(85.4) -> wait_ms(85)) - # Pa082: Operation involving two values from two registers (ie: (float)(*obj->MR)/(float)(LPC_PWM1->MR0)) - "-e", # Enable IAR language extension - "--diag_suppress=Pa050,Pa084,Pa093,Pa082"], - 'asm': [], - 'c': ["--vla"], - 'cxx': ["--guard_calls", "--no_static_destruction"], - 'ld': ["--skip_dynamic_initialization", "--threaded_lib"], - } - @staticmethod def check_executable(): """Returns True if the executable (arm-none-eabi-gcc) location @@ -54,8 +36,11 @@ def check_executable(): Returns False otherwise.""" return mbedToolchain.generic_check_executable("IAR", 'iccarm', 2, "bin") - def __init__(self, target, options=None, notify=None, macros=None, silent=False, extra_verbose=False): - mbedToolchain.__init__(self, target, options, notify, macros, silent, extra_verbose=extra_verbose) + def __init__(self, target, notify=None, macros=None, + silent=False, extra_verbose=False, build_profile=None): + mbedToolchain.__init__(self, target, notify, macros, silent, + extra_verbose=extra_verbose, + build_profile=build_profile) if target.core == "Cortex-M7F" or target.core == "Cortex-M7FD": cpuchoice = "Cortex-M7" else: @@ -94,12 +79,6 @@ def __init__(self, target, options=None, notify=None, macros=None, silent=False, asm_flags_cmd += ["--fpu", "VFPv5_sp"] c_flags_cmd.append("--fpu=VFPv5_sp") - if "debug-info" in self.options: - c_flags_cmd.append("-r") - c_flags_cmd.append("-On") - else: - c_flags_cmd.append("-Oh") - IAR_BIN = join(TOOLCHAIN_PATHS['IAR'], "bin") main_cc = join(IAR_BIN, "iccarm")