joey shelton / LED_Demo

Dependencies:   MAX44000 PWM_Tone_Library nexpaq_mdk

Fork of LED_Demo by Maxim nexpaq

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
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):
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             print resource.features
00109             for res in [resource] + resource.features.values():
00110                 extras = []
00111                 for directory in res.repo_dirs:
00112                     for root, _, files in walk(directory):
00113                         for repo_file in files:
00114                             source = join(root, repo_file)
00115                             extras.append(source)
00116                             res.file_basepath[source] = res.base_path
00117                 for source in \
00118                     res.headers + res.s_sources + res.c_sources +\
00119                     res.cpp_sources + res.libraries + res.hex_files + \
00120                     [res.linker_script] + res.bin_files + res.objects + \
00121                     res.json_files + res.lib_refs + res.lib_builds + \
00122                     res.repo_files + extras:
00123                     if source:
00124                         zip_file.write(
00125                             source,
00126                             join(prefix, loc,
00127                                  relpath(source, res.file_basepath[source])))
00128 
00129 
00130 
00131 def export_project (src_paths, export_path, target, ide,
00132                    libraries_paths=None, options=None, linker_script=None,
00133                    clean=False, notify=None, verbose=False, name=None,
00134                    inc_dirs=None, jobs=1, silent=False, extra_verbose=False,
00135                    config=None, macros=None, zip_proj=None):
00136     """Generates a project file and creates a zip archive if specified
00137 
00138     Positional Arguments:
00139     src_paths - a list of paths from which to find source files
00140     export_path - a path specifying the location of generated project files
00141     target - the mbed board/mcu for which to generate the executable
00142     ide - the ide for which to generate the project fields
00143 
00144     Keyword Arguments:
00145     libraries_paths - paths to additional libraries
00146     options - build options passed by -o flag
00147     linker_script - path to the linker script for the specified target
00148     clean - removes the export_path if it exists
00149     notify - function is passed all events, and expected to handle notification
00150       of the user, emit the events to a log, etc.
00151     verbose - assigns the notify function to toolchains print_notify_verbose
00152     name - project name
00153     inc_dirs - additional include directories
00154     jobs - number of threads
00155     silent - silent build - no output
00156     extra_verbose - assigns the notify function to toolchains
00157       print_notify_verbose
00158     config - toolchain's config object
00159     macros - User-defined macros
00160     zip_proj - string name of the zip archive you wish to creat (exclude arg
00161      if you do not wish to create an archive
00162     """
00163 
00164     # Convert src_path to a list if needed
00165     if isinstance(src_paths, dict):
00166         paths = sum(src_paths.values(), [])
00167     elif isinstance(src_paths, list):
00168         paths = src_paths[:]
00169     else:
00170         paths = [src_paths]
00171 
00172     # Extend src_paths wit libraries_paths
00173     if libraries_paths is not None:
00174         paths.extend(libraries_paths)
00175 
00176     if not isinstance(src_paths, dict):
00177         src_paths = {"": paths}
00178 
00179     # Export Directory
00180     if exists(export_path) and clean:
00181         rmtree(export_path)
00182     if not exists(export_path):
00183         makedirs(export_path)
00184 
00185     _, toolchain_name = get_exporter_toolchain(ide)
00186 
00187     # Pass all params to the unified prepare_resources()
00188     toolchain = prepare_toolchain(paths, target, toolchain_name,
00189                                   macros=macros, options=options, clean=clean,
00190                                   jobs=jobs, notify=notify, silent=silent,
00191                                   verbose=verbose, extra_verbose=extra_verbose,
00192                                   config=config)
00193     # The first path will give the name to the library
00194     if name is None:
00195         name = basename(normpath(abspath(src_paths[0])))
00196 
00197     # Call unified scan_resources
00198     resource_dict = {loc: scan_resources(path, toolchain, inc_dirs=inc_dirs)
00199                      for loc, path in src_paths.iteritems()}
00200     resources = Resources()
00201     toolchain.build_dir = export_path
00202     config_header = toolchain.get_config_header()
00203     resources.headers.append(config_header)
00204     resources.file_basepath[config_header] = dirname(config_header)
00205 
00206     if zip_proj:
00207         subtract_basepath(resources, export_path)
00208         for loc, res in resource_dict.iteritems():
00209             temp = copy.deepcopy(res)
00210             subtract_basepath(temp, export_path, loc)
00211             resources.add(temp)
00212     else:
00213         for _, res in resource_dict.iteritems():
00214             resources.add(res)
00215 
00216     # Change linker script if specified
00217     if linker_script is not None:
00218         resources.linker_script = linker_script
00219 
00220     files, exporter = generate_project_files(resources, export_path,
00221                                              target, name, toolchain, ide,
00222                                              macros=macros)
00223     files.append(config_header)
00224     if zip_proj:
00225         if isinstance(zip_proj, basestring):
00226             zip_export(join(export_path, zip_proj), name, resource_dict, files)
00227         else:
00228             zip_export(zip_proj, name, resource_dict, files)
00229 
00230     return exporter
00231 
00232 
00233 def print_results (successes, failures, skips=None):
00234     """ Print out the results of an export process
00235 
00236     Positional arguments:
00237     successes - The list of exports that succeeded
00238     failures - The list of exports that failed
00239 
00240     Keyword arguments:
00241     skips - The list of exports that were skipped
00242     """
00243     print
00244     if successes:
00245         print "Successful: "
00246         for success in successes:
00247             print "  * %s" % success
00248     if failures:
00249         print "Failed: "
00250         for failure in failures:
00251             print "  * %s" % failure
00252     if skips:
00253         print "Skipped: "
00254         for skip in skips:
00255             print "  * %s" % skip
00256