Skip to content

Tools: Scan for "components" #7644

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Aug 28, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 18 additions & 34 deletions tools/resources/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@
from os.path import (join, splitext, dirname, relpath, basename, split, normcase,
abspath, exists)

from .ignore import MbedIgnoreSet, IGNORE_FILENAME

# Support legacy build conventions: the original mbed build system did not have
# standard labels for the "TARGET_" and "TOOLCHAIN_" specific directories, but
# had the knowledge of a list of these directories to be ignored.
Expand Down Expand Up @@ -135,16 +137,15 @@ def __init__(self, notify, collect_ignores=False):

# Incremental scan related
self._label_paths = []
self._labels = {"TARGET": [], "TOOLCHAIN": [], "FEATURE": []}
self._labels = {
"TARGET": [], "TOOLCHAIN": [], "FEATURE": [], "COMPONENT": []
}
self._prefixed_labels = set()

# Path seperator style (defaults to OS-specific seperator)
self._sep = sep

# Ignore patterns from .mbedignore files and add_ignore_patters
self._ignore_patterns = []
self._ignore_regex = re.compile("$^")

self._ignoreset = MbedIgnoreSet()

def ignore_dir(self, directory):
if self._collect_ignores:
Expand Down Expand Up @@ -227,6 +228,8 @@ def _add_labels(self, prefix, labels):

def add_target_labels(self, target):
self._add_labels("TARGET", target.labels)
self._add_labels("COMPONENT", target.components)
self.add_features(target.features)

def add_features(self, features):
self._add_labels("FEATURE", features)
Expand All @@ -237,27 +240,9 @@ def add_toolchain_labels(self, toolchain):
self._legacy_ignore_dirs -= set(
[toolchain.target.name, LEGACY_TOOLCHAIN_NAMES[toolchain.name]])

def is_ignored(self, file_path):
"""Check if file path is ignored by any .mbedignore thus far"""
return self._ignore_regex.match(normcase(file_path))

def add_ignore_patterns(self, root, base_path, patterns):
"""Add a series of patterns to the ignored paths

Positional arguments:
root - the directory containing the ignore file
base_path - the location that the scan started from
patterns - the list of patterns we will ignore in the future
"""
real_base = relpath(root, base_path)
if real_base == ".":
self._ignore_patterns.extend(normcase(p) for p in patterns)
else:
self._ignore_patterns.extend(
normcase(join(real_base, pat)) for pat in patterns)
if self._ignore_patterns:
self._ignore_regex = re.compile("|".join(
fnmatch.translate(p) for p in self._ignore_patterns))
self._ignoreset.add_ignore_patterns(real_base, patterns)

def _not_current_label(self, dirname, label_type):
return (dirname.startswith(label_type + "_") and
Expand Down Expand Up @@ -401,15 +386,13 @@ def add_directory(

for root, dirs, files in walk(path, followlinks=True):
# Check if folder contains .mbedignore
if ".mbedignore" in files:
with open (join(root,".mbedignore"), "r") as f:
lines=f.readlines()
lines = [l.strip() for l in lines
if l.strip() != "" and not l.startswith("#")]
self.add_ignore_patterns(root, base_path, lines)
if IGNORE_FILENAME in files:
real_base = relpath(root, base_path)
self._ignoreset.add_mbedignore(
real_base, join(root, IGNORE_FILENAME))

root_path =join(relpath(root, base_path))
if self.is_ignored(join(root_path,"")):
if self._ignoreset.is_ignored(join(root_path,"")):
self.ignore_dir(root_path)
dirs[:] = []
continue
Expand All @@ -421,12 +404,12 @@ def add_directory(
self.add_file_ref(FileType.REPO_DIR, fake_path, dir_path)

if (any(self._not_current_label(d, t) for t
in ['TARGET', 'TOOLCHAIN', 'FEATURE'])):
in self._labels.keys())):
self._label_paths.append((dir_path, base_path, into_path))
self.ignore_dir(dir_path)
dirs.remove(d)
elif (d.startswith('.') or d in self._legacy_ignore_dirs or
self.is_ignored(join(root_path, d, ""))):
self._ignoreset.is_ignored(join(root_path, d, ""))):
self.ignore_dir(dir_path)
dirs.remove(d)

Expand Down Expand Up @@ -468,7 +451,7 @@ def _add_file(self, file_path, base_path, into_path):
scanning starting as base_path
"""

if (self.is_ignored(relpath(file_path, base_path)) or
if (self._ignoreset.is_ignored(relpath(file_path, base_path)) or
basename(file_path).startswith(".")):
self.ignore_dir(relpath(file_path, base_path))
return
Expand Down Expand Up @@ -546,3 +529,4 @@ def scan_with_config(self, src_paths, config):
self.add_directory(path)
config.load_resources(self)
return self

69 changes: 69 additions & 0 deletions tools/resources/ignore.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# 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 fnmatch
import re
from os.path import normcase, join


IGNORE_FILENAME = ".mbedignore"


class MbedIgnoreSet(object):
"""
# The mbedignore rules as an object

A project in Mbed OS contains metadata files that exclude files from a build.
These rules are stored as `fnmatch` patterns in text in a files named `.mbedignore`.
"""

def __init__(self):
self._ignore_patterns = []
self._ignore_regex = re.compile("$^")

def is_ignored(self, file_path):
"""Check if file path is ignored by any .mbedignore thus far"""
return self._ignore_regex.match(normcase(file_path))

def add_ignore_patterns(self, in_name, patterns):
"""Ignore all files and directories matching the paterns in
directories named by in_name.

