|
|
|
#!/usr/bin/env python3
|
|
|
|
|
|
|
|
# Copyright 2022 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.
|
|
|
|
|
|
|
|
import argparse
|
|
|
|
import collections
|
|
|
|
from doctest import SKIP
|
|
|
|
import multiprocessing
|
|
|
|
import os
|
|
|
|
import re
|
|
|
|
import sys
|
|
|
|
|
|
|
|
import run_buildozer
|
|
|
|
|
|
|
|
# find our home
|
|
|
|
ROOT = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), "../.."))
|
|
|
|
os.chdir(ROOT)
|
|
|
|
|
|
|
|
vendors = collections.defaultdict(list)
|
|
|
|
scores = collections.defaultdict(int)
|
|
|
|
avoidness = collections.defaultdict(int)
|
|
|
|
consumes = {}
|
|
|
|
no_update = set()
|
|
|
|
buildozer_commands = []
|
|
|
|
original_deps = {}
|
|
|
|
original_external_deps = {}
|
|
|
|
skip_headers = collections.defaultdict(set)
|
|
|
|
|
|
|
|
# TODO(ctiller): ideally we wouldn't hardcode a bunch of paths here.
|
|
|
|
# We can likely parse out BUILD files from dependencies to generate this index.
|
|
|
|
EXTERNAL_DEPS = {
|
|
|
|
"absl/algorithm/container.h": "absl/algorithm:container",
|
|
|
|
"absl/base/attributes.h": "absl/base:core_headers",
|
|
|
|
"absl/base/call_once.h": "absl/base",
|
|
|
|
"absl/base/config.h": "absl/base:config",
|
|
|
|
# TODO(ctiller) remove this
|
|
|
|
"absl/base/internal/endian.h": "absl/base:endian",
|
|
|
|
"absl/base/thread_annotations.h": "absl/base:core_headers",
|
|
|
|
"absl/container/flat_hash_map.h": "absl/container:flat_hash_map",
|
|
|
|
"absl/container/flat_hash_set.h": "absl/container:flat_hash_set",
|
|
|
|
"absl/container/inlined_vector.h": "absl/container:inlined_vector",
|
|
|
|
"absl/cleanup/cleanup.h": "absl/cleanup",
|
|
|
|
"absl/debugging/failure_signal_handler.h": (
|
|
|
|
"absl/debugging:failure_signal_handler"
|
|
|
|
),
|
|
|
|
"absl/debugging/stacktrace.h": "absl/debugging:stacktrace",
|
|
|
|
"absl/debugging/symbolize.h": "absl/debugging:symbolize",
|
|
|
|
"absl/flags/flag.h": "absl/flags:flag",
|
|
|
|
"absl/flags/marshalling.h": "absl/flags:marshalling",
|
|
|
|
"absl/flags/parse.h": "absl/flags:parse",
|
|
|
|
"absl/functional/any_invocable.h": "absl/functional:any_invocable",
|
|
|
|
"absl/functional/bind_front.h": "absl/functional:bind_front",
|
|
|
|
"absl/functional/function_ref.h": "absl/functional:function_ref",
|
|
|
|
"absl/hash/hash.h": "absl/hash",
|
|
|
|
"absl/log/check.h": "absl/log:check",
|
|
|
|
"absl/log/log.h": "absl/log",
|
|
|
|
"absl/memory/memory.h": "absl/memory",
|
|
|
|
"absl/meta/type_traits.h": "absl/meta:type_traits",
|
|
|
|
"absl/numeric/int128.h": "absl/numeric:int128",
|
|
|
|
"absl/random/random.h": "absl/random",
|
|
|
|
"absl/random/bit_gen_ref.h": "absl/random:bit_gen_ref",
|
|
|
|
"absl/random/mocking_bit_gen.h": "absl/random:mocking_bit_gen",
|
|
|
|
"absl/random/distributions.h": "absl/random:distributions",
|
|
|
|
"absl/random/uniform_int_distribution.h": "absl/random:distributions",
|
|
|
|
"absl/status/status.h": "absl/status",
|
|
|
|
"absl/status/statusor.h": "absl/status:statusor",
|
|
|
|
"absl/strings/ascii.h": "absl/strings",
|
|
|
|
"absl/strings/cord.h": "absl/strings:cord",
|
|
|
|
"absl/strings/escaping.h": "absl/strings",
|
|
|
|
"absl/strings/match.h": "absl/strings",
|
|
|
|
"absl/strings/numbers.h": "absl/strings",
|
|
|
|
"absl/strings/str_cat.h": "absl/strings",
|
|
|
|
"absl/strings/str_format.h": "absl/strings:str_format",
|
|
|
|
"absl/strings/str_join.h": "absl/strings",
|
|
|
|
"absl/strings/str_replace.h": "absl/strings",
|
|
|
|
"absl/strings/str_split.h": "absl/strings",
|
|
|
|
"absl/strings/string_view.h": "absl/strings",
|
|
|
|
"absl/strings/strip.h": "absl/strings",
|
|
|
|
"absl/strings/substitute.h": "absl/strings",
|
|
|
|
"absl/synchronization/mutex.h": "absl/synchronization",
|
|
|
|
"absl/synchronization/notification.h": "absl/synchronization",
|
|
|
|
"absl/time/clock.h": "absl/time",
|
|
|
|
"absl/time/time.h": "absl/time",
|
|
|
|
"absl/types/optional.h": "absl/types:optional",
|
|
|
|
"absl/types/span.h": "absl/types:span",
|
|
|
|
"absl/types/variant.h": "absl/types:variant",
|
|
|
|
"absl/utility/utility.h": "absl/utility",
|
|
|
|
"benchmark/benchmark.h": "benchmark",
|
|
|
|
"address_sorting/address_sorting.h": "address_sorting",
|
|
|
|
"google/cloud/opentelemetry/resource_detector.h": "google_cloud_cpp:opentelemetry",
|
|
|
|
"opentelemetry/common/attribute_value.h": "otel/api",
|
|
|
|
"opentelemetry/common/key_value_iterable.h": "otel/api",
|
|
|
|
"opentelemetry/nostd/function_ref.h": "otel/api",
|
|
|
|
"opentelemetry/nostd/string_view.h": "otel/api",
|
|
|
|
"opentelemetry/context/context.h": "otel/api",
|
|
|
|
"opentelemetry/metrics/meter.h": "otel/api",
|
|
|
|
"opentelemetry/metrics/meter_provider.h": "otel/api",
|
|
|
|
"opentelemetry/metrics/provider.h": "otel/api",
|
|
|
|
"opentelemetry/metrics/sync_instruments.h": "otel/api",
|
|
|
|
"opentelemetry/nostd/shared_ptr.h": "otel/api",
|
|
|
|
"opentelemetry/nostd/unique_ptr.h": "otel/api",
|
|
|
|
"opentelemetry/sdk/metrics/meter_provider.h": "otel/sdk/src/metrics",
|
|
|
|
"opentelemetry/sdk/common/attribute_utils.h": "otel/sdk:headers",
|
|
|
|
"opentelemetry/sdk/resource/resource.h": "otel/sdk:headers",
|
|
|
|
"opentelemetry/sdk/resource/resource_detector.h": "otel/sdk:headers",
|
|
|
|
"opentelemetry/sdk/resource/semantic_conventions.h": "otel/sdk:headers",
|
|
|
|
"ares.h": "cares",
|
|
|
|
"fuzztest/fuzztest.h": ["fuzztest", "fuzztest_main"],
|
|
|
|
"google/api/monitored_resource.pb.h": (
|
|
|
|
"google/api:monitored_resource_cc_proto"
|
|
|
|
),
|
|
|
|
"google/devtools/cloudtrace/v2/tracing.grpc.pb.h": (
|
|
|
|
"googleapis_trace_grpc_service"
|
|
|
|
),
|
|
|
|
"google/logging/v2/logging.grpc.pb.h": "googleapis_logging_grpc_service",
|
|
|
|
"google/logging/v2/logging.pb.h": "googleapis_logging_cc_proto",
|
|
|
|
"google/logging/v2/log_entry.pb.h": "googleapis_logging_cc_proto",
|
|
|
|
"google/monitoring/v3/metric_service.grpc.pb.h": (
|
|
|
|
"googleapis_monitoring_grpc_service"
|
|
|
|
),
|
|
|
|
"gmock/gmock.h": "gtest",
|
|
|
|
"gtest/gtest.h": "gtest",
|
|
|
|
"opencensus/exporters/stats/stackdriver/stackdriver_exporter.h": (
|
|
|
|
"opencensus-stats-stackdriver_exporter"
|
|
|
|
),
|
|
|
|
"opencensus/exporters/trace/stackdriver/stackdriver_exporter.h": (
|
|
|
|
"opencensus-trace-stackdriver_exporter"
|
|
|
|
),
|
|
|
|
"opencensus/trace/context_util.h": "opencensus-trace-context_util",
|
|
|
|
"opencensus/trace/propagation/grpc_trace_bin.h": (
|
|
|
|
"opencensus-trace-propagation"
|
|
|
|
),
|
|
|
|
"opencensus/tags/context_util.h": "opencensus-tags-context_util",
|
|
|
|
"opencensus/trace/span_context.h": "opencensus-trace-span_context",
|
|
|
|
"openssl/base.h": "libssl",
|
|
|
|
"openssl/bio.h": "libssl",
|
|
|
|
"openssl/bn.h": "libcrypto",
|
|
|
|
"openssl/buffer.h": "libcrypto",
|
|
|
|
"openssl/crypto.h": "libcrypto",
|
|
|
|
"openssl/digest.h": "libssl",
|
|
|
|
"openssl/engine.h": "libcrypto",
|
|
|
|
"openssl/err.h": "libcrypto",
|
|
|
|
"openssl/evp.h": "libcrypto",
|
|
|
|
"openssl/hmac.h": "libcrypto",
|
|
|
|
"openssl/mem.h": "libcrypto",
|
|
|
|
"openssl/param_build.h": "libcrypto",
|
|
|
|
"openssl/pem.h": "libcrypto",
|
|
|
|
"openssl/rsa.h": "libcrypto",
|
|
|
|
"openssl/sha.h": "libcrypto",
|
|
|
|
"openssl/ssl.h": "libssl",
|
|
|
|
"openssl/tls1.h": "libssl",
|
|
|
|
"openssl/x509.h": "libcrypto",
|
|
|
|
"openssl/x509v3.h": "libcrypto",
|
|
|
|
"re2/re2.h": "re2",
|
|
|
|
"upb/base/status.hpp": "upb_base_lib",
|
|
|
|
"upb/base/string_view.h": "upb_base_lib",
|
|
|
|
"upb/message/map.h": "upb_message_lib",
|
|
|
|
"upb/reflection/def.h": "upb_reflection",
|
|
|
|
"upb/json/encode.h": "upb_json_lib",
|
|
|
|
"upb/mem/arena.h": "upb_mem_lib",
|
|
|
|
"upb/mem/arena.hpp": "upb_mem_lib",
|
|
|
|
"upb/text/encode.h": "upb_textformat_lib",
|
|
|
|
"upb/reflection/def.hpp": "upb_reflection",
|
|
|
|
"xxhash.h": "xxhash",
|
|
|
|
"zlib.h": "madler_zlib",
|
|
|
|
}
|
|
|
|
|
|
|
|
INTERNAL_DEPS = {
|
|
|
|
"test/core/event_engine/fuzzing_event_engine/fuzzing_event_engine.h": (
|
|
|
|
"//test/core/event_engine/fuzzing_event_engine"
|
|
|
|
),
|
|
|
|
"test/core/event_engine/fuzzing_event_engine/fuzzing_event_engine.pb.h": "//test/core/event_engine/fuzzing_event_engine:fuzzing_event_engine_proto",
|
|
|
|
"test/core/experiments/test_experiments.h": "//test/core/experiments:test_experiments_lib",
|
|
|
|
"google/api/expr/v1alpha1/syntax.upb.h": "google_api_expr_v1alpha1_syntax_upb",
|
|
|
|
"google/rpc/status.upb.h": "google_rpc_status_upb",
|
|
|
|
"google/protobuf/any.upb.h": "protobuf_any_upb",
|
|
|
|
"google/protobuf/duration.upb.h": "protobuf_duration_upb",
|
|
|
|
"google/protobuf/struct.upb.h": "protobuf_struct_upb",
|
|
|
|
"google/protobuf/timestamp.upb.h": "protobuf_timestamp_upb",
|
|
|
|
"google/protobuf/wrappers.upb.h": "protobuf_wrappers_upb",
|
|
|
|
"grpc/status.h": "grpc_public_hdrs",
|
|
|
|
"src/proto/grpc/channelz/channelz.grpc.pb.h": (
|
|
|
|
"//src/proto/grpc/channelz:channelz_proto"
|
|
|
|
),
|
|
|
|
"src/proto/grpc/core/stats.pb.h": "//src/proto/grpc/core:stats_proto",
|
|
|
|
"src/proto/grpc/health/v1/health.upb.h": "grpc_health_upb",
|
|
|
|
"src/proto/grpc/lb/v1/load_reporter.grpc.pb.h": (
|
|
|
|
"//src/proto/grpc/lb/v1:load_reporter_proto"
|
|
|
|
),
|
|
|
|
"src/proto/grpc/lb/v1/load_balancer.upb.h": "grpc_lb_upb",
|
|
|
|
"src/proto/grpc/reflection/v1alpha/reflection.grpc.pb.h": (
|
|
|
|
"//src/proto/grpc/reflection/v1alpha:reflection_proto"
|
|
|
|
),
|
|
|
|
"src/proto/grpc/gcp/transport_security_common.upb.h": "alts_upb",
|
|
|
|
"src/proto/grpc/gcp/handshaker.upb.h": "alts_upb",
|
|
|
|
"src/proto/grpc/gcp/altscontext.upb.h": "alts_upb",
|
|
|
|
"src/proto/grpc/lookup/v1/rls.upb.h": "rls_upb",
|
|
|
|
"src/proto/grpc/lookup/v1/rls_config.upb.h": "rls_config_upb",
|
|
|
|
"src/proto/grpc/lookup/v1/rls_config.upbdefs.h": "rls_config_upbdefs",
|
|
|
|
"src/proto/grpc/testing/xds/v3/csds.grpc.pb.h": (
|
|
|
|
"//src/proto/grpc/testing/xds/v3:csds_proto"
|
|
|
|
),
|
|
|
|
"xds/data/orca/v3/orca_load_report.upb.h": "xds_orca_upb",
|
|
|
|
"xds/service/orca/v3/orca.upb.h": "xds_orca_service_upb",
|
|
|
|
"xds/type/v3/typed_struct.upb.h": "xds_type_upb",
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
class FakeSelects:
|
|
|
|
def config_setting_group(self, **kwargs):
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
num_cc_libraries = 0
|
|
|
|
num_opted_out_cc_libraries = 0
|
|
|
|
parsing_path = None
|
|
|
|
|
|
|
|
|
|
|
|
# Convert the source or header target to a relative path.
|
|
|
|
def _get_filename(name, parsing_path):
|
|
|
|
filename = "%s%s" % (
|
|
|
|
(
|
|
|
|
parsing_path + "/"
|
|
|
|
if (parsing_path and not name.startswith("//"))
|
|
|
|
else ""
|
|
|
|
),
|
|
|
|
name,
|
|
|
|
)
|
|
|
|
filename = filename.replace("//:", "")
|
|
|
|
filename = filename.replace("//src/core:", "src/core/")
|
|
|
|
filename = filename.replace(
|
|
|
|
"//src/cpp/ext/filters/census:", "src/cpp/ext/filters/census/"
|
|
|
|
)
|
|
|
|
return filename
|
|
|
|
|
|
|
|
|
|
|
|
def grpc_cc_library(
|
|
|
|
name,
|
|
|
|
hdrs=[],
|
|
|
|
public_hdrs=[],
|
|
|
|
srcs=[],
|
|
|
|
select_deps=None,
|
|
|
|
tags=[],
|
|
|
|
deps=[],
|
|
|
|
external_deps=[],
|
|
|
|
proto=None,
|
|
|
|
**kwargs,
|
|
|
|
):
|
|
|
|
global args
|
|
|
|
global num_cc_libraries
|
|
|
|
global num_opted_out_cc_libraries
|
|
|
|
global parsing_path
|
|
|
|
assert parsing_path is not None
|
|
|
|
try:
|
|
|
|
name = "//%s:%s" % (parsing_path, name)
|
|
|
|
num_cc_libraries += 1
|
|
|
|
if select_deps or "nofixdeps" in tags:
|
|
|
|
if args.whats_left and not select_deps and "nofixdeps" not in tags:
|
|
|
|
num_opted_out_cc_libraries += 1
|
|
|
|
print("Not opted in: {}".format(name))
|
|
|
|
no_update.add(name)
|
|
|
|
scores[name] = len(public_hdrs + hdrs)
|
|
|
|
# avoid_dep is the internal way of saying prefer something else
|
|
|
|
# we add grpc_avoid_dep to allow internal grpc-only stuff to avoid each
|
|
|
|
# other, whilst not biasing dependent projects
|
|
|
|
if "avoid_dep" in tags or "grpc_avoid_dep" in tags:
|
|
|
|
avoidness[name] += 10
|
|
|
|
if proto:
|
|
|
|
proto_hdr = "%s%s" % (
|
|
|
|
(parsing_path + "/" if parsing_path else ""),
|
|
|
|
proto.replace(".proto", ".pb.h"),
|
|
|
|
)
|
|
|
|
skip_headers[name].add(proto_hdr)
|
|
|
|
|
|
|
|
for hdr in hdrs + public_hdrs:
|
|
|
|
vendors[_get_filename(hdr, parsing_path)].append(name)
|
|
|
|
inc = set()
|
|
|
|
original_deps[name] = frozenset(deps)
|
|
|
|
original_external_deps[name] = frozenset(external_deps)
|
|
|
|
for src in hdrs + public_hdrs + srcs:
|
|
|
|
for line in open(_get_filename(src, parsing_path)):
|
|
|
|
m = re.search(r"^#include <(.*)>", line)
|
|
|
|
if m:
|
|
|
|
inc.add(m.group(1))
|
|
|
|
m = re.search(r'^#include "(.*)"', line)
|
|
|
|
if m:
|
|
|
|
inc.add(m.group(1))
|
|
|
|
consumes[name] = list(inc)
|
|
|
|
except:
|
|
|
|
print("Error while parsing ", name)
|
|
|
|
raise
|
|
|
|
|
|
|
|
|
|
|
|
def grpc_proto_library(name, srcs, **kwargs):
|
|
|
|
global parsing_path
|
|
|
|
assert parsing_path is not None
|
|
|
|
name = "//%s:%s" % (parsing_path, name)
|
|
|
|
for src in srcs:
|
|
|
|
proto_hdr = src.replace(".proto", ".pb.h")
|
|
|
|
vendors[_get_filename(proto_hdr, parsing_path)].append(name)
|
|
|
|
|
|
|
|
|
|
|
|
def buildozer(cmd, target):
|
|
|
|
buildozer_commands.append("%s|%s" % (cmd, target))
|
|
|
|
|
|
|
|
|
|
|
|
def buildozer_set_list(name, values, target, via=""):
|
|
|
|
if not values:
|
|
|
|
buildozer("remove %s" % name, target)
|
|
|
|
return
|
|
|
|
adjust = via if via else name
|
|
|
|
buildozer(
|
|
|
|
"set %s %s" % (adjust, " ".join('"%s"' % s for s in values)), target
|
|
|
|
)
|
|
|
|
if via:
|
|
|
|
buildozer("remove %s" % name, target)
|
|
|
|
buildozer("rename %s %s" % (via, name), target)
|
|
|
|
|
|
|
|
|
|
|
|
def score_edit_distance(proposed, existing):
|
|
|
|
"""Score a proposed change primarily by edit distance"""
|
|
|
|
sum = 0
|
|
|
|
for p in proposed:
|
|
|
|
if p not in existing:
|
|
|
|
sum += 1
|
|
|
|
for e in existing:
|
|
|
|
if e not in proposed:
|
|
|
|
sum += 1
|
|
|
|
return sum
|
|
|
|
|
|
|
|
|
|
|
|
def total_score(proposal):
|
|
|
|
return sum(scores[dep] for dep in proposal)
|
|
|
|
|
|
|
|
|
|
|
|
def total_avoidness(proposal):
|
|
|
|
return sum(avoidness[dep] for dep in proposal)
|
|
|
|
|
|
|
|
|
|
|
|
def score_list_size(proposed, existing):
|
|
|
|
"""Score a proposed change primarily by number of dependencies"""
|
|
|
|
return len(proposed)
|
|
|
|
|
|
|
|
|
|
|
|
def score_best(proposed, existing):
|
|
|
|
"""Score a proposed change primarily by dependency score"""
|
|
|
|
return 0
|
|
|
|
|
|
|
|
|
|
|
|
SCORERS = {
|
|
|
|
"edit_distance": score_edit_distance,
|
|
|
|
"list_size": score_list_size,
|
|
|
|
"best": score_best,
|
|
|
|
}
|
|
|
|
|
|
|
|
parser = argparse.ArgumentParser(description="Fix build dependencies")
|
|
|
|
parser.add_argument("targets", nargs="+", help="targets to fix")
|
|
|
|
parser.add_argument(
|
|
|
|
"--score",
|
|
|
|
type=str,
|
|
|
|
default="edit_distance",
|
|
|
|
help="scoring function to use: one of " + ", ".join(SCORERS.keys()),
|
|
|
|
)
|
|
|
|
parser.add_argument(
|
|
|
|
"--whats_left",
|
|
|
|
action="store_true",
|
|
|
|
default=False,
|
|
|
|
help="show what is left to opt in",
|
|
|
|
)
|
|
|
|
parser.add_argument(
|
|
|
|
"--explain",
|
|
|
|
action="store_true",
|
|
|
|
default=False,
|
|
|
|
help="try to explain some decisions",
|
|
|
|
)
|
|
|
|
parser.add_argument(
|
|
|
|
"--why",
|
|
|
|
type=str,
|
|
|
|
default=None,
|
|
|
|
help="with --explain, target why a given dependency is needed",
|
|
|
|
)
|
|
|
|
args = parser.parse_args()
|
|
|
|
|
|
|
|
for dirname in [
|
|
|
|
"",
|
|
|
|
"src/core",
|
|
|
|
"src/cpp/ext/gcp",
|
|
|
|
"src/cpp/ext/csm",
|
|
|
|
"src/cpp/ext/otel",
|
|
|
|
"test/core/util",
|
|
|
|
"test/core/call",
|
|
|
|
"test/core/call/yodel",
|
|
|
|
"test/core/client_channel",
|
|
|
|
"test/core/experiments",
|
|
|
|
"test/core/load_balancing",
|
|
|
|
"test/core/util",
|
|
|
|
"test/core/test_util",
|
|
|
|
"test/core/end2end",
|
|
|
|
"test/core/event_engine",
|
|
|
|
"test/core/filters",
|
|
|
|
"test/core/promise",
|
|
|
|
"test/core/resource_quota",
|
|
|
|
"test/core/transport/chaotic_good",
|
|
|
|
"test/core/transport/test_suite",
|
|
|
|
"test/core/transport",
|
|
|
|
"fuzztest",
|
|
|
|
"fuzztest/core/channel",
|
|
|
|
"fuzztest/core/transport/chttp2",
|
|
|
|
]:
|
|
|
|
parsing_path = dirname
|
|
|
|
exec(
|
|
|
|
open("%sBUILD" % (dirname + "/" if dirname else ""), "r").read(),
|
|
|
|
{
|
|
|
|
"load": lambda filename, *args: None,
|
|
|
|
"licenses": lambda licenses: None,
|
|
|
|
"package": lambda **kwargs: None,
|
|
|
|
"exports_files": lambda files, visibility=None: None,
|
|
|
|
"bool_flag": lambda **kwargs: None,
|
|
|
|
"config_setting": lambda **kwargs: None,
|
|
|
|
"selects": FakeSelects(),
|
|
|
|
"python_config_settings": lambda **kwargs: None,
|
|
|
|
"grpc_cc_benchmark": grpc_cc_library,
|
|
|
|
"grpc_cc_binary": grpc_cc_library,
|
|
|
|
"grpc_cc_library": grpc_cc_library,
|
|
|
|
"grpc_cc_test": grpc_cc_library,
|
|
|
|
"grpc_cc_benchmark": grpc_cc_library,
|
|
|
|
"grpc_core_end2end_test": lambda **kwargs: None,
|
|
|
|
"grpc_filegroup": lambda **kwargs: None,
|
|
|
|
"grpc_transport_test": lambda **kwargs: None,
|
|
|
|
"grpc_yodel_test": lambda **kwargs: None,
|
|
|
|
"grpc_yodel_simple_test": lambda **kwargs: None,
|
|
|
|
"grpc_fuzzer": grpc_cc_library,
|
|
|
|
"grpc_fuzz_test": grpc_cc_library,
|
|
|
|
"grpc_proto_fuzzer": grpc_cc_library,
|
|
|
|
"grpc_proto_library": grpc_proto_library,
|
|
|
|
"grpc_internal_proto_library": grpc_proto_library,
|
|
|
|
"grpc_cc_proto_library": grpc_cc_library,
|
|
|
|
"select": lambda d: d["//conditions:default"],
|
|
|
|
"glob": lambda files, **kwargs: None,
|
|
|
|
"grpc_end2end_tests": lambda: None,
|
|
|
|
"grpc_upb_proto_library": lambda name, **kwargs: None,
|
|
|
|
"grpc_upb_proto_reflection_library": lambda name, **kwargs: None,
|
|
|
|
"grpc_generate_one_off_targets": lambda: None,
|
|
|
|
"grpc_generate_one_off_internal_targets": lambda: None,
|
|
|
|
"grpc_package": lambda **kwargs: None,
|
|
|
|
"filegroup": lambda name, **kwargs: None,
|
|
|
|
"sh_library": lambda name, **kwargs: None,
|
|
|
|
"platform": lambda name, **kwargs: None,
|
|
|
|
"grpc_clang_cl_settings": lambda **kwargs: None,
|
|
|
|
"grpc_benchmark_args": lambda **kwargs: [],
|
[chaotic-good] Revamp wire format (#37765)
Update the chaotic-good wire format with some learnings from the past year, and set up things for the next round of changes we'd like to make:
* Instead of a composite FRAGMENT frame, split out CLIENT_INITIAL_METADATA, CLIENT_END_OF_STREAM, MESSAGE, SERVER_INITIAL_METADATA, SERVER_TRAILING_METADATA as separate frame types - this eliminates a ton of complexity in the transport, and corresponds to how we used the wire format in practice anyway.
* Switch the frame payload for metadata, settings to be protobuf instead of HPACK - this eliminates the ordering requirements on interpreting these frames between streams, which I expect to open up some flexibility with head of line avoidance in the future. It's a heck of a lot easier to read and reason about the code. It's also easier to predict the size of the frame at encode time, which lets us treat metadata and payloads more uniformly in the protocol.
* Add a connection id field to our header, in preparation for allowing multiple data connections
* Allow payloads to be shipped on the control channel ('connection id 0') and use this for sending small messages
Closes #37765
COPYBARA_INTEGRATE_REVIEW=https://github.com/grpc/grpc/pull/37765 from ctiller:tiefling 7b57f723675573fdd22ffab48acf67b716287f3b
PiperOrigin-RevId: 695766541
2 weeks ago
|
|
|
"LARGE_MACHINE": 1,
|
|
|
|
"HISTORY": 1,
|
|
|
|
},
|
|
|
|
{},
|
|
|
|
)
|
|
|
|
parsing_path = None
|
|
|
|
|
|
|
|
if args.whats_left:
|
|
|
|
print(
|
|
|
|
"{}/{} libraries are opted in".format(
|
|
|
|
num_cc_libraries - num_opted_out_cc_libraries, num_cc_libraries
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
def make_relative_path(dep, lib):
|
|
|
|
if lib is None:
|
|
|
|
return dep
|
|
|
|
lib_path = lib[: lib.rfind(":") + 1]
|
|
|
|
if dep.startswith(lib_path):
|
|
|
|
return dep[len(lib_path) :]
|
|
|
|
return dep
|
|
|
|
|
|
|
|
|
|
|
|
if args.whats_left:
|
|
|
|
print(
|
|
|
|
"{}/{} libraries are opted in".format(
|
|
|
|
num_cc_libraries - num_opted_out_cc_libraries, num_cc_libraries
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
# Keeps track of all possible sets of dependencies that could satisfy the
|
|
|
|
# problem. (models the list monad in Haskell!)
|
|
|
|
class Choices:
|
|
|
|
def __init__(self, library, substitutions):
|
|
|
|
self.library = library
|
|
|
|
self.to_add = []
|
|
|
|
self.to_remove = []
|
|
|
|
self.substitutions = substitutions
|
|
|
|
|
|
|
|
def add_one_of(self, choices, trigger):
|
|
|
|
if not choices:
|
|
|
|
return
|
|
|
|
choices = sum(
|
|
|
|
[self.apply_substitutions(choice) for choice in choices], []
|
|
|
|
)
|
|
|
|
if args.explain and (args.why is None or args.why in choices):
|
|
|
|
print(
|
|
|
|
"{}: Adding one of {} for {}".format(
|
|
|
|
self.library, choices, trigger
|
|
|
|
)
|
|
|
|
)
|
|
|
|
self.to_add.append(
|
|
|
|
tuple(
|
|
|
|
make_relative_path(choice, self.library) for choice in choices
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
def add(self, choice, trigger):
|
|
|
|
self.add_one_of([choice], trigger)
|
|
|
|
|
|
|
|
def remove(self, remove):
|
|
|
|
for remove in self.apply_substitutions(remove):
|
|
|
|
self.to_remove.append(make_relative_path(remove, self.library))
|
|
|
|
|
|
|
|
def apply_substitutions(self, dep):
|
|
|
|
if dep in self.substitutions:
|
|
|
|
return self.substitutions[dep]
|
|
|
|
return [dep]
|
|
|
|
|
|
|
|
def best(self, scorer):
|
|
|
|
choices = set()
|
|
|
|
choices.add(frozenset())
|
|
|
|
|
|
|
|
for add in sorted(set(self.to_add), key=lambda x: (len(x), x)):
|
|
|
|
new_choices = set()
|
|
|
|
for append_choice in add:
|
|
|
|
for choice in choices:
|
|
|
|
new_choices.add(choice.union([append_choice]))
|
|
|
|
choices = new_choices
|
|
|
|
for remove in sorted(set(self.to_remove)):
|
|
|
|
new_choices = set()
|
|
|
|
for choice in choices:
|
|
|
|
new_choices.add(choice.difference([remove]))
|
|
|
|
choices = new_choices
|
|
|
|
|
|
|
|
best = None
|
|
|
|
|
|
|
|
def final_scorer(x):
|
|
|
|
return (total_avoidness(x), scorer(x), total_score(x))
|
|
|
|
|
|
|
|
for choice in choices:
|
|
|
|
if best is None or final_scorer(choice) < final_scorer(best):
|
|
|
|
best = choice
|
|
|
|
return best
|
|
|
|
|
|
|
|
|
|
|
|
def make_library(library):
|
|
|
|
error = False
|
|
|
|
hdrs = sorted(consumes[library])
|
|
|
|
# we need a little trickery here since grpc_base has channel.cc, which calls grpc_init
|
|
|
|
# which is in grpc, which is illegal but hard to change
|
|
|
|
# once EventEngine lands we can clean this up
|
|
|
|
deps = Choices(
|
|
|
|
library,
|
|
|
|
(
|
|
|
|
{"//:grpc_base": ["//:grpc", "//:grpc_unsecure"]}
|
|
|
|
if library.startswith("//test/")
|
|
|
|
else {}
|
|
|
|
),
|
|
|
|
)
|
|
|
|
external_deps = Choices(None, {})
|
|
|
|
for hdr in hdrs:
|
|
|
|
if hdr in skip_headers[library]:
|
|
|
|
continue
|
|
|
|
|
|
|
|
if hdr == "systemd/sd-daemon.h":
|
|
|
|
continue
|
|
|
|
|
|
|
|
if hdr == "src/core/lib/profiling/stap_probes.h":
|
|
|
|
continue
|
|
|
|
|
|
|
|
if hdr.startswith("src/libfuzzer/"):
|
|
|
|
continue
|
|
|
|
|
|
|
|
if hdr == "grpc/grpc.h" and library.startswith("//test:"):
|
|
|
|
# not the root build including grpc.h ==> //:grpc
|
|
|
|
deps.add_one_of(["//:grpc", "//:grpc_unsecure"], hdr)
|
|
|
|
continue
|
|
|
|
|
|
|
|
if hdr in INTERNAL_DEPS:
|
|
|
|
dep = INTERNAL_DEPS[hdr]
|
|
|
|
if isinstance(dep, list):
|
|
|
|
for d in dep:
|
|
|
|
deps.add(d, hdr)
|
|
|
|
else:
|
|
|
|
if not ("//" in dep):
|
|
|
|
dep = "//:" + dep
|
|
|
|
deps.add(dep, hdr)
|
|
|
|
continue
|
|
|
|
|
|
|
|
if hdr in vendors:
|
|
|
|
deps.add_one_of(vendors[hdr], hdr)
|
|
|
|
continue
|
|
|
|
|
|
|
|
if "include/" + hdr in vendors:
|
|
|
|
deps.add_one_of(vendors["include/" + hdr], hdr)
|
|
|
|
continue
|
|
|
|
|
|
|
|
if "." not in hdr:
|
|
|
|
# assume a c++ system include
|
|
|
|
continue
|
|
|
|
|
|
|
|
if hdr in EXTERNAL_DEPS:
|
|
|
|
if isinstance(EXTERNAL_DEPS[hdr], list):
|
|
|
|
for dep in EXTERNAL_DEPS[hdr]:
|
|
|
|
external_deps.add(dep, hdr)
|
|
|
|
else:
|
|
|
|
external_deps.add(EXTERNAL_DEPS[hdr], hdr)
|
|
|
|
continue
|
|
|
|
|
|
|
|
if hdr.startswith("opencensus/"):
|
|
|
|
trail = hdr[len("opencensus/") :]
|
|
|
|
trail = trail[: trail.find("/")]
|
|
|
|
external_deps.add("opencensus-" + trail, hdr)
|
|
|
|
continue
|
|
|
|
|
|
|
|
if hdr.startswith("envoy/"):
|
|
|
|
path, file = os.path.split(hdr)
|
|
|
|
file = file.split(".")
|
|
|
|
path = path.split("/")
|
|
|
|
dep = "_".join(path[:-1] + [file[1]])
|
|
|
|
deps.add(dep, hdr)
|
|
|
|
continue
|
|
|
|
|
|
|
|
if hdr.startswith("google/protobuf/") and not hdr.endswith(".upb.h"):
|
|
|
|
external_deps.add("protobuf_headers", hdr)
|
|
|
|
continue
|
|
|
|
|
|
|
|
if "/" not in hdr:
|
|
|
|
# assume a system include
|
|
|
|
continue
|
|
|
|
|
|
|
|
is_sys_include = False
|
|
|
|
for sys_path in [
|
|
|
|
"sys",
|
|
|
|
"arpa",
|
|
|
|
"gperftools",
|
|
|
|
"netinet",
|
|
|
|
"linux",
|
|
|
|
"android",
|
|
|
|
"mach",
|
|
|
|
"net",
|
|
|
|
"CoreFoundation",
|
|
|
|
]:
|
|
|
|
if hdr.startswith(sys_path + "/"):
|
|
|
|
is_sys_include = True
|
|
|
|
break
|
|
|
|
if is_sys_include:
|
|
|
|
# assume a system include
|
|
|
|
continue
|
|
|
|
|
|
|
|
print(
|
|
|
|
"# ERROR: can't categorize header: %s used by %s" % (hdr, library)
|
|
|
|
)
|
|
|
|
error = True
|
|
|
|
|
|
|
|
deps.remove(library)
|
|
|
|
|
|
|
|
deps = sorted(
|
|
|
|
deps.best(lambda x: SCORERS[args.score](x, original_deps[library]))
|
|
|
|
)
|
|
|
|
external_deps = sorted(
|
|
|
|
external_deps.best(
|
|
|
|
lambda x: SCORERS[args.score](x, original_external_deps[library])
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
return (library, error, deps, external_deps)
|
|
|
|
|
|
|
|
|
|
|
|
def matches_target(library, target):
|
|
|
|
if not target.startswith("//"):
|
|
|
|
if "/" in target:
|
|
|
|
target = "//" + target
|
|
|
|
else:
|
|
|
|
target = "//:" + target
|
|
|
|
if target == "..." or target == "//...":
|
|
|
|
return True
|
|
|
|
if target.endswith("/..."):
|
|
|
|
return library.startswith(target[:-4])
|
|
|
|
return library == target
|
|
|
|
|
|
|
|
|
|
|
|
def main() -> None:
|
|
|
|
update_libraries = []
|
|
|
|
for library in sorted(consumes.keys()):
|
|
|
|
if library in no_update:
|
|
|
|
continue
|
|
|
|
for target in args.targets:
|
|
|
|
if matches_target(library, target):
|
|
|
|
update_libraries.append(library)
|
|
|
|
break
|
|
|
|
with multiprocessing.Pool(processes=multiprocessing.cpu_count()) as p:
|
|
|
|
updated_libraries = p.map(make_library, update_libraries, 1)
|
|
|
|
|
|
|
|
error = False
|
|
|
|
for library, lib_error, deps, external_deps in updated_libraries:
|
|
|
|
if lib_error:
|
|
|
|
error = True
|
|
|
|
continue
|
|
|
|
buildozer_set_list("external_deps", external_deps, library, via="deps")
|
|
|
|
buildozer_set_list("deps", deps, library)
|
|
|
|
|
|
|
|
run_buildozer.run_buildozer(buildozer_commands)
|
|
|
|
|
|
|
|
if error:
|
|
|
|
sys.exit(1)
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
main()
|