def __init__(self, name, srcs, deps, visibility, tags, type, out, shell, kwargs): srcs = var_to_list(srcs) deps = var_to_list(deps) super(PackageTarget, self).__init__(name=name, type='package', srcs=[], src_exts=None, deps=deps, visibility=visibility, tags=tags, kwargs=kwargs) if type not in _package_types: self.error( 'Invalid type %s. Types supported by the package are %s' % (type, ', '.join(sorted(_package_types)))) self.attr['type'] = type self.attr['sources'] = [] self.attr['locations'] = [] self._add_tags('type:archive') self._process_srcs(srcs) if not out: out = '%s.%s' % (name, type) self.attr['out'] = out self.attr['shell'] = shell
def __init__(self, name, srcs, deps, visibility, tags, main, base, exclusions, kwargs): """Init method.""" srcs = var_to_list(srcs) deps = var_to_list(deps) super(PythonBinary, self).__init__(name=name, srcs=srcs, deps=deps, visibility=visibility, tags=tags, base=base, kwargs=kwargs) self.type = 'py_binary' self.attr['run_in_shell'] = True if main: self.attr['main'] = main else: if len(srcs) == 1: self.attr['main'] = srcs[0] else: self.error('The entry file must be specified by the "main" ' 'argument if there are more than one srcs') self.attr['exclusions'] = exclusions self._add_tags('type:binary')
def __init__(self, name, srcs, deps, visibility, tags, resources, source_encoding, warnings, prebuilt, binary_jar, exported_deps, provided_deps, coverage, kwargs): type = 'java_library' if prebuilt: type = 'prebuilt_java_library' exported_deps = var_to_list(exported_deps) provided_deps = var_to_list(provided_deps) all_deps = var_to_list(deps) + exported_deps + provided_deps super(JavaLibrary, self).__init__(name=name, type=type, srcs=srcs, deps=all_deps, visibility=visibility, tags=tags, resources=resources, source_encoding=source_encoding, warnings=warnings, kwargs=kwargs) self.attr['exported_deps'] = self._unify_deps(exported_deps) self.attr['provided_deps'] = self._unify_deps(provided_deps) self._add_tags('type:library') if prebuilt: if not binary_jar: binary_jar = name + '.jar' self.attr['binary_jar'] = self._source_file_path(binary_jar) self._add_tags('type:prebuilt') self.attr['jacoco_coverage'] = coverage and bool(srcs)
def __init__(self, name, srcs, deps, visibility, tags, warning, defs, incs, extra_cppflags, extra_linkflags, testdata, always_run, exclusive, kwargs): # pylint: disable=too-many-locals super(CuTest, self).__init__(name=name, srcs=srcs, deps=deps, visibility=visibility, tags=tags, warning=warning, defs=defs, incs=incs, extra_cppflags=extra_cppflags, extra_linkflags=extra_linkflags, kwargs=kwargs) self._add_tags('lang:cu') self.type = 'cu_test' self.attr['testdata'] = var_to_list(testdata) self.attr['always_run'] = always_run self.attr['exclusive'] = exclusive cc_test_config = config.get_section('cc_test_config') gtest_lib = var_to_list(cc_test_config['gtest_libs']) gtest_main_lib = var_to_list(cc_test_config['gtest_main_libs']) # Hardcode deps rule to thirdparty gtest main lib. self._add_implicit_library(gtest_lib) self._add_implicit_library(gtest_main_lib)
def __init__(self, name, type, srcs, deps, visibility, tags, resources, source_encoding, warnings, kwargs): """Init method. Init the scala target. """ srcs = var_to_list(srcs) deps = var_to_list(deps) resources = var_to_list(resources) super(ScalaTarget, self).__init__(name=name, type=type, srcs=srcs, src_exts=['scala', 'java'], deps=deps, visibility=visibility, tags=tags, kwargs=kwargs) self._process_resources(resources) if source_encoding: self.attr['source_encoding'] = source_encoding if warnings: self.attr['warnings'] = warnings self._add_tags('lang:scala')
def __init__(self, name, srcs, deps, optimize, visibility, tags, deprecated, kwargs): srcs = var_to_list(srcs) super(FBThriftLibrary, self).__init__(name=name, type='fbthrift_library', srcs=srcs, src_exts=['thrift'], deps=deps, visibility=visibility, tags=tags, warning='', defs=[], incs=[], export_incs=[], optimize=optimize, linkflags=None, extra_cppflags=[], extra_linkflags=[], kwargs=kwargs) fbthrift_config = config.get_section('fbthrift_config') fbthrift_libs = var_to_list(fbthrift_config['fbthrift_libs']) # Add implicit deps rule to thrift libraries. self._add_implicit_library(fbthrift_libs) # Link all the symbols by default self.attr['link_all_symbols'] = True # For each thrift file initialize a FBThriftHelper, which will be used # to get the source files generated from thrift file. self.fbthrift_helpers = {} for src in srcs: self.fbthrift_helpers[src] = FBThriftHelper( os.path.join(self.path, src))
def __init__(self, name, srcs, deps, visibility, tags, warning, defs, incs, extra_cppflags, extra_linkflags, allow_undefined, recursive, prefix, lexflags, yaccflags, kwargs): """Init method. Init the cc lex yacc target """ super(LexYaccLibrary, self).__init__( name=name, type='lex_yacc_library', srcs=srcs, src_exts=['l', 'y', 'll', 'yy'], deps=deps, visibility=visibility, tags=tags, warning=warning, defs=defs, incs=incs, export_incs=[], optimize=None, linkflags=None, extra_cppflags=[], extra_linkflags=[], kwargs=kwargs) if (len(srcs) != 2 or (not (srcs[0].endswith('.l') or srcs[0].endswith('.ll'))) or (not (srcs[1].endswith('.y') or srcs[1].endswith('.yy')))): self.error('"lex_yacc_library.srcs" must be a pair of [lex_file, yacc_file]') self.attr['recursive'] = recursive self.attr['prefix'] = prefix self.attr['lexflags'] = var_to_list(lexflags) self.attr['yaccflags'] = var_to_list(yaccflags) self.attr['prefix'] = prefix self.attr['extra_cppflags'] = var_to_list(extra_cppflags) self.attr['extra_linkflags'] = var_to_list(extra_linkflags) self.attr['allow_undefined'] = allow_undefined self.attr['link_all_symbols'] = True cc, h, cc_path, h_path = self._yacc_generated_files(self.srcs[1]) self._set_hdrs(h) self.attr['generated_hdrs'] = [h_path]
def _append_item_value(self, section, name, item_name, value, user_config): """Append value to config item.""" if item_name in user_config: self.error('"%s" and "%s" can not be used together' % (name, item_name)) return if isinstance(section[item_name], list): section[item_name] += var_to_list(value) elif isinstance(section[item_name], set): section[item_name].update(var_to_list(value)) else: self.warning('Invalid "%s", "%s" is not appendable' % (name, item_name))
def _assign_item_value(self, section, name, value): """Assign value to config item.""" if isinstance(section[name], list): section[name] = var_to_list(value) elif isinstance(section[name], set): # Allow using `list` to config `set` section[name] = set(var_to_list(value)) elif isinstance(value, type(section[name])): section[name] = value else: self.error( 'Incorrect type for "%s", expect "%s", actual "%s"' % (name, type(section[name]).__name__, type(value).__name__))
def __init__(self, name, srcs, deps, visibility, tags, testdata, kwargs): srcs = var_to_list(srcs) deps = var_to_list(deps) testdata = var_to_list(testdata) super(ShellTest, self).__init__(name=name, type='sh_test', srcs=srcs, src_exts=['sh', 'bash', ''], deps=deps, visibility=visibility, tags=tags, kwargs=kwargs) self._add_tags('lang:sh', 'type:test') self._process_test_data(testdata)
def __init__(self, name, srcs, deps, visibility, tags, resources, source_encoding, warnings, exclusions, testdata, kwargs): super(ScalaTest, self).__init__(name=name, srcs=srcs, deps=deps, resources=resources, visibility=visibility, tags=tags, source_encoding=source_encoding, warnings=warnings, exclusions=exclusions, kwargs=kwargs) self.type = 'scala_test' self.attr['testdata'] = var_to_list(testdata) self._add_tags('type:test') if not self.srcs: self.warning('Empty scala test sources.') scalatest_libs = config.get_item('scala_test_config', 'scalatest_libs') if scalatest_libs: self._add_implicit_library(scalatest_libs) else: console.warning( 'Config: "scala_test_config.scalatest_libs" is not configured')
def _check_proto_deps(self): """Only proto_library or gen_rule target is allowed as deps.""" proto_config = config.get_section('proto_library_config') protobuf_libs = var_to_list(proto_config['protobuf_libs']) protobuf_java_libs = var_to_list(proto_config['protobuf_java_libs']) protobuf_libs = [ self._unify_dep(d) for d in protobuf_libs + protobuf_java_libs ] proto_deps = protobuf_libs + self.attr['protoc_plugin_deps'] for dkey in self.deps: if dkey in proto_deps: continue dep = self.target_database[dkey] if dkey not in self._implicit_deps and dep.type not in ( 'proto_library', 'gen_rule'): self.error( 'Invalid dep %s. proto_library can only depend on proto_library ' 'or gen_rule.' % dep.fullname)
def _check_default_visibility(kwargs): if 'default_visibility' not in kwargs: return value = var_to_list(kwargs['default_visibility']) if not value: return if len(value) != 1 or 'PUBLIC' not in value: _blade_config.error( '''"global_config.default_visibility" can only be empty("[]") or "['PUBLIC']"''' )
def __init__(self, name, srcs, deps, visibility, tags, resources, source_encoding, warnings, exported_deps, provided_deps, coverage, kwargs): exported_deps = var_to_list(exported_deps) provided_deps = var_to_list(provided_deps) all_deps = var_to_list(deps) + exported_deps + provided_deps super(ScalaLibrary, self).__init__(name=name, type='scala_library', srcs=srcs, deps=all_deps, visibility=visibility, tags=tags, resources=resources, source_encoding=source_encoding, warnings=warnings, kwargs=kwargs) self.attr['exported_deps'] = self._unify_deps(exported_deps) self.attr['provided_deps'] = self._unify_deps(provided_deps) self.attr['jacoco_coverage'] = coverage and bool(srcs) self._add_tags('type:library')
def __init__(self, name, type, srcs, deps, extra_goflags, visibility, tags, kwargs): """Init the go target.""" srcs = var_to_list(srcs) deps = var_to_list(deps) extra_goflags = ' '.join(var_to_list(extra_goflags)) super(GoTarget, self).__init__(name=name, type=type, srcs=srcs, src_exts=['go'], deps=deps, visibility=visibility, tags=tags, kwargs=kwargs) self._set_go_package() self._init_go_environment() self.attr['extra_goflags'] = extra_goflags self._add_tags('lang:go')
def __init__(self, name, type, srcs, deps, base, visibility, tags, kwargs): """Init method.""" srcs = var_to_list(srcs) deps = var_to_list(deps) super(PythonTarget, self).__init__(name=name, type=type, srcs=srcs, src_exts=['py', 'py2', 'py3', 'egg', 'whl'], deps=deps, visibility=visibility, tags=tags, kwargs=kwargs) if base: if not base.startswith('//'): self.error( 'Invalid base directory %s. Option base should be a directory ' 'starting with \'//\' from BLADE_ROOT directory.' % base) return self.attr['python_base'] = base[2:]
def __init__(self, name, srcs, deps, visibility, tags, testdata, extra_goflags, kwargs): super(GoTest, self).__init__(name=name, type='go_test', srcs=srcs, deps=deps, visibility=visibility, tags=tags, extra_goflags=extra_goflags, kwargs=kwargs) self.attr['go_rule'] = 'gotest' self.attr['testdata'] = var_to_list(testdata) self._add_tags('type:test')
def __init__(self, name, type, srcs, deps, visibility, tags, warning, defs, incs, extra_cppflags, extra_linkflags, kwargs): srcs = var_to_list(srcs) deps = var_to_list(deps) extra_cppflags = var_to_list(extra_cppflags) extra_linkflags = var_to_list(extra_linkflags) super(CuTarget, self).__init__(name=name, type=type, srcs=srcs, deps=deps, visibility=visibility, tags=tags, warning=warning, defs=defs, incs=incs, export_incs=[], optimize=None, linkflags=None, extra_cppflags=extra_cppflags, extra_linkflags=extra_linkflags, kwargs=kwargs) self._add_tags('lang:cu')
def _set_pack_exclusions(self, exclusions): exclusions = var_to_list(exclusions) self.attr['exclusions'] = [] for exclusion in exclusions: if maven.is_valid_id(exclusion): if '*' in exclusion: if not self.__is_valid_maven_id_with_wildcards(exclusion): self.warning( 'Invalid maven id with wildcards %s. Ignored. The valid id ' 'could be: group:artifact:*, group:*:*, *:*:*' % exclusion) continue self.attr['exclusions'].append(exclusion) else: self.warning( 'Exclusions only support maven id group:artifact:version. Ignore %s' % exclusion)
def _go_dependencies(self): targets = self.blade.get_build_targets() srcs = [self._source_file_path(s) for s in self.srcs] implicit_deps = [] for key in self.deps: path = targets[key]._get_target_file('gopkg') if path: # There are two cases for go package(gopkg) # # - gopkg produced by another go_library, # the target file here is a path to the # generated lib # # - gopkg produced by a proto_library, the # target file is a list of pb.go files implicit_deps += var_to_list(path) return srcs + implicit_deps
def _append_config(self, section_name, section, append): """Append config section items""" self.warning( '"append" is deprecated, please use the "append_" prefix to append' ) if not isinstance(append, dict): self.error('%s: Append must be a dict' % section_name) for k in append: if k in section: if isinstance(section[k], list): section[k] += var_to_list(append[k]) else: self.warning('%s: Config item %s is not a list' % (section_name, k)) else: self.warning('%s: Unknown config item name: %s' % (section_name, k))
def filter_cc_flags(self, flag_list, language='c'): """Filter out the unrecognized compilation flags.""" flag_list = var_to_list(flag_list) valid_flags, unrecognized_flags = [], [] # Put compilation output into test.o instead of /dev/null # because the command line with '--coverage' below exit # with status 1 which makes '--coverage' unsupported # echo "int main() { return 0; }" | gcc -o /dev/null -c -x c --coverage - > /dev/null 2>&1 fd, obj = tempfile.mkstemp('.o', 'filter_cc_flags_test') cmd = ('export LC_ALL=C; echo "int main() { return 0; }" | ' '%s -o %s -c -x %s -Werror %s -' % (self.cc, obj, language, ' '.join(flag_list))) p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) unused_out, err = p.communicate() try: # In case of error, the `.o` file will be deleted by the compiler os.remove(obj) except OSError: pass os.close(fd) if p.returncode == 0: return flag_list for flag in flag_list: # Example error messages: # clang: warning: unknown warning option '-Wzzz' [-Wunknown-warning-option] # gcc: gcc: error: unrecognized command line option '-Wxxx' if " option '%s'" % flag in err: unrecognized_flags.append(flag) else: valid_flags.append(flag) if unrecognized_flags: console.warning('config: Unrecognized %s flags: %s' % (language, ', '.join(unrecognized_flags))) return valid_flags
def __init__(self, name, srcs, deps, visibility, tags, resources, source_encoding, warnings, main_class, exclusions, testdata, target_under_test, kwargs): super(JavaTest, self).__init__(name=name, srcs=srcs, deps=deps, visibility=visibility, tags=tags, resources=resources, source_encoding=source_encoding, warnings=warnings, main_class=main_class, exclusions=exclusions, kwargs=kwargs) if target_under_test: self.warning( '"target_under_test" is deprecated, you can remove it safely') self.type = 'java_test' self.attr['testdata'] = var_to_list(testdata) self._add_tags('type:test')
def _init_visibility(self, visibility): """Initialize the `visibility` attribute. Parameters ----------- visibility: the visibility list in BUILD file Description ----------- Visibility determines whether another target is able to depend on this target. Visibility specify a list of target patterns in the same form as deps, i.e. //path:target, '//path/:...'. There is a special value is "PUBLIC", which means this target is visible globally within the code base. Note that targets inside the same BUILD file are always visible to each other. """ if visibility is None: global_config = config.get_section('global_config') if self.key in global_config.get('legacy_public_targets'): visibility = {'PUBLIC'} else: visibility = global_config.get('default_visibility') self._visibility.update(visibility) return self._visibility_is_default = False visibility = var_to_list(visibility) if 'PUBLIC' in visibility: self._visibility.add('PUBLIC') return self._visibility.clear() for v in visibility: if not target_pattern.is_valid_in_build(v): #self.error('Invalid build target pattern "%s" for visibility' % v) continue key = target_pattern.normalize(v, self.path) self._visibility.add(key)
def __init__(self, name, path, code_generation): self.name = name self.path = path assert isinstance(code_generation, dict) self.code_generation = {} for language, v in iteritems(code_generation): if language not in self.__languages: console.error( '%s: Language %s is invalid. ' 'Protoc plugins in %s are supported by blade currently.' % (name, language, ', '.join(self.__languages))) continue self.code_generation[language] = {} # Note that each plugin dep should be in the global target format # since protoc plugin is defined in the global scope deps = [] for dep in var_to_list(v['deps']): if dep.startswith('//'): dep = dep[2:] if dep not in deps: deps.append(dep) self.code_generation[language]['deps'] = deps
def __init__(self, name, srcs, deps, visibility, tags, optimize, deprecated, kwargs): srcs = var_to_list(srcs) super(ThriftLibrary, self).__init__(name=name, type='thrift_library', srcs=srcs, src_exts=['thrift'], deps=deps, visibility=visibility, tags=tags, warning='', defs=[], incs=[], export_incs=[], optimize=optimize, linkflags=None, extra_cppflags=[], extra_linkflags=[], kwargs=kwargs) thrift_libs = config.get_item('thrift_config', 'thrift_libs') # Hardcode deps rule to thrift libraries. self._add_implicit_library(thrift_libs) # Link all the symbols by default self.attr['link_all_symbols'] = True self.attr['deprecated'] = deprecated self._add_tags('lang:thrift', 'type:library') # For each thrift file initialize a ThriftHelper, which will be used # to get the source files generated from thrift file. sources, headers = [], [] self.thrift_helpers = {} for src in self.srcs: self.thrift_helpers[src] = ThriftHelper(self.path, src) thrift_files = self._thrift_gen_cpp_files(src) headers += [h for h in thrift_files if h.endswith('.h')] self.attr['generated_hdrs'] = headers
def _set_protoc_plugins(self, plugins): """Handle protoc plugins and corresponding dependencies.""" plugins = var_to_list(plugins) self.attr['protoc_plugins'] = plugins protoc_plugin_config = config.get_section('protoc_plugin_config') protoc_plugins = [] protoc_plugin_deps, protoc_plugin_java_deps = set(), set() for plugin in plugins: if plugin not in protoc_plugin_config: self.error('Unknown plugin %s' % plugin) continue p = protoc_plugin_config[plugin] protoc_plugins.append(p) for language, v in iteritems(p.code_generation): for key in v['deps']: if key not in self.deps: self.deps.append(key) protoc_plugin_deps.add(key) if language == 'java': protoc_plugin_java_deps.add(key) self.attr['protoc_plugin_deps'] = list(protoc_plugin_deps) self.attr['exported_deps'] += list(protoc_plugin_java_deps) self.data['protoc_plugin_objects'] = protoc_plugins
def generate_build(self, rule, outputs, inputs=None, implicit_deps=None, order_only_deps=None, variables=None, implicit_outputs=None, clean=None): """Generate a ninja build statement with specified parameters. Args: clean:list[str], files to be removed on clean, defaults to outputs + implicit_outputs, you can pass a empty list to prevent cleaning. (For example, if you want to remove the entire outer dir instead of single files) See ninja documents for description for other args. """ outputs = var_to_list(outputs) implicit_outputs = var_to_list(implicit_outputs) outs = outputs[:] if implicit_outputs: outs.append('|') outs += implicit_outputs ins = var_to_list(inputs) if implicit_deps: ins.append('|') ins += var_to_list(implicit_deps) if order_only_deps: ins.append('||') ins += var_to_list(order_only_deps) self._write_rule('build %s: %s %s' % (' '.join(outs), rule, ' '.join(ins))) clean = (outputs + implicit_outputs) if clean is None else var_to_list(clean) if clean: self._remove_on_clean(*clean) if variables: assert isinstance(variables, dict) for name, v in iteritems(variables): assert v is not None if v: self._write_rule(' %s = %s' % (name, v)) else: self._write_rule(' %s =' % name) self._write_rule('') # An empty line to improve readability
def __init__(self, name, srcs, deps, visibility, tags, optimize, deprecated, generate_descriptors, target_languages, plugins, source_encoding, kwargs): """Init method. Init the proto target. """ # pylint: disable=too-many-locals srcs = var_to_list(srcs) super(ProtoLibrary, self).__init__(name=name, type='proto_library', srcs=srcs, src_exts=['proto'], deps=deps, visibility=visibility, tags=tags, warning='', defs=[], incs=[], export_incs=[], optimize=optimize, linkflags=None, extra_cppflags=[], extra_linkflags=[], kwargs=kwargs) self._check_proto_srcs_name(srcs) if srcs: self.attr['public_protos'] = [ self._source_file_path(s) for s in srcs ] self._add_tags('lang:proto', 'type:library') proto_config = config.get_section('proto_library_config') protobuf_libs = var_to_list(proto_config['protobuf_libs']) protobuf_java_libs = var_to_list(proto_config['protobuf_java_libs']) protobuf_python_libs = var_to_list( proto_config['protobuf_python_libs']) # Implicit deps rule to thirdparty protobuf lib. self._add_implicit_library(protobuf_libs) self._add_implicit_library(protobuf_java_libs) self._add_implicit_library(protobuf_python_libs) # Normally a proto target depends on another proto target when # it references a message defined in that target. Then in the # generated code there is public API with return type/arguments # defined outside and in java it needs to export that dependency, # which is also the case for java protobuf library. self.attr['exported_deps'] = self._unify_deps(var_to_list(deps)) self.attr['exported_deps'] += self._unify_deps(protobuf_java_libs) self._set_protoc_plugins(plugins) # Link all the symbols by default self.attr['link_all_symbols'] = True self.attr['deprecated'] = deprecated self.attr['source_encoding'] = source_encoding self.attr['generate_descriptors'] = generate_descriptors # TODO(chen3feng): Change the values to a `set` rather than separated attributes target_languages = var_to_list(target_languages) self.attr['target_languages'] = target_languages options = self.blade.get_options() self.attr['generate_java'] = 'java' in target_languages or getattr( options, 'generate_java', False) self.attr['generate_python'] = 'python' in target_languages or getattr( options, 'generate_python', False) self.attr['generate_go'] = 'go' in target_languages or getattr( options, 'generate_go', False) # Declare generated header files full_cpp_headers = [] cpp_headers = [] for src in self.srcs: full_source, full_header = self._proto_gen_cpp_files(src) full_cpp_headers.append(full_header) source, header = self._proto_gen_cpp_file_names(src) cpp_headers.append(header) self.attr['generated_hdrs'] = full_cpp_headers self._set_hdrs(cpp_headers)
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 = _current_source_location() include = var_to_list(include) severity = config.get_item('global_config', 'glob_error_severity') if excludes: console.diagnose(source_loc, severity, '"excludes" is deprecated, use "exclude" instead') exclude = var_to_list(exclude) + var_to_list(excludes) def includes_iterator(): results = [] for pattern in include: if not pattern: console.diagnose(source_loc, 'error', '"glob": Empty pattern is not allowed') continue 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) console.diagnose(source_loc, severity, '"glob(%s)" got an empty result. If it is the expected behavior, ' 'specify "allow_empty=True" to eliminate this message' % args) return result