pass androidmk variables via CcUnstrippedInfo provider

Bug: 265758350
Change-Id: I9eedded292eafba65d92fd0888c1dcf0b2c0e6db
diff --git a/rules/abi/abi_dump.bzl b/rules/abi/abi_dump.bzl
index 7cc9774..55c4dd2 100644
--- a/rules/abi/abi_dump.bzl
+++ b/rules/abi/abi_dump.bzl
@@ -83,7 +83,7 @@
 
 abi_dump_aspect = aspect(
     implementation = _abi_dump_aspect_impl,
-    attr_aspects = ["static_deps"],
+    attr_aspects = ["static_deps", "whole_archive_deps"],
     attrs = {
         "_skip_abi_checks": attr.label(
             default = "//build/bazel/flags/cc/abi:skip_abi_checks",
diff --git a/rules/apex/apex_available.bzl b/rules/apex/apex_available.bzl
index 0c6937e..56b1225 100644
--- a/rules/apex/apex_available.bzl
+++ b/rules/apex/apex_available.bzl
@@ -84,6 +84,17 @@
     # All good!
     return True
 
+_IGNORED_ATTRS = [
+    "certificate",
+    "key",
+    "android_manifest",
+    "applicable_licenses",
+    "androidmk_static_deps",
+    "androidmk_whole_archive_deps",
+    "androidmk_dynamic_deps",
+    "androidmk_deps",
+]
+
 def _apex_available_aspect_impl(target, ctx):
     apex_available_tags = [
         t.removeprefix("apex_available=")
@@ -108,7 +119,7 @@
             transitive_unvalidated_targets.append(info.transitive_unvalidated_targets)
             if attr in CC_ATTR_ASPECTS:
                 transitive_invalid_targets.append(info.transitive_invalid_targets)
-            if attr not in ["certificate", "key", "android_manifest", "applicable_licenses"]:
+            if attr not in _IGNORED_ATTRS:
                 if info.platform_available != None:
                     platform_available = platform_available and info.platform_available
 
diff --git a/rules/apex/apex_deps_validation.bzl b/rules/apex/apex_deps_validation.bzl
index 7d47555..aef853c 100644
--- a/rules/apex/apex_deps_validation.bzl
+++ b/rules/apex/apex_deps_validation.bzl
@@ -19,7 +19,7 @@
 load(":apex_available.bzl", "ApexAvailableInfo")
 load(":apex_key.bzl", "ApexKeyInfo")
 load(":cc.bzl", "get_min_sdk_version")
-load("//build/bazel/rules:common.bzl", "get_dep_targets")
+load("//build/bazel/rules:common.bzl", "get_dep_targets", "strip_bp2build_label_suffix")
 load("//build/bazel/rules/android:android_app_certificate.bzl", "AndroidAppCertificateInfo")
 
 ApexDepsInfo = provider(
@@ -61,6 +61,12 @@
     ApexKeyInfo,
     ProtoInfo,
 ]
+_IGNORED_ATTRS = [
+    "androidmk_static_deps",
+    "androidmk_whole_archive_deps",
+    "androidmk_dynamic_deps",
+    "androidmk_deps",
+]
 
 def _should_skip_apex_dep(target, ctx):
     # Ignore Bazel-specific targets like platform/os/arch constraints,
@@ -76,7 +82,9 @@
 
 def _apex_dep_validation_aspect_impl(target, ctx):
     transitive_deps = []
-    for _, attr_deps in get_dep_targets(ctx.rule.attr, predicate = lambda target: ApexDepsInfo in target).items():
+    for attr, attr_deps in get_dep_targets(ctx.rule.attr, predicate = lambda target: ApexDepsInfo in target).items():
+        if attr in _IGNORED_ATTRS:
+            continue
         for dep in attr_deps:
             transitive_deps.append(dep[ApexDepsInfo].transitive_deps)
 
@@ -147,18 +155,6 @@
     provides = [ApexDepsInfo],
 )
 
-_BP2BUILD_LABEL_SUFFIXES = [
-    # cc rules
-    "_bp2build_cc_library_static",
-    "_cc_proto_lite",
-    "_aidl_code_gen",
-]
-
-def _strip_bp2build_label_suffix(name):
-    for suffix in _BP2BUILD_LABEL_SUFFIXES:
-        name = name.removesuffix(suffix)
-    return name
-
 def _min_sdk_version_string(version):
     if version.apex_inherit:
         return "apex_inherit"
@@ -168,7 +164,7 @@
 
 def _apex_dep_to_string(apex_dep_info):
     return "{name}(minSdkVersion:{min_sdk_version})".format(
-        name = _strip_bp2build_label_suffix(apex_dep_info.label.name),
+        name = strip_bp2build_label_suffix(apex_dep_info.label.name),
         min_sdk_version = _min_sdk_version_string(apex_dep_info.min_sdk_version),
     )
 
diff --git a/rules/apex/cc.bzl b/rules/apex/cc.bzl
index 5137eca..817f7eb 100644
--- a/rules/apex/cc.bzl
+++ b/rules/apex/cc.bzl
@@ -209,6 +209,7 @@
     "src",
     "runtime_deps",
     "static_deps",
+    "whole_archive_deps",
 ]
 
 # This aspect is intended to be applied on a apex.native_shared_libs attribute
diff --git a/rules/cc/BUILD.bazel b/rules/cc/BUILD.bazel
index fa29e25..f9b9faa 100644
--- a/rules/cc/BUILD.bazel
+++ b/rules/cc/BUILD.bazel
@@ -15,6 +15,7 @@
 
 load(":cc_aidl_library_test.bzl", "cc_aidl_library_test_suite")
 load(":cc_binary_test.bzl", "cc_binary_test_suite")
+load(":cc_test_test.bzl", "cc_test_test_suite")
 load(":cc_hidl_library_test.bzl", "cc_hidl_library_test_suite")
 load(":cc_library_common_test.bzl", "cc_library_common_test_suites")
 load(":cc_library_shared_test.bzl", "cc_library_shared_test_suite")
@@ -55,6 +56,8 @@
 
 cc_binary_test_suite(name = "cc_binary_tests")
 
+cc_test_test_suite(name = "cc_test_tests")
+
 cc_hidl_library_test_suite(name = "cc_hidl_library_tests")
 
 cc_library_common_test_suites("cc_library_common_tests")
diff --git a/rules/cc/cc_binary.bzl b/rules/cc/cc_binary.bzl
index eef0a5b..9f5a684 100644
--- a/rules/cc/cc_binary.bzl
+++ b/rules/cc/cc_binary.bzl
@@ -201,5 +201,6 @@
         tags = tags,
         unstripped = unstripped_name,
         testonly = generate_cc_test,
+        androidmk_deps = [root_name],
         **strip
     )
diff --git a/rules/cc/cc_binary_test.bzl b/rules/cc/cc_binary_test.bzl
index 81b9590..6802059 100644
--- a/rules/cc/cc_binary_test.bzl
+++ b/rules/cc/cc_binary_test.bzl
@@ -16,6 +16,9 @@
 
 load("@bazel_skylib//lib:unittest.bzl", "analysistest", "asserts")
 load(":cc_binary.bzl", "cc_binary")
+load(":cc_library_shared.bzl", "cc_library_shared")
+load(":cc_library_static.bzl", "cc_library_static")
+load(":cc_library_common_test.bzl", "target_provides_androidmk_info_test")
 
 def strip_test_assert_flags(env, strip_action, strip_flags):
     # Extract these flags from strip_action (for example):
@@ -245,6 +248,59 @@
     )
     return test_name
 
