mirror of https://github.com/ARMmbed/mbed-os.git
				
				
				
			IDE build tests with progen
							parent
							
								
									38ae4f9289
								
							
						
					
					
						commit
						b969fa5bb1
					
				| 
						 | 
					@ -3,7 +3,7 @@ PySerial>=2.7
 | 
				
			||||||
PrettyTable>=0.7.2
 | 
					PrettyTable>=0.7.2
 | 
				
			||||||
Jinja2>=2.7.3
 | 
					Jinja2>=2.7.3
 | 
				
			||||||
IntelHex>=1.3
 | 
					IntelHex>=1.3
 | 
				
			||||||
project-generator>=0.9.3,<0.10.0
 | 
					project-generator>=0.9.7,<0.10.0
 | 
				
			||||||
project_generator_definitions>=0.2.26,<0.3.0
 | 
					project_generator_definitions>=0.2.26,<0.3.0
 | 
				
			||||||
junit-xml
 | 
					junit-xml
 | 
				
			||||||
pyYAML
 | 
					pyYAML
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -21,7 +21,7 @@ import yaml
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from tools.utils import mkdir
 | 
					from tools.utils import mkdir
 | 
				
			||||||
from tools.export import uvision4, uvision5, codered, gccarm, ds5_5, iar, emblocks, coide, kds, zip, simplicityv3, atmelstudio, sw4stm32, e2studio
 | 
					from tools.export import uvision4, uvision5, codered, gccarm, ds5_5, iar, emblocks, coide, kds, zip, simplicityv3, atmelstudio, sw4stm32, e2studio
 | 
				
			||||||
from tools.export.exporters import zip_working_directory_and_clean_up, OldLibrariesException
 | 
					from tools.export.exporters import zip_working_directory_and_clean_up, OldLibrariesException, FailedBuildException
 | 
				
			||||||
from tools.targets import TARGET_NAMES, EXPORT_MAP, TARGET_MAP
 | 
					from tools.targets import TARGET_NAMES, EXPORT_MAP, TARGET_MAP
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from project_generator_definitions.definitions import ProGenDef
 | 
					from project_generator_definitions.definitions import ProGenDef
 | 
				
			||||||
| 
						 | 
					@ -58,7 +58,8 @@ def online_build_url_resolver(url):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def export(project_path, project_name, ide, target, destination='/tmp/',
 | 
					def export(project_path, project_name, ide, target, destination='/tmp/',
 | 
				
			||||||
           tempdir=None, clean=True, extra_symbols=None, make_zip=True, sources_relative=False, build_url_resolver=online_build_url_resolver):
 | 
					           tempdir=None, pgen_build = False, clean=True, extra_symbols=None, make_zip=True, sources_relative=False,
 | 
				
			||||||
 | 
					           build_url_resolver=online_build_url_resolver, progen_build=False):
 | 
				
			||||||
    # Convention: we are using capitals for toolchain and target names
 | 
					    # Convention: we are using capitals for toolchain and target names
 | 
				
			||||||
    if target is not None:
 | 
					    if target is not None:
 | 
				
			||||||
        target = target.upper()
 | 
					        target = target.upper()
 | 
				
			||||||
