mirror of https://github.com/ARMmbed/mbed-os.git
Merge pull request #2179 from sarahmarshy/progen_build_tests_v2
IDE build tests with progenpull/2185/head
commit
4e1ac4dba2
|
|
@ -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 = []
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,7 @@ class IAREmbeddedWorkbench(Exporter):
|
||||||
continue
|
continue
|
||||||
return self._targets_supported
|
return self._targets_supported
|
||||||
|
|
||||||
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 = {}
|
||||||
|
|
@ -78,7 +78,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():
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,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 = {}
|
||||||
|
|
@ -99,4 +99,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)
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,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 = {}
|
||||||
|
|
@ -102,4 +102,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