Positional arguments:
in_name - the filename prefix that this ignore will apply to
patterns - the list of patterns we will ignore in the future
"""
if in_name == ".":
self._ignore_patterns.extend(normcase(p) for p in patterns)
else:
self._ignore_patterns.extend(
normcase(join(in_name, pat)) for pat in patterns)
if self._ignore_patterns:
self._ignore_regex = re.compile("|".join(
fnmatch.translate(p) for p in self._ignore_patterns))

def add_mbedignore(self, in_name, filepath):
"""Add a series of patterns to the ignored paths

Positional arguments:
in_name - the filename prefix that this ignore will apply to
patterns - the list of patterns we will ignore in the future
"""
with open (filepath) as f:
patterns = [l.strip() for l in f
if l.strip() != "" and not l.startswith("#")]
self.add_ignore_patterns(in_name, patterns)


5 changes: 2 additions & 3 deletions tools/targets/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ def wrapper(*args, **kwargs):

# Cumulative attributes can have values appended to them, so they
# need to be computed differently than regular attributes
CUMULATIVE_ATTRIBUTES = ['extra_labels', 'macros', 'device_has', 'features']
CUMULATIVE_ATTRIBUTES = ['extra_labels', 'macros', 'device_has', 'features', 'components']


def get_resolution_order(json_data, target_name, order, level=0):
Expand Down Expand Up @@ -222,8 +222,7 @@ def __getattr_cumulative(self, attrname):
def_idx = idx
break
else:
raise AttributeError("Attribute '%s' not found in target '%s'"
% (attrname, self.name))
return []
# Get the starting value of the attribute
starting_value = (tdata[self.resolution_order[def_idx][0]][attrname]
or [])[:]
Expand Down
21 changes: 16 additions & 5 deletions tools/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
from Queue import Queue, Empty
except ImportError:
from queue import Queue, Empty
from os.path import join, exists, basename, relpath, isdir
from os.path import join, exists, basename, relpath, isdir, isfile
from threading import Thread, Lock
from multiprocessing import Pool, cpu_count
from subprocess import Popen, PIPE
Expand All @@ -55,6 +55,7 @@
from tools.utils import construct_enum
from tools.memap import MemapParser
from tools.targets import TARGET_MAP, Target
from tools.config import Config
import tools.test_configs as TestConfig
from tools.test_db import BaseDBAccess
from tools.build_api import build_project, build_mbed_libs, build_lib
Expand All @@ -66,7 +67,7 @@
from tools.build_api import add_result_to_report
from tools.build_api import prepare_toolchain
from tools.build_api import get_config
from tools.resources import Resources
from tools.resources import Resources, MbedIgnoreSet, IGNORE_FILENAME
from tools.libraries import LIBRARIES, LIBRARY_MAP
from tools.options import extract_profile
from tools.toolchains import TOOLCHAIN_PATHS
Expand Down Expand Up @@ -2082,19 +2083,29 @@ def find_tests(base_dir, target_name, toolchain_name, app_config=None):
# List of common folders: (predicate function, path) tuple
commons = []

config = Config(target_name, base_dir, app_config)

# Scan the directory for paths to probe for 'TESTS' folders
base_resources = Resources(MockNotifier(), collect_ignores=True)
base_resources.add_directory(base_dir)
base_resources.scan_with_config(base_dir, config)

dirs = [d for d in base_resources.ignored_dirs if basename(d) == 'TESTS']
ignoreset = MbedIgnoreSet()

for directory in dirs:
ignorefile = join(directory, IGNORE_FILENAME)
if isfile(ignorefile):
ignoreset.add_mbedignore(directory, ignorefile)
for test_group_directory in os.listdir(directory):
grp_dir = join(directory, test_group_directory)
if not isdir(grp_dir):
if not isdir(grp_dir) or ignoreset.is_ignored(grp_dir):
continue
grpignorefile = join(grp_dir, IGNORE_FILENAME)
if isfile(grpignorefile):
ignoreset.add_mbedignore(grp_dir, grpignorefile)
for test_case_directory in os.listdir(grp_dir):
d = join(directory, test_group_directory, test_case_directory)
if not isdir(d):
if not isdir(d) or ignoreset.is_ignored(d):
continue
special_dirs = ['host_tests', 'COMMON']
if test_group_directory not in special_dirs and test_case_directory not in special_dirs:
Expand Down
3 changes: 3 additions & 0 deletions tools/toolchains/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,8 @@ def get_symbols(self, for_asm=False):
self.cxx_symbols += ["DEVICE_" + data + "=1" for data in self.target.device_has]
# Add target's features
self.cxx_symbols += ["FEATURE_" + data + "=1" for data in self.target.features]
# Add target's components
self.cxx_symbols += ["COMPONENT_" + data + "=1" for data in self.target.components]
# Add extra symbols passed via 'macros' parameter
self.cxx_symbols += self.macros

Expand All @@ -224,6 +226,7 @@ def get_labels(self):
self.labels = {
'TARGET': self.target.labels,
'FEATURE': self.target.features,
'COMPONENT': self.target.components,
'TOOLCHAIN': toolchain_labels
}

Expand Down