Newer
Older
mbed-os / tools / make.py
@Devaraj Ranganna Devaraj Ranganna on 27 Apr 2020 12 KB psa: Remove PSA secure binary building tools
#! /usr/bin/env python2
"""
mbed SDK
Copyright (c) 2011-2013 ARM Limited

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.


TEST BUILD & RUN
"""
from __future__ import print_function
from builtins import str
import sys
from os.path import join, abspath, dirname, normpath

# Be sure that the tools directory is in the search path
ROOT = abspath(join(dirname(__file__), ".."))
sys.path.insert(0, ROOT)

from tools.utils import args_error
from tools.utils import NotSupportedException
from tools.paths import BUILD_DIR
from tools.paths import MBED_LIBRARIES
from tools.paths import RPC_LIBRARY
from tools.paths import USB_LIBRARIES
from tools.paths import DSP_LIBRARIES
from tools.tests import TESTS, Test, TEST_MAP
from tools.tests import TEST_MBED_LIB
from tools.tests import test_known, test_name_known
from tools.options import get_default_options_parser
from tools.options import extract_profile
from tools.options import extract_mcus
from tools.options import get_toolchain_list
from tools.notifier.term import TerminalNotifier
from tools.build_api import build_project
from tools.build_api import mcu_toolchain_matrix
from tools.build_api import mcu_target_list
from tools.build_api import merge_build_data
from tools.build_api import find_valid_toolchain
from tools.utils import argparse_filestring_type
from tools.utils import argparse_many
from tools.utils import argparse_dir_not_parent
from tools.utils import NoValidToolchainException
from tools.utils import print_end_warnings
from tools.utils import print_large_string
from tools.settings import ROOT
from tools.targets import Target

def default_args_dict(options):
    return dict(
        linker_script=options.linker_script,
        clean=options.clean,
        macros=options.macros,
        jobs=options.jobs,
        name=options.artifact_name,
        app_config=options.app_config,
        stats_depth=options.stats_depth,
        ignore=options.ignore
    )

def wrapped_build_project(src_dir, build_dir, mcu, end_warnings, options, *args, **kwargs):
    error = False
    try:
        bin_file, update_file = build_project(
            src_dir, build_dir, mcu,
            *args, **kwargs
        )
        if update_file:
            print('Update Image: %s' % update_file)
        print('Image: %s' % bin_file)
    except KeyboardInterrupt as e:
        print("\n[CTRL+c] exit")
    except NotSupportedException as e:
        print("\nCould not compile for {}: {}".format(mcu, str(e)))
        error = True
    except Exception as e:
        if options.verbose:
            import traceback
            traceback.print_exc(file=sys.stdout)
        else:
            print("[ERROR] {}".format(str(e)))

        error = True

    print_end_warnings(end_warnings)
    if error:
        sys.exit(1)