| 
						 | 
					@ -68,8 +69,8 @@ def export(project_path, project_name, ide, target, destination='/tmp/',
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    use_progen = False
 | 
					    use_progen = False
 | 
				
			||||||
    supported = True
 | 
					    supported = True
 | 
				
			||||||
    report = {'success': False, 'errormsg':''}
 | 
					    report = {'success': False, 'errormsg':'', 'skip': False}
 | 
				
			||||||
    
 | 
					
 | 
				
			||||||
    if ide is None or ide == "zip":
 | 
					    if ide is None or ide == "zip":
 | 
				
			||||||
        # Simple ZIP exporter
 | 
					        # Simple ZIP exporter
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
| 
						 | 
					@ -83,6 +84,7 @@ def export(project_path, project_name, ide, target, destination='/tmp/',
 | 
				
			||||||
    else:
 | 
					    else:
 | 
				
			||||||
        if ide not in EXPORTERS:
 | 
					        if ide not in EXPORTERS:
 | 
				
			||||||
            report['errormsg'] = ERROR_MESSAGE_UNSUPPORTED_TOOLCHAIN % (target, ide)
 | 
					            report['errormsg'] = ERROR_MESSAGE_UNSUPPORTED_TOOLCHAIN % (target, ide)
 | 
				
			||||||
 | 
					            report['skip'] = True
 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
            Exporter = EXPORTERS[ide]
 | 
					            Exporter = EXPORTERS[ide]
 | 
				
			||||||
            target = EXPORT_MAP.get(target, target)
 | 
					            target = EXPORT_MAP.get(target, target)
 | 
				
			||||||
| 
						 | 
					@ -91,24 +93,35 @@ def export(project_path, project_name, ide, target, destination='/tmp/',
 | 
				
			||||||
                    use_progen = True
 | 
					                    use_progen = True
 | 
				
			||||||
            except AttributeError:
 | 
					            except AttributeError:
 | 
				
			||||||
                pass
 | 
					                pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if target not in Exporter.TARGETS or Exporter.TOOLCHAIN not in TARGET_MAP[target].supported_toolchains:
 | 
				
			||||||
 | 
					                supported = False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if use_progen:
 | 
					            if use_progen:
 | 
				
			||||||
                if not ProGenDef(ide).is_supported(TARGET_MAP[target].progen['target']):
 | 
					                if not ProGenDef(ide).is_supported(TARGET_MAP[target].progen['target']):
 | 
				
			||||||
                    supported = False
 | 
					                    supported = False
 | 
				
			||||||
            else:
 | 
					 | 
				
			||||||
                if target not in Exporter.TARGETS:
 | 
					 | 
				
			||||||
                    supported = False
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if supported:
 | 
					            if supported:
 | 
				
			||||||
                # target checked, export
 | 
					                # target checked, export
 | 
				
			||||||
                try:
 | 
					                try:
 | 
				
			||||||
                    exporter = Exporter(target, tempdir, project_name, build_url_resolver, extra_symbols=extra_symbols, sources_relative=sources_relative)
 | 
					                    exporter = Exporter(target, tempdir, project_name, build_url_resolver, extra_symbols=extra_symbols, sources_relative=sources_relative)
 | 
				
			||||||
                    exporter.scan_and_copy_resources(project_path, tempdir, sources_relative)
 | 
					                    exporter.scan_and_copy_resources(project_path, tempdir, sources_relative)
 | 
				
			||||||
                    exporter.generate()
 | 
					                    if progen_build:
 | 
				
			||||||
                    report['success'] = True
 | 
					                        #try to build with pgen ide builders
 | 
				
			||||||
 | 
					                        try:
 | 
				
			||||||
 | 
					                            exporter.generate(progen_build=True)
 | 
				
			||||||
 | 
					                            report['success'] = True
 | 
				
			||||||
 | 
					                        except FailedBuildException, f:
 | 
				
			||||||
 | 
					                            report['errormsg'] = "Build Failed"
 | 
				
			||||||
 | 
					                    else:
 | 
				
			||||||
 | 
					                        exporter.generate()
 | 
				
			||||||
 | 
					                        report['success'] = True
 | 
				
			||||||
                except OldLibrariesException, e:
 | 
					                except OldLibrariesException, e:
 | 
				
			||||||
                    report['errormsg'] = ERROR_MESSAGE_NOT_EXPORT_LIBS
 | 
					                    report['errormsg'] = ERROR_MESSAGE_NOT_EXPORT_LIBS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            else:
 | 
					            else:
 | 
				
			||||||
                report['errormsg'] = ERROR_MESSAGE_UNSUPPORTED_TOOLCHAIN % (target, ide)
 | 
					                report['errormsg'] = ERROR_MESSAGE_UNSUPPORTED_TOOLCHAIN % (target, ide)
 | 
				
			||||||
 | 
					                report['skip'] = True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    zip_path = None
 | 
					    zip_path = None
 | 
				
			||||||
    if report['success']:
 | 
					    if report['success']:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -21,6 +21,8 @@ from tools.config import Config
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class OldLibrariesException(Exception): pass
 | 
					class OldLibrariesException(Exception): pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class FailedBuildException(Exception) : pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Exporter(object):
 | 
					class Exporter(object):
 | 
				
			||||||
    TEMPLATE_DIR = dirname(__file__)
 | 
					    TEMPLATE_DIR = dirname(__file__)
 | 
				
			||||||
    DOT_IN_RELATIVE_PATH = False
 | 
					    DOT_IN_RELATIVE_PATH = False
 | 
				
			||||||
| 
						 | 
					@ -107,7 +109,7 @@ class Exporter(object):
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return project_data
 | 
					        return project_data
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def progen_gen_file(self, tool_name, project_data):
 | 
					    def progen_gen_file(self, tool_name, project_data, progen_build=False):
 | 
				
			||||||
        """ Generate project using ProGen Project API """
 | 
					        """ Generate project using ProGen Project API """
 | 
				
			||||||
        settings = ProjectSettings()
 | 
					        settings = ProjectSettings()
 | 
				
			||||||
        project = Project(self.program_name, [project_data], settings)
 | 
					        project = Project(self.program_name, [project_data], settings)
 | 
				
			||||||
| 
						 | 
					@ -115,6 +117,11 @@ class Exporter(object):
 | 
				
			||||||
        # thinks it is not dict but a file, and adds them to workspace.
 | 
					        # thinks it is not dict but a file, and adds them to workspace.
 | 
				
			||||||
        project.project['common']['include_paths'] = self.resources.inc_dirs
 | 
					        project.project['common']['include_paths'] = self.resources.inc_dirs
 | 
				
			||||||
        project.generate(tool_name, copied=not self.sources_relative)
 | 
					        project.generate(tool_name, copied=not self.sources_relative)
 | 
				
			||||||
 | 
					        if progen_build:
 | 
				
			||||||
 | 
					            print("Project exported, building...")
 | 
				
			||||||
 | 
					            result = project.build(tool_name)
 | 
				
			||||||
 | 
					            if result == -1:
 | 
				
			||||||
 | 
					                raise FailedBuildException("Build Failed")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __scan_all(self, path):
 | 
					    def __scan_all(self, path):
 | 
				
			||||||
        resources = []
 | 
					        resources = []
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -46,7 +46,7 @@ class IAREmbeddedWorkbench(Exporter):
 | 
				
			||||||
            # target is not supported yet
 | 
					            # target is not supported yet
 | 
				
			||||||
            continue
 | 
					            continue
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def generate(self):
 | 
					    def generate(self, progen_build=False):
 | 
				
			||||||
        """ Generates the project files """
 | 
					        """ Generates the project files """
 | 
				
			||||||
        project_data = self.progen_get_project_data()
 | 
					        project_data = self.progen_get_project_data()
 | 
				
			||||||
        tool_specific = {}
 | 
					        tool_specific = {}
 | 
				
			||||||
| 
						 | 
					@ -75,7 +75,10 @@ class IAREmbeddedWorkbench(Exporter):
 | 
				
			||||||
        # VLA is enabled via template IccAllowVLA
 | 
					        # VLA is enabled via template IccAllowVLA
 | 
				
			||||||
        project_data['tool_specific']['iar']['misc']['c_flags'].remove("--vla")
 | 
					        project_data['tool_specific']['iar']['misc']['c_flags'].remove("--vla")
 | 
				
			||||||
        project_data['common']['build_dir'] = os.path.join(project_data['common']['build_dir'], 'iar_arm')
 | 
					        project_data['common']['build_dir'] = os.path.join(project_data['common']['build_dir'], 'iar_arm')
 | 
				
			||||||
        self.progen_gen_file('iar_arm', project_data)
 | 
					        if progen_build:
 | 
				
			||||||
 | 
					            self.progen_gen_file('iar_arm', project_data, True)
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            self.progen_gen_file('iar_arm', project_data)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Currently not used, we should reuse folder_name to create virtual folders
 | 
					# Currently not used, we should reuse folder_name to create virtual folders
 | 
				
			||||||
class IarFolder():
 | 
					class IarFolder():
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -50,7 +50,7 @@ class Uvision4(Exporter):
 | 
				
			||||||
    def get_toolchain(self):
 | 
					    def get_toolchain(self):
 | 
				
			||||||
        return TARGET_MAP[self.target].default_toolchain
 | 
					        return TARGET_MAP[self.target].default_toolchain
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def generate(self):
 | 
					    def generate(self, progen_build=False):
 | 
				
			||||||
        """ Generates the project files """
 | 
					        """ Generates the project files """
 | 
				
			||||||
        project_data = self.progen_get_project_data()
 | 
					        project_data = self.progen_get_project_data()
 | 
				
			||||||
        tool_specific = {}
 | 
					        tool_specific = {}
 | 
				
			||||||
| 
						 | 
					@ -96,4 +96,7 @@ class Uvision4(Exporter):
 | 
				
			||||||
            i += 1
 | 
					            i += 1
 | 
				
			||||||
        project_data['common']['macros'].append('__ASSERT_MSG')
 | 
					        project_data['common']['macros'].append('__ASSERT_MSG')
 | 
				
			||||||
        project_data['common']['build_dir'] = join(project_data['common']['build_dir'], 'uvision4')
 | 
					        project_data['common']['build_dir'] = join(project_data['common']['build_dir'], 'uvision4')
 | 
				
			||||||
        self.progen_gen_file('uvision', project_data)
 | 
					        if progen_build:
 | 
				
			||||||
 | 
					            self.progen_gen_file('uvision', project_data, True)
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            self.progen_gen_file('uvision', project_data)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -50,7 +50,7 @@ class Uvision5(Exporter):
 | 
				
			||||||
    def get_toolchain(self):
 | 
					    def get_toolchain(self):
 | 
				
			||||||
        return TARGET_MAP[self.target].default_toolchain
 | 
					        return TARGET_MAP[self.target].default_toolchain
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def generate(self):
 | 
					    def generate(self, progen_build=False):
 | 
				
			||||||
        """ Generates the project files """
 | 
					        """ Generates the project files """
 | 
				
			||||||
        project_data = self.progen_get_project_data()
 | 
					        project_data = self.progen_get_project_data()
 | 
				
			||||||
        tool_specific = {}
 | 
					        tool_specific = {}
 | 
				
			||||||
| 
						 | 
					@ -95,4 +95,7 @@ class Uvision5(Exporter):
 | 
				
			||||||
                project_data['common']['macros'].pop(i)
 | 
					                project_data['common']['macros'].pop(i)
 | 
				
			||||||
            i += 1
 | 
					            i += 1
 | 
				
			||||||
        project_data['common']['macros'].append('__ASSERT_MSG')
 | 
					        project_data['common']['macros'].append('__ASSERT_MSG')
 | 
				
			||||||
        self.progen_gen_file('uvision5', project_data)
 | 
					        if progen_build:
 | 
				
			||||||
 | 
					            self.progen_gen_file('uvision5', project_data, True)
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            self.progen_gen_file('uvision5', project_data)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,16 +7,14 @@ from shutil import move, rmtree
 | 
				
			||||||
from argparse import ArgumentParser
 | 
					from argparse import ArgumentParser
 | 
				
			||||||
from os import path
 | 
					from os import path
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from tools.paths import EXPORT_DIR, EXPORT_WORKSPACE, EXPORT_TMP
 | 
					from tools.paths import EXPORT_DIR
 | 
				
			||||||
from tools.paths import MBED_BASE, MBED_LIBRARIES
 | 
					from tools.export import export, EXPORTERS, mcu_ide_matrix
 | 
				
			||||||
from tools.export import export, setup_user_prj, EXPORTERS, mcu_ide_matrix
 | 
					from tools.tests import TESTS, TEST_MAP
 | 
				
			||||||
from tools.utils import args_error, mkdir
 | 
					 | 
				
			||||||
from tools.tests import TESTS, Test, TEST_MAP
 | 
					 | 
				
			||||||
from tools.tests import test_known, test_name_known
 | 
					from tools.tests import test_known, test_name_known
 | 
				
			||||||
from tools.targets import TARGET_NAMES
 | 
					from tools.targets import TARGET_NAMES
 | 
				
			||||||
from tools.libraries import LIBRARIES
 | 
					from utils import argparse_filestring_type, argparse_many
 | 
				
			||||||
from utils import argparse_lowercase_type, argparse_uppercase_type, argparse_filestring_type, argparse_many
 | 
					 | 
				
			||||||
from utils import argparse_force_lowercase_type, argparse_force_uppercase_type
 | 
					from utils import argparse_force_lowercase_type, argparse_force_uppercase_type
 | 
				
			||||||
 | 
					from project_api import setup_project, perform_export, print_results, get_lib_symbols
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -129,8 +127,6 @@ if __name__ == '__main__':
 | 
				
			||||||
    # Export results
 | 
					    # Export results
 | 
				
			||||||
    successes = []
 | 
					    successes = []
 | 
				
			||||||
    failures = []
 | 
					    failures = []
 | 
				
			||||||
    zip = True
 | 
					 | 
				
			||||||
    clean = True
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # source_dir = use relative paths, otherwise sources are copied
 | 
					    # source_dir = use relative paths, otherwise sources are copied
 | 
				
			||||||
    sources_relative = True if options.source_dir else False
 | 
					    sources_relative = True if options.source_dir else False
 | 
				
			||||||
| 
						 | 
					@ -138,47 +134,13 @@ if __name__ == '__main__':
 | 
				
			||||||
    for mcu in options.mcu:
 | 
					    for mcu in options.mcu:
 | 
				
			||||||
        # Program Number or name
 | 
					        # Program Number or name
 | 
				
			||||||
        p, src, ide = options.program, options.source_dir, options.ide
 | 
					        p, src, ide = options.program, options.source_dir, options.ide
 | 
				
			||||||
 | 
					        project_dir, project_name, project_temp = setup_project(mcu, ide, p, src, options.build)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if src:
 | 
					        zip = src is []  # create zip when no src_dir provided
 | 
				
			||||||
            # --source is used to generate IDE files to toolchain directly in the source tree and doesn't generate zip file
 | 
					        clean = src is []  # don't clean when source is provided, use acrual source tree for IDE files
 | 
				
			||||||
            project_dir = options.source_dir
 | 
					 | 
				
			||||||
            project_name = TESTS[p] if p else "Unnamed_project"
 | 
					 | 
				
			||||||
            project_temp = path.join(options.source_dir[0], 'projectfiles', '%s_%s' % (ide, mcu))
 | 
					 | 
				
			||||||
            mkdir(project_temp)
 | 
					 | 
				
			||||||
            lib_symbols = []
 | 
					 | 
				
			||||||
            if options.macros:
 | 
					 | 
				
			||||||
                lib_symbols += options.macros
 | 
					 | 
				
			||||||
            zip = False   # don't create zip
 | 
					 | 
				
			||||||
            clean = False # don't cleanup because we use the actual source tree to generate IDE files
 | 
					 | 
				
			||||||
        else:
 | 
					 | 
				
			||||||
            test = Test(p)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            # 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
 | 
					 | 
				
			||||||
            lib_symbols = []
 | 
					 | 
				
			||||||
            if options.macros:
 | 
					 | 
				
			||||||
                lib_symbols += options.macros
 | 
					 | 
				
			||||||
            for lib in LIBRARIES:
 | 
					 | 
				
			||||||
                if lib['build_dir'] in test.dependencies:
 | 
					 | 
				
			||||||
                    lib_macros = lib.get('macros', None)
 | 
					 | 
				
			||||||
                    if lib_macros is not None:
 | 
					 | 
				
			||||||
                        lib_symbols.extend(lib_macros)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if not options.build:
 | 
					 | 
				
			||||||
                # Substitute the library builds with the sources
 | 
					 | 
				
			||||||
                # TODO: Substitute also the other library build paths
 | 
					 | 
				
			||||||
                if MBED_LIBRARIES in test.dependencies:
 | 
					 | 
				
			||||||
                    test.dependencies.remove(MBED_LIBRARIES)
 | 
					 | 
				
			||||||
                    test.dependencies.append(MBED_BASE)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            # Build the project with the same directory structure of the mbed online IDE
 | 
					 | 
				
			||||||
            project_name = test.id
 | 
					 | 
				
			||||||
            project_dir = [join(EXPORT_WORKSPACE, project_name)]
 | 
					 | 
				
			||||||
            project_temp = EXPORT_TMP
 | 
					 | 
				
			||||||
            setup_user_prj(project_dir[0], test.source_dir, test.dependencies)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # Export to selected toolchain
 | 
					        # 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)
 | 
					        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)
 | 
				
			||||||
        if report['success']:
 | 
					        if report['success']:
 | 
				
			||||||
            if not zip:
 | 
					            if not zip:
 | 
				
			||||||
| 
						 | 
					@ -191,12 +153,4 @@ if __name__ == '__main__':
 | 
				
			||||||
            failures.append("%s::%s\t%s"% (mcu, ide, report['errormsg']))
 | 
					            failures.append("%s::%s\t%s"% (mcu, ide, report['errormsg']))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Prints export results
 | 
					    # Prints export results
 | 
				
			||||||
    print
 | 
					    print_results(successes, failures)
 | 
				
			||||||
    if len(successes) > 0:
 | 
					 | 
				
			||||||
        print "Successful exports:"
 | 
					 | 
				
			||||||
        for success in successes:
 | 
					 | 
				
			||||||
            print "  * %s"% success
 | 
					 | 
				
			||||||
    if len(failures) > 0:
 | 
					 | 
				
			||||||
        print "Failed exports:"
 | 
					 | 
				
			||||||
        for failure in failures:
 | 
					 | 
				
			||||||
            print "  * %s"% failure
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,111 @@
 | 
				
			||||||
 | 
					import sys
 | 
				
			||||||
 | 
					from os.path import join, abspath, dirname, exists, basename
 | 
				
			||||||
 | 
					ROOT = abspath(join(dirname(__file__), ".."))
 | 
				
			||||||
 | 
					sys.path.insert(0, ROOT)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from tools.paths import EXPORT_WORKSPACE, EXPORT_TMP
 | 
				
			||||||
 | 
					from tools.paths import MBED_BASE, MBED_LIBRARIES
 | 
				
			||||||
 | 
					from tools.export import export, setup_user_prj
 | 
				
			||||||
 | 
					from tools.utils import mkdir
 | 
				
			||||||
 | 
					from tools.tests import Test, TEST_MAP, TESTS
 | 
				
			||||||
 | 
					from tools.libraries import LIBRARIES
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					try:
 | 
				
			||||||
 | 
					    import tools.private_settings as ps
 | 
				
			||||||
 | 
					except:
 | 
				
			||||||
 | 
					    ps = object()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def get_program(n):
 | 
				
			||||||
 | 
					    p = TEST_MAP[n].n
 | 
				
			||||||
 | 
					    return p
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def get_test(p):
 | 
				
			||||||
 | 
					    return Test(p)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def get_test_from_name(n):
 | 
				
			||||||
 | 
					    if not n in TEST_MAP.keys():
 | 
				
			||||||
 | 
					        # Check if there is an alias for this in private_settings.py
 | 
				
			||||||
 | 
					        if getattr(ps, "test_alias", None) is not None:
 | 
				
			||||||
 | 
					            alias = ps.test_alias.get(n, "")
 | 
				
			||||||
 | 
					            if not alias in TEST_MAP.keys():
 | 
				
			||||||
 | 
					                return None
 | 
				
			||||||
 | 
					            else:
 | 
				
			||||||
 | 
					                n = alias
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            return None
 | 
				
			||||||
 | 
					    return get_program(n)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def get_lib_symbols(macros, src, program):
 | 
				
			||||||
 | 
					    # 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
 | 
				
			||||||
 | 
					    lib_symbols = []
 | 
				
			||||||
 | 
					    if macros:
 | 
				
			||||||
 | 
					        lib_symbols += macros
 | 
				
			||||||
 | 
					    if src:
 | 
				
			||||||
 | 
					        return lib_symbols
 | 
				
			||||||
 | 
					    test = get_test(program)
 | 
				
			||||||
 | 
					    for lib in LIBRARIES:
 | 
				
			||||||
 | 
					        if lib['build_dir'] in test.dependencies:
 | 
				
			||||||
 | 
					            lib_macros = lib.get('macros', None)
 | 
				
			||||||
 | 
					            if lib_macros is not None:
 | 
				
			||||||
 | 
					                lib_symbols.extend(lib_macros)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def setup_project(mcu, ide, program=None, source_dir=None, build=None):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    # 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 = source_dir
 | 
				
			||||||
 | 
					        project_name = TESTS[program] if program else "Unnamed_Project"
 | 
				
			||||||
 | 
					        project_temp = join(source_dir[0], 'projectfiles', '%s_%s' % (ide, mcu))
 | 
				
			||||||
 | 
					        mkdir(project_temp)
 | 
				
			||||||
 | 
					    else:
 | 
				
			||||||
 | 
					        test = get_test(program)
 | 
				
			||||||
 | 
					        if not build:
 | 
				
			||||||
 | 
					            # Substitute the library builds with the sources
 | 
				
			||||||
 | 
					            # TODO: Substitute also the other library build paths
 | 
				
			||||||
 | 
					            if MBED_LIBRARIES in test.dependencies:
 | 
				
			||||||
 | 
					                test.dependencies.remove(MBED_LIBRARIES)
 | 
				
			||||||
 | 
					                test.dependencies.append(MBED_BASE)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Build the project with the same directory structure of the mbed online IDE
 | 
				
			||||||
 | 
					        project_name = test.id
 | 
				
			||||||
 | 
					        project_dir = [join(EXPORT_WORKSPACE, project_name)]
 | 
				
			||||||
 | 
					        project_temp = EXPORT_TMP
 | 
				
			||||||
 | 
					        setup_user_prj(project_dir[0], test.source_dir, test.dependencies)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return project_dir, project_name, project_temp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def perform_export(dir, name, ide, mcu, temp, clean=False, zip=False, lib_symbols='',
 | 
				
			||||||
 | 
					                   sources_relative=False, progen_build=False):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    tmp_path, report = export(dir, name, ide, mcu, dir[0], temp, clean=clean,
 | 
				
			||||||
 | 
					                              make_zip=zip, extra_symbols=lib_symbols, sources_relative=sources_relative,
 | 
				
			||||||
 | 
					                              progen_build=progen_build)
 | 
				
			||||||
 | 
					    return tmp_path, report
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def print_results(successes, failures, skips = []):
 | 
				
			||||||
 | 
					    print
 | 
				
			||||||
 | 
					    if len(successes) > 0:
 | 
				
			||||||
 | 
					        print "Successful: "
 | 
				
			||||||
 | 
					        for success in successes:
 | 
				
			||||||
 | 
					            print "  * %s" % success
 | 
				
			||||||
 | 
					    if len(failures) > 0:
 | 
				
			||||||
 | 
					        print "Failed: "
 | 
				
			||||||
 | 
					        for failure in failures:
 | 
				
			||||||
 | 
					            print "  * %s" % failure
 | 
				
			||||||
 | 
					    if len(skips) > 0:
 | 
				
			||||||
 | 
					        print "Skipped: "
 | 
				
			||||||
 | 
					        for skip in skips:
 | 
				
			||||||
 | 
					            print "  * %s" % skip
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,169 @@
 | 
				
			||||||
 | 
					#!/usr/bin/env python
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					mbed SDK
 | 
				
			||||||
 | 
					Copyright (c) 2011-2013 ARM Limited
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					You may obtain a copy of the License at
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					limitations under the License.
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import sys
 | 
				
			||||||
 | 
					import argparse
 | 
				
			||||||
 | 
					import os
 | 
				
			||||||
 | 
					import shutil
 | 
				
			||||||
 | 
					from os.path import join, abspath, dirname, exists, basename
 | 
				
			||||||
 | 
					r=dirname(__file__)
 | 
				
			||||||
 | 
					ROOT = abspath(join(r, "..","..",".."))
 | 
				
			||||||
 | 
					sys.path.insert(0, ROOT)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from tools.export import EXPORTERS
 | 
				
			||||||
 | 
					from tools.targets import TARGET_NAMES, TARGET_MAP
 | 
				
			||||||
 | 
					from tools.project_api import setup_project, perform_export, print_results, get_test_from_name, get_lib_symbols
 | 
				
			||||||
 | 
					from project_generator_definitions.definitions import ProGenDef
 | 
				
			||||||
 | 
					from tools.utils import args_error
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ProgenBuildTest():
 | 
				
			||||||
 | 
					    def __init__(self, desired_ides, targets):
 | 
				
			||||||
 | 
					        #map of targets and the ides that can build programs for them
 | 
				
			||||||
 | 
					        self.target_ides = {}
 | 
				
			||||||
 | 
					        for target in targets:
 | 
				
			||||||
 | 
					            self.target_ides[target] =[]
 | 
				
			||||||
 | 
					            for ide in desired_ides:
 | 
				
			||||||
 | 
					                if target in EXPORTERS[ide].TARGETS:
 | 
				
			||||||
 | 
					                    #target is supported by ide
 | 
				
			||||||
 | 
					                    self.target_ides[target].append(ide)
 | 
				
			||||||
 | 
					            if len(self.target_ides[target]) == 0:
 | 
				
			||||||
 | 
					                del self.target_ides[target]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @staticmethod
 | 
				
			||||||
 | 
					    def get_pgen_targets(ides):
 | 
				
			||||||
 | 
					        #targets supported by pgen and desired ides for tests
 | 
				
			||||||
 | 
					        targs = []
 | 
				
			||||||
 | 
					        for ide in ides:
 | 
				
			||||||
 | 
					            for target in TARGET_NAMES:
 | 
				
			||||||
 | 
					                if target not in targs and hasattr(TARGET_MAP[target],'progen') \
 | 
				
			||||||
 | 
					                        and ProGenDef(ide).is_supported(TARGET_MAP[target].progen['target']):
 | 
				
			||||||
 | 
					                    targs.append(target)
 | 
				
			||||||
 | 
					        return targs
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @staticmethod
 | 
				
			||||||
 | 
					    def handle_project_files(project_dir, mcu, test, tool, clean=False):
 | 
				
			||||||
 | 
					        log = ''
 | 
				
			||||||
 | 
					        if tool == 'uvision' or tool == 'uvision5':
 | 
				
			||||||
 | 
					            log = os.path.join(project_dir,"build","build_log.txt")
 | 
				
			||||||
 | 
					        elif tool == 'iar':
 | 
				
			||||||
 | 
					            log = os.path.join(project_dir, 'build_log.txt')
 | 
				
			||||||
 | 
					        try:
 | 
				
			||||||
 | 
					            with open(log, 'r') as f:
 | 
				
			||||||
 | 
					                print f.read()
 | 
				
			||||||
 | 
					        except:
 | 
				
			||||||
 | 
					            return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        prefix = "_".join([test, mcu, tool])
 | 
				
			||||||
 | 
					        log_name = os.path.join(os.path.dirname(project_dir), prefix+"_log.txt")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        #check if a log already exists for this platform+test+ide
 | 
				
			||||||
 | 
					        if os.path.exists(log_name):
 | 
				
			||||||
 | 
					            #delete it if so
 | 
				
			||||||
 | 
					            os.remove(log_name)
 | 
				
			||||||
 | 
					        os.rename(log, log_name)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if clean:
 | 
				
			||||||
 | 
					            shutil.rmtree(project_dir, ignore_errors=True)
 | 
				
			||||||
 | 
					            return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def generate_and_build(self, tests, clean=False):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        #build results
 | 
				
			||||||
 | 
					        successes = []
 | 
				
			||||||
 | 
					        failures = []
 | 
				
			||||||
 | 
					        skips = []
 | 
				
			||||||
 | 
					        for mcu, ides in self.target_ides.items():
 | 
				
			||||||
 | 
					            for test in tests:
 | 
				
			||||||
 | 
					                #resolve name alias
 | 
				
			||||||
 | 
					                test = get_test_from_name(test)
 | 
				
			||||||
 | 
					                for ide in ides:
 | 
				
			||||||
 | 
					                    lib_symbols = get_lib_symbols(None, None, test)
 | 
				
			||||||
 | 
					                    project_dir, project_name, project_temp = setup_project(mcu, ide, test)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    dest_dir = os.path.dirname(project_temp)
 | 
				
			||||||
 | 
					                    destination = os.path.join(dest_dir,"_".join([project_name, mcu, ide]))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    tmp_path, report = perform_export(project_dir, project_name, ide, mcu, destination,
 | 
				
			||||||
 | 
					                                                      lib_symbols=lib_symbols, progen_build = True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    if report['success']:
 | 
				
			||||||
 | 
					                        successes.append("build for %s::%s\t%s" % (mcu, ide, project_name))
 | 
				
			||||||
 | 
					                    elif report['skip']:
 | 
				
			||||||
 | 
					                        skips.append("%s::%s\t%s" % (mcu, ide, project_name))
 | 
				
			||||||
 | 
					                    else:
 | 
				
			||||||
 | 
					                        failures.append("%s::%s\t%s for %s" % (mcu, ide, report['errormsg'], project_name))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    ProgenBuildTest.handle_project_files(destination, mcu, project_name, ide, clean)
 | 
				
			||||||
 | 
					        return successes, failures, skips
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if __name__ == '__main__':
 | 
				
			||||||
 | 
					    accepted_ides = ["iar", "uvision", "uvision5"]
 | 
				
			||||||
 | 
					    accepted_targets = sorted(ProgenBuildTest.get_pgen_targets(accepted_ides))
 | 
				
			||||||
 | 
					    default_tests = ["MBED_BLINKY"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    parser = argparse.ArgumentParser(description = "Test progen builders. Leave any flag off to run with all possible options.")
 | 
				
			||||||
 | 
					    parser.add_argument("-i", "--IDEs",
 | 
				
			||||||
 | 
					                      nargs = '+',
 | 
				
			||||||
 | 
					                      dest="ides",
 | 
				
			||||||
 | 
					                      help="tools you wish to perfrom build tests. (%s)" % ', '.join(accepted_ides),
 | 
				
			||||||
 | 
					                      default = accepted_ides)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    parser.add_argument("-n",
 | 
				
			||||||
 | 
					                    nargs='+',
 | 
				
			||||||
 | 
					                    dest="tests",
 | 
				
			||||||
 | 
					                    help="names of desired test programs",
 | 
				
			||||||
 | 
					                    default = default_tests)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    parser.add_argument("-m", "--mcus",
 | 
				
			||||||
 | 
					                      nargs='+',
 | 
				
			||||||
 | 
					                      dest ="targets",
 | 
				
			||||||
 | 
					                      help="generate project for the given MCUs (%s)" % '\n '.join(accepted_targets),
 | 
				
			||||||
 | 
					                      default = accepted_targets)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    parser.add_argument("-c", "--clean",
 | 
				
			||||||
 | 
					                        dest="clean",
 | 
				
			||||||
 | 
					                        action = "store_true",
 | 
				
			||||||
 | 
					                        help="clean up the exported project files",
 | 
				
			||||||
 | 
					                        default=False)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    options = parser.parse_args()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    tests = options.tests
 | 
				
			||||||
 | 
					    ides = [ide.lower() for ide in options.ides]
 | 
				
			||||||
 | 
					    targets = [target.upper() for target in options.targets]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if any(get_test_from_name(test) is None for test in tests):
 | 
				
			||||||
 | 
					        args_error(parser, "[ERROR] test name not recognized")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if any(target not in accepted_targets for target in targets):
 | 
				
			||||||
 | 
					        args_error(parser, "[ERROR] mcu must be one of the following:\n %s" % '\n '.join(accepted_targets))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if any(ide not in accepted_ides for ide in ides):
 | 
				
			||||||
 | 
					        args_error(parser, "[ERROR] ide must be in %s" % ', '.join(accepted_ides))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    build_test = ProgenBuildTest(ides, targets)
 | 
				
			||||||
 | 
					    successes, failures, skips = build_test.generate_and_build(tests, options.clean)
 | 
				
			||||||
 | 
					    print_results(successes, failures, skips)
 | 
				
			||||||
 | 
					    sys.exit(len(failures))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue