183 lines
5.5 KiB
Python
Executable File
183 lines
5.5 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
# Copyright (C) 2023 The Android Open Source Project
|
|
#
|
|
# 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 json
|
|
import os
|
|
import subprocess
|
|
import sys
|
|
from typing import Any, Dict, List
|
|
import yaml
|
|
|
|
ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
|
|
|
GRPC_GN_HEADER = '''
|
|
#
|
|
# DO NOT EDIT. AUTOGENERATED file
|
|
#
|
|
# This file is generated with the command:
|
|
# tools/gen_grpc_build_gn.py > buildtools/grpc/BUILD.gn
|
|
#
|
|
|
|
import("../../gn/perfetto.gni")
|
|
|
|
# Prevent the gRPC from being depended upon without explicitly being opted in.
|
|
assert(enable_perfetto_grpc)
|
|
|
|
# BoringSSL has assembly code which is tied to platform-specific. For now, we
|
|
# only care about Linux x64 so assert this as the case.
|
|
assert(is_linux && current_cpu == "x64")
|
|
'''
|
|
|
|
TARGET_TEMPLATE = """
|
|
{target_type}("{name}") {{
|
|
sources = {srcs}
|
|
public_deps = {deps}
|
|
public_configs = ["..:{config_name}"]
|
|
configs -= [ "//gn/standalone:extra_warnings" ]
|
|
}}"""
|
|
|
|
LIBRARY_IGNORE_LIST = set([
|
|
'grpcpp_channelz',
|
|
'grpc++_reflection',
|
|
'benchmark_helpers',
|
|
'boringssl_test_util',
|
|
])
|
|
|
|
TARGET_ALLOW_LIST = set([
|
|
'grpc_cpp_plugin',
|
|
])
|
|
|
|
STATIC_LIBRARY_TARGETS = set([
|
|
'upb',
|
|
're2',
|
|
'boringssl',
|
|
'grpc++',
|
|
])
|
|
|
|
|
|
def grpc_relpath(*segments: str) -> str:
|
|
'''From path segments to GRPC root, returns the absolute path.'''
|
|
return os.path.join(ROOT_DIR, 'buildtools', 'grpc', 'src', *segments)
|
|
|
|
|
|
GRPC_BUILD_YAML = grpc_relpath('build_autogenerated.yaml')
|
|
ABSL_GEN_BUILD_YAML = grpc_relpath('src', 'abseil-cpp', 'gen_build_yaml.py')
|
|
UPB_GEN_BUILD_YAML = grpc_relpath('src', 'upb', 'gen_build_yaml.py')
|
|
RE2_GEN_BUILD_YAML = grpc_relpath('src', 're2', 'gen_build_yaml.py')
|
|
BSSL_GEN_BUILD_YAML = grpc_relpath('src', 'boringssl', 'gen_build_yaml.py')
|
|
|
|
|
|
def gen_grpc_dep_yaml(gen_path: str) -> Dict[str, Any]:
|
|
'''Invokes a gen_build_yaml.py file for creating YAML for gRPC deps.'''
|
|
return yaml.safe_load(subprocess.check_output(['python3', gen_path]))
|
|
|
|
|
|
def bazel_label_to_gn_target(dep: str) -> str:
|
|
'''Converts a Bazel label name into a gn target name.'''
|
|
if dep == 'libssl':
|
|
return 'boringssl'
|
|
return dep.replace('/', '_').replace(':', '_')
|
|
|
|
|
|
def get_deps_for_target(target: str) -> List[str]:
|
|
if target == 'grpc_plugin_support':
|
|
return ['..:protoc_lib']
|
|
if target == 'grpc':
|
|
return [':re2', '../../gn:zlib']
|
|
if target == 'grpc_authorization_provider':
|
|
return [':re2']
|
|
return []
|
|
|
|
|
|
def get_library_target_type(target: str) -> str:
|
|
if target in STATIC_LIBRARY_TARGETS:
|
|
return 'static_library'
|
|
return 'source_set'
|
|
|
|
|
|
def yaml_to_gn_targets(desc: Dict[str, Any], build_types: list[str],
|
|
config_name: str) -> List[str]:
|
|
'''Given a gRPC YAML description of the build graph, generates GN targets.'''
|
|
out = []
|
|
for lib in desc['libs']:
|
|
if lib['build'] not in build_types:
|
|
continue
|
|
if lib['name'] in LIBRARY_IGNORE_LIST:
|
|
continue
|
|
srcs = [f'src/{file}' for file in lib['src'] + lib['headers']]
|
|
if 'asm_src' in lib:
|
|
srcs += [f'src/{file}' for file in lib['asm_src']['crypto_linux_x86_64']]
|
|
deps = [f':{bazel_label_to_gn_target(dep)}' for dep in lib.get('deps', [])
|
|
] + get_deps_for_target(lib['name'])
|
|
library_target = TARGET_TEMPLATE.format(
|
|
name=bazel_label_to_gn_target(lib['name']),
|
|
config_name=config_name,
|
|
srcs=json.dumps(srcs),
|
|
deps=json.dumps(deps),
|
|
target_type=get_library_target_type(lib['name']))
|
|
out.append(library_target)
|
|
|
|
for bin in desc.get('targets', []):
|
|
if bin['build'] not in build_types:
|
|
continue
|
|
if bin['name'] not in TARGET_ALLOW_LIST:
|
|
continue
|
|
srcs = json.dumps([f'src/{file}' for file in bin['src'] + bin['headers']])
|
|
deps = [f':{bazel_label_to_gn_target(dep)}' for dep in bin.get('deps', [])
|
|
] + get_deps_for_target(bin['name'])
|
|
binary_target = TARGET_TEMPLATE.format(
|
|
name=bazel_label_to_gn_target(bin['name']),
|
|
config_name=config_name,
|
|
srcs=srcs,
|
|
deps=json.dumps(deps),
|
|
target_type='executable')
|
|
out.append(binary_target)
|
|
return out
|
|
|
|
|
|
def main():
|
|
out: List[str] = []
|
|
|
|
# Generate absl rules
|
|
absl_yaml = gen_grpc_dep_yaml(ABSL_GEN_BUILD_YAML)
|
|
out.extend(yaml_to_gn_targets(absl_yaml, ['private'], 'grpc_absl_config'))
|
|
|
|
# Generate upb rules
|
|
upb_yaml = gen_grpc_dep_yaml(UPB_GEN_BUILD_YAML)
|
|
out.extend(yaml_to_gn_targets(upb_yaml, ['all'], 'grpc_upb_config'))
|
|
|
|
# Generate re2 rules
|
|
re2_yaml = gen_grpc_dep_yaml(RE2_GEN_BUILD_YAML)
|
|
out.extend(yaml_to_gn_targets(re2_yaml, ['private'], 'grpc_re2_config'))
|
|
|
|
# Generate boringssl rules
|
|
boringssl_yaml = gen_grpc_dep_yaml(BSSL_GEN_BUILD_YAML)
|
|
out.extend(
|
|
yaml_to_gn_targets(boringssl_yaml, ['private'], 'grpc_boringssl_config'))
|
|
|
|
# Generate grpc rules
|
|
with open(GRPC_BUILD_YAML, 'r', encoding='utf-8') as f:
|
|
grpc_yaml = yaml.safe_load(f.read())
|
|
out.extend(
|
|
yaml_to_gn_targets(grpc_yaml, ['all', 'protoc'], 'grpc_internal_config'))
|
|
|
|
print(GRPC_GN_HEADER)
|
|
print('\n'.join(out))
|
|
return 0
|
|
|
|
|
|
if __name__ == '__main__':
|
|
sys.exit(main())
|