def main():
    # Parse Options
    parser = get_default_options_parser(add_app_config=True)

    group = parser.add_mutually_exclusive_group(required=False)
    group.add_argument(
        "-p",
        type=argparse_many(test_known),
        dest="program",
        help="The index of the desired test program: [0-%d]" % (len(TESTS)-1)
    )
    group.add_argument(
        "-n",
        type=argparse_many(test_name_known),
        dest="program",
        help="The name of the desired test program"
    )
    group.add_argument(
        "-L", "--list-tests",
        action="store_true",
        dest="list_tests",
        default=False,
        help="List available tests in order and exit"
    )
    group.add_argument(
        "-S", "--supported-toolchains",
        dest="supported_toolchains",
        default=False,
        const="matrix",
        choices=["matrix", "toolchains", "targets"],
        nargs="?",
        help="Displays supported matrix of MCUs and toolchains"
    )

    parser.add_argument(
        "-j", "--jobs",
        type=int,
        dest="jobs",
        default=0,
        help="Number of concurrent jobs. Default: 0/auto "
        "(based on host machine's number of CPUs)"
    )
    parser.add_argument(
        "-v", "--verbose",
        action="store_true",
        dest="verbose",
        default=False,
        help="Verbose diagnostic output"
    )
    parser.add_argument(
        "--silent",
        action="store_true",
        dest="silent",
        default=False,
        help="Silent diagnostic output (no copy, compile notification)"
    )
    parser.add_argument(
        "-D",
        action="append",
        dest="macros",
        help="Add a macro definition"
    )
    parser.add_argument(
        '-f', '--filter',
        dest='general_filter_regex',
        default=None,
        help='For some commands you can use filter to filter out results'
    )
    parser.add_argument(
        "--stats-depth",
        type=int,
        dest="stats_depth",
        default=2,
        help="Depth level for static memory report"
    )
    parser.add_argument(
        "--automated",
        action="store_true",
        dest="automated",
        default=False,
        help="Automated test"
    )
    parser.add_argument(
        "--host",
        dest="host_test",
        default=None,
        help="Host test"
    )
    parser.add_argument(
        "--extra",
        dest="extra",
        default=None,
        help="Extra files"
    )
    parser.add_argument(
        "--peripherals",
        dest="peripherals",
        default=None,
        help="Required peripherals"
    )
    parser.add_argument(
        "--dep",
        dest="dependencies",
        default=None,
        help="Dependencies"
    )
    parser.add_argument(
        "--source",
        dest="source_dir",
        type=argparse_filestring_type,
        default=None,
        action="append",
        help="The source (input) directory"
    )
    parser.add_argument(
        "--duration",
        type=int,
        dest="duration",
        default=None,
        help="Duration of the test"
    )
    parser.add_argument(
        "--build",
        dest="build_dir",
        type=argparse_dir_not_parent(ROOT),
        default=None,
        help="The build (output) directory"
    )
    parser.add_argument(
        "-N", "--artifact-name",
        dest="artifact_name",
        default=None,
        help="The built project's name"
    )
    parser.add_argument(
        "--ignore",
        dest="ignore",
        type=argparse_many(str),
        default=None,
        help="Comma separated list of patterns to add to mbedignore "
        "(eg. ./main.cpp)"
    )
    parser.add_argument(
        "-b", "--baud",
        type=int,
        dest="baud",
        default=None,
        help="The mbed serial baud rate"
    )
    parser.add_argument(
        "--rpc",
        action="store_true",
        dest="rpc",
        default=False,
        help="Link with RPC library"
    )
    parser.add_argument(
        "--usb",
        action="store_true",
        dest="usb",
        default=False,
        help="Link with USB Device library"
    )
    parser.add_argument(
        "--dsp",
        action="store_true",
        dest="dsp",
        default=False,
        help="Link with DSP library"
    )
    parser.add_argument(
        "--testlib",
        action="store_true",
        dest="testlib",
        default=False,
        help="Link with mbed test library"
    )
    parser.add_argument(
        "--build-data",
        dest="build_data",
        default=None,
        help="Dump build_data to this file"
    )
    parser.add_argument(
        "-l", "--linker",
        dest="linker_script",
        type=argparse_filestring_type,
        default=None,
        help="use the specified linker script"
    )
    options = parser.parse_args()

    end_warnings = []

    if options.supported_toolchains:
        if options.supported_toolchains == "matrix":
            print_large_string(mcu_toolchain_matrix(
                platform_filter=options.general_filter_regex,
                release_version=None
            ))
        elif options.supported_toolchains == "toolchains":
            print('\n'.join(get_toolchain_list()))
        elif options.supported_toolchains == "targets":
            print_large_string(mcu_target_list())
    elif options.list_tests is True:
        print('\n'.join(map(str, sorted(TEST_MAP.values()))))
    else:
        # Target
        if options.mcu is None:
            args_error(parser, "argument -m/--mcu is required")
        mcu = extract_mcus(parser, options)[0]

        # Toolchain
        if options.tool is None:
            args_error(parser, "argument -t/--tool is required")
        toolchain = options.tool[0]

        target = Target.get_target(mcu)

        if (options.program is None) and (not options.source_dir):
            args_error(parser, "one of -p, -n, or --source is required")

        if options.source_dir and not options.build_dir:
            args_error(parser, "argument --build is required when argument --source is provided")


        notify = TerminalNotifier(options.verbose, options.silent, options.color)

        try:
            toolchain_name, internal_tc_name, end_warnings = find_valid_toolchain(
                target, toolchain
            )
        except NoValidToolchainException as e:
            print_end_warnings(e.end_warnings)
            args_error(parser, str(e))

        if options.source_dir is not None:
            resource_filter = None
            wrapped_build_project(
                options.source_dir,
                options.build_dir,
                mcu,
                end_warnings,
                options,
                toolchain_name,
                notify=notify,
                build_profile=extract_profile(parser, options, internal_tc_name),
                resource_filter=resource_filter,
                **default_args_dict(options)
            )
        else:
            p = options.program

            # If 'p' was set via -n to list of numbers make this a single element
            # integer list
            if not isinstance(p, list):
                p = [p]

            build_data_blob = {} if options.build_data else None
            for test_no in p:
                test = Test(test_no)
                if options.automated is not None:
                    test.automated = options.automated
                if options.dependencies is not None:
                    test.dependencies = options.dependencies
                if options.host_test is not None:
                    test.host_test = options.host_test
                if options.peripherals is not None:
                    test.peripherals = options.peripherals
                if options.duration is not None:
                    test.duration = options.duration
                if options.extra is not None:
                    test.extra_files = options.extra

                if not test.is_supported(mcu, toolchain):
                    print(
                        'The selected test is not supported on target '
                        '%s with toolchain %s' % (mcu, toolchain)
                    )
                    sys.exit()

                # Linking with extra libraries
                if options.rpc:
                    test.dependencies.append(RPC_LIBRARY)
                if options.usb:
                    test.dependencies.append(USB_LIBRARIES)
                if options.dsp:
                    test.dependencies.append(DSP_LIBRARIES)
                if options.testlib:
                    test.dependencies.append(TEST_MBED_LIB)

                build_dir = join(BUILD_DIR, "test", mcu, toolchain, test.id)
                if options.build_dir is not None:
                    build_dir = options.build_dir

                wrapped_build_project(
                    test.source_dir,
                    build_dir,
                    mcu,
                    end_warnings,
                    options,
                    toolchain_name,
                    set(test.dependencies),
                    notify=notify,
                    report=build_data_blob,
                    inc_dirs=[dirname(MBED_LIBRARIES)],
                    build_profile=extract_profile(parser, options, internal_tc_name),
                    **default_args_dict(options)
                )
            if options.build_data:
                merge_build_data(options.build_data, build_data_blob, "application")

if __name__ == '__main__':
    main()