• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python
2
3import json
4import os
5import sys
6
7PRINT_ORIGINAL_FULL = False
8
9# This flags are augmented with flags added to the json files but not present in .gn or .gni files
10IGNORED_FLAGS = [
11    '-D_DEBUG',
12    '-Werror',
13    '-Xclang'
14    ]
15DEFAULT_CFLAGS = [
16    '-DHAVE_ARM64_CRC32C=0',
17    '-DUSE_AURA=1',
18    '-DUSE_GLIB=1',
19    '-DUSE_NSS_CERTS=1',
20    '-DUSE_UDEV',
21    '-DUSE_X11=1',
22    '-DWEBRTC_ANDROID_PLATFORM_BUILD=1',
23    '-DWEBRTC_APM_DEBUG_DUMP=0',
24    '-D_FILE_OFFSET_BITS=64',
25    '-D_GNU_SOURCE',
26    '-D_LARGEFILE64_SOURCE',
27    '-D_LARGEFILE_SOURCE',
28    '-Wno-all',
29    '-Wno-error',
30    '-Wno-everything',
31    '-Wno-implicit-const-int-float-conversion',
32    '-Wno-missing-field-initializers',
33    '-Wno-unreachable-code-aggressive',
34    '-Wno-unreachable-code-break',
35]
36
37DEFAULT_CFLAGS_BY_ARCH = {
38        'x86': ['-mavx2', '-mfma', '-msse2', '-msse3'],
39        'x64': ['-mavx2', '-mfma', '-msse2', '-msse3'],
40        'arm': ['-mthumb'],
41        'arm64': [],
42        'riscv64': [],
43        }
44
45FLAGS = ['cflags', 'cflags_c', 'cflags_cc', 'asmflags']
46FLAG_NAME_MAP = {
47    'cflags': 'cflags',
48    'asmflags': 'asflags',
49    'cflags_cc': 'cppflags',
50    'cflags_c': 'conlyflags',
51}
52
53ARCH_NAME_MAP = {n: n for n in DEFAULT_CFLAGS_BY_ARCH.keys()}
54ARCH_NAME_MAP['x64'] = 'x86_64'
55
56ARCHS = sorted(ARCH_NAME_MAP.keys())
57
58def FormatList(l):
59    return json.dumps(sorted(list(l)))
60
61def IsInclude(name):
62    return name.endswith('.h') or name.endswith('.inc')
63
64def FilterIncludes(l):
65    return filter(lambda x: not IsInclude(x), l)
66
67def PrintOrigin(target):
68    print('/* From target:')
69    if PRINT_ORIGINAL_FULL:
70        print(json.dumps(target, sort_keys = True, indent = 4))
71    else:
72        print(target['original_name'])
73    print('*/')
74
75def MakeRelatives(l):
76    return map(lambda x: x.split('//').pop(), l)
77
78def FormatName(name):
79    return 'webrtc_' + name.split('/').pop().replace(':', '__')
80
81def FormatNames(target):
82    target['original_name'] = target['name']
83    target['name'] = FormatName(target['name'])
84    target['deps'] = sorted([FormatName(d) for d in target['deps']])
85    target['sources'] = list(map(lambda s: (':' + FormatName(s[1:])) if s.startswith(':') else s, target['sources']))
86    return target
87
88def FilterFlags(flags, to_skip = set()):
89    skipped_opts = set(IGNORED_FLAGS).union(to_skip)
90    return [x for x in flags if not any([x.startswith(y) for y in skipped_opts])]
91
92def PrintHeader():
93    print('package {')
94    print('    default_applicable_licenses: ["external_webrtc_license"],')
95    print('}')
96    print('')
97    print('// Added automatically by a large-scale-change that took the approach of')
98    print('// \'apply every license found to every target\'. While this makes sure we respect')
99    print('// every license restriction, it may not be entirely correct.')
100    print('//')
101    print('// e.g. GPL in an MIT project might only apply to the contrib/ directory.')
102    print('//')
103    print('// Please consider splitting the single license below into multiple licenses,')
104    print('// taking care not to lose any license_kind information, and overriding the')
105    print('// default license using the \'licenses: [...]\' property on targets as needed.')
106    print('//')
107    print('// For unused files, consider creating a \'fileGroup\' with "//visibility:private"')
108    print('// to attach the license to, and including a comment whether the files may be')
109    print('// used in the current project.')
110    print('//')
111    print('// large-scale-change included anything that looked like it might be a license')
112    print('// text as a license_text. e.g. LICENSE, NOTICE, COPYING etc.')
113    print('//')
114    print('// Please consider removing redundant or irrelevant files from \'license_text:\'.')
115    print('// See: http://go/android-license-faq')
116    print('')
117    print('///////////////////////////////////////////////////////////////////////////////')
118    print('// Do not edit this file directly, it\'s automatically generated by a script. //')
119    print('// Modify android_tools/generate_android_bp.py and run that instead.         //')
120    print('///////////////////////////////////////////////////////////////////////////////')
121    print('')
122    print('license {')
123    print('    name: "external_webrtc_license",')
124    print('    visibility: [":__subpackages__"],')
125    print('    license_kinds: [')
126    print('        "SPDX-license-identifier-Apache-2.0",')
127    print('        "SPDX-license-identifier-BSD",')
128    print('        "SPDX-license-identifier-MIT",')
129    print('        "SPDX-license-identifier-Zlib",')
130    print('        "legacy_notice",')
131    print('        "legacy_unencumbered",')
132    print('    ],')
133    print('    license_text: [')
134    print('        "LICENSE",')
135    print('        "PATENTS",')
136    print('        "license_template.txt",')
137    print('    ],')
138    print('}')
139
140
141
142def GatherDefaultFlags(targets_by_arch):
143    # Iterate through all of the targets for each architecture collecting the flags that
144    # are the same for all targets in that architecture.  Use a list instead of a set
145    # to maintain the flag ordering, which may be significant (e.g. -Wno-shadow has to
146    # come after -Wshadow).
147    arch_default_flags = {}
148    for arch, targets in targets_by_arch.items():
149        arch_default_flags[arch] = {}
150        for target in targets.values():
151            typ = target['type']
152            if typ != 'static_library':
153                continue
154            for flag_type in FLAGS:
155                if not flag_type in arch_default_flags:
156                    arch_default_flags[arch][flag_type] = target[flag_type]
157                else:
158                    target_flags = set(target[flag_type])
159                    flags = arch_default_flags[arch][flag_type]
160                    flags[:]  = [ x for x in flags if x in target_flags ]
161        for flag_type, flags in arch_default_flags[arch].items():
162            arch_default_flags[arch][flag_type] = FilterFlags(flags)
163        # Add in the hardcoded extra default cflags
164        arch_default_flags[arch]['cflags'] += DEFAULT_CFLAGS_BY_ARCH.get(arch, [])
165
166    # Iterate through all of the architectures collecting the flags that are the same
167    # for all targets in all architectures.
168    default_flags = {}
169    for arch, flagset in arch_default_flags.items():
170        for flag_type, arch_flags in flagset.items():
171            if not flag_type in default_flags:
172                default_flags[flag_type] = arch_flags.copy()
173            else:
174                flags = default_flags[flag_type]
175                flags[:] = [ x for x in flags if x in arch_flags ]
176    # Add in the hardcoded extra default cflags
177    default_flags['cflags'] += DEFAULT_CFLAGS
178
179    # Remove the global default flags from the per-architecture default flags
180    for arch, flagset in arch_default_flags.items():
181        for flag_type in flagset.keys():
182            flags = flagset[flag_type]
183            flags[:] = [ x for x in flags if x not in default_flags[flag_type] ]
184
185    default_flags['arch'] = arch_default_flags
186    return default_flags
187
188def GenerateDefault(targets_by_arch):
189    in_default = GatherDefaultFlags(targets_by_arch)
190    print('cc_defaults {')
191    print('    name: "webrtc_defaults",')
192    print('    local_include_dirs: [')
193    print('      ".",')
194    print('      "webrtc",')
195    print('      "third_party/crc32c/src/include",')
196    print('    ],')
197    for typ in sorted(in_default.keys() - {'arch'}):
198        flags = in_default[typ]
199        if len(flags) > 0:
200            print('    {0}: ['.format(FLAG_NAME_MAP[typ]))
201            for flag in flags:
202                print('        "{0}",'.format(flag.replace('"', '\\"')))
203            print('    ],')
204    print('    header_libs: [')
205    print('      "libwebrtc_absl_headers",')
206    print('    ],')
207    print('    static_libs: [')
208    print('        "libaom",')
209    print('        "libevent",')
210    print('        "libopus",')
211    print('        "libsrtp2",')
212    print('        "libvpx",')
213    print('        "libyuv",')
214    print('        "libpffft",')
215    print('        "rnnoise_rnn_vad",')
216    print('    ],')
217    print('    shared_libs: [')
218    print('        "libcrypto",')
219    print('        "libprotobuf-cpp-full",')
220    print('        "libprotobuf-cpp-lite",')
221    print('        "libssl",')
222    print('    ],')
223    print('    host_supported: true,')
224    print('    // vendor needed for libpreprocessing effects.')
225    print('    vendor: true,')
226    print('    target: {')
227    print('        darwin: {')
228    print('            enabled: false,')
229    print('        },')
230    print('    },')
231    print('    arch: {')
232    for a in ARCHS:
233        print('        {0}: {{'.format(ARCH_NAME_MAP[a]))
234        for typ in FLAGS:
235            flags = in_default['arch'].get(a, {}).get(typ, [])
236            if len(flags) > 0:
237                print('            {0}: ['.format(FLAG_NAME_MAP[typ]))
238                for flag in flags:
239                    print('                "{0}",'.format(flag.replace('"', '\\"')))
240                print('            ],')
241        print('        },')
242    print('    },')
243    print('    visibility: [')
244    print('        "//frameworks/av/media/libeffects/preprocessing:__subpackages__",')
245    print('        "//device/google/cuttlefish/host/frontend/webrtc:__subpackages__",')
246    print('    ],')
247    print('}')
248
249    # The flags in the default entry can be safely removed from the targets
250    for arch, targets in targets_by_arch.items():
251        for flag_type in FLAGS:
252            default_flags = set(in_default[flag_type]) | set(in_default['arch'][arch][flag_type])
253            for target in targets.values():
254                target[flag_type] = FilterFlags(target.get(flag_type, []), default_flags)
255                if len(target[flag_type]) == 0:
256                    target.pop(flag_type)
257
258    return in_default
259
260
261def TransitiveDependencies(name, dep_type, targets):
262    target = targets[name]
263    field = 'transitive_' + dep_type
264    if field in target.keys():
265        return target[field]
266    target[field] = {'global': set()}
267    for a in ARCHS:
268        target[field][a] = set()
269    if target['type'] == dep_type:
270        target[field]['global'].add(name)
271    for d in target.get('deps', []):
272        if targets[d]['type'] == dep_type:
273            target[field]['global'].add(d)
274        tDeps = TransitiveDependencies(d, dep_type, targets)
275        target[field]['global'] |= tDeps['global']
276        for a in ARCHS:
277            target[field][a] |= tDeps[a]
278    if 'arch' in target:
279        for a, x in target['arch'].items():
280            for d in x.get('deps', []):
281                tDeps = TransitiveDependencies(d, dep_type, targets)
282                target[field][a] |= tDeps['global'] | tDeps[a]
283            target[field][a] -= target[field]['global']
284
285    return target[field]
286
287def GenerateGroup(target):
288    # PrintOrigin(target)
289    pass
290
291def GenerateSourceSet(target):
292    sources = target.get('sources', [])
293    # arch is not defined for filegroups so put all the sources in the top level,
294    # the static libraries that depend on the filegroup will add it in the
295    # appropriate arch.
296    for arch in target.get('arch', {}).values():
297        sources += arch.get('sources', [])
298    if len(sources) == 0:
299        return ''
300    PrintOrigin(target)
301
302    name = target['name']
303    print('filegroup {')
304    print('    name: "{0}",'.format(name))
305    print('    srcs: {0},'.format(FormatList(sources)))
306    print('}')
307    return name
308
309def GenerateStaticLib(target, targets):
310    PrintOrigin(target)
311    name = target['name']
312    print('cc_library_static {')
313    print('    name: "{0}",'.format(name))
314    print('    defaults: ["webrtc_defaults"],')
315    sources = target.get('sources', [])
316    print('    srcs: {0},'.format(FormatList(sources)))
317    print('    host_supported: true,')
318    if 'asmflags' in target.keys():
319        asmflags = target['asmflags']
320        if len(asmflags) > 0:
321            print('    asflags: {0},'.format(FormatList(asmflags)))
322    if 'cflags' in target.keys():
323        cflags = target['cflags']
324        print('    cflags: {0},'.format(FormatList(cflags)))
325    if 'cflags_c' in target.keys():
326        cflags_c = target['cflags_c']
327        if len(cflags_c) > 0:
328            print('    conlyflags: {0},'.format(FormatList(cflags_c)))
329    if 'cflags_cc' in target.keys():
330        cflags_cc = target['cflags_cc']
331        if len(cflags_cc) > 0:
332            print('    cppflags: {0},'.format(FormatList(cflags_cc)))
333    static_libs = sorted([d for d in target.get('deps', []) if targets[d]['type'] == 'static_library'])
334    if len(static_libs) > 0:
335        print('    static_libs: {0},'.format(FormatList(static_libs)))
336    if 'arch' in target:
337        print('   arch: {')
338        for arch_name in ARCHS:
339            if arch_name not in target['arch'].keys():
340                continue
341            arch = target['arch'][arch_name]
342            print('       ' + ARCH_NAME_MAP[arch_name] + ': {')
343            if 'cflags' in arch.keys():
344                cflags = arch['cflags']
345                print('            cflags: {0},'.format(FormatList(cflags)))
346            if 'cflags_c' in arch.keys():
347                cflags_c = arch['cflags_c']
348                if len(cflags_c) > 0:
349                    print('            conlyflags: {0},'.format(FormatList(cflags_c)))
350            if 'cflags_cc' in arch.keys():
351                cflags_cc = arch['cflags_cc']
352                if len(cflags_cc) > 0:
353                    print('            cppflags: {0},'.format(FormatList(cflags_cc)))
354            if 'deps' in arch:
355                  static_libs = [d for d in arch['deps'] if targets[d]['type'] == 'static_library']
356                  print('            static_libs: {0},'.format(FormatList(static_libs)))
357            if 'sources' in arch:
358                  sources = arch['sources']
359                  print('            srcs: {0},'.format(FormatList(sources)))
360            if 'enabled' in arch:
361                print('            enabled: {0},'.format(arch['enabled']))
362            print('        },')
363        print('   },')
364    print('}')
365    return name
366
367def DFS(seed, targets):
368    visited = set()
369    stack = [seed]
370    while len(stack) > 0:
371        nxt = stack.pop()
372        if nxt in visited:
373            continue
374        visited.add(nxt)
375        stack += targets[nxt]['deps']
376        stack += [s[1:] for s in targets[nxt]['sources'] if s.startswith(':')]
377        if 'arch' not in targets[nxt]:
378            continue
379        for arch in targets[nxt]['arch']:
380            if 'deps' in arch:
381                stack += arch['deps']
382            if 'sources' in arch:
383                stack += [s[1:] for s in arch['sources'] if s.startswith(':')]
384    return visited
385
386def Preprocess(project):
387    targets = {}
388    for name, target in project['targets'].items():
389        target['name'] = name
390        targets[name] = target
391        if target['type'] == 'shared_library':
392            # Don't bother creating shared libraries
393            target['type'] = 'static_library'
394        if 'defines' in target:
395            target['cflags'] = target.get('cflags', []) + ['-D{0}'.format(d) for d in target['defines']]
396            target.pop('defines')
397        if 'sources' not in target:
398            continue
399        sources = list(MakeRelatives(FilterIncludes(target['sources'])))
400        if len(sources) > 0:
401            target['sources'] = sources
402        else:
403            target.pop('sources')
404
405    # These dependencies are provided by aosp
406    ignored_targets = {
407            '//third_party/libaom:libaom',
408            '//third_party/libevent:libevent',
409            '//third_party/opus:opus',
410            '//third_party/libsrtp:libsrtp',
411            '//third_party/libvpx:libvpx',
412            '//third_party/libyuv:libyuv',
413            '//third_party/pffft:pffft',
414            '//third_party/rnnoise:rnn_vad',
415            '//third_party/boringssl:boringssl',
416            '//third_party/android_ndk:cpu_features',
417            '//buildtools/third_party/libunwind:libunwind',
418            '//buildtools/third_party/libc++:libc++',
419        }
420    for name, target in targets.items():
421        # Skip all "action" targets
422        if target['type'] in {'action', 'action_foreach'}:
423            ignored_targets.add(name)
424    targets = {name: target for name, target in targets.items() if name not in ignored_targets}
425
426    for target in targets.values():
427        # Don't depend on ignored targets
428        target['deps'] = [d for d in target['deps'] if d not in ignored_targets]
429
430    # filegroups can't have dependencies, so put their dependencies in the static libraries that
431    # depend on them.
432    for target in targets.values():
433        if target['type'] == 'static_library':
434            source_sets = TransitiveDependencies(target['name'], 'source_set', targets)
435            source_sets_deps = {}
436            for a in ['global'] + ARCHS:
437                deps = set()
438                if a == 'global':
439                    for ss in [targets[n].get('deps', []) for n in source_sets[a]]:
440                        deps |= set(ss)
441                else:
442                    for ss in [targets[n].get('arch', {}).get(a, {}).get('deps') for n in source_sets[a]]:
443                        deps |= set(ss)
444                source_sets_deps[a] = deps
445            target['deps'] = sorted(set(target['deps']) | source_sets['global'] | source_sets_deps['global'])
446            for a in ARCHS:
447                deps = source_sets[a] | source_sets_deps[a]
448                if len(deps) == 0:
449                    continue
450                if 'arch' not in target:
451                    target['arch'] = {}
452                if a not in target['arch']:
453                    target['arch'][a] = {}
454                if 'deps' not in target['arch'][a]:
455                    target['arch'][a]['deps'] = []
456                deps |= set(target['arch'][a]['deps'])
457                target['arch'][a]['deps'] = sorted(deps)
458
459    # Ignore empty source sets
460    empty_sets = set()
461    for name, target in targets.items():
462        if target['type'] == 'source_set' and 'sources' not in target:
463            empty_sets.add(name)
464    for s in empty_sets:
465        targets.pop(s)
466    for target in targets.values():
467        target['deps'] = [d for d in target['deps'] if d not in empty_sets]
468
469    # Move source_set dependencies to the sources fields of static libs
470    for target in targets.values():
471        if 'sources' not in target:
472            target['sources'] = []
473        if target['type'] != 'static_library':
474            continue
475        source_sets = {d for d in target['deps'] if targets[d]['type'] == 'source_set'}
476        target['deps'] = sorted(list(set(target['deps']) - source_sets))
477        target['sources'] += [':' + ss for ss in source_sets]
478        target['sources'] = sorted(target['sources'])
479        if 'arch' in target:
480            for arch in target['arch'].values():
481                if 'deps' in arch:
482                    source_sets = {d for d in arch['deps'] if targets[d]['type'] == 'source_set'}
483                    if len(source_sets) == 0:
484                        continue;
485                    arch['deps'] = sorted(list(set(arch['deps']) - source_sets))
486                    arch['sources'] = sorted(arch.get('sources', []) + [':' + ss for ss in source_sets])
487
488    # Select libwebrtc, libaudio_processing and its dependencies
489    selected = set()
490    selected |= DFS('//:webrtc', targets)
491    selected |= DFS('//modules/audio_processing:audio_processing', targets)
492    return {FormatName(n): FormatNames(targets[n]) for n in selected}
493
494def NonNoneFrom(l):
495    for a in l:
496        if a is not None:
497            return a
498    return None
499
500def MergeListField(target, f, target_by_arch):
501    set_by_arch = {}
502    for a, t in target_by_arch.items():
503        if len(t) == 0:
504            # We only care about enabled archs
505            continue
506        set_by_arch[a] = set(t.get(f, []))
507
508    union = set()
509    for _, s in set_by_arch.items():
510        union |= s
511
512    common = union
513    for a, s in set_by_arch.items():
514        common &= s
515
516    not_common = {a: s - common for a,s in set_by_arch.items()}
517
518    if len(common) > 0:
519        target[f] = list(common)
520    for a, s in not_common.items():
521        if len(s) > 0:
522            target['arch'][a][f] = sorted(list(s))
523
524def Merge(target_by_arch):
525    # The new target shouldn't have the transitive dependencies memoization fields
526    # or have the union of those fields from all 4 input targets.
527    target = {}
528    for f in ['original_name', 'name', 'type']:
529        target[f] = NonNoneFrom([t.get(f) for _,t in target_by_arch.items()])
530
531    target['arch'] = {}
532    for a, t in target_by_arch.items():
533        target['arch'][a] = {}
534        if len(t) == 0:
535            target['arch'][a]['enabled'] = 'false'
536
537    list_fields = ['sources',
538                   'deps',
539                   'cflags',
540                   'cflags_c',
541                   'cflags_cc',
542                   'asmflags']
543    for lf in list_fields:
544        MergeListField(target, lf, target_by_arch)
545
546    # Static libraries should be depended on at the root level and disabled for
547    # the corresponding architectures.
548    for arch in target['arch'].values():
549        if 'deps' not in arch:
550            continue
551        deps = arch['deps']
552        if 'deps' not in target:
553            target['deps'] = []
554        target['deps'] += deps
555        arch.pop('deps')
556    if 'deps' in target:
557        target['deps'] = sorted(target['deps'])
558
559    # Remove empty sets
560    for a in ARCHS:
561        if len(target['arch'][a]) == 0:
562            target['arch'].pop(a)
563    if len(target['arch']) == 0:
564        target.pop('arch')
565
566    return target
567
568def DisabledArchs4Target(target):
569    ret = set()
570    for a in ARCHS:
571        if a not in target.get('arch', {}):
572            continue
573        if target['arch'][a].get('enabled', 'true') == 'false':
574            ret.add(a)
575    return ret
576
577
578def HandleDisabledArchs(targets):
579    for n, t in targets.items():
580        if 'arch' not in t:
581            continue
582        disabledArchs = DisabledArchs4Target(t)
583        if len(disabledArchs) == 0:
584            continue
585        # Fix targets that depend on this one
586        for t in targets.values():
587            if DisabledArchs4Target(t) == disabledArchs:
588                # With the same disabled archs there is no need to move dependencies
589                continue
590            if 'deps' in t and n in t['deps']:
591                # Remove the dependency from the high level list
592                t['deps'] = sorted(set(t['deps']) - {n})
593                if 'arch' not in t:
594                    t['arch'] = {}
595                for a in ARCHS:
596                    if a in disabledArchs:
597                        continue
598                    if a not in t['arch']:
599                        t['arch'][a] = {}
600                    if 'deps' not in t['arch'][a]:
601                        t['arch'][a]['deps'] = []
602                    t['arch'][a]['deps'] += [n]
603
604def MergeAll(targets_by_arch):
605    names = set()
606    for t in targets_by_arch.values():
607        names |= t.keys()
608    targets = {}
609    for name in names:
610        targets[name] = Merge({a: t.get(name, {}) for a,t in targets_by_arch.items()})
611
612    HandleDisabledArchs(targets)
613
614    return targets
615
616def GatherAllFlags(obj):
617    if type(obj) != type({}):
618        # not a dictionary
619        return set()
620    ret = set()
621    for f in FLAGS:
622        ret |= set(obj.get(f, []))
623    for v in obj.values():
624        ret |= GatherAllFlags(v)
625    return ret
626
627def FilterFlagsInUse(flags, directory):
628    unused = []
629    for f in flags:
630        nf = f
631        if nf.startswith("-D"):
632            nf = nf[2:]
633            i = nf.find('=')
634            if i > 0:
635                nf = nf[:i]
636        c = os.system(f"find {directory} -name '*.gn*' | xargs grep -q -s -e '{nf}'")
637        if c != 0:
638            # couldn't find the flag in *.gn or *.gni
639            unused.append(f)
640    return unused
641
642if len(sys.argv) != 2:
643    print('wrong number of arguments', file = sys.stderr)
644    exit(1)
645
646dir = sys.argv[1]
647
648targets_by_arch = {}
649flags = set()
650for arch in ARCHS:
651    path = "{0}/project_{1}.json".format(dir, arch)
652    json_file = open(path, 'r')
653    targets_by_arch[arch] = Preprocess(json.load(json_file))
654    flags |= GatherAllFlags(targets_by_arch[arch])
655
656unusedFlags = FilterFlagsInUse(flags, f"{dir}/..")
657IGNORED_FLAGS = sorted(set(IGNORED_FLAGS) | set(unusedFlags))
658
659PrintHeader()
660
661GenerateDefault(targets_by_arch)
662
663targets = MergeAll(targets_by_arch)
664
665print('\n\n')
666
667for name, target in sorted(targets.items()):
668    typ = target['type']
669    if typ == 'static_library':
670        GenerateStaticLib(target, targets)
671    elif typ == 'source_set':
672        GenerateSourceSet(target)
673    elif typ == 'group':
674        GenerateGroup(target)
675    else:
676        print('Unknown type: {0} ({1})'.format(typ, target['name']), file = sys.stderr)
677        exit(1)
678    print('\n\n')
679
680webrtc_libs = TransitiveDependencies(FormatName('//:webrtc'), 'static_library', targets)
681print('cc_library_static {')
682print('    name: "libwebrtc",')
683print('    defaults: ["webrtc_defaults"],')
684print('    export_include_dirs: ["."],')
685print('    whole_static_libs: {0},'.format(FormatList(sorted(webrtc_libs['global']) + ['libpffft', 'rnnoise_rnn_vad'])))
686print('    arch: {')
687for a in ARCHS:
688    if len(webrtc_libs[a]) > 0:
689        print('        {0}: {{'.format(ARCH_NAME_MAP[a]))
690        print('            whole_static_libs: {0},'.format(FormatList(sorted(webrtc_libs[a]))))
691        print('        },')
692print('    },')
693print('}')
694
695print('\n\n')
696
697audio_proc_libs = TransitiveDependencies(FormatName('//modules/audio_processing:audio_processing'), 'static_library', targets)
698print('cc_library_static {')
699print('    name: "webrtc_audio_processing",')
700print('    defaults: ["webrtc_defaults"],')
701print('    export_include_dirs: [')
702print('        ".",')
703print('        "modules/include",')
704print('        "modules/audio_processing/include",')
705print('    ],')
706print('    whole_static_libs: {0},'.format(FormatList(sorted(audio_proc_libs['global']) + ['libpffft', 'rnnoise_rnn_vad'])))
707print('    arch: {')
708for a in ARCHS:
709    if len(audio_proc_libs[a]) > 0:
710        print('        {0}: {{'.format(ARCH_NAME_MAP[a]))
711        print('            whole_static_libs: {0},'.format(FormatList(sorted(audio_proc_libs[a]))))
712        print('        },')
713print('    },')
714print('}')
715