ON Semiconductor / mbed-os

Dependents:   mbed-TFT-example-NCS36510 mbed-Accelerometer-example-NCS36510 mbed-Accelerometer-example-NCS36510

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers project_api.py Source File

project_api.py

00001 """ The new way of doing exports """
00002 import sys
00003 from os.path import join, abspath, dirname, exists
00004 from os.path import basename, relpath, normpath, splitext
00005 from os import makedirs, walk
00006 ROOT = abspath(join(dirname(__file__), ".."))
00007 sys.path.insert(0, ROOT)
00008 import copy
00009 from shutil import rmtree
00010 import zipfile
00011 
00012 from tools.build_api import prepare_toolchain
00013 from tools.build_api import scan_resources
00014 from tools.export import EXPORTERS
00015 from tools.toolchains import Resources
00016 
00017 
00018 def get_exporter_toolchain (ide):
00019     """ Return the exporter class and the toolchain string as a tuple
00020 
00021     Positional arguments:
00022     ide - the ide name of an exporter
00023     """
00024     return EXPORTERS[ide], EXPORTERS[ide].TOOLCHAIN
00025 
00026 
00027 def rewrite_basepath (file_name, resources, export_path, loc):
00028     """ Replace the basepath of filename with export_path
00029 
00030     Positional arguments:
00031     file_name - the absolute path to a file
00032     resources - the resources object that the file came from
00033     export_path - the final destination of the file after export
00034     """
00035     new_f = join(loc, relpath(file_name, resources.file_basepath[file_name]))
00036     resources.file_basepath[join(export_path, new_f)] = export_path
00037     return new_f
00038 
00039 
00040 def subtract_basepath (resources, export_path, loc=""):
00041     """ Rewrite all of the basepaths with the export_path
00042 
00043     Positional arguments:
00044     resources - the resource object to rewrite the basepaths of
00045     export_path - the final destination of the resources with respect to the
00046       generated project files
00047     """
00048     keys = ['s_sources', 'c_sources', 'cpp_sources', 'hex_files',
00049             'objects', 'libraries', 'inc_dirs', 'headers', 'linker_script',
00050             'lib_dirs']
00051     for key in keys:
00052         vals = getattr(resources, key)
00053         if isinstance(vals, set):
00054             vals = list(vals)
00055         if isinstance(vals, list):
00056             new_vals = []
00057             for val in vals:
00058                 new_vals.append(rewrite_basepath(val, resources, export_path,
00059                                                  loc))
00060             if isinstance(getattr(resources, key), set):
00061                 setattr(resources, key, set(new_vals))
00062             else:
00063                 setattr(resources, key, new_vals)
00064         elif vals:
00065             setattr(resources, key, rewrite_basepath(vals, resources,
00066                                                      export_path, loc))
00067 
00068 
00069 def generate_project_files (resources, export_path, target, name, toolchain, ide,
00070                            macros=None):
00071     """Generate the project files for a project
00072 
00073     Positional arguments:
00074     resources - a Resources object containing all of the files needed to build
00075       this project
00076     export_path - location to place project files
00077     name - name of the project
00078     toolchain - a toolchain class that corresponds to the toolchain used by the
00079       IDE or makefile
00080     ide - IDE name to export to
00081 
00082     Optional arguments:
00083     macros - additional macros that should be defined within the exported
00084       project
00085     """
00086     exporter_cls, _ = get_exporter_toolchain(ide)
00087     exporter = exporter_cls(target, export_path, name, toolchain,
00088                             extra_symbols=macros, resources=resources)
00089     exporter.generate()
00090     files = exporter.generated_files
00091     return files, exporter
00092 
00093 
00094 def zip_export (file_name, prefix, resources, project_files, inc_repos):
00095     """Create a zip file from an exported project.
00096 
00097     Positional Parameters:
00098     file_name - the file name of the resulting zip file
00099     prefix - a directory name that will prefix the entire zip file's contents
00100     resources - a resources object with files that must be included in the zip
00101     project_files - a list of extra files to be added to the root of the prefix
00102       directory
00103     """
00104     with zipfile.ZipFile(file_name, "w") as zip_file:
00105         for prj_file in project_files:
00106             zip_file.write(prj_file, join(prefix, basename(prj_file)))
00107         for loc, resource in resources.iteritems():
00108             for res in [resource] + resource.features.values():
00109                 to_zip = (
00110                     res.headers + res.s_sources + res.c_sources +\
00111                     res.cpp_sources + res.libraries + res.hex_files + \
00112                     [res.linker_script] + res.bin_files + res.objects + \
00113                     res.json_files + res.lib_refs + res.lib_builds)
00114                 if inc_repos:
00115                     for directory in res.repo_dirs:
00116                         for root, _, files in walk(directory):
00117                             for repo_file in files:
00118                                 source = join(root, repo_file)
00119                                 to_zip.append(source)
00120                                 res.file_basepath[source] = res.base_path
00121                     to_zip += res.repo_files
00122                 for source in to_zip:
00123                     if source:
00124                         zip_file.write(
00125                             source,
00126                             join(prefix, loc,
00127                                  relpath(source, res.file_basepath[source])))
00128                 for source in res.lib_builds:
00129                     target_dir, _ = splitext(source)
00130                     dest = join(prefix, loc,
00131                                 relpath(target_dir, res.file_basepath[source]),
00132                                 ".bld", "bldrc")
00133                     zip_file.write(source, dest)
00134 
00135 
00136 
00137 def export_project (src_paths, export_path, target, ide, libraries_paths=None,
00138                    linker_script=None, notify=None, verbose=False, name=None,
00139                    inc_dirs=None, jobs=1, silent=False, extra_verbose=False,
00140                    config=None, macros=None, zip_proj=None, inc_repos=False,
00141                    build_profile=None):
00142     """Generates a project file and creates a zip archive if specified
00143 
00144     Positional Arguments:
00145     src_paths - a list of paths from which to find source files
00146     export_path - a path specifying the location of generated project files
00147     target - the mbed board/mcu for which to generate the executable
00148     ide - the ide for which to generate the project fields
00149 
00150     Keyword Arguments:
00151     libraries_paths - paths to additional libraries
00152     linker_script - path to the linker script for the specified target
00153     notify - function is passed all events, and expected to handle notification
00154       of the user, emit the events to a log, etc.
00155     verbose - assigns the notify function to toolchains print_notify_verbose
00156     name - project name
00157     inc_dirs - additional include directories
00158     jobs - number of threads
00159     silent - silent build - no output
00160     extra_verbose - assigns the notify function to toolchains
00161       print_notify_verbose
00162     config - toolchain's config object
00163     macros - User-defined macros
00164     zip_proj - string name of the zip archive you wish to creat (exclude arg
00165      if you do not wish to create an archive
00166     """
00167 
00168     # Convert src_path to a list if needed
00169     if isinstance(src_paths, dict):
00170         paths = sum(src_paths.values(), [])
00171     elif isinstance(src_paths, list):
00172         paths = src_paths[:]
00173     else:
00174         paths = [src_paths]
00175 
00176     # Extend src_paths wit libraries_paths
00177     if libraries_paths is not None:
00178         paths.extend(libraries_paths)
00179 
00180     if not isinstance(src_paths, dict):
00181         src_paths = {"": paths}
00182 
00183     # Export Directory
00184     if not exists(export_path):
00185         makedirs(export_path)
00186 
00187     _, toolchain_name = get_exporter_toolchain(ide)
00188 
00189     # Pass all params to the unified prepare_resources()
00190     toolchain = prepare_toolchain(paths, target, toolchain_name, macros=macros,
00191                                   jobs=jobs, notify=notify, silent=silent,
00192                                   verbose=verbose, extra_verbose=extra_verbose,
00193                                   config=config, build_profile=build_profile)
00194     # The first path will give the name to the library
00195     if name is None:
00196         name = basename(normpath(abspath(src_paths[0])))
00197 
00198     # Call unified scan_resources
00199     resource_dict = {loc: scan_resources(path, toolchain, inc_dirs=inc_dirs)
00200                      for loc, path in src_paths.iteritems()}
00201     resources = Resources()
00202     toolchain.build_dir = export_path
00203     config_header = toolchain.get_config_header()
00204     resources.headers.append(config_header)
00205     resources.file_basepath[config_header] = dirname(config_header)
00206 
00207     if zip_proj:
00208         subtract_basepath(resources, export_path)
00209         for loc, res in resource_dict.iteritems():
00210             temp = copy.deepcopy(res)
00211             subtract_basepath(temp, export_path, loc)
00212             resources.add(temp)
00213     else:
00214         for _, res in resource_dict.iteritems():
00215             resources.add(res)
00216 
00217     # Change linker script if specified
00218     if linker_script is not None:
00219         resources.linker_script = linker_script
00220 
00221     files, exporter = generate_project_files(resources, export_path,
00222                                              target, name, toolchain, ide,
00223                                              macros=macros)
00224     files.append(config_header)
00225     if zip_proj:
00226         if isinstance(zip_proj, basestring):
00227             zip_export(join(export_path, zip_proj), name, resource_dict, files, inc_repos)
00228         else:
00229             zip_export(zip_proj, name, resource_dict, files, inc_repos)
00230 
00231     return exporter
00232 
00233 
00234 def print_results (successes, failures, skips=None):
00235     """ Print out the results of an export process
00236 
00237     Positional arguments:
00238     successes - The list of exports that succeeded
00239     failures - The list of exports that failed
00240 
00241     Keyword arguments:
00242     skips - The list of exports that were skipped
00243     """
00244     print
00245     if successes:
00246         print "Successful: "
00247         for success in successes:
00248             print "  * %s" % success
00249     if failures:
00250         print "Failed: "
00251         for failure in failures:
00252             print "  * %s" % failure
00253     if skips:
00254         print "Skipped: "
00255         for skip in skips:
00256             print "  * %s" % skip
00257