From 898d8fa1fd6ff07149b283b3bbff00a6a3d8c52b Mon Sep 17 00:00:00 2001 From: Mike Kruskal Date: Wed, 18 Oct 2023 12:21:32 -0700 Subject: [PATCH] Open-source editions Bazel rules for embedding defaults. These utilities provide a way to embed a FeatureSetDefaults message into generators or runtimes that need to implement feature resolution. They use protoc to handle the tricky reflection-based algorithm over feature protos, leaving only simple merges to be implemented in other languages. See docs/design/editions/editions-life-of-a-featureset.md for more information. PiperOrigin-RevId: 574554333 --- BUILD.bazel | 1 - cmake/tests.cmake | 1 + src/google/protobuf/BUILD.bazel | 46 ++++-- src/google/protobuf/compiler/BUILD.bazel | 28 +++- .../protobuf/compiler/allowlists/BUILD.bazel | 4 +- src/google/protobuf/compiler/cpp/BUILD.bazel | 6 +- .../protobuf/compiler/csharp/BUILD.bazel | 4 +- src/google/protobuf/compiler/java/BUILD.bazel | 8 +- .../protobuf/compiler/main_no_generators.cc | 36 +++++ .../protobuf/compiler/objectivec/BUILD.bazel | 8 +- src/google/protobuf/compiler/php/BUILD.bazel | 4 +- .../protobuf/compiler/python/BUILD.bazel | 2 +- src/google/protobuf/compiler/ruby/BUILD.bazel | 2 +- src/google/protobuf/compiler/rust/BUILD.bazel | 14 +- src/google/protobuf/editions/BUILD | 84 ++++++++++ src/google/protobuf/editions/defaults.bzl | 112 ++++++++++++++ src/google/protobuf/editions/defaults_test.cc | 145 ++++++++++++++++++ .../editions/internal_defaults_escape.cc | 35 +++++ src/google/protobuf/io/BUILD.bazel | 12 +- src/google/protobuf/stubs/BUILD.bazel | 4 +- src/google/protobuf/testing/BUILD.bazel | 2 +- 21 files changed, 503 insertions(+), 55 deletions(-) create mode 100644 src/google/protobuf/compiler/main_no_generators.cc create mode 100644 src/google/protobuf/editions/defaults.bzl create mode 100644 src/google/protobuf/editions/defaults_test.cc create mode 100644 src/google/protobuf/editions/internal_defaults_escape.cc diff --git a/BUILD.bazel b/BUILD.bazel index 23efee4a31..5951297816 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -224,7 +224,6 @@ alias( cc_library( name = "protobuf", copts = COPTS, - include_prefix = "google/protobuf/io", linkopts = LINK_OPTS, visibility = ["//visibility:public"], deps = [ diff --git a/cmake/tests.cmake b/cmake/tests.cmake index 489ca65c2a..044af4835f 100644 --- a/cmake/tests.cmake +++ b/cmake/tests.cmake @@ -62,6 +62,7 @@ set(tests_files ${protobuf_test_files} ${compiler_test_files} ${annotation_test_util_srcs} + ${editions_test_files} ${io_test_files} ${util_test_files} ${stubs_test_files} diff --git a/src/google/protobuf/BUILD.bazel b/src/google/protobuf/BUILD.bazel index 8961ca6af1..f85e88b16c 100644 --- a/src/google/protobuf/BUILD.bazel +++ b/src/google/protobuf/BUILD.bazel @@ -162,6 +162,7 @@ cc_library( copts = COPTS, includes = ["wkt"], linkopts = LINK_OPTS, + strip_include_prefix = "/src", visibility = ["//pkg:__pkg__"], deps = [":protobuf_nowkt"], ) @@ -198,7 +199,7 @@ cc_library( "port_def.inc", "port_undef.inc", ], - include_prefix = "google/protobuf", + strip_include_prefix = "/src", visibility = [ "//:__subpackages__", "//src/google/protobuf:__subpackages__", @@ -212,7 +213,7 @@ cc_library( name = "varint_shuffle", hdrs = ["varint_shuffle.h"], copts = COPTS, - include_prefix = "google/protobuf", + strip_include_prefix = "/src", visibility = [ "//:__subpackages__", "//src/google/protobuf:__subpackages__", @@ -248,7 +249,7 @@ cc_library( name = "arena_align", srcs = ["arena_align.cc"], hdrs = ["arena_align.h"], - include_prefix = "google/protobuf", + strip_include_prefix = "/src", visibility = [ "//:__subpackages__", "//src/google/protobuf:__subpackages__", @@ -264,7 +265,7 @@ cc_library( cc_library( name = "arena_cleanup", hdrs = ["arena_cleanup.h"], - include_prefix = "google/protobuf", + strip_include_prefix = "/src", visibility = [ "//:__subpackages__", "//src/google/protobuf:__subpackages__", @@ -278,7 +279,7 @@ cc_library( cc_library( name = "arena_allocation_policy", hdrs = ["arena_allocation_policy.h"], - include_prefix = "google/protobuf", + strip_include_prefix = "/src", visibility = [ "//:__subpackages__", "//src/google/protobuf:__subpackages__", @@ -291,7 +292,7 @@ cc_library( cc_library( name = "string_block", hdrs = ["string_block.h"], - include_prefix = "google/protobuf", + strip_include_prefix = "/src", deps = [ ":arena_align", "@com_google_absl//absl/base:core_headers", @@ -320,7 +321,7 @@ cc_library( "serial_arena.h", "thread_safe_arena.h", ], - include_prefix = "google/protobuf", + strip_include_prefix = "/src", visibility = [ "//:__subpackages__", "//src/google/protobuf:__subpackages__", @@ -343,7 +344,7 @@ cc_library( name = "internal_visibility", hdrs = ["internal_visibility.h"], copts = COPTS, - include_prefix = "google/protobuf", + strip_include_prefix = "/src", visibility = [ "//:__subpackages__", "//src/google/protobuf:__subpackages__", @@ -355,7 +356,7 @@ cc_library( testonly = 1, hdrs = ["internal_visibility_for_testing.h"], copts = COPTS, - include_prefix = "google/protobuf", + strip_include_prefix = "/src", visibility = [ "//:__subpackages__", "//src/google/protobuf:__subpackages__", @@ -419,8 +420,8 @@ cc_library( "-Wno-error", ], }), - include_prefix = "google/protobuf", linkopts = LINK_OPTS, + strip_include_prefix = "/src", visibility = [ "//:__pkg__", "//pkg:__pkg__", @@ -506,8 +507,8 @@ cc_library( "wire_format.h", ], copts = COPTS, - include_prefix = "google/protobuf", linkopts = LINK_OPTS, + strip_include_prefix = "/src", visibility = [ "//:__pkg__", "//pkg:__pkg__", @@ -549,8 +550,8 @@ cc_test( cc_library( name = "protobuf", copts = COPTS, - include_prefix = "google/protobuf", linkopts = LINK_OPTS, + strip_include_prefix = "/src", visibility = [ "//:__pkg__", "//pkg:__pkg__", @@ -573,14 +574,15 @@ cc_library( "**/*.h", "**/*.inc", ]), + strip_include_prefix = "/src", ) cc_library( name = "descriptor_legacy", hdrs = ["descriptor_legacy.h"], copts = COPTS, - include_prefix = "google/protobuf", linkopts = LINK_OPTS, + strip_include_prefix = "/src", visibility = ["//:__subpackages__"], deps = [ ":port_def", @@ -593,8 +595,8 @@ cc_library( name = "descriptor_visitor", hdrs = ["descriptor_visitor.h"], copts = COPTS, - include_prefix = "google/protobuf", linkopts = LINK_OPTS, + strip_include_prefix = "/src", visibility = ["//:__subpackages__"], deps = [ ":port_def", @@ -749,6 +751,22 @@ proto_library( ], ) +proto_library( + name = "unittest_features_proto", + srcs = ["unittest_features.proto"], + strip_import_prefix = "/src", + visibility = ["//src/google/protobuf:__subpackages__"], + deps = [ + ":descriptor_proto", + ], +) + +cc_proto_library( + name = "unittest_features_cc_proto", + visibility = ["//src/google/protobuf:__subpackages__"], + deps = [":unittest_features_proto"], +) + proto_library( name = "generic_test_protos", srcs = [":test_proto_srcs"], diff --git a/src/google/protobuf/compiler/BUILD.bazel b/src/google/protobuf/compiler/BUILD.bazel index 273dae00b4..f98c31785b 100644 --- a/src/google/protobuf/compiler/BUILD.bazel +++ b/src/google/protobuf/compiler/BUILD.bazel @@ -42,7 +42,7 @@ cc_library( "parser.h", ], copts = COPTS, - include_prefix = "google/protobuf/compiler", + strip_include_prefix = "/src", visibility = ["//visibility:public"], deps = [ "//src/google/protobuf:protobuf_nowkt", @@ -66,7 +66,7 @@ cc_library( "scc.h", ], copts = COPTS, - include_prefix = "google/protobuf/compiler", + strip_include_prefix = "/src", visibility = ["//visibility:public"], deps = [ "//src/google/protobuf:protobuf_nowkt", @@ -87,7 +87,7 @@ cc_library( "versions_suffix.h", ], copts = COPTS, - include_prefix = "google/protobuf/compiler", + strip_include_prefix = "/src", visibility = [ "//src/google/protobuf/compiler:__subpackages__", ], @@ -107,7 +107,7 @@ cc_library( "zip_writer.h", ], copts = COPTS, - include_prefix = "google/protobuf/compiler", + strip_include_prefix = "/src", visibility = ["//visibility:public"], deps = [ ":code_generator", @@ -133,6 +133,7 @@ cc_library( "main.cc", ], copts = COPTS, + strip_include_prefix = "/src", visibility = [ "//:__pkg__", "//pkg:__pkg__", @@ -154,6 +155,23 @@ cc_library( ], ) +# This is a build of the protobuf compiler without code generators. +cc_binary( + name = "protoc_minimal", + srcs = [ + "main_no_generators.cc", + ], + copts = COPTS, + visibility = [ + "//src/google/protobuf:__subpackages__", + ], + deps = [ + ":command_line_interface", + "//src/google/protobuf:port_def", + "@com_google_absl//absl/log:initialize", + ], +) + # Note: this is an alias for now. In the future, this rule will become the # cc_binary for protoc, and //:protoc will become an alias. alias( @@ -397,7 +415,7 @@ cc_library( name = "retention", srcs = ["retention.cc"], hdrs = ["retention.h"], - include_prefix = "google/protobuf/compiler", + strip_include_prefix = "/src", visibility = ["//src/google/protobuf:__subpackages__"], deps = [ "//src/google/protobuf:protobuf_nowkt", diff --git a/src/google/protobuf/compiler/allowlists/BUILD.bazel b/src/google/protobuf/compiler/allowlists/BUILD.bazel index 470181fd6d..e6671c05c1 100644 --- a/src/google/protobuf/compiler/allowlists/BUILD.bazel +++ b/src/google/protobuf/compiler/allowlists/BUILD.bazel @@ -7,7 +7,7 @@ cc_library( name = "allowlist", hdrs = ["allowlist.h"], copts = COPTS, - include_prefix = "google/protobuf/compiler/allowlists", + strip_include_prefix = "/src", deps = [ "//src/google/protobuf/stubs", "@com_google_absl//absl/algorithm:container", @@ -28,7 +28,7 @@ cc_library( ], hdrs = ["allowlists.h"], copts = COPTS, - include_prefix = "google/protobuf/compiler/allowlists", + strip_include_prefix = "/src", visibility = ["//src/google/protobuf:__subpackages__"], deps = [ ":allowlist", diff --git a/src/google/protobuf/compiler/cpp/BUILD.bazel b/src/google/protobuf/compiler/cpp/BUILD.bazel index 8ca37b4b67..fb168b03db 100644 --- a/src/google/protobuf/compiler/cpp/BUILD.bazel +++ b/src/google/protobuf/compiler/cpp/BUILD.bazel @@ -11,7 +11,7 @@ cc_library( name = "names", hdrs = ["names.h"], copts = COPTS, - include_prefix = "google/protobuf/compiler/cpp", + strip_include_prefix = "/src", visibility = ["//visibility:public"], deps = [ ":names_internal", @@ -32,7 +32,7 @@ cc_library( "options.h", ], copts = COPTS, - include_prefix = "google/protobuf/compiler/cpp", + strip_include_prefix = "/src", visibility = [ "//pkg:__pkg__", "//src/google/protobuf/compiler/rust:__subpackages__", @@ -79,7 +79,7 @@ cc_library( "tracker.h", ], copts = COPTS, - include_prefix = "google/protobuf/compiler/cpp", + strip_include_prefix = "/src", visibility = [ "//pkg:__pkg__", "//src/google/protobuf/compiler:__pkg__", diff --git a/src/google/protobuf/compiler/csharp/BUILD.bazel b/src/google/protobuf/compiler/csharp/BUILD.bazel index 414dd0ffd6..a182bc2a30 100644 --- a/src/google/protobuf/compiler/csharp/BUILD.bazel +++ b/src/google/protobuf/compiler/csharp/BUILD.bazel @@ -11,7 +11,7 @@ cc_library( srcs = ["names.cc"], hdrs = ["names.h"], copts = COPTS, - include_prefix = "google/protobuf/compiler/csharp", + strip_include_prefix = "/src", visibility = ["//visibility:public"], deps = [ "//src/google/protobuf:protobuf_nowkt", @@ -62,7 +62,7 @@ cc_library( "//build_defs:config_msvc": [], "//conditions:default": ["-Wno-overloaded-virtual"], }), - include_prefix = "google/protobuf/compiler/csharp", + strip_include_prefix = "/src", visibility = [ "//pkg:__pkg__", "//src/google/protobuf/compiler:__pkg__", diff --git a/src/google/protobuf/compiler/java/BUILD.bazel b/src/google/protobuf/compiler/java/BUILD.bazel index a9461d0901..8ca67c1bbb 100644 --- a/src/google/protobuf/compiler/java/BUILD.bazel +++ b/src/google/protobuf/compiler/java/BUILD.bazel @@ -10,7 +10,7 @@ cc_library( name = "names", hdrs = ["names.h"], copts = COPTS, - include_prefix = "google/protobuf/compiler/java", + strip_include_prefix = "/src", visibility = ["//visibility:public"], deps = [ ":names_internal", @@ -33,7 +33,7 @@ cc_library( "options.h", ], copts = COPTS, - include_prefix = "google/protobuf/compiler/java", + strip_include_prefix = "/src", visibility = ["//pkg:__pkg__"], deps = [ ":java_features_bootstrap", @@ -48,7 +48,7 @@ cc_library( name = "java_features_bootstrap", srcs = ["java_features.pb.cc"], hdrs = ["java_features.pb.h"], - include_prefix = "google/protobuf/compiler/java", + strip_include_prefix = "/src", deps = [ "//src/google/protobuf:arena", "//src/google/protobuf:protobuf_nowkt", @@ -119,7 +119,7 @@ cc_library( "string_field_lite.h", ], copts = COPTS, - include_prefix = "google/protobuf/compiler/java", + strip_include_prefix = "/src", visibility = [ "//pkg:__pkg__", "//src/google/protobuf/compiler:__pkg__", diff --git a/src/google/protobuf/compiler/main_no_generators.cc b/src/google/protobuf/compiler/main_no_generators.cc new file mode 100644 index 0000000000..83a44e8b4c --- /dev/null +++ b/src/google/protobuf/compiler/main_no_generators.cc @@ -0,0 +1,36 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file or at +// https://developers.google.com/open-source/licenses/bsd + +#include "google/protobuf/compiler/command_line_interface.h" + +#include "absl/log/initialize.h" + +// Must be included last. +#include "google/protobuf/port_def.inc" + +namespace google { +namespace protobuf { +namespace compiler { + +// This is a version of protoc that has no built-in code generators. +// See go/protobuf-toolchain-protoc +int ProtocMain(int argc, char* argv[]) { + absl::InitializeLog(); + + CommandLineInterface cli; + cli.AllowPlugins("protoc-"); + + return cli.Run(argc, argv); +} + +} // namespace compiler +} // namespace protobuf +} // namespace google + +int main(int argc, char* argv[]) { + return google::protobuf::compiler::ProtocMain(argc, argv); +} diff --git a/src/google/protobuf/compiler/objectivec/BUILD.bazel b/src/google/protobuf/compiler/objectivec/BUILD.bazel index 5ab3381afa..a3a6fcfec0 100644 --- a/src/google/protobuf/compiler/objectivec/BUILD.bazel +++ b/src/google/protobuf/compiler/objectivec/BUILD.bazel @@ -10,7 +10,7 @@ cc_library( name = "names", hdrs = ["names.h"], copts = COPTS, - include_prefix = "google/protobuf/compiler/objectivec", + strip_include_prefix = "/src", visibility = ["//visibility:public"], deps = [ ":names_internal", @@ -27,7 +27,7 @@ cc_library( "nsobject_methods.h", ], copts = COPTS, - include_prefix = "google/protobuf/compiler/objectivec", + strip_include_prefix = "/src", visibility = ["//pkg:__pkg__"], deps = [ ":line_consumer", @@ -43,7 +43,7 @@ cc_library( srcs = ["line_consumer.cc"], hdrs = ["line_consumer.h"], copts = COPTS, - include_prefix = "google/protobuf/compiler/objectivec", + strip_include_prefix = "/src", visibility = ["//pkg:__pkg__"], deps = [ "//src/google/protobuf:protobuf_nowkt", @@ -87,7 +87,7 @@ cc_library( "text_format_decode_data.h", ], copts = COPTS, - include_prefix = "google/protobuf/compiler/objectivec", + strip_include_prefix = "/src", visibility = [ "//pkg:__pkg__", "//src/google/protobuf/compiler:__pkg__", diff --git a/src/google/protobuf/compiler/php/BUILD.bazel b/src/google/protobuf/compiler/php/BUILD.bazel index f814a03a74..2a9746d808 100644 --- a/src/google/protobuf/compiler/php/BUILD.bazel +++ b/src/google/protobuf/compiler/php/BUILD.bazel @@ -11,7 +11,7 @@ cc_library( srcs = ["names.cc"], hdrs = ["names.h"], copts = COPTS, - include_prefix = "google/protobuf/compiler/php", + strip_include_prefix = "/src", visibility = ["//visibility:public"], deps = [ "//src/google/protobuf:protobuf_nowkt", @@ -25,7 +25,7 @@ cc_library( srcs = ["php_generator.cc"], hdrs = ["php_generator.h"], copts = COPTS, - include_prefix = "google/protobuf/compiler/php", + strip_include_prefix = "/src", visibility = [ "//pkg:__pkg__", "//src/google/protobuf/compiler:__pkg__", diff --git a/src/google/protobuf/compiler/python/BUILD.bazel b/src/google/protobuf/compiler/python/BUILD.bazel index 64b5808cb6..e9501f2b56 100644 --- a/src/google/protobuf/compiler/python/BUILD.bazel +++ b/src/google/protobuf/compiler/python/BUILD.bazel @@ -19,7 +19,7 @@ cc_library( "pyi_generator.h", ], copts = COPTS, - include_prefix = "google/protobuf/compiler/python", + strip_include_prefix = "/src", visibility = [ "//pkg:__pkg__", "//src/google/protobuf/compiler:__pkg__", diff --git a/src/google/protobuf/compiler/ruby/BUILD.bazel b/src/google/protobuf/compiler/ruby/BUILD.bazel index d01764c2ff..62afc3c35a 100644 --- a/src/google/protobuf/compiler/ruby/BUILD.bazel +++ b/src/google/protobuf/compiler/ruby/BUILD.bazel @@ -11,7 +11,7 @@ cc_library( srcs = ["ruby_generator.cc"], hdrs = ["ruby_generator.h"], copts = COPTS, - include_prefix = "google/protobuf/compiler/ruby", + strip_include_prefix = "/src", visibility = [ "//pkg:__pkg__", "//src/google/protobuf/compiler:__pkg__", diff --git a/src/google/protobuf/compiler/rust/BUILD.bazel b/src/google/protobuf/compiler/rust/BUILD.bazel index 1429b9bff1..9939c2ca21 100644 --- a/src/google/protobuf/compiler/rust/BUILD.bazel +++ b/src/google/protobuf/compiler/rust/BUILD.bazel @@ -10,7 +10,7 @@ cc_library( srcs = ["generator.cc"], hdrs = ["generator.h"], copts = COPTS, - include_prefix = "google/protobuf/compiler/rust", + strip_include_prefix = "/src", visibility = [ "//pkg:__pkg__", "//src/google/protobuf/compiler:__pkg__", @@ -34,7 +34,7 @@ cc_library( srcs = ["message.cc"], hdrs = ["message.h"], copts = COPTS, - include_prefix = "google/protobuf/compiler/rust", + strip_include_prefix = "/src", deps = [ ":accessors", ":context", @@ -62,7 +62,7 @@ cc_library( "accessors/accessors.h", ], copts = COPTS, - include_prefix = "google/protobuf/compiler/rust", + strip_include_prefix = "/src", deps = [ ":context", ":naming", @@ -78,7 +78,7 @@ cc_library( srcs = ["context.cc"], hdrs = ["context.h"], copts = COPTS, - include_prefix = "google/protobuf/compiler/rust", + strip_include_prefix = "/src", deps = [ "//src/google/protobuf/compiler:code_generator", "//src/google/protobuf/io:printer", @@ -96,7 +96,7 @@ cc_library( srcs = ["naming.cc"], hdrs = ["naming.h"], copts = COPTS, - include_prefix = "google/protobuf/compiler/rust", + strip_include_prefix = "/src", deps = [ ":context", "//src/google/protobuf:protobuf_nowkt", @@ -110,7 +110,7 @@ cc_library( srcs = ["oneof.cc"], hdrs = ["oneof.h"], copts = COPTS, - include_prefix = "google/protobuf/compiler/rust", + strip_include_prefix = "/src", deps = [ ":context", ":naming", @@ -124,7 +124,7 @@ cc_library( name = "relative_path", srcs = ["relative_path.cc"], hdrs = ["relative_path.h"], - include_prefix = "google/protobuf/compiler/rust", + strip_include_prefix = "/src", deps = [ "@com_google_absl//absl/algorithm:container", "@com_google_absl//absl/log:absl_check", diff --git a/src/google/protobuf/editions/BUILD b/src/google/protobuf/editions/BUILD index 04e1967ac1..0fa11a8453 100644 --- a/src/google/protobuf/editions/BUILD +++ b/src/google/protobuf/editions/BUILD @@ -1,4 +1,88 @@ load("@rules_cc//cc:defs.bzl", "cc_proto_library") +load("@bazel_skylib//:bzl_library.bzl", "bzl_library") +load(":defaults.bzl", "compile_edition_defaults", "embed_edition_defaults") + +bzl_library( + name = "defaults", + srcs = ["defaults.bzl"], + visibility = ["//visibility:public"], +) + +compile_edition_defaults( + name = "test_defaults_2023", + testonly = True, + srcs = ["//src/google/protobuf:unittest_features_proto"], + maximum_edition = "2023", + minimum_edition = "2023", +) + +compile_edition_defaults( + name = "test_defaults_future", + testonly = True, + srcs = ["//src/google/protobuf:unittest_features_proto"], + maximum_edition = "99997_TEST_ONLY", + minimum_edition = "2023", +) + +compile_edition_defaults( + name = "test_defaults_far_future", + testonly = True, + srcs = ["//src/google/protobuf:unittest_features_proto"], + maximum_edition = "99999_TEST_ONLY", + minimum_edition = "99997_TEST_ONLY", +) + +embed_edition_defaults( + name = "embed_test_defaults", + testonly = True, + defaults = ":test_defaults_2023", + output = "defaults_test_embedded.h", + placeholder = "DEFAULTS_VALUE", + template = "defaults_test_embedded.h.template", +) + +cc_binary( + name = "internal_defaults_escape", + srcs = ["internal_defaults_escape.cc"], + # This needs to be public for users of embed_edition_defaults. + visibility = ["//visibility:public"], + deps = [ + "//src/google/protobuf", + "@com_google_absl//absl/strings", + ], +) + +cc_library( + name = "defaults_test_embedded", + hdrs = [ + "defaults_test_embedded.h", + ], + strip_include_prefix = "/src", +) + +cc_test( + name = "defaults_test", + srcs = ["defaults_test.cc"], + data = [ + ":test_defaults_2023", + ":test_defaults_far_future", + ":test_defaults_future", + ], + deps = [ + ":defaults_test_embedded", + "//src/google/protobuf", + "//src/google/protobuf:unittest_features_cc_proto", + "//src/google/protobuf/stubs", + "//src/google/protobuf/testing", + "@bazel_tools//tools/cpp/runfiles", + "@com_google_absl//absl/memory", + "@com_google_absl//absl/status", + "@com_google_absl//absl/status:statusor", + "@com_google_absl//absl/strings", + "@com_google_absl//absl/strings:string_view", + "@com_google_googletest//:gtest_main", + ], +) proto_library( name = "test_messages_proto2_proto", diff --git a/src/google/protobuf/editions/defaults.bzl b/src/google/protobuf/editions/defaults.bzl new file mode 100644 index 0000000000..865efaf705 --- /dev/null +++ b/src/google/protobuf/editions/defaults.bzl @@ -0,0 +1,112 @@ +# Protocol Buffers - Google's data interchange format +# Copyright 2023 Google Inc. All rights reserved. +# +# Use of this source code is governed by a BSD-style +# license that can be found in the LICENSE file or at +# https://developers.google.com/open-source/licenses/bsd + +""" +Provide a rule for generating the intermediate feature set defaults used for feature resolution. + +See go/life-of-a-featureset for more information. +""" + +def _compile_edition_defaults_impl(ctx): + out_file = ctx.actions.declare_file(ctx.outputs.output.basename) + sources = [] + paths = [] + for src in ctx.attr.srcs: + sources.extend(src[ProtoInfo].transitive_sources.to_list()) + paths.extend(src[ProtoInfo].transitive_proto_path.to_list()) + + args = ctx.actions.args() + args.add("--experimental_edition_defaults_out", out_file) + + args.add("--experimental_edition_defaults_minimum", ctx.attr.minimum_edition) + args.add("--experimental_edition_defaults_maximum", ctx.attr.maximum_edition) + for p in paths: + args.add("--proto_path", p) + for source in sources: + args.add(source) + ctx.actions.run( + outputs = [out_file], + inputs = sources, + executable = ctx.executable._protoc, + arguments = [args], + progress_message = "Generating edition defaults", + ) + +compile_edition_defaults = rule( + attrs = { + "srcs": attr.label_list( + mandatory = True, + allow_rules = ["proto_library"], + providers = [ProtoInfo], + ), + "minimum_edition": attr.string(mandatory = True), + "maximum_edition": attr.string(mandatory = True), + "_protoc": attr.label( + default = "//src/google/protobuf/compiler:protoc_minimal", + executable = True, + cfg = "exec", + ), + }, + implementation = _compile_edition_defaults_impl, + outputs = { + "output": "%{name}.binpb", + }, +) + +def _embed_edition_defaults_impl(ctx): + ctx.actions.run_shell( + outputs = [ctx.outputs.output], + inputs = [ctx.file.defaults, ctx.file.template], + tools = [ctx.executable._escape], + command = """ + DEFAULTS_RAW=$({escape} < {defaults}) + # Windows requires extra escaping. + DEFAULTS_ESCAPED=$(echo $DEFAULTS_RAW | sed 's/\\\\/\\\\\\\\/g' || + echo $DEFAULTS_RAW | sed 's/\\\\\\\\/\\\\\\\\\\\\\\\\/g') + cp -f {template} {output} + # MacOS requires a backup file. + sed -i.bak \"s|{placeholder}|$DEFAULTS_ESCAPED|g\" {output} + """.format( + escape = ctx.executable._escape.path, + defaults = ctx.file.defaults.path, + template = ctx.file.template.path, + output = ctx.outputs.output.path, + placeholder = ctx.attr.placeholder, + ), + ) + +embed_edition_defaults = rule( + doc = "genrule to embed edition defaults binary data into a template file using octal C-style escaping.", + attrs = { + "defaults": attr.label( + mandatory = True, + allow_single_file = True, + allow_rules = ["compile_edition_defaults"], + providers = [ProtoInfo], + doc = "The compile_edition_defaults rule to embed", + ), + "output": attr.output( + mandatory = True, + doc = "The name of the output file", + ), + "template": attr.label( + mandatory = True, + allow_single_file = True, + doc = "The template to use for generating the output file", + ), + "placeholder": attr.string( + mandatory = True, + doc = "The placeholder to replace with a serialized string in the template", + ), + "_escape": attr.label( + default = "//src/google/protobuf/editions:internal_defaults_escape", + executable = True, + cfg = "exec", + ), + }, + implementation = _embed_edition_defaults_impl, +) diff --git a/src/google/protobuf/editions/defaults_test.cc b/src/google/protobuf/editions/defaults_test.cc new file mode 100644 index 0000000000..24c66ec6e9 --- /dev/null +++ b/src/google/protobuf/editions/defaults_test.cc @@ -0,0 +1,145 @@ +#include + +#include "tools/cpp/runfiles/runfiles.h" +#include "google/protobuf/testing/file.h" +#include "google/protobuf/testing/file.h" +#include "google/protobuf/descriptor.pb.h" +#include +#include +#include "absl/memory/memory.h" +#include "absl/status/status.h" +#include "absl/status/statusor.h" +#include "absl/strings/str_cat.h" +#include "absl/strings/string_view.h" +#include "google/protobuf/editions/defaults_test_embedded.h" +#include "google/protobuf/unittest_features.pb.h" +#include "google/protobuf/stubs/status_macros.h" + +// Must be included last. +#include "google/protobuf/port_def.inc" + +#define ASSERT_OK(x) ASSERT_TRUE(x.ok()) << x.status().message(); + +namespace google { +namespace protobuf { +namespace { + +absl::StatusOr ReadDefaults(absl::string_view name) { + auto runfiles = absl::WrapUnique(bazel::tools::cpp::runfiles::Runfiles::CreateForTest()); + std::string file = runfiles->Rlocation(absl::StrCat( + "com_google_protobuf/src/google/protobuf/editions/", + name, ".binpb")); + std::string data; + RETURN_IF_ERROR(File::GetContents(file, &data, true)); + FeatureSetDefaults defaults; + if (!defaults.ParseFromString(data)) { + return absl::InternalError("Could not parse edition defaults!"); + } + return defaults; +} + +TEST(DefaultsTest, Check2023) { + auto defaults = ReadDefaults("test_defaults_2023"); + ASSERT_OK(defaults); + ASSERT_EQ(defaults->defaults().size(), 3); + ASSERT_EQ(defaults->minimum_edition(), EDITION_2023); + ASSERT_EQ(defaults->maximum_edition(), EDITION_2023); + + EXPECT_EQ(defaults->defaults()[0].edition(), EDITION_PROTO2); + EXPECT_EQ(defaults->defaults()[1].edition(), EDITION_PROTO3); + EXPECT_EQ(defaults->defaults()[2].edition(), EDITION_2023); + EXPECT_EQ(defaults->defaults()[2].features().field_presence(), + FeatureSet::EXPLICIT); + EXPECT_EQ(defaults->defaults()[2] + .features() + .GetExtension(pb::test) + .int_file_feature(), + 1); +} + +TEST(DefaultsTest, CheckFuture) { + auto defaults = ReadDefaults("test_defaults_future"); + ASSERT_OK(defaults); + ASSERT_EQ(defaults->defaults().size(), 4); + ASSERT_EQ(defaults->minimum_edition(), EDITION_2023); + ASSERT_EQ(defaults->maximum_edition(), EDITION_99997_TEST_ONLY); + + EXPECT_EQ(defaults->defaults()[0].edition(), EDITION_PROTO2); + EXPECT_EQ(defaults->defaults()[1].edition(), EDITION_PROTO3); + EXPECT_EQ(defaults->defaults()[2].edition(), EDITION_2023); + EXPECT_EQ(defaults->defaults()[2].features().field_presence(), + FeatureSet::EXPLICIT); + EXPECT_EQ(defaults->defaults()[2] + .features() + .GetExtension(pb::test) + .int_file_feature(), + 1); + EXPECT_EQ(defaults->defaults()[3].edition(), EDITION_99997_TEST_ONLY); + EXPECT_EQ(defaults->defaults()[3].features().field_presence(), + FeatureSet::EXPLICIT); + EXPECT_EQ(defaults->defaults()[3] + .features() + .GetExtension(pb::test) + .int_file_feature(), + 2); +} + +TEST(DefaultsTest, CheckFarFuture) { + auto defaults = ReadDefaults("test_defaults_far_future"); + ASSERT_OK(defaults); + ASSERT_EQ(defaults->defaults().size(), 5); + ASSERT_EQ(defaults->minimum_edition(), EDITION_99997_TEST_ONLY); + ASSERT_EQ(defaults->maximum_edition(), EDITION_99999_TEST_ONLY); + + EXPECT_EQ(defaults->defaults()[0].edition(), EDITION_PROTO2); + EXPECT_EQ(defaults->defaults()[1].edition(), EDITION_PROTO3); + EXPECT_EQ(defaults->defaults()[2].edition(), EDITION_2023); + EXPECT_EQ(defaults->defaults()[2].features().field_presence(), + FeatureSet::EXPLICIT); + EXPECT_EQ(defaults->defaults()[2] + .features() + .GetExtension(pb::test) + .int_file_feature(), + 1); + EXPECT_EQ(defaults->defaults()[3].edition(), EDITION_99997_TEST_ONLY); + EXPECT_EQ(defaults->defaults()[3].features().field_presence(), + FeatureSet::EXPLICIT); + EXPECT_EQ(defaults->defaults()[3] + .features() + .GetExtension(pb::test) + .int_file_feature(), + 2); + EXPECT_EQ(defaults->defaults()[4].edition(), EDITION_99998_TEST_ONLY); + EXPECT_EQ(defaults->defaults()[4].features().field_presence(), + FeatureSet::EXPLICIT); + EXPECT_EQ(defaults->defaults()[4] + .features() + .GetExtension(pb::test) + .int_file_feature(), + 3); +} + +TEST(DefaultsTest, Embedded) { + FeatureSetDefaults defaults; + ASSERT_TRUE(defaults.ParseFromArray(DEFAULTS_TEST_EMBEDDED, + sizeof(DEFAULTS_TEST_EMBEDDED) - 1)) + << "Could not parse embedded data"; + ASSERT_EQ(defaults.defaults().size(), 3); + ASSERT_EQ(defaults.minimum_edition(), EDITION_2023); + ASSERT_EQ(defaults.maximum_edition(), EDITION_2023); + + EXPECT_EQ(defaults.defaults()[0].edition(), EDITION_PROTO2); + EXPECT_EQ(defaults.defaults()[1].edition(), EDITION_PROTO3); + EXPECT_EQ(defaults.defaults()[2].edition(), EDITION_2023); + EXPECT_EQ(defaults.defaults()[2].features().field_presence(), + FeatureSet::EXPLICIT); + EXPECT_EQ(defaults.defaults()[2] + .features() + .GetExtension(pb::test) + .int_file_feature(), + 1); +} + +} // namespace +} // namespace protobuf +} // namespace google diff --git a/src/google/protobuf/editions/internal_defaults_escape.cc b/src/google/protobuf/editions/internal_defaults_escape.cc new file mode 100644 index 0000000000..4c1aa469ec --- /dev/null +++ b/src/google/protobuf/editions/internal_defaults_escape.cc @@ -0,0 +1,35 @@ +#include +#include + +#ifdef _WIN32 +#include +#else +#include +#endif + +#include "google/protobuf/descriptor.pb.h" +#include "absl/strings/escaping.h" + +#if defined(_WIN32) +#include "google/protobuf/io/io_win32.h" + +// DO NOT include , instead create functions in io_win32.{h,cc} and import +// them like we do below. +using google::protobuf::io::win32::setmode; +#endif + +int main(int argc, char *argv[]) { +#ifdef _WIN32 + setmode(STDIN_FILENO, _O_BINARY); + setmode(STDOUT_FILENO, _O_BINARY); +#endif + google::protobuf::FeatureSetDefaults defaults; + if (!defaults.ParseFromFileDescriptor(STDIN_FILENO)) { + std::cerr << argv[0] << ": unable to parse edition defaults." << std::endl; + return 1; + } + std::string output; + defaults.SerializeToString(&output); + std::cout << absl::CEscape(output); + return 0; +} diff --git a/src/google/protobuf/io/BUILD.bazel b/src/google/protobuf/io/BUILD.bazel index 0578742d62..a5c44e2aad 100644 --- a/src/google/protobuf/io/BUILD.bazel +++ b/src/google/protobuf/io/BUILD.bazel @@ -23,7 +23,7 @@ cc_library( "zero_copy_stream_impl_lite.h", ], copts = COPTS, - include_prefix = "google/protobuf/io", + strip_include_prefix = "/src", deps = [ ":io_win32", "//src/google/protobuf:arena", @@ -39,7 +39,7 @@ cc_library( testonly = 1, hdrs = ["test_zero_copy_stream.h"], copts = COPTS, - include_prefix = "google/protobuf/io", + strip_include_prefix = "/src", deps = [ ":io", "//src/google/protobuf/stubs", @@ -90,7 +90,7 @@ cc_library( srcs = ["printer.cc"], hdrs = ["printer.h"], copts = COPTS, - include_prefix = "google/protobuf/io", + strip_include_prefix = "/src", deps = [ ":zero_copy_sink", "//src/google/protobuf/stubs", @@ -119,7 +119,7 @@ cc_library( "tokenizer.h", ], copts = COPTS, - include_prefix = "google/protobuf/io", + strip_include_prefix = "/src", deps = [ ":io", "//src/google/protobuf/stubs", @@ -134,7 +134,7 @@ cc_library( srcs = ["gzip_stream.cc"], hdrs = ["gzip_stream.h"], copts = COPTS, - include_prefix = "google/protobuf/io", + strip_include_prefix = "/src", deps = [ ":io", "//src/google/protobuf/stubs", @@ -151,7 +151,7 @@ cc_library( srcs = ["io_win32.cc"], hdrs = ["io_win32.h"], copts = COPTS, - include_prefix = "google/protobuf/io", + strip_include_prefix = "/src", visibility = [ "//pkg:__pkg__", "//src/google/protobuf/compiler:__pkg__", diff --git a/src/google/protobuf/stubs/BUILD.bazel b/src/google/protobuf/stubs/BUILD.bazel index 740e43e815..f89f34a004 100644 --- a/src/google/protobuf/stubs/BUILD.bazel +++ b/src/google/protobuf/stubs/BUILD.bazel @@ -22,8 +22,8 @@ cc_library( "status_macros.h", ], copts = COPTS, - include_prefix = "google/protobuf/stubs", linkopts = LINK_OPTS, + strip_include_prefix = "/src", deps = [ "//src/google/protobuf:port_def", "@com_google_absl//absl/log:absl_log", @@ -40,7 +40,7 @@ cc_library( hdrs = [ ], copts = COPTS, - include_prefix = "google/protobuf/stubs", + strip_include_prefix = "/src", textual_hdrs = [ "callback.h", "common.h", diff --git a/src/google/protobuf/testing/BUILD.bazel b/src/google/protobuf/testing/BUILD.bazel index 572c1f9f46..ab3e979d91 100644 --- a/src/google/protobuf/testing/BUILD.bazel +++ b/src/google/protobuf/testing/BUILD.bazel @@ -19,8 +19,8 @@ cc_library( "googletest.h", ], copts = COPTS, - include_prefix = "google/protobuf/testing", linkopts = LINK_OPTS, + strip_include_prefix = "/src", deps = [ "//:protobuf_lite", # for ShutdownProtobufLibrary "//src/google/protobuf/io",