Nicolas Borla / Mbed OS BBR_1Ebene
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     """Generates a project file and creates a zip archive if specified
00226 
00227     Positional Arguments:
00228     src_paths - a list of paths from which to find source files
00229     export_path - a path specifying the location of generated project files
00230     target - the mbed board/mcu for which to generate the executable
00231     ide - the ide for which to generate the project fields
00232 
00233     Keyword Arguments:
00234     libraries_paths - paths to additional libraries
00235     linker_script - path to the linker script for the specified target
00236     notify - function is passed all events, and expected to handle notification
00237       of the user, emit the events to a log, etc.
00238     name - project name
00239     inc_dirs - additional include directories
00240     jobs - number of threads
00241     config - toolchain's config object
00242     macros - User-defined macros
00243     zip_proj - string name of the zip archive you wish to creat (exclude arg
00244      if you do not wish to create an archive
00245     """
00246 
00247     # Convert src_path to a list if needed
00248     if isinstance(src_paths, dict):
00249         paths = sum(src_paths.values(), [])
00250     elif isinstance(src_paths, list):
00251         paths = src_paths[:]
00252     else:
00253         paths = [src_paths]
00254 
00255     # Extend src_paths wit libraries_paths
00256     if libraries_paths is not None:
00257         paths.extend(libraries_paths)
00258 
00259     if not isinstance(src_paths, dict):
00260         src_paths = {"": paths}
00261 
00262     # Export Directory
00263     if not exists(export_path):
00264         makedirs(export_path)
00265 
00266     _, toolchain_name = get_exporter_toolchain(ide)
00267 
00268     # Pass all params to the unified prepare_resources()
00269     toolchain = prepare_toolchain(
00270         paths, "", target, toolchain_name, macros=macros, jobs=jobs,
00271         notify=notify, config=config, build_profile=build_profile,
00272         app_config=app_config)
00273 
00274     toolchain.RESPONSE_FILES = False
00275     if name is None:
00276         name = basename(normpath(abspath(src_paths[0])))
00277 
00278     resource_dict = {loc: sum((toolchain.scan_resources(p, collect_ignores=True)
00279                                for p in path),
00280                               Resources())
00281                      for loc, path in src_paths.items()}
00282     resources = Resources()
00283 
00284     for loc, res in resource_dict.items():
00285         temp = copy.deepcopy(res)
00286         temp.subtract_basepath(".", loc)
00287         resources.add(temp)
00288 
00289     toolchain.build_dir = export_path
00290     toolchain.config.load_resources(resources)
00291     toolchain.set_config_data(toolchain.config.get_config_data())
00292     config_header = toolchain.get_config_header()
00293     resources.headers.append(config_header)
00294     resources.file_basepath[config_header] = dirname(config_header)
00295 
00296     # Change linker script if specified
00297     if linker_script is not None:
00298         resources.linker_script = linker_script
00299 
00300     files, exporter = generate_project_files(resources, export_path,
00301                                              target, name, toolchain, ide,
00302                                              macros=macros)
00303     files.append(config_header)
00304     if zip_proj:
00305         for resource in resource_dict.values():
00306             for label, res in resource.features.items():
00307                 resource.add(res)
00308         if isinstance(zip_proj, basestring):
00309             zip_export(join(export_path, zip_proj), name, resource_dict,
00310                        files + list(exporter.static_files), inc_repos, notify)
00311         else:
00312             zip_export(zip_proj, name, resource_dict,
00313                        files + list(exporter.static_files), inc_repos, notify)
00314     else:
00315         for static_file in exporter.static_files:
00316             if not exists(join(export_path, basename(static_file))):
00317                 copyfile(static_file, join(export_path, basename(static_file)))
00318 
00319     return exporter