| """Tests the compile actions for linkstamps.""" | |
| load("@bazel_features//:features.bzl", "bazel_features") | |
| load("@bazel_skylib//lib:paths.bzl", "paths") | |
| 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_library.bzl", "cc_library") | |
| load("//cc/common:cc_common.bzl", "cc_common") | |
| load("//cc/toolchains:fdo_profile.bzl", "fdo_profile") | |
| load("//tests/cc/testutil:cc_analysis_test.bzl", "cc_analysis_test") | |
| def _test_linkstamp_compile_options_for_executable(name, **kwargs): | |
| util.helper_target( | |
| cc_library, | |
| name = name + "/lib", | |
| srcs = ["lib.cc"], | |
| linkstamp = "ls.cc", | |
| ) | |
| util.helper_target( | |
| cc_binary, | |
| name = name + "/foo", | |
| deps = [name + "/lib"], | |
| ) | |
| cc_analysis_test( | |
| name = name, | |
| impl = _test_linkstamp_compile_options_for_executable_impl, | |
| targets = { | |
| "target": name + "/foo", | |
| "cc_toolchain": "//tests/cc/testutil/toolchains:current_cc_toolchain", | |
| }, | |
| **kwargs | |
| ) | |
| def _test_linkstamp_compile_options_for_executable_impl(env, targets): | |
| target = targets.target | |
| cc_toolchain_info = targets.cc_toolchain[cc_common.CcToolchainInfo] | |
| assert_linkstamp_action = env.expect.that_target(target).action_generating("{package}/{test_name}/_objs/foo/{package}/ls.o") | |
| assert_linkstamp_action.argv().contains_at_least([ | |
| "--sysroot={}".format(cc_toolchain_info.sysroot), | |
| "-include", | |
| "-DGPLATFORM=\"{}\"".format(cc_toolchain_info.toolchain_id), | |
| "-I.", | |
| "-DG3_BUILD_TARGET=\"{bindir}/{package}/{name}\"", | |
| ]) | |
| assert_linkstamp_action.argv().contains_predicate( | |
| matching.str_matches("-DG3_TARGET_NAME=\"*//{}:{}".format(target.label.package, target.label.name)), | |
| ) | |
| assert_linkstamp_action.argv().not_contains_predicate( | |
| matching.str_matches("-DBUILD_FDO_TYPE"), | |
| ) | |
| def _test_linkstamp_compile_options_for_shared_library(name, **kwargs): | |
| util.helper_target( | |
| cc_library, | |
| name = name + "/lib", | |
| srcs = ["lib.cc"], | |
| linkstamp = "ls.cc", | |
| ) | |
| util.helper_target( | |
| cc_binary, | |
| name = name + "/foo", | |
| deps = [name + "/lib"], | |
| linkshared = True, | |
| ) | |
| cc_analysis_test( | |
| name = name, | |
| impl = _test_linkstamp_compile_options_for_shared_library_impl, | |
| targets = { | |
| "target": name + "/foo", | |
| "cc_toolchain": "//tests/cc/testutil/toolchains:current_cc_toolchain", | |
| }, | |
| **kwargs | |
| ) | |
| def _test_linkstamp_compile_options_for_shared_library_impl(env, targets): | |
| target = targets.target | |
| cc_toolchain_info = targets.cc_toolchain[cc_common.CcToolchainInfo] | |
| libfoo_so_name = paths.dirname(target.label.name) + "/libfoo.so" | |
| assert_linkstamp_action = env.expect.that_target(target).action_generating("{package}/{test_name}/_objs/libfoo.so/{package}/ls.o") | |
| assert_linkstamp_action.argv().contains_at_least([ | |
| "--sysroot={}".format(cc_toolchain_info.sysroot), | |
| "-include", | |
| "-DGPLATFORM=\"{}\"".format(cc_toolchain_info.toolchain_id), | |
| "-I.", | |
| "-DG3_BUILD_TARGET=\"{bindir}/{package}/" + libfoo_so_name + "\"", | |
| ]) | |
| assert_linkstamp_action.argv().contains_predicate( | |
| matching.str_matches("-DG3_TARGET_NAME=\"*//{}:{}".format(target.label.package, target.label.name)), | |
| ) | |
| assert_linkstamp_action.argv().not_contains_predicate( | |
| matching.str_matches("-DBUILD_FDO_TYPE"), | |
| ) | |
| def _test_linkstamp_compile_pic(name, **kwargs): | |
| util.helper_target( | |
| cc_library, | |
| name = name + "/lib", | |
| srcs = ["lib.cc"], | |
| linkstamp = "ls.cc", | |
| ) | |
| util.helper_target( | |
| cc_binary, | |
| name = name + "/foo", | |
| deps = [name + "/lib"], | |
| ) | |
| cc_analysis_test( | |
| name = name, | |
| impl = _test_linkstamp_compile_pic_impl, | |
| target = name + "/foo", | |
| config_settings = { | |
| "//command_line_option:force_pic": True, | |
| }, | |
| **kwargs | |
| ) | |
| def _test_linkstamp_compile_pic_impl(env, target): | |
| assert_linkstamp_action = env.expect.that_target(target).action_generating("{package}/{test_name}/_objs/foo/{package}/ls.o") | |
| assert_linkstamp_action.argv().contains("-fPIC") | |
| def _test_linkstamp_compile_fdo(name, **kwargs): | |
| util.helper_target( | |
| cc_library, | |
| name = name + "/lib", | |
| srcs = ["lib.cc"], | |
| linkstamp = "ls.cc", | |
| ) | |
| util.helper_target( | |
| cc_binary, | |
| name = name + "/foo", | |
| deps = [name + "/lib"], | |
| ) | |
| cc_analysis_test( | |
| name = name, | |
| impl = _test_linkstamp_compile_fdo_impl, | |
| target = name + "/foo", | |
| config_settings = { | |
| "//command_line_option:fdo_instrument": "foo", | |
| }, | |
| **kwargs | |
| ) | |
| def _test_linkstamp_compile_fdo_impl(env, target): | |
| assert_linkstamp_action = env.expect.that_target(target).action_generating("{package}/{test_name}/_objs/foo/{package}/ls.o") | |
| assert_linkstamp_action.argv().contains("-DBUILD_FDO_TYPE=\"FDO\"") | |
| # Regression test for b/73447914 - Linkstamps were not re-built when only | |
| # volatile data changed - they were not recompiled after changing a cc_binary | |
| # source resulting in old timestamps. | |
| # Assert that the relevant compilation outputs from a cc_binary are added as | |
| # inputs to the linkstamp action to ensure the action is invalidated whenever | |
| # any cc_binary inputs change. | |
| def _test_linkstamp_compile_cc_binary_deps(name, **kwargs): | |
| util.helper_target( | |
| cc_library, | |
| name = name + "/lib", | |
| srcs = ["lib.cc"], | |
| linkstamp = "ls.cc", | |
| ) | |
| util.helper_target( | |
| cc_binary, | |
| name = name + "/foo", | |
| srcs = ["foo.cc"], | |
| deps = [name + "/lib"], | |
| ) | |
| cc_analysis_test( | |
| name = name, | |
| impl = _test_linkstamp_compile_cc_binary_deps_impl, | |
| target = name + "/foo", | |
| **kwargs | |
| ) | |
| def _test_linkstamp_compile_cc_binary_deps_impl(env, target): | |
| assert_linkstamp_action = env.expect.that_target(target).action_generating("{package}/{test_name}/_objs/foo/{package}/ls.o") | |
| assert_linkstamp_action.inputs().contains_at_least([ | |
| "{package}/_objs/{name}/foo.o", | |
| "{package}/{test_name}/liblib.a", | |
| ]) | |
| def _test_linkstamp_compile_gets_copts_from_options(name, **kwargs): | |
| util.helper_target( | |
| cc_library, | |
| name = name + "/lib", | |
| srcs = ["lib.cc"], | |
| copts = ["-copt_from_cc_library"], | |
| linkstamp = "ls.cc", | |
| ) | |
| util.helper_target( | |
| cc_binary, | |
| name = name + "/foo", | |
| copts = ["-copt_from_cc_binary"], | |
| deps = [name + "/lib"], | |
| ) | |
| cc_analysis_test( | |
| name = name, | |
| impl = _test_linkstamp_compile_gets_copts_from_options_impl, | |
| target = name + "/foo", | |
| config_settings = { | |
| "//command_line_option:copt": ["-copt_from_config"], | |
| }, | |
| **kwargs | |
| ) | |
| def _test_linkstamp_compile_gets_copts_from_options_impl(env, target): | |
| assert_linkstamp_action = env.expect.that_target(target).action_generating("{package}/{test_name}/_objs/foo/{package}/ls.o") | |
| assert_linkstamp_action.argv().contains( | |
| "-copt_from_config", | |
| ) | |
| assert_linkstamp_action.argv().contains_none_of([ | |
| "-copt_from_cc_library", | |
| "-copt_from_cc_binary", | |
| ]) | |
| def _test_linkstamp_compile_ignores_copts_from_attributes(name, **kwargs): | |
| util.helper_target( | |
| cc_library, | |
| name = name + "/lib", | |
| srcs = ["lib.cc"], | |
| copts = ["-copt_from_cc_library"], | |
| linkstamp = "ls.cc", | |
| ) | |
| util.helper_target( | |
| cc_binary, | |
| name = name + "/foo", | |
| copts = ["-copt_from_cc_binary"], | |
| deps = [name + "/lib"], | |
| ) | |
| cc_analysis_test( | |
| name = name, | |
| impl = _test_linkstamp_compile_ignores_copts_from_attributes_impl, | |
| target = name + "/foo", | |
| **kwargs | |
| ) | |
| def _test_linkstamp_compile_ignores_copts_from_attributes_impl(env, target): | |
| assert_linkstamp_action = env.expect.that_target(target).action_generating("{package}/{test_name}/_objs/foo/{package}/ls.o") | |
| assert_linkstamp_action.argv().contains_none_of([ | |
| "-copt_from_cc_library", | |
| "-copt_from_cc_binary", | |
| ]) | |
| def _test_linkstamp_compile_uses_memprof(name, **kwargs): | |
| util.helper_target( | |
| fdo_profile, | |
| name = name + "/prof", | |
| profile = "out.afdo", | |
| memprof_profile = "memprof.zip", | |
| changelist = "12345", | |
| ) | |
| util.helper_target( | |
| cc_library, | |
| name = name + "/lib", | |
| srcs = ["lib.cc"], | |
| linkstamp = "ls.cc", | |
| ) | |
| util.helper_target( | |
| cc_binary, | |
| name = name + "/foo", | |
| deps = [name + "/lib"], | |
| ) | |
| cc_analysis_test( | |
| name = name, | |
| impl = _test_linkstamp_compile_uses_memprof_impl, | |
| target = name + "/foo", | |
| config_settings = { | |
| "//command_line_option:compilation_mode": "opt", | |
| # buildifier: disable=canonical-repository | |
| "//command_line_option:fdo_profile": "@@//" + native.package_name() + ":" + name + "/prof", | |
| }, | |
| test_features = [ | |
| "memprof_optimize", | |
| ], | |
| **kwargs | |
| ) | |
| def _test_linkstamp_compile_uses_memprof_impl(env, target): | |
| assert_linkstamp_action = env.expect.that_target(target).action_generating("{package}/{test_name}/_objs/foo/{package}/ls.o") | |
| assert_linkstamp_action.argv().contains("-DBUILD_PGHO_TYPE=\"opt\"") | |
| assert_linkstamp_action.argv().contains("-DBUILD_MEMPROF_PROFILE_CHANGELIST=12345") | |
| assert_linkstamp_action.argv().contains("-DBUILD_FDO_PROFILE_CHANGELIST=12345") | |
| def cc_linkstamp_compile_tests(name): | |
| tests = [ | |
| _test_linkstamp_compile_options_for_executable, | |
| _test_linkstamp_compile_options_for_shared_library, | |
| _test_linkstamp_compile_pic, | |
| _test_linkstamp_compile_fdo, | |
| _test_linkstamp_compile_cc_binary_deps, | |
| _test_linkstamp_compile_gets_copts_from_options, | |
| _test_linkstamp_compile_ignores_copts_from_attributes, | |
| ] | |
| # TODO(cmita): This is overly restrictive - the requirement is for the memprof_profile attribute (Bazel 8) | |
| if bazel_features.cc.cc_common_is_in_rules_cc: | |
| tests.extend([ | |
| _test_linkstamp_compile_uses_memprof, | |
| ]) | |
| test_suite( | |
| name = name, | |
| tests = tests, | |
| ) |