BA / Mbed OS BaBoRo1
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 EXPORTERS, mcu_ide_matrix, mcu_ide_list, export_project, get_exporter_toolchain
00020 from tools.tests import TESTS, TEST_MAP
00021 from tools.tests import test_known, test_name_known, Test
00022 from tools.targets import TARGET_NAMES
00023 from tools.utils import argparse_filestring_type, argparse_profile_filestring_type, argparse_many, args_error
00024 from tools.utils import argparse_force_lowercase_type
00025 from tools.utils import argparse_force_uppercase_type
00026 from tools.utils import print_large_string
00027 from tools.utils import NotSupportedException
00028 from tools.options import extract_profile, list_profiles, extract_mcus
00029 
00030 def setup_project (ide, target, program=None, source_dir=None, build=None, export_path=None):
00031     """Generate a name, if not provided, and find dependencies
00032 
00033     Positional arguments:
00034     ide - IDE or project structure that will soon be exported to
00035     target - MCU that the project will build for
00036 
00037     Keyword arguments:
00038     program - the index of a test program
00039     source_dir - the directory, or directories that contain all of the sources
00040     build - a directory that will contain the result of the export
00041     """
00042     # Some libraries have extra macros (called by exporter symbols) to we need
00043     # to pass them to maintain compilation macros integrity between compiled
00044     # library and header files we might use with it
00045     if source_dir:
00046         # --source is used to generate IDE files to toolchain directly
00047         # in the source tree and doesn't generate zip file
00048         project_dir = export_path or source_dir[0]
00049         if program:
00050             project_name = TESTS[program]
00051         else:
00052             project_name = basename(normpath(realpath(source_dir[0])))
00053         src_paths = {relpath(path, project_dir): [path] for path in source_dir}
00054         lib_paths = None
00055     else:
00056         test = Test(program)
00057         if not build:
00058             # Substitute the mbed library builds with their sources
00059             if MBED_LIBRARIES in test.dependencies:
00060                 test.dependencies.remove(MBED_LIBRARIES)
00061                 test.dependencies.append(MBED_HAL)
00062                 test.dependencies.append(MBED_TARGETS_PATH)
00063 
00064 
00065         src_paths = [test.source_dir]
00066         lib_paths = test.dependencies
00067         project_name = "_".join([test.id, ide, target])
00068         project_dir = join(EXPORT_DIR, project_name)
00069 
00070     return project_dir, project_name, src_paths, lib_paths
00071 
00072 
00073 def export (target, ide, build=None, src=None, macros=None, project_id=None,
00074            zip_proj=False, build_profile=None, export_path=None, silent=False,
00075            app_config=None):
00076     """Do an export of a project.
00077 
00078     Positional arguments:
00079     target - MCU that the project will compile for
00080     ide - the IDE or project structure to export to
00081 
00082     Keyword arguments:
00083     build - to use the compiled mbed libraries or not
00084     src - directory or directories that contain the source to export
00085     macros - extra macros to add to the project
00086     project_id - the name of the project
00087     clean - start from a clean state before exporting
00088     zip_proj - create a zip file or not
00089 
00090     Returns an object of type Exporter (tools/exports/exporters.py)
00091     """
00092     project_dir, name, src, lib = setup_project(ide, target, program=project_id,
00093                                                 source_dir=src, build=build, export_path=export_path)
00094 
00095     zip_name = name+".zip" if zip_proj else None
00096 
00097     return export_project(src, project_dir, target, ide, name=name,
00098                           macros=macros, libraries_paths=lib, zip_proj=zip_name,
00099                           build_profile=build_profile, silent=silent,
00100                           app_config=app_config)
00101 
00102 
00103 def main ():
00104     """Entry point"""
00105     # Parse Options
00106     parser = ArgumentParser()
00107 
00108     targetnames = TARGET_NAMES
00109     targetnames.sort()
00110     toolchainlist = list(EXPORTERS.keys())
00111     toolchainlist.sort()
00112 
00113     parser.add_argument("-m", "--mcu",
00114                         metavar="MCU",
00115                         help="generate project for the given MCU ({})".format(
00116                             ', '.join(targetnames)))
00117 
00118     parser.add_argument("-i",
00119                         dest="ide",
00120                         type=argparse_force_lowercase_type(
00121                             toolchainlist, "toolchain"),
00122                         help="The target IDE: %s"% str(toolchainlist))
00123 
00124     parser.add_argument("-c", "--clean",
00125                         action="store_true",
00126                         default=False,
00127                         help="clean the export directory")
00128 
00129     group = parser.add_mutually_exclusive_group(required=False)
00130     group.add_argument(
00131         "-p",
00132         type=test_known,
00133         dest="program",
00134         help="The index of the desired test program: [0-%s]"% (len(TESTS)-1))
00135 
00136     group.add_argument("-n",
00137                        type=test_name_known,
00138                        dest="program",
00139                        help="The name of the desired test program")
00140 
00141     parser.add_argument("-b",
00142                       dest="build",
00143                       default=False,
00144                       action="store_true",
00145                       help="use the mbed library build, instead of the sources")
00146 
00147     group.add_argument("-L", "--list-tests",
00148                        action="store_true",
00149                        dest="list_tests",
00150                        default=False,
00151                        help="list available programs in order and exit")
00152 
00153     group.add_argument("-S", "--list-matrix",
00154                        dest="supported_ides",
00155                        default=False,
00156                        const="matrix",
00157                        choices=["matrix", "ides"],
00158                        nargs="?",
00159                        help="displays supported matrix of MCUs and IDEs")
00160 
00161     parser.add_argument("-E",
00162                         action="store_true",
00163                         dest="supported_ides_html",
00164                         default=False,
00165                         help="writes tools/export/README.md")
00166 
00167     parser.add_argument("--build",
00168                         type=argparse_filestring_type,
00169                         dest="build_dir",
00170                         default=None,
00171                         help="Directory for the exported project files")
00172 
00173     parser.add_argument("--source",
00174                         action="append",
00175                         type=argparse_filestring_type,
00176                         dest="source_dir",
00177                         default=[],
00178                         help="The source (input) directory")
00179 
00180     parser.add_argument("-D",
00181                         action="append",
00182                         dest="macros",
00183                         help="Add a macro definition")
00184 
00185     parser.add_argument("--profile", dest="profile", action="append",
00186                         type=argparse_profile_filestring_type,
00187                         help="Build profile to use. Can be either path to json" \
00188                         "file or one of the default one ({})".format(", ".join(list_profiles())),
00189                         default=[])
00190 
00191     parser.add_argument("--update-packs",
00192                         dest="update_packs",
00193                         action="store_true",
00194                         default=False)
00195     parser.add_argument("--app-config",
00196                         dest="app_config",
00197                         default=None)
00198 
00199     options = parser.parse_args()
00200 
00201     # Print available tests in order and exit
00202     if options.list_tests is True:
00203         print('\n'.join([str(test) for test in  sorted(TEST_MAP.values())]))
00204         sys.exit()
00205 
00206     # Only prints matrix of supported IDEs
00207     if options.supported_ides:
00208         if options.supported_ides == "matrix":
00209             print_large_string(mcu_ide_matrix())
00210         elif options.supported_ides == "ides":
00211             print(mcu_ide_list())
00212         exit(0)
00213 
00214     # Only prints matrix of supported IDEs
00215     if options.supported_ides_html:
00216         html = mcu_ide_matrix(verbose_html=True)
00217         try:
00218             with open("./export/README.md", "w") as readme:
00219                 readme.write("Exporter IDE/Platform Support\n")
00220                 readme.write("-----------------------------------\n")
00221                 readme.write("\n")
00222                 readme.write(html)
00223         except IOError as exc:
00224             print("I/O error({0}): {1}".format(exc.errno, exc.strerror))
00225         except:
00226             print("Unexpected error:", sys.exc_info()[0])
00227             raise
00228         exit(0)
00229 
00230     if options.update_packs:
00231         from tools.arm_pack_manager import Cache
00232         cache = Cache(True, True)
00233         cache.cache_everything()
00234 
00235     # Target
00236     if not options.mcu:
00237         args_error(parser, "argument -m/--mcu is required")
00238 
00239     # Toolchain
00240     if not options.ide:
00241         args_error(parser, "argument -i is required")
00242 
00243     # Clean Export Directory
00244     if options.clean:
00245         if exists(EXPORT_DIR):
00246             rmtree(EXPORT_DIR)
00247 
00248     zip_proj = not bool(options.source_dir)
00249 
00250     if (options.program is None) and (not options.source_dir):
00251         args_error(parser, "one of -p, -n, or --source is required")
00252     exporter, toolchain_name = get_exporter_toolchain(options.ide)
00253     mcu = extract_mcus(parser, options)[0]
00254     if not exporter.is_target_supported(mcu):
00255         args_error(parser, "%s not supported by %s"%(mcu,options.ide))
00256     profile = extract_profile(parser, options, toolchain_name, fallback="debug")
00257     if options.clean:
00258         for cls in EXPORTERS.values():
00259             try:
00260                 cls.clean(basename(abspath(options.source_dir[0])))
00261             except (NotImplementedError, IOError, OSError):
00262                 pass
00263         for f in list(EXPORTERS.values())[0].CLEAN_FILES:
00264             try:
00265                 remove(f)
00266             except (IOError, OSError):
00267                 pass
00268     try:
00269         export(mcu, options.ide, build=options.build,
00270                src=options.source_dir, macros=options.macros,
00271                project_id=options.program, zip_proj=zip_proj,
00272                build_profile=profile, app_config=options.app_config,
00273                export_path=options.build_dir)
00274     except NotSupportedException as exc:
00275         print("[ERROR] %s" % str(exc))
00276 
00277 if __name__ == "__main__":
00278     main()