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