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.
Diff: project.py
- Revision:
- 31:8ea194f6145b
- Parent:
- 29:1210849dba19
- Child:
- 35:da9c89f8be7d
--- a/project.py Mon Aug 29 11:56:59 2016 +0100 +++ b/project.py Wed Jan 04 11:58:24 2017 -0600 @@ -1,3 +1,6 @@ +""" The CLI entry point for exporting projects from the mbed tools to any of the +supported IDEs or project structures. +""" import sys from os.path import join, abspath, dirname, exists, basename ROOT = abspath(join(dirname(__file__), "..")) @@ -5,21 +8,94 @@ from shutil import move, rmtree from argparse import ArgumentParser -from os import path +from os.path import normpath, realpath -from tools.paths import EXPORT_DIR -from tools.export import export, EXPORTERS, mcu_ide_matrix +from tools.paths import EXPORT_DIR, MBED_HAL, MBED_LIBRARIES, MBED_TARGETS_PATH +from tools.export import EXPORTERS, mcu_ide_matrix from tools.tests import TESTS, TEST_MAP -from tools.tests import test_known, test_name_known +from tools.tests import test_known, test_name_known, Test from tools.targets import TARGET_NAMES -from tools.libraries import LIBRARIES -from utils import argparse_filestring_type, argparse_many -from utils import argparse_force_lowercase_type, argparse_force_uppercase_type, argparse_dir_not_parent -from project_api import setup_project, perform_export, print_results, get_lib_symbols +from tools.utils import argparse_filestring_type, argparse_profile_filestring_type, argparse_many, args_error +from tools.utils import argparse_force_lowercase_type +from tools.utils import argparse_force_uppercase_type +from tools.utils import print_large_string +from tools.project_api import export_project, get_exporter_toolchain +from tools.options import extract_profile, list_profiles + +def setup_project(ide, target, program=None, source_dir=None, build=None, export_path=None): + """Generate a name, if not provided, and find dependencies + + Positional arguments: + ide - IDE or project structure that will soon be exported to + target - MCU that the project will build for + + Keyword arguments: + program - the index of a test program + source_dir - the directory, or directories that contain all of the sources + build - a directory that will contain the result of the export + """ + # Some libraries have extra macros (called by exporter symbols) to we need + # to pass them to maintain compilation macros integrity between compiled + # library and header files we might use with it + if source_dir: + # --source is used to generate IDE files to toolchain directly + # in the source tree and doesn't generate zip file + project_dir = export_path or source_dir[0] + if program: + project_name = TESTS[program] + else: + project_name = basename(normpath(realpath(source_dir[0]))) + src_paths = source_dir + lib_paths = None + else: + test = Test(program) + if not build: + # Substitute the mbed library builds with their sources + if MBED_LIBRARIES in test.dependencies: + test.dependencies.remove(MBED_LIBRARIES) + test.dependencies.append(MBED_HAL) + test.dependencies.append(MBED_TARGETS_PATH) + src_paths = [test.source_dir] + lib_paths = test.dependencies + project_name = "_".join([test.id, ide, target]) + project_dir = join(EXPORT_DIR, project_name) -if __name__ == '__main__': + return project_dir, project_name, src_paths, lib_paths + + +def export(target, ide, build=None, src=None, macros=None, project_id=None, + clean=False, zip_proj=False, build_profile=None, export_path=None, + silent=False): + """Do an export of a project. + + Positional arguments: + target - MCU that the project will compile for + ide - the IDE or project structure to export to + + Keyword arguments: + build - to use the compiled mbed libraries or not + src - directory or directories that contain the source to export + macros - extra macros to add to the project + project_id - the name of the project + clean - start from a clean state before exporting + zip_proj - create a zip file or not + + Returns an object of type Exporter (tools/exports/exporters.py) + """ + project_dir, name, src, lib = setup_project(ide, target, program=project_id, + source_dir=src, build=build, export_path=export_path) + + zip_name = name+".zip" if zip_proj else None + + return export_project(src, project_dir, target, ide, clean=clean, name=name, + macros=macros, libraries_paths=lib, zip_proj=zip_name, + build_profile=build_profile, silent=silent) + + +def main(): + """Entry point""" # Parse Options parser = ArgumentParser() @@ -29,32 +105,35 @@ toolchainlist.sort() parser.add_argument("-m", "--mcu", - metavar="MCU", - default='LPC1768', - type=argparse_many(argparse_force_uppercase_type(targetnames, "MCU")), - help="generate project for the given MCU (%s)"% ', '.join(targetnames)) + metavar="MCU", + default='LPC1768', + type=argparse_force_uppercase_type(targetnames, "MCU"), + help="generate project for the given MCU ({})".format( + ', '.join(targetnames))) parser.add_argument("-i", - dest="ide", - default='uvision', - type=argparse_force_lowercase_type(toolchainlist, "toolchain"), - help="The target IDE: %s"% str(toolchainlist)) + dest="ide", + default='uvision', + type=argparse_force_lowercase_type( + toolchainlist, "toolchain"), + help="The target IDE: %s"% str(toolchainlist)) parser.add_argument("-c", "--clean", - action="store_true", - default=False, - help="clean the export directory") + action="store_true", + default=False, + help="clean the export directory") group = parser.add_mutually_exclusive_group(required=False) - group.add_argument("-p", - type=test_known, - dest="program", - help="The index of the desired test program: [0-%d]"% (len(TESTS)-1)) + group.add_argument( + "-p", + type=test_known, + dest="program", + help="The index of the desired test program: [0-%s]"% (len(TESTS)-1)) group.add_argument("-n", - type=test_name_known, - dest="program", - help="The name of the desired test program") + type=test_name_known, + dest="program", + help="The name of the desired test program") parser.add_argument("-b", dest="build", @@ -63,100 +142,107 @@ help="use the mbed library build, instead of the sources") group.add_argument("-L", "--list-tests", - action="store_true", - dest="list_tests", - default=False, - help="list available programs in order and exit") + action="store_true", + dest="list_tests", + default=False, + help="list available programs in order and exit") group.add_argument("-S", "--list-matrix", - action="store_true", - dest="supported_ides", - default=False, - help="displays supported matrix of MCUs and IDEs") + action="store_true", + dest="supported_ides", + default=False, + help="displays supported matrix of MCUs and IDEs") parser.add_argument("-E", - action="store_true", - dest="supported_ides_html", - default=False, - help="writes tools/export/README.md") + action="store_true", + dest="supported_ides_html", + default=False, + help="writes tools/export/README.md") parser.add_argument("--source", - action="append", - type=argparse_filestring_type, - dest="source_dir", - default=[], - help="The source (input) directory") + action="append", + type=argparse_filestring_type, + dest="source_dir", + default=[], + help="The source (input) directory") parser.add_argument("-D", - action="append", - dest="macros", - help="Add a macro definition") + action="append", + dest="macros", + help="Add a macro definition") + + parser.add_argument("--profile", dest="profile", action="append", + type=argparse_profile_filestring_type, + help="Build profile to use. Can be either path to json" \ + "file or one of the default one ({})".format(", ".join(list_profiles())), + default=[]) + + parser.add_argument("--update-packs", + dest="update_packs", + action="store_true", + default=False) options = parser.parse_args() # Print available tests in order and exit if options.list_tests is True: - print '\n'.join(map(str, sorted(TEST_MAP.values()))) + print '\n'.join([str(test) for test in sorted(TEST_MAP.values())]) sys.exit() # Only prints matrix of supported IDEs if options.supported_ides: - print mcu_ide_matrix() + print_large_string(mcu_ide_matrix()) exit(0) # Only prints matrix of supported IDEs if options.supported_ides_html: html = mcu_ide_matrix(verbose_html=True) try: - with open("./export/README.md","w") as f: - f.write("Exporter IDE/Platform Support\n") - f.write("-----------------------------------\n") - f.write("\n") - f.write(html) - except IOError as e: - print "I/O error({0}): {1}".format(e.errno, e.strerror) + with open("./export/README.md", "w") as readme: + readme.write("Exporter IDE/Platform Support\n") + readme.write("-----------------------------------\n") + readme.write("\n") + readme.write(html) + except IOError as exc: + print "I/O error({0}): {1}".format(exc.errno, exc.strerror) except: print "Unexpected error:", sys.exc_info()[0] raise exit(0) + if options.update_packs: + from tools.arm_pack_manager import Cache + cache = Cache(True, True) + cache.cache_descriptors() + # Clean Export Directory if options.clean: if exists(EXPORT_DIR): rmtree(EXPORT_DIR) - # Export results - successes = [] - failures = [] - - # source_dir = use relative paths, otherwise sources are copied - sources_relative = True if options.source_dir else False + for mcu in options.mcu: + zip_proj = not bool(options.source_dir) - for mcu in options.mcu: - # Program Number or name - p, src, ide = options.program, options.source_dir, options.ide - try: - project_dir, project_name, project_temp = setup_project(mcu, ide, p, src, options.build) - zip = not bool(src) # create zip when no src_dir provided - clean = not bool(src) # don't clean when source is provided, use acrual source tree for IDE files + # Target + if not options.mcu: + args_error(parser, "argument -m/--mcu is required") + + # Toolchain + if not options.ide: + args_error(parser, "argument -i is required") - # Export to selected toolchain - lib_symbols = get_lib_symbols(options.macros, src, p) - 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) - except OSError as e: - if e.errno == 2: - report = dict(success=False, errormsg="Library path '%s' does not exist. Ensure that the library is built." % (e.filename)) - else: - report = dict(success=False, errormsg="An OS error occured: errno #{}".format(e.errno)) - if report['success']: - if not zip: - zip_path = join(project_temp, project_name) - else: - zip_path = join(EXPORT_DIR, "%s_%s_%s.zip" % (project_name, ide, mcu)) - move(tmp_path, zip_path) - successes.append("%s::%s\t%s"% (mcu, ide, zip_path)) - else: - failures.append("%s::%s\t%s"% (mcu, ide, report['errormsg'])) + if (options.program is None) and (not options.source_dir): + args_error(parser, "one of -p, -n, or --source is required") + # Export to selected toolchain + exporter, toolchain_name = get_exporter_toolchain(options.ide) + if options.mcu not in exporter.TARGETS: + args_error(parser, "%s not supported by %s"%(options.mcu,options.ide)) + profile = extract_profile(parser, options, toolchain_name) + export(options.mcu, options.ide, build=options.build, + src=options.source_dir, macros=options.macros, + project_id=options.program, clean=options.clean, + zip_proj=zip_proj, build_profile=profile) - # Prints export results - print_results(successes, failures) + +if __name__ == "__main__": + main()