|  | # Copyright 2015 gRPC authors. | 
|  | # | 
|  | # 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. | 
|  |  | 
|  | """Buildgen expand filegroups plugin. | 
|  |  | 
|  | This takes the list of libs from our yaml dictionary, | 
|  | and expands any and all filegroup. | 
|  |  | 
|  | """ | 
|  |  | 
|  |  | 
|  | def excluded(filename, exclude_res): | 
|  | for r in exclude_res: | 
|  | if r.search(filename): | 
|  | return True | 
|  | return False | 
|  |  | 
|  |  | 
|  | def uniquify(lst): | 
|  | out = [] | 
|  | for el in lst: | 
|  | if el not in out: | 
|  | out.append(el) | 
|  | return out | 
|  |  | 
|  |  | 
|  | FILEGROUP_LISTS = ['src', 'headers', 'public_headers', 'deps'] | 
|  |  | 
|  |  | 
|  | FILEGROUP_DEFAULTS = { | 
|  | 'language': 'c', | 
|  | 'boringssl': False, | 
|  | 'zlib': False, | 
|  | 'ares': False, | 
|  | } | 
|  |  | 
|  |  | 
|  | def mako_plugin(dictionary): | 
|  | """The exported plugin code for expand_filegroups. | 
|  |  | 
|  | The list of libs in the build.yaml file can contain "filegroups" tags. | 
|  | These refer to the filegroups in the root object. We will expand and | 
|  | merge filegroups on the src, headers and public_headers properties. | 
|  |  | 
|  | """ | 
|  | libs = dictionary.get('libs') | 
|  | targets = dictionary.get('targets') | 
|  | filegroups_list = dictionary.get('filegroups') | 
|  | filegroups = {} | 
|  |  | 
|  | for fg in filegroups_list: | 
|  | for lst in FILEGROUP_LISTS: | 
|  | fg[lst] = fg.get(lst, []) | 
|  | fg['own_%s' % lst] = list(fg[lst]) | 
|  | for attr, val in FILEGROUP_DEFAULTS.iteritems(): | 
|  | if attr not in fg: | 
|  | fg[attr] = val | 
|  |  | 
|  | todo = list(filegroups_list) | 
|  | skips = 0 | 
|  |  | 
|  | while todo: | 
|  | assert skips != len(todo), "infinite loop in filegroup uses clauses: %r" % [t['name'] for t in todo] | 
|  | # take the first element of the todo list | 
|  | cur = todo[0] | 
|  | todo = todo[1:] | 
|  | # check all uses filegroups are present (if no, skip and come back later) | 
|  | skip = False | 
|  | for uses in cur.get('uses', []): | 
|  | if uses not in filegroups: | 
|  | skip = True | 
|  | if skip: | 
|  | skips += 1 | 
|  | todo.append(cur) | 
|  | else: | 
|  | skips = 0 | 
|  | assert 'plugins' not in cur | 
|  | plugins = [] | 
|  | for uses in cur.get('uses', []): | 
|  | for plugin in filegroups[uses]['plugins']: | 
|  | if plugin not in plugins: | 
|  | plugins.append(plugin) | 
|  | for lst in FILEGROUP_LISTS: | 
|  | vals = cur.get(lst, []) | 
|  | vals.extend(filegroups[uses].get(lst, [])) | 
|  | cur[lst] = vals | 
|  | cur_plugin_name = cur.get('plugin') | 
|  | if cur_plugin_name: | 
|  | plugins.append(cur_plugin_name) | 
|  | cur['plugins'] = plugins | 
|  | filegroups[cur['name']] = cur | 
|  |  | 
|  | # build reverse dependency map | 
|  | things = {} | 
|  | for thing in dictionary['libs'] + dictionary['targets'] + dictionary['filegroups']: | 
|  | things[thing['name']] = thing | 
|  | thing['used_by'] = [] | 
|  | thing_deps = lambda t: t.get('uses', []) + t.get('filegroups', []) + t.get('deps', []) | 
|  | for thing in things.itervalues(): | 
|  | done = set() | 
|  | todo = thing_deps(thing) | 
|  | while todo: | 
|  | cur = todo[0] | 
|  | todo = todo[1:] | 
|  | if cur in done: continue | 
|  | things[cur]['used_by'].append(thing['name']) | 
|  | todo.extend(thing_deps(things[cur])) | 
|  | done.add(cur) | 
|  |  | 
|  | # the above expansion can introduce duplicate filenames: contract them here | 
|  | for fg in filegroups.itervalues(): | 
|  | for lst in FILEGROUP_LISTS: | 
|  | fg[lst] = uniquify(fg.get(lst, [])) | 
|  |  | 
|  | for tgt in dictionary['targets']: | 
|  | for lst in FILEGROUP_LISTS: | 
|  | tgt[lst] = tgt.get(lst, []) | 
|  | tgt['own_%s' % lst] = list(tgt[lst]) | 
|  |  | 
|  | for lib in libs + targets: | 
|  | assert 'plugins' not in lib | 
|  | plugins = [] | 
|  | for lst in FILEGROUP_LISTS: | 
|  | vals = lib.get(lst, []) | 
|  | lib[lst] = list(vals) | 
|  | lib['own_%s' % lst] = list(vals) | 
|  | for fg_name in lib.get('filegroups', []): | 
|  | fg = filegroups[fg_name] | 
|  | for plugin in fg['plugins']: | 
|  | if plugin not in plugins: | 
|  | plugins.append(plugin) | 
|  | for lst in FILEGROUP_LISTS: | 
|  | vals = lib.get(lst, []) | 
|  | vals.extend(fg.get(lst, [])) | 
|  | lib[lst] = vals | 
|  | lib['plugins'] = plugins | 
|  | if lib.get('generate_plugin_registry', False): | 
|  | lib['src'].append('src/core/plugin_registry/%s_plugin_registry.cc' % | 
|  | lib['name']) | 
|  | for lst in FILEGROUP_LISTS: | 
|  | lib[lst] = uniquify(lib.get(lst, [])) |