+def _cc_binary_provides_androidmk_info():
+    name = "cc_binary_provides_androidmk_info"
+    dep_name = name + "_static_dep"
+    whole_archive_dep_name = name + "_whole_archive_dep"
+    dynamic_dep_name = name + "_dynamic_dep"
+    test_name = name + "_test"
+
+    cc_library_static(
+        name = dep_name,
+        srcs = ["foo.c"],
+        tags = ["manual"],
+    )
+    cc_library_static(
+        name = whole_archive_dep_name,
+        srcs = ["foo.c"],
+        tags = ["manual"],
+    )
+    cc_library_shared(
+        name = dynamic_dep_name,
+        srcs = ["foo.c"],
+        tags = ["manual"],
+    )
+    cc_binary(
+        name = name,
+        srcs = ["foo.cc"],
+        deps = [dep_name],
+        whole_archive_deps = [whole_archive_dep_name],
+        dynamic_deps = [dynamic_dep_name],
+        tags = ["manual"],
+    )
+    android_test_name = test_name + "_android"
+    linux_test_name = test_name + "_linux"
+    target_provides_androidmk_info_test(
+        name = android_test_name,
+        target_under_test = name,
+        expected_static_libs = [dep_name, "libc++demangle", "libunwind"],
+        expected_whole_static_libs = [whole_archive_dep_name],
+        expected_shared_libs = [dynamic_dep_name, "libc++", "libc", "libdl", "libm"],
+        target_compatible_with = ["//build/bazel/platforms/os:android"],
+    )
+    target_provides_androidmk_info_test(
+        name = linux_test_name,
+        target_under_test = name,
+        expected_static_libs = [dep_name],
+        expected_whole_static_libs = [whole_archive_dep_name],
+        expected_shared_libs = [dynamic_dep_name, "libc++"],
+        target_compatible_with = ["//build/bazel/platforms/os:linux"],
+    )
+    return [
+        android_test_name,
+        linux_test_name,
+    ]
+
 def cc_binary_test_suite(name):
     native.test_suite(
         name = name,
@@ -256,5 +312,5 @@
             _cc_binary_strip_all(),
             _cc_binary_suffix(),
             _cc_binary_empty_suffix(),
-        ],
+        ] + _cc_binary_provides_androidmk_info(),
     )
