Anders Blomdell / mbed-sdk-tools
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, isfile
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 ..resources import Resources, FileType, FileRef
00029 from ..config import ALLOWED_FEATURES
00030 from ..build_api import prepare_toolchain
00031 from ..targets import TARGET_NAMES
00032 from . import (lpcxpresso, ds5_5, iar, makefile, embitz, coide, kds, simplicity,
00033                atmelstudio, mcuxpresso, sw4stm32, e2studio, zip, cmsis, uvision,
00034                cdt, vscode, gnuarmeclipse, qtcreator, cmake, nb, cces, codeblocks)
00035 
00036 EXPORTERS = {
00037     u'uvision6': uvision.UvisionArmc6,
00038     u'uvision5': uvision.UvisionArmc5,
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, prj_files, inc_repos):
00167     to_zip = sum((resources.get_file_refs(ftype) for ftype
00168                   in Resources.ALL_FILE_TYPES),
00169                  [])
00170     to_zip.extend(FileRef(basename(pfile), pfile) for pfile in prj_files)
00171     for dest, source in resources.get_file_refs(FileType.BLD_REF):
00172         target_dir, _ = splitext(dest)
00173         dest = join(target_dir, ".bld", "bldrc")
00174         to_zip.append(FileRef(dest, source))
00175     if inc_repos:
00176         for dest, source in resources.get_file_refs(FileType.REPO_DIRS):
00177             for root, _, files in walk(source):
00178                 for repo_file in files:
00179                     file_source = join(root, repo_file)
00180                     file_dest = join(dest, relpath(file_source, source))
00181                     to_zip.append(FileRef(file_dest, file_source))
00182     return to_zip
00183 
00184 def zip_export (file_name, prefix, resources, project_files, inc_repos, notify):
00185     """Create a zip file from an exported project.
00186 
00187     Positional Parameters:
00188     file_name - the file name of the resulting zip file
00189     prefix - a directory name that will prefix the entire zip file's contents
00190     resources - a resources object with files that must be included in the zip
00191     project_files - a list of extra files to be added to the root of the prefix
00192       directory
00193     """
00194     to_zip_list = sorted(set(_inner_zip_export(
00195         resources, project_files, inc_repos)))
00196     total_files = len(to_zip_list)
00197     zipped = 0
00198     with zipfile.ZipFile(file_name, "w") as zip_file:
00199         for dest, source in to_zip_list:
00200             if source and isfile(source):
00201                 zip_file.write(source, join(prefix, dest))
00202                 zipped += 1
00203                 notify.progress("Zipping", source,
00204                                 100 * (zipped / total_files))
00205             else:
00206                 zipped += 1
00207 
00208 
00209 def export_project (src_paths, export_path, target, ide, libraries_paths=None,
00210                    linker_script=None, notify=None, name=None, inc_dirs=None,
00211                    jobs=1, config=None, macros=None, zip_proj=None,
00212                    inc_repos=False, build_profile=None, app_config=None,
00213                    ignore=None):
00214     """Generates a project file and creates a zip archive if specified
00215 
00216     Positional Arguments:
00217     src_paths - a list of paths from which to find source files
00218     export_path - a path specifying the location of generated project files
00219     target - the mbed board/mcu for which to generate the executable
00220     ide - the ide for which to generate the project fields
00221 
00222     Keyword Arguments:
00223     libraries_paths - paths to additional libraries
00224     linker_script - path to the linker script for the specified target
00225     notify - function is passed all events, and expected to handle notification
00226       of the user, emit the events to a log, etc.
00227     name - project name
00228     inc_dirs - additional include directories
00229     jobs - number of threads
00230     config - toolchain's config object
00231     macros - User-defined macros
00232     zip_proj - string name of the zip archive you wish to creat (exclude arg
00233      if you do not wish to create an archive
00234     ignore - list of paths to add to mbedignore
00235     """
00236 
00237     # Convert src_path to a list if needed
00238     if isinstance(src_paths, dict):
00239         paths = sum(src_paths.values(), [])
00240     elif isinstance(src_paths, list):
00241         paths = src_paths[:]
00242     else:
00243         paths = [src_paths]
00244 
00245     # Extend src_paths wit libraries_paths
00246     if libraries_paths is not None:
00247         paths.extend(libraries_paths)
00248 
00249     if not isinstance(src_paths, dict):
00250         src_paths = {"": paths}
00251 
00252     # Export Directory
00253     if not exists(export_path):
00254         makedirs(export_path)
00255 
00256     _, toolchain_name = get_exporter_toolchain(ide)
00257 
00258     # Pass all params to the unified prepare_resources()
00259     toolchain = prepare_toolchain(
00260         paths, "", target, toolchain_name, macros=macros, jobs=jobs,
00261         notify=notify, config=config, build_profile=build_profile,
00262         app_config=app_config, ignore=ignore)
00263 
00264     toolchain.RESPONSE_FILES = False
00265     if name is None:
00266         name = basename(normpath(abspath(src_paths[0])))
00267 
00268     resources = Resources(notify, collect_ignores=True)
00269     resources.add_toolchain_labels(toolchain)
00270     for loc, path in src_paths.items():
00271         for p in path:
00272             resources.add_directory(p, into_path=loc)
00273     toolchain.build_dir = export_path
00274     toolchain.config.load_resources(resources)
00275     toolchain.set_config_data(toolchain.config.get_config_data())
00276     config_header = toolchain.get_config_header()
00277     resources.add_file_ref(FileType.HEADER, basename(config_header), config_header)
00278 
00279     # Change linker script if specified
00280     if linker_script is not None:
00281         resources.linker_script = linker_script
00282 
00283     files, exporter = generate_project_files(resources, export_path,
00284                                              target, name, toolchain, ide,
00285                                              macros=macros)
00286     if zip_proj:
00287         resources.add_features(ALLOWED_FEATURES)
00288         if isinstance(zip_proj, basestring):
00289             zip_export(join(export_path, zip_proj), name, resources,
00290                        files + list(exporter.static_files), inc_repos, notify)
00291         else:
00292             zip_export(zip_proj, name, resources,
00293                        files + list(exporter.static_files), inc_repos, notify)
00294     else:
00295         for static_file in exporter.static_files:
00296             if not exists(join(export_path, basename(static_file))):
00297                 copyfile(static_file, join(export_path, basename(static_file)))
00298 
00299     return exporter