def glob(include, exclude=None, excludes=None, allow_empty=False): """This function can be called in BUILD to specify a set of files using patterns. Args: include:List[str], file patterns to be matched. exclude:Optional[List[str]], file patterns to be removed from the result. allow_empty:bool: Whether a empty result is a error. Patterns may contain shell-like wildcards, such as * , ? , or [charset]. Additionally, the path element '**' matches any subpath. """ from blade import build_manager # pylint: disable=import-outside-toplevel source_dir = Path(build_manager.instance.get_current_source_path()) source_loc = source_location(os.path.join(str(source_dir), 'BUILD')) include = var_to_list(include) severity = config.get_item('global_config', 'glob_error_severity') output = getattr(console, severity) if excludes: output('%s %s: "excludes" is deprecated, use "exclude" instead' % (source_loc, severity), prefix=False) exclude = var_to_list(exclude) + var_to_list(excludes) def includes_iterator(): results = [] for pattern in include: for path in source_dir.glob(pattern): if path.is_file() and not path.name.startswith('.'): results.append(path.relative_to(source_dir)) return results def is_special(pattern): return '*' in pattern or '?' in pattern or '[' in pattern non_special_excludes = set() match_excludes = set() for pattern in exclude: if is_special(pattern): match_excludes.add(pattern) else: non_special_excludes.add(pattern) def exclusion(path): if str(path) in non_special_excludes: return True for pattern in match_excludes: ret = path.match(pattern) if ret: return True return False result = sorted({str(p) for p in includes_iterator() if not exclusion(p)}) if not result and not allow_empty: args = repr(include) if exclude: args += ', exclude=%s' % repr(exclude) output('%s %s: "glob(%s)" got an empty result. If it is the expected behavior, ' 'specify "allow_empty=True" to eliminate this message' % (source_loc, severity, args), prefix=False) return result
def __init__(self, name, type, srcs, deps, visibility, kwargs): """Init method. Init the target. """ from blade import build_manager # pylint: disable=import-outside-toplevel self.blade = build_manager.instance self.build_dir = self.blade.get_build_dir() current_source_path = self.blade.get_current_source_path() self.target_database = self.blade.get_target_database() self.name = name self.path = current_source_path # The unique key of this target, for internal use mainly. self.key = '%s:%s' % (current_source_path, name) # The full qualified target id, to be displayed in diagnostic message self.fullname = '//' + self.key self.source_location = source_location( os.path.join(current_source_path, 'BUILD')) self.type = type self.srcs = srcs self.deps = [] self.expanded_deps = None # Expanded dependencies, includes direct and indirect dependies. self.dependents = set() # Target keys which depends on this self.expanded_dependents = set( ) # Expanded target keys which depends on this self._implicit_deps = set() self.visibility = 'PUBLIC' if not name: self.fatal('Missing "name"') # Keep track of target filess generated by this target. Note that one target rule # may correspond to several target files, such as: # proto_library: static lib/shared lib/jar variables self.__targets = {} self.__default_target = '' self.__clean_list = [] # Paths to be cleaned # Target releated attributes, they should be set only before generating build rules. self.attr = {} # For temporary, mutable fields only, their values should not relate to rule_hash self.data = {} # TODO: Remove it, make a `TestTargetMixin` self.attr['test_timeout'] = config.get_item('global_config', 'test_timeout') self._check_name() self._check_kwargs(kwargs) self._check_srcs() self._check_deps(deps) self._init_target_deps(deps) self._init_visibility(visibility) self.__build_rules = None self.__rule_hash = None # Cached rule hash
def __init__(self, name, type, srcs, deps, visibility, kwargs): """Init method. Init the target. """ from blade import build_manager self.blade = build_manager.instance self.build_dir = self.blade.get_build_dir() current_source_path = self.blade.get_current_source_path() self.target_database = self.blade.get_target_database() self.key = (current_source_path, name) self.fullname = '%s:%s' % self.key self.name = name self.path = current_source_path self.source_location = source_location(os.path.join(current_source_path, 'BUILD')) self.type = type self.srcs = srcs self.deps = [] self.expanded_deps = [] self.visibility = 'PUBLIC' self.data = {} self.data['test_timeout'] = config.get_item('global_config', 'test_timeout') # Keep track of target filess generated by this target. Note that one target rule # may correspond to several target files, such as: # proto_library: static lib/shared lib/jar variables self.data['targets'] = {} self.data['default_target'] = '' self._check_name() self._check_kwargs(kwargs) self._check_srcs() self._check_deps(deps) self._init_target_deps(deps) self._init_visibility(visibility) self.build_rules = [] self.data['generated_hdrs'] = []
def fatal(self, msg): # NOTE: VSCode's problem matcher doesn't recognize 'fatal', use 'error' instead console.fatal('%s error: %s' % (source_location(self.current_file_name), msg), prefix=False)
def error(self, msg): console.error('%s error: %s' % (source_location(self.current_file_name), msg), prefix=False)
def warning(self, msg): console.warning('%s warning: %s' % (source_location(self.current_file_name), msg), prefix=False)
def info(self, msg): console.info('%s info: %s' % (source_location(self.current_file_name), msg), prefix=False)
def _current_source_location(): """Return source location in current BUILD file""" from blade import build_manager # pylint: disable=import-outside-toplevel source_dir = Path(build_manager.instance.get_current_source_path()) return source_location(os.path.join(str(source_dir), 'BUILD'))
def fatal(self, msg): console.fatal('%s: %s' % (source_location(self.current_file_name), msg), prefix=False)