Update upb's _message target and Copybara config to use OSS rules_python py_extension

Updates the Copybara configuration for upb to load py_extension from @rules_python instead of the local path. Changes the _message target to use the new py_extension.

PiperOrigin-RevId: 963822572
diff --git a/.github/workflows/test_python.yml b/.github/workflows/test_python.yml
index 1470a65..b3e09fe 100644
--- a/.github/workflows/test_python.yml
+++ b/.github/workflows/test_python.yml
@@ -67,7 +67,12 @@
           image: ${{ matrix.image || format('us-docker.pkg.dev/protobuf-build/containers/test/linux/python:9.2.0-{0}-5bb1a8fdfc30f8c21c1b38cf053d2db9fca865a7 ', matrix.version) }}
           credentials: ${{ secrets.GAR_SERVICE_ACCOUNT }}
           bazel-cache: python_linux/${{ matrix.type }}_${{ matrix.version }}
-          bazel: test ${{ matrix.targets }} ${{ matrix.flags }} ${{ matrix.nobzlmod && '--noenable_bzlmod' || '' }} --test_env=KOKORO_PYTHON_VERSION
+          bazel: >-
+            test ${{ matrix.targets }} ${{ matrix.flags }}
+            ${{ matrix.nobzlmod && '--noenable_bzlmod' || '' }}
+            ${{ matrix.version != 'aarch64' && '--//python:use_hermetic_python=true' || '' }}
+            ${{ matrix.version != 'aarch64' && format('--@rules_python//python/config_settings:python_version={0}', matrix.version) || '' }}
+            --test_env=KOKORO_PYTHON_VERSION
 
 
   macos:
diff --git a/MODULE.bazel b/MODULE.bazel
index dab3a45..1ec318c 100644
--- a/MODULE.bazel
+++ b/MODULE.bazel
@@ -37,6 +37,12 @@
 bazel_dep(name = "rules_license", version = "1.0.0")
 bazel_dep(name = "rules_pkg", version = "1.0.1")
 bazel_dep(name = "rules_python", version = "2.3.0")
+git_override(
+    module_name = "rules_python",
+    commit = "84874d514e343a32ce1c611165b1f26952dedd79",
+    remote = "https://github.com/rsartor-cmd/rules_python.git",
+)
+
 bazel_dep(name = "rules_rust", version = "0.69.0")
 
 bazel_dep(name = "rules_ruby", version = "0.20.1", dev_dependency = True)
@@ -174,6 +180,9 @@
     name = "local_toolchains",
     dev_dependency = True,
     runtimes = ["local_python3"],
+    target_settings = {
+        "local_python3": ["@//python:is_system_python"],
+    },
 )
 
 register_toolchains(
@@ -181,6 +190,16 @@
     dev_dependency = True,
 )
 
+python = use_extension("@rules_python//python/extensions:python.bzl", "python", dev_dependency = True)
+
+[
+    python.toolchain(
+        is_default = (python_version == "3.10"),
+        python_version = python_version,
+    )
+    for python_version in SUPPORTED_PYTHON_VERSIONS
+]
+
 rust = use_extension("@rules_rust//rust:extensions.bzl", "rust", dev_dependency = True)
 
 # As of October 2025, our minimum supported Rust version is 1.79. However, we
diff --git a/conformance/BUILD b/conformance/BUILD
index f94a990..ba12887 100644
--- a/conformance/BUILD
+++ b/conformance/BUILD
@@ -522,8 +522,8 @@
         "//conformance/test_protos:test_messages_edition_unstable_py_pb2",
         "//editions:test_messages_proto2_editions_py_pb2",
         "//editions:test_messages_proto3_editions_py_pb2",
-        "//python:_message",  # Make upb visible if we need it.
         "//python:conformance_test_py_proto",
+        "//python:google/_upb/_message",  # Make upb visible if we need it.
     ],
 )
 
diff --git a/examples/MODULE.bazel b/examples/MODULE.bazel
index f13e8f7..1f339e6 100644
--- a/examples/MODULE.bazel
+++ b/examples/MODULE.bazel
@@ -23,3 +23,8 @@
 bazel_dep(name = "rules_java", version = "8.6.1")
 bazel_dep(name = "rules_pkg", version = "1.0.1")
 bazel_dep(name = "rules_python", version = "2.3.0")
+git_override(
+    module_name = "rules_python",
+    commit = "84874d514e343a32ce1c611165b1f26952dedd79",
+    remote = "https://github.com/rsartor-cmd/rules_python.git",
+)
diff --git a/python/BUILD.bazel b/python/BUILD.bazel
index 4bc0695..f918658 100644
--- a/python/BUILD.bazel
+++ b/python/BUILD.bazel
@@ -6,8 +6,8 @@
 # https://developers.google.com/open-source/licenses/bsd
 
 load("@bazel_skylib//rules:common_settings.bzl", "bool_flag", "string_flag")