diff --git a/rules/cc/cc_library_common.bzl b/rules/cc/cc_library_common.bzl
index 5e42514..8632171 100644
--- a/rules/cc/cc_library_common.bzl
+++ b/rules/cc/cc_library_common.bzl
@@ -24,6 +24,7 @@
 load("@soong_injection//api_levels:api_levels.bzl", "api_levels")
 load("@soong_injection//product_config:product_variables.bzl", "product_vars")
 load("@soong_injection//android:constants.bzl", android_constants = "constants")
+load("//build/bazel/rules:common.bzl", "strip_bp2build_label_suffix")
 
 _bionic_targets = ["//bionic/libc", "//bionic/libdl", "//bionic/libm"]
 _static_bionic_targets = ["//bionic/libc:libc_bp2build_cc_library_static", "//bionic/libdl:libdl_bp2build_cc_library_static", "//bionic/libm:libm_bp2build_cc_library_static"]
@@ -376,3 +377,36 @@
 
 def is_bootstrap_lib(name):
     return name in _bootstrap_libs
+
+CcAndroidMkInfo = provider(
+    "Provides information to be passed to AndroidMk in Soong",
+    fields = {
+        "local_static_libs": "list of target names passed to LOCAL_STATIC_LIBRARIES AndroidMk variable",
+        "local_whole_static_libs": "list of target names passed to LOCAL_WHOLE_STATIC_LIBRARIES AndroidMk variable",
+        "local_shared_libs": "list of target names passed to LOCAL_SHARED_LIBRARIES AndroidMk variable",
+    },
+)
+
+def create_cc_androidmk_provider(*, static_deps, whole_archive_deps, dynamic_deps):
+    # Since this information is provided to Soong for mixed builds,
+    # we are just taking the Soong module name rather than the Bazel
+    # label.
+    # TODO(b/266197834) consider moving this logic to the mixed builds
+    # handler in Soong
+    local_static_libs = [
+        strip_bp2build_label_suffix(d.label.name)
+        for d in static_deps
+    ]
+    local_whole_static_libs = [
+        strip_bp2build_label_suffix(d.label.name)
+        for d in whole_archive_deps
+    ]
+    local_shared_libs = [
+        strip_bp2build_label_suffix(d.label.name)
+        for d in dynamic_deps
+    ]
+    return CcAndroidMkInfo(
+        local_static_libs = local_static_libs,
+        local_whole_static_libs = local_whole_static_libs,
+        local_shared_libs = local_shared_libs,
+    )
diff --git a/rules/cc/cc_library_common_test.bzl b/rules/cc/cc_library_common_test.bzl
index c7199f2..a2cf816 100644
--- a/rules/cc/cc_library_common_test.bzl
+++ b/rules/cc/cc_library_common_test.bzl
@@ -14,8 +14,11 @@
 limitations under the License.
 """
 
-load("@bazel_skylib//lib:unittest.bzl", "asserts", "unittest")
-load(":cc_library_common.bzl", "is_external_directory")
+load("@bazel_skylib//lib:unittest.bzl", "analysistest", "unittest", skylib_asserts = "asserts")
+load("//build/bazel/rules/test_common:asserts.bzl", roboleaf_asserts = "asserts")
+load(":cc_library_common.bzl", "CcAndroidMkInfo", "is_external_directory")
+
+asserts = skylib_asserts + roboleaf_asserts
 
 def _is_external_directory_test(ctx):
     env = unittest.begin(ctx)
@@ -105,6 +108,50 @@
         )
     return test_cases.keys()
 
+def _target_provides_androidmk_info_test_impl(ctx):
+    env = analysistest.begin(ctx)
+
+    target_under_test = analysistest.target_under_test(env)
+    mkinfo = target_under_test[CcAndroidMkInfo]
+    asserts.list_equals(
+        env,
+        ctx.attr.expected_static_libs,
+        mkinfo.local_static_libs,
+        "expected static_libs to be %s, but got %s" % (
+            ctx.attr.expected_static_libs,
+            mkinfo.local_static_libs,
+        ),
+    )
+    asserts.list_equals(
+        env,
+        ctx.attr.expected_whole_static_libs,
+        mkinfo.local_whole_static_libs,
+        "expected whole_static_libs to be %s, but got %s" % (
+            ctx.attr.expected_static_libs,
+            mkinfo.local_static_libs,
+        ),
+    )
+    asserts.list_equals(
+        env,
+        ctx.attr.expected_shared_libs,
+        mkinfo.local_shared_libs,
+        "expected shared_libs to be %s, but got %s" % (
+            ctx.attr.expected_static_libs,
+            mkinfo.local_static_libs,
+        ),
+    )
+
+    return analysistest.end(env)
+
+target_provides_androidmk_info_test = analysistest.make(
+    _target_provides_androidmk_info_test_impl,
+    attrs = {
+        "expected_static_libs": attr.string_list(),
+        "expected_whole_static_libs": attr.string_list(),
+        "expected_shared_libs": attr.string_list(),
+    },
+)
+
 def cc_library_common_test_suites(name):
     native.test_suite(
         name = name,
diff --git a/rules/cc/cc_library_shared.bzl b/rules/cc/cc_library_shared.bzl
index a4faa5a..5c6a7bb 100644
--- a/rules/cc/cc_library_shared.bzl
+++ b/rules/cc/cc_library_shared.bzl
@@ -16,9 +16,10 @@
 
 load(
     ":cc_library_common.bzl",
+    "CcAndroidMkInfo",
     "add_lists_defaulting_to_none",
+    "create_cc_androidmk_provider",
     "disable_crt_link",
-    "get_sanitizer_lib_info",
     "parse_sdk_version",
     "sanitizer_deps",
     "system_dynamic_deps_defaults",
@@ -332,6 +333,9 @@
         shared = stripped_name,
         shared_debuginfo = unstripped_name,
         deps = [shared_root_name],
+        androidmk_static_deps = deps + stl_info.static_deps,
+        androidmk_whole_archive_deps = whole_archive_deps,
+        androidmk_dynamic_deps = dynamic_deps + stl_info.shared_deps,
         features = features,
         table_of_contents = toc_name,
         output_file = soname,
@@ -460,6 +464,11 @@
         CcSharedLibraryOutputInfo(output_file = ctx.outputs.output_file),
         CcUnstrippedInfo(unstripped = shared_debuginfo[0]),
         ctx.attr.abi_dump[AbiDiffInfo],
+        create_cc_androidmk_provider(
+            static_deps = ctx.attr.androidmk_static_deps,
+            whole_archive_deps = ctx.attr.androidmk_whole_archive_deps,
+            dynamic_deps = ctx.attr.androidmk_dynamic_deps,
+        ),
     ]
 
 _cc_library_shared_proxy = rule(
@@ -492,7 +501,23 @@
         "_allowlist_function_transition": attr.label(
             default = "@bazel_tools//tools/allowlists/function_transition_allowlist",
         ),
+        "androidmk_static_deps": attr.label_list(
+            providers = [CcInfo],
+            doc = "All the whole archive deps of the lib. This is used to propagate" +
+                  " information to AndroidMk about LOCAL_STATIC_LIBRARIES.",
+        ),
+        "androidmk_whole_archive_deps": attr.label_list(
+            providers = [CcInfo],
+            doc = "All the whole archive deps of the lib. This is used to propagate" +
+                  " information to AndroidMk about LOCAL_WHOLE_STATIC_LIBRARIES.",
+        ),
+        "androidmk_dynamic_deps": attr.label_list(
+            providers = [CcInfo],
+            doc = "All the dynamic deps of the lib. This is used to propagate" +
+                  " information to AndroidMk about LOCAL_SHARED_LIBRARIES.",
+        ),
     },
+    provides = [CcAndroidMkInfo],
     fragments = ["cpp"],
     toolchains = ["@bazel_tools//tools/cpp:toolchain_type"],
 )
diff --git a/rules/cc/cc_library_shared_test.bzl b/rules/cc/cc_library_shared_test.bzl
index 80e60f7..b24a6f6 100644
--- a/rules/cc/cc_library_shared_test.bzl
+++ b/rules/cc/cc_library_shared_test.bzl
@@ -17,6 +17,7 @@
 load("//build/bazel/rules/cc:cc_library_shared.bzl", "cc_library_shared")
 load("//build/bazel/rules/cc:cc_library_static.bzl", "cc_library_static")
 load("//build/bazel/rules/cc:cc_stub_library.bzl", "cc_stub_suite")
+load(":cc_library_common_test.bzl", "target_provides_androidmk_info_test")
 load("//build/bazel/rules/test_common:paths.bzl", "get_package_dir_based_path")
 load("//build/bazel/rules/test_common:flags.bzl", "action_flags_present_only_for_mnemonic_test")
 load("@bazel_skylib//lib:unittest.bzl", "analysistest", "asserts")
@@ -750,6 +751,59 @@
     )
     return test_name
 
+def _cc_library_shared_provides_androidmk_info():
+    name = "cc_library_shared_provides_androidmk_info"
+    dep_name = name + "_static_dep"
+    whole_archive_dep_name = name + "_whole_archive_dep"
+    dynamic_dep_name = name + "_dynamic_dep"
+    test_name = name + "_test"
+
+    cc_library_static(
+        name = dep_name,
+        srcs = ["foo.c"],
+        tags = ["manual"],
+    )
+    cc_library_static(
+        name = whole_archive_dep_name,
+        srcs = ["foo.c"],
+        tags = ["manual"],
+    )
+    cc_library_shared(
+        name = dynamic_dep_name,
+        srcs = ["foo.c"],
+        tags = ["manual"],
+    )
+    cc_library_shared(
+        name = name,
+        srcs = ["foo.cc"],
+        deps = [dep_name],
+        whole_archive_deps = [whole_archive_dep_name],
+        dynamic_deps = [dynamic_dep_name],
+        tags = ["manual"],
+    )
+    android_test_name = test_name + "_android"
+    linux_test_name = test_name + "_linux"
+    target_provides_androidmk_info_test(
+        name = android_test_name,
+        target_under_test = name,
+        expected_static_libs = [dep_name, "libc++demangle"],
+        expected_whole_static_libs = [whole_archive_dep_name],
+        expected_shared_libs = [dynamic_dep_name, "libc++"],
+        target_compatible_with = ["//build/bazel/platforms/os:android"],
+    )
+    target_provides_androidmk_info_test(
+        name = linux_test_name,
+        target_under_test = name,
+        expected_static_libs = [dep_name],
+        expected_whole_static_libs = [whole_archive_dep_name],
+        expected_shared_libs = [dynamic_dep_name, "libc++"],
+        target_compatible_with = ["//build/bazel/platforms/os:linux"],
+    )
+    return [
+        android_test_name,
+        linux_test_name,
+    ]
+
 def cc_library_shared_test_suite(name):
     native.genrule(name = "cc_library_shared_hdr", cmd = "null", outs = ["cc_shared_f.h"], tags = ["manual"])
 
@@ -770,5 +824,5 @@
             _cc_library_with_fdo_profile_link_flags(),
             _cc_library_disable_fdo_optimization_if_coverage_is_enabled_test(),
             _cc_library_set_defines_for_stubs(),
-        ],
+        ] + _cc_library_shared_provides_androidmk_info(),
     )
diff --git a/rules/cc/cc_library_static.bzl b/rules/cc/cc_library_static.bzl
index 55803a0..84d1008 100644
--- a/rules/cc/cc_library_static.bzl
+++ b/rules/cc/cc_library_static.bzl
@@ -18,7 +18,9 @@
     ":cc_library_common.bzl",
     "CPP_EXTENSIONS",
     "C_EXTENSIONS",
+    "CcAndroidMkInfo",
     "check_absolute_include_dirs_disabled",
+    "create_cc_androidmk_provider",
     "create_ccinfo_for_includes",
     "get_non_header_srcs",
     "get_sanitizer_lib_info",
@@ -31,6 +33,7 @@
 load("@bazel_skylib//rules:common_settings.bzl", "BuildSettingInfo")
 load("@bazel_tools//tools/build_defs/cc:action_names.bzl", "ACTION_NAMES")
 load("@bazel_tools//tools/cpp:toolchain_utils.bzl", "find_cpp_toolchain")
+load("@soong_injection//api_levels:api_levels.bzl", "api_levels")
 
 CcStaticLibraryInfo = provider(fields = ["root_static_archive", "objects"])
 
@@ -221,9 +224,14 @@
         target_compatible_with = target_compatible_with,
         alwayslink = alwayslink,
         static_deps = deps + implementation_deps + whole_archive_deps + implementation_whole_archive_deps,
+        androidmk_static_deps = deps + implementation_deps + stl_info.static_deps,
+        androidmk_whole_archive_deps = whole_archive_deps + implementation_whole_archive_deps,
+        androidmk_dynamic_deps = dynamic_deps + implementation_dynamic_deps + system_dynamic_deps + stl_info.shared_deps,
         exports = exports_name,
         tags = tags,
         features = toolchain_features,
+
+        # clang-tidy attributes
         tidy = tidy,
         srcs_cpp = srcs,
         srcs_c = srcs_c,
@@ -430,6 +438,11 @@
         CcInfo(compilation_context = combined_info.compilation_context, linking_context = linking_context),
         CcStaticLibraryInfo(root_static_archive = output_file, objects = objects_to_link),
         get_sanitizer_lib_info(ctx.attr.features, ctx.attr.deps + ctx.attr.additional_sanitizer_deps),
+        create_cc_androidmk_provider(
+            static_deps = ctx.attr.androidmk_static_deps,
+            whole_archive_deps = ctx.attr.androidmk_whole_archive_deps,
+            dynamic_deps = ctx.attr.androidmk_dynamic_deps,
+        ),
     ]
     providers.extend(_generate_tidy_actions(ctx))
 
@@ -457,15 +470,36 @@
             providers = [CcInfo],
             doc = "Deps that should be installed along with this target. Read by the apex cc aspect.",
         ),
-        # All the static deps of the lib, this is used by abi_dump_aspect to travel along the
-        # static_deps edges to create abi dump files.
-        "static_deps": attr.label_list(providers = [CcInfo]),
-        # The exported includes used by abi_dump_aspect to retrieve and use as the inputs
-        # of abi dumper binary.
+        "static_deps": attr.label_list(
+            providers = [CcInfo],
+            doc = "All the static deps of the lib. This is used by" +
+                  " abi_dump_aspect to travel along the static_deps edges" +
+                  " to create abi dump files.",
+        ),
+        "androidmk_static_deps": attr.label_list(
+            providers = [CcInfo],
+            doc = "All the whole archive deps of the lib. This is used to propagate" +
+                  " information to AndroidMk about LOCAL_STATIC_LIBRARIES.",
+        ),
+        "androidmk_whole_archive_deps": attr.label_list(
+            providers = [CcInfo],
+            doc = "All the whole archive deps of the lib. This is used to propagate" +
+                  " information to AndroidMk about LOCAL_WHOLE_STATIC_LIBRARIES.",
+        ),
+        "androidmk_dynamic_deps": attr.label_list(
+            providers = [CcInfo],
+            doc = "All the dynamic deps of the lib. This is used to propagate" +
+                  " information to AndroidMk about LOCAL_SHARED_LIBRARIES." +
+                  " The attribute name is prefixed with androidmk to avoid" +
+                  " collision with the dynamic_deps attribute used in APEX" +
+                  " aspects' propagation.",
+        ),
         "exports": attr.label(providers = [CcInfo]),
         "_cc_toolchain": attr.label(
             default = Label("@local_config_cc//:toolchain"),
             providers = [cc_common.CcToolchainInfo],
+            doc = "The exported includes used by abi_dump_aspect to retrieve" +
+                  " and use as the inputs of abi dumper binary.",
         ),
         "alwayslink": attr.bool(
             doc = """At link time, whether these libraries should be wrapped in
