deps: load cc symbols from @rules_cc (#1852)

Adds dependency on rules_cc 0.0.9 for both bzlmod and workspace

This elevates rules_cc from a dev dependency to a full dependency of
rules_python.

Work towards incompatible_stop_exporting_language_modules, see
https://github.com/bazelbuild/bazel/issues/19455
diff --git a/.gitignore b/.gitignore
index 6da16fe..863b0e9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -43,6 +43,9 @@
 *.swp
 *.swo
 
+# CLion
+.clwb
+
 # Python cache
 **/__pycache__/
 
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2c2b388..b481832 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -73,6 +73,7 @@
   the whl and sdist files will be written to the lock file. Controlling whether
   the downloading of metadata is done in parallel can be done using
   `parallel_download` attribute.
+* (deps): `rules_python` depends now on `rules_cc` 0.0.9
 
 [0.XX.0]: https://github.com/bazelbuild/rules_python/releases/tag/0.XX.0
 [python_default_visibility]: gazelle/README.md#directive-python_default_visibility
diff --git a/MODULE.bazel b/MODULE.bazel
index c7d5e23..2c325a6 100644
--- a/MODULE.bazel
+++ b/MODULE.bazel
@@ -6,6 +6,7 @@
 
 bazel_dep(name = "bazel_features", version = "1.9.1")
 bazel_dep(name = "bazel_skylib", version = "1.3.0")
+bazel_dep(name = "rules_cc", version = "0.0.9")
 bazel_dep(name = "platforms", version = "0.0.4")
 
 # Those are loaded only when using py_proto_library
@@ -71,7 +72,6 @@
 bazel_dep(name = "stardoc", version = "0.6.2", dev_dependency = True, repo_name = "io_bazel_stardoc")
 bazel_dep(name = "rules_bazel_integration_test", version = "0.20.0", dev_dependency = True)
 bazel_dep(name = "rules_testing", version = "0.6.0", dev_dependency = True)
-bazel_dep(name = "rules_cc", version = "0.0.9", dev_dependency = True)
 
 # Extra gazelle plugin deps so that WORKSPACE.bzlmod can continue including it for e2e tests.
 # We use `WORKSPACE.bzlmod` because it is impossible to have dev-only local overrides.
diff --git a/internal_deps.bzl b/internal_deps.bzl
index a8bfd47..8818751 100644
--- a/internal_deps.bzl
+++ b/internal_deps.bzl
@@ -217,3 +217,10 @@
         strip_prefix = "bazel_features-1.9.1",
         url = "https://github.com/bazel-contrib/bazel_features/releases/download/v1.9.1/bazel_features-v1.9.1.tar.gz",
     )
+
+    http_archive(
+        name = "rules_cc",
+        sha256 = "2037875b9a4456dce4a79d112a8ae885bbc4aad968e6587dca6e64f3a0900cdf",
+        strip_prefix = "rules_cc-0.0.9",
+        urls = ["https://github.com/bazelbuild/rules_cc/releases/download/0.0.9/rules_cc-0.0.9.tar.gz"],
+    )
diff --git a/python/private/BUILD.bazel b/python/private/BUILD.bazel
index b105c47..f1928e2 100644
--- a/python/private/BUILD.bazel
+++ b/python/private/BUILD.bazel
@@ -143,6 +143,7 @@
     ],
     deps = [
         ":py_cc_toolchain_info_bzl",
+        ":rules_cc_srcs_bzl",
         ":util_bzl",
     ],
 )
@@ -293,6 +294,13 @@
     ],
 )
 
+# @rules_cc does not offer a bzl_library target for @rules_cc//cc:defs.bzl
+bzl_library(
+    name = "rules_cc_srcs_bzl",
+    srcs = ["@rules_cc//cc:bzl_srcs"],
+    deps = [":bazel_tools_bzl"],
+)
+
 # Needed to define bzl_library targets for docgen. (We don't define the
 # bzl_library target here because it'd give our users a transitive dependency
 # on Skylib.)
