Greg Steiert / maxim_dev

Dependents:   sensomed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers examples_lib.py Source File

examples_lib.py

00001 """ Import and bulid a bunch of example programs
00002 
00003     This library includes functions that are shared between the examples.py and 
00004     the update.py modules.
00005     
00006  """
00007 import os
00008 from os.path import dirname, abspath, basename
00009 import os.path
00010 import sys
00011 import subprocess
00012 from shutil import rmtree
00013 
00014 ROOT = abspath(dirname(dirname(dirname(dirname(__file__)))))
00015 sys.path.insert(0, ROOT)
00016 
00017 from tools.build_api import get_mbed_official_release
00018 from tools.targets import TARGET_MAP
00019 from tools.export import EXPORTERS
00020 
00021 SUPPORTED_TOOLCHAINS = ["ARM", "IAR", "GCC_ARM"]
00022 SUPPORTED_IDES = ["iar", "uvision", "make_gcc_arm", "make_iar", "make_armc5"]
00023 
00024 def print_list (lst):
00025     """Prints to screen the contents of a list
00026 
00027     Args:
00028     lst - a list of any type, to be displayed
00029 
00030     """
00031     if lst:
00032         for thing in lst:
00033             print("# %s" % thing)
00034 
00035 def print_summary (results, export=False):
00036     """Prints to screen the results of compiling/exporting combinations of example programs,
00037        targets and compile toolchains/IDEs.
00038 
00039     Args:
00040     results - results of the compilation stage. See compile_repos() and export_repos()
00041               for details of the format.
00042 
00043     """
00044 
00045     print("#"*80)
00046     print("# Examples compilation summary")
00047     print("#"*80)
00048     print("#")
00049     print("# Passed example combinations")
00050     print("#")
00051     for key, val in results.iteritems():
00052         print_list(val[2])
00053 
00054     second_result = "Failed example combinations" if not export else \
00055         "Failed export example combinations"
00056             
00057     print("#")
00058     print("# %s"%second_result)
00059     print("#")
00060     for key, val in results.iteritems():
00061         print_list(val[3])
00062 
00063     if export:
00064         print("#")
00065         print("# Failed build example combinations")
00066         print("#")
00067         for key, val in results.iteritems():
00068             print_list(val[4])
00069 
00070     print("#")
00071     print("#"*80)
00072     
00073 
00074 def target_cross_toolchain (allowed_toolchains,
00075                            features=[], targets=[]):
00076     """Generate pairs of target and toolchains
00077 
00078     Args:
00079     allowed_toolchains - a list of all possible toolchains
00080 
00081     Kwargs:
00082     features - the features that must be in the features array of a
00083                target
00084     targets - a list of available targets
00085     """
00086     if len(targets) == 0:
00087         targets=TARGET_MAP.keys()
00088         
00089     for target, toolchains in get_mbed_official_release("5"):
00090         for toolchain in toolchains:
00091             if (toolchain in allowed_toolchains and
00092                 target in targets and
00093                 all(feature in TARGET_MAP[target].features
00094                     for feature in features)):
00095                 yield target, toolchain
00096 
00097 
00098 def target_cross_ide (allowed_ides,
00099                     features=[], targets=[]):
00100     """Generate pairs of target and ides
00101 
00102     Args:
00103     allowed_ides - a list of all possible IDEs
00104 
00105     Kwargs:
00106     features - the features that must be in the features array of a
00107                target
00108     targets - a list of available targets
00109     """
00110     if len(targets) == 0:
00111         targets=TARGET_MAP.keys()
00112 
00113     for target, toolchains in get_mbed_official_release("5"):
00114         for ide in allowed_ides:
00115             if (EXPORTERS[ide].TOOLCHAIN in toolchains and
00116                 target in EXPORTERS[ide].TARGETS and
00117                 target in targets and
00118                 all(feature in TARGET_MAP[target].features
00119                     for feature in features)):
00120                 yield target, ide
00121 
00122 
00123 def get_repo_list (example):
00124     """ Returns a list of all the repos associated with the specific example in the json
00125         config file.
00126         If there are repos listed under the mbed section then these will be returned as a 
00127         list. If not then the github single repo with be returned. 
00128         NOTE: This does not currently deal with multiple examples underneath a github 
00129         sourced exampe repo.
00130 
00131     Args:
00132     example - Example for which the repo list is requested
00133     repos - The list of repos contained within that example in the json file 
00134 
00135     """
00136     repos = []
00137     if len(example['mbed']) > 0:
00138         for repo in example['mbed']:
00139             repos.append(repo)
00140     else:
00141         repos.append(example['github'])
00142     return repos
00143 
00144 def source_repos (config):
00145     """ Clones each of the repos associated with the specific examples name from the 
00146         json config file. Note if there is already a clone of the repo then it will first
00147         be removed to ensure a clean, up to date cloning.
00148     Args:
00149     config - the json object imported from the file. 
00150 
00151     """
00152     print("\nImporting example repos....\n")
00153     for example in config['examples']:
00154         for repo in get_repo_list(example):
00155             name = basename(repo)
00156             if os.path.exists(name):
00157                 print("'%s' example directory already exists. Deleting..." % name)
00158                 rmtree(name)
00159         
00160             subprocess.call(["mbed-cli", "import", repo])
00161 
00162 def get_num_failures (results, export=False):
00163     """ Returns the number of failed compilations from the results summary
00164     Args:
00165     results - results summary of the compilation stage. See compile_repos() for
00166               details of the format.
00167     num_failures 
00168 
00169     """
00170     num_failures = 0
00171 
00172     for key, val in results.iteritems():
00173         num_failures = num_failures + len(val[3])
00174         if export:
00175             num_failures += len(val[4])
00176 
00177     return num_failures
00178 
00179 
00180 def export_repos(config, ides):
00181     def print_message(message, name):
00182         print(message+ " %s"%name)
00183         sys.stdout.flush()
00184 
00185     results = {}
00186     print("\nExporting example repos....\n")
00187     for example in config['examples']:
00188         export_failures = []
00189         build_failures = []
00190         successes = []
00191         exported = True
00192         pass_status = True
00193         if example['export']:
00194             for repo in get_repo_list(example):
00195                 example_project_name = basename(repo)
00196                 os.chdir(example_project_name)
00197                 # Check that the target, IDE, and features combinations are valid and return a
00198                 # list of valid combinations to work through
00199                 for target, ide in target_cross_ide(ides,
00200                                                     example['features'],
00201                                                     example['targets']):
00202                     example_name = "{} {} {}".format(example_project_name, target,
00203                                                      ide)
00204                     def status(message):
00205                         print(message + " %s" % example_name)
00206                         sys.stdout.flush()
00207 
00208                     status("Exporting")
00209                     proc = subprocess.Popen(["mbed-cli", "export", "-i", ide,
00210                                              "-m", target])
00211                     proc.wait()
00212                     if proc.returncode:
00213                         export_failures.append(example_name)
00214                         status("FAILURE exporting")
00215                     else:
00216                         status("SUCCESS exporting")
00217                         status("Building")
00218                         if EXPORTERS[ide].build(example_project_name):
00219                             status("FAILURE building")
00220                             build_failures.append(example_name)
00221                         else:
00222                             status("SUCCESS building")
00223                             successes.append(example_name)
00224                     os.chdir("..")
00225 
00226                 if len(build_failures+export_failures) > 0:
00227                     pass_status= False
00228         else:
00229             exported = False
00230 
00231         results[example['name']] = [exported, pass_status, successes, export_failures, build_failures]
00232 
00233     return results
00234 
00235 
00236 def compile_repos (config, toolchains):
00237     """Compiles combinations of example programs, targets and compile chains.
00238        
00239        The results are returned in a [key: value] dictionary format:
00240        Where key = The example name from the json config file
00241              value = a list containing: pass_status, successes, and failures
00242              
00243              where pass_status = The overall pass status for the compilation of the full
00244                                  set of example programs comprising the example suite.
00245                                  True if all examples pass, false otherwise
00246                    successes = list of passing examples. 
00247                    failures = list of failing examples.
00248                    
00249                    Both successes and failures contain the example name, target and compile chain
00250 
00251     Args:
00252     config - the json object imported from the file. 
00253     toolchains - List of toolchains to compile for.
00254     results - results of the compilation stage. 
00255 
00256     """
00257     results = {}
00258     print("\nCompiling example repos....\n")
00259     for example in config['examples']:        
00260         failures = []
00261         successes = []
00262         compiled = True
00263         pass_status = True
00264         if example['compile']:
00265             if len(example['toolchains']) > 0:
00266                 toolchains = example['toolchains']
00267             
00268             for repo in get_repo_list(example):
00269                 os.chdir(basename(repo))
00270                 
00271                 # Check that the target, toolchain and features combinations are valid and return a 
00272                 # list of valid combinations to work through
00273                 for target, toolchain in target_cross_toolchain(toolchains,
00274                                                                 example['features'], example['targets']):
00275                     proc = subprocess.Popen(["mbed-cli", "compile", "-t", toolchain,
00276                                              "-m", target, "--silent"])
00277                     proc.wait()
00278                     example_summary = "{} {} {}".format(basename(repo), target, toolchain)
00279                     if proc.returncode:
00280                         failures.append(example_summary)
00281                     else:
00282                         successes.append(example_summary)
00283                 os.chdir("..")
00284             
00285             # If there are any compilation failures for the example 'set' then the overall status is fail.
00286             if len(failures) > 0:
00287                 pass_status = False
00288         else:
00289             compiled = False
00290 
00291         results[example['name']] = [compiled, pass_status, successes, failures]
00292 
00293     return results
00294 
00295 
00296 def update_mbedos_version (config, tag):
00297     """ For each example repo identified in the config json object, update the version of 
00298         mbed-os to that specified by the supplied GitHub tag. This function assumes that each
00299         example repo has already been cloned.
00300         
00301     Args:
00302     config - the json object imported from the file. 
00303     tag - GitHub tag corresponding to a version of mbed-os to upgrade to.
00304     
00305     """
00306     print("Updating mbed-os in examples to version %s\n" % tag)
00307     for example in config['examples']:
00308         for repo in get_repo_list(example):
00309             update_dir =  basename(repo) + "/mbed-os"
00310             print("\nChanging dir to %s\n" % update_dir)
00311             os.chdir(update_dir)
00312             subprocess.call(["mbed-cli", "update", tag, "--clean"])
00313             os.chdir("../..")
00314