@@ -525,7 +559,7 @@
         ),
     },
     toolchains = ["@bazel_tools//tools/cpp:toolchain_type"],
-    provides = [CcInfo],
+    provides = [CcInfo, CcAndroidMkInfo],
     fragments = ["cpp"],
 )
 
diff --git a/rules/cc/cc_library_static_test.bzl b/rules/cc/cc_library_static_test.bzl
index adb9190..d57aedf 100644
--- a/rules/cc/cc_library_static_test.bzl
+++ b/rules/cc/cc_library_static_test.bzl
@@ -21,6 +21,7 @@
 load("//build/bazel/rules/cc:cc_library_headers.bzl", "cc_library_headers")
 load("//build/bazel/rules/cc:cc_prebuilt_library_static.bzl", "cc_prebuilt_library_static")
 load("//build/bazel/rules/cc:cc_binary.bzl", "cc_binary")
+load(":cc_library_common_test.bzl", "target_provides_androidmk_info_test")
 load("//build/bazel/rules/test_common:paths.bzl", "get_output_and_package_dir_based_path", "get_package_dir_based_path")
 load("//build/bazel/rules/test_common:rules.bzl", "expect_failure_test")
 
@@ -435,6 +436,59 @@
 
     return test_name
 
+def _cc_library_static_provides_androidmk_info():
+    name = "cc_library_static_provides_androidmk_info"
+    dep_name = name + "_static_dep"
+    whole_archive_dep_name = name + "_whole_archive_dep"
+    dynamic_dep_name = name + "_dynamic_dep"
+    test_name = name + "_test"
+
+    cc_library_static(
+        name = dep_name,
+        srcs = ["foo.c"],
+        tags = ["manual"],
+    )
+    cc_library_static(
+        name = whole_archive_dep_name,
+        srcs = ["foo.c"],
+        tags = ["manual"],
+    )
+    cc_library_shared(
+        name = dynamic_dep_name,
+        srcs = ["foo.c"],
+        tags = ["manual"],
+    )
+    cc_library_static(
+        name = name,
+        srcs = ["foo.cc"],
+        deps = [dep_name],
+        whole_archive_deps = [whole_archive_dep_name],
+        dynamic_deps = [dynamic_dep_name],
+        tags = ["manual"],
+    )
+    android_test_name = test_name + "_android"
+    linux_test_name = test_name + "_linux"
+    target_provides_androidmk_info_test(
+        name = android_test_name,
+        target_under_test = name,
+        expected_static_libs = [dep_name, "libc++_static", "libc++demangle"],
+        expected_whole_static_libs = [whole_archive_dep_name],
+        expected_shared_libs = [dynamic_dep_name, "libc", "libdl", "libm"],
+        target_compatible_with = ["//build/bazel/platforms/os:android"],
+    )
+    target_provides_androidmk_info_test(
+        name = linux_test_name,
+        target_under_test = name,
+        expected_static_libs = [dep_name, "libc++_static"],
+        expected_whole_static_libs = [whole_archive_dep_name],
+        expected_shared_libs = [dynamic_dep_name],
+        target_compatible_with = ["//build/bazel/platforms/os:linux"],
+    )
+    return [
+        android_test_name,
+        linux_test_name,
+    ]
+
 def cc_library_static_test_suite(name):
     native.genrule(name = "hdr", cmd = "null", outs = ["f.h"], tags = ["manual"])
 