diff --git a/python/private/common/BUILD.bazel b/python/private/common/BUILD.bazel
index 4d329bb..2f0683b 100644
--- a/python/private/common/BUILD.bazel
+++ b/python/private/common/BUILD.bazel
@@ -21,6 +21,7 @@
 bzl_library(
     name = "attributes_bazel_bzl",
     srcs = ["attributes_bazel.bzl"],
+    deps = ["//python/private:rules_cc_srcs_bzl"],
 )
 
 bzl_library(
@@ -61,6 +62,7 @@
         ":py_internal_bzl",
         ":semantics_bzl",
         "//python/private:reexports_bzl",
+        "//python/private:rules_cc_srcs_bzl",
     ],
 )
 
@@ -74,6 +76,7 @@
     srcs = ["providers.bzl"],
     deps = [
         ":semantics_bzl",
+        "//python/private:rules_cc_srcs_bzl",
         "//python/private:util_bzl",
     ],
 )
@@ -121,6 +124,7 @@
         ":common_bzl",
         ":providers_bzl",
         ":py_internal_bzl",
+        "//python/private:rules_cc_srcs_bzl",
         "@bazel_skylib//lib:dicts",
     ],
 )
diff --git a/python/private/common/attributes.bzl b/python/private/common/attributes.bzl
index 5ddca72..d4f8532 100644
--- a/python/private/common/attributes.bzl
+++ b/python/private/common/attributes.bzl
@@ -13,6 +13,7 @@
 # limitations under the License.
 """Attributes for Python rules."""
 
+load("@rules_cc//cc:defs.bzl", "CcInfo")
 load("//python/private:reexports.bzl", "BuiltinPyInfo")
 load(":common.bzl", "union_attrs")
 load(":providers.bzl", "PyInfo")
@@ -23,8 +24,6 @@
     "SRCS_ATTR_ALLOW_FILES",
 )
 
-# TODO: Load CcInfo from rules_cc
-_CcInfo = CcInfo
 _PackageSpecificationInfo = getattr(py_internal, "PackageSpecificationInfo", None)
 
 _STAMP_VALUES = [-1, 0, 1]
