Rtos API example

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 import sys
00019 from os.path import join, abspath, dirname, exists
00020 from os.path import basename, relpath, normpath, splitext
00021 from os import makedirs, walk
00022 import copy
00023 from shutil import rmtree, copyfile
00024 import zipfile
00025 ROOT = abspath(join(dirname(__file__), ".."))
00026 sys.path.insert(0, ROOT)
00027 
00028 from tools.build_api import prepare_toolchain
00029 from tools.build_api import scan_resources
00030 from tools.toolchains import Resources
00031 from tools.export import lpcxpresso, ds5_5, iar, makefile
00032 from tools.export import embitz, coide, kds, simplicity, atmelstudio, mcuxpresso
00033 from tools.export import sw4stm32, e2studio, zip, cmsis, uvision, cdt, vscode
00034 from tools.export import gnuarmeclipse
00035 from tools.export import qtcreator
00036 from tools.targets import TARGET_NAMES
00037 
00038 EXPORTERS = {
00039     'uvision5': uvision.Uvision,
00040     'uvision': uvision.Uvision,
00041     'lpcxpresso': lpcxpresso.LPCXpresso,
00042     'gcc_arm': makefile.GccArm,
00043     'make_gcc_arm': makefile.GccArm,
00044     'make_armc5': makefile.Armc5,
00045     'make_armc6': makefile.Armc6,
00046     'make_iar': makefile.IAR,
00047     'ds5_5': ds5_5.DS5_5,
00048     'iar': iar.IAR,
00049     'embitz' : embitz.EmBitz,
00050     'coide' : coide.CoIDE,
00051     'kds' : kds.KDS,
00052     'simplicityv3' : simplicity.SimplicityV3,
00053     'atmelstudio' : atmelstudio.AtmelStudio,
00054     'sw4stm32'    : sw4stm32.Sw4STM32,
00055     'e2studio' : e2studio.E2Studio,
00056     'eclipse_gcc_arm'  : cdt.EclipseGcc,
00057     'eclipse_iar'      : cdt.EclipseIAR,
00058     'eclipse_armc5'    : cdt.EclipseArmc5,
00059     'gnuarmeclipse': gnuarmeclipse.GNUARMEclipse,
00060     'mcuxpresso': mcuxpresso.MCUXpresso,
00061     'qtcreator': qtcreator.QtCreator,
00062     'vscode_gcc_arm' : vscode.VSCodeGcc,
00063     'vscode_iar' : vscode.VSCodeIAR,
00064     'vscode_armc5' : vscode.VSCodeArmc5
00065 }
00066 
00067 ERROR_MESSAGE_UNSUPPORTED_TOOLCHAIN = """
00068 Sorry, the target %s is not currently supported on the %s toolchain.
00069 Please refer to <a href='/handbook/Exporting-to-offline-toolchains' target='_blank'>Exporting to offline toolchains</a> for more information.
00070 """
00071 
00072 ERROR_MESSAGE_NOT_EXPORT_LIBS = """
00073 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>.
00074 """
00075 
00076 def mcu_ide_list ():
00077     """Shows list of exportable ides 
00078 
00079     """
00080     supported_ides = sorted(EXPORTERS.keys())
00081     return "\n".join(supported_ides)
00082 
00083 
00084 def mcu_ide_matrix (verbose_html=False):
00085     """Shows target map using prettytable
00086 
00087     Keyword argumets:
00088     verbose_html - print the matrix in html format
00089     """
00090     supported_ides = sorted(EXPORTERS.keys())
00091     # Only use it in this function so building works without extra modules
00092     from prettytable import PrettyTable, ALL
00093 
00094     # All tests status table print
00095     table_printer = PrettyTable(["Platform"] + supported_ides)
00096     # Align table
00097     for col in supported_ides:
00098         table_printer.align[col] = "c"
00099     table_printer.align["Platform"] = "l"
00100 
00101     perm_counter = 0
00102     for target in sorted(TARGET_NAMES):
00103         row = [target]  # First column is platform name
00104         for ide in supported_ides:
00105             text = "-"
00106             if EXPORTERS[ide].is_target_supported(target):
00107                 if verbose_html:
00108                     text = "&#10003;"
00109                 else:
00110                     text = "x"
00111                 perm_counter += 1
00112             row.append(text)
00113         table_printer.add_row(row)
00114 
00115     table_printer.border = True
00116     table_printer.vrules = ALL
00117     table_printer.hrules = ALL
00118     # creates a html page in a shorter format suitable for readme.md
00119     if verbose_html:
00120         result = table_printer.get_html_string()
00121     else:
00122         result = table_printer.get_string()
00123     result += "\n"
00124     result += "Total IDEs: %d\n"% (len(supported_ides))
00125     if verbose_html:
00126         result += "<br>"
00127     result += "Total platforms: %d\n"% (len(TARGET_NAMES))
00128     if verbose_html:
00129         result += "<br>"
00130     result += "Total permutations: %d"% (perm_counter)
00131     if verbose_html:
00132         result = result.replace("&amp;", "&")
00133     return result
00134 
00135 
00136 def get_exporter_toolchain (ide):
00137     """ Return the exporter class and the toolchain string as a tuple
00138 
00139     Positional arguments:
00140     ide - the ide name of an exporter
00141     """
00142     return EXPORTERS[ide], EXPORTERS[ide].TOOLCHAIN
00143 
00144 
00145 def rewrite_basepath (file_name, resources, export_path, loc):
00146     """ Replace the basepath of filename with export_path
00147 
00148     Positional arguments:
00149     file_name - the absolute path to a file
00150     resources - the resources object that the file came from
00151     export_path - the final destination of the file after export
00152     """
00153     new_f = join(loc, relpath(file_name, resources.file_basepath[file_name]))
00154     resources.file_basepath[new_f] = export_path
00155     return new_f
00156 
00157 
00158 def subtract_basepath (resources, export_path, loc=""):
00159     """ Rewrite all of the basepaths with the export_path
00160 
00161     Positional arguments:
00162     resources - the resource object to rewrite the basepaths of
00163     export_path - the final destination of the resources with respect to the
00164       generated project files
00165     """
00166     keys = ['s_sources', 'c_sources', 'cpp_sources', 'hex_files',
00167             'objects', 'libraries', 'inc_dirs', 'headers', 'linker_script',
00168             'lib_dirs']
00169     for key in keys:
00170         vals = getattr(resources, key)
00171         if isinstance(vals, set):
00172             vals = list(vals)
00173         if isinstance(vals, list):
00174             new_vals = []
00175             for val in vals:
00176                 new_vals.append(rewrite_basepath(val, resources, export_path,
00177                                                  loc))
00178             if isinstance(getattr(resources, key), set):
00179                 setattr(resources, key, set(new_vals))
00180             else:
00181                 setattr(resources, key, new_vals)
00182         elif vals:
00183             setattr(resources, key, rewrite_basepath(vals, resources,
00184                                                      export_path, loc))
00185 
00186 
00187 def generate_project_files (resources, export_path, target, name, toolchain, ide,
00188                            macros=None):
00189     """Generate the project files for a project
00190 
00191     Positional arguments:
00192     resources - a Resources object containing all of the files needed to build
00193       this project
00194     export_path - location to place project files
00195     name - name of the project
00196     toolchain - a toolchain class that corresponds to the toolchain used by the
00197       IDE or makefile
00198     ide - IDE name to export to
00199 
00200     Optional arguments:
00201     macros - additional macros that should be defined within the exported
00202       project
00203     """
00204     exporter_cls, _ = get_exporter_toolchain(ide)
00205     exporter = exporter_cls(target, export_path, name, toolchain,
00206                             extra_symbols=macros, resources=resources)
00207     exporter.generate()
00208     files = exporter.generated_files
00209     return files, exporter
00210 
00211 
00212 def zip_export (file_name, prefix, resources, project_files, inc_repos):
00213     """Create a zip file from an exported project.
00214 
00215     Positional Parameters:
00216     file_name - the file name of the resulting zip file
00217     prefix - a directory name that will prefix the entire zip file's contents
00218     resources - a resources object with files that must be included in the zip
00219     project_files - a list of extra files to be added to the root of the prefix
00220       directory
00221     """
00222     with zipfile.ZipFile(file_name, "w") as zip_file:
00223         for prj_file in project_files:
00224             zip_file.write(prj_file, join(prefix, basename(prj_file)))
00225         for loc, res in resources.iteritems():
00226             to_zip = (
00227                 res.headers + res.s_sources + res.c_sources +\
00228                 res.cpp_sources + res.libraries + res.hex_files + \
00229                 [res.linker_script] + res.bin_files + res.objects + \
00230                 res.json_files + res.lib_refs + res.lib_builds)
00231             if inc_repos:
00232                 for directory in res.repo_dirs:
00233                     for root, _, files in walk(directory):
00234                         for repo_file in files:
00235                             source = join(root, repo_file)
00236                             to_zip.append(source)
00237                             res.file_basepath[source] = res.base_path
00238                 to_zip += res.repo_files
00239             for source in to_zip:
00240                 if source:
00241                     zip_file.write(
00242                         source,
00243                         join(prefix, loc,
00244                              relpath(source, res.file_basepath[source])))
00245             for source in res.lib_builds:
00246                 target_dir, _ = splitext(source)
00247                 dest = join(prefix, loc,
00248                             relpath(target_dir, res.file_basepath[source]),
00249                             ".bld", "bldrc")
00250                 zip_file.write(source, dest)
00251 
00252 
00253 
00254 def export_project (src_paths, export_path, target, ide, libraries_paths=None,
00255                    linker_script=None, notify=None, verbose=False, name=None,
00256                    inc_dirs=None, jobs=1, silent=False, extra_verbose=False,
00257                    config=None, macros=None, zip_proj=None, inc_repos=False,
00258                    build_profile=None, app_config=None):
00259     """Generates a project file and creates a zip archive if specified
00260 
00261     Positional Arguments:
00262     src_paths - a list of paths from which to find source files
00263     export_path - a path specifying the location of generated project files
00264     target - the mbed board/mcu for which to generate the executable
00265     ide - the ide for which to generate the project fields
00266 
00267     Keyword Arguments:
00268     libraries_paths - paths to additional libraries
00269     linker_script - path to the linker script for the specified target
00270     notify - function is passed all events, and expected to handle notification
00271       of the user, emit the events to a log, etc.
00272     verbose - assigns the notify function to toolchains print_notify_verbose
00273     name - project name
00274     inc_dirs - additional include directories
00275     jobs - number of threads
00276     silent - silent build - no output
00277     extra_verbose - assigns the notify function to toolchains
00278       print_notify_verbose
00279     config - toolchain's config object
00280     macros - User-defined macros
00281     zip_proj - string name of the zip archive you wish to creat (exclude arg
00282      if you do not wish to create an archive
00283     """
00284 
00285     # Convert src_path to a list if needed
00286     if isinstance(src_paths, dict):
00287         paths = sum(src_paths.values(), [])
00288     elif isinstance(src_paths, list):
00289         paths = src_paths[:]
00290     else:
00291         paths = [src_paths]
00292 
00293     # Extend src_paths wit libraries_paths
00294     if libraries_paths is not None:
00295         paths.extend(libraries_paths)
00296 
00297     if not isinstance(src_paths, dict):
00298         src_paths = {"": paths}
00299 
00300     # Export Directory
00301     if not exists(export_path):
00302         makedirs(export_path)
00303 
00304     _, toolchain_name = get_exporter_toolchain(ide)
00305 
00306     # Pass all params to the unified prepare_resources()
00307     toolchain = prepare_toolchain(
00308         paths, "", target, toolchain_name, macros=macros, jobs=jobs,
00309         notify=notify, silent=silent, verbose=verbose,
00310         extra_verbose=extra_verbose, config=config, build_profile=build_profile,
00311         app_config=app_config)
00312     # The first path will give the name to the library
00313     toolchain.RESPONSE_FILES = False
00314     if name is None:
00315         name = basename(normpath(abspath(src_paths[0])))
00316 
00317     # Call unified scan_resources
00318     resource_dict = {loc: scan_resources(path, toolchain, inc_dirs=inc_dirs, collect_ignores=True)
00319                      for loc, path in src_paths.iteritems()}
00320     resources = Resources()
00321     toolchain.build_dir = export_path
00322     config_header = toolchain.get_config_header()
00323     resources.headers.append(config_header)
00324     resources.file_basepath[config_header] = dirname(config_header)
00325 
00326     if zip_proj:
00327         subtract_basepath(resources, ".")
00328         for loc, res in resource_dict.iteritems():
00329             temp = copy.deepcopy(res)
00330             subtract_basepath(temp, ".", loc)
00331             resources.add(temp)
00332     else:
00333         for _, res in resource_dict.iteritems():
00334             resources.add(res)
00335 
00336     # Change linker script if specified
00337     if linker_script is not None:
00338         resources.linker_script = linker_script
00339 
00340     files, exporter = generate_project_files(resources, export_path,
00341                                              target, name, toolchain, ide,
00342                                              macros=macros)
00343     files.append(config_header)
00344     if zip_proj:
00345         for resource in resource_dict.values():
00346             for label, res in resource.features.iteritems():
00347                 if label not in toolchain.target.features:
00348                     resource.add(res)
00349         if isinstance(zip_proj, basestring):
00350             zip_export(join(export_path, zip_proj), name, resource_dict,
00351                        files + list(exporter.static_files), inc_repos)
00352         else:
00353             zip_export(zip_proj, name, resource_dict,
00354                        files + list(exporter.static_files), inc_repos)
00355     else:
00356         for static_file in exporter.static_files:
00357             if not exists(join(export_path, basename(static_file))):
00358                 copyfile(static_file, join(export_path, basename(static_file)))
00359 
00360     return exporter