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
diff --git a/BUILD.bazel b/BUILD.bazel
index 23efee4..5951297 100644
--- a/BUILD.bazel
+++ b/BUILD.bazel
@@ -224,7 +224,6 @@
 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 489ca65..044af48 100644
--- a/cmake/tests.cmake
+++ b/cmake/tests.cmake
@@ -62,6 +62,7 @@
   ${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 8961ca6..f85e88b 100644
--- a/src/google/protobuf/BUILD.bazel
+++ b/src/google/protobuf/BUILD.bazel
@@ -162,6 +162,7 @@
     copts = COPTS,
     includes = ["wkt"],
     linkopts = LINK_OPTS,
+    strip_include_prefix = "/src",
     visibility = ["//pkg:__pkg__"],
     deps = [":protobuf_nowkt"],
 )
@@ -198,7 +199,7 @@
         "port_def.inc",
         "port_undef.inc",
     ],
-    include_prefix = "google/protobuf",
+    strip_include_prefix = "/src",
     visibility = [
         "//:__subpackages__",
         "//src/google/protobuf:__subpackages__",
@@ -212,7 +213,7 @@
     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 @@
     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(
     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(
     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(
     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 @@
         "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 @@
     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 @@
     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 @@
             "-Wno-error",
         ],
     }),
-    include_prefix = "google/protobuf",
     linkopts = LINK_OPTS,
+    strip_include_prefix = "/src",
     visibility = [
         "//:__pkg__",
         "//pkg:__pkg__",
@@ -506,8 +507,8 @@
         "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_library(
     name = "protobuf",
     copts = COPTS,
-    include_prefix = "google/protobuf",
     linkopts = LINK_OPTS,
+    strip_include_prefix = "/src",
     visibility = [
         "//:__pkg__",
         "//pkg:__pkg__",
@@ -573,14 +574,15 @@
         "**/*.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 @@
     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",
@@ -750,6 +752,22 @@
 )
 
 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"],
     strip_import_prefix = "/src",
diff --git a/src/google/protobuf/compiler/BUILD.bazel b/src/google/protobuf/compiler/BUILD.bazel
index 273dae0..f98c317 100644
--- a/src/google/protobuf/compiler/BUILD.bazel
+++ b/src/google/protobuf/compiler/BUILD.bazel
@@ -42,7 +42,7 @@
         "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 @@
         "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 @@
         "versions_suffix.h",
     ],
     copts = COPTS,
-    include_prefix = "google/protobuf/compiler",
+    strip_include_prefix = "/src",
     visibility = [
         "//src/google/protobuf/compiler:__subpackages__",
     ],
@@ -107,7 +107,7 @@
         "zip_writer.h",
     ],
     copts = COPTS,
-    include_prefix = "google/protobuf/compiler",
+    strip_include_prefix = "/src",
     visibility = ["//visibility:public"],
     deps = [
         ":code_generator",
@@ -133,6 +133,7 @@
         "main.cc",
     ],
     copts = COPTS,
+    strip_include_prefix = "/src",
     visibility = [
         "//:__pkg__",
         "//pkg:__pkg__",
@@ -154,6 +155,23 @@
     ],
 )
 
+# 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 @@
     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 470181f..e6671c0 100644
--- a/src/google/protobuf/compiler/allowlists/BUILD.bazel
+++ b/src/google/protobuf/compiler/allowlists/BUILD.bazel
@@ -7,7 +7,7 @@
     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 @@
     ],
     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 8ca37b4..fb168b0 100644
--- a/src/google/protobuf/compiler/cpp/BUILD.bazel
+++ b/src/google/protobuf/compiler/cpp/BUILD.bazel
@@ -11,7 +11,7 @@
     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 @@
         "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 @@
         "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 414dd0f..a182bc2 100644
--- a/src/google/protobuf/compiler/csharp/BUILD.bazel
+++ b/src/google/protobuf/compiler/csharp/BUILD.bazel
@@ -11,7 +11,7 @@
     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 @@
         "//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 a9461d0..8ca67c1 100644
--- a/src/google/protobuf/compiler/java/BUILD.bazel
+++ b/src/google/protobuf/compiler/java/BUILD.bazel
@@ -10,7 +10,7 @@
     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 @@
         "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 @@
     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 @@
         "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 0000000..83a44e8
--- /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 5ab3381..a3a6fcf 100644
--- a/src/google/protobuf/compiler/objectivec/BUILD.bazel
+++ b/src/google/protobuf/compiler/objectivec/BUILD.bazel
@@ -10,7 +10,7 @@
     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 @@
         "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 @@
     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 @@
         "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 f814a03..2a9746d 100644
--- a/src/google/protobuf/compiler/php/BUILD.bazel
+++ b/src/google/protobuf/compiler/php/BUILD.bazel
@@ -11,7 +11,7 @@
     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 @@
     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 64b5808..e9501f2 100644
--- a/src/google/protobuf/compiler/python/BUILD.bazel
+++ b/src/google/protobuf/compiler/python/BUILD.bazel
@@ -19,7 +19,7 @@
         "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 d01764c..62afc3c 100644
--- a/src/google/protobuf/compiler/ruby/BUILD.bazel
+++ b/src/google/protobuf/compiler/ruby/BUILD.bazel
@@ -11,7 +11,7 @@
     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 1429b9b..9939c2c 100644
--- a/src/google/protobuf/compiler/rust/BUILD.bazel
+++ b/src/google/protobuf/compiler/rust/BUILD.bazel
@@ -10,7 +10,7 @@
     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 @@
     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 @@
         "accessors/accessors.h",
     ],
     copts = COPTS,
-    include_prefix = "google/protobuf/compiler/rust",
+    strip_include_prefix = "/src",
     deps = [
         ":context",
         ":naming",
@@ -78,7 +78,7 @@
     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 @@
     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 @@
     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 @@
     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 04e1967..0fa11a8 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 0000000..865efaf
--- /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 0000000..24c66ec
--- /dev/null
+++ b/src/google/protobuf/editions/defaults_test.cc
@@ -0,0 +1,145 @@
+#include <string>
+
+#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 <gmock/gmock.h>
+#include <gtest/gtest.h>
+#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<FeatureSetDefaults> 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 0000000..4c1aa46
--- /dev/null
+++ b/src/google/protobuf/editions/internal_defaults_escape.cc
@@ -0,0 +1,35 @@
+#include <iostream>
+#include <string>
+
+#ifdef _WIN32
+#include <fcntl.h>
+#else
+#include <unistd.h>
+#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 <io.h>, 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 0578742..a5c44e2 100644
--- a/src/google/protobuf/io/BUILD.bazel
+++ b/src/google/protobuf/io/BUILD.bazel
@@ -23,7 +23,7 @@
         "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 @@
     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 @@
     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 @@
         "tokenizer.h",
     ],
     copts = COPTS,
-    include_prefix = "google/protobuf/io",
+    strip_include_prefix = "/src",
     deps = [
         ":io",
         "//src/google/protobuf/stubs",
@@ -134,7 +134,7 @@
     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 @@
     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 740e43e..f89f34a 100644
--- a/src/google/protobuf/stubs/BUILD.bazel
+++ b/src/google/protobuf/stubs/BUILD.bazel
@@ -22,8 +22,8 @@
         "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 @@
     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 572c1f9..ab3e979 100644
--- a/src/google/protobuf/testing/BUILD.bazel
+++ b/src/google/protobuf/testing/BUILD.bazel
@@ -19,8 +19,8 @@
         "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",