Knight KE / Mbed OS Game_Master
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers __init__.py Source File

__init__.py

00001 """The generic interface for all exporters.
00002 """
00003 # mbed SDK
00004 # Copyright (c) 2011-2016 ARM Limited
00005 #
00006 # Licensed under the Apache License, Version 2.0 (the "License");
00007 # you may not use this file except in compliance with the License.
00008 # You may obtain a copy of the License at
00009 #
00010 #     http://www.apache.org/licenses/LICENSE-2.0
00011 #
00012 # Unless required by applicable law or agreed to in writing, software
00013 # distributed under the License is distributed on an "AS IS" BASIS,
00014 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00015 # See the License for the specific language governing permissions and
00016 # limitations under the License.
00017 
00018 from __future__ import print_function, division, absolute_import
00019 
00020 import sys
00021 from os.path import join, abspath, dirname, exists
00022 from os.path import basename, relpath, normpath, splitext
00023 from os import makedirs, walk
00024 import copy
00025 from shutil import rmtree, copyfile
00026 import zipfile
00027 
00028 from ..build_api import prepare_toolchain, scan_resources
00029 from ..toolchains import Resources
00030 from ..targets import TARGET_NAMES
00031 from . import (lpcxpresso, ds5_5, iar, makefile, embitz, coide, kds, simplicity,
00032                atmelstudio, mcuxpresso, sw4stm32, e2studio, zip, cmsis, uvision,
00033                cdt, vscode, gnuarmeclipse, qtcreator, cmake, nb, cces, codeblocks)
00034 
00035 EXPORTERS = {
00036     u'uvision5': uvision.Uvision,
00037     u'uvision': uvision.Uvision,
00038     u'gcc_arm': makefile.GccArm,
00039     u'make_gcc_arm': makefile.GccArm,
00040     u'make_armc5': makefile.Armc5,
00041     u'make_armc6': makefile.Armc6,
00042     u'make_iar': makefile.IAR,
00043     u'ds5_5': ds5_5.DS5_5,
00044     u'iar': iar.IAR,
00045     u'embitz' : embitz.EmBitz,
00046     u'sw4stm32'    : sw4stm32.Sw4STM32,
00047     u'e2studio' : e2studio.E2Studio,
00048     u'eclipse_gcc_arm'  : cdt.EclipseGcc,
00049     u'eclipse_iar'      : cdt.EclipseIAR,
00050     u'eclipse_armc5'    : cdt.EclipseArmc5,
00051     u'gnuarmeclipse': gnuarmeclipse.GNUARMEclipse,
00052     u'mcuxpresso': mcuxpresso.MCUXpresso,
00053     u'netbeans':     nb.GNUARMNetbeans,
00054     u'qtcreator': qtcreator.QtCreator,
00055     u'vscode_gcc_arm' : vscode.VSCodeGcc,
00056     u'vscode_iar' : vscode.VSCodeIAR,
00057     u'vscode_armc5' : vscode.VSCodeArmc5,
00058     u'cmake_gcc_arm': cmake.GccArm,
00059     u'cces' : cces.CCES,
00060     u'codeblocks': codeblocks.CodeBlocks
00061 }
00062 
00063 ERROR_MESSAGE_UNSUPPORTED_TOOLCHAIN = """
00064 Sorry, the target %s is not currently supported on the %s toolchain.
00065 Please refer to <a href='/handbook/Exporting-to-offline-toolchains' target='_blank'>Exporting to offline toolchains</a> for more information.
00066 """
00067 
00068 ERROR_MESSAGE_NOT_EXPORT_LIBS = """
00069 To export this project please <a href='http://mbed.org/compiler/?import=http://mbed.org/users/mbed_official/code/mbed-export/k&mode=lib' target='_blank'>import the export version of the mbed library</a>.
00070 """
00071 
00072 def mcu_ide_list ():
00073     """Shows list of exportable ides 
00074 
00075     """
00076     supported_ides = sorted(EXPORTERS.keys())
00077     return "\n".join(supported_ides)
00078 
00079 
00080 def mcu_ide_matrix (verbose_html=False):
00081     """Shows target map using prettytable
00082 
00083     Keyword argumets:
00084     verbose_html - print the matrix in html format
00085     """
00086     supported_ides = sorted(EXPORTERS.keys())
00087     # Only use it in this function so building works without extra modules
00088     from prettytable import PrettyTable, ALL
00089 
00090     # All tests status table print
00091     table_printer = PrettyTable(["Platform"] + supported_ides)
00092     # Align table
00093     for col in supported_ides:
00094         table_printer.align[col] = "c"
00095     table_printer.align["Platform"] = "l"
00096 
00097     perm_counter = 0
00098     for target in sorted(TARGET_NAMES):
00099         row = [target]  # First column is platform name
00100         for ide in supported_ides:
00101             text = "-"
00102             if EXPORTERS[ide].is_target_supported(target):
00103                 if verbose_html:
00104                     text = "&#10003;"
00105                 else:
00106                     text = "x"
00107                 perm_counter += 1
00108             row.append(text)
00109         table_printer.add_row(row)
00110 
00111     table_printer.border = True
00112     table_printer.vrules = ALL
00113     table_printer.hrules = ALL
00114     # creates a html page in a shorter format suitable for readme.md
00115     if verbose_html:
00116         result = table_printer.get_html_string()
00117     else:
00118         result = table_printer.get_string()
00119     result += "\n"
00120     result += "Total IDEs: %d\n"% (len(supported_ides))
00121     if verbose_html:
00122         result += "<br>"
00123     result += "Total platforms: %d\n"% (len(TARGET_NAMES))
00124     if verbose_html:
00125         result += "<br>"
00126     result += "Total permutations: %d"% (perm_counter)
00127     if verbose_html:
00128         result = result.replace("&amp;", "&")
00129     return result
00130 
00131 
00132 def get_exporter_toolchain (ide):
00133     """ Return the exporter class and the toolchain string as a tuple
00134 
00135     Positional arguments:
00136     ide - the ide name of an exporter
00137     """
00138     return EXPORTERS[ide], EXPORTERS[ide].TOOLCHAIN
00139 
00140 
00141 def generate_project_files (resources, export_path, target, name, toolchain, ide,
00142                            macros=None):
00143     """Generate the project files for a project
00144 
00145     Positional arguments:
00146     resources - a Resources object containing all of the files needed to build
00147       this project
00148     export_path - location to place project files
00149     name - name of the project
00150     toolchain - a toolchain class that corresponds to the toolchain used by the
00151       IDE or makefile
00152     ide - IDE name to export to
00153 
00154     Optional arguments:
00155     macros - additional macros that should be defined within the exported
00156       project
00157     """
00158     exporter_cls, _ = get_exporter_toolchain(ide)
00159     exporter = exporter_cls(target, export_path, name, toolchain,
00160                             extra_symbols=macros, resources=resources)
00161     exporter.generate()
00162     files = exporter.generated_files
00163     return files, exporter
00164 
00165 
00166 def _inner_zip_export(resources, inc_repos):
00167     for loc, res in resources.items():
00168         to_zip = (
00169             res.headers + res.s_sources + res.c_sources +\
00170             res.cpp_sources + res.libraries + res.hex_files + \
00171             [res.linker_script] + res.bin_files + res.objects + \
00172             res.json_files + res.lib_refs + res.lib_builds)
00173         if inc_repos:
00174             for directory in res.repo_dirs:
00175                 for root, _, files in walk(directory):
00176                     for repo_file in files:
00177                         source = join(root, repo_file)
00178                         to_zip.append(source)
00179                         res.file_basepath[source] = res.base_path
00180             to_zip += res.repo_files
00181         yield loc, to_zip
00182 
00183 def zip_export (file_name, prefix, resources, project_files, inc_repos, notify):
00184     """Create a zip file from an exported project.
00185 
00186     Positional Parameters:
00187     file_name - the file name of the resulting zip file
00188     prefix - a directory name that will prefix the entire zip file's contents
00189     resources - a resources object with files that must be included in the zip
00190     project_files - a list of extra files to be added to the root of the prefix
00191       directory
00192     """
00193     to_zip_list = list(_inner_zip_export(resources, inc_repos))
00194     total_files = sum(len(to_zip) for _, to_zip in to_zip_list)
00195     total_files += len(project_files)
00196     zipped = 0
00197     with zipfile.ZipFile(file_name, "w") as zip_file:
00198         for prj_file in project_files:
00199             zip_file.write(prj_file, join(prefix, basename(prj_file)))
00200         for loc, to_zip in to_zip_list:
00201             res = resources[loc]
00202             for source in to_zip:
00203                 if source:
00204                     zip_file.write(
00205                         source,
00206                         join(prefix, loc,
00207                              relpath(source, res.file_basepath[source])))
00208                     notify.progress("Zipping", source,
00209                                     100 * (zipped / total_files))
00210                     zipped += 1
00211         for lib, res in resources.items():
00212             for source in res.lib_builds:
00213                 target_dir, _ = splitext(source)
00214                 dest = join(prefix, loc,
00215                             relpath(target_dir, res.file_basepath[source]),
00216                             ".bld", "bldrc")
00217                 zip_file.write(source, dest)
00218 
00219 
00220 
00221 def export_project (src_paths, export_path, target, ide, libraries_paths=None,
00222                    linker_script=None, notify=None, name=None, inc_dirs=None,
00223                    jobs=1, config=None, macros=None, zip_proj=None,
00224                    inc_repos=False, build_profile=None, app_config=None,
00225                    ignore=None):
00226     """Generates a project file and creates a zip archive if specified
00227 
00228     Positional Arguments:
00229     src_paths - a list of paths from which to find source files
00230     export_path - a path specifying the location of generated project files
00231     target - the mbed board/mcu for which to generate the executable
00232     ide - the ide for which to generate the project fields
00233 
00234     Keyword Arguments:
00235     libraries_paths - paths to additional libraries
00236     linker_script - path to the linker script for the specified target
00237     notify - function is passed all events, and expected to handle notification
00238       of the user, emit the events to a log, etc.
00239     name - project name
00240     inc_dirs - additional include directories
00241     jobs - number of threads
00242     config - toolchain's config object
00243     macros - User-defined macros
00244     zip_proj - string name of the zip archive you wish to creat (exclude arg
00245      if you do not wish to create an archive
00246     ignore - list of paths to add to mbedignore
00247     """
00248 
00249     # Convert src_path to a list if needed
00250     if isinstance(src_paths, dict):
00251         paths = sum(src_paths.values(), [])
00252     elif isinstance(src_paths, list):
00253         paths = src_paths[:]
00254     else:
00255         paths = [src_paths]
00256 
00257     # Extend src_paths wit libraries_paths
00258     if libraries_paths is not None:
00259         paths.extend(libraries_paths)
00260 
00261     if not isinstance(src_paths, dict):
00262         src_paths = {"": paths}
00263 
00264     # Export Directory
00265     if not exists(export_path):
00266         makedirs(export_path)
00267 
00268     _, toolchain_name = get_exporter_toolchain(ide)
00269 
00270     # Pass all params to the unified prepare_resources()
00271     toolchain = prepare_toolchain(
00272         paths, "", target, toolchain_name, macros=macros, jobs=jobs,
00273         notify=notify, config=config, build_profile=build_profile,
00274         app_config=app_config, ignore=ignore)
00275 
00276     toolchain.RESPONSE_FILES = False
00277     if name is None:
00278         name = basename(normpath(abspath(src_paths[0])))
00279 
00280     resource_dict = {loc: sum((toolchain.scan_resources(p, collect_ignores=True)
00281                                for p in path),
00282                               Resources())
00283                      for loc, path in src_paths.items()}
00284     resources = Resources()
00285 
00286     for loc, res in resource_dict.items():
00287         temp = copy.deepcopy(res)
00288         temp.subtract_basepath(".", loc)
00289         resources.add(temp)
00290 
00291     toolchain.build_dir = export_path
00292     toolchain.config.load_resources(resources)
00293     toolchain.set_config_data(toolchain.config.get_config_data())
00294     config_header = toolchain.get_config_header()
00295     resources.headers.append(config_header)
00296     resources.file_basepath[config_header] = dirname(config_header)
00297 
00298     # Change linker script if specified
00299     if linker_script is not None:
00300         resources.linker_script = linker_script
00301 
00302     files, exporter = generate_project_files(resources, export_path,
00303                                              target, name, toolchain, ide,
00304                                              macros=macros)
00305     files.append(config_header)
00306     if zip_proj:
00307         for resource in resource_dict.values():
00308             for label, res in resource.features.items():
00309                 resource.add(res)
00310         if isinstance(zip_proj, basestring):
00311             zip_export(join(export_path, zip_proj), name, resource_dict,
00312                        files + list(exporter.static_files), inc_repos, notify)
00313         else:
00314             zip_export(zip_proj, name, resource_dict,
00315                        files + list(exporter.static_files), inc_repos, notify)
00316     else:
00317         for static_file in exporter.static_files:
00318             if not exists(join(export_path, basename(static_file))):
00319                 copyfile(static_file, join(export_path, basename(static_file)))
00320 
00321     return exporter