Integrate with mbeb-cli build system

PSA code generation will be called automatically upon mbed invocation.
The autogenerated files will be created under <mbed-os-root>/PSA_AUTOGEN directory.
pull/10447/head
Alexander Zilberkant 2019-04-21 15:33:32 +03:00 committed by Alexander Zilberkant
parent 117e3e82b6
commit 91505184d3
11 changed files with 151 additions and 45 deletions

3
.gitignore vendored
View File

@ -97,3 +97,6 @@ test_suite.json
# default delivery dir
DELIVERY/
# Directory hosting PSA autogenerated source files
PSA_AUTOGEN/

View File

@ -21,7 +21,7 @@ from __future__ import print_function, division, absolute_import
import sys
from time import time
from os.path import join, abspath, dirname
from os.path import join, abspath, dirname, normpath
# Be sure that the tools directory is in the search path
@ -44,7 +44,8 @@ from tools.utils import argparse_filestring_type, args_error, argparse_many
from tools.utils import argparse_dir_not_parent
from tools.utils import NoValidToolchainException
from tools.utils import print_end_warnings
from tools.paths import is_relative_to_root
from tools.psa import generate_psa_sources, clean_psa_autogen
from tools.resources import OsAndSpeResourceFilter
def main():
start = time()
@ -171,6 +172,9 @@ def main():
skipped = []
end_warnings = []
if options.clean:
clean_psa_autogen()
for toolchain in toolchains:
for target_name in targets:
target = Target.get_target(target_name)
@ -192,10 +196,17 @@ def main():
notifier = TerminalNotifier(options.verbose, options.silent)
profile = extract_profile(parser, options, internal_tc_name)
if target.is_PSA_secure_target and \
not is_relative_to_root(options.source_dir):
options.source_dir = ROOT
if options.source_dir:
if target.is_PSA_target:
generate_psa_sources(
source_dirs=options.source_dir,
ignore_paths=[options.build_dir]
)
resource_filter = None
if target.is_PSA_secure_target:
resource_filter = OsAndSpeResourceFilter()
lib_build_res = build_library(
options.source_dir, options.build_dir, target, toolchain_name,
jobs=options.jobs,
@ -205,7 +216,8 @@ def main():
name=options.artifact_name,
build_profile=profile,
ignore=options.ignore,
notify = notifier,
notify=notifier,
resource_filter=resource_filter
)
else:
lib_build_res = build_mbed_libs(

View File

@ -41,7 +41,7 @@ from .paths import (MBED_CMSIS_PATH, MBED_TARGETS_PATH, MBED_LIBRARIES,
MBED_CONFIG_FILE, MBED_LIBRARIES_DRIVERS,
MBED_LIBRARIES_PLATFORM, MBED_LIBRARIES_HAL,
BUILD_DIR)
from .resources import Resources, FileType, FileRef
from .resources import Resources, FileType, FileRef, PsaManifestResourceFilter
from .notifier.mock import MockNotifier
from .targets import TARGET_NAMES, TARGET_MAP, CORE_ARCH, Target
from .libraries import Library
@ -511,7 +511,7 @@ def build_project(src_paths, build_path, target, toolchain_name,
report=None, properties=None, project_id=None,
project_description=None, config=None,
app_config=None, build_profile=None, stats_depth=None,
ignore=None, spe_build=False):
ignore=None, resource_filter=None):
""" Build a project. A project may be a test or a user program.
Positional arguments:
@ -539,6 +539,7 @@ def build_project(src_paths, build_path, target, toolchain_name,
build_profile - a dict of flags that will be passed to the compiler
stats_depth - depth level for memap to display file/dirs
ignore - list of paths to add to mbedignore
resource_filter - can be used for filtering out resources after scan
"""
# Convert src_path to a list if needed
if not isinstance(src_paths, list):
@ -581,8 +582,8 @@ def build_project(src_paths, build_path, target, toolchain_name,
try:
resources = Resources(notify).scan_with_toolchain(
src_paths, toolchain, inc_dirs=inc_dirs)
if spe_build:
resources.filter_spe()
resources.filter(resource_filter)
# Change linker script if specified
if linker_script is not None:
resources.add_file_ref(FileType.LD_SCRIPT, linker_script, linker_script)
@ -664,7 +665,7 @@ def build_library(src_paths, build_path, target, toolchain_name,
archive=True, notify=None, macros=None, inc_dirs=None, jobs=1,
report=None, properties=None, project_id=None,
remove_config_header_file=False, app_config=None,
build_profile=None, ignore=None):
build_profile=None, ignore=None, resource_filter=None):
""" Build a library
Positional arguments:
@ -690,6 +691,7 @@ def build_library(src_paths, build_path, target, toolchain_name,
app_config - location of a chosen mbed_app.json file
build_profile - a dict of flags that will be passed to the compiler
ignore - list of paths to add to mbedignore
resource_filter - can be used for filtering out resources after scan
"""
# Convert src_path to a list if needed
@ -750,6 +752,8 @@ def build_library(src_paths, build_path, target, toolchain_name,
try:
res = Resources(notify).scan_with_toolchain(
src_paths, toolchain, dependencies_paths, inc_dirs=inc_dirs)
res.filter(resource_filter)
res.filter(PsaManifestResourceFilter())
# Copy headers, objects and static libraries - all files needed for
# static lib

View File

@ -208,7 +208,7 @@ def export_project(src_paths, export_path, target, ide, libraries_paths=None,
linker_script=None, notify=None, name=None, inc_dirs=None,
jobs=1, config=None, macros=None, zip_proj=None,
inc_repos=False, build_profile=None, app_config=None,
ignore=None):
ignore=None, resource_filter=None):
"""Generates a project file and creates a zip archive if specified
Positional Arguments:
@ -230,6 +230,7 @@ def export_project(src_paths, export_path, target, ide, libraries_paths=None,
zip_proj - string name of the zip archive you wish to creat (exclude arg
if you do not wish to create an archive
ignore - list of paths to add to mbedignore
resource_filter - can be used for filtering out resources after scan
"""
# Convert src_path to a list if needed
@ -279,6 +280,8 @@ def export_project(src_paths, export_path, target, ide, libraries_paths=None,
if toolchain.config.name:
name = toolchain.config.name
resources.filter(resource_filter)
files, exporter = generate_project_files(
resources, export_path, target, name, toolchain, ide, zip_proj, macros=macros
)

View File

@ -21,7 +21,7 @@ TEST BUILD & RUN
from __future__ import print_function
from builtins import str
import sys
from os.path import join, abspath, dirname
from os.path import join, abspath, dirname, normpath
# Be sure that the tools directory is in the search path
ROOT = abspath(join(dirname(__file__), ".."))
@ -34,7 +34,6 @@ from tools.paths import MBED_LIBRARIES
from tools.paths import RPC_LIBRARY
from tools.paths import USB_LIBRARIES
from tools.paths import DSP_LIBRARIES
from tools.paths import is_relative_to_root
from tools.tests import TESTS, Test, TEST_MAP
from tools.tests import TEST_MBED_LIB
from tools.tests import test_known, test_name_known
@ -56,7 +55,8 @@ from tools.utils import print_end_warnings
from tools.utils import print_large_string
from tools.settings import ROOT
from tools.targets import Target
from tools.psa import generate_psa_sources, clean_psa_autogen
from tools.resources import OsAndSpeResourceFilter
def default_args_dict(options):
return dict(
@ -74,7 +74,8 @@ def wrapped_build_project(src_dir, build_dir, mcu, end_warnings, options, *args,
error = False
try:
bin_file, update_file = build_project(
src_dir, build_dir, mcu, *args, **kwargs
src_dir, build_dir, mcu,
*args, **kwargs
)
if update_file:
print('Update Image: %s' % update_file)
@ -304,6 +305,10 @@ def main():
elif options.list_tests is True:
print('\n'.join(map(str, sorted(TEST_MAP.values()))))
else:
if options.clean:
clean_psa_autogen()
# Target
if options.mcu is None:
args_error(parser, "argument -m/--mcu is required")
@ -315,9 +320,6 @@ def main():
toolchain = options.tool[0]
target = Target.get_target(mcu)
if target.is_PSA_secure_target and \
not is_relative_to_root(options.source_dir):
options.source_dir = ROOT
if (options.program is None) and (not options.source_dir):
args_error(parser, "one of -p, -n, or --source is required")
@ -337,6 +339,16 @@ def main():
args_error(parser, str(e))
if options.source_dir is not None:
if target.is_PSA_target:
generate_psa_sources(
source_dirs=options.source_dir,
ignore_paths=[options.build_dir]
)
resource_filter = None
if target.is_PSA_secure_target:
resource_filter = OsAndSpeResourceFilter()
wrapped_build_project(
options.source_dir,
options.build_dir,
@ -346,6 +358,7 @@ def main():
toolchain_name,
notify=notify,
build_profile=extract_profile(parser, options, internal_tc_name),
resource_filter=resource_filter,
**default_args_dict(options)
)
else:

View File

@ -85,11 +85,3 @@ CPPUTEST_TESTRUNNER_SCR = join(TEST_DIR, "utest", "testrunner")
CPPUTEST_TESTRUNNER_INC = join(TEST_DIR, "utest", "testrunner")
CPPUTEST_LIBRARY = join(BUILD_DIR, "cpputest")
def is_relative_to_root(dirs):
if not isinstance(dirs, list):
dirs = [dirs]
dirs = [realpath(d) for d in dirs]
out = commonprefix(dirs + [ROOT])
return out == ROOT

View File

@ -40,7 +40,7 @@ from tools.export import (
)
from tools.tests import TESTS, TEST_MAP
from tools.tests import test_known, test_name_known, Test
from tools.targets import TARGET_NAMES
from tools.targets import TARGET_NAMES, Target
from tools.utils import (
argparse_filestring_type,
argparse_profile_filestring_type,
@ -53,6 +53,8 @@ from tools.utils import print_large_string
from tools.utils import NotSupportedException
from tools.options import extract_profile, list_profiles, extract_mcus
from tools.notifier.term import TerminalNotifier
from tools.psa import generate_psa_sources, clean_psa_autogen
from tools.resources import OsAndSpeResourceFilter
""" The CLI entry point for exporting projects from the mbed tools to any of the
supported IDEs or project structures.
@ -126,7 +128,7 @@ def setup_project(
def export(target, ide, build=None, src=None, macros=None, project_id=None,
zip_proj=False, build_profile=None, export_path=None, notify=None,
app_config=None, ignore=None):
app_config=None, ignore=None, resource_filter=None):
"""Do an export of a project.
Positional arguments:
@ -141,6 +143,7 @@ def export(target, ide, build=None, src=None, macros=None, project_id=None,
clean - start from a clean state before exporting
zip_proj - create a zip file or not
ignore - list of paths to add to mbedignore
resource_filter - can be used for filtering out resources after scan
Returns an object of type Exporter (tools/exports/exporters.py)
"""
@ -168,7 +171,8 @@ def export(target, ide, build=None, src=None, macros=None, project_id=None,
build_profile=build_profile,
notify=TerminalNotifier(),
app_config=app_config,
ignore=ignore
ignore=ignore,
resource_filter=resource_filter
)
def clean(source_dir):
@ -376,6 +380,7 @@ def main():
if options.clean:
clean(options.source_dir)
clean_psa_autogen()
ide = resolve_exporter_alias(options.ide)
exporter, toolchain_name = get_exporter_toolchain(ide)
@ -385,6 +390,16 @@ def main():
args_error(parser, "%s not supported by %s" % (mcu, ide))
try:
target = Target.get_target(mcu)
if target.is_PSA_target:
generate_psa_sources(source_dirs=options.source_dir,
ignore_paths=[]
)
resource_filter = None
if target.is_PSA_secure_target:
resource_filter = OsAndSpeResourceFilter()
export(
mcu,
ide,
@ -396,12 +411,14 @@ def main():
build_profile=profile,
app_config=options.app_config,
export_path=options.build_dir,
ignore=options.ignore
ignore=options.ignore,
resource_filter=resource_filter
)
except NotSupportedException as exc:
print("[Not Supported] %s" % str(exc))
exit(1)
exit(0)
if __name__ == "__main__":
main()

View File

@ -41,6 +41,7 @@ from os import walk, sep
from os.path import (join, splitext, dirname, relpath, basename, split, normpath,
abspath, exists)
from tools.settings import ROOT
from .ignore import MbedIgnoreSet, IGNORE_FILENAME
# Support legacy build conventions: the original mbed build system did not have
@ -594,7 +595,45 @@ class Resources(object):
config.load_resources(self)
return self
def filter_spe(self):
spe_filter = lambda x: 'COMPONENT_SPE' in x
for type in [FileType.ASM_SRC, FileType.C_SRC, FileType.CPP_SRC]:
self._file_refs[type] = set([f for f in self._file_refs[type] if spe_filter(f.name) or spe_filter(f.path)])
def filter(self, res_filter):
if res_filter is None:
return
for t in res_filter.file_types:
self._file_refs[t] = set(filter(
res_filter.predicate, self._file_refs[t]))
class ResourceFilter(object):
def __init__(self, file_types):
self.file_types = file_types
def predicate(self, ref):
raise NotImplemented
class SpeOnlyResourceFilter(ResourceFilter):
def __init__(self):
ResourceFilter.__init__(
self, [FileType.ASM_SRC, FileType.C_SRC, FileType.CPP_SRC])
def predicate(self, ref):
return 'COMPONENT_SPE' in ref.name
class OsAndSpeResourceFilter(ResourceFilter):
def __init__(self):
ResourceFilter.__init__(
self, [FileType.ASM_SRC, FileType.C_SRC, FileType.CPP_SRC])
def predicate(self, ref):
return ROOT in abspath(ref.name) or 'COMPONENT_SPE' in ref.name
class PsaManifestResourceFilter(ResourceFilter):
def __init__(self):
ResourceFilter.__init__(
self, [FileType.JSON])
def predicate(self, ref):
return not ref.name.endswith('_psa.json')

View File

@ -387,6 +387,10 @@ class Target(namedtuple(
def is_PSA_non_secure_target(self):
return 'NSPE_Target' in self.labels
@property
def is_PSA_target(self):
return self.is_PSA_secure_target or self.is_PSA_non_secure_target
def get_post_build_hook(self, toolchain_labels):
"""Initialize the post-build hooks for a toolchain. For now, this
function only allows "post binary" hooks (hooks that are executed

View File

@ -43,7 +43,8 @@ from tools.utils import argparse_dir_not_parent
from tools.utils import print_end_warnings
from tools.settings import ROOT
from tools.targets import Target
from tools.paths import is_relative_to_root
from tools.psa import generate_psa_sources, clean_psa_autogen
from tools.resources import OsAndSpeResourceFilter, SpeOnlyResourceFilter
def main():
error = False
@ -150,7 +151,6 @@ def main():
args_error(parser, "argument -m/--mcu is required")
mcu = extract_mcus(parser, options)[0]
target = Target.get_target(mcu)
mcu_secured = target.is_PSA_secure_target
# Toolchain
if options.tool is None:
@ -212,14 +212,15 @@ def main():
print_tests(tests, options.format)
sys.exit(0)
else:
if options.clean:
clean_psa_autogen()
# Build all tests
if not options.build_dir:
args_error(parser, "argument --build is required")
if mcu_secured and not is_relative_to_root(options.source_dir):
base_source_paths = ROOT
else:
base_source_paths = options.source_dir
base_source_paths = options.source_dir
# Default base source path is the current directory
if not base_source_paths:
@ -231,6 +232,16 @@ def main():
library_build_success = False
profile = extract_profile(parser, options, internal_tc_name)
try:
resource_filter = None
if target.is_PSA_secure_target:
resource_filter = OsAndSpeResourceFilter()
if target.is_PSA_target:
generate_psa_sources(
source_dirs=base_source_paths,
ignore_paths=[options.build_dir]
)
# Build sources
notify = TerminalNotifier(options.verbose)
build_library(base_source_paths, options.build_dir, mcu,
@ -241,7 +252,9 @@ def main():
notify=notify, archive=False,
app_config=config,
build_profile=profile,
ignore=options.ignore)
ignore=options.ignore,
resource_filter=resource_filter
)
library_build_success = True
except ToolException as e:
@ -260,6 +273,11 @@ def main():
if not library_build_success:
print("Failed to build library")
else:
if target.is_PSA_secure_target:
resource_filter = SpeOnlyResourceFilter()
else:
resource_filter = None
# Build all the tests
notify = TerminalNotifier(options.verbose)
test_build_success, test_build = build_tests(
@ -279,7 +297,7 @@ def main():
build_profile=profile,
stats_depth=options.stats_depth,
ignore=options.ignore,
spe_build=mcu_secured)
resource_filter=resource_filter)
# If a path to a test spec is provided, write it to a file
if options.test_spec:

View File

@ -2120,7 +2120,8 @@ def build_tests(tests, base_source_paths, build_path, target, toolchain_name,
clean=False, notify=None, jobs=1, macros=None,
silent=False, report=None, properties=None,
continue_on_build_fail=False, app_config=None,
build_profile=None, stats_depth=None, ignore=None, spe_build=False):
build_profile=None, stats_depth=None, ignore=None,
resource_filter=None):
"""Given the data structure from 'find_tests' and the typical build parameters,
build all the tests
@ -2179,7 +2180,7 @@ def build_tests(tests, base_source_paths, build_path, target, toolchain_name,
'toolchain_paths': TOOLCHAIN_PATHS,
'stats_depth': stats_depth,
'notify': MockNotifier(),
'spe_build': spe_build
'resource_filter': resource_filter
}
results.append(p.apply_async(build_test_worker, args, kwargs))