@@ -166,7 +165,7 @@
         "deps": attr.label_list(
             providers = [
                 [PyInfo],
-                [_CcInfo],
+                [CcInfo],
                 [BuiltinPyInfo],
             ],
             # TODO(b/228692666): Google-specific; remove these allowances once
diff --git a/python/private/common/common_bazel.bzl b/python/private/common/common_bazel.bzl
index 7277337..a037213 100644
--- a/python/private/common/common_bazel.bzl
+++ b/python/private/common/common_bazel.bzl
@@ -14,16 +14,11 @@
 """Common functions that are specific to Bazel rule implementation"""
 
 load("@bazel_skylib//lib:paths.bzl", "paths")
+load("@rules_cc//cc:defs.bzl", "CcInfo", "cc_common")
 load(":common.bzl", "is_bool")
 load(":providers.bzl", "PyCcLinkParamsProvider")
 load(":py_internal.bzl", "py_internal")
 
-# TODO: Load cc_common from rules_cc
-_cc_common = cc_common
-
-# TODO: Load CcInfo from rules_cc
-_CcInfo = CcInfo
-
 _py_builtins = py_internal
 
 def collect_cc_info(ctx, extra_deps = []):
@@ -42,13 +37,13 @@
         deps.extend(extra_deps)
     cc_infos = []
     for dep in deps:
-        if _CcInfo in dep:
-            cc_infos.append(dep[_CcInfo])
+        if CcInfo in dep:
+            cc_infos.append(dep[CcInfo])
 
         if PyCcLinkParamsProvider in dep:
             cc_infos.append(dep[PyCcLinkParamsProvider].cc_info)
 
-    return _cc_common.merge_cc_infos(cc_infos = cc_infos)
+    return cc_common.merge_cc_infos(cc_infos = cc_infos)
 
 def maybe_precompile(ctx, srcs):
     """Computes all the outputs (maybe precompiled) from the input srcs.
diff --git a/python/private/common/providers.bzl b/python/private/common/providers.bzl
index f36a2d1..0b43413 100644
--- a/python/private/common/providers.bzl
+++ b/python/private/common/providers.bzl
@@ -13,11 +13,9 @@
 # limitations under the License.
 """Providers for Python rules."""
 
+load("@rules_cc//cc:defs.bzl", "CcInfo")
 load("//python/private:util.bzl", "IS_BAZEL_6_OR_HIGHER")
 
-# TODO: load CcInfo from rules_cc
-_CcInfo = CcInfo
-
 DEFAULT_STUB_SHEBANG = "#!/usr/bin/env python3"
 
 DEFAULT_BOOTSTRAP_TEMPLATE = Label("//python/private:python_bootstrap_template.txt")
@@ -241,7 +239,7 @@
 
 def _PyCcLinkParamsProvider_init(cc_info):
     return {
-        "cc_info": _CcInfo(linking_context = cc_info.linking_context),
+        "cc_info": CcInfo(linking_context = cc_info.linking_context),
     }
 
 # buildifier: disable=name-conventions
diff --git a/python/private/common/py_executable.bzl b/python/private/common/py_executable.bzl
index df73927..0360893 100644
--- a/python/private/common/py_executable.bzl
+++ b/python/private/common/py_executable.bzl
@@ -14,6 +14,7 @@
 """Common functionality between test/binary executables."""
 
 load("@bazel_skylib//lib:dicts.bzl", "dicts")
+load("@rules_cc//cc:defs.bzl", "cc_common")
 load("//python/private:reexports.bzl", "BuiltinPyRuntimeInfo")
 load(
     ":attributes.bzl",
@@ -53,9 +54,6 @@
     "PY_RUNTIME_ATTR_NAME",
 )
 
-# TODO: Load cc_common from rules_cc
-_cc_common = cc_common
-
 _py_builtins = py_internal
 
 # Bazel 5.4 doesn't have config_common.toolchain_type
@@ -559,10 +557,10 @@
     linkstamps = py_internal.linking_context_linkstamps(cc_info.linking_context)
 
     partially_disabled_thin_lto = (
-        _cc_common.is_enabled(
+        cc_common.is_enabled(
             feature_name = "thin_lto_linkstatic_tests_use_shared_nonlto_backends",
             feature_configuration = feature_configuration,
-        ) and not _cc_common.is_enabled(
+        ) and not cc_common.is_enabled(
             feature_name = "thin_lto_all_linkstatic_use_shared_nonlto_backends",
             feature_configuration = feature_configuration,
         )
@@ -876,7 +874,7 @@
     requested_features.extend(ctx.features)
     if "legacy_whole_archive" not in ctx.disabled_features:
         requested_features.append("legacy_whole_archive")
-    feature_configuration = _cc_common.configure_features(
+    feature_configuration = cc_common.configure_features(
         ctx = ctx,
         cc_toolchain = cc_toolchain,
         requested_features = requested_features,
diff --git a/python/private/current_py_cc_headers.bzl b/python/private/current_py_cc_headers.bzl
index be7f8f8..e72199e 100644
--- a/python/private/current_py_cc_headers.bzl
+++ b/python/private/current_py_cc_headers.bzl
@@ -14,6 +14,8 @@
 
 """Implementation of current_py_cc_headers rule."""
 
+load("@rules_cc//cc:defs.bzl", "CcInfo")
+
 def _current_py_cc_headers_impl(ctx):
     py_cc_toolchain = ctx.toolchains["//python/cc:toolchain_type"].py_cc_toolchain
     return py_cc_toolchain.headers.providers_map.values()
diff --git a/python/private/current_py_cc_libs.bzl b/python/private/current_py_cc_libs.bzl
index 863e59a..d66c401 100644
--- a/python/private/current_py_cc_libs.bzl
+++ b/python/private/current_py_cc_libs.bzl
@@ -14,6 +14,8 @@
 
 """Implementation of current_py_cc_libs rule."""
 
+load("@rules_cc//cc:defs.bzl", "CcInfo")
+
 def _current_py_cc_libs_impl(ctx):
     py_cc_toolchain = ctx.toolchains["//python/cc:toolchain_type"].py_cc_toolchain
     return py_cc_toolchain.libs.providers_map.values()
diff --git a/python/private/py_cc_toolchain_rule.bzl b/python/private/py_cc_toolchain_rule.bzl
index abb3fb6..5d3debb 100644
--- a/python/private/py_cc_toolchain_rule.bzl
+++ b/python/private/py_cc_toolchain_rule.bzl
@@ -18,6 +18,7 @@
 https://github.com/bazelbuild/rules_python/issues/824 is considered done.
 """
 
+load("@rules_cc//cc:defs.bzl", "CcInfo")
 load(":py_cc_toolchain_info.bzl", "PyCcToolchainInfo")
 
 def _py_cc_toolchain_impl(ctx):
diff --git a/python/repositories.bzl b/python/repositories.bzl
index aab68eb..f77d302 100644
--- a/python/repositories.bzl
+++ b/python/repositories.bzl
@@ -62,6 +62,12 @@
             "https://github.com/bazelbuild/bazel-skylib/releases/download/1.3.0/bazel-skylib-1.3.0.tar.gz",
         ],
     )
