Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of mbed-sdk-tools by
project_api.py@31:182518299918, 2017-01-04 (annotated)
- 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?
User | Revision | Line number | New 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 | |
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 |