Clone of official tools
project.py@13:ab47a20b66f0, 2016-07-14 (annotated)
- Committer:
- screamer
- Date:
- Thu Jul 14 20:21:19 2016 +0100
- Revision:
- 13:ab47a20b66f0
- Parent:
- 0:66f3b5499f7f
- Child:
- 22:9e85236d8716
Apply latest tools
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
screamer | 0:66f3b5499f7f | 1 | import sys |
screamer | 0:66f3b5499f7f | 2 | from os.path import join, abspath, dirname, exists, basename |
screamer | 0:66f3b5499f7f | 3 | ROOT = abspath(join(dirname(__file__), "..")) |
screamer | 0:66f3b5499f7f | 4 | sys.path.insert(0, ROOT) |
screamer | 0:66f3b5499f7f | 5 | |
screamer | 0:66f3b5499f7f | 6 | from shutil import move, rmtree |
screamer | 0:66f3b5499f7f | 7 | from optparse import OptionParser |
screamer | 0:66f3b5499f7f | 8 | from os import path |
screamer | 0:66f3b5499f7f | 9 | |
screamer | 0:66f3b5499f7f | 10 | from tools.paths import EXPORT_DIR, EXPORT_WORKSPACE, EXPORT_TMP |
screamer | 0:66f3b5499f7f | 11 | from tools.paths import MBED_BASE, MBED_LIBRARIES |
screamer | 0:66f3b5499f7f | 12 | from tools.export import export, setup_user_prj, EXPORTERS, mcu_ide_matrix |
screamer | 0:66f3b5499f7f | 13 | from tools.utils import args_error, mkdir |
screamer | 0:66f3b5499f7f | 14 | from tools.tests import TESTS, Test, TEST_MAP |
screamer | 0:66f3b5499f7f | 15 | from tools.targets import TARGET_NAMES |
screamer | 0:66f3b5499f7f | 16 | from tools.libraries import LIBRARIES |
screamer | 0:66f3b5499f7f | 17 | |
screamer | 0:66f3b5499f7f | 18 | try: |
screamer | 0:66f3b5499f7f | 19 | import tools.private_settings as ps |
screamer | 0:66f3b5499f7f | 20 | except: |
screamer | 0:66f3b5499f7f | 21 | ps = object() |
screamer | 0:66f3b5499f7f | 22 | |
screamer | 0:66f3b5499f7f | 23 | |
screamer | 0:66f3b5499f7f | 24 | if __name__ == '__main__': |
screamer | 0:66f3b5499f7f | 25 | # Parse Options |
screamer | 0:66f3b5499f7f | 26 | parser = OptionParser() |
screamer | 0:66f3b5499f7f | 27 | |
screamer | 0:66f3b5499f7f | 28 | targetnames = TARGET_NAMES |
screamer | 0:66f3b5499f7f | 29 | targetnames.sort() |
screamer | 0:66f3b5499f7f | 30 | toolchainlist = EXPORTERS.keys() |
screamer | 0:66f3b5499f7f | 31 | toolchainlist.sort() |
screamer | 0:66f3b5499f7f | 32 | |
screamer | 0:66f3b5499f7f | 33 | parser.add_option("-m", "--mcu", |
screamer | 0:66f3b5499f7f | 34 | metavar="MCU", |
screamer | 0:66f3b5499f7f | 35 | default='LPC1768', |
screamer | 0:66f3b5499f7f | 36 | help="generate project for the given MCU (%s)"% ', '.join(targetnames)) |
screamer | 0:66f3b5499f7f | 37 | |
screamer | 0:66f3b5499f7f | 38 | parser.add_option("-i", |
screamer | 0:66f3b5499f7f | 39 | dest="ide", |
screamer | 0:66f3b5499f7f | 40 | default='uvision', |
screamer | 0:66f3b5499f7f | 41 | help="The target IDE: %s"% str(toolchainlist)) |
screamer | 0:66f3b5499f7f | 42 | |
screamer | 0:66f3b5499f7f | 43 | parser.add_option("-c", "--clean", |
screamer | 0:66f3b5499f7f | 44 | action="store_true", |
screamer | 0:66f3b5499f7f | 45 | default=False, |
screamer | 0:66f3b5499f7f | 46 | help="clean the export directory") |
screamer | 0:66f3b5499f7f | 47 | |
screamer | 0:66f3b5499f7f | 48 | parser.add_option("-p", |
screamer | 0:66f3b5499f7f | 49 | type="int", |
screamer | 0:66f3b5499f7f | 50 | dest="program", |
screamer | 0:66f3b5499f7f | 51 | help="The index of the desired test program: [0-%d]"% (len(TESTS)-1)) |
screamer | 0:66f3b5499f7f | 52 | |
screamer | 0:66f3b5499f7f | 53 | parser.add_option("-n", |
screamer | 0:66f3b5499f7f | 54 | dest="program_name", |
screamer | 0:66f3b5499f7f | 55 | help="The name of the desired test program") |
screamer | 0:66f3b5499f7f | 56 | |
screamer | 0:66f3b5499f7f | 57 | parser.add_option("-b", |
screamer | 0:66f3b5499f7f | 58 | dest="build", |
screamer | 0:66f3b5499f7f | 59 | action="store_true", |
screamer | 0:66f3b5499f7f | 60 | default=False, |
screamer | 0:66f3b5499f7f | 61 | help="use the mbed library build, instead of the sources") |
screamer | 0:66f3b5499f7f | 62 | |
screamer | 0:66f3b5499f7f | 63 | parser.add_option("-L", "--list-tests", |
screamer | 0:66f3b5499f7f | 64 | action="store_true", |
screamer | 0:66f3b5499f7f | 65 | dest="list_tests", |
screamer | 0:66f3b5499f7f | 66 | default=False, |
screamer | 0:66f3b5499f7f | 67 | help="list available programs in order and exit") |
screamer | 0:66f3b5499f7f | 68 | |
screamer | 0:66f3b5499f7f | 69 | parser.add_option("-S", "--list-matrix", |
screamer | 0:66f3b5499f7f | 70 | action="store_true", |
screamer | 0:66f3b5499f7f | 71 | dest="supported_ides", |
screamer | 0:66f3b5499f7f | 72 | default=False, |
screamer | 0:66f3b5499f7f | 73 | help="displays supported matrix of MCUs and IDEs") |
screamer | 0:66f3b5499f7f | 74 | |
screamer | 0:66f3b5499f7f | 75 | parser.add_option("-E", |
screamer | 0:66f3b5499f7f | 76 | action="store_true", |
screamer | 0:66f3b5499f7f | 77 | dest="supported_ides_html", |
screamer | 0:66f3b5499f7f | 78 | default=False, |
screamer | 0:66f3b5499f7f | 79 | help="writes tools/export/README.md") |
screamer | 0:66f3b5499f7f | 80 | |
screamer | 0:66f3b5499f7f | 81 | parser.add_option("--source", |
screamer | 13:ab47a20b66f0 | 82 | action="append", |
screamer | 0:66f3b5499f7f | 83 | dest="source_dir", |
screamer | 0:66f3b5499f7f | 84 | default=None, |
screamer | 0:66f3b5499f7f | 85 | help="The source (input) directory") |
screamer | 0:66f3b5499f7f | 86 | |
screamer | 0:66f3b5499f7f | 87 | parser.add_option("-D", "", |
screamer | 0:66f3b5499f7f | 88 | action="append", |
screamer | 0:66f3b5499f7f | 89 | dest="macros", |
screamer | 0:66f3b5499f7f | 90 | help="Add a macro definition") |
screamer | 0:66f3b5499f7f | 91 | |
screamer | 0:66f3b5499f7f | 92 | (options, args) = parser.parse_args() |
screamer | 0:66f3b5499f7f | 93 | |
screamer | 0:66f3b5499f7f | 94 | # Print available tests in order and exit |
screamer | 0:66f3b5499f7f | 95 | if options.list_tests is True: |
screamer | 0:66f3b5499f7f | 96 | print '\n'.join(map(str, sorted(TEST_MAP.values()))) |
screamer | 0:66f3b5499f7f | 97 | sys.exit() |
screamer | 0:66f3b5499f7f | 98 | |
screamer | 0:66f3b5499f7f | 99 | # Only prints matrix of supported IDEs |
screamer | 0:66f3b5499f7f | 100 | if options.supported_ides: |
screamer | 0:66f3b5499f7f | 101 | print mcu_ide_matrix() |
screamer | 0:66f3b5499f7f | 102 | exit(0) |
screamer | 0:66f3b5499f7f | 103 | |
screamer | 0:66f3b5499f7f | 104 | # Only prints matrix of supported IDEs |
screamer | 0:66f3b5499f7f | 105 | if options.supported_ides_html: |
screamer | 0:66f3b5499f7f | 106 | html = mcu_ide_matrix(verbose_html=True) |
screamer | 0:66f3b5499f7f | 107 | try: |
screamer | 0:66f3b5499f7f | 108 | with open("./export/README.md","w") as f: |
screamer | 0:66f3b5499f7f | 109 | f.write("Exporter IDE/Platform Support\n") |
screamer | 0:66f3b5499f7f | 110 | f.write("-----------------------------------\n") |
screamer | 0:66f3b5499f7f | 111 | f.write("\n") |
screamer | 0:66f3b5499f7f | 112 | f.write(html) |
screamer | 0:66f3b5499f7f | 113 | except IOError as e: |
screamer | 0:66f3b5499f7f | 114 | print "I/O error({0}): {1}".format(e.errno, e.strerror) |
screamer | 0:66f3b5499f7f | 115 | except: |
screamer | 0:66f3b5499f7f | 116 | print "Unexpected error:", sys.exc_info()[0] |
screamer | 0:66f3b5499f7f | 117 | raise |
screamer | 0:66f3b5499f7f | 118 | exit(0) |
screamer | 0:66f3b5499f7f | 119 | |
screamer | 0:66f3b5499f7f | 120 | # Clean Export Directory |
screamer | 0:66f3b5499f7f | 121 | if options.clean: |
screamer | 0:66f3b5499f7f | 122 | if exists(EXPORT_DIR): |
screamer | 0:66f3b5499f7f | 123 | rmtree(EXPORT_DIR) |
screamer | 0:66f3b5499f7f | 124 | |
screamer | 0:66f3b5499f7f | 125 | # Target |
screamer | 0:66f3b5499f7f | 126 | if options.mcu is None : |
screamer | 0:66f3b5499f7f | 127 | args_error(parser, "[ERROR] You should specify an MCU") |
screamer | 0:66f3b5499f7f | 128 | mcus = options.mcu |
screamer | 0:66f3b5499f7f | 129 | |
screamer | 0:66f3b5499f7f | 130 | # IDE |
screamer | 0:66f3b5499f7f | 131 | if options.ide is None: |
screamer | 0:66f3b5499f7f | 132 | args_error(parser, "[ERROR] You should specify an IDE") |
screamer | 0:66f3b5499f7f | 133 | ide = options.ide |
screamer | 0:66f3b5499f7f | 134 | |
screamer | 0:66f3b5499f7f | 135 | # Export results |
screamer | 0:66f3b5499f7f | 136 | successes = [] |
screamer | 0:66f3b5499f7f | 137 | failures = [] |
screamer | 0:66f3b5499f7f | 138 | zip = True |
screamer | 0:66f3b5499f7f | 139 | clean = True |
screamer | 0:66f3b5499f7f | 140 | |
screamer | 0:66f3b5499f7f | 141 | # source_dir = use relative paths, otherwise sources are copied |
screamer | 0:66f3b5499f7f | 142 | sources_relative = True if options.source_dir else False |
screamer | 0:66f3b5499f7f | 143 | |
screamer | 0:66f3b5499f7f | 144 | for mcu in mcus.split(','): |
screamer | 0:66f3b5499f7f | 145 | # Program Number or name |
screamer | 0:66f3b5499f7f | 146 | p, n, src, ide = options.program, options.program_name, options.source_dir, options.ide |
screamer | 0:66f3b5499f7f | 147 | |
screamer | 0:66f3b5499f7f | 148 | if src is not None: |
screamer | 0:66f3b5499f7f | 149 | # --source is used to generate IDE files to toolchain directly in the source tree and doesn't generate zip file |
screamer | 0:66f3b5499f7f | 150 | project_dir = options.source_dir |
screamer | 13:ab47a20b66f0 | 151 | project_name = n if n else "Unnamed_Project" |
screamer | 13:ab47a20b66f0 | 152 | project_temp = path.join(options.source_dir[0], 'projectfiles', '%s_%s' % (ide, mcu)) |
screamer | 0:66f3b5499f7f | 153 | mkdir(project_temp) |
screamer | 0:66f3b5499f7f | 154 | lib_symbols = [] |
screamer | 0:66f3b5499f7f | 155 | if options.macros: |
screamer | 0:66f3b5499f7f | 156 | lib_symbols += options.macros |
screamer | 0:66f3b5499f7f | 157 | zip = False # don't create zip |
screamer | 0:66f3b5499f7f | 158 | clean = False # don't cleanup because we use the actual source tree to generate IDE files |
screamer | 0:66f3b5499f7f | 159 | else: |
screamer | 0:66f3b5499f7f | 160 | if n is not None and p is not None: |
screamer | 0:66f3b5499f7f | 161 | args_error(parser, "[ERROR] specify either '-n' or '-p', not both") |
screamer | 0:66f3b5499f7f | 162 | if n: |
screamer | 0:66f3b5499f7f | 163 | if not n in TEST_MAP.keys(): |
screamer | 0:66f3b5499f7f | 164 | # Check if there is an alias for this in private_settings.py |
screamer | 0:66f3b5499f7f | 165 | if getattr(ps, "test_alias", None) is not None: |
screamer | 0:66f3b5499f7f | 166 | alias = ps.test_alias.get(n, "") |
screamer | 0:66f3b5499f7f | 167 | if not alias in TEST_MAP.keys(): |
screamer | 0:66f3b5499f7f | 168 | args_error(parser, "[ERROR] Program with name '%s' not found" % n) |
screamer | 0:66f3b5499f7f | 169 | else: |
screamer | 0:66f3b5499f7f | 170 | n = alias |
screamer | 0:66f3b5499f7f | 171 | else: |
screamer | 0:66f3b5499f7f | 172 | args_error(parser, "[ERROR] Program with name '%s' not found" % n) |
screamer | 0:66f3b5499f7f | 173 | p = TEST_MAP[n].n |
screamer | 0:66f3b5499f7f | 174 | |
screamer | 0:66f3b5499f7f | 175 | if p is None or (p < 0) or (p > (len(TESTS)-1)): |
screamer | 0:66f3b5499f7f | 176 | message = "[ERROR] You have to specify one of the following tests:\n" |
screamer | 0:66f3b5499f7f | 177 | message += '\n'.join(map(str, sorted(TEST_MAP.values()))) |
screamer | 0:66f3b5499f7f | 178 | args_error(parser, message) |
screamer | 0:66f3b5499f7f | 179 | |
screamer | 0:66f3b5499f7f | 180 | # Project |
screamer | 0:66f3b5499f7f | 181 | if p is None or (p < 0) or (p > (len(TESTS)-1)): |
screamer | 0:66f3b5499f7f | 182 | message = "[ERROR] You have to specify one of the following tests:\n" |
screamer | 0:66f3b5499f7f | 183 | message += '\n'.join(map(str, sorted(TEST_MAP.values()))) |
screamer | 0:66f3b5499f7f | 184 | args_error(parser, message) |
screamer | 0:66f3b5499f7f | 185 | test = Test(p) |
screamer | 0:66f3b5499f7f | 186 | |
screamer | 0:66f3b5499f7f | 187 | # Some libraries have extra macros (called by exporter symbols) to we need to pass |
screamer | 0:66f3b5499f7f | 188 | # them to maintain compilation macros integrity between compiled library and |
screamer | 0:66f3b5499f7f | 189 | # header files we might use with it |
screamer | 0:66f3b5499f7f | 190 | lib_symbols = [] |
screamer | 0:66f3b5499f7f | 191 | if options.macros: |
screamer | 0:66f3b5499f7f | 192 | lib_symbols += options.macros |
screamer | 0:66f3b5499f7f | 193 | for lib in LIBRARIES: |
screamer | 0:66f3b5499f7f | 194 | if lib['build_dir'] in test.dependencies: |
screamer | 0:66f3b5499f7f | 195 | lib_macros = lib.get('macros', None) |
screamer | 0:66f3b5499f7f | 196 | if lib_macros is not None: |
screamer | 0:66f3b5499f7f | 197 | lib_symbols.extend(lib_macros) |
screamer | 0:66f3b5499f7f | 198 | |
screamer | 0:66f3b5499f7f | 199 | if not options.build: |
screamer | 0:66f3b5499f7f | 200 | # Substitute the library builds with the sources |
screamer | 0:66f3b5499f7f | 201 | # TODO: Substitute also the other library build paths |
screamer | 0:66f3b5499f7f | 202 | if MBED_LIBRARIES in test.dependencies: |
screamer | 0:66f3b5499f7f | 203 | test.dependencies.remove(MBED_LIBRARIES) |
screamer | 0:66f3b5499f7f | 204 | test.dependencies.append(MBED_BASE) |
screamer | 0:66f3b5499f7f | 205 | |
screamer | 0:66f3b5499f7f | 206 | # Build the project with the same directory structure of the mbed online IDE |
screamer | 0:66f3b5499f7f | 207 | project_name = test.id |
screamer | 13:ab47a20b66f0 | 208 | project_dir = [join(EXPORT_WORKSPACE, project_name)] |
screamer | 0:66f3b5499f7f | 209 | project_temp = EXPORT_TMP |
screamer | 13:ab47a20b66f0 | 210 | setup_user_prj(project_dir[0], test.source_dir, test.dependencies) |
screamer | 0:66f3b5499f7f | 211 | |
screamer | 0:66f3b5499f7f | 212 | # Export to selected toolchain |
screamer | 13:ab47a20b66f0 | 213 | tmp_path, report = export(project_dir, project_name, ide, mcu, project_dir[0], project_temp, clean=clean, make_zip=zip, extra_symbols=lib_symbols, sources_relative=sources_relative) |
screamer | 0:66f3b5499f7f | 214 | if report['success']: |
screamer | 13:ab47a20b66f0 | 215 | if not zip: |
screamer | 13:ab47a20b66f0 | 216 | zip_path = join(project_temp, project_name) |
screamer | 13:ab47a20b66f0 | 217 | else: |
screamer | 13:ab47a20b66f0 | 218 | zip_path = join(EXPORT_DIR, "%s_%s_%s.zip" % (project_name, ide, mcu)) |
screamer | 0:66f3b5499f7f | 219 | move(tmp_path, zip_path) |
screamer | 0:66f3b5499f7f | 220 | successes.append("%s::%s\t%s"% (mcu, ide, zip_path)) |
screamer | 0:66f3b5499f7f | 221 | else: |
screamer | 0:66f3b5499f7f | 222 | failures.append("%s::%s\t%s"% (mcu, ide, report['errormsg'])) |
screamer | 0:66f3b5499f7f | 223 | |
screamer | 0:66f3b5499f7f | 224 | # Prints export results |
screamer | 0:66f3b5499f7f | 225 | |
screamer | 0:66f3b5499f7f | 226 | if len(successes) > 0: |
screamer | 0:66f3b5499f7f | 227 | print "Successful exports:" |
screamer | 0:66f3b5499f7f | 228 | for success in successes: |
screamer | 0:66f3b5499f7f | 229 | print " * %s"% success |
screamer | 0:66f3b5499f7f | 230 | if len(failures) > 0: |
screamer | 0:66f3b5499f7f | 231 | print "Failed exports:" |
screamer | 0:66f3b5499f7f | 232 | for failure in failures: |
screamer | 0:66f3b5499f7f | 233 | print " * %s"% failure |