+    http_archive(
+        name = "rules_cc",
+        urls = ["https://github.com/bazelbuild/rules_cc/releases/download/0.0.9/rules_cc-0.0.9.tar.gz"],
+        sha256 = "2037875b9a4456dce4a79d112a8ae885bbc4aad968e6587dca6e64f3a0900cdf",
+        strip_prefix = "rules_cc-0.0.9",
+    )
     pip_install_dependencies()
 
 ########
diff --git a/tests/cc/current_py_cc_headers/current_py_cc_headers_tests.bzl b/tests/cc/current_py_cc_headers/current_py_cc_headers_tests.bzl
index 931a9c1..9aeec38 100644
--- a/tests/cc/current_py_cc_headers/current_py_cc_headers_tests.bzl
+++ b/tests/cc/current_py_cc_headers/current_py_cc_headers_tests.bzl
@@ -14,6 +14,7 @@
 
 """Tests for current_py_cc_headers."""
 
+load("@rules_cc//cc:defs.bzl", "CcInfo")
 load("@rules_testing//lib:analysis_test.bzl", "analysis_test", "test_suite")
 load("@rules_testing//lib:truth.bzl", "matching")
 load("//tests:cc_info_subject.bzl", "cc_info_subject")
diff --git a/tests/cc/current_py_cc_libs/current_py_cc_libs_tests.bzl b/tests/cc/current_py_cc_libs/current_py_cc_libs_tests.bzl
index 5699b75..44615ee 100644
--- a/tests/cc/current_py_cc_libs/current_py_cc_libs_tests.bzl
+++ b/tests/cc/current_py_cc_libs/current_py_cc_libs_tests.bzl
@@ -14,6 +14,7 @@
 
 """Tests for current_py_cc_libs."""
 
+load("@rules_cc//cc:defs.bzl", "CcInfo")
 load("@rules_testing//lib:analysis_test.bzl", "analysis_test", "test_suite")
 load("@rules_testing//lib:truth.bzl", "matching")
 load("//tests:cc_info_subject.bzl", "cc_info_subject")
diff --git a/tests/cc/fake_cc_toolchain_config.bzl b/tests/cc/fake_cc_toolchain_config.bzl
index b3214a6..a2ad615 100644
--- a/tests/cc/fake_cc_toolchain_config.bzl
+++ b/tests/cc/fake_cc_toolchain_config.bzl
@@ -14,6 +14,8 @@
 
 """Fake for providing CcToolchainConfigInfo."""
 
+load("@rules_cc//cc:defs.bzl", "cc_common")
+
 def _impl(ctx):
     return cc_common.create_cc_toolchain_config_info(
         ctx = ctx,