the other jimmy / mbed-sdk-tools

Fork of mbed-sdk-tools by mbed official

Committer:
The Other Jimmy
Date:
Wed Jan 04 11:58:24 2017 -0600
Revision:
31:182518299918
Parent:
26:ed5e0d4e691e
Update tools to follow mbed-os tools release 5.3.1

Who changed what in which revision?

UserRevisionLine numberNew contents of line
The Other Jimmy 31:182518299918 1 """ The new way of doing exports """
screamer 26:ed5e0d4e691e 2 import sys
The Other Jimmy 31:182518299918 3 from os.path import join, abspath, dirname, exists
The Other Jimmy 31:182518299918 4 from os.path import basename, relpath, normpath, splitext
The Other Jimmy 31:182518299918 5 from os import makedirs, walk
screamer 26:ed5e0d4e691e 6 ROOT = abspath(join(dirname(__file__), ".."))
screamer 26:ed5e0d4e691e 7 sys.path.insert(0, ROOT)
The Other Jimmy 31:182518299918 8 import copy
The Other Jimmy 31:182518299918 9 from shutil import rmtree
The Other Jimmy 31:182518299918 10 import zipfile
screamer 26:ed5e0d4e691e 11
The Other Jimmy 31:182518299918 12 from tools.build_api import prepare_toolchain
The Other Jimmy 31:182518299918 13 from tools.build_api import scan_resources
The Other Jimmy 31:182518299918 14 from tools.export import EXPORTERS
The Other Jimmy 31:182518299918 15 from tools.toolchains import Resources
The Other Jimmy 31:182518299918 16
The Other Jimmy 31:182518299918 17
The Other Jimmy 31:182518299918 18 def get_exporter_toolchain(ide):
The Other Jimmy 31:182518299918 19 """ Return the exporter class and the toolchain string as a tuple
screamer 26:ed5e0d4e691e 20
The Other Jimmy 31:182518299918 21 Positional arguments:
The Other Jimmy 31:182518299918 22 ide - the ide name of an exporter
The Other Jimmy 31:182518299918 23 """
The Other Jimmy 31:182518299918 24 return EXPORTERS[ide], EXPORTERS[ide].TOOLCHAIN
The Other Jimmy 31:182518299918 25
The Other Jimmy 31:182518299918 26
The Other Jimmy 31:182518299918 27 def rewrite_basepath(file_name, resources, export_path, loc):
The Other Jimmy 31:182518299918 28 """ Replace the basepath of filename with export_path
The Other Jimmy 31:182518299918 29
The Other Jimmy 31:182518299918 30 Positional arguments:
The Other Jimmy 31:182518299918 31 file_name - the absolute path to a file
The Other Jimmy 31:182518299918 32 resources - the resources object that the file came from
The Other Jimmy 31:182518299918 33 export_path - the final destination of the file after export
The Other Jimmy 31:182518299918 34 """
The Other Jimmy 31:182518299918 35 new_f = join(loc, relpath(file_name, resources.file_basepath[file_name]))
The Other Jimmy 31:182518299918 36 resources.file_basepath[join(export_path, new_f)] = export_path
The Other Jimmy 31:182518299918 37 return new_f
screamer 26:ed5e0d4e691e 38
screamer 26:ed5e0d4e691e 39
The Other Jimmy 31:182518299918 40 def subtract_basepath(resources, export_path, loc=""):
The Other Jimmy 31:182518299918 41 """ Rewrite all of the basepaths with the export_path
screamer 26:ed5e0d4e691e 42
The Other Jimmy 31:182518299918 43 Positional arguments:
The Other Jimmy 31:182518299918 44 resources - the resource object to rewrite the basepaths of
The Other Jimmy 31:182518299918 45 export_path - the final destination of the resources with respect to the
The Other Jimmy 31:182518299918 46 generated project files
The Other Jimmy 31:182518299918 47 """
The Other Jimmy 31:182518299918 48 keys = ['s_sources', 'c_sources', 'cpp_sources', 'hex_files',
The Other Jimmy 31:182518299918 49 'objects', 'libraries', 'inc_dirs', 'headers', 'linker_script',
The Other Jimmy 31:182518299918 50 'lib_dirs']
The Other Jimmy 31:182518299918 51 for key in keys:
The Other Jimmy 31:182518299918 52 vals = getattr(resources, key)
The Other Jimmy 31:182518299918 53 if isinstance(vals, set):
The Other Jimmy 31:182518299918 54 vals = list(vals)
The Other Jimmy 31:182518299918 55 if isinstance(vals, list):
The Other Jimmy 31:182518299918 56 new_vals = []
The Other Jimmy 31:182518299918 57 for val in vals:
The Other Jimmy 31:182518299918 58 new_vals.append(rewrite_basepath(val, resources, export_path,
The Other Jimmy 31:182518299918 59 loc))
The Other Jimmy 31:182518299918 60 if isinstance(getattr(resources, key), set):
The Other Jimmy 31:182518299918 61 setattr(resources, key, set(new_vals))
The Other Jimmy 31:182518299918 62 else:
The Other Jimmy 31:182518299918 63 setattr(resources, key, new_vals)
The Other Jimmy 31:182518299918 64 elif vals:
The Other Jimmy 31:182518299918 65 setattr(resources, key, rewrite_basepath(vals, resources,
The Other Jimmy 31:182518299918 66 export_path, loc))
screamer 26:ed5e0d4e691e 67
screamer 26:ed5e0d4e691e 68
The Other Jimmy 31:182518299918 69 def generate_project_files(resources, export_path, target, name, toolchain, ide,
The Other Jimmy 31:182518299918 70 macros=None):
The Other Jimmy 31:182518299918 71 """Generate the project files for a project
The Other Jimmy 31:182518299918 72
The Other Jimmy 31:182518299918 73 Positional arguments:
The Other Jimmy 31:182518299918 74 resources - a Resources object containing all of the files needed to build
The Other Jimmy 31:182518299918 75 this project
The Other Jimmy 31:182518299918 76 export_path - location to place project files
The Other Jimmy 31:182518299918 77 name - name of the project
The Other Jimmy 31:182518299918 78 toolchain - a toolchain class that corresponds to the toolchain used by the
The Other Jimmy 31:182518299918 79 IDE or makefile
The Other Jimmy 31:182518299918 80 ide - IDE name to export to
The Other Jimmy 31:182518299918 81
The Other Jimmy 31:182518299918 82 Optional arguments:
The Other Jimmy 31:182518299918 83 macros - additional macros that should be defined within the exported
The Other Jimmy 31:182518299918 84 project
The Other Jimmy 31:182518299918 85 """
The Other Jimmy 31:182518299918 86 exporter_cls, _ = get_exporter_toolchain(ide)
The Other Jimmy 31:182518299918 87 exporter = exporter_cls(target, export_path, name, toolchain,
The Other Jimmy 31:182518299918 88 extra_symbols=macros, resources=resources)
The Other Jimmy 31:182518299918 89 exporter.generate()
The Other Jimmy 31:182518299918 90 files = exporter.generated_files
The Other Jimmy 31:182518299918 91 return files, exporter
screamer 26:ed5e0d4e691e 92
screamer 26:ed5e0d4e691e 93
The Other Jimmy 31:182518299918 94 def zip_export(file_name, prefix, resources, project_files, inc_repos):
The Other Jimmy 31:182518299918 95 """Create a zip file from an exported project.
The Other Jimmy 31:182518299918 96
The Other Jimmy 31:182518299918 97 Positional Parameters:
The Other Jimmy 31:182518299918 98 file_name - the file name of the resulting zip file
The Other Jimmy 31:182518299918 99 prefix - a directory name that will prefix the entire zip file's contents
The Other Jimmy 31:182518299918 100 resources - a resources object with files that must be included in the zip
The Other Jimmy 31:182518299918 101 project_files - a list of extra files to be added to the root of the prefix
The Other Jimmy 31:182518299918 102 directory
The Other Jimmy 31:182518299918 103 """
The Other Jimmy 31:182518299918 104 with zipfile.ZipFile(file_name, "w") as zip_file:
The Other Jimmy 31:182518299918 105 for prj_file in project_files:
The Other Jimmy 31:182518299918 106 zip_file.write(prj_file, join(prefix, basename(prj_file)))
The Other Jimmy 31:182518299918 107 for loc, resource in resources.iteritems():
The Other Jimmy 31:182518299918 108 for res in [resource] + resource.features.values():
The Other Jimmy 31:182518299918 109 to_zip = (
The Other Jimmy 31:182518299918 110 res.headers + res.s_sources + res.c_sources +\
The Other Jimmy 31:182518299918 111 res.cpp_sources + res.libraries + res.hex_files + \
The Other Jimmy 31:182518299918 112 [res.linker_script] + res.bin_files + res.objects + \
The Other Jimmy 31:182518299918 113 res.json_files + res.lib_refs + res.lib_builds)
The Other Jimmy 31:182518299918 114 if inc_repos:
The Other Jimmy 31:182518299918 115 for directory in res.repo_dirs:
The Other Jimmy 31:182518299918 116 for root, _, files in walk(directory):
The Other Jimmy 31:182518299918 117 for repo_file in files:
The Other Jimmy 31:182518299918 118 source = join(root, repo_file)
The Other Jimmy 31:182518299918 119 to_zip.append(source)
The Other Jimmy 31:182518299918 120 res.file_basepath[source] = res.base_path
The Other Jimmy 31:182518299918 121 to_zip += res.repo_files
The Other Jimmy 31:182518299918 122 for source in to_zip:
The Other Jimmy 31:182518299918 123 if source:
The Other Jimmy 31:182518299918 124 zip_file.write(
The Other Jimmy 31:182518299918 125 source,
The Other Jimmy 31:182518299918 126 join(prefix, loc,
The Other Jimmy 31:182518299918 127 relpath(source, res.file_basepath[source])))
The Other Jimmy 31:182518299918 128 for source in res.lib_builds:
The Other Jimmy 31:182518299918 129 target_dir, _ = splitext(source)
The Other Jimmy 31:182518299918 130 dest = join(prefix, loc,
The Other Jimmy 31:182518299918 131 relpath(target_dir, res.file_basepath[source]),
The Other Jimmy 31:182518299918 132 ".bld", "bldrc")
The Other Jimmy 31:182518299918 133 zip_file.write(source, dest)
The Other Jimmy 31:182518299918 134
screamer 26:ed5e0d4e691e 135
screamer 26:ed5e0d4e691e 136
The Other Jimmy 31:182518299918 137 def export_project(src_paths, export_path, target, ide,
The Other Jimmy 31:182518299918 138 libraries_paths=None, linker_script=None, clean=False,
The Other Jimmy 31:182518299918 139 notify=None, verbose=False, name=None, inc_dirs=None,
The Other Jimmy 31:182518299918 140 jobs=1, silent=False, extra_verbose=False, config=None,
The Other Jimmy 31:182518299918 141 macros=None, zip_proj=None, inc_repos=False,
The Other Jimmy 31:182518299918 142 build_profile=None):
The Other Jimmy 31:182518299918 143 """Generates a project file and creates a zip archive if specified
The Other Jimmy 31:182518299918 144
The Other Jimmy 31:182518299918 145 Positional Arguments:
The Other Jimmy 31:182518299918 146 src_paths - a list of paths from which to find source files
The Other Jimmy 31:182518299918 147 export_path - a path specifying the location of generated project files
The Other Jimmy 31:182518299918 148 target - the mbed board/mcu for which to generate the executable
The Other Jimmy 31:182518299918 149 ide - the ide for which to generate the project fields
screamer 26:ed5e0d4e691e 150
The Other Jimmy 31:182518299918 151 Keyword Arguments:
The Other Jimmy 31:182518299918 152 libraries_paths - paths to additional libraries
The Other Jimmy 31:182518299918 153 linker_script - path to the linker script for the specified target
The Other Jimmy 31:182518299918 154 clean - removes the export_path if it exists
The Other Jimmy 31:182518299918 155 notify - function is passed all events, and expected to handle notification
The Other Jimmy 31:182518299918 156 of the user, emit the events to a log, etc.
The Other Jimmy 31:182518299918 157 verbose - assigns the notify function to toolchains print_notify_verbose
The Other Jimmy 31:182518299918 158 name - project name
The Other Jimmy 31:182518299918 159 inc_dirs - additional include directories
The Other Jimmy 31:182518299918 160 jobs - number of threads
The Other Jimmy 31:182518299918 161 silent - silent build - no output
The Other Jimmy 31:182518299918 162 extra_verbose - assigns the notify function to toolchains
The Other Jimmy 31:182518299918 163 print_notify_verbose
The Other Jimmy 31:182518299918 164 config - toolchain's config object
The Other Jimmy 31:182518299918 165 macros - User-defined macros
The Other Jimmy 31:182518299918 166 zip_proj - string name of the zip archive you wish to creat (exclude arg
The Other Jimmy 31:182518299918 167 if you do not wish to create an archive
The Other Jimmy 31:182518299918 168 """
The Other Jimmy 31:182518299918 169
The Other Jimmy 31:182518299918 170 # Convert src_path to a list if needed
The Other Jimmy 31:182518299918 171 if isinstance(src_paths, dict):
The Other Jimmy 31:182518299918 172 paths = sum(src_paths.values(), [])
The Other Jimmy 31:182518299918 173 elif isinstance(src_paths, list):
The Other Jimmy 31:182518299918 174 paths = src_paths[:]
screamer 26:ed5e0d4e691e 175 else:
The Other Jimmy 31:182518299918 176 paths = [src_paths]
The Other Jimmy 31:182518299918 177
The Other Jimmy 31:182518299918 178 # Extend src_paths wit libraries_paths
The Other Jimmy 31:182518299918 179 if libraries_paths is not None:
The Other Jimmy 31:182518299918 180 paths.extend(libraries_paths)
The Other Jimmy 31:182518299918 181
The Other Jimmy 31:182518299918 182 if not isinstance(src_paths, dict):
The Other Jimmy 31:182518299918 183 src_paths = {"": paths}
The Other Jimmy 31:182518299918 184
The Other Jimmy 31:182518299918 185 # Export Directory
The Other Jimmy 31:182518299918 186 if exists(export_path) and clean:
The Other Jimmy 31:182518299918 187 rmtree(export_path)
The Other Jimmy 31:182518299918 188 if not exists(export_path):
The Other Jimmy 31:182518299918 189 makedirs(export_path)
The Other Jimmy 31:182518299918 190
The Other Jimmy 31:182518299918 191 _, toolchain_name = get_exporter_toolchain(ide)
The Other Jimmy 31:182518299918 192
The Other Jimmy 31:182518299918 193 # Pass all params to the unified prepare_resources()
The Other Jimmy 31:182518299918 194 toolchain = prepare_toolchain(paths, target, toolchain_name,
The Other Jimmy 31:182518299918 195 macros=macros, clean=clean, jobs=jobs,
The Other Jimmy 31:182518299918 196 notify=notify, silent=silent, verbose=verbose,
The Other Jimmy 31:182518299918 197 extra_verbose=extra_verbose, config=config,
The Other Jimmy 31:182518299918 198 build_profile=build_profile)
The Other Jimmy 31:182518299918 199 try:
The Other Jimmy 31:182518299918 200 # The first path will give the name to the library
The Other Jimmy 31:182518299918 201 if name is None:
The Other Jimmy 31:182518299918 202 name = basename(normpath(abspath(src_paths[0])))
screamer 26:ed5e0d4e691e 203
The Other Jimmy 31:182518299918 204 # Call unified scan_resources
The Other Jimmy 31:182518299918 205 resource_dict = {loc: scan_resources(path, toolchain, inc_dirs=inc_dirs)
The Other Jimmy 31:182518299918 206 for loc, path in src_paths.iteritems()}
The Other Jimmy 31:182518299918 207 resources = Resources()
The Other Jimmy 31:182518299918 208 toolchain.build_dir = export_path
The Other Jimmy 31:182518299918 209 config_header = toolchain.get_config_header()
The Other Jimmy 31:182518299918 210 resources.headers.append(config_header)
The Other Jimmy 31:182518299918 211 resources.file_basepath[config_header] = dirname(config_header)
screamer 26:ed5e0d4e691e 212
The Other Jimmy 31:182518299918 213 if zip_proj:
The Other Jimmy 31:182518299918 214 subtract_basepath(resources, export_path)
The Other Jimmy 31:182518299918 215 for loc, res in resource_dict.iteritems():
The Other Jimmy 31:182518299918 216 temp = copy.deepcopy(res)
The Other Jimmy 31:182518299918 217 subtract_basepath(temp, export_path, loc)
The Other Jimmy 31:182518299918 218 resources.add(temp)
The Other Jimmy 31:182518299918 219 else:
The Other Jimmy 31:182518299918 220 for _, res in resource_dict.iteritems():
The Other Jimmy 31:182518299918 221 resources.add(res)
The Other Jimmy 31:182518299918 222
The Other Jimmy 31:182518299918 223 # Change linker script if specified
The Other Jimmy 31:182518299918 224 if linker_script is not None:
The Other Jimmy 31:182518299918 225 resources.linker_script = linker_script
The Other Jimmy 31:182518299918 226
The Other Jimmy 31:182518299918 227 files, exporter = generate_project_files(resources, export_path,
The Other Jimmy 31:182518299918 228 target, name, toolchain, ide,
The Other Jimmy 31:182518299918 229 macros=macros)
The Other Jimmy 31:182518299918 230 files.append(config_header)
The Other Jimmy 31:182518299918 231 if zip_proj:
The Other Jimmy 31:182518299918 232 if isinstance(zip_proj, basestring):
The Other Jimmy 31:182518299918 233 zip_export(join(export_path, zip_proj), name, resource_dict, files, inc_repos)
The Other Jimmy 31:182518299918 234 else:
The Other Jimmy 31:182518299918 235 zip_export(zip_proj, name, resource_dict, files, inc_repos)
The Other Jimmy 31:182518299918 236
The Other Jimmy 31:182518299918 237 return exporter
The Other Jimmy 31:182518299918 238 except Exception as e:
The Other Jimmy 31:182518299918 239 toolchain.tool_error(str(e))
screamer 26:ed5e0d4e691e 240
screamer 26:ed5e0d4e691e 241
The Other Jimmy 31:182518299918 242 def print_results(successes, failures, skips=None):
The Other Jimmy 31:182518299918 243 """ Print out the results of an export process
screamer 26:ed5e0d4e691e 244
The Other Jimmy 31:182518299918 245 Positional arguments:
The Other Jimmy 31:182518299918 246 successes - The list of exports that succeeded
The Other Jimmy 31:182518299918 247 failures - The list of exports that failed
screamer 26:ed5e0d4e691e 248
The Other Jimmy 31:182518299918 249 Keyword arguments:
The Other Jimmy 31:182518299918 250 skips - The list of exports that were skipped
The Other Jimmy 31:182518299918 251 """
screamer 26:ed5e0d4e691e 252 print
The Other Jimmy 31:182518299918 253 if successes:
screamer 26:ed5e0d4e691e 254 print "Successful: "
screamer 26:ed5e0d4e691e 255 for success in successes:
screamer 26:ed5e0d4e691e 256 print " * %s" % success
The Other Jimmy 31:182518299918 257 if failures:
screamer 26:ed5e0d4e691e 258 print "Failed: "
screamer 26:ed5e0d4e691e 259 for failure in failures:
screamer 26:ed5e0d4e691e 260 print " * %s" % failure
The Other Jimmy 31:182518299918 261 if skips:
screamer 26:ed5e0d4e691e 262 print "Skipped: "
screamer 26:ed5e0d4e691e 263 for skip in skips:
screamer 26:ed5e0d4e691e 264 print " * %s" % skip
screamer 26:ed5e0d4e691e 265