takashi kadono / Mbed OS Nucleo_446

Dependencies:   ssd1331

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers project.py Source File

project.py

00001 """ The CLI entry point for exporting projects from the mbed tools to any of the
00002 supported IDEs or project structures.
00003 """
00004 from __future__ import print_function, absolute_import
00005 from builtins import str
00006 
00007 import sys
00008 from os.path import (join, abspath, dirname, exists, basename, normpath,
00009                      realpath, relpath, basename)
00010 from os import remove
00011 ROOT = abspath(join(dirname(__file__), ".."))
00012 sys.path.insert(0, ROOT)
00013 
00014 from shutil import move, rmtree
00015 from argparse import ArgumentParser
00016 
00017 from tools.paths import EXPORT_DIR, MBED_HAL, MBED_LIBRARIES, MBED_TARGETS_PATH
00018 from tools.settings import BUILD_DIR
00019 from tools.export import (
00020     EXPORTERS,
00021     mcu_ide_matrix,
00022     mcu_ide_list,
00023     export_project,
00024     get_exporter_toolchain,
00025 )
00026 from tools.tests import TESTS, TEST_MAP
00027 from tools.tests import test_known, test_name_known, Test
00028 from tools.targets import TARGET_NAMES
00029 from tools.utils import (
00030     argparse_filestring_type,
00031     argparse_profile_filestring_type,
00032     argparse_many,
00033     args_error,
00034 )
00035 from tools.utils import argparse_force_lowercase_type
00036 from tools.utils import argparse_force_uppercase_type
00037 from tools.utils import print_large_string
00038 from tools.utils import NotSupportedException
00039 from tools.options import extract_profile, list_profiles, extract_mcus
00040 from tools.notifier.term import TerminalNotifier
00041 
00042 EXPORTER_ALIASES = {
00043     u'gcc_arm': u'make_gcc_arm',
00044     u'uvision': u'uvision5',
00045 }
00046 
00047 
00048 def resolve_exporter_alias(ide):
00049     if ide in EXPORTER_ALIASES:
00050         return EXPORTER_ALIASES[ide]
00051     else:
00052         return ide
00053 
00054 
00055 def setup_project (
00056         ide,
00057         target,
00058         zip,
00059         program,
00060         source_dir,
00061         build,
00062         export_path,
00063 ):
00064     """Generate a name, if not provided, and find dependencies
00065 
00066     Positional arguments:
00067     ide - IDE or project structure that will soon be exported to
00068     target - MCU that the project will build for
00069 
00070     Keyword arguments:
00071     program - the index of a test program
00072     source_dir - the directory, or directories that contain all of the sources
00073     build - a directory that will contain the result of the export
00074     """
00075     # Some libraries have extra macros (called by exporter symbols) to we need
00076     # to pass them to maintain compilation macros integrity between compiled
00077     # library and header files we might use with it
00078     if source_dir:
00079         # --source is used to generate IDE files to toolchain directly
00080         # in the source tree and doesn't generate zip file
00081         project_dir = export_path or source_dir[0]
00082         if program:
00083             project_name = TESTS[program]
00084         else:
00085             project_name = basename(normpath(realpath(source_dir[0])))
00086         if zip:
00087             src_paths = {path.strip(".\\/"): [path] for path in source_dir}
00088         else:
00089             src_paths = {relpath(path, project_dir): [path] for path in source_dir}
00090         lib_paths = None
00091     else:
00092         test = Test(program)
00093         if not build:
00094             # Substitute the mbed library builds with their sources
00095             if MBED_LIBRARIES in test.dependencies:
00096                 test.dependencies.remove(MBED_LIBRARIES)
00097                 test.dependencies.append(MBED_HAL)
00098                 test.dependencies.append(MBED_TARGETS_PATH)
00099 
00100         src_paths = [test.source_dir]
00101         lib_paths = test.dependencies
00102         project_name = "_".join([test.id, ide, target])
00103         project_dir = join(EXPORT_DIR, project_name)
00104 
00105     return project_dir, project_name, src_paths, lib_paths
00106 
00107 
00108 def export (target, ide, build=None, src=None, macros=None, project_id=None,
00109            zip_proj=False, build_profile=None, export_path=None, notify=None,
00110            app_config=None, ignore=None):
00111     """Do an export of a project.
00112 
00113     Positional arguments:
00114     target - MCU that the project will compile for
00115     ide - the IDE or project structure to export to
00116 
00117     Keyword arguments:
00118     build - to use the compiled mbed libraries or not
00119     src - directory or directories that contain the source to export
00120     macros - extra macros to add to the project
00121     project_id - the name of the project
00122     clean - start from a clean state before exporting
00123     zip_proj - create a zip file or not
00124     ignore - list of paths to add to mbedignore
00125 
00126     Returns an object of type Exporter (tools/exports/exporters.py)
00127     """
00128     project_dir, name, src, lib = setup_project(
00129         ide,
00130         target,
00131         bool(zip_proj),
00132         program=project_id,
00133         source_dir=src,
00134         build=build,
00135         export_path=export_path,
00136     )
00137 
00138     zip_name = name+".zip" if zip_proj else None
00139 
00140     return export_project(
00141         src,
00142         project_dir,
00143         target,
00144         ide,
00145         name=name,
00146         macros=macros,
00147         libraries_paths=lib,
00148         zip_proj=zip_name,
00149         build_profile=build_profile,
00150         notify=TerminalNotifier(),
00151         app_config=app_config,
00152         ignore=ignore
00153     )
00154 
00155 def clean(source_dir):
00156     if exists(EXPORT_DIR):
00157         rmtree(EXPORT_DIR)
00158     for cls in EXPORTERS.values():
00159         try:
00160             cls.clean(basename(abspath(source_dir[0])))
00161         except (NotImplementedError, IOError, OSError):
00162             pass
00163     for f in list(EXPORTERS.values())[0].CLEAN_FILES:
00164         try:
00165             remove(f)
00166         except (IOError, OSError):
00167             pass
00168 
00169 
00170 def get_args(argv):
00171     parser = ArgumentParser()
00172 
00173     targetnames = TARGET_NAMES
00174     targetnames.sort()
00175     toolchainlist = list(EXPORTERS.keys()) + list(EXPORTER_ALIASES.keys())
00176     toolchainlist.sort()
00177 
00178     parser.add_argument(
00179         "-m", "--mcu",
00180         metavar="MCU",
00181         help="generate project for the given MCU ({})".format(
00182             ', '.join(targetnames))
00183     )
00184 
00185     parser.add_argument(
00186         "-i",
00187         dest="ide",
00188         type=argparse_force_lowercase_type(
00189             toolchainlist, "toolchain"),
00190         help="The target IDE: %s" % str(toolchainlist)
00191     )
00192 
00193     parser.add_argument(
00194         "-c", "--clean",
00195         action="store_true",
00196         default=False,
00197         help="clean the export directory"
00198     )
00199 
00200     group = parser.add_mutually_exclusive_group(required=False)
00201     group.add_argument(
00202         "-p",
00203         type=test_known,
00204         dest="program",
00205         help="The index of the desired test program: [0-%s]" % (len(TESTS) - 1)
00206     )
00207 
00208     group.add_argument(
00209         "-n",
00210         type=test_name_known,
00211         dest="program",
00212         help="The name of the desired test program"
00213     )
00214 
00215     parser.add_argument(
00216         "-b",
00217         dest="build",
00218         default=False,
00219         action="store_true",
00220         help="use the mbed library build, instead of the sources"
00221     )
00222 
00223     group.add_argument(
00224         "-L", "--list-tests",
00225         action="store_true",
00226         dest="list_tests",
00227         default=False,
00228         help="list available programs in order and exit"
00229     )
00230 
00231     group.add_argument(
00232         "-S", "--list-matrix",
00233         dest="supported_ides",
00234         default=False,
00235         const="matrix",
00236         choices=["matrix", "ides"],
00237         nargs="?",
00238         help="displays supported matrix of MCUs and IDEs"
00239     )
00240 
00241     group.add_argument(
00242         "--update-packs",
00243         dest="update_packs",
00244         action="store_true",
00245         default=False
00246     )
00247 
00248     parser.add_argument(
00249         "-E",
00250         action="store_true",
00251         dest="supported_ides_html",
00252         default=False,
00253         help="Generate a markdown version of the results of -S in README.md"
00254     )
00255 
00256     parser.add_argument(
00257         "--build",
00258         type=argparse_filestring_type,
00259         dest="build_dir",
00260         default=None,
00261         help="Directory for the exported project files"
00262     )
00263 
00264     parser.add_argument(
00265         "--source",
00266         action="append",
00267         type=argparse_filestring_type,
00268         dest="source_dir",
00269         default=[],
00270         help="The source (input) directory"
00271     )
00272 
00273     parser.add_argument(
00274         "-D",
00275         action="append",
00276         dest="macros",
00277         help="Add a macro definition"
00278     )
00279 
00280     parser.add_argument(
00281         "--profile",
00282         dest="profile",
00283         action="append",
00284         type=argparse_profile_filestring_type,
00285         help=("Build profile to use. Can be either path to json"
00286               "file or one of the default one ({})".format(
00287                   ", ".join(list_profiles()))),
00288         default=[]
00289     )
00290 
00291     parser.add_argument(
00292         "--app-config",
00293         dest="app_config",
00294         default=None
00295     )
00296 
00297     parser.add_argument(
00298         "-z",
00299         action="store_true",
00300         default=None,
00301         dest="zip",
00302     )
00303 
00304     parser.add_argument(
00305         "--ignore",
00306         dest="ignore",
00307         type=argparse_many(str),
00308         default=None,
00309         help=("Comma separated list of patterns to add to mbedignore "
00310               "(eg. ./main.cpp)")
00311     )
00312 
00313     return parser.parse_args(argv), parser
00314 
00315 
00316 def main ():
00317     """Entry point"""
00318     # Parse Options
00319     options, parser = get_args(sys.argv[1:])
00320 
00321     # Print available tests in order and exit
00322     if options.list_tests:
00323         print('\n'.join(str(test) for test in sorted(TEST_MAP.values())))
00324     elif options.supported_ides:
00325         if options.supported_ides == "matrix":
00326             print_large_string(mcu_ide_matrix())
00327         elif options.supported_ides == "ides":
00328             print(mcu_ide_list())
00329     elif options.supported_ides_html:
00330         html = mcu_ide_matrix(verbose_html=True)
00331         with open("README.md", "w") as readme:
00332             readme.write("Exporter IDE/Platform Support\n")
00333             readme.write("-----------------------------------\n")
00334             readme.write("\n")
00335             readme.write(html)
00336     elif options.update_packs:
00337         from tools.arm_pack_manager import Cache
00338         cache = Cache(True, True)
00339         cache.cache_everything()
00340     else:
00341         # Check required arguments
00342         if not options.mcu:
00343             args_error(parser, "argument -m/--mcu is required")
00344         if not options.ide:
00345             args_error(parser, "argument -i is required")
00346         if (options.program is None) and (not options.source_dir):
00347             args_error(parser, "one of -p, -n, or --source is required")
00348 
00349         if options.clean:
00350             clean(options.source_dir)
00351 
00352         ide = resolve_exporter_alias(options.ide)
00353         exporter, toolchain_name = get_exporter_toolchain(ide)
00354         profile = extract_profile(parser, options, toolchain_name, fallback="debug")
00355         mcu = extract_mcus(parser, options)[0]
00356         if not exporter.is_target_supported(mcu):
00357             args_error(parser, "%s not supported by %s" % (mcu, ide))
00358 
00359         try:
00360             export(
00361                 mcu,
00362                 ide,
00363                 build=options.build,
00364                 src=options.source_dir,
00365                 macros=options.macros,
00366                 project_id=options.program,
00367                 zip_proj=not bool(options.source_dir) or options.zip,
00368                 build_profile=profile,
00369                 app_config=options.app_config,
00370                 export_path=options.build_dir,
00371                 ignore=options.ignore
00372             )
00373         except NotSupportedException as exc:
00374             args_error(parser, "%s not supported by %s" % (mcu, ide))
00375             print("[Not Supported] %s" % str(exc))
00376     exit(0)
00377 
00378 if __name__ == "__main__":
00379     main()