| """White-box unit test of cc_binary rule.""" | |
| load("@bazel_features//:features.bzl", "bazel_features") | |
| load("@rules_testing//lib:analysis_test.bzl", "analysis_test", "test_suite") | |
| load("@rules_testing//lib:truth.bzl", "matching", "subjects") | |
| load("@rules_testing//lib:util.bzl", "TestingAspectInfo", "util") | |
| load("//cc:action_names.bzl", "ACTION_NAMES") | |
| load("//cc:cc_binary.bzl", _actual_cc_binary = "cc_binary") | |
| load("//cc:cc_import.bzl", "cc_import") | |
| load("//cc:cc_library.bzl", "cc_library") | |
| load("//cc:cc_test.bzl", _actual_cc_test = "cc_test") | |
| load("//tests/cc/testutil:cc_analysis_test.bzl", "MOCK_TOOLCHAINS", "cc_analysis_test") | |
| load("//tests/cc/testutil:cc_binary_target_subject.bzl", "cc_binary_target_subject") | |
| load("//tests/cc/testutil:link_action_subject.bzl", "link_action_subject") | |
| load( | |
| "//tests/cc/testutil:mock_rules.bzl", | |
| "cc_runtimes_toolchain", | |
| "mock_go_library", | |
| "mock_runtime_library", | |
| ) | |
| load("//tests/cc/testutil/toolchains:features.bzl", "FEATURE_NAMES") | |
| # Wrap cc_binary to mock out common dependencies. | |
| def cc_binary(name, **kwargs): | |
| if "malloc" not in kwargs: | |
| # Avoid the real "malloc", which might use arbitrary toolchain actions and features. | |
| kwargs["malloc"] = "//tests/cc/testutil/toolchains:mock_malloc" | |
| _actual_cc_binary( | |
| name = name, | |
| **kwargs | |
| ) | |
| # Wrap cc_test to mock out common dependencies. | |
| def cc_test(name, **kwargs): | |
| if "malloc" not in kwargs: | |
| # Avoid the real "malloc", which might use arbitrary toolchain actions and features. | |
| kwargs["malloc"] = "//tests/cc/testutil/toolchains:mock_malloc" | |
| _actual_cc_test( | |
| name = name, | |
| **kwargs | |
| ) | |
| def _test_files_to_build(name, **kwargs): | |
| util.helper_target( | |
| cc_binary, | |
| name = name + "/hello", | |
| srcs = ["hello.cc"], | |
| ) | |
| cc_analysis_test( | |
| name = name, | |
| impl = _test_files_to_build_impl, | |
| target = name + "/hello", | |
| **kwargs | |
| ) | |
| def _test_files_to_build_impl(env, target): | |
| cc_binary_subject = cc_binary_target_subject.from_target(env, target) | |
| cc_binary_subject.default_outputs().contains_exactly(["{package}/{name}{binary_extension}"]) | |
| cc_binary_subject.executable().short_path_equals("{package}/{name}{binary_extension}") | |
| def _test_headers_not_passed_to_linking_action(name, **kwargs): | |
| util.helper_target( | |
| cc_binary, | |
| name = name + "/bye", | |
| srcs = ["bye.cc", "bye.h"], | |
| ) | |
| cc_analysis_test( | |
| name = name, | |
| impl = _test_headers_not_passed_to_linking_action_impl, | |
| target = name + "/bye", | |
| config_settings = { | |
| "//command_line_option:features": ["parse_headers"], | |
| "//command_line_option:process_headers_in_dependencies": True, | |
| }, | |
| **kwargs | |
| ) | |
| def _test_headers_not_passed_to_linking_action_impl(env, target): | |
| link_action_subject.from_target(env, target).inputs().not_contains_predicate( | |
| matching.file_extension_in(["h", "hpp", "hxx"]), | |
| ) | |
| def _test_no_duplicate_linkopts(name, **kwargs): | |
| # Regression test for b/943558: linkopts duplicated in linker invocation | |
| util.helper_target( | |
| cc_binary, | |
| name = name + "/hello", | |
| srcs = ["hello.cc"], | |
| linkopts = ["-fake_option"], | |
| ) | |
| cc_analysis_test( | |
| name = name, | |
| impl = _test_no_duplicate_linkopts_impl, | |
| target = name + "/hello", | |
| **kwargs | |
| ) | |
| def _test_no_duplicate_linkopts_impl(env, target): | |
| link_action = link_action_subject.from_target(env, target) | |
| link_action.argv().contains("-fake_option") | |
| link_action.argv().transform( | |
| filter = matching.equals_wrapper("-fake_option"), | |
| ).contains_no_duplicates() | |
| def _test_action_graph(name, **kwargs): | |
| util.helper_target( | |
| cc_binary, | |
| name = name + "/hello", | |
| srcs = ["hello.cc"], | |
| ) | |
| config_settings = { | |
| "//command_line_option:force_pic": False, | |
| } | |
| cc_analysis_test( | |
| name = name, | |
| impl = _test_action_graph_impl, | |
| target = name + "/hello", | |
| config_settings = config_settings, | |
| test_features = [ | |
| "no_dotd_file", | |
| ], | |
| **kwargs | |
| ) | |
| def _test_action_graph_impl(env, target): | |
| executable = target[DefaultInfo].files_to_run.executable | |
| link_action = link_action_subject.from_target(env, target) | |
| object_file = "{package}/_objs/{name}/hello.o" | |
| # link.inputs = { hello.o } | |
| link_action.inputs().contains(object_file) | |
| # link.outputs = { hello } | |
| link_action.outputs().contains_exactly([executable.short_path]) | |
| compile_action = env.expect.that_target(target).action_generating(object_file) | |
| compile_action.mnemonic().equals("CppCompile") | |
| # compile.inputs = { hello_cc } | |
| compile_action.inputs().contains("{package}/hello.cc") | |
| # compile.outputs = { hello.o } (mock toolchain doesn't generate .d) | |
| compile_action.outputs().contains_exactly([ | |
| object_file, | |
| ]) | |
| # TODO: Test stripped action | |
| def _make_dll(name): | |
| # make a fake dll so the dll shows up in the output directory (where the | |
| # binary will be) instead of as a source file (the way cc_import on its own would) | |
| # Example taken from | |
| # https://github.com/bazelbuild/bazel/blob/f720ed385e245e292b0afe19ebd84e4283c30565/examples/windows/dll/windows_dll_library.bzl | |
| dll = name + ".dll" | |
| mask = name + "_mask" | |
| util.helper_target( | |
| cc_binary, | |
| name = dll, | |
| srcs = ["hello.cc"], | |
| linkshared = 1, | |
| ) | |
| # Mask the cc_binary behind a cc_import so we can depend on it as a library | |
| util.helper_target( | |
| cc_import, | |
| name = mask, | |
| shared_library = dll, | |
| ) | |
| # cc_imports are always source files, so make it a generated file again | |
| util.helper_target( | |
| cc_library, | |
| name = name, | |
| deps = [mask], | |
| ) | |
| def _test_runtime_dynamic_libraries_copy_behavior(name, **kwargs): | |
| sub_dir_lib = name + "/dst/sub/sub_dir_lib" | |
| same_dir_lib = name + "/dst/same_dir_lib" | |
| binary_target = name + "/dst/hello" | |
| # project a dll into the same directory as the binary, and a second one in | |
| # a subdirectory | |
| _make_dll(same_dir_lib) | |
| _make_dll(sub_dir_lib) | |
| util.helper_target( | |
| cc_binary, | |
| name = binary_target, | |
| srcs = ["hello.cc"], | |
| deps = [ | |
| same_dir_lib, | |
| sub_dir_lib, | |
| ], | |
| linkstatic = False, | |
| ) | |
| analysis_test( | |
| name = name, | |
| impl = _test_runtime_dynamic_libraries_copy_behavior_impl, | |
| target = binary_target, | |
| # TODO: This would be better-done with the mock toolchain, once that is | |
| # wired up | |
| attrs = { | |
| "copy_feature_supported": attr.bool(), | |
| }, | |
| attr_values = { | |
| "copy_feature_supported": select({ | |
| # copy_dynamic_libraries_to_binary is only defined in the | |
| # windows toolchain currently | |
| "@platforms//os:windows": True, | |
| "//conditions:default": False, | |
| }), | |
| "size": "small", | |
| }, | |
| **kwargs | |
| ) | |
| def _test_runtime_dynamic_libraries_copy_behavior_impl(env, target): | |
| if not env.ctx.attr.copy_feature_supported: | |
| return | |
| test_name = env.ctx.label.name | |
| expected_copied_library = "tests/cc/common/{name}/dst/sub_dir_lib.dll".format( | |
| name = test_name, | |
| ) | |
| expected_same_dir_library = "tests/cc/common/{name}/dst/same_dir_lib.dll".format( | |
| name = test_name, | |
| ) | |
| # Both libraries should be listed as runtime dependencies, but... | |
| expected_libraries = [expected_copied_library, expected_same_dir_library] | |
| env.expect \ | |
| .that_target(target) \ | |
| .output_group("runtime_dynamic_libraries") \ | |
| .contains_exactly(expected_libraries) | |
| actions = {} | |
| for action in target[TestingAspectInfo].actions: | |
| if action.mnemonic != "Symlink": | |
| continue | |
| for output in action.outputs.to_list(): | |
| if output.short_path in expected_libraries: | |
| actions[output.short_path] = action | |
| # ... only one of the libraries should have a Symlink action (Copying | |
| # Execution Dynamic Library) since the other one should already be in the | |
| # same dir | |
| expected_copies = [expected_copied_library] | |
| env.expect.that_dict(actions).keys().contains_exactly(expected_copies) | |
| def _test_pic(name, **kwargs): | |
| util.helper_target( | |
| cc_binary, | |
| name = name + "/hello", | |
| srcs = ["hello.cc"], | |
| ) | |
| cc_analysis_test( | |
| name = name, | |
| impl = _test_pic_impl, | |
| target = name + "/hello", | |
| test_features = [FEATURE_NAMES.supports_pic], | |
| config_settings = { | |
| "//command_line_option:force_pic": True, | |
| }, | |
| **kwargs | |
| ) | |
| def _test_pic_impl(env, target): | |
| link_action = link_action_subject.from_target(env, target) | |
| link_action.inputs().contains_predicate( | |
| matching.file_basename_equals("hello.pic.o"), | |
| ) | |
| def _generated_def_file_test(name, impl, with_action_configs = None, **kwargs): | |
| if with_action_configs == None: | |
| with_action_configs = [] | |
| util.helper_target( | |
| cc_binary, | |
| name = name + "/hello", | |
| srcs = ["hello.cc"], | |
| linkshared = True, | |
| ) | |
| cc_analysis_test( | |
| name = name, | |
| impl = impl, | |
| target = name + "/hello", | |
| test_features = [ | |
| FEATURE_NAMES.copy_dynamic_libraries_to_binary, | |
| FEATURE_NAMES.targets_windows, | |
| FEATURE_NAMES.windows_export_all_symbols, | |
| ], | |
| with_action_configs = with_action_configs, | |
| **kwargs | |
| ) | |
| def _generated_def_file_action(env, target): | |
| action = cc_binary_target_subject.from_target(env, target).action_generating( | |
| "{package}/{name}.gen.def", | |
| ) | |
| action.mnemonic().equals("DefParser") | |
| return action | |
| # buildifier: disable=unused-variable | |
| def _test_generated_def_file_uses_default_tool(name, **kwargs): | |
| _generated_def_file_test( | |
| name, | |
| _test_generated_def_file_uses_default_tool_impl, | |
| **kwargs | |
| ) | |
| def _test_generated_def_file_uses_default_tool_impl(env, target): | |
| _generated_def_file_action(env, target).argv().contains_predicate( | |
| matching.contains("tools/def_parser"), | |
| ) | |
| # buildifier: disable=unused-variable | |
| def _test_generated_def_file_uses_toolchain_action(name, **kwargs): | |
| _generated_def_file_test( | |
| name, | |
| _test_generated_def_file_uses_toolchain_action_impl, | |
| with_action_configs = [ACTION_NAMES.generate_def_file], | |
| **kwargs | |
| ) | |
| def _test_generated_def_file_uses_toolchain_action_impl(env, target): | |
| _generated_def_file_action(env, target).argv().contains_predicate( | |
| matching.contains("def_parser_tool"), | |
| ) | |
| def _test_duplicate_linkopts(name, **kwargs): | |
| util.helper_target( | |
| cc_library, | |
| name = name + "/lib", | |
| srcs = ["lib.cc"], | |
| linkopts = [ | |
| "-z bar", | |
| "-z baz", | |
| ], | |
| ) | |
| util.helper_target( | |
| cc_binary, | |
| name = name + "/app", | |
| srcs = ["app.cc"], | |
| linkopts = [ | |
| "-z foo", | |
| "-z bar", | |
| ], | |
| deps = [name + "/lib"], | |
| ) | |
| cc_analysis_test( | |
| name = name, | |
| impl = _test_duplicate_linkopts_impl, | |
| target = name + "/app", | |
| **kwargs | |
| ) | |
| def _test_duplicate_linkopts_impl(env, target): | |
| executable = target[DefaultInfo].files_to_run.executable | |
| link_action = env.expect.that_target(target).action_generating(executable.short_path) | |
| argv = link_action.actual.argv | |
| env.expect.that_collection(argv).contains_at_least([ | |
| "-z", | |
| "foo", | |
| "-z", | |
| "bar", | |
| "-z", | |
| "bar", | |
| "-z", | |
| "baz", | |
| ]).in_order() | |
| def _test_unsupported_src_file(name, **kwargs): | |
| util.helper_target( | |
| cc_binary, | |
| name = name + "/bad", | |
| srcs = ["bad.unknown"], | |
| ) | |
| cc_analysis_test( | |
| name = name, | |
| impl = _test_unsupported_src_file_impl, | |
| target = name + "/bad", | |
| expect_failure = True, | |
| **kwargs | |
| ) | |
| def _test_unsupported_src_file_impl(env, target): | |
| env.expect.that_target(target).failures().contains_predicate( | |
| matching.contains("is misplaced here"), | |
| ) | |
| env.expect.that_target(target).failures().contains_predicate( | |
| matching.contains("bad.unknown"), | |
| ) | |
| def _test_missing_action_config_for_strip_is_a_rule_error(name, **kwargs): | |
| util.helper_target( | |
| cc_binary, | |
| name = name + "/hello", | |
| srcs = ["hello.cc"], | |
| ) | |
| cc_analysis_test( | |
| name = name, | |
| impl = _test_missing_action_config_for_strip_is_a_rule_error_impl, | |
| target = name + "/hello", | |
| test_features = [FEATURE_NAMES.no_legacy_features, FEATURE_NAMES.pic], | |
| with_action_configs = [ | |
| ACTION_NAMES.cpp_compile, | |
| ACTION_NAMES.cpp_link_static_library, | |
| ACTION_NAMES.cpp_link_executable, | |
| ], | |
| expect_failure = True, | |
| **kwargs | |
| ) | |
| def _test_missing_action_config_for_strip_is_a_rule_error_impl(env, target): | |
| env.expect.that_target(target).failures().contains_predicate( | |
| matching.contains("Expected action_config for 'strip' to be configured."), | |
| ) | |
| def _test_sanitize_pwd_feature_enabled(name, **kwargs): | |
| """sanitize_pwd is on by default, PWD should be set via the feature's env_set.""" | |
| util.helper_target( | |
| cc_binary, | |
| name = name + "/hello", | |
| srcs = ["hello.cc"], | |
| ) | |
| cc_analysis_test( | |
| name = name, | |
| impl = _test_sanitize_pwd_feature_enabled_impl, | |
| target = name + "/hello", | |
| config_settings = { | |
| "//command_line_option:platforms": str(Label("//tests/cc/testutil/toolchains:linux_x86_64")), | |
| }, | |
| **kwargs | |
| ) | |
| def _test_sanitize_pwd_feature_enabled_impl(env, target): | |
| link_action = link_action_subject.from_target(env, target) | |
| link_action.env().get("PWD", factory = subjects.str).equals("/proc/self/cwd") | |
| def _test_sanitize_pwd_feature_disabled(name, **kwargs): | |
| """When sanitize_pwd is explicitly disabled, the legacy requires_darwin fallback still applies.""" | |
| util.helper_target( | |
| cc_binary, | |
| name = name + "/hello", | |
| srcs = ["hello.cc"], | |
| ) | |
| cc_analysis_test( | |
| name = name, | |
| impl = _test_sanitize_pwd_feature_disabled_impl, | |
| target = name + "/hello", | |
| config_settings = { | |
| "//command_line_option:features": ["-sanitize_pwd"], | |
| }, | |
| **kwargs | |
| ) | |
| def _test_sanitize_pwd_feature_disabled_impl(env, target): | |
| link_action = link_action_subject.from_target(env, target) | |
| link_action.env().get("PWD", factory = subjects.str).equals("/proc/self/cwd") | |
| def _test_sanitize_pwd_macos_no_pwd(name, **kwargs): | |
| """On macOS, sanitize_pwd is enabled but should not set PWD.""" | |
| util.helper_target( | |
| cc_binary, | |
| name = name + "/hello", | |
| srcs = ["hello.cc"], | |
| ) | |
| cc_analysis_test( | |
| name = name, | |
| impl = _test_sanitize_pwd_macos_no_pwd_impl, | |
| target = name + "/hello", | |
| config_settings = { | |
| "//command_line_option:platforms": str(Label("//tests/cc/testutil/toolchains:macos_arm64")), | |
| }, | |
| **kwargs | |
| ) | |
| def _test_sanitize_pwd_macos_no_pwd_impl(env, target): | |
| link_action = link_action_subject.from_target(env, target) | |
| link_action.env().keys().not_contains("PWD") | |
| def _include_paths_from_argv(argv, flag): | |
| include_paths = [] | |
| for i in range(len(argv) - 1): | |
| if argv[i] == flag: | |
| include_paths.append(argv[i + 1]) | |
| return include_paths | |
| def _system_include_paths_from_argv(argv): | |
| return _include_paths_from_argv(argv, "-isystem") | |
| def _test_system_include_paths_reclassifies_local_includes_without_propagation(name, **kwargs): | |
| util.helper_target( | |
| cc_library, | |
| name = name + "/dep", | |
| srcs = ["dep.cc", "dep_local.h"], | |
| hdrs = ["dep_public.h"], | |
| local_includes = ["dep_private"], | |
| ) | |
| util.helper_target( | |
| cc_binary, | |
| name = name + "/hello", | |
| srcs = ["hello.cc", "hello_local.h"], | |
| deps = [name + "/dep"], | |
| local_includes = ["hello_private"], | |
| ) | |
| cc_analysis_test( | |
| name = name, | |
| impl = _test_system_include_paths_reclassifies_local_includes_without_propagation_impl, | |
| target = name + "/hello", | |
| config_settings = { | |
| "//command_line_option:features": ["system_include_paths"], | |
| }, | |
| **kwargs | |
| ) | |
| def _test_system_include_paths_reclassifies_local_includes_without_propagation_impl(env, target): | |
| executable = target[DefaultInfo].files_to_run.executable | |
| link_action = env.expect.that_target(target).action_generating(executable.short_path) | |
| hello_obj_files = [ | |
| f | |
| for f in link_action.actual.inputs.to_list() | |
| if f.basename.startswith("hello.") and f.extension in ["o", "obj"] | |
| ] | |
| env.expect.that_collection(hello_obj_files).has_size(1) | |
| compile_action = env.expect.that_target(target).action_generating(hello_obj_files[0].short_path) | |
| system_include_paths = _system_include_paths_from_argv(compile_action.actual.argv) | |
| env.expect.that_collection(system_include_paths).contains_predicate( | |
| matching.str_endswith("/hello_private"), | |
| ) | |
| env.expect.that_collection(system_include_paths).transform( | |
| filter = matching.str_endswith("/dep_private"), | |
| ).contains_exactly([]) | |
| def _test_system_include_paths_reclassifies_local_includes_after_includes(name, **kwargs): | |
| util.helper_target( | |
| cc_library, | |
| name = name + "/dep", | |
| srcs = ["dep.cc", "dep_local.h"], | |
| hdrs = ["dep_public.h"], | |
| includes = ["dep_includes"], | |
| local_includes = ["dep_private"], | |
| ) | |
| cc_analysis_test( | |
| name = name, | |
| impl = _test_system_include_paths_reclassifies_local_includes_after_includes_impl, | |
| target = name + "/dep", | |
| config_settings = { | |
| "//command_line_option:features": ["system_include_paths"], | |
| }, | |
| **kwargs | |
| ) | |
| def _test_system_include_paths_reclassifies_local_includes_after_includes_impl(env, target): | |
| dep_compile_actions = [] | |
| for action in target[TestingAspectInfo].actions: | |
| if action.mnemonic != "CppCompile": | |
| continue | |
| for output in action.outputs.to_list(): | |
| if output.basename.startswith("dep.") and output.extension in ["o", "obj"]: | |
| dep_compile_actions.append(action) | |
| break | |
| env.expect.that_collection(dep_compile_actions).has_size(1) | |
| dep_system_include_paths = _system_include_paths_from_argv(dep_compile_actions[0].argv) | |
| dep_system_include_kinds = [] | |
| for path in dep_system_include_paths: | |
| if path.endswith("/dep_includes"): | |
| dep_system_include_kinds.append("dep_includes") | |
| elif path.endswith("/dep_private"): | |
| dep_system_include_kinds.append("dep_private") | |
| env.expect.that_collection(dep_system_include_kinds).contains_at_least([ | |
| "dep_includes", | |
| "dep_private", | |
| ]).in_order() | |
| # buildifier: disable=unused-variable | |
| def _test_external_include_paths_reclassifies_external_quote_includes(name, **kwargs): | |
| util.helper_target( | |
| cc_binary, | |
| name = name + "/hello", | |
| srcs = ["hello.cc"], | |
| deps = ["@googletest//:gtest"], | |
| ) | |
| cc_analysis_test( | |
| name = name, | |
| impl = _test_external_include_paths_reclassifies_external_quote_includes_impl, | |
| target = name + "/hello", | |
| test_features = [FEATURE_NAMES.external_include_paths], | |
| **kwargs | |
| ) | |
| def _test_external_include_paths_reclassifies_external_quote_includes_impl(env, target): | |
| executable = target[DefaultInfo].files_to_run.executable | |
| link_action = env.expect.that_target(target).action_generating(executable.short_path) | |
| hello_obj_files = [ | |
| f | |
| for f in link_action.actual.inputs.to_list() | |
| if f.basename.startswith("hello.") and f.extension in ["o", "obj"] | |
| ] | |
| env.expect.that_collection(hello_obj_files).has_size(1) | |
| compile_action = env.expect.that_target(target).action_generating(hello_obj_files[0].short_path) | |
| quote_include_paths = _include_paths_from_argv(compile_action.actual.argv, "-iquote") | |
| system_include_paths = _system_include_paths_from_argv(compile_action.actual.argv) | |
| if not quote_include_paths: | |
| fail("expected the compile action to still have non-external -iquote paths") | |
| env.expect.that_collection(system_include_paths).contains_predicate( | |
| matching.contains("googletest"), | |
| ) | |
| env.expect.that_collection(quote_include_paths).transform( | |
| filter = matching.contains("googletest"), | |
| ).contains_exactly([]) | |
| def _test_linkopts_diamond(name, **kwargs): | |
| util.helper_target( | |
| cc_library, | |
| name = name + "/core", | |
| srcs = ["core.cc"], | |
| linkopts = ["-z core"], | |
| ) | |
| util.helper_target( | |
| cc_library, | |
| name = name + "/lib1", | |
| srcs = ["lib1.cc"], | |
| linkopts = ["-z lib1"], | |
| deps = [name + "/core"], | |
| ) | |
| util.helper_target( | |
| cc_library, | |
| name = name + "/lib2", | |
| srcs = ["lib2.cc"], | |
| linkopts = ["-z lib2"], | |
| deps = [name + "/core"], | |
| ) | |
| util.helper_target( | |
| cc_binary, | |
| name = name + "/app", | |
| srcs = ["app.cc"], | |
| linkopts = ["-z app"], | |
| deps = [ | |
| name + "/lib1", | |
| name + "/lib2", | |
| ], | |
| ) | |
| cc_analysis_test( | |
| name = name, | |
| impl = _test_linkopts_diamond_impl, | |
| target = name + "/app", | |
| **kwargs | |
| ) | |
| def _test_linkopts_diamond_impl(env, target): | |
| link_action = link_action_subject.from_target(env, target) | |
| link_action.argv().contains_at_least([ | |
| "-z", | |
| "app", | |
| "-z", | |
| "lib1", | |
| "-z", | |
| "lib2", | |
| "-z", | |
| "core", | |
| ]).in_order() | |
| def _test_linkopts_fake_diamond(name, **kwargs): | |
| util.helper_target( | |
| cc_library, | |
| name = name + "/core1", | |
| srcs = ["core.cc"], | |
| linkopts = ["-z core"], | |
| ) | |
| util.helper_target( | |
| cc_library, | |
| name = name + "/core2", | |
| srcs = ["core.cc"], | |
| linkopts = ["-z core"], | |
| ) | |
| util.helper_target( | |
| cc_library, | |
| name = name + "/lib1", | |
| srcs = ["lib1.cc"], | |
| linkopts = ["-z lib1"], | |
| deps = [name + "/core1"], | |
| ) | |
| util.helper_target( | |
| cc_library, | |
| name = name + "/lib2", | |
| srcs = ["lib2.cc"], | |
| linkopts = ["-z lib2"], | |
| deps = [name + "/core2"], | |
| ) | |
| util.helper_target( | |
| cc_binary, | |
| name = name + "/app", | |
| srcs = ["app.cc"], | |
| linkopts = ["-z app"], | |
| deps = [ | |
| name + "/lib1", | |
| name + "/lib2", | |
| ], | |
| ) | |
| cc_analysis_test( | |
| name = name, | |
| impl = _test_linkopts_fake_diamond_impl, | |
| target = name + "/app", | |
| **kwargs | |
| ) | |
| def _test_linkopts_fake_diamond_impl(env, target): | |
| link_action = link_action_subject.from_target(env, target) | |
| link_action.argv().contains_at_least([ | |
| "-z", | |
| "app", | |
| "-z", | |
| "lib1", | |
| "-z", | |
| "core", | |
| "-z", | |
| "lib2", | |
| "-z", | |
| "core", | |
| ]).in_order() | |
| def _is_shared_library(f): | |
| return f.extension in ["so", "dylib", "dll", "ifso"] or ".so" in f.basename or ".dylib" in f.basename | |
| def _assert_link_staticness(env, target, expected_static): | |
| link_action = link_action_subject.from_target(env, target) | |
| shared_library_matcher = matching.custom("is shared library", _is_shared_library) | |
| if expected_static: | |
| link_action.inputs().not_contains_predicate(shared_library_matcher) | |
| else: | |
| link_action.inputs().contains_predicate(shared_library_matcher) | |
| def _create_dep_tree(name, use_actual_cc_binary = False): | |
| binary_rule = _actual_cc_binary if use_actual_cc_binary else cc_binary | |
| # Mallocs | |
| util.helper_target( | |
| cc_library, | |
| name = name + "/system_malloc", | |
| srcs = ["system_malloc.cc"], | |
| ) | |
| util.helper_target( | |
| cc_library, | |
| name = name + "/mymalloc", | |
| srcs = ["mymalloc.cc"], | |
| linkopts = ["-Lmalloc_dir -lmalloc_opt"], | |
| ) | |
| # Infrastructure | |
| util.helper_target( | |
| cc_library, | |
| name = name + "/infrastructure1", | |
| srcs = ["infrastructure1.cc"], | |
| linkopts = [ | |
| "-Linfrastructure1_dir", | |
| "-linfrastructure1_opt", | |
| ], | |
| linkstamp = "linkstamp.cc", | |
| linkstatic = 1, | |
| ) | |
| util.helper_target( | |
| cc_library, | |
| name = name + "/infrastructure2", | |
| srcs = ["infrastructure2.cc"], | |
| linkopts = ["-Linfrastructure2_dir -linfrastructure2_opt"], | |
| linkstamp = "linkstamp.cc", | |
| ) | |
| # Middleware | |
| util.helper_target( | |
| cc_library, | |
| name = name + "/middleware1", | |
| srcs = ["middleware1.cc"], | |
| linkopts = [ | |
| "-Lmiddleware1_dir", | |
| "-lmiddleware1_opt", | |
| ], | |
| deps = [name + "/infrastructure1"], | |
| ) | |
| util.helper_target( | |
| binary_rule, | |
| name = name + "/middleware2.so", | |
| srcs = ["middleware2.cc"], | |
| linkopts = [ | |
| "-Lmiddleware2_dir", | |
| "-lmiddleware2_opt", | |
| ], | |
| linkshared = 1, | |
| linkstatic = 1, | |
| deps = [name + "/infrastructure2"], | |
| ) | |
| util.helper_target( | |
| binary_rule, | |
| name = name + "/middleware3.so.1", | |
| srcs = ["middleware3.cc"], | |
| linkopts = [ | |
| "-Lmiddleware3_dir", | |
| "-lmiddleware3_opt", | |
| ], | |
| linkshared = 1, | |
| deps = [name + "/infrastructure2"], | |
| ) | |
| # App | |
| util.helper_target( | |
| binary_rule, | |
| name = name + "/app", | |
| srcs = ["app.cc"], | |
| # Override potential default link_extra_lib attribute value | |
| link_extra_lib = "//tests/cc/testutil/toolchains:link_extra_lib", | |
| linkopts = [ | |
| "-Lapp_dir1 -Lapp_dir2", | |
| "-lapp_opt", | |
| ], | |
| deps = [ | |
| name + "/middleware1", | |
| name + "/middleware2.so", | |
| name + "/middleware3.so.1", | |
| ], | |
| ) | |
| util.helper_target( | |
| binary_rule, | |
| name = name + "/app_nonstatic", | |
| srcs = ["app.cc"], | |
| # Override potential default link_extra_lib attribute value | |
| link_extra_lib = "//tests/cc/testutil/toolchains:link_extra_lib", | |
| linkopts = [ | |
| "-Lapp_dir1 -Lapp_dir2", | |
| "-lapp_opt", | |
| ], | |
| linkstatic = 0, | |
| deps = [ | |
| name + "/middleware1", | |
| name + "/middleware2.so", | |
| name + "/middleware3.so.1", | |
| ], | |
| ) | |
| # buildifier: disable=unused-variable | |
| def _test_cc_runtimes_added_to_libraries(name, **kwargs): | |
| _create_dep_tree(name) | |
| cc_analysis_test( | |
| name = name, | |
| impl = _test_cc_runtimes_added_to_libraries_impl, | |
| target = name + "/app", | |
| test_features = [ | |
| FEATURE_NAMES.supports_pic, | |
| ], | |
| config_settings = { | |
| "//command_line_option:extra_toolchains": ",".join( | |
| MOCK_TOOLCHAINS + [ | |
| "//tests/cc/common:cc_runtimes_mock_toolchain", | |
| ], | |
| ), | |
| }, | |
| **kwargs | |
| ) | |
| def _test_cc_runtimes_added_to_libraries_impl(env, target): | |
| link_action = link_action_subject.from_target(env, target) | |
| link_action.inputs().contains_at_least_predicates([ | |
| matching.file_basename_equals("app.pic.o"), | |
| matching.file_basename_equals("libmiddleware1.a"), | |
| matching.file_basename_equals("libinfrastructure1.a"), | |
| matching.file_basename_equals("liblink_extra_lib.a"), | |
| matching.file_basename_equals("libruntime.a"), | |
| matching.file_basename_equals("linkstamp.o"), | |
| ]) | |
| def _test_ignore_custom_malloc(name, **kwargs): | |
| _create_dep_tree(name, use_actual_cc_binary = True) | |
| custom_malloc_label = Label("//tests/cc/common:" + name + "/system_malloc") | |
| cc_analysis_test( | |
| name = name, | |
| impl = _test_ignore_custom_malloc_impl, | |
| target = name + "/app", | |
| config_settings = { | |
| "//command_line_option:custom_malloc": custom_malloc_label, | |
| }, | |
| **kwargs | |
| ) | |
| def _test_ignore_custom_malloc_impl(env, target): | |
| link_action = link_action_subject.from_target(env, target) | |
| link_action.inputs().contains_predicate(matching.file_basename_equals("libsystem_malloc.a")) | |
| link_action.inputs().not_contains_predicate(matching.file_basename_equals("libmock_malloc.a")) | |
| def _test_custom_malloc(name, **kwargs): | |
| _create_dep_tree(name, use_actual_cc_binary = True) | |
| custom_malloc_label = Label("//tests/cc/common:" + name + "/mymalloc") | |
| cc_analysis_test( | |
| name = name, | |
| impl = _test_custom_malloc_impl, | |
| target = name + "/app", | |
| test_features = [FEATURE_NAMES.supports_pic], | |
| config_settings = { | |
| "//command_line_option:custom_malloc": custom_malloc_label, | |
| }, | |
| **kwargs | |
| ) | |
| def _test_custom_malloc_impl(env, target): | |
| link_action = link_action_subject.from_target(env, target) | |
| link_action.inputs().contains_predicate(matching.file_basename_equals("libmymalloc.a")) | |
| link_action.inputs().not_contains_predicate(matching.file_basename_equals("libmock_malloc.a")) | |
| def _test_app_linking_static(name, **kwargs): | |
| _create_dep_tree(name) | |
| cc_analysis_test( | |
| name = name, | |
| impl = _test_app_linking_static_impl, | |
| target = name + "/app", | |
| test_features = [ | |
| FEATURE_NAMES.supports_pic, | |
| FEATURE_NAMES.supports_dynamic_linker, | |
| FEATURE_NAMES.supports_interface_shared_libraries, | |
| ], | |
| **kwargs | |
| ) | |
| def _test_app_linking_static_impl(env, target): | |
| link_action = link_action_subject.from_target(env, target) | |
| # Assert inputs | |
| link_action.inputs().contains_at_least_predicates([ | |
| matching.file_basename_equals("app.pic.o"), | |
| matching.file_basename_equals("libmiddleware1.a"), | |
| matching.file_basename_equals("libinfrastructure1.a"), | |
| matching.file_basename_equals("linkstamp.o"), | |
| ]) | |
| # Assert NOT inputs | |
| link_action.inputs().not_contains_predicate(matching.file_basename_equals("libinfrastructure2.a")) | |
| link_action.inputs().not_contains_predicate(matching.file_basename_equals("libmiddleware2.so")) | |
| link_action.inputs().not_contains_predicate(matching.file_basename_equals("libmiddleware3.so.1")) | |
| # Assert linkopts | |
| link_action.argv().contains_at_least([ | |
| "-Lapp_dir1", | |
| "-Lapp_dir2", | |
| "-lapp_opt", | |
| "-Lmiddleware1_dir", | |
| "-lmiddleware1_opt", | |
| "-Linfrastructure1_dir", | |
| "-linfrastructure1_opt", | |
| ]).in_order() | |
| def _test_app_linking_dynamic(name, **kwargs): | |
| _create_dep_tree(name) | |
| cc_analysis_test( | |
| name = name, | |
| impl = _test_app_linking_dynamic_impl, | |
| target = name + "/app_nonstatic", | |
| test_features = [ | |
| FEATURE_NAMES.supports_pic, | |
| FEATURE_NAMES.supports_dynamic_linker, | |
| FEATURE_NAMES.supports_interface_shared_libraries, | |
| ], | |
| **kwargs | |
| ) | |
| def _test_app_linking_dynamic_impl(env, target): | |
| link_action = link_action_subject.from_target(env, target) | |
| # Assert inputs | |
| link_action.inputs().contains_at_least_predicates([ | |
| matching.file_basename_equals("app.pic.o"), | |
| matching.file_basename_equals("libinfrastructure1.a"), | |
| matching.file_basename_equals("linkstamp.o"), | |
| ]) | |
| # Assert dynamic library symlink (mangled) | |
| link_action.inputs().contains_predicate( | |
| matching.custom("basename ends with _Slibmiddleware1.ifso", lambda f: f.basename.endswith("_Slibmiddleware1.ifso")), | |
| ) | |
| # Assert NOT inputs | |
| link_action.inputs().not_contains_predicate(matching.file_basename_equals("libmiddleware1.a")) | |
| link_action.inputs().not_contains_predicate(matching.file_basename_equals("libinfrastructure2.a")) | |
| # Assert linkopts | |
| link_action.argv().contains_at_least([ | |
| "-Lapp_dir1", | |
| "-Lapp_dir2", | |
| "-lapp_opt", | |
| "-Lmiddleware1_dir", | |
| "-lmiddleware1_opt", | |
| "-Linfrastructure1_dir", | |
| "-linfrastructure1_opt", | |
| ]).in_order() | |
| def _test_so_in_srcs(name, **kwargs): | |
| util.helper_target( | |
| cc_binary, | |
| name = name + "/cookies", | |
| srcs = [ | |
| "cookies.cc", | |
| "library.so", | |
| "library2.so.1", | |
| ], | |
| ) | |
| cc_analysis_test( | |
| name = name, | |
| impl = _test_so_in_srcs_impl, | |
| target = name + "/cookies", | |
| **kwargs | |
| ) | |
| def _test_so_in_srcs_impl(env, target): | |
| runfiles = env.expect.that_target(target).runfiles() | |
| runfiles.contains_predicate(matching.str_endswith("library.so")) | |
| runfiles.not_contains_predicate(matching.str_endswith("library.so.1")) | |
| runfiles.contains_predicate(matching.str_endswith("library2.so.1")) | |
| runfiles.not_contains_predicate(matching.str_endswith("library2.so")) | |
| def _create_three_rules_chain(name): | |
| util.helper_target( | |
| cc_library, | |
| name = name + "/baz", | |
| srcs = ["baz.cc"], | |
| linkstamp = "linkstamp.cc", | |
| ) | |
| util.helper_target( | |
| cc_library, | |
| name = name + "/bar", | |
| srcs = ["bar.cc"], | |
| deps = [":" + name + "/baz"], | |
| ) | |
| util.helper_target( | |
| cc_binary, | |
| name = name + "/foo", | |
| srcs = ["foo.cc"], | |
| deps = [":" + name + "/bar"], | |
| ) | |
| def _test_transitive_libs_are_collected(name, **kwargs): | |
| _create_three_rules_chain(name) | |
| cc_analysis_test( | |
| name = name, | |
| impl = _test_transitive_libs_are_collected_impl, | |
| target = name + "/foo", | |
| config_settings = { | |
| "//command_line_option:start_end_lib": False, | |
| }, | |
| test_features = [FEATURE_NAMES.supports_pic], | |
| **kwargs | |
| ) | |
| def _test_transitive_libs_are_collected_impl(env, target): | |
| link_action = link_action_subject.from_target(env, target) | |
| link_action.inputs().contains_at_least_predicates([ | |
| matching.file_basename_equals("foo.pic.o"), | |
| matching.file_basename_equals("libbar.a"), | |
| matching.file_basename_equals("libbaz.a"), | |
| matching.file_basename_equals("linkstamp.o"), | |
| ]) | |
| def _test_transitive_linkstamps_are_collected(name, **kwargs): | |
| _create_three_rules_chain(name) | |
| cc_analysis_test( | |
| name = name, | |
| impl = _test_transitive_linkstamps_are_collected_impl, | |
| target = name + "/foo", | |
| **kwargs | |
| ) | |
| def _test_transitive_linkstamps_are_collected_impl(env, target): | |
| link_action = link_action_subject.from_target(env, target) | |
| link_action.inputs().contains_predicate(matching.file_basename_equals("linkstamp.o")) | |
| link_action.inputs().not_contains_predicate(matching.file_basename_equals("linkstamp.cc")) | |
| def _test_linker_toolchain_feature(name, **kwargs): | |
| util.helper_target( | |
| cc_binary, | |
| name = name + "/foo", | |
| srcs = ["foo.cc"], | |
| ) | |
| cc_analysis_test( | |
| name = name, | |
| impl = _test_linker_toolchain_feature_impl, | |
| target = name + "/foo", | |
| test_features = [FEATURE_NAMES.link_env], | |
| **kwargs | |
| ) | |
| def _test_linker_toolchain_feature_impl(env, target): | |
| link_action = link_action_subject.from_target(env, target) | |
| link_action.env().contains_at_least({"foo": "bar"}) | |
| def _test_go_code_comes_after_deps(name, **kwargs): | |
| util.helper_target( | |
| mock_go_library, | |
| name = name + "/go_lib", | |
| ) | |
| util.helper_target( | |
| cc_library, | |
| name = name + "/cc_lib", | |
| srcs = ["cc_lib.cc"], | |
| deps = [":" + name + "/go_lib"], | |
| ) | |
| util.helper_target( | |
| cc_binary, | |
| name = name + "/bin", | |
| srcs = ["binary.cc"], | |
| deps = [":" + name + "/cc_lib"], | |
| ) | |
| cc_analysis_test( | |
| name = name, | |
| impl = _test_go_code_comes_after_deps_impl, | |
| target = name + "/bin", | |
| **kwargs | |
| ) | |
| def _test_go_code_comes_after_deps_impl(env, target): | |
| link_action = link_action_subject.from_target(env, target) | |
| link_action.argv().contains_at_least_predicates([ | |
| matching.str_endswith("libcc_lib.a"), | |
| matching.str_endswith("libgo_lib.a"), | |
| ]).in_order() | |
| def _test_additional_linker_inputs(name, **kwargs): | |
| util.helper_target( | |
| native.genrule, | |
| name = name + "/gen_extra", | |
| outs = ["main.extra_file"], | |
| cmd = "echo '' > $@", | |
| ) | |
| util.helper_target( | |
| cc_binary, | |
| name = name + "/bin", | |
| srcs = ["main.cc"], | |
| additional_linker_inputs = [":" + name + "/gen_extra"], | |
| linkopts = ["--option=$(location :" + name + "/gen_extra)"], | |
| ) | |
| cc_analysis_test( | |
| name = name, | |
| impl = _test_additional_linker_inputs_impl, | |
| target = name + "/bin", | |
| **kwargs | |
| ) | |
| def _test_additional_linker_inputs_impl(env, target): | |
| link_action = link_action_subject.from_target(env, target) | |
| link_action.argv().contains_predicate( | |
| matching.custom( | |
| "starts with --option= and ends with main.extra_file", | |
| lambda arg: arg.startswith("--option=") and arg.endswith("main.extra_file"), | |
| ), | |
| ) | |
| link_action.inputs().contains_predicate(matching.file_basename_equals("main.extra_file")) | |
| # Regression test for b/193125967 | |
| def _test_conflicting_linkstamps(name, **kwargs): | |
| util.helper_target( | |
| cc_library, | |
| name = name + "/foo", | |
| hdrs = ["foo.h"], | |
| linkstamp = "foo.cc", | |
| ) | |
| util.helper_target( | |
| cc_library, | |
| name = name + "/bar", | |
| hdrs = ["bar.h"], | |
| linkstamp = "foo.cc", | |
| ) | |
| util.helper_target( | |
| cc_binary, | |
| name = name + "/bin", | |
| deps = [ | |
| ":" + name + "/bar", | |
| ":" + name + "/foo", | |
| ], | |
| ) | |
| cc_analysis_test( | |
| name = name, | |
| impl = _test_conflicting_linkstamps_impl, | |
| target = name + "/bin", | |
| **kwargs | |
| ) | |
| def _test_conflicting_linkstamps_impl(_env, _target): | |
| # The test passes if analysis succeeds. | |
| pass | |
| def _test_compilation_prerequisites_in_output_group(name, **kwargs): | |
| out_file = name + "_a.cc" | |
| util.helper_target( | |
| native.genrule, | |
| name = name + "/gen", | |
| outs = [out_file], | |
| cmd = "echo '' > $@", | |
| ) | |
| util.helper_target( | |
| cc_library, | |
| name = name + "/mylib", | |
| hdrs = ["b.h"], | |
| ) | |
| util.helper_target( | |
| cc_binary, | |
| name = name + "/prerequisites", | |
| srcs = [ | |
| name + "/gen", | |
| "hello.cc", | |
| "hello.h", | |
| ], | |
| deps = [name + "/mylib"], | |
| ) | |
| cc_analysis_test( | |
| name = name, | |
| impl = _test_compilation_prerequisites_in_output_group_impl, | |
| target = name + "/prerequisites", | |
| attrs = { | |
| "out_file": attr.string(), | |
| }, | |
| attr_values = { | |
| "out_file": out_file, | |
| }, | |
| **kwargs | |
| ) | |
| def _test_compilation_prerequisites_in_output_group_impl(env, target): | |
| prereqs = target[OutputGroupInfo].compilation_prerequisites_INTERNAL_.to_list() | |
| prereq_paths = [f.short_path for f in prereqs] | |
| target_subject = env.expect.that_target(target) | |
| prereqs_subject = subjects.collection( | |
| prereq_paths, | |
| meta = target_subject.meta.derive("compilation_prerequisites"), | |
| format = True, | |
| ) | |
| prereqs_subject.contains("{package}/hello.cc") | |
| prereqs_subject.contains("{package}/hello.h") | |
| prereqs_subject.contains("{package}/b.h") | |
| out_file = env.ctx.attr.out_file | |
| prereqs_subject.contains("{package}/" + out_file) | |
| prereqs_subject.contains_predicate(matching.str_endswith("cppmap")) | |
| def _create_prefers_pic_libs_dep_tree(name): | |
| util.helper_target( | |
| cc_library, | |
| name = name + "/mylib", | |
| srcs = ["dep.pic.a", "dep.nopic.a"], | |
| ) | |
| util.helper_target( | |
| cc_binary, | |
| name = name + "/mybinary", | |
| srcs = ["mybinary.cc"], | |
| deps = [name + "/mylib"], | |
| ) | |
| def _test_pic_mode_prefers_pic_libs_force_pic_disabled(name, **kwargs): | |
| _create_prefers_pic_libs_dep_tree(name) | |
| cc_analysis_test( | |
| name = name, | |
| impl = _test_pic_mode_prefers_pic_libs_force_pic_disabled_impl, | |
| target = name + "/mybinary", | |
| test_features = [FEATURE_NAMES.supports_pic], | |
| config_settings = { | |
| "//command_line_option:force_pic": False, | |
| }, | |
| **kwargs | |
| ) | |
| def _test_pic_mode_prefers_pic_libs_force_pic_disabled_impl(env, target): | |
| link_action = link_action_subject.from_target(env, target) | |
| link_action.inputs().contains_predicate(matching.file_basename_equals("dep.nopic.a")) | |
| link_action.inputs().not_contains_predicate(matching.file_basename_equals("dep.pic.a")) | |
| def _test_pic_mode_prefers_pic_libs_force_pic_enabled(name, **kwargs): | |
| _create_prefers_pic_libs_dep_tree(name) | |
| cc_analysis_test( | |
| name = name, | |
| impl = _test_pic_mode_prefers_pic_libs_force_pic_enabled_impl, | |
| target = name + "/mybinary", | |
| test_features = [FEATURE_NAMES.supports_pic], | |
| config_settings = { | |
| "//command_line_option:force_pic": True, | |
| }, | |
| **kwargs | |
| ) | |
| def _test_pic_mode_prefers_pic_libs_force_pic_enabled_impl(env, target): | |
| link_action = link_action_subject.from_target(env, target) | |
| link_action.inputs().contains_predicate(matching.file_basename_equals("dep.pic.a")) | |
| link_action.inputs().not_contains_predicate(matching.file_basename_equals("dep.nopic.a")) | |
| def _test_pic_mode_uses_pic_libs(name, **kwargs): | |
| util.helper_target( | |
| cc_library, | |
| name = name + "/mylib", | |
| srcs = ["dep.pic.o"], | |
| ) | |
| util.helper_target( | |
| cc_binary, | |
| name = name + "/mybinary", | |
| srcs = ["mybinary.cc"], | |
| deps = [name + "/mylib"], | |
| ) | |
| cc_analysis_test( | |
| name = name, | |
| impl = _test_pic_mode_uses_pic_libs_impl, | |
| target = name + "/mybinary", | |
| test_features = [ | |
| FEATURE_NAMES.supports_pic, | |
| FEATURE_NAMES.supports_start_end_lib, | |
| ], | |
| config_settings = { | |
| "//command_line_option:force_pic": True, | |
| }, | |
| **kwargs | |
| ) | |
| def _test_pic_mode_uses_pic_libs_impl(env, target): | |
| link_action = link_action_subject.from_target(env, target) | |
| link_action.inputs().contains_predicate(matching.file_basename_equals("dep.pic.o")) | |
| def _create_does_not_use_nopic_library_dep_tree(name): | |
| util.helper_target( | |
| cc_library, | |
| name = name + "/mylib", | |
| srcs = ["dep.nopic.o"], | |
| ) | |
| util.helper_target( | |
| cc_binary, | |
| name = name + "/mybinary", | |
| srcs = ["mybinary.cc"], | |
| deps = [name + "/mylib"], | |
| ) | |
| def _test_pic_mode_does_not_use_nopic_library_force_pic_disabled(name, **kwargs): | |
| _create_does_not_use_nopic_library_dep_tree(name) | |
| cc_analysis_test( | |
| name = name, | |
| impl = _test_pic_mode_does_not_use_nopic_library_force_pic_disabled_impl, | |
| target = name + "/mybinary", | |
| test_features = [FEATURE_NAMES.supports_pic], | |
| config_settings = { | |
| "//command_line_option:force_pic": False, | |
| }, | |
| **kwargs | |
| ) | |
| def _test_pic_mode_does_not_use_nopic_library_force_pic_disabled_impl(env, target): | |
| link_action = link_action_subject.from_target(env, target) | |
| link_action.inputs().contains_predicate(matching.file_basename_equals("mybinary.pic.o")) | |
| link_action.inputs().not_contains_predicate(matching.file_basename_equals("dep.nopic.o")) | |
| def _test_pic_mode_does_not_use_nopic_library_force_pic_enabled(name, **kwargs): | |
| _create_does_not_use_nopic_library_dep_tree(name) | |
| cc_analysis_test( | |
| name = name, | |
| impl = _test_pic_mode_does_not_use_nopic_library_force_pic_enabled_impl, | |
| target = name + "/mybinary", | |
| test_features = [FEATURE_NAMES.supports_pic], | |
| config_settings = { | |
| "//command_line_option:force_pic": True, | |
| }, | |
| **kwargs | |
| ) | |
| def _test_pic_mode_does_not_use_nopic_library_force_pic_enabled_impl(env, target): | |
| link_action = link_action_subject.from_target(env, target) | |
| link_action.inputs().not_contains_predicate(matching.file_basename_equals("dep.nopic.o")) | |
| def _test_pic_mode_does_not_use_nopic_binary(name, **kwargs): | |
| util.helper_target( | |
| cc_binary, | |
| name = name + "/mybinary", | |
| srcs = ["xyz.nopic.o"], | |
| ) | |
| cc_analysis_test( | |
| name = name, | |
| impl = _test_pic_mode_does_not_use_nopic_binary_impl, | |
| target = name + "/mybinary", | |
| test_features = [FEATURE_NAMES.supports_pic], | |
| **kwargs | |
| ) | |
| def _test_pic_mode_does_not_use_nopic_binary_impl(env, target): | |
| link_action = link_action_subject.from_target(env, target) | |
| link_action.inputs().not_contains_predicate(matching.file_basename_equals("xyz.nopic.o")) | |
| def _setup_cc_runtimes_mock(): | |
| util.helper_target( | |
| mock_runtime_library, | |
| name = "runtime", | |
| ) | |
| util.helper_target( | |
| cc_runtimes_toolchain, | |
| name = "runtimes_toolchain", | |
| copts = ["-Iruntimes"], | |
| runtimes = [":runtime"], | |
| ) | |
| native.toolchain( | |
| name = "cc_runtimes_mock_toolchain", | |
| toolchain = ":runtimes_toolchain", | |
| toolchain_type = Label("@bazel_tools//tools/cpp:cc_runtimes_toolchain_type"), | |
| tags = ["manual", "notap"], | |
| ) | |
| def _register_link_staticness_test(name, target_under_test, expected_static, config_settings = {}, with_features = [], **kwargs): | |
| config_settings = dict( | |
| { | |
| # Apple builds do not support statically linked binaries so we force the target platform | |
| # to Linux. TODO: Do we want to test this separately for Windows targets? | |
| # Note: Already the previous Java tests set --cpu=k8 for these tests. | |
| "//command_line_option:platforms": [Label("//tests/cc/testutil:linux_x86_64")], | |
| }, | |
| **config_settings | |
| ) | |
| cc_analysis_test( | |
| name = name, | |
| impl = _link_staticness_test_impl, | |
| target = target_under_test, | |
| config_settings = config_settings, | |
| with_features = with_features, | |
| attrs = { | |
| "expected_static": attr.bool(), | |
| }, | |
| attr_values = { | |
| "expected_static": expected_static, | |
| }, | |
| **kwargs | |
| ) | |
| def _link_staticness_test_impl(env, target): | |
| _assert_link_staticness(env, target, env.ctx.attr.expected_static) | |
| def _create_link_staticness_dep_tree(name): | |
| util.helper_target( | |
| cc_library, | |
| name = name + "/dep", | |
| srcs = ["dep.cc"], | |
| ) | |
| util.helper_target( | |
| cc_binary, | |
| name = name + "/binary-static", | |
| srcs = ["binary.cc"], | |
| deps = [name + "/dep"], | |
| linkopts = ["-static"], | |
| ) | |
| util.helper_target( | |
| cc_test, | |
| name = name + "/test", | |
| srcs = ["binary.cc", "test.cc"], | |
| deps = [name + "/dep"], | |
| ) | |
| util.helper_target( | |
| cc_test, | |
| name = name + "/test-linkstatic", | |
| srcs = ["binary.cc", "test.cc"], | |
| deps = [name + "/dep"], | |
| linkstatic = 1, | |
| ) | |
| # Default Config Suite | |
| def _test_link_staticness_binary_static_dynamic_mode_default(name, **kwargs): | |
| _create_link_staticness_dep_tree(name) | |
| _register_link_staticness_test( | |
| name = name, | |
| target_under_test = name + "/binary-static", | |
| expected_static = True, | |
| config_settings = { | |
| "//command_line_option:dynamic_mode": "default", | |
| }, | |
| with_features = [FEATURE_NAMES.supports_pic, FEATURE_NAMES.supports_dynamic_linker], | |
| **kwargs | |
| ) | |
| def _test_link_staticness_hello_test_dynamic_mode_default(name, **kwargs): | |
| _create_link_staticness_dep_tree(name) | |
| _register_link_staticness_test( | |
| name = name, | |
| target_under_test = name + "/test", | |
| expected_static = False, | |
| config_settings = { | |
| "//command_line_option:dynamic_mode": "default", | |
| }, | |
| with_features = [FEATURE_NAMES.supports_pic, FEATURE_NAMES.supports_dynamic_linker], | |
| **kwargs | |
| ) | |
| def _test_link_staticness_hello_test_linkstatic_dynamic_mode_default(name, **kwargs): | |
| _create_link_staticness_dep_tree(name) | |
| _register_link_staticness_test( | |
| name = name, | |
| target_under_test = name + "/test-linkstatic", | |
| expected_static = True, | |
| config_settings = { | |
| "//command_line_option:dynamic_mode": "default", | |
| }, | |
| with_features = [FEATURE_NAMES.supports_pic, FEATURE_NAMES.supports_dynamic_linker], | |
| **kwargs | |
| ) | |
| # Off Config Suite | |
| def _test_link_staticness_binary_static_dynamic_mode_off(name, **kwargs): | |
| _create_link_staticness_dep_tree(name) | |
| _register_link_staticness_test( | |
| name = name, | |
| target_under_test = name + "/binary-static", | |
| expected_static = True, | |
| config_settings = { | |
| "//command_line_option:dynamic_mode": "off", | |
| }, | |
| with_features = [FEATURE_NAMES.supports_pic, FEATURE_NAMES.supports_dynamic_linker], | |
| **kwargs | |
| ) | |
| def _test_link_staticness_hello_test_dynamic_mode_off(name, **kwargs): | |
| _create_link_staticness_dep_tree(name) | |
| _register_link_staticness_test( | |
| name = name, | |
| target_under_test = name + "/test", | |
| expected_static = True, | |
| config_settings = { | |
| "//command_line_option:dynamic_mode": "off", | |
| }, | |
| with_features = [FEATURE_NAMES.supports_pic, FEATURE_NAMES.supports_dynamic_linker], | |
| **kwargs | |
| ) | |
| def _test_link_staticness_hello_test_linkstatic_dynamic_mode_off(name, **kwargs): | |
| _create_link_staticness_dep_tree(name) | |
| _register_link_staticness_test( | |
| name = name, | |
| target_under_test = name + "/test-linkstatic", | |
| expected_static = True, | |
| config_settings = { | |
| "//command_line_option:dynamic_mode": "off", | |
| }, | |
| with_features = [FEATURE_NAMES.supports_pic, FEATURE_NAMES.supports_dynamic_linker], | |
| **kwargs | |
| ) | |
| # Fully Config Suite | |
| def _test_link_staticness_binary_static_dynamic_mode_fully(name, **kwargs): | |
| _create_link_staticness_dep_tree(name) | |
| _register_link_staticness_test( | |
| name = name, | |
| target_under_test = name + "/binary-static", | |
| expected_static = False, | |
| config_settings = { | |
| "//command_line_option:dynamic_mode": "fully", | |
| }, | |
| with_features = [FEATURE_NAMES.supports_pic, FEATURE_NAMES.supports_dynamic_linker], | |
| **kwargs | |
| ) | |
| def _test_link_staticness_hello_test_dynamic_mode_fully(name, **kwargs): | |
| _create_link_staticness_dep_tree(name) | |
| _register_link_staticness_test( | |
| name = name, | |
| target_under_test = name + "/test", | |
| expected_static = False, | |
| config_settings = { | |
| "//command_line_option:dynamic_mode": "fully", | |
| }, | |
| with_features = [FEATURE_NAMES.supports_pic, FEATURE_NAMES.supports_dynamic_linker], | |
| **kwargs | |
| ) | |
| def _test_link_staticness_hello_test_linkstatic_dynamic_mode_fully(name, **kwargs): | |
| _create_link_staticness_dep_tree(name) | |
| _register_link_staticness_test( | |
| name = name, | |
| target_under_test = name + "/test-linkstatic", | |
| expected_static = False, | |
| config_settings = { | |
| "//command_line_option:dynamic_mode": "fully", | |
| }, | |
| with_features = [FEATURE_NAMES.supports_pic, FEATURE_NAMES.supports_dynamic_linker], | |
| **kwargs | |
| ) | |
| def _create_linking_mode_features_dep_tree(name): | |
| util.helper_target( | |
| cc_binary, | |
| name = name + "/linkstatic_true", | |
| srcs = ["binary.cc"], | |
| ) | |
| util.helper_target( | |
| cc_binary, | |
| name = name + "/linkstatic_false", | |
| srcs = ["binary.cc"], | |
| linkstatic = 0, | |
| ) | |
| def _register_linking_mode_features_test(name, target_under_test, expected_mode, config_settings = {}, **kwargs): | |
| config_settings = dict( | |
| { | |
| # Windows does not support linking_mode features so we force the target platform to | |
| # Linux. TODO: Do we want to test this separately for Apple targets? | |
| "//command_line_option:platforms": [Label("//tests/cc/testutil:linux_x86_64")], | |
| }, | |
| **config_settings | |
| ) | |
| cc_analysis_test( | |
| name = name, | |
| impl = _linking_mode_features_test_impl, | |
| target = target_under_test, | |
| config_settings = config_settings, | |
| with_features = [ | |
| FEATURE_NAMES.static_linking_mode, | |
| FEATURE_NAMES.dynamic_linking_mode, | |
| FEATURE_NAMES.supports_dynamic_linker, | |
| ], | |
| attrs = { | |
| "expected_mode": attr.string(), | |
| }, | |
| attr_values = { | |
| "expected_mode": expected_mode, | |
| }, | |
| **kwargs | |
| ) | |
| def _linking_mode_features_test_impl(env, target): | |
| link_action = link_action_subject.from_target(env, target) | |
| link_action.env().get("linking_mode", factory = subjects.str).equals(env.ctx.attr.expected_mode) | |
| # Default Config | |
| def _test_linking_mode_features_true_default(name, **kwargs): | |
| _create_linking_mode_features_dep_tree(name) | |
| _register_linking_mode_features_test(name, name + "/linkstatic_true", "static", **kwargs) | |
| def _test_linking_mode_features_false_default(name, **kwargs): | |
| _create_linking_mode_features_dep_tree(name) | |
| _register_linking_mode_features_test(name, name + "/linkstatic_false", "dynamic", **kwargs) | |
| # Fully Config | |
| def _test_linking_mode_features_true_fully(name, **kwargs): | |
| _create_linking_mode_features_dep_tree(name) | |
| _register_linking_mode_features_test( | |
| name, | |
| name + "/linkstatic_true", | |
| "dynamic", | |
| config_settings = {"//command_line_option:dynamic_mode": "fully"}, | |
| **kwargs | |
| ) | |
| def _test_linking_mode_features_false_fully(name, **kwargs): | |
| _create_linking_mode_features_dep_tree(name) | |
| _register_linking_mode_features_test( | |
| name, | |
| name + "/linkstatic_false", | |
| "dynamic", | |
| config_settings = {"//command_line_option:dynamic_mode": "fully"}, | |
| **kwargs | |
| ) | |
| # Off Config | |
| def _test_linking_mode_features_true_off(name, **kwargs): | |
| _create_linking_mode_features_dep_tree(name) | |
| _register_linking_mode_features_test( | |
| name, | |
| name + "/linkstatic_true", | |
| "static", | |
| config_settings = {"//command_line_option:dynamic_mode": "off"}, | |
| **kwargs | |
| ) | |
| def _test_linking_mode_features_false_off(name, **kwargs): | |
| _create_linking_mode_features_dep_tree(name) | |
| _register_linking_mode_features_test( | |
| name, | |
| name + "/linkstatic_false", | |
| "static", | |
| config_settings = {"//command_line_option:dynamic_mode": "off"}, | |
| **kwargs | |
| ) | |
| # Regression test for b/157471662. | |
| def _test_link_shared_does_not_have_to_provide_extension(name, **kwargs): | |
| util.helper_target( | |
| cc_binary, | |
| name = name + "/foo", | |
| srcs = ["foo.cc"], | |
| linkshared = 1, | |
| ) | |
| cc_analysis_test( | |
| name = name, | |
| impl = _test_link_shared_does_not_have_to_provide_extension_impl, | |
| target = name + "/foo", | |
| **kwargs | |
| ) | |
| def _test_link_shared_does_not_have_to_provide_extension_impl(env, target): | |
| executable = target[DefaultInfo].files_to_run.executable | |
| env.expect.that_str(executable.basename).equals("libfoo.so") | |
| def _test_pdb_files(name, **kwargs): | |
| util.helper_target( | |
| cc_binary, | |
| name = name + "/bin.dll", | |
| ) | |
| cc_analysis_test( | |
| name = name, | |
| impl = _test_pdb_files_impl, | |
| target = name + "/bin.dll", | |
| test_features = [FEATURE_NAMES.generate_pdb_file], | |
| **kwargs | |
| ) | |
| def _test_pdb_files_impl(env, target): | |
| env.expect.that_target(target).output_group("pdb_file").contains_predicate( | |
| matching.file_basename_equals("bin.pdb"), | |
| ) | |
| # Even if there are no instrumented C++ files, a C++ binary must provide some form of coverage | |
| # support since this is assumed by other tooling. Specifically, lcov_merger. See b/269749859. | |
| # TODO(cmita): This doesn't seem reasonable; if nothing C++ is instrumented then we shouldn't | |
| # need this. | |
| def _test_coverage_support_always_provided(name, **kwargs): | |
| util.helper_target( | |
| cc_binary, | |
| name = name + "/main", | |
| srcs = ["main.cc"], | |
| ) | |
| cc_analysis_test( | |
| name = name, | |
| impl = _test_coverage_support_always_provided_impl, | |
| target = name + "/main", | |
| config_settings = { | |
| "//command_line_option:collect_code_coverage": "true", | |
| "//command_line_option:instrumentation_filter": "/unused", | |
| }, | |
| **kwargs | |
| ) | |
| def _test_coverage_support_always_provided_impl(env, target): | |
| target_subject = env.expect.that_target(target) | |
| target_subject.has_provider(InstrumentedFilesInfo) | |
| info_subject = target_subject.provider(InstrumentedFilesInfo) | |
| info_subject.metadata_files().contains_exactly([]) | |
| info_subject.instrumented_files().contains_exactly([]) | |
| info = info_subject.actual | |
| # TODO: Remove the hasattr conditions once all supported Bazel versions support these | |
| # InstrumentedFilesInfoApi methods. Expected: Bazel 10, Bazel 9.3, maybe Bazel 8.8. | |
| if hasattr(info, "get_coverage_environment"): | |
| coverage_env = env.expect.that_dict( | |
| info.get_coverage_environment(), | |
| meta = env.expect.meta.derive("coverage_environment"), | |
| ) | |
| coverage_env.contains_at_least({ | |
| "COVERAGE_GCOV_PATH": "/usr/bin/mock-gcov", | |
| "LLVM_COV": "/usr/bin/mock-llvm-cov", | |
| "LLVM_PROFDATA": "/usr/bin/mock-llvm-profdata", | |
| "GENERATE_LLVM_LCOV": "0", | |
| }) | |
| if hasattr(info, "get_coverage_support_files"): | |
| support_files = env.expect.that_collection( | |
| info.get_coverage_support_files().to_list(), | |
| expr = "coverage_support_files", | |
| ) | |
| support_files.contains_predicate( | |
| matching.file_basename_equals("coverage-file"), | |
| ) | |
| def _test_malloc_is_compile_time_dep(name, **kwargs): | |
| util.helper_target( | |
| cc_library, | |
| name = name + "/malloc", | |
| defines = ["foobar"], | |
| linkstatic = 1, | |
| ) | |
| util.helper_target( | |
| cc_binary, | |
| name = name + "/foo", | |
| srcs = ["foo.cc"], | |
| ) | |
| cc_analysis_test( | |
| name = name, | |
| impl = _test_malloc_is_compile_time_dep_impl, | |
| target = name + "/foo", | |
| config_settings = { | |
| "//command_line_option:custom_malloc": Label("//tests/cc/common:" + name + "/malloc"), | |
| }, | |
| **kwargs | |
| ) | |
| def _test_malloc_is_compile_time_dep_impl(env, target): | |
| compilation_outputs = target[OutputGroupInfo].compilation_outputs.to_list() | |
| env.expect.that_collection(compilation_outputs).has_size(1) | |
| compile_action = env.expect.that_target(target).action_generating(compilation_outputs[0].short_path) | |
| compile_action.argv().contains("-Dfoobar") | |
| def _test_custom_malloc_filegroup(name, **kwargs): | |
| util.helper_target( | |
| native.filegroup, | |
| name = name + "/custom_malloc", | |
| srcs = ["malloc.cc"], | |
| ) | |
| util.helper_target( | |
| cc_binary, | |
| name = name + "/bin", | |
| srcs = ["binary.cc"], | |
| ) | |
| cc_analysis_test( | |
| name = name, | |
| impl = _test_custom_malloc_filegroup_impl, | |
| target = name + "/bin", | |
| config_settings = { | |
| "//command_line_option:custom_malloc": Label("//tests/cc/common:" + name + "/custom_malloc"), | |
| }, | |
| **kwargs | |
| ) | |
| def _test_custom_malloc_filegroup_impl(env, target): # buildifier: disable=unused-variable | |
| pass | |
| def _test_pic_and_no_pic_gcno_files(name, **kwargs): | |
| util.helper_target( | |
| cc_binary, | |
| name = name + "/a", | |
| srcs = ["a.cc"], | |
| ) | |
| cc_analysis_test( | |
| name = name, | |
| impl = _test_pic_and_no_pic_gcno_files_impl, | |
| target = name + "/a", | |
| test_features = [FEATURE_NAMES.supports_pic], | |
| config_settings = { | |
| "//command_line_option:collect_code_coverage": "true", | |
| "//command_line_option:compilation_mode": "opt", | |
| }, | |
| **kwargs | |
| ) | |
| def _test_pic_and_no_pic_gcno_files_impl(env, target): | |
| target_subject = env.expect.that_target(target) | |
| target_subject.has_provider(InstrumentedFilesInfo) | |
| info_subject = target_subject.provider(InstrumentedFilesInfo) | |
| info_subject.metadata_files().contains_at_least_predicates([ | |
| matching.file_basename_equals("a.gcno"), | |
| matching.file_basename_equals("a.pic.gcno"), | |
| ]) | |
| def _test_cctoolchain_coverage_files(name, **kwargs): | |
| util.helper_target( | |
| cc_test, | |
| name = name + "/a", | |
| srcs = ["a.cc"], | |
| ) | |
| cc_analysis_test( | |
| name = name, | |
| impl = _test_cctoolchain_coverage_files_impl, | |
| target = name + "/a", | |
| config_settings = { | |
| "//command_line_option:collect_code_coverage": "true", | |
| }, | |
| **kwargs | |
| ) | |
| def _test_cctoolchain_coverage_files_impl(env, target): | |
| target_subject = env.expect.that_target(target) | |
| target_subject.has_provider(InstrumentedFilesInfo) | |
| info_subject = target_subject.provider(InstrumentedFilesInfo) | |
| # TODO: Remove the hasattr conditions once all supported Bazel versions support these | |
| # InstrumentedFilesInfoApi methods. Expected: Bazel 10, Bazel 9.3, maybe Bazel 8.8. | |
| if hasattr(info_subject.actual, "get_coverage_support_files"): | |
| support_files = env.expect.that_collection( | |
| info_subject.actual.get_coverage_support_files().to_list(), | |
| expr = "coverage_support_files", | |
| ) | |
| support_files.contains_exactly_predicates([ | |
| matching.file_basename_equals("coverage-file"), | |
| ]) | |
| def _test_thin_lto(name, **kwargs): | |
| util.helper_target( | |
| cc_binary, | |
| name = name + "/hello", | |
| srcs = ["hello.cc"], | |
| ) | |
| cc_analysis_test( | |
| name = name, | |
| impl = _test_thin_lto_impl, | |
| target = name + "/hello", | |
| test_features = ["thin_lto", "supports_start_end_lib"], | |
| **kwargs | |
| ) | |
| def _test_thin_lto_impl(env, target): | |
| actions = target[TestingAspectInfo].actions | |
| compile_actions = [a for a in actions if a.mnemonic == "CppCompile"] | |
| thin_lto_compile_actions = [a for a in compile_actions if "-flto=thin" in a.argv] | |
| env.expect.that_collection(thin_lto_compile_actions).is_not_empty() | |
| lto_indexing_actions = [a for a in actions if a.mnemonic == "CppLTOIndexing"] | |
| env.expect.that_collection(lto_indexing_actions).has_size(1) | |
| lto_backend_actions = [a for a in actions if a.mnemonic == "CcLtoBackendCompile"] | |
| env.expect.that_collection(lto_backend_actions).is_not_empty() | |
| def _test_thin_lto_disabled(name, **kwargs): | |
| util.helper_target( | |
| cc_binary, | |
| name = name + "/hello", | |
| srcs = ["hello.cc"], | |
| ) | |
| cc_analysis_test( | |
| name = name, | |
| impl = _test_thin_lto_disabled_impl, | |
| target = name + "/hello", | |
| with_features = ["thin_lto", "supports_start_end_lib"], | |
| test_features = ["-thin_lto", "supports_start_end_lib"], | |
| **kwargs | |
| ) | |
| def _test_thin_lto_disabled_impl(env, target): | |
| actions = target[TestingAspectInfo].actions | |
| compile_actions = [a for a in actions if a.mnemonic == "CppCompile"] | |
| env.expect.that_collection(compile_actions).is_not_empty() | |
| thin_lto_compile_actions = [a for a in compile_actions if "-flto=thin" in a.argv] | |
| env.expect.that_collection(thin_lto_compile_actions).is_empty() | |
| lto_indexing_actions = [a for a in actions if a.mnemonic == "CppLTOIndexing"] | |
| env.expect.that_collection(lto_indexing_actions).is_empty() | |
| lto_backend_actions = [a for a in actions if a.mnemonic == "CcLtoBackendCompile"] | |
| env.expect.that_collection(lto_backend_actions).is_empty() | |
| def cc_binary_configured_target_tests(name): | |
| """Creates the test suite for cc_binary tests. | |
| Args: | |
| name: The name of the test suite. | |
| """ | |
| tests = [ | |
| _test_files_to_build, | |
| _test_headers_not_passed_to_linking_action, | |
| _test_no_duplicate_linkopts, | |
| _test_action_graph, | |
| _test_runtime_dynamic_libraries_copy_behavior, | |
| _test_pic, | |
| _test_duplicate_linkopts, | |
| _test_unsupported_src_file, | |
| _test_missing_action_config_for_strip_is_a_rule_error, | |
| _test_linkopts_diamond, | |
| _test_linkopts_fake_diamond, | |
| _test_app_linking_static, | |
| _test_app_linking_dynamic, | |
| _test_so_in_srcs, | |
| _test_transitive_libs_are_collected, | |
| _test_transitive_linkstamps_are_collected, | |
| _test_go_code_comes_after_deps, | |
| _test_additional_linker_inputs, | |
| _test_conflicting_linkstamps, | |
| _test_compilation_prerequisites_in_output_group, | |
| _test_pic_mode_prefers_pic_libs_force_pic_disabled, | |
| _test_pic_mode_prefers_pic_libs_force_pic_enabled, | |
| _test_pic_mode_uses_pic_libs, | |
| _test_pic_mode_does_not_use_nopic_library_force_pic_disabled, | |
| _test_pic_mode_does_not_use_nopic_library_force_pic_enabled, | |
| _test_pic_mode_does_not_use_nopic_binary, | |
| _test_ignore_custom_malloc, | |
| _test_custom_malloc, | |
| _test_link_shared_does_not_have_to_provide_extension, | |
| _test_pdb_files, | |
| _test_coverage_support_always_provided, | |
| _test_malloc_is_compile_time_dep, | |
| _test_custom_malloc_filegroup, | |
| _test_pic_and_no_pic_gcno_files, | |
| _test_cctoolchain_coverage_files, | |
| _test_thin_lto, | |
| _test_thin_lto_disabled, | |
| ] | |
| # sanitize_pwd is implemented in Starlark in rules_cc, requires Bazel 9+. | |
| if bazel_features.cc.cc_common_is_in_rules_cc: | |
| _setup_cc_runtimes_mock() | |
| tests.extend([ | |
| _test_sanitize_pwd_feature_enabled, | |
| _test_sanitize_pwd_feature_disabled, | |
| _test_sanitize_pwd_macos_no_pwd, | |
| _test_external_include_paths_reclassifies_external_quote_includes, # copybara-uncomment-this-please | |
| _test_system_include_paths_reclassifies_local_includes_after_includes, | |
| _test_system_include_paths_reclassifies_local_includes_without_propagation, | |
| _test_generated_def_file_uses_toolchain_action, # copybara-uncomment-this-please | |
| _test_generated_def_file_uses_default_tool, # copybara-uncomment-this-please | |
| _test_linker_toolchain_feature, | |
| _test_link_staticness_binary_static_dynamic_mode_default, | |
| _test_link_staticness_hello_test_dynamic_mode_default, | |
| _test_link_staticness_hello_test_linkstatic_dynamic_mode_default, | |
| _test_link_staticness_binary_static_dynamic_mode_off, | |
| _test_link_staticness_hello_test_dynamic_mode_off, | |
| _test_link_staticness_hello_test_linkstatic_dynamic_mode_off, | |
| _test_link_staticness_binary_static_dynamic_mode_fully, | |
| _test_link_staticness_hello_test_dynamic_mode_fully, | |
| _test_link_staticness_hello_test_linkstatic_dynamic_mode_fully, | |
| _test_linking_mode_features_true_default, | |
| _test_linking_mode_features_false_default, | |
| _test_linking_mode_features_true_fully, | |
| _test_linking_mode_features_false_fully, | |
| _test_linking_mode_features_true_off, | |
| _test_linking_mode_features_false_off, | |
| _test_cc_runtimes_added_to_libraries, | |
| ]) | |
| test_suite( | |
| name = name, | |
| tests = tests, | |
| ) |