mbed-os

Fork of mbed-os by erkin yucel

Committer:
elessair
Date:
Sun Oct 23 15:10:02 2016 +0000
Revision:
0:f269e3021894
Initial commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
elessair 0:f269e3021894 1 #! /usr/bin/env python2
elessair 0:f269e3021894 2 """
elessair 0:f269e3021894 3 mbed SDK
elessair 0:f269e3021894 4 Copyright (c) 2011-2013 ARM Limited
elessair 0:f269e3021894 5
elessair 0:f269e3021894 6 Licensed under the Apache License, Version 2.0 (the "License");
elessair 0:f269e3021894 7 you may not use this file except in compliance with the License.
elessair 0:f269e3021894 8 You may obtain a copy of the License at
elessair 0:f269e3021894 9
elessair 0:f269e3021894 10 http://www.apache.org/licenses/LICENSE-2.0
elessair 0:f269e3021894 11
elessair 0:f269e3021894 12 Unless required by applicable law or agreed to in writing, software
elessair 0:f269e3021894 13 distributed under the License is distributed on an "AS IS" BASIS,
elessair 0:f269e3021894 14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
elessair 0:f269e3021894 15 See the License for the specific language governing permissions and
elessair 0:f269e3021894 16 limitations under the License.
elessair 0:f269e3021894 17
elessair 0:f269e3021894 18
elessair 0:f269e3021894 19 TEST BUILD & RUN
elessair 0:f269e3021894 20 """
elessair 0:f269e3021894 21 import sys
elessair 0:f269e3021894 22 import os
elessair 0:f269e3021894 23 import json
elessair 0:f269e3021894 24 import fnmatch
elessair 0:f269e3021894 25
elessair 0:f269e3021894 26 ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
elessair 0:f269e3021894 27 sys.path.insert(0, ROOT)
elessair 0:f269e3021894 28
elessair 0:f269e3021894 29 from tools.test_api import test_path_to_name, find_tests, print_tests, build_tests, test_spec_from_test_builds
elessair 0:f269e3021894 30 from tools.options import get_default_options_parser, extract_profile
elessair 0:f269e3021894 31 from tools.build_api import build_project, build_library
elessair 0:f269e3021894 32 from tools.build_api import print_build_memory_usage
elessair 0:f269e3021894 33 from tools.targets import TARGET_MAP
elessair 0:f269e3021894 34 from tools.utils import mkdir, ToolException, NotSupportedException, args_error
elessair 0:f269e3021894 35 from tools.test_exporters import ReportExporter, ResultExporterType
elessair 0:f269e3021894 36 from utils import argparse_filestring_type, argparse_lowercase_type, argparse_many
elessair 0:f269e3021894 37 from utils import argparse_dir_not_parent
elessair 0:f269e3021894 38 from tools.toolchains import mbedToolchain, TOOLCHAIN_PATHS, TOOLCHAIN_CLASSES
elessair 0:f269e3021894 39 from tools.settings import CLI_COLOR_MAP
elessair 0:f269e3021894 40
elessair 0:f269e3021894 41 if __name__ == '__main__':
elessair 0:f269e3021894 42 try:
elessair 0:f269e3021894 43 # Parse Options
elessair 0:f269e3021894 44 parser = get_default_options_parser(add_app_config=True)
elessair 0:f269e3021894 45
elessair 0:f269e3021894 46 parser.add_argument("-D",
elessair 0:f269e3021894 47 action="append",
elessair 0:f269e3021894 48 dest="macros",
elessair 0:f269e3021894 49 help="Add a macro definition")
elessair 0:f269e3021894 50
elessair 0:f269e3021894 51 parser.add_argument("-j", "--jobs",
elessair 0:f269e3021894 52 type=int,
elessair 0:f269e3021894 53 dest="jobs",
elessair 0:f269e3021894 54 default=0,
elessair 0:f269e3021894 55 help="Number of concurrent jobs. Default: 0/auto (based on host machine's number of CPUs)")
elessair 0:f269e3021894 56
elessair 0:f269e3021894 57 parser.add_argument("--source", dest="source_dir",
elessair 0:f269e3021894 58 type=argparse_filestring_type,
elessair 0:f269e3021894 59 default=None, help="The source (input) directory (for sources other than tests). Defaults to current directory.", action="append")
elessair 0:f269e3021894 60
elessair 0:f269e3021894 61 parser.add_argument("--build", dest="build_dir", type=argparse_dir_not_parent(ROOT),
elessair 0:f269e3021894 62 default=None, help="The build (output) directory")
elessair 0:f269e3021894 63
elessair 0:f269e3021894 64 parser.add_argument("-l", "--list", action="store_true", dest="list",
elessair 0:f269e3021894 65 default=False, help="List (recursively) available tests in order and exit")
elessair 0:f269e3021894 66
elessair 0:f269e3021894 67 parser.add_argument("-p", "--paths", dest="paths",
elessair 0:f269e3021894 68 type=argparse_many(argparse_filestring_type),
elessair 0:f269e3021894 69 default=None, help="Limit the tests to those within the specified comma separated list of paths")
elessair 0:f269e3021894 70
elessair 0:f269e3021894 71 format_choices = ["list", "json"]
elessair 0:f269e3021894 72 format_default_choice = "list"
elessair 0:f269e3021894 73 format_help = "Change the format in which tests are listed. Choices include: %s. Default: %s" % (", ".join(format_choices), format_default_choice)
elessair 0:f269e3021894 74 parser.add_argument("-f", "--format", dest="format",
elessair 0:f269e3021894 75 type=argparse_lowercase_type(format_choices, "format"),
elessair 0:f269e3021894 76 default=format_default_choice, help=format_help)
elessair 0:f269e3021894 77
elessair 0:f269e3021894 78 parser.add_argument("--continue-on-build-fail", action="store_true", dest="continue_on_build_fail",
elessair 0:f269e3021894 79 default=None, help="Continue trying to build all tests if a build failure occurs")
elessair 0:f269e3021894 80
elessair 0:f269e3021894 81 #TODO validate the names instead of just passing through str
elessair 0:f269e3021894 82 parser.add_argument("-n", "--names", dest="names", type=argparse_many(str),
elessair 0:f269e3021894 83 default=None, help="Limit the tests to a comma separated list of names")
elessair 0:f269e3021894 84
elessair 0:f269e3021894 85 parser.add_argument("--test-spec", dest="test_spec",
elessair 0:f269e3021894 86 default=None, help="Destination path for a test spec file that can be used by the Greentea automated test tool")
elessair 0:f269e3021894 87
elessair 0:f269e3021894 88 parser.add_argument("--build-report-junit", dest="build_report_junit",
elessair 0:f269e3021894 89 default=None, help="Destination path for a build report in the JUnit xml format")
elessair 0:f269e3021894 90
elessair 0:f269e3021894 91 parser.add_argument("-v", "--verbose",
elessair 0:f269e3021894 92 action="store_true",
elessair 0:f269e3021894 93 dest="verbose",
elessair 0:f269e3021894 94 default=False,
elessair 0:f269e3021894 95 help="Verbose diagnostic output")
elessair 0:f269e3021894 96
elessair 0:f269e3021894 97 options = parser.parse_args()
elessair 0:f269e3021894 98
elessair 0:f269e3021894 99 # Filter tests by path if specified
elessair 0:f269e3021894 100 if options.paths:
elessair 0:f269e3021894 101 all_paths = options.paths
elessair 0:f269e3021894 102 else:
elessair 0:f269e3021894 103 all_paths = ["."]
elessair 0:f269e3021894 104
elessair 0:f269e3021894 105 all_tests = {}
elessair 0:f269e3021894 106 tests = {}
elessair 0:f269e3021894 107
elessair 0:f269e3021894 108 # Target
elessair 0:f269e3021894 109 if options.mcu is None :
elessair 0:f269e3021894 110 args_error(parser, "argument -m/--mcu is required")
elessair 0:f269e3021894 111 mcu = options.mcu[0]
elessair 0:f269e3021894 112
elessair 0:f269e3021894 113 # Toolchain
elessair 0:f269e3021894 114 if options.tool is None:
elessair 0:f269e3021894 115 args_error(parser, "argument -t/--tool is required")
elessair 0:f269e3021894 116 toolchain = options.tool[0]
elessair 0:f269e3021894 117
elessair 0:f269e3021894 118 if not TOOLCHAIN_CLASSES[toolchain].check_executable():
elessair 0:f269e3021894 119 search_path = TOOLCHAIN_PATHS[toolchain] or "No path set"
elessair 0:f269e3021894 120 args_error(parser, "Could not find executable for %s.\n"
elessair 0:f269e3021894 121 "Currently set search path: %s"
elessair 0:f269e3021894 122 % (toolchain, search_path))
elessair 0:f269e3021894 123
elessair 0:f269e3021894 124 # App config
elessair 0:f269e3021894 125 # Disable finding `mbed_app.json` files in the source tree if not
elessair 0:f269e3021894 126 # explicitly defined on the command line. Config system searches for
elessair 0:f269e3021894 127 # `mbed_app.json` files if `app_config` is None, but will set the
elessair 0:f269e3021894 128 # app config data to an empty dictionary if the path value is another
elessair 0:f269e3021894 129 # falsey value besides None.
elessair 0:f269e3021894 130 if options.app_config is None:
elessair 0:f269e3021894 131 options.app_config = ''
elessair 0:f269e3021894 132
elessair 0:f269e3021894 133 # Find all tests in the relevant paths
elessair 0:f269e3021894 134 for path in all_paths:
elessair 0:f269e3021894 135 all_tests.update(find_tests(path, mcu, toolchain,
elessair 0:f269e3021894 136 app_config=options.app_config))
elessair 0:f269e3021894 137
elessair 0:f269e3021894 138 # Filter tests by name if specified
elessair 0:f269e3021894 139 if options.names:
elessair 0:f269e3021894 140 all_names = options.names
elessair 0:f269e3021894 141 all_names = [x.lower() for x in all_names]
elessair 0:f269e3021894 142
elessair 0:f269e3021894 143 for name in all_names:
elessair 0:f269e3021894 144 if any(fnmatch.fnmatch(testname, name) for testname in all_tests):
elessair 0:f269e3021894 145 for testname, test in all_tests.items():
elessair 0:f269e3021894 146 if fnmatch.fnmatch(testname, name):
elessair 0:f269e3021894 147 tests[testname] = test
elessair 0:f269e3021894 148 else:
elessair 0:f269e3021894 149 print "[Warning] Test with name '%s' was not found in the available tests" % (name)
elessair 0:f269e3021894 150 else:
elessair 0:f269e3021894 151 tests = all_tests
elessair 0:f269e3021894 152
elessair 0:f269e3021894 153 if options.color:
elessair 0:f269e3021894 154 # This import happens late to prevent initializing colorization when we don't need it
elessair 0:f269e3021894 155 import colorize
elessair 0:f269e3021894 156 if options.verbose:
elessair 0:f269e3021894 157 notify = mbedToolchain.print_notify_verbose
elessair 0:f269e3021894 158 else:
elessair 0:f269e3021894 159 notify = mbedToolchain.print_notify
elessair 0:f269e3021894 160 notify = colorize.print_in_color_notifier(CLI_COLOR_MAP, notify)
elessair 0:f269e3021894 161 else:
elessair 0:f269e3021894 162 notify = None
elessair 0:f269e3021894 163
elessair 0:f269e3021894 164 if options.list:
elessair 0:f269e3021894 165 # Print available tests in order and exit
elessair 0:f269e3021894 166 print_tests(tests, options.format)
elessair 0:f269e3021894 167 sys.exit(0)
elessair 0:f269e3021894 168 else:
elessair 0:f269e3021894 169 # Build all tests
elessair 0:f269e3021894 170 if not options.build_dir:
elessair 0:f269e3021894 171 args_error(parser, "argument --build is required")
elessair 0:f269e3021894 172
elessair 0:f269e3021894 173 base_source_paths = options.source_dir
elessair 0:f269e3021894 174
elessair 0:f269e3021894 175 # Default base source path is the current directory
elessair 0:f269e3021894 176 if not base_source_paths:
elessair 0:f269e3021894 177 base_source_paths = ['.']
elessair 0:f269e3021894 178
elessair 0:f269e3021894 179 build_report = {}
elessair 0:f269e3021894 180 build_properties = {}
elessair 0:f269e3021894 181
elessair 0:f269e3021894 182 library_build_success = False
elessair 0:f269e3021894 183 profile = extract_profile(parser, options, toolchain)
elessair 0:f269e3021894 184 try:
elessair 0:f269e3021894 185 # Build sources
elessair 0:f269e3021894 186 build_library(base_source_paths, options.build_dir, mcu, toolchain,
elessair 0:f269e3021894 187 jobs=options.jobs,
elessair 0:f269e3021894 188 clean=options.clean,
elessair 0:f269e3021894 189 report=build_report,
elessair 0:f269e3021894 190 properties=build_properties,
elessair 0:f269e3021894 191 name="mbed-build",
elessair 0:f269e3021894 192 macros=options.macros,
elessair 0:f269e3021894 193 verbose=options.verbose,
elessair 0:f269e3021894 194 notify=notify,
elessair 0:f269e3021894 195 archive=False,
elessair 0:f269e3021894 196 app_config=options.app_config,
elessair 0:f269e3021894 197 build_profile=profile)
elessair 0:f269e3021894 198
elessair 0:f269e3021894 199 library_build_success = True
elessair 0:f269e3021894 200 except ToolException, e:
elessair 0:f269e3021894 201 # ToolException output is handled by the build log
elessair 0:f269e3021894 202 pass
elessair 0:f269e3021894 203 except NotSupportedException, e:
elessair 0:f269e3021894 204 # NotSupportedException is handled by the build log
elessair 0:f269e3021894 205 pass
elessair 0:f269e3021894 206 except Exception, e:
elessair 0:f269e3021894 207 # Some other exception occurred, print the error message
elessair 0:f269e3021894 208 print e
elessair 0:f269e3021894 209
elessair 0:f269e3021894 210 if not library_build_success:
elessair 0:f269e3021894 211 print "Failed to build library"
elessair 0:f269e3021894 212 else:
elessair 0:f269e3021894 213 # Build all the tests
elessair 0:f269e3021894 214
elessair 0:f269e3021894 215 test_build_success, test_build = build_tests(tests, [options.build_dir], options.build_dir, mcu, toolchain,
elessair 0:f269e3021894 216 clean=options.clean,
elessair 0:f269e3021894 217 report=build_report,
elessair 0:f269e3021894 218 properties=build_properties,
elessair 0:f269e3021894 219 macros=options.macros,
elessair 0:f269e3021894 220 verbose=options.verbose,
elessair 0:f269e3021894 221 notify=notify,
elessair 0:f269e3021894 222 jobs=options.jobs,
elessair 0:f269e3021894 223 continue_on_build_fail=options.continue_on_build_fail,
elessair 0:f269e3021894 224 app_config=options.app_config,
elessair 0:f269e3021894 225 build_profile=profile)
elessair 0:f269e3021894 226
elessair 0:f269e3021894 227 # If a path to a test spec is provided, write it to a file
elessair 0:f269e3021894 228 if options.test_spec:
elessair 0:f269e3021894 229 test_spec_data = test_spec_from_test_builds(test_build)
elessair 0:f269e3021894 230
elessair 0:f269e3021894 231 # Create the target dir for the test spec if necessary
elessair 0:f269e3021894 232 # mkdir will not create the dir if it already exists
elessair 0:f269e3021894 233 test_spec_dir = os.path.dirname(options.test_spec)
elessair 0:f269e3021894 234 if test_spec_dir:
elessair 0:f269e3021894 235 mkdir(test_spec_dir)
elessair 0:f269e3021894 236
elessair 0:f269e3021894 237 try:
elessair 0:f269e3021894 238 with open(options.test_spec, 'w') as f:
elessair 0:f269e3021894 239 f.write(json.dumps(test_spec_data, indent=2))
elessair 0:f269e3021894 240 except IOError, e:
elessair 0:f269e3021894 241 print "[ERROR] Error writing test spec to file"
elessair 0:f269e3021894 242 print e
elessair 0:f269e3021894 243
elessair 0:f269e3021894 244 # If a path to a JUnit build report spec is provided, write it to a file
elessair 0:f269e3021894 245 if options.build_report_junit:
elessair 0:f269e3021894 246 report_exporter = ReportExporter(ResultExporterType.JUNIT, package="build")
elessair 0:f269e3021894 247 report_exporter.report_to_file(build_report, options.build_report_junit, test_suite_properties=build_properties)
elessair 0:f269e3021894 248
elessair 0:f269e3021894 249 # Print memory map summary on screen
elessair 0:f269e3021894 250 if build_report:
elessair 0:f269e3021894 251 print
elessair 0:f269e3021894 252 print print_build_memory_usage(build_report)
elessair 0:f269e3021894 253
elessair 0:f269e3021894 254 print_report_exporter = ReportExporter(ResultExporterType.PRINT, package="build")
elessair 0:f269e3021894 255 status = print_report_exporter.report(build_report)
elessair 0:f269e3021894 256
elessair 0:f269e3021894 257 if status:
elessair 0:f269e3021894 258 sys.exit(0)
elessair 0:f269e3021894 259 else:
elessair 0:f269e3021894 260 sys.exit(1)
elessair 0:f269e3021894 261
elessair 0:f269e3021894 262 except KeyboardInterrupt, e:
elessair 0:f269e3021894 263 print "\n[CTRL+c] exit"
elessair 0:f269e3021894 264 except Exception,e:
elessair 0:f269e3021894 265 import traceback
elessair 0:f269e3021894 266 traceback.print_exc(file=sys.stdout)
elessair 0:f269e3021894 267 print "[ERROR] %s" % str(e)
elessair 0:f269e3021894 268 sys.exit(1)