@@ -449,5 +503,8 @@
             _cc_library_static_does_not_propagate_implementation_dynamic_deps(),
             _cc_library_static_links_against_prebuilt_library(),
             _cc_library_static_whole_archive_deps_objects_precede_target_objects(),
-        ] + _cc_rules_do_not_allow_absolute_includes(),
+        ] + (
+            _cc_rules_do_not_allow_absolute_includes() +
+            _cc_library_static_provides_androidmk_info()
+        ),
     )
diff --git a/rules/cc/cc_test_test.bzl b/rules/cc/cc_test_test.bzl
new file mode 100644
index 0000000..fea3500
--- /dev/null
+++ b/rules/cc/cc_test_test.bzl
@@ -0,0 +1,79 @@
+"""
+Copyright (C) 2023 The Android Open Source Project
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+"""
+
+load(":cc_test.bzl", "cc_test")
+load(":cc_library_shared.bzl", "cc_library_shared")
+load(":cc_library_static.bzl", "cc_library_static")
+load(":cc_library_common_test.bzl", "target_provides_androidmk_info_test")
+
+def _cc_test_provides_androidmk_info():
+    name = "cc_test_provides_androidmk_info"
+    dep_name = name + "_static_dep"
+    whole_archive_dep_name = name + "_whole_archive_dep"
+    dynamic_dep_name = name + "_dynamic_dep"
+    test_name = name + "_test"
+
+    cc_library_static(
+        name = dep_name,
+        srcs = ["foo.c"],
+        tags = ["manual"],
+    )
+    cc_library_static(
+        name = whole_archive_dep_name,
+        srcs = ["foo.c"],
+        tags = ["manual"],
+    )
+    cc_library_shared(
+        name = dynamic_dep_name,
+        srcs = ["foo.c"],
+        tags = ["manual"],
+    )
+    cc_test(
+        name = name,
+        srcs = ["foo.cc"],
+        deps = [dep_name],
+        whole_archive_deps = [whole_archive_dep_name],
+        dynamic_deps = [dynamic_dep_name],
+        tags = ["manual"],
+    )
+    android_test_name = test_name + "_android"
+    linux_test_name = test_name + "_linux"
+    target_provides_androidmk_info_test(
+        name = android_test_name,
+        target_under_test = name,
+        expected_static_libs = [dep_name, "libgtest_main", "libgtest", "libc++demangle", "libunwind"],
+        expected_whole_static_libs = [whole_archive_dep_name],
+        expected_shared_libs = [dynamic_dep_name, "libc++", "libc", "libdl", "libm"],
+        target_compatible_with = ["//build/bazel/platforms/os:android"],
+    )
+    target_provides_androidmk_info_test(
+        name = linux_test_name,
+        target_under_test = name,
+        expected_static_libs = [dep_name, "libgtest_main", "libgtest"],
+        expected_whole_static_libs = [whole_archive_dep_name],
+        expected_shared_libs = [dynamic_dep_name, "libc++"],
+        target_compatible_with = ["//build/bazel/platforms/os:linux"],
+    )
+    return [
+        android_test_name,
+        linux_test_name,
+    ]
+
+def cc_test_test_suite(name):
+    native.test_suite(
+        name = name,
+        tests = _cc_test_provides_androidmk_info(),
+    )
diff --git a/rules/cc/stripped_cc_common.bzl b/rules/cc/stripped_cc_common.bzl
index 9cfd67c..3ed14ca 100644
--- a/rules/cc/stripped_cc_common.bzl
+++ b/rules/cc/stripped_cc_common.bzl
@@ -17,6 +17,7 @@
 """A macro to handle shared library stripping."""
 
 load("@bazel_tools//tools/cpp:toolchain_utils.bzl", "find_cpp_toolchain")
+load(":cc_library_common.bzl", "CcAndroidMkInfo")
 
 CcUnstrippedInfo = provider(
     "Provides unstripped binary/shared library",
@@ -188,7 +189,12 @@
         ctx.attr.src[DebugPackageInfo],
         ctx.attr.src[OutputGroupInfo],
         StrippedCcBinaryInfo(),  # a marker for dependents
-        CcUnstrippedInfo(unstripped = ctx.attr.unstripped),
+        CcUnstrippedInfo(
+            unstripped = ctx.attr.unstripped,
+        ),
+    ] + [
+        d[CcAndroidMkInfo]
+        for d in ctx.attr.androidmk_deps
     ]
 
     out_file = stripped_impl(ctx, suffix = ctx.attr.suffix)
@@ -209,6 +215,9 @@
             providers = [CcInfo],
             doc = "Deps that should be installed along with this target. Read by the apex cc aspect.",
         ),
+        androidmk_deps = attr.label_list(
+            providers = [CcAndroidMkInfo],
+        ),
         suffix = attr.string(),
         unstripped = attr.label(
             mandatory = True,
diff --git a/rules/common.bzl b/rules/common.bzl
index 17f3cf6..99cdb67 100644
--- a/rules/common.bzl
+++ b/rules/common.bzl
@@ -40,3 +40,15 @@
             if type(item) == "Target" and predicate(item):
                 targets[a].append(item)
     return targets
+
+_BP2BUILD_LABEL_SUFFIXES = [
+    # cc rules
+    "_bp2build_cc_library_static",
+    "_cc_proto_lite",
+    "_aidl_code_gen",
+]
+
+def strip_bp2build_label_suffix(name):
+    for suffix in _BP2BUILD_LABEL_SUFFIXES:
+        name = name.removesuffix(suffix)
+    return name
diff --git a/rules/test_common/asserts.bzl b/rules/test_common/asserts.bzl
new file mode 100644
index 0000000..d34276a
--- /dev/null
+++ b/rules/test_common/asserts.bzl
@@ -0,0 +1,36 @@
+"""
+Copyright (C) 2022 The Android Open Source Project
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+"""
+
+load("@bazel_skylib//lib:unittest.bzl", skylib_asserts = "asserts")
+
+def _list_equals(env, l1, l2, msg = None):
+    skylib_asserts.equals(
+        env,
+        len(l1),
+        len(l2),
+        msg,
+    )
+    for i in range(len(l1)):
+        skylib_asserts.equals(
+            env,
+            l1[i],
+            l2[i],
+            msg,
+        )
+
+asserts = struct(
+    list_equals = _list_equals,
+)