+load("@rules_python//python/cc:py_extension.bzl", "py_extension")
 load("//python:build_targets.bzl", "build_targets")
-load("//python:py_extension.bzl", "py_extension")
 load("//upb/bazel:copts.bzl", "UPB_DEFAULT_COPTS", "UPB_DEFAULT_FEATURES")
 
 build_targets(name = "python")
@@ -40,6 +40,26 @@
     ],
 )
 
+bool_flag(
+    name = "use_hermetic_python",
+    build_setting_default = False,
+)
+
+config_setting(
+    name = "is_hermetic_python",
+    flag_values = {":use_hermetic_python": "true"},
+    visibility = ["//visibility:public"],
+)
+
+config_setting(
+    name = "is_system_python",
+    flag_values = {
+        ":python_version": "system",
+        ":use_hermetic_python": "false",
+    },
+    visibility = ["//visibility:public"],
+)
+
 config_setting(
     name = "limited_api_3.10",
     flag_values = {
@@ -108,11 +128,15 @@
 )
 
 py_extension(
-    name = "_message",
+    name = "google/_upb/_message",
     srcs = [":message_srcs"],
     copts = UPB_DEFAULT_COPTS + select(LIMITED_API_FLAG_SELECT),
     features = UPB_DEFAULT_FEATURES,
     target_compatible_with = select(_message_target_compatible_with),
+    visibility = [
+        ":__subpackages__",
+        "//conformance:__pkg__",
+    ],
     deps = [
         ":breaking_changes",
         "//src/google/protobuf:descriptor_upb_minitable_proto",
diff --git a/python/dist/BUILD.bazel b/python/dist/BUILD.bazel
index a87dfc4..f381184 100644
--- a/python/dist/BUILD.bazel
+++ b/python/dist/BUILD.bazel
@@ -21,7 +21,7 @@
 
 py_dist_module(
     name = "message_mod",
-    extension = "//python:_message_binary",
+    extension = "//python:google/_upb/_message",
     module_name = "google._upb._message",
 )
 
diff --git a/python/dist/dist.bzl b/python/dist/dist.bzl
index e4da083..629e3bd 100644
--- a/python/dist/dist.bzl
+++ b/python/dist/dist.bzl
@@ -77,7 +77,7 @@
 #
 #   py_dist_module(
 #       name = "message_mod",
-#       extension = "//python:_message_binary",
+#       extension = "//python:google/_upb/_message",
 #       module_name = "google._upb._message",
 #   )
 #
diff --git a/python/py_extension.bzl b/python/py_extension.bzl
index 93bc28f..876869f 100644
--- a/python/py_extension.bzl
+++ b/python/py_extension.bzl
@@ -4,6 +4,7 @@
 load("@rules_cc//cc:cc_binary.bzl", "cc_binary")
 load("@rules_python//python:py_library.bzl", "py_library")
 
+# TODO: Remove this file once _message has successfully switched to OSS rules_python's py_extension.
 def py_extension(name, srcs, copts, deps = [], **kwargs):
     """Creates a C++ library to extend python
 
diff --git a/toolchain/cc_toolchain_config.bzl b/toolchain/cc_toolchain_config.bzl
index facf3d2..a893864 100644
--- a/toolchain/cc_toolchain_config.bzl
+++ b/toolchain/cc_toolchain_config.bzl
@@ -6,6 +6,7 @@
     "flag_group",
     "flag_set",
     "tool_path",
+    "variable_with_value",
     "with_feature_set",
 )
 load("@rules_cc//cc/common:cc_common.bzl", "cc_common")
@@ -176,10 +177,51 @@
         ],
     )
 
+    archiver_flags = feature(
+        name = "archiver_flags",
+        enabled = True,
+        flag_sets = [
+            flag_set(
+                actions = [ACTION_NAMES.cpp_link_static_library],
+                flag_groups = [
+                    flag_group(
+                        flags = ["rcsD"],
+                    ),
+                    flag_group(
+                        expand_if_available = "output_execpath",
+                        flags = ["%{output_execpath}"],
+                    ),
+                    flag_group(
+                        expand_if_available = "libraries_to_link",
+                        iterate_over = "libraries_to_link",
+                        flag_groups = [
+                            flag_group(
+                                expand_if_equal = variable_with_value(
+                                    "libraries_to_link.type",
+                                    "object_file",
+                                ),
+                                flags = ["%{libraries_to_link.name}"],
+                            ),
+                            flag_group(
+                                expand_if_equal = variable_with_value(
+                                    "libraries_to_link.type",
+                                    "object_file_group",
+                                ),
+                                iterate_over = "libraries_to_link.object_files",
+                                flags = ["%{libraries_to_link.object_files}"],
+                            ),
+                        ],
+                    ),
+                ],
+            ),
+        ],
+    )
+
     features = [
         linker_flags,
         compiler_flags,
         sysroot_flags,
+        archiver_flags,
         feature(name = "dbg"),
         feature(name = "opt"),
     ]
@@ -199,6 +241,13 @@
             ),
         )
 
+    if "apple" in ctx.attr.target_full_name or "osx" in ctx.attr.target_full_name or "darwin" in ctx.attr.target_full_name:
+        target_libc = "macosx"
+    elif "mingw" in ctx.attr.target_full_name:
+        target_libc = "mingw"
+    else:
+        target_libc = ctx.attr.target_cpu
+
     return cc_common.create_cc_toolchain_config_info(
         abi_libc_version = ctx.attr.abi_version,
         abi_version = ctx.attr.abi_version,
@@ -214,7 +263,7 @@
         features = features,
         host_system_name = "local",
         target_cpu = ctx.attr.target_cpu,
-        target_libc = ctx.attr.target_cpu,
+        target_libc = target_libc,
         target_system_name = ctx.attr.target_full_name,
         toolchain_identifier = ctx.attr.target_full_name,
         tool_paths = tool_paths,
diff --git a/upb/bazel/private/upb_proto_library_internal/rule.bzl b/upb/bazel/private/upb_proto_library_internal/rule.bzl
index feb2929..d712827 100644
--- a/upb/bazel/private/upb_proto_library_internal/rule.bzl
+++ b/upb/bazel/private/upb_proto_library_internal/rule.bzl
@@ -1,5 +1,8 @@
 """Internal rule implementation for upb_*_proto_library() rules."""
 
+load("@rules_cc//cc/common:cc_common.bzl", "cc_common")
+load("@rules_cc//cc/common:cc_info.bzl", "CcInfo")
+
 def _filter_none(elems):
     out = []
     for elem in elems:
@@ -32,6 +35,28 @@
         lib.pic_static_library,
         lib.dynamic_library,
     ])
+
+    linker_inputs = []
+    dep_prefix = dep.label.name + "."
+    for input in cc_info.linking_context.linker_inputs.to_list():
+        if input.owner == dep.label or (input.owner.package == dep.label.package and input.owner.name.startswith(dep_prefix)):
+            linker_inputs.append(cc_common.create_linker_input(
+                owner = ctx.label,
+                libraries = depset(input.libraries),
+                user_link_flags = depset(input.user_link_flags),
+                additional_inputs = depset(input.additional_inputs),
+            ))
+        else:
+            linker_inputs.append(input)
+
+    linking_context = cc_common.create_linking_context(
+        linker_inputs = depset(linker_inputs, order = "topological"),
+    )
+    cc_info = CcInfo(
+        compilation_context = cc_info.compilation_context,
+        linking_context = linking_context,
+    )
+
     return [
         DefaultInfo(files = depset(files + srcs.hdrs + srcs.srcs)),
         srcs,
diff --git a/upb/bazel/upb_minitable_proto_library.bzl b/upb/bazel/upb_minitable_proto_library.bzl
index 6a27082..9bd86c9 100644
--- a/upb/bazel/upb_minitable_proto_library.bzl
+++ b/upb/bazel/upb_minitable_proto_library.bzl
@@ -1,6 +1,5 @@
 """upb_minitable_proto_library() exposes upb's generated minitables (foo.upb_minitable.h)"""
 
-load("@rules_cc//cc/common:cc_common.bzl", "cc_common")
 load("@rules_cc//cc/common:cc_info.bzl", "CcInfo")
 load("//bazel/common:proto_info.bzl", "ProtoInfo")
 load("//upb/bazel:visibility.bzl", "upb_clients")
@@ -28,22 +27,15 @@
         cc_provider = UpbMinitableCcInfo,
         dep_cc_provider = None,
         file_provider = _UpbWrappedGeneratedSrcsInfo,
+        provide_cc_shared_library_hints = False,
     )
 
 def _get_upb_minitable_proto_library_aspect_provides():
-    provides = [
+    return [
         UpbMinitableCcInfo,
         _UpbWrappedGeneratedSrcsInfo,
     ]
 
-    if hasattr(cc_common, "CcSharedLibraryHintInfo"):
-        provides.append(cc_common.CcSharedLibraryHintInfo)
-    elif hasattr(cc_common, "CcSharedLibraryHintInfo_6_X_getter_do_not_use"):
-        # This branch can be deleted once 6.X is not supported by upb rules
-        provides.append(cc_common.CcSharedLibraryHintInfo_6_X_getter_do_not_use)
-
-    return provides
-
 upb_minitable_proto_library_aspect = aspect(
     attrs = {
         "_copts": attr.label(