Dependents:   sensomed

Committer:
switches
Date:
Tue Nov 08 18:27:11 2016 +0000
Revision:
0:0e018d759a2a
Initial commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
switches 0:0e018d759a2a 1 """ Import and bulid a bunch of example programs
switches 0:0e018d759a2a 2
switches 0:0e018d759a2a 3 This library includes functions that are shared between the examples.py and
switches 0:0e018d759a2a 4 the update.py modules.
switches 0:0e018d759a2a 5
switches 0:0e018d759a2a 6 """
switches 0:0e018d759a2a 7 import os
switches 0:0e018d759a2a 8 from os.path import dirname, abspath, basename
switches 0:0e018d759a2a 9 import os.path
switches 0:0e018d759a2a 10 import sys
switches 0:0e018d759a2a 11 import subprocess
switches 0:0e018d759a2a 12 from shutil import rmtree
switches 0:0e018d759a2a 13
switches 0:0e018d759a2a 14 ROOT = abspath(dirname(dirname(dirname(dirname(__file__)))))
switches 0:0e018d759a2a 15 sys.path.insert(0, ROOT)
switches 0:0e018d759a2a 16
switches 0:0e018d759a2a 17 from tools.build_api import get_mbed_official_release
switches 0:0e018d759a2a 18 from tools.targets import TARGET_MAP
switches 0:0e018d759a2a 19 from tools.export import EXPORTERS
switches 0:0e018d759a2a 20
switches 0:0e018d759a2a 21 SUPPORTED_TOOLCHAINS = ["ARM", "IAR", "GCC_ARM"]
switches 0:0e018d759a2a 22 SUPPORTED_IDES = ["iar", "uvision", "make_gcc_arm", "make_iar", "make_armc5"]
switches 0:0e018d759a2a 23
switches 0:0e018d759a2a 24 def print_list(lst):
switches 0:0e018d759a2a 25 """Prints to screen the contents of a list
switches 0:0e018d759a2a 26
switches 0:0e018d759a2a 27 Args:
switches 0:0e018d759a2a 28 lst - a list of any type, to be displayed
switches 0:0e018d759a2a 29
switches 0:0e018d759a2a 30 """
switches 0:0e018d759a2a 31 if lst:
switches 0:0e018d759a2a 32 for thing in lst:
switches 0:0e018d759a2a 33 print("# %s" % thing)
switches 0:0e018d759a2a 34
switches 0:0e018d759a2a 35 def print_summary(results, export=False):
switches 0:0e018d759a2a 36 """Prints to screen the results of compiling/exporting combinations of example programs,
switches 0:0e018d759a2a 37 targets and compile toolchains/IDEs.
switches 0:0e018d759a2a 38
switches 0:0e018d759a2a 39 Args:
switches 0:0e018d759a2a 40 results - results of the compilation stage. See compile_repos() and export_repos()
switches 0:0e018d759a2a 41 for details of the format.
switches 0:0e018d759a2a 42
switches 0:0e018d759a2a 43 """
switches 0:0e018d759a2a 44
switches 0:0e018d759a2a 45 print("#"*80)
switches 0:0e018d759a2a 46 print("# Examples compilation summary")
switches 0:0e018d759a2a 47 print("#"*80)
switches 0:0e018d759a2a 48 print("#")
switches 0:0e018d759a2a 49 print("# Passed example combinations")
switches 0:0e018d759a2a 50 print("#")
switches 0:0e018d759a2a 51 for key, val in results.iteritems():
switches 0:0e018d759a2a 52 print_list(val[2])
switches 0:0e018d759a2a 53
switches 0:0e018d759a2a 54 second_result = "Failed example combinations" if not export else \
switches 0:0e018d759a2a 55 "Failed export example combinations"
switches 0:0e018d759a2a 56
switches 0:0e018d759a2a 57 print("#")
switches 0:0e018d759a2a 58 print("# %s"%second_result)
switches 0:0e018d759a2a 59 print("#")
switches 0:0e018d759a2a 60 for key, val in results.iteritems():
switches 0:0e018d759a2a 61 print_list(val[3])
switches 0:0e018d759a2a 62
switches 0:0e018d759a2a 63 if export:
switches 0:0e018d759a2a 64 print("#")
switches 0:0e018d759a2a 65 print("# Failed build example combinations")
switches 0:0e018d759a2a 66 print("#")
switches 0:0e018d759a2a 67 for key, val in results.iteritems():
switches 0:0e018d759a2a 68 print_list(val[4])
switches 0:0e018d759a2a 69
switches 0:0e018d759a2a 70 print("#")
switches 0:0e018d759a2a 71 print("#"*80)
switches 0:0e018d759a2a 72
switches 0:0e018d759a2a 73
switches 0:0e018d759a2a 74 def target_cross_toolchain(allowed_toolchains,
switches 0:0e018d759a2a 75 features=[], targets=[]):
switches 0:0e018d759a2a 76 """Generate pairs of target and toolchains
switches 0:0e018d759a2a 77
switches 0:0e018d759a2a 78 Args:
switches 0:0e018d759a2a 79 allowed_toolchains - a list of all possible toolchains
switches 0:0e018d759a2a 80
switches 0:0e018d759a2a 81 Kwargs:
switches 0:0e018d759a2a 82 features - the features that must be in the features array of a
switches 0:0e018d759a2a 83 target
switches 0:0e018d759a2a 84 targets - a list of available targets
switches 0:0e018d759a2a 85 """
switches 0:0e018d759a2a 86 if len(targets) == 0:
switches 0:0e018d759a2a 87 targets=TARGET_MAP.keys()
switches 0:0e018d759a2a 88
switches 0:0e018d759a2a 89 for target, toolchains in get_mbed_official_release("5"):
switches 0:0e018d759a2a 90 for toolchain in toolchains:
switches 0:0e018d759a2a 91 if (toolchain in allowed_toolchains and
switches 0:0e018d759a2a 92 target in targets and
switches 0:0e018d759a2a 93 all(feature in TARGET_MAP[target].features
switches 0:0e018d759a2a 94 for feature in features)):
switches 0:0e018d759a2a 95 yield target, toolchain
switches 0:0e018d759a2a 96
switches 0:0e018d759a2a 97
switches 0:0e018d759a2a 98 def target_cross_ide(allowed_ides,
switches 0:0e018d759a2a 99 features=[], targets=[]):
switches 0:0e018d759a2a 100 """Generate pairs of target and ides
switches 0:0e018d759a2a 101
switches 0:0e018d759a2a 102 Args:
switches 0:0e018d759a2a 103 allowed_ides - a list of all possible IDEs
switches 0:0e018d759a2a 104
switches 0:0e018d759a2a 105 Kwargs:
switches 0:0e018d759a2a 106 features - the features that must be in the features array of a
switches 0:0e018d759a2a 107 target
switches 0:0e018d759a2a 108 targets - a list of available targets
switches 0:0e018d759a2a 109 """
switches 0:0e018d759a2a 110 if len(targets) == 0:
switches 0:0e018d759a2a 111 targets=TARGET_MAP.keys()
switches 0:0e018d759a2a 112
switches 0:0e018d759a2a 113 for target, toolchains in get_mbed_official_release("5"):
switches 0:0e018d759a2a 114 for ide in allowed_ides:
switches 0:0e018d759a2a 115 if (EXPORTERS[ide].TOOLCHAIN in toolchains and
switches 0:0e018d759a2a 116 target in EXPORTERS[ide].TARGETS and
switches 0:0e018d759a2a 117 target in targets and
switches 0:0e018d759a2a 118 all(feature in TARGET_MAP[target].features
switches 0:0e018d759a2a 119 for feature in features)):
switches 0:0e018d759a2a 120 yield target, ide
switches 0:0e018d759a2a 121
switches 0:0e018d759a2a 122
switches 0:0e018d759a2a 123 def get_repo_list(example):
switches 0:0e018d759a2a 124 """ Returns a list of all the repos associated with the specific example in the json
switches 0:0e018d759a2a 125 config file.
switches 0:0e018d759a2a 126 If there are repos listed under the mbed section then these will be returned as a
switches 0:0e018d759a2a 127 list. If not then the github single repo with be returned.
switches 0:0e018d759a2a 128 NOTE: This does not currently deal with multiple examples underneath a github
switches 0:0e018d759a2a 129 sourced exampe repo.
switches 0:0e018d759a2a 130
switches 0:0e018d759a2a 131 Args:
switches 0:0e018d759a2a 132 example - Example for which the repo list is requested
switches 0:0e018d759a2a 133 repos - The list of repos contained within that example in the json file
switches 0:0e018d759a2a 134
switches 0:0e018d759a2a 135 """
switches 0:0e018d759a2a 136 repos = []
switches 0:0e018d759a2a 137 if len(example['mbed']) > 0:
switches 0:0e018d759a2a 138 for repo in example['mbed']:
switches 0:0e018d759a2a 139 repos.append(repo)
switches 0:0e018d759a2a 140 else:
switches 0:0e018d759a2a 141 repos.append(example['github'])
switches 0:0e018d759a2a 142 return repos
switches 0:0e018d759a2a 143
switches 0:0e018d759a2a 144 def source_repos(config):
switches 0:0e018d759a2a 145 """ Clones each of the repos associated with the specific examples name from the
switches 0:0e018d759a2a 146 json config file. Note if there is already a clone of the repo then it will first
switches 0:0e018d759a2a 147 be removed to ensure a clean, up to date cloning.
switches 0:0e018d759a2a 148 Args:
switches 0:0e018d759a2a 149 config - the json object imported from the file.
switches 0:0e018d759a2a 150
switches 0:0e018d759a2a 151 """
switches 0:0e018d759a2a 152 print("\nImporting example repos....\n")
switches 0:0e018d759a2a 153 for example in config['examples']:
switches 0:0e018d759a2a 154 for repo in get_repo_list(example):
switches 0:0e018d759a2a 155 name = basename(repo)
switches 0:0e018d759a2a 156 if os.path.exists(name):
switches 0:0e018d759a2a 157 print("'%s' example directory already exists. Deleting..." % name)
switches 0:0e018d759a2a 158 rmtree(name)
switches 0:0e018d759a2a 159
switches 0:0e018d759a2a 160 subprocess.call(["mbed-cli", "import", repo])
switches 0:0e018d759a2a 161
switches 0:0e018d759a2a 162 def get_num_failures(results, export=False):
switches 0:0e018d759a2a 163 """ Returns the number of failed compilations from the results summary
switches 0:0e018d759a2a 164 Args:
switches 0:0e018d759a2a 165 results - results summary of the compilation stage. See compile_repos() for
switches 0:0e018d759a2a 166 details of the format.
switches 0:0e018d759a2a 167 num_failures
switches 0:0e018d759a2a 168
switches 0:0e018d759a2a 169 """
switches 0:0e018d759a2a 170 num_failures = 0
switches 0:0e018d759a2a 171
switches 0:0e018d759a2a 172 for key, val in results.iteritems():
switches 0:0e018d759a2a 173 num_failures = num_failures + len(val[3])
switches 0:0e018d759a2a 174 if export:
switches 0:0e018d759a2a 175 num_failures += len(val[4])
switches 0:0e018d759a2a 176
switches 0:0e018d759a2a 177 return num_failures
switches 0:0e018d759a2a 178
switches 0:0e018d759a2a 179
switches 0:0e018d759a2a 180 def export_repos(config, ides):
switches 0:0e018d759a2a 181 def print_message(message, name):
switches 0:0e018d759a2a 182 print(message+ " %s"%name)
switches 0:0e018d759a2a 183 sys.stdout.flush()
switches 0:0e018d759a2a 184
switches 0:0e018d759a2a 185 results = {}
switches 0:0e018d759a2a 186 print("\nExporting example repos....\n")
switches 0:0e018d759a2a 187 for example in config['examples']:
switches 0:0e018d759a2a 188 export_failures = []
switches 0:0e018d759a2a 189 build_failures = []
switches 0:0e018d759a2a 190 successes = []
switches 0:0e018d759a2a 191 exported = True
switches 0:0e018d759a2a 192 pass_status = True
switches 0:0e018d759a2a 193 if example['export']:
switches 0:0e018d759a2a 194 for repo in get_repo_list(example):
switches 0:0e018d759a2a 195 example_project_name = basename(repo)
switches 0:0e018d759a2a 196 os.chdir(example_project_name)
switches 0:0e018d759a2a 197 # Check that the target, IDE, and features combinations are valid and return a
switches 0:0e018d759a2a 198 # list of valid combinations to work through
switches 0:0e018d759a2a 199 for target, ide in target_cross_ide(ides,
switches 0:0e018d759a2a 200 example['features'],
switches 0:0e018d759a2a 201 example['targets']):
switches 0:0e018d759a2a 202 example_name = "{} {} {}".format(example_project_name, target,
switches 0:0e018d759a2a 203 ide)
switches 0:0e018d759a2a 204 def status(message):
switches 0:0e018d759a2a 205 print(message + " %s" % example_name)
switches 0:0e018d759a2a 206 sys.stdout.flush()
switches 0:0e018d759a2a 207
switches 0:0e018d759a2a 208 status("Exporting")
switches 0:0e018d759a2a 209 proc = subprocess.Popen(["mbed-cli", "export", "-i", ide,
switches 0:0e018d759a2a 210 "-m", target])
switches 0:0e018d759a2a 211 proc.wait()
switches 0:0e018d759a2a 212 if proc.returncode:
switches 0:0e018d759a2a 213 export_failures.append(example_name)
switches 0:0e018d759a2a 214 status("FAILURE exporting")
switches 0:0e018d759a2a 215 else:
switches 0:0e018d759a2a 216 status("SUCCESS exporting")
switches 0:0e018d759a2a 217 status("Building")
switches 0:0e018d759a2a 218 if EXPORTERS[ide].build(example_project_name):
switches 0:0e018d759a2a 219 status("FAILURE building")
switches 0:0e018d759a2a 220 build_failures.append(example_name)
switches 0:0e018d759a2a 221 else:
switches 0:0e018d759a2a 222 status("SUCCESS building")
switches 0:0e018d759a2a 223 successes.append(example_name)
switches 0:0e018d759a2a 224 os.chdir("..")
switches 0:0e018d759a2a 225
switches 0:0e018d759a2a 226 if len(build_failures+export_failures) > 0:
switches 0:0e018d759a2a 227 pass_status= False
switches 0:0e018d759a2a 228 else:
switches 0:0e018d759a2a 229 exported = False
switches 0:0e018d759a2a 230
switches 0:0e018d759a2a 231 results[example['name']] = [exported, pass_status, successes, export_failures, build_failures]
switches 0:0e018d759a2a 232
switches 0:0e018d759a2a 233 return results
switches 0:0e018d759a2a 234
switches 0:0e018d759a2a 235
switches 0:0e018d759a2a 236 def compile_repos(config, toolchains):
switches 0:0e018d759a2a 237 """Compiles combinations of example programs, targets and compile chains.
switches 0:0e018d759a2a 238
switches 0:0e018d759a2a 239 The results are returned in a [key: value] dictionary format:
switches 0:0e018d759a2a 240 Where key = The example name from the json config file
switches 0:0e018d759a2a 241 value = a list containing: pass_status, successes, and failures
switches 0:0e018d759a2a 242
switches 0:0e018d759a2a 243 where pass_status = The overall pass status for the compilation of the full
switches 0:0e018d759a2a 244 set of example programs comprising the example suite.
switches 0:0e018d759a2a 245 True if all examples pass, false otherwise
switches 0:0e018d759a2a 246 successes = list of passing examples.
switches 0:0e018d759a2a 247 failures = list of failing examples.
switches 0:0e018d759a2a 248
switches 0:0e018d759a2a 249 Both successes and failures contain the example name, target and compile chain
switches 0:0e018d759a2a 250
switches 0:0e018d759a2a 251 Args:
switches 0:0e018d759a2a 252 config - the json object imported from the file.
switches 0:0e018d759a2a 253 toolchains - List of toolchains to compile for.
switches 0:0e018d759a2a 254 results - results of the compilation stage.
switches 0:0e018d759a2a 255
switches 0:0e018d759a2a 256 """
switches 0:0e018d759a2a 257 results = {}
switches 0:0e018d759a2a 258 print("\nCompiling example repos....\n")
switches 0:0e018d759a2a 259 for example in config['examples']:
switches 0:0e018d759a2a 260 failures = []
switches 0:0e018d759a2a 261 successes = []
switches 0:0e018d759a2a 262 compiled = True
switches 0:0e018d759a2a 263 pass_status = True
switches 0:0e018d759a2a 264 if example['compile']:
switches 0:0e018d759a2a 265 if len(example['toolchains']) > 0:
switches 0:0e018d759a2a 266 toolchains = example['toolchains']
switches 0:0e018d759a2a 267
switches 0:0e018d759a2a 268 for repo in get_repo_list(example):
switches 0:0e018d759a2a 269 os.chdir(basename(repo))
switches 0:0e018d759a2a 270
switches 0:0e018d759a2a 271 # Check that the target, toolchain and features combinations are valid and return a
switches 0:0e018d759a2a 272 # list of valid combinations to work through
switches 0:0e018d759a2a 273 for target, toolchain in target_cross_toolchain(toolchains,
switches 0:0e018d759a2a 274 example['features'], example['targets']):
switches 0:0e018d759a2a 275 proc = subprocess.Popen(["mbed-cli", "compile", "-t", toolchain,
switches 0:0e018d759a2a 276 "-m", target, "--silent"])
switches 0:0e018d759a2a 277 proc.wait()
switches 0:0e018d759a2a 278 example_summary = "{} {} {}".format(basename(repo), target, toolchain)
switches 0:0e018d759a2a 279 if proc.returncode:
switches 0:0e018d759a2a 280 failures.append(example_summary)
switches 0:0e018d759a2a 281 else:
switches 0:0e018d759a2a 282 successes.append(example_summary)
switches 0:0e018d759a2a 283 os.chdir("..")
switches 0:0e018d759a2a 284
switches 0:0e018d759a2a 285 # If there are any compilation failures for the example 'set' then the overall status is fail.
switches 0:0e018d759a2a 286 if len(failures) > 0:
switches 0:0e018d759a2a 287 pass_status = False
switches 0:0e018d759a2a 288 else:
switches 0:0e018d759a2a 289 compiled = False
switches 0:0e018d759a2a 290
switches 0:0e018d759a2a 291 results[example['name']] = [compiled, pass_status, successes, failures]
switches 0:0e018d759a2a 292
switches 0:0e018d759a2a 293 return results
switches 0:0e018d759a2a 294
switches 0:0e018d759a2a 295
switches 0:0e018d759a2a 296 def update_mbedos_version(config, tag):
switches 0:0e018d759a2a 297 """ For each example repo identified in the config json object, update the version of
switches 0:0e018d759a2a 298 mbed-os to that specified by the supplied GitHub tag. This function assumes that each
switches 0:0e018d759a2a 299 example repo has already been cloned.
switches 0:0e018d759a2a 300
switches 0:0e018d759a2a 301 Args:
switches 0:0e018d759a2a 302 config - the json object imported from the file.
switches 0:0e018d759a2a 303 tag - GitHub tag corresponding to a version of mbed-os to upgrade to.
switches 0:0e018d759a2a 304
switches 0:0e018d759a2a 305 """
switches 0:0e018d759a2a 306 print("Updating mbed-os in examples to version %s\n" % tag)
switches 0:0e018d759a2a 307 for example in config['examples']:
switches 0:0e018d759a2a 308 for repo in get_repo_list(example):
switches 0:0e018d759a2a 309 update_dir = basename(repo) + "/mbed-os"
switches 0:0e018d759a2a 310 print("\nChanging dir to %s\n" % update_dir)
switches 0:0e018d759a2a 311 os.chdir(update_dir)
switches 0:0e018d759a2a 312 subprocess.call(["mbed-cli", "update", tag, "--clean"])
switches 0:0e018d759a2a 313 os.chdir("../..")
switches 0:0e018d759a2a 314