Move tests from Bazel's CcImportBaseConfiguredTargetTest to rules_cc.
Adjusts the cc_info testing subject to inherit its meta from the original
target so we can use the "{package}" format string when examining files
contained within.
PiperOrigin-RevId: 963987087
Change-Id: I27b233e87298f291c3706c0dad0608da21f888e7
diff --git a/tests/cc/common/cc_import_configured_target_tests.bzl b/tests/cc/common/cc_import_configured_target_tests.bzl
index 1f1c49b..65cd373 100644
--- a/tests/cc/common/cc_import_configured_target_tests.bzl
+++ b/tests/cc/common/cc_import_configured_target_tests.bzl
@@ -4,8 +4,15 @@
load("@rules_testing//lib:analysis_test.bzl", "test_suite")
load("@rules_testing//lib:truth.bzl", "matching")
load("@rules_testing//lib:util.bzl", "util")
+load("//cc:cc_binary.bzl", "cc_binary")
load("//cc:cc_import.bzl", "cc_import")
+load("//cc:cc_library.bzl", "cc_library")
+load("//cc:defs.bzl", "CcInfo")
+load("//cc/common:cc_common.bzl", "cc_common")
+load("//cc/common:cc_helper.bzl", "cc_helper")
load("//tests/cc/testutil:cc_analysis_test.bzl", "cc_analysis_test")
+load("//tests/cc/testutil:cc_info_subject.bzl", "cc_info_subject")
+load("//tests/cc/testutil:link_action_subject.bzl", "link_action_subject")
def _test_data_in_runfiles(name, **kwargs):
util.helper_target(
@@ -26,10 +33,470 @@
target.runfiles().contains_predicate(matching.str_endswith("/data_file.txt"))
target.data_runfiles().contains_predicate(matching.str_endswith("/data_file.txt"))
+def _test_wrong_cc_import_definitions_fails(name, **kwargs):
+ util.helper_target(
+ cc_import,
+ name = name + "/static_so",
+ static_library = "libfoo.so",
+ )
+
+ util.helper_target(
+ cc_import,
+ name = name + "/shared_a",
+ shared_library = "libfoo.a",
+ )
+
+ util.helper_target(
+ cc_import,
+ name = name + "/dll_interface_a",
+ shared_library = "libfoo.dll",
+ interface_library = "libfoo.a",
+ )
+
+ util.helper_target(
+ cc_import,
+ name = name + "/system_shared_so",
+ shared_library = "libfoo.so",
+ system_provided = True,
+ )
+
+ util.helper_target(
+ cc_import,
+ name = name + "/nosystem_interface",
+ interface_library = "libfoo.ifso",
+ system_provided = False,
+ )
+
+ cc_analysis_test(
+ name = name,
+ impl = _test_wrong_cc_import_definitions_fails_impl,
+ targets = {
+ "static_so": name + "/static_so",
+ "shared_a": name + "/shared_a",
+ "dll_interface_a": name + "/dll_interface_a",
+ "system_shared_so": name + "/system_shared_so",
+ "nosystem_interface": name + "/nosystem_interface",
+ },
+ expect_failure = True,
+ **kwargs
+ )
+
+def _test_wrong_cc_import_definitions_fails_impl(env, targets):
+ env.expect.that_target(targets.static_so).failures().contains_predicate(
+ matching.str_matches("'*:libfoo.so' does not produce any cc_import static_library files"),
+ )
+ env.expect.that_target(targets.shared_a).failures().contains_predicate(
+ matching.str_matches("'shared_library' does not produce any cc_import shared_library files"),
+ )
+ env.expect.that_target(targets.dll_interface_a).failures().contains_predicate(
+ matching.str_matches("'*:libfoo.a' does not produce any cc_import interface_library files"),
+ )
+ env.expect.that_target(targets.system_shared_so).failures().contains_predicate(
+ matching.str_matches("'shared_library' shouldn't be specified when 'system_provided' is true"),
+ )
+ env.expect.that_target(targets.nosystem_interface).failures().contains_predicate(
+ matching.str_matches("'shared_library' should be specified when 'system_provided' is false"),
+ )
+
+def _test_runtime_only_import_on_windows(name, **kwargs):
+ util.helper_target(
+ cc_import,
+ name = name + "/foo",
+ shared_library = "libfoo.dll",
+ )
+
+ cc_analysis_test(
+ name = name,
+ impl = _test_runtime_only_import_on_windows_impl,
+ target = name + "/foo",
+ test_features = [
+ "copy_dynamic_libraries_to_binary",
+ "targets_windows",
+ ],
+ **kwargs
+ )
+
+def _test_runtime_only_import_on_windows_impl(env, target):
+ assert_cc_info = cc_info_subject.from_target(env, target)
+ assert_cc_info.linking_context().resolved_symlink_dynamic_library_files().is_empty()
+ assert_cc_info.linking_context().dynamic_library_files().contains_exactly([
+ "{package}/libfoo.dll",
+ ])
+
+ runtime_libs = cc_helper.get_dynamic_libraries_for_runtime(
+ target[CcInfo].linking_context,
+ linking_statically = False,
+ )
+ env.expect.that_collection(runtime_libs).contains_exactly_predicates([
+ matching.file_basename_equals("libfoo.dll"),
+ ])
+
+def _test_static_library(name, **kwargs):
+ util.helper_target(
+ cc_import,
+ name = name + "/foo",
+ static_library = "libfoo.a",
+ )
+
+ cc_analysis_test(
+ name = name,
+ impl = _test_static_library_impl,
+ target = name + "/foo",
+ **kwargs
+ )
+
+def _test_static_library_impl(env, target):
+ assert_cc_info = cc_info_subject.from_target(env, target)
+ assert_cc_info.linking_context().static_library_files().contains_exactly([
+ "{package}/libfoo.a",
+ ])
+
+def _test_shared_library(name, **kwargs):
+ util.helper_target(
+ cc_import,
+ name = name + "/foo",
+ shared_library = "libfoo.so",
+ )
+
+ cc_analysis_test(
+ name = name,
+ impl = _test_shared_library_impl,
+ target = name + "/foo",
+ **kwargs
+ )
+
+def _test_shared_library_impl(env, target):
+ assert_cc_info = cc_info_subject.from_target(env, target)
+ assert_cc_info.linking_context().resolved_symlink_dynamic_library_files().contains_exactly([
+ "{package}/libfoo.so",
+ ])
+ assert_cc_info.linking_context().dynamic_library_files().contains_predicate(
+ matching.file_path_matches("_solib*libfoo.so"),
+ )
+
+def _test_versioned_shared_library(name, **kwargs):
+ util.helper_target(
+ cc_import,
+ name = name + "/foo",
+ shared_library = "libfoo.so.1ab2.1_a2",
+ )
+
+ cc_analysis_test(
+ name = name,
+ impl = _test_versioned_shared_library_impl,
+ target = name + "/foo",
+ **kwargs
+ )
+
+def _test_versioned_shared_library_impl(env, target):
+ assert_cc_info = cc_info_subject.from_target(env, target)
+ assert_cc_info.linking_context().resolved_symlink_dynamic_library_files().contains_exactly([
+ "{package}/libfoo.so.1ab2.1_a2",
+ ])
+ assert_cc_info.linking_context().dynamic_library_files().contains_predicate(
+ matching.file_path_matches("_solib*libfoo.so.1ab2.1_a2"),
+ )
+
+def _test_versioned_shared_library_with_dot(name, **kwargs):
+ util.helper_target(
+ cc_import,
+ name = name + "/foo",
+ shared_library = "libfoo.qux.so.1ab2.1_a2",
+ )
+
+ cc_analysis_test(
+ name = name,
+ impl = _test_versioned_shared_library_with_dot_impl,
+ target = name + "/foo",
+ **kwargs
+ )
+
+def _test_versioned_shared_library_with_dot_impl(env, target):
+ assert_cc_info = cc_info_subject.from_target(env, target)
+ assert_cc_info.linking_context().resolved_symlink_dynamic_library_files().contains_exactly([
+ "{package}/libfoo.qux.so.1ab2.1_a2",
+ ])
+ assert_cc_info.linking_context().dynamic_library_files().contains_predicate(
+ matching.file_path_matches("_solib*libfoo.qux.so.1ab2.1_a2"),
+ )
+
+def _test_invalid_shared_library_version_fails(name, **kwargs):
+ util.helper_target(
+ cc_import,
+ name = name + "/foo",
+ shared_library = "libfoo.so.1ab2.ab",
+ )
+
+ cc_analysis_test(
+ name = name,
+ impl = _test_invalid_shared_library_version_fails_impl,
+ target = name + "/foo",
+ expect_failure = True,
+ **kwargs
+ )
+
+def _test_invalid_shared_library_version_fails_impl(env, target):
+ env.expect.that_target(target).failures().contains_predicate(
+ matching.str_matches("'shared_library' does not produce any cc_import shared_library files"),
+ )
+
+def _test_shared_library_with_no_extension_fails(name, **kwargs):
+ util.helper_target(
+ cc_import,
+ name = name + "/foo",
+ shared_library = "libfoo",
+ )
+
+ cc_analysis_test(
+ name = name,
+ impl = _test_shared_library_with_no_extension_fails_impl,
+ target = name + "/foo",
+ expect_failure = True,
+ **kwargs
+ )
+
+def _test_shared_library_with_no_extension_fails_impl(env, target):
+ env.expect.that_target(target).failures().contains_predicate(
+ matching.str_matches("'shared_library' does not produce any cc_import shared_library files"),
+ )
+
+def _test_interface_shared_library(name, **kwargs):
+ util.helper_target(
+ cc_import,
+ name = name + "/foo",
+ shared_library = "libfoo.so",
+ interface_library = "libfoo.ifso",
+ )
+
+ cc_analysis_test(
+ name = name,
+ impl = _test_interface_shared_library_impl,
+ target = name + "/foo",
+ **kwargs
+ )
+
+def _test_interface_shared_library_impl(env, target):
+ assert_cc_info = cc_info_subject.from_target(env, target)
+ assert_cc_info.linking_context().resolved_symlink_interface_library_files().contains_exactly([
+ "{package}/libfoo.ifso",
+ ])
+ assert_cc_info.linking_context().resolved_symlink_dynamic_library_files().contains_exactly([
+ "{package}/libfoo.so",
+ ])
+ assert_cc_info.linking_context().interface_library_files().contains_predicate(
+ matching.file_path_matches("_solib*libfoo.ifso"),
+ )
+ assert_cc_info.linking_context().dynamic_library_files().contains_predicate(
+ matching.file_path_matches("_solib*libfoo.so"),
+ )
+
+def _test_static_and_shared_libraries(name, **kwargs):
+ util.helper_target(
+ cc_import,
+ name = name + "/foo",
+ static_library = "libfoo.a",
+ shared_library = "libfoo.so",
+ )
+
+ cc_analysis_test(
+ name = name,
+ impl = _test_static_and_shared_libraries_impl,
+ target = name + "/foo",
+ **kwargs
+ )
+
+def _test_static_and_shared_libraries_impl(env, target):
+ assert_cc_info = cc_info_subject.from_target(env, target)
+ assert_cc_info.linking_context().static_library_files().contains_exactly([
+ "{package}/libfoo.a",
+ ])
+ assert_cc_info.linking_context().resolved_symlink_dynamic_library_files().contains_exactly([
+ "{package}/libfoo.so",
+ ])
+ assert_cc_info.linking_context().dynamic_library_files().contains_predicate(
+ matching.file_path_matches("_solib*libfoo.so"),
+ )
+
+def _test_always_link_static_library(name, **kwargs):
+ util.helper_target(
+ cc_import,
+ name = name + "/foo",
+ static_library = "libfoo.a",
+ alwayslink = True,
+ )
+
+ cc_analysis_test(
+ name = name,
+ impl = _test_always_link_static_library_impl,
+ target = name + "/foo",
+ **kwargs
+ )
+
+def _test_always_link_static_library_impl(env, target):
+ assert_library = cc_info_subject.from_target(env, target).linking_context().libraries_to_link().singleton()
+ assert_library.alwayslink().equals(True)
+
+def _test_system_provided(name, **kwargs):
+ util.helper_target(
+ cc_import,
+ name = name + "/foo",
+ interface_library = "libfoo.ifso",
+ system_provided = True,
+ )
+
+ cc_analysis_test(
+ name = name,
+ impl = _test_system_provided_impl,
+ target = name + "/foo",
+ **kwargs
+ )
+
+def _test_system_provided_impl(env, target):
+ assert_cc_info = cc_info_subject.from_target(env, target)
+ assert_cc_info.linking_context().resolved_symlink_interface_library_files().contains_exactly([
+ "{package}/libfoo.ifso",
+ ])
+ assert_cc_info.linking_context().dynamic_library_files().is_empty()
+
+def _test_providing_header_files(name, **kwargs):
+ util.helper_target(
+ cc_import,
+ name = name + "/foo",
+ static_library = "libfoo.a",
+ hdrs = ["foo.h"],
+ )
+
+ cc_analysis_test(
+ name = name,
+ impl = _test_providing_header_files_impl,
+ target = name + "/foo",
+ **kwargs
+ )
+
+def _test_providing_header_files_impl(env, target):
+ assert_cc_info = cc_info_subject.from_target(env, target)
+ assert_cc_info.compilation_context().headers().contains(
+ "{package}/foo.h",
+ )
+ assert_cc_info.compilation_context().direct_public_headers().contains_exactly_predicates([
+ matching.file_basename_equals("foo.h"),
+ ])
+
+def _test_shared_library_adds_rpath_entry(name, **kwargs):
+ util.helper_target(
+ cc_import,
+ name = name + "/foo",
+ shared_library = "libfoo.so",
+ )
+
+ util.helper_target(
+ cc_binary,
+ name = name + "/bin",
+ deps = [name + "/foo"],
+ )
+
+ cc_analysis_test(
+ name = name,
+ impl = _test_shared_library_adds_rpath_entry_impl,
+ target = name + "/bin",
+ **kwargs
+ )
+
+def _test_shared_library_adds_rpath_entry_impl(env, target):
+ assert_action = link_action_subject.from_target(env, target)
+ assert_action.argv().contains_at_least_predicates([
+ matching.equals_wrapper("-Xlinker"),
+ matching.equals_wrapper("-rpath"),
+ matching.equals_wrapper("-Xlinker"),
+ matching.str_matches("*/_solib*/*Sfoo___U*"),
+ ]).in_order()
+
+def _test_transition_impl(_settings, _attr):
+ return {"//command_line_option:copt": ["-DFLAG"]}
+
+test_transition = transition(
+ implementation = _test_transition_impl,
+ inputs = [],
+ outputs = ["//command_line_option:copt"],
+)
+
+def _apply_test_transition_impl(ctx):
+ cc_infos = [dep[CcInfo] for dep in ctx.attr.deps]
+ merged = cc_common.merge_cc_infos(cc_infos = cc_infos)
+ return [merged]
+
+apply_test_transition = rule(
+ implementation = _apply_test_transition_impl,
+ attrs = {
+ "deps": attr.label_list(cfg = test_transition),
+ },
+)
+
+def _test_shared_library_adds_rpath_entry_under_transition(name, **kwargs):
+ util.helper_target(
+ cc_import,
+ name = name + "/foo",
+ shared_library = "libfoo.so",
+ )
+
+ util.helper_target(
+ cc_library,
+ name = name + "/bar",
+ deps = [name + "/foo"],
+ )
+
+ util.helper_target(
+ apply_test_transition,
+ name = name + "/transitioned_bar",
+ deps = [name + "/bar"],
+ )
+
+ util.helper_target(
+ cc_binary,
+ name = name + "/bin",
+ deps = [name + "/transitioned_bar"],
+ )
+
+ cc_analysis_test(
+ name = name,
+ impl = _test_shared_library_adds_rpath_entry_under_transition_impl,
+ target = name + "/bin",
+ **kwargs
+ )
+
+def _test_shared_library_adds_rpath_entry_under_transition_impl(env, target):
+ assert_action = link_action_subject.from_target(env, target)
+ assert_action.argv().contains_at_least_predicates([
+ matching.equals_wrapper("-Xlinker"),
+ matching.equals_wrapper("-rpath"),
+ matching.equals_wrapper("-Xlinker"),
+ matching.str_matches("*/_solib*/*Sfoo___U*"),
+ ]).in_order()
+
def cc_import_configured_target_tests(name):
+ tests = [
+ _test_wrong_cc_import_definitions_fails,
+ _test_runtime_only_import_on_windows,
+ _test_static_library,
+ _test_shared_library,
+ _test_versioned_shared_library,
+ _test_versioned_shared_library_with_dot,
+ _test_invalid_shared_library_version_fails,
+ _test_shared_library_with_no_extension_fails,
+ _test_interface_shared_library,
+ _test_static_and_shared_libraries,
+ _test_always_link_static_library,
+ _test_system_provided,
+ _test_providing_header_files,
+ _test_shared_library_adds_rpath_entry,
+ _test_shared_library_adds_rpath_entry_under_transition,
+ ]
+ if bazel_features.cc.cc_common_is_in_rules_cc:
+ tests.extend([
+ _test_data_in_runfiles,
+ ])
+
test_suite(
name = name,
- tests = [
- _test_data_in_runfiles,
- ] if bazel_features.cc.cc_common_is_in_rules_cc else [],
+ tests = tests,
)
diff --git a/tests/cc/testutil/cc_info_subject.bzl b/tests/cc/testutil/cc_info_subject.bzl
index d7f0ed5..baf1f87 100644
--- a/tests/cc/testutil/cc_info_subject.bzl
+++ b/tests/cc/testutil/cc_info_subject.bzl
@@ -23,8 +23,9 @@
return public
def _new_cc_info_subject_from_target(env, target):
- env.expect.that_target(target).has_provider(CcInfo)
- return _new_cc_info_subject(target[CcInfo], env.expect.meta)
+ assert_target = env.expect.that_target(target)
+ assert_target.has_provider(CcInfo)
+ return _new_cc_info_subject(target[CcInfo], assert_target.meta)
def _new_cc_compilation_context_subject(cc_compilation_context, meta):
self = struct(
@@ -72,6 +73,11 @@
equals = lambda other: _cc_info_linking_context_equals(self.actual, other, self.meta),
library_files = lambda: _new_library_files_subject(self.actual, self.meta),
static_library_files = lambda: _new_static_library_files_subject(self.actual, self.meta),
+ dynamic_library_files = lambda: _new_dynamic_library_files_subject(self.actual, self.meta),
+ interface_library_files = lambda: _new_interface_library_files_subject(self.actual, self.meta),
+ resolved_symlink_dynamic_library_files = lambda: _new_resolved_symlink_dynamic_library_files_subject(self.actual, self.meta),
+ resolved_symlink_interface_library_files = lambda: _new_resolved_symlink_interface_library_files_subject(self.actual, self.meta),
+ libraries_to_link = lambda: _new_libraries_to_link_subject_from_linking_context(self.actual, self.meta),
)
return public
@@ -104,6 +110,56 @@
meta = meta.derive("static_library_files"),
)
+def _new_dynamic_library_files_subject(linking_context, meta):
+ dynamic_libraries = []
+ for linker_input in linking_context.linker_inputs.to_list():
+ for lib in linker_input.libraries:
+ if lib.dynamic_library:
+ dynamic_libraries.append(lib.dynamic_library)
+ return subjects.depset_file(
+ depset(dynamic_libraries),
+ meta = meta.derive("dynamic_library_files"),
+ )
+
+def _new_interface_library_files_subject(linking_context, meta):
+ interface_libraries = []
+ for linker_input in linking_context.linker_inputs.to_list():
+ for lib in linker_input.libraries:
+ if lib.interface_library:
+ interface_libraries.append(lib.interface_library)
+ return subjects.depset_file(
+ depset(interface_libraries),
+ meta = meta.derive("interface_library_files"),
+ )
+
+def _new_resolved_symlink_dynamic_library_files_subject(linking_context, meta):
+ libs = []
+ for linker_input in linking_context.linker_inputs.to_list():
+ for lib in linker_input.libraries:
+ if lib.resolved_symlink_dynamic_library:
+ libs.append(lib.resolved_symlink_dynamic_library)
+ return subjects.depset_file(
+ depset(libs),
+ meta = meta.derive("resolved_symlink_dynamic_library_files"),
+ )
+
+def _new_resolved_symlink_interface_library_files_subject(linking_context, meta):
+ libs = []
+ for linker_input in linking_context.linker_inputs.to_list():
+ for lib in linker_input.libraries:
+ if lib.resolved_symlink_interface_library:
+ libs.append(lib.resolved_symlink_interface_library)
+ return subjects.depset_file(
+ depset(libs),
+ meta = meta.derive("resolved_symlink_interface_library_files"),
+ )
+
+def _new_libraries_to_link_subject_from_linking_context(linking_context, meta):
+ libs = []
+ for linker_input in linking_context.linker_inputs.to_list():
+ libs.extend(linker_input.libraries)
+ return _new_cc_info_libraries_to_link_subject(libs, meta)
+
def _cc_info_linking_context_equals(actual, expected, meta):
if actual == expected:
return
@@ -128,6 +184,7 @@
def _new_library_to_link_subject(library_to_link, meta):
public = struct(
dynamic_library = lambda: subjects.file(library_to_link.dynamic_library, meta.derive("dynamic_library")),
+ alwayslink = lambda: subjects.bool(library_to_link.alwayslink, meta.derive("alwayslink")),
)
return public