| """Tests for cc_binary with ThinLTO.""" |
| |
| load("@bazel_features//:features.bzl", "bazel_features") |
| load("@rules_testing//lib:analysis_test.bzl", "test_suite") |
| load("@rules_testing//lib:truth.bzl", "matching", "subjects") |
| load("@rules_testing//lib:util.bzl", "TestingAspectInfo", "util") |
| load("//cc:cc_binary.bzl", _actual_cc_binary = "cc_binary") |
| load("//cc:cc_library.bzl", "cc_library") |
| load("//cc:cc_test.bzl", _actual_cc_test = "cc_test") |
| load("//cc/toolchains:fdo_prefetch_hints.bzl", "fdo_prefetch_hints") |
| load("//cc/toolchains:fdo_profile.bzl", "fdo_profile") |
| load("//cc/toolchains:propeller_optimize.bzl", "propeller_optimize") |
| load("//tests/cc/testutil:cc_analysis_test.bzl", "cc_analysis_test") |
| load("//tests/cc/testutil:cc_binary_target_subject.bzl", "cc_binary_target_subject") |
| |
| # Wrap cc_binary to mock out common dependencies. |
| def cc_binary(name, **kwargs): |
| if "malloc" not in kwargs: |
| 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: |
| kwargs["malloc"] = "//tests/cc/testutil/toolchains:mock_malloc" |
| _actual_cc_test( |
| name = name, |
| **kwargs |
| ) |
| |
| def _test_thin_lto_action_graph(name, **kwargs): |
| util.helper_target( |
| cc_library, |
| name = name + "/lib", |
| srcs = ["bye.cc"], |
| hdrs = ["bye.h"], |
| linkstamp = "linkstamp.cc", |
| ) |
| util.helper_target( |
| cc_binary, |
| name = name + "/bin", |
| srcs = ["hello.cc"], |
| deps = [":" + name + "/lib"], |
| ) |
| cc_analysis_test( |
| name = name, |
| impl = _test_thin_lto_action_graph_impl, |
| target = name + "/bin", |
| test_features = ["thin_lto", "supports_pic", "supports_start_end_lib"], |
| **kwargs |
| ) |
| |
| def _test_thin_lto_action_graph_impl(env, target): |
| package = target.label.package |
| name = target.label.name |
| bindir = target[TestingAspectInfo].bin_path |
| |
| test_name = name.split("/")[0] |
| lib_name = test_name + "/lib" |
| |
| binary_obj_path = "{package}/{name}.lto/{bindir}/{package}/_objs/{name}/hello.pic.o".format( |
| package = package, |
| name = name, |
| bindir = bindir, |
| ) |
| library_obj_path = "{package}/{name}.lto/{bindir}/{package}/_objs/{lib_name}/bye.pic.o".format( |
| package = package, |
| name = name, |
| bindir = bindir, |
| lib_name = lib_name, |
| ) |
| params_path = "{package}/{name}-lto-final.params".format( |
| package = package, |
| name = name, |
| ) |
| param_file_arg = "thinlto_param_file={bindir}/{params_path}".format( |
| bindir = bindir, |
| params_path = params_path, |
| ) |
| |
| binary_target = cc_binary_target_subject.from_target(env, target) |
| link_action = binary_target.action_generating("{package}/{name}{binary_extension}") |
| |
| link_action.inputs().contains(binary_obj_path) |
| link_action.inputs().contains(library_obj_path) |
| link_action.inputs().contains(params_path) |
| |
| # Check linkstamp |
| link_action.inputs().contains_predicate(matching.file_basename_contains("linkstamp")) |
| |
| # Check argv |
| link_action.argv().contains_at_least([ |
| "{bindir}/{package}/{name}.lto.merged.o".format(bindir = bindir, package = package, name = name), |
| param_file_arg, |
| ]).in_order() |
| |
| # Check that all our _objs args (except linkstamp) are in LTO dir |
| lto_dir = "{package}/{name}.lto".format(package = package, name = name) |
| objs_args = link_action.argv().transform( |
| desc = "object arguments", |
| filter = lambda arg: "_objs" in arg and "linkstamp" not in arg and package in arg, |
| ) |
| bad_args = objs_args.transform( |
| desc = "object arguments not using LTO paths", |
| filter = lambda arg: lto_dir not in arg, |
| ) |
| bad_args.is_empty() |
| |
| # Backend action |
| backend_action = env.expect.that_target(target).action_generating(binary_obj_path) |
| backend_action.mnemonic().equals("CcLtoBackendCompile") |
| backend_action.inputs().contains(binary_obj_path + ".thinlto.bc") |
| backend_action.inputs().contains(binary_obj_path + ".imports") |
| |
| thinlto_index_arg = "thinlto_index={bindir}/{package}/{name}.lto/{bindir}/{package}/_objs/{name}/hello.pic.o".format( |
| package = package, |
| name = name, |
| bindir = bindir, |
| ) + ".thinlto.bc" |
| thinlto_output_arg = "thinlto_output_object_file={bindir}/{package}/{name}.lto/{bindir}/{package}/_objs/{name}/hello.pic.o".format( |
| package = package, |
| name = name, |
| bindir = bindir, |
| ) |
| thinlto_input_arg = "thinlto_input_bitcode_file={bindir}/{package}/_objs/{name}/hello.pic.o".format( |
| package = package, |
| name = name, |
| bindir = bindir, |
| ) |
| backend_action.argv().contains_at_least([ |
| thinlto_index_arg, |
| thinlto_output_arg, |
| thinlto_input_arg, |
| ]) |
| |
| # Index action |
| index_action = env.expect.that_target(target).action_generating(binary_obj_path + ".thinlto.bc") |
| index_action.mnemonic().equals("CppLTOIndexing") |
| |
| # Linkstamp compile action should not be input to indexing |
| linkstamp_compile_action = env.expect.that_target(target).action_named("CppLinkstampCompile") |
| linkstamp_outputs = linkstamp_compile_action.actual.outputs.to_list() |
| index_action.inputs().contains_none_of(linkstamp_outputs) |
| |
| index_action.argv().not_contains( |
| param_file_arg, |
| ) |
| |
| index_outputs = env.expect.that_depset_of_files(index_action.actual.outputs) |
| index_outputs.contains(binary_obj_path + ".imports") |
| index_outputs.contains(binary_obj_path + ".thinlto.bc") |
| index_outputs.contains(library_obj_path + ".imports") |
| index_outputs.contains(library_obj_path + ".thinlto.bc") |
| index_outputs.contains(params_path) |
| |
| binary_indexing_obj = "{package}/_objs/{name}/hello.pic.indexing.o".format( |
| package = package, |
| name = name, |
| ) |
| library_indexing_obj = "{package}/_objs/{lib_name}/bye.pic.indexing.o".format( |
| package = package, |
| lib_name = lib_name, |
| ) |
| index_action.inputs().contains(binary_indexing_obj) |
| index_action.inputs().contains(library_indexing_obj) |
| |
| bitcode_action = env.expect.that_target(target).action_generating(binary_indexing_obj) |
| bitcode_action.mnemonic().equals("CppCompile") |
| bitcode_action.argv().contains( |
| "lto_indexing_bitcode={bindir}/{binary_indexing_obj}".format( |
| bindir = bindir, |
| binary_indexing_obj = binary_indexing_obj, |
| ), |
| ) |
| |
| def _test_thin_lto_linkshared(name, **kwargs): |
| util.helper_target( |
| cc_library, |
| name = name + "/lib", |
| srcs = ["bye.cc"], |
| hdrs = ["bye.h"], |
| ) |
| util.helper_target( |
| cc_binary, |
| name = name + "/bin.so", |
| srcs = ["hello.cc"], |
| deps = [":" + name + "/lib"], |
| linkshared = 1, |
| ) |
| cc_analysis_test( |
| name = name, |
| impl = _test_thin_lto_linkshared_impl, |
| target = name + "/bin.so", |
| test_features = ["thin_lto", "supports_pic", "supports_start_end_lib", "user_compile_flags"], |
| config_settings = { |
| "//command_line_option:linkopt": ["alinkopt"], |
| }, |
| **kwargs |
| ) |
| |
| def _test_thin_lto_linkshared_impl(env, target): |
| package = target.label.package |
| name = target.label.name |
| bindir = target[TestingAspectInfo].bin_path |
| |
| binary_obj_path = "{package}/{name}.lto/{bindir}/{package}/_objs/{name}/hello.pic.o".format( |
| package = package, |
| name = name, |
| bindir = bindir, |
| ) |
| |
| backend_action = env.expect.that_target(target).action_generating(binary_obj_path) |
| backend_action.mnemonic().equals("CcLtoBackendCompile") |
| backend_action.argv().not_contains("alinkopt") |
| |
| def _test_thin_lto_no_linkstatic(name, **kwargs): |
| util.helper_target( |
| cc_library, |
| name = name + "/lib", |
| srcs = ["bye.cc"], |
| hdrs = ["bye.h"], |
| ) |
| util.helper_target( |
| cc_binary, |
| name = name + "/bin", |
| srcs = ["hello.cc"], |
| deps = [":" + name + "/lib"], |
| linkstatic = 0, |
| ) |
| cc_analysis_test( |
| name = name, |
| impl = _test_thin_lto_no_linkstatic_impl, |
| targets = { |
| "bin": name + "/bin", |
| "lib": name + "/lib", |
| }, |
| test_features = [ |
| "thin_lto", |
| "supports_pic", |
| "supports_start_end_lib", |
| "supports_dynamic_linker", |
| "supports_interface_shared_libraries", |
| ], |
| **kwargs |
| ) |
| |
| def _test_thin_lto_no_linkstatic_impl(env, targets): |
| bin_target = targets.bin |
| lib_target = targets.lib |
| |
| package = bin_target.label.package |
| name = bin_target.label.name |
| bindir = bin_target[TestingAspectInfo].bin_path |
| |
| test_name = name.split("/")[0] |
| lib_target_name = test_name + "/lib" |
| |
| binary_target = cc_binary_target_subject.from_target(env, bin_target) |
| link_action = binary_target.action_generating("{package}/{name}{binary_extension}") |
| |
| # TODO(b/526555277): Propose enhancement to rules_testing to add transform/to_collection to DepsetFileSubject. |
| # Manually wrap inputs in CollectionSubject to use transform |
| link_inputs_collection = subjects.collection( |
| link_action.actual.inputs.to_list(), |
| link_action.meta.derive("inputs()"), |
| ) |
| solib_inputs = link_inputs_collection.transform( |
| desc = "solib inputs", |
| filter = lambda f: "_solib" in f.path and "linkstatic_Sliblib" in f.path, |
| ) |
| solib_inputs.has_size(1) |
| solib_file = solib_inputs.offset(0, subjects.file).actual |
| |
| lib_target_subject = env.expect.that_target(lib_target) |
| solib_action = lib_target_subject.action_generating(solib_file.short_path) |
| solib_action.mnemonic().is_in(["SolibSymlink", "Symlink"]) |
| |
| # The input to the solib symlink action is the library itself. |
| solib_action_inputs = solib_action.actual.inputs.to_list() |
| lib_file = solib_action_inputs[0] |
| |
| lib_link_action = lib_target_subject.action_generating(lib_file.short_path) |
| lib_link_action.mnemonic().equals("CppLink") |
| |
| # Construct library LTO paths |
| library_lto_dir = "{package}/{test_name}/liblib.so.lto".format( |
| package = package, |
| test_name = test_name, |
| ) |
| lib_obj_path = "{library_lto_dir}/{bindir}/{package}/_objs/{lib_target_name}/bye.pic.o".format( |
| library_lto_dir = library_lto_dir, |
| bindir = bindir, |
| package = package, |
| lib_target_name = lib_target_name, |
| ) |
| lib_params_path = "{package}/{test_name}/liblib.so-lto-final.params".format( |
| package = package, |
| test_name = test_name, |
| ) |
| binary_obj_path = "{package}/{name}.lto/{bindir}/{package}/_objs/{name}/hello.pic.o".format( |
| package = package, |
| name = name, |
| bindir = bindir, |
| ) |
| params_path = "{package}/{name}-lto-final.params".format( |
| package = package, |
| name = name, |
| ) |
| |
| # Binary link action assertions |
| link_action.inputs().contains(binary_obj_path) |
| link_action.inputs().contains(solib_file.short_path) |
| link_action.inputs().contains(params_path) |
| |
| # Check argv for binary link |
| link_action.argv().contains("-Wl,@{bindir}/{params_path}".format( |
| bindir = bindir, |
| params_path = params_path, |
| )) |
| |
| # Check that all our _objs args (except linkstamp) are in LTO dir |
| lto_dir = "{package}/{name}.lto".format(package = package, name = name) |
| objs_args = link_action.argv().transform( |
| desc = "object arguments", |
| filter = lambda arg: "_objs" in arg and "linkstamp" not in arg and package in arg, |
| ) |
| bad_args = objs_args.transform( |
| desc = "object arguments not using LTO paths", |
| filter = lambda arg: lto_dir not in arg, |
| ) |
| bad_args.is_empty() |
| |
| # Library LTO backend action |
| lib_backend_action = lib_target_subject.action_generating(lib_obj_path) |
| lib_backend_action.mnemonic().equals("CcLtoBackendCompile") |
| lib_backend_action.inputs().contains(lib_obj_path + ".thinlto.bc") |
| |
| # Library backend argv |
| lib_thinlto_index_arg = "thinlto_index={bindir}/{lib_obj_path}.thinlto.bc".format( |
| bindir = bindir, |
| lib_obj_path = lib_obj_path, |
| ) |
| lib_thinlto_output_arg = "thinlto_output_object_file={bindir}/{lib_obj_path}".format( |
| bindir = bindir, |
| lib_obj_path = lib_obj_path, |
| ) |
| lib_thinlto_input_arg = "thinlto_input_bitcode_file={bindir}/{package}/_objs/{lib_target_name}/bye.pic.o".format( |
| bindir = bindir, |
| package = package, |
| lib_target_name = lib_target_name, |
| ) |
| lib_backend_action.argv().contains_at_least([ |
| lib_thinlto_index_arg, |
| lib_thinlto_output_arg, |
| lib_thinlto_input_arg, |
| ]) |
| |
| # Library Index action |
| lib_index_action = lib_target_subject.action_generating(lib_obj_path + ".thinlto.bc") |
| lib_index_action.mnemonic().equals("CppLTOIndexing") |
| |
| lib_index_outputs = env.expect.that_depset_of_files(lib_index_action.actual.outputs) |
| lib_index_outputs.contains(lib_obj_path + ".imports") |
| lib_index_outputs.contains(lib_obj_path + ".thinlto.bc") |
| lib_index_outputs.contains(lib_params_path) |
| |
| lib_indexing_obj = "{package}/_objs/{lib_target_name}/bye.pic.indexing.o".format( |
| package = package, |
| lib_target_name = lib_target_name, |
| ) |
| lib_index_action.inputs().contains(lib_indexing_obj) |
| |
| # Library bitcode action |
| lib_bitcode_action = lib_target_subject.action_generating(lib_indexing_obj) |
| lib_bitcode_action.mnemonic().equals("CppCompile") |
| lib_bitcode_action.argv().contains( |
| "lto_indexing_bitcode={bindir}/{lib_indexing_obj}".format( |
| bindir = bindir, |
| lib_indexing_obj = lib_indexing_obj, |
| ), |
| ) |
| |
| def _test_thin_lto_backend_env(name, **kwargs): |
| util.helper_target( |
| cc_library, |
| name = name + "/lib", |
| srcs = ["bye.cc"], |
| hdrs = ["bye.h"], |
| ) |
| util.helper_target( |
| cc_binary, |
| name = name + "/bin", |
| srcs = ["hello.cc"], |
| deps = [":" + name + "/lib"], |
| ) |
| cc_analysis_test( |
| name = name, |
| impl = _test_thin_lto_backend_env_impl, |
| target = name + "/bin", |
| test_features = ["thin_lto", "supports_pic", "supports_start_end_lib", "env_feature", "static_env_feature", "module_maps"], |
| **kwargs |
| ) |
| |
| def _test_thin_lto_backend_env_impl(env, target): |
| package = target.label.package |
| name = target.label.name |
| bindir = target[TestingAspectInfo].bin_path |
| |
| binary_obj_path = "{package}/{name}.lto/{bindir}/{package}/_objs/{name}/hello.pic.o".format( |
| package = package, |
| name = name, |
| bindir = bindir, |
| ) |
| |
| backend_action = env.expect.that_target(target).action_generating(binary_obj_path) |
| backend_action.mnemonic().equals("CcLtoBackendCompile") |
| backend_action.env().contains_at_least({"cat": "meow"}) |
| |
| def _test_thin_lto_fission(name, **kwargs): |
| util.helper_target( |
| cc_library, |
| name = name + "/lib", |
| srcs = ["bye.cc"], |
| hdrs = ["bye.h"], |
| ) |
| util.helper_target( |
| cc_binary, |
| name = name + "/bin", |
| srcs = ["hello.cc"], |
| deps = [":" + name + "/lib"], |
| ) |
| cc_analysis_test( |
| name = name, |
| impl = _test_thin_lto_fission_impl, |
| target = name + "/bin", |
| test_features = ["thin_lto", "supports_pic", "supports_start_end_lib", "per_object_debug_info"], |
| config_settings = { |
| "//command_line_option:fission": ["yes"], |
| "//command_line_option:copt": ["-g0"], |
| }, |
| **kwargs |
| ) |
| |
| def _test_thin_lto_fission_impl(env, target): |
| package = target.label.package |
| name = target.label.name |
| bindir = target[TestingAspectInfo].bin_path |
| |
| test_name = name.split("/")[0] |
| lib_target_name = test_name + "/lib" |
| |
| # Binary LTO backend |
| binary_obj_path = "{package}/{name}.lto/{bindir}/{package}/_objs/{name}/hello.pic.o".format( |
| package = package, |
| name = name, |
| bindir = bindir, |
| ) |
| binary_dwo_path = "{package}/{name}.lto/{bindir}/{package}/_objs/{name}/hello.pic.dwo".format( |
| package = package, |
| name = name, |
| bindir = bindir, |
| ) |
| |
| backend_action = env.expect.that_target(target).action_generating(binary_obj_path) |
| backend_action.mnemonic().equals("CcLtoBackendCompile") |
| |
| backend_outputs = env.expect.that_depset_of_files(backend_action.actual.outputs) |
| backend_outputs.contains_exactly([binary_obj_path, binary_dwo_path]) |
| backend_action.argv().contains_at_least(["-g0", "per_object_debug_info_option"]) |
| |
| # Library LTO backend (static linking, so in binary's LTO dir) |
| lib_obj_path = "{package}/{name}.lto/{bindir}/{package}/_objs/{lib_target_name}/bye.pic.o".format( |
| package = package, |
| name = name, |
| bindir = bindir, |
| lib_target_name = lib_target_name, |
| ) |
| lib_dwo_path = "{package}/{name}.lto/{bindir}/{package}/_objs/{lib_target_name}/bye.pic.dwo".format( |
| package = package, |
| name = name, |
| bindir = bindir, |
| lib_target_name = lib_target_name, |
| ) |
| |
| lib_backend_action = env.expect.that_target(target).action_generating(lib_obj_path) |
| lib_backend_action.mnemonic().equals("CcLtoBackendCompile") |
| |
| lib_backend_outputs = env.expect.that_depset_of_files(lib_backend_action.actual.outputs) |
| lib_backend_outputs.contains_exactly([lib_obj_path, lib_dwo_path]) |
| lib_backend_action.argv().contains("per_object_debug_info_option") |
| |
| # DWP action |
| dwp_file_path = "{package}/{name}.dwp".format( |
| package = package, |
| name = name, |
| ) |
| dwp_action = env.expect.that_target(target).action_generating(dwp_file_path) |
| dwp_action.mnemonic().equals("CcGenerateDwp") |
| |
| dwp_inputs = dwp_action.actual.inputs.to_list() |
| inter_dwps = [f for f in dwp_inputs if f.extension == "dwp"] |
| _verify_dwos_in_dwp(env, dwp_action, [target], ["hello.pic.dwo", "bye.pic.dwo"]) |
| |
| # Verify final DWP action arguments |
| if inter_dwps: |
| some_inter_dwp_arg = "{bindir}/{package}/_dwps/{package}/{name}-1.dwp".format( |
| bindir = bindir, |
| package = package, |
| name = name, |
| ) |
| dwp_action.argv().contains(some_inter_dwp_arg) |
| else: |
| dwp_action.argv().contains("{bindir}/{binary_dwo_path}".format(bindir = bindir, binary_dwo_path = binary_dwo_path)) |
| dwp_action.argv().contains("{bindir}/{lib_dwo_path}".format(bindir = bindir, lib_dwo_path = lib_dwo_path)) |
| |
| dwp_action.argv().contains_at_least(["-o", "{bindir}/{dwp_file_path}".format(bindir = bindir, dwp_file_path = dwp_file_path)]).in_order() |
| |
| def _test_thin_lto_no_linkstatic_fission(name, **kwargs): |
| util.helper_target( |
| cc_library, |
| name = name + "/lib", |
| srcs = ["bye.cc"], |
| hdrs = ["bye.h"], |
| ) |
| util.helper_target( |
| cc_binary, |
| name = name + "/bin", |
| srcs = ["hello.cc"], |
| deps = [":" + name + "/lib"], |
| linkstatic = 0, |
| ) |
| cc_analysis_test( |
| name = name, |
| impl = _test_thin_lto_no_linkstatic_fission_impl, |
| targets = { |
| "bin": name + "/bin", |
| "lib": name + "/lib", |
| }, |
| test_features = [ |
| "thin_lto", |
| "supports_pic", |
| "supports_start_end_lib", |
| "supports_dynamic_linker", |
| "supports_interface_shared_libraries", |
| "per_object_debug_info", |
| ], |
| config_settings = { |
| "//command_line_option:fission": ["yes"], |
| }, |
| **kwargs |
| ) |
| |
| def _test_thin_lto_no_linkstatic_fission_impl(env, targets): |
| bin_target = targets.bin |
| lib_target = targets.lib |
| |
| package = bin_target.label.package |
| name = bin_target.label.name |
| bindir = bin_target[TestingAspectInfo].bin_path |
| |
| test_name = name.split("/")[0] |
| lib_target_name = test_name + "/lib" |
| |
| # Library LTO backend |
| library_lto_dir = "{package}/{test_name}/liblib.so.lto".format( |
| package = package, |
| test_name = test_name, |
| ) |
| lib_obj_path = "{library_lto_dir}/{bindir}/{package}/_objs/{lib_target_name}/bye.pic.o".format( |
| library_lto_dir = library_lto_dir, |
| bindir = bindir, |
| package = package, |
| lib_target_name = lib_target_name, |
| ) |
| lib_dwo_path = "{library_lto_dir}/{bindir}/{package}/_objs/{lib_target_name}/bye.pic.dwo".format( |
| library_lto_dir = library_lto_dir, |
| bindir = bindir, |
| package = package, |
| lib_target_name = lib_target_name, |
| ) |
| |
| lib_target_subject = env.expect.that_target(lib_target) |
| lib_backend_action = lib_target_subject.action_generating(lib_obj_path) |
| lib_backend_action.mnemonic().equals("CcLtoBackendCompile") |
| |
| lib_backend_outputs = env.expect.that_depset_of_files(lib_backend_action.actual.outputs) |
| lib_backend_outputs.contains_exactly([lib_obj_path, lib_dwo_path]) |
| |
| # Binary LTO backend |
| binary_obj_path = "{package}/{name}.lto/{bindir}/{package}/_objs/{name}/hello.pic.o".format( |
| package = package, |
| name = name, |
| bindir = bindir, |
| ) |
| binary_dwo_path = "{package}/{name}.lto/{bindir}/{package}/_objs/{name}/hello.pic.dwo".format( |
| package = package, |
| name = name, |
| bindir = bindir, |
| ) |
| binary_backend_action = env.expect.that_target(bin_target).action_generating(binary_obj_path) |
| binary_backend_outputs = env.expect.that_depset_of_files(binary_backend_action.actual.outputs) |
| binary_backend_outputs.contains_exactly([binary_obj_path, binary_dwo_path]) |
| |
| # DWP action |
| dwp_file_path = "{package}/{name}.dwp".format( |
| package = package, |
| name = name, |
| ) |
| dwp_action = env.expect.that_target(bin_target).action_generating(dwp_file_path) |
| dwp_action.mnemonic().equals("CcGenerateDwp") |
| |
| # Assert binary dwo is input, but library dwo is NOT |
| dwp_action.inputs().contains(binary_dwo_path) |
| dwp_action.inputs().not_contains(lib_dwo_path) |
| |
| # Assert argv |
| binary_dwo_arg = "{bindir}/{binary_dwo_path}".format(bindir = bindir, binary_dwo_path = binary_dwo_path) |
| lib_dwo_arg = "{bindir}/{lib_dwo_path}".format(bindir = bindir, lib_dwo_path = lib_dwo_path) |
| |
| dwp_action.argv().contains(binary_dwo_arg) |
| dwp_action.argv().not_contains(lib_dwo_arg) |
| dwp_action.argv().contains_at_least(["-o", "{bindir}/{dwp_file_path}".format(bindir = bindir, dwp_file_path = dwp_file_path)]).in_order() |
| |
| def _test_thin_lto_linkstatic_cc_test_fission(name, **kwargs): |
| util.helper_target( |
| cc_library, |
| name = name + "/lib", |
| srcs = ["bye.cc"], |
| hdrs = ["bye.h"], |
| linkstamp = "linkstamp.cc", |
| ) |
| util.helper_target( |
| cc_test, |
| name = name + "/bin_test", |
| srcs = ["hello.cc"], |
| deps = [":" + name + "/lib"], |
| linkstatic = 1, |
| ) |
| cc_analysis_test( |
| name = name, |
| impl = _test_thin_lto_linkstatic_cc_test_fission_impl, |
| targets = { |
| "bin": name + "/bin_test", |
| "lib": name + "/lib", |
| }, |
| test_features = [ |
| "thin_lto", |
| "supports_pic", |
| "supports_start_end_lib", |
| "per_object_debug_info", |
| "thin_lto_linkstatic_tests_use_shared_nonlto_backends", |
| ], |
| config_settings = { |
| "//command_line_option:fission": ["yes"], |
| }, |
| **kwargs |
| ) |
| |
| def _test_thin_lto_linkstatic_cc_test_fission_impl(env, targets): |
| bin_target = targets.bin |
| lib_target = targets.lib |
| |
| package = bin_target.label.package |
| name = bin_target.label.name |
| bindir = bin_target[TestingAspectInfo].bin_path |
| |
| test_name = name.split("/")[0] |
| lib_target_name = test_name + "/lib" |
| |
| # All backends should be shared non-LTO in this case. |
| binary_obj_path = "shared.nonlto/{bindir}/{package}/_objs/{name}/hello.pic.o".format( |
| bindir = bindir, |
| package = package, |
| name = name, |
| ) |
| binary_dwo_path = "shared.nonlto/{bindir}/{package}/_objs/{name}/hello.pic.dwo".format( |
| bindir = bindir, |
| package = package, |
| name = name, |
| ) |
| |
| backend_action = env.expect.that_target(bin_target).action_generating(binary_obj_path) |
| backend_action.mnemonic().equals("CcLtoBackendCompile") |
| |
| backend_outputs = env.expect.that_depset_of_files(backend_action.actual.outputs) |
| backend_outputs.contains_exactly([binary_obj_path, binary_dwo_path]) |
| backend_action.argv().contains("per_object_debug_info_option") |
| |
| # Library backend |
| lib_obj_path = "shared.nonlto/{bindir}/{package}/_objs/{lib_target_name}/bye.pic.o".format( |
| bindir = bindir, |
| package = package, |
| lib_target_name = lib_target_name, |
| ) |
| lib_dwo_path = "shared.nonlto/{bindir}/{package}/_objs/{lib_target_name}/bye.pic.dwo".format( |
| bindir = bindir, |
| package = package, |
| lib_target_name = lib_target_name, |
| ) |
| |
| # Query from lib_target instead of bin_target |
| lib_backend_action = env.expect.that_target(lib_target).action_generating(lib_obj_path) |
| lib_backend_action.mnemonic().equals("CcLtoBackendCompile") |
| lib_backend_action.argv().contains("-fPIC") |
| |
| lib_backend_outputs = env.expect.that_depset_of_files(lib_backend_action.actual.outputs) |
| lib_backend_outputs.contains_exactly([lib_obj_path, lib_dwo_path]) |
| lib_backend_action.argv().contains("per_object_debug_info_option") |
| |
| # DWP action |
| dwp_file_path = "{package}/{name}.dwp".format( |
| package = package, |
| name = name, |
| ) |
| dwp_action = env.expect.that_target(bin_target).action_generating(dwp_file_path) |
| dwp_action.mnemonic().equals("CcGenerateDwp") |
| |
| dwp_inputs = dwp_action.actual.inputs.to_list() |
| inter_dwps = [f for f in dwp_inputs if f.extension == "dwp"] |
| |
| # We need to search actions in both bin and lib targets because the library's |
| # DWP action (or intermediate DWP actions) might be registered on lib? |
| # Actually, intermediate DWP actions for the binary's DWP are created by the binary. |
| # So they should be on bin_target. |
| # But let's check. |
| _verify_dwos_in_dwp(env, dwp_action, [bin_target, lib_target], ["hello.pic.dwo", "bye.pic.dwo"]) |
| |
| # Verify final DWP action arguments |
| if inter_dwps: |
| some_inter_dwp_arg = "{bindir}/{package}/_dwps/{package}/{name}-1.dwp".format( |
| bindir = bindir, |
| package = package, |
| name = name, |
| ) |
| dwp_action.argv().contains(some_inter_dwp_arg) |
| else: |
| dwp_action.argv().contains("{bindir}/{binary_dwo_path}".format(bindir = bindir, binary_dwo_path = binary_dwo_path)) |
| dwp_action.argv().contains("{bindir}/{lib_dwo_path}".format(bindir = bindir, lib_dwo_path = lib_dwo_path)) |
| |
| dwp_action.argv().contains_at_least(["-o", "{bindir}/{dwp_file_path}".format(bindir = bindir, dwp_file_path = dwp_file_path)]).in_order() |
| |
| def _find_action(targets, short_path): |
| for t in targets: |
| if TestingAspectInfo in t: |
| for action in t[TestingAspectInfo].actions: |
| for output in action.outputs.to_list(): |
| if output.short_path == short_path: |
| return action |
| return None |
| |
| def _verify_dwos_in_dwp(env, dwp_action, targets, expected_dwos): |
| dwo_found = {dwo: False for dwo in expected_dwos} |
| |
| dwp_inputs = dwp_action.actual.inputs.to_list() |
| inter_dwps = [f for f in dwp_inputs if f.extension == "dwp"] |
| |
| if inter_dwps: |
| for inter_file in inter_dwps: |
| action = _find_action(targets, inter_file.short_path) |
| if action: |
| inputs = action.inputs.to_list() |
| for f in inputs: |
| for dwo in expected_dwos: |
| if dwo in f.path: |
| dwo_found[dwo] = True |
| else: |
| for f in dwp_inputs: |
| for dwo in expected_dwos: |
| if dwo in f.path: |
| dwo_found[dwo] = True |
| |
| expected_dict = {dwo: True for dwo in expected_dwos} |
| env.expect.that_dict(dwo_found).contains_exactly(expected_dict) |
| |
| def _test_linkstatic_cc_test(name, **kwargs): |
| util.helper_target( |
| cc_library, |
| name = name + "/lib", |
| srcs = ["bye.cc"], |
| hdrs = ["bye.h"], |
| linkstamp = "linkstamp.cc", |
| ) |
| util.helper_target( |
| cc_test, |
| name = name + "/bin_test", |
| srcs = ["hello.cc"], |
| deps = [":" + name + "/lib"], |
| linkstatic = 1, |
| ) |
| util.helper_target( |
| cc_test, |
| name = name + "/bin_test2", |
| srcs = ["hello.cc"], |
| deps = [":" + name + "/lib"], |
| linkstatic = 1, |
| ) |
| cc_analysis_test( |
| name = name, |
| impl = _test_linkstatic_cc_test_impl, |
| targets = { |
| "bin1": name + "/bin_test", |
| "bin2": name + "/bin_test2", |
| "lib": name + "/lib", |
| }, |
| test_features = [ |
| "thin_lto", |
| "supports_pic", |
| "supports_start_end_lib", |
| "thin_lto_linkstatic_tests_use_shared_nonlto_backends", |
| "per_object_debug_info", |
| "user_compile_flags", |
| ], |
| config_settings = { |
| "//command_line_option:linkopt": ["alinkopt"], |
| }, |
| **kwargs |
| ) |
| |
| def _test_linkstatic_cc_test_impl(env, targets): |
| bin1_target = targets.bin1 |
| bin2_target = targets.bin2 |
| lib_target = targets.lib |
| |
| package = bin1_target.label.package |
| bin1_name = bin1_target.label.name |
| bin2_name = bin2_target.label.name |
| lib_name = lib_target.label.name |
| bindir = bin1_target[TestingAspectInfo].bin_path |
| |
| lib_obj_path = "shared.nonlto/{bindir}/{package}/_objs/{lib_target_name}/bye.pic.o".format( |
| bindir = bindir, |
| package = package, |
| lib_target_name = lib_name, |
| ) |
| |
| bin1_obj_path = "shared.nonlto/{bindir}/{package}/_objs/{bin1_target_name}/hello.pic.o".format( |
| bindir = bindir, |
| package = package, |
| bin1_target_name = bin1_name, |
| ) |
| |
| bin1_backend_action = env.expect.that_target(bin1_target).action_generating(bin1_obj_path) |
| bin1_backend_action.mnemonic().equals("CcLtoBackendCompile") |
| bin1_backend_action.argv().not_contains("alinkopt") |
| |
| lib_backend_action = env.expect.that_target(lib_target).action_generating(lib_obj_path) |
| lib_backend_action.mnemonic().equals("CcLtoBackendCompile") |
| lib_backend_action.argv().contains("-fPIC") |
| lib_backend_action.argv().not_contains("alinkopt") |
| |
| bin1_subject = cc_binary_target_subject.from_target(env, bin1_target) |
| bin1_executable = "{package}/{name}".format(package = package, name = bin1_name) |
| bin1_link_action = bin1_subject.action_generating(bin1_executable) |
| bin1_link_action.inputs().contains(lib_obj_path) |
| |
| bin2_subject = cc_binary_target_subject.from_target(env, bin2_target) |
| bin2_executable = "{package}/{name}".format(package = package, name = bin2_name) |
| bin2_link_action = bin2_subject.action_generating(bin2_executable) |
| bin2_link_action.inputs().contains(lib_obj_path) |
| |
| def _test_test_only_target(name, **kwargs): |
| util.helper_target( |
| cc_binary, |
| name = name + "/bin", |
| srcs = ["hello.cc"], |
| testonly = 1, |
| ) |
| cc_analysis_test( |
| name = name, |
| impl = _test_test_only_target_impl, |
| target = name + "/bin", |
| test_features = [ |
| "thin_lto", |
| "supports_pic", |
| "supports_start_end_lib", |
| "thin_lto_linkstatic_tests_use_shared_nonlto_backends", |
| "user_compile_flags", |
| ], |
| config_settings = { |
| "//command_line_option:linkopt": ["alinkopt"], |
| }, |
| **kwargs |
| ) |
| |
| def _test_test_only_target_impl(env, target): |
| package = target.label.package |
| name = target.label.name |
| bindir = target[TestingAspectInfo].bin_path |
| |
| obj_path = "shared.nonlto/{bindir}/{package}/_objs/{name}/hello.pic.o".format( |
| bindir = bindir, |
| package = package, |
| name = name, |
| ) |
| |
| backend_action = env.expect.that_target(target).action_generating(obj_path) |
| backend_action.mnemonic().equals("CcLtoBackendCompile") |
| backend_action.argv().not_contains("alinkopt") |
| |
| def _test_use_shared_all_linkstatic(name, **kwargs): |
| util.helper_target( |
| cc_binary, |
| name = name + "/bin", |
| srcs = ["hello.cc"], |
| ) |
| cc_analysis_test( |
| name = name, |
| impl = _test_use_shared_all_linkstatic_impl, |
| target = name + "/bin", |
| test_features = [ |
| "thin_lto", |
| "supports_pic", |
| "supports_start_end_lib", |
| "thin_lto_all_linkstatic_use_shared_nonlto_backends", |
| "user_compile_flags", |
| ], |
| config_settings = { |
| "//command_line_option:linkopt": ["alinkopt"], |
| }, |
| **kwargs |
| ) |
| |
| def _test_use_shared_all_linkstatic_impl(env, target): |
| package = target.label.package |
| name = target.label.name |
| bindir = target[TestingAspectInfo].bin_path |
| |
| obj_path = "shared.nonlto/{bindir}/{package}/_objs/{name}/hello.pic.o".format( |
| bindir = bindir, |
| package = package, |
| name = name, |
| ) |
| |
| backend_action = env.expect.that_target(target).action_generating(obj_path) |
| backend_action.mnemonic().equals("CcLtoBackendCompile") |
| backend_action.argv().not_contains("alinkopt") |
| |
| def _test_assembler_source(name, **kwargs): |
| util.helper_target( |
| cc_library, |
| name = name + "/lib", |
| srcs = [ |
| "bye.cc", |
| name + "_tracing.S", |
| ], |
| hdrs = ["bye.h"], |
| ) |
| util.helper_target( |
| cc_binary, |
| name = name + "/bin", |
| srcs = ["hello.cc"], |
| deps = [":" + name + "/lib"], |
| ) |
| cc_analysis_test( |
| name = name, |
| impl = _test_assembler_source_impl, |
| targets = { |
| "bin": name + "/bin", |
| "lib": name + "/lib", |
| }, |
| test_features = ["thin_lto", "supports_pic", "supports_start_end_lib"], |
| **kwargs |
| ) |
| |
| def _test_assembler_source_impl(env, targets): |
| bin_target = targets.bin |
| lib_target = targets.lib |
| |
| package = bin_target.label.package |
| name = bin_target.label.name |
| |
| test_name = name.split("/")[0] |
| lib_target_name = test_name + "/lib" |
| s_file_name = test_name + "_tracing" |
| |
| obj_path = "{package}/_objs/{lib_target_name}/{s_file_name}.pic.o".format( |
| package = package, |
| lib_target_name = lib_target_name, |
| s_file_name = s_file_name, |
| ) |
| |
| compile_action = env.expect.that_target(lib_target).action_generating(obj_path) |
| compile_action.mnemonic().equals("CppCompile") |
| |
| binary_target = cc_binary_target_subject.from_target(env, bin_target) |
| link_action = binary_target.action_generating("{package}/{name}{binary_extension}") |
| link_action.inputs().contains(obj_path) |
| |
| def _test_assembler_source_with_shared_nonlto_backends(name, **kwargs): |
| # The assembler source (.S file) is compiled to a native object, not bitcode. |
| # This forces the library to contain at least one non-bitcode object, which |
| # triggers the LTO indexing code path for non-bitcode objects when |
| # include_link_static_in_lto_indexing is false. |
| s_file = util.empty_file(name + "_tracing.S") |
| util.helper_target( |
| cc_library, |
| name = name + "/lib", |
| srcs = ["bye.cc", s_file], |
| hdrs = ["bye.h"], |
| ) |
| util.helper_target( |
| cc_binary, |
| name = name + "/bin", |
| srcs = ["hello.cc"], |
| deps = [":" + name + "/lib"], |
| ) |
| cc_analysis_test( |
| name = name, |
| impl = _test_assembler_source_impl, |
| targets = { |
| "bin": name + "/bin", |
| "lib": name + "/lib", |
| }, |
| test_features = [ |
| "thin_lto", |
| "supports_pic", |
| "supports_start_end_lib", |
| "thin_lto_all_linkstatic_use_shared_nonlto_backends", |
| ], |
| **kwargs |
| ) |
| |
| def _test_duplicated_static_libraries_in_lto(name, **kwargs): |
| # The static library file (.a) is precompiled. |
| lib_file = util.empty_file(name + "_static.a") |
| |
| util.helper_target( |
| cc_library, |
| name = name + "/lib1", |
| srcs = [lib_file], |
| ) |
| util.helper_target( |
| cc_library, |
| name = name + "/lib2", |
| srcs = [lib_file], |
| ) |
| util.helper_target( |
| cc_binary, |
| name = name + "/bin", |
| srcs = ["hello.cc"], |
| deps = [ |
| ":" + name + "/lib1", |
| ":" + name + "/lib2", |
| ], |
| ) |
| cc_analysis_test( |
| name = name, |
| impl = _test_duplicated_static_libraries_in_lto_impl, |
| target = name + "/bin", |
| test_features = ["thin_lto", "supports_pic", "supports_start_end_lib"], |
| **kwargs |
| ) |
| |
| def _test_duplicated_static_libraries_in_lto_impl(env, target): |
| package = target.label.package |
| name = target.label.name |
| |
| test_name = name.split("/")[0] |
| lib_file_path = "{package}/{test_name}_static.a".format( |
| package = package, |
| test_name = test_name, |
| ) |
| |
| binary_target = cc_binary_target_subject.from_target(env, target) |
| link_action = binary_target.action_generating("{package}/{name}{binary_extension}") |
| |
| # Verify that the static library is an input to the link action. |
| link_action.inputs().contains(lib_file_path) |
| |
| # Make sure we don't choke on a cc_library without sources and therefore, without bitcode files. |
| def _test_no_source_files(name, **kwargs): |
| util.helper_target( |
| cc_library, |
| name = name + "/lib", |
| srcs = [name + "_static.a"], |
| ) |
| util.helper_target( |
| cc_binary, |
| name = name + "/bin", |
| srcs = ["hello.cc"], |
| deps = [":" + name + "/lib"], |
| ) |
| cc_analysis_test( |
| name = name, |
| impl = _test_no_source_files_impl, |
| target = name + "/bin", |
| test_features = ["thin_lto", "supports_pic", "supports_start_end_lib"], |
| **kwargs |
| ) |
| |
| def _test_no_source_files_impl(env, target): |
| env.expect.that_str(target.label.name).ends_with("bin") |
| |
| def _test_fdo_instrument(name, **kwargs): |
| util.helper_target( |
| cc_binary, |
| name = name + "/bin", |
| srcs = ["hello.cc"], |
| ) |
| cc_analysis_test( |
| name = name, |
| impl = _test_fdo_instrument_impl, |
| target = name + "/bin", |
| test_features = ["thin_lto", "supports_pic", "supports_start_end_lib"], |
| with_features = ["thin_lto", "supports_pic", "supports_start_end_lib", "fdo_instrument"], |
| config_settings = { |
| "//command_line_option:fdo_instrument": "profiles", |
| }, |
| **kwargs |
| ) |
| |
| def _test_fdo_instrument_impl(env, target): |
| package = target.label.package |
| name = target.label.name |
| bindir = target[TestingAspectInfo].bin_path |
| |
| obj_path = "{package}/{name}.lto/{bindir}/{package}/_objs/{name}/hello.pic.o".format( |
| package = package, |
| name = name, |
| bindir = bindir, |
| ) |
| |
| backend_action = env.expect.that_target(target).action_generating(obj_path) |
| backend_action.mnemonic().equals("CcLtoBackendCompile") |
| |
| # If the LtoBackendAction incorrectly tries to add the fdo_instrument |
| # feature, we will fail with an "unknown variable 'fdo_instrument_path'" |
| # error. But let's also explicitly confirm that the fdo_instrument |
| # option didn't end up here. |
| backend_action.argv().not_contains("fdo_instrument_option") |
| |
| def _create_thin_lto_basic_targets(name): |
| util.helper_target( |
| cc_library, |
| name = name + "/lib", |
| srcs = ["libfile.cc"], |
| hdrs = ["libfile.h"], |
| linkstamp = "linkstamp.cc", |
| ) |
| util.helper_target( |
| cc_binary, |
| name = name + "/bin", |
| srcs = ["binfile.cc"], |
| deps = [":" + name + "/lib"], |
| ) |
| |
| def _test_lto_index_opt(name, **kwargs): |
| _create_thin_lto_basic_targets(name) |
| cc_analysis_test( |
| name = name, |
| impl = _test_lto_index_opt_impl, |
| target = name + "/bin", |
| test_features = ["thin_lto", "supports_pic", "supports_start_end_lib"], |
| config_settings = { |
| "//command_line_option:ltoindexopt": ["anltoindexopt"], |
| }, |
| **kwargs |
| ) |
| |
| def _test_lto_index_opt_impl(env, target): |
| package = target.label.package |
| name = target.label.name |
| bindir = target[TestingAspectInfo].bin_path |
| |
| binary_obj_path = "{package}/{name}.lto/{bindir}/{package}/_objs/{name}/binfile.pic.o".format( |
| package = package, |
| name = name, |
| bindir = bindir, |
| ) |
| |
| index_action = env.expect.that_target(target).action_generating(binary_obj_path + ".thinlto.bc") |
| index_action.mnemonic().equals("CppLTOIndexing") |
| index_action.argv().contains("anltoindexopt") |
| |
| def _test_lto_standalone_command_lines(name, **kwargs): |
| _create_thin_lto_basic_targets(name) |
| cc_analysis_test( |
| name = name, |
| impl = _test_lto_standalone_command_lines_impl, |
| target = name + "/bin", |
| test_features = ["thin_lto", "supports_pic", "supports_start_end_lib"], |
| config_settings = { |
| "//command_line_option:ltoindexopt": ["anltoindexopt"], |
| }, |
| **kwargs |
| ) |
| |
| def _test_lto_standalone_command_lines_impl(env, target): |
| package = target.label.package |
| name = target.label.name |
| bindir = target[TestingAspectInfo].bin_path |
| |
| binary_obj_path = "{package}/{name}.lto/{bindir}/{package}/_objs/{name}/binfile.pic.o".format( |
| package = package, |
| name = name, |
| bindir = bindir, |
| ) |
| |
| index_action = env.expect.that_target(target).action_generating(binary_obj_path + ".thinlto.bc") |
| index_action.mnemonic().equals("CppLTOIndexing") |
| index_action.argv().contains("--i_come_from_standalone_lto_index=anltoindexopt") |
| |
| def _test_copt(name, **kwargs): |
| _create_thin_lto_basic_targets(name) |
| cc_analysis_test( |
| name = name, |
| impl = _test_copt_impl, |
| target = name + "/bin", |
| test_features = ["thin_lto", "supports_pic", "supports_start_end_lib"], |
| config_settings = { |
| "//command_line_option:copt": ["acopt"], |
| }, |
| **kwargs |
| ) |
| |
| def _test_copt_impl(env, target): |
| package = target.label.package |
| name = target.label.name |
| bindir = target[TestingAspectInfo].bin_path |
| |
| binary_obj_path = "{package}/{name}.lto/{bindir}/{package}/_objs/{name}/binfile.pic.o".format( |
| package = package, |
| name = name, |
| bindir = bindir, |
| ) |
| |
| backend_action = env.expect.that_target(target).action_generating(binary_obj_path) |
| backend_action.mnemonic().equals("CcLtoBackendCompile") |
| backend_action.argv().contains("acopt") |
| |
| def _test_per_file_copt(name, **kwargs): |
| _create_thin_lto_basic_targets(name) |
| cc_analysis_test( |
| name = name, |
| impl = _test_per_file_copt_impl, |
| target = name + "/bin", |
| test_features = ["thin_lto", "supports_pic", "supports_start_end_lib"], |
| config_settings = { |
| "//command_line_option:per_file_copt": [ |
| "binfile\\.cc@copt1", |
| "libfile\\.cc@copt2", |
| ".*\\.cc,-binfile\\.cc@copt2", |
| ], |
| }, |
| **kwargs |
| ) |
| |
| def _test_per_file_copt_impl(env, target): |
| package = target.label.package |
| name = target.label.name |
| bindir = target[TestingAspectInfo].bin_path |
| |
| test_name = name.split("/")[0] |
| lib_target_name = test_name + "/lib" |
| |
| binary_obj_path = "{package}/{name}.lto/{bindir}/{package}/_objs/{name}/binfile.pic.o".format( |
| package = package, |
| name = name, |
| bindir = bindir, |
| ) |
| lib_obj_path = "{package}/{name}.lto/{bindir}/{package}/_objs/{lib_target_name}/libfile.pic.o".format( |
| package = package, |
| name = name, |
| bindir = bindir, |
| lib_target_name = lib_target_name, |
| ) |
| |
| bin_backend_action = env.expect.that_target(target).action_generating(binary_obj_path) |
| bin_backend_action.mnemonic().equals("CcLtoBackendCompile") |
| bin_backend_action.argv().contains("copt1") |
| bin_backend_action.argv().not_contains("copt2") |
| |
| lib_backend_action = env.expect.that_target(target).action_generating(lib_obj_path) |
| lib_backend_action.mnemonic().equals("CcLtoBackendCompile") |
| lib_backend_action.argv().contains("copt2") |
| lib_backend_action.argv().not_contains("copt1") |
| |
| def _test_lto_backend_opt(name, **kwargs): |
| _create_thin_lto_basic_targets(name) |
| cc_analysis_test( |
| name = name, |
| impl = _test_lto_backend_opt_impl, |
| target = name + "/bin", |
| test_features = ["thin_lto", "supports_pic", "supports_start_end_lib", "user_compile_flags"], |
| config_settings = { |
| "//command_line_option:ltobackendopt": ["anltobackendopt"], |
| "//command_line_option:linkopt": ["alinkopt"], |
| }, |
| **kwargs |
| ) |
| |
| def _test_lto_backend_opt_impl(env, target): |
| package = target.label.package |
| name = target.label.name |
| bindir = target[TestingAspectInfo].bin_path |
| |
| binary_obj_path = "{package}/{name}.lto/{bindir}/{package}/_objs/{name}/binfile.pic.o".format( |
| package = package, |
| name = name, |
| bindir = bindir, |
| ) |
| |
| backend_action = env.expect.that_target(target).action_generating(binary_obj_path) |
| backend_action.mnemonic().equals("CcLtoBackendCompile") |
| backend_action.argv().contains_at_least([ |
| "--default-compile-flag", |
| "anltobackendopt", |
| ]) |
| backend_action.argv().not_contains("alinkopt") |
| |
| def _test_per_file_lto_backend_opt(name, **kwargs): |
| _create_thin_lto_basic_targets(name) |
| cc_analysis_test( |
| name = name, |
| impl = _test_per_file_lto_backend_opt_impl, |
| target = name + "/bin", |
| test_features = ["thin_lto", "supports_pic", "supports_start_end_lib"], |
| config_settings = { |
| "//command_line_option:per_file_ltobackendopt": [ |
| "binfile\\.pic\\.o@ltobackendopt1", |
| ".*\\.o,-binfile\\.pic\\.o@ltobackendopt2", |
| ], |
| }, |
| **kwargs |
| ) |
| |
| def _test_per_file_lto_backend_opt_impl(env, target): |
| package = target.label.package |
| name = target.label.name |
| bindir = target[TestingAspectInfo].bin_path |
| |
| test_name = name.split("/")[0] |
| lib_target_name = test_name + "/lib" |
| |
| binary_obj_path = "{package}/{name}.lto/{bindir}/{package}/_objs/{name}/binfile.pic.o".format( |
| package = package, |
| name = name, |
| bindir = bindir, |
| ) |
| lib_obj_path = "{package}/{name}.lto/{bindir}/{package}/_objs/{lib_target_name}/libfile.pic.o".format( |
| package = package, |
| name = name, |
| bindir = bindir, |
| lib_target_name = lib_target_name, |
| ) |
| |
| bin_backend_action = env.expect.that_target(target).action_generating(binary_obj_path) |
| bin_backend_action.mnemonic().equals("CcLtoBackendCompile") |
| bin_backend_action.argv().contains("ltobackendopt1") |
| bin_backend_action.argv().not_contains("ltobackendopt2") |
| |
| lib_backend_action = env.expect.that_target(target).action_generating(lib_obj_path) |
| lib_backend_action.mnemonic().equals("CcLtoBackendCompile") |
| lib_backend_action.argv().contains("ltobackendopt2") |
| lib_backend_action.argv().not_contains("ltobackendopt1") |
| |
| def _test_link_opt(name, **kwargs): |
| _create_thin_lto_basic_targets(name) |
| cc_analysis_test( |
| name = name, |
| impl = _test_link_opt_impl, |
| target = name + "/bin", |
| test_features = ["thin_lto", "supports_pic", "supports_start_end_lib"], |
| config_settings = { |
| "//command_line_option:linkopt": ["alinkopt"], |
| }, |
| **kwargs |
| ) |
| |
| def _test_link_opt_impl(env, target): |
| package = target.label.package |
| name = target.label.name |
| bindir = target[TestingAspectInfo].bin_path |
| |
| binary_obj_path = "{package}/{name}.lto/{bindir}/{package}/_objs/{name}/binfile.pic.o".format( |
| package = package, |
| name = name, |
| bindir = bindir, |
| ) |
| |
| backend_action = env.expect.that_target(target).action_generating(binary_obj_path) |
| backend_action.mnemonic().equals("CcLtoBackendCompile") |
| backend_action.argv().not_contains("alinkopt") |
| |
| def _test_autofdo(name, **kwargs): |
| """Tests that ThinLTO is enabled for AFDO with LLVM when thin_lto feature is explicitly requested.""" |
| util.helper_target( |
| cc_binary, |
| name = name + "/bin", |
| srcs = ["binfile.cc"], |
| features = ["thin_lto"], |
| ) |
| cc_analysis_test( |
| name = name, |
| impl = _test_autofdo_impl, |
| target = name + "/bin", |
| test_features = ["thin_lto", "autofdo", "supports_start_end_lib"], |
| config_settings = { |
| "//command_line_option:fdo_optimize": "/pkg/profile.afdo", |
| "//command_line_option:compilation_mode": "opt", |
| }, |
| **kwargs |
| ) |
| |
| def _test_autofdo_impl(env, target): |
| binary_obj_path = "{package}/{name}.lto/{bindir}/{package}/_objs/{name}/binfile.o".format( |
| package = target.label.package, |
| name = target.label.name, |
| bindir = target[TestingAspectInfo].bin_path, |
| ) |
| |
| backend_action = env.expect.that_target(target).action_generating(binary_obj_path) |
| backend_action.mnemonic().equals("CcLtoBackendCompile") |
| backend_action.argv().contains_predicate(matching.str_matches("-fauto-profile=*profile.afdo")) |
| backend_action.inputs().contains_predicate(matching.file_basename_equals("profile.afdo")) |
| |
| def _make_lto_backend_disabled_test_impl(obj_name): |
| def impl(env, target): |
| binary_obj_path = "{package}/{name}.lto/{bindir}/{package}/_objs/{name}/{obj_name}".format( |
| package = target.label.package, |
| name = target.label.name, |
| bindir = target[TestingAspectInfo].bin_path, |
| obj_name = obj_name, |
| ) |
| |
| _expect_no_lto_backend_action(env, target, binary_obj_path) |
| |
| return impl |
| |
| def _expect_no_lto_backend_action(env, target, binary_obj_path): |
| found_actions = [] |
| for action in target[TestingAspectInfo].actions: |
| for output in action.outputs.to_list(): |
| if output.short_path == binary_obj_path: |
| found_actions.append(action) |
| break |
| env.expect.that_collection(found_actions, expr = "LTO backend action exists").is_empty() |
| |
| def _test_autofdo_no_implicit_thin_lto(name, **kwargs): |
| """Tests that ThinLTO is not enabled for AFDO with LLVM without --features=autofdo_implicit_thinlto.""" |
| util.helper_target( |
| cc_binary, |
| name = name + "/bin", |
| srcs = ["binfile.cc"], |
| ) |
| cc_analysis_test( |
| name = name, |
| impl = _make_lto_backend_disabled_test_impl("binfile.o"), |
| target = name + "/bin", |
| with_features = ["thin_lto", "autofdo", "enable_afdo_thinlto", "autofdo_implicit_thinlto", "supports_start_end_lib"], |
| test_features = [], |
| config_settings = { |
| "//command_line_option:fdo_optimize": "/pkg/profile.afdo", |
| "//command_line_option:compilation_mode": "opt", |
| }, |
| **kwargs |
| ) |
| |
| def _test_autofdo_implicit_thin_lto(name, **kwargs): |
| """Tests that --features=autofdo_implicit_thinlto enables ThinLTO for AFDO with LLVM.""" |
| util.helper_target( |
| cc_binary, |
| name = name + "/bin", |
| srcs = ["binfile.cc"], |
| ) |
| cc_analysis_test( |
| name = name, |
| impl = _test_autofdo_implicit_thin_lto_impl, |
| target = name + "/bin", |
| with_features = ["thin_lto", "autofdo", "enable_afdo_thinlto", "autofdo_implicit_thinlto", "supports_start_end_lib"], |
| test_features = ["autofdo_implicit_thinlto"], |
| config_settings = { |
| "//command_line_option:fdo_optimize": "/pkg/profile.afdo", |
| "//command_line_option:compilation_mode": "opt", |
| }, |
| **kwargs |
| ) |
| |
| def _test_autofdo_implicit_thin_lto_impl(env, target): |
| binary_obj_path = "{package}/{name}.lto/{bindir}/{package}/_objs/{name}/binfile.o".format( |
| package = target.label.package, |
| name = target.label.name, |
| bindir = target[TestingAspectInfo].bin_path, |
| ) |
| |
| backend_action = env.expect.that_target(target).action_generating(binary_obj_path) |
| backend_action.mnemonic().equals("CcLtoBackendCompile") |
| |
| def _test_autofdo_implicit_thin_lto_disabled_option(name, **kwargs): |
| """Tests that --features=-thin_lto overrides --features=autofdo_implicit_thinlto and prevents enabling ThinLTO for AFDO with LLVM.""" |
| util.helper_target( |
| cc_binary, |
| name = name + "/bin", |
| srcs = ["binfile.cc"], |
| ) |
| cc_analysis_test( |
| name = name, |
| impl = _make_lto_backend_disabled_test_impl("binfile.o"), |
| target = name + "/bin", |
| with_features = ["thin_lto", "autofdo", "enable_afdo_thinlto", "autofdo_implicit_thinlto", "supports_start_end_lib"], |
| test_features = ["autofdo_implicit_thinlto", "-thin_lto"], |
| config_settings = { |
| "//command_line_option:fdo_optimize": "/pkg/profile.afdo", |
| "//command_line_option:compilation_mode": "opt", |
| }, |
| **kwargs |
| ) |
| |
| def _test_autofdo_implicit_thin_lto_disabled_rule(name, **kwargs): |
| """Tests that features=[-thin_lto] in the build rule overrides --features=autofdo_implicit_thinlto and prevents enabling ThinLTO for AFDO with LLVM.""" |
| util.helper_target( |
| cc_binary, |
| name = name + "/bin", |
| srcs = ["binfile.cc"], |
| features = ["-thin_lto"], |
| ) |
| cc_analysis_test( |
| name = name, |
| impl = _make_lto_backend_disabled_test_impl("binfile.o"), |
| target = name + "/bin", |
| with_features = ["thin_lto", "autofdo", "enable_afdo_thinlto", "autofdo_implicit_thinlto", "supports_start_end_lib"], |
| test_features = ["autofdo_implicit_thinlto"], |
| config_settings = { |
| "//command_line_option:fdo_optimize": "/pkg/profile.afdo", |
| "//command_line_option:compilation_mode": "opt", |
| }, |
| **kwargs |
| ) |
| |
| def _test_autofdo_implicit_thin_lto_disabled_package(name, **kwargs): |
| """Tests that features=[-thin_lto] in the package overrides --features=autofdo_implicit_thinlto and prevents enabling ThinLTO for AFDO with LLVM.""" |
| cc_analysis_test( |
| name = name, |
| impl = _make_lto_backend_disabled_test_impl("empty.o"), |
| target = "//tests/cc/common/disabled_package:bin", |
| with_features = ["thin_lto", "autofdo", "enable_afdo_thinlto", "autofdo_implicit_thinlto", "supports_start_end_lib"], |
| test_features = ["autofdo_implicit_thinlto"], |
| config_settings = { |
| "//command_line_option:fdo_optimize": "/pkg/profile.afdo", |
| "//command_line_option:compilation_mode": "opt", |
| }, |
| **kwargs |
| ) |
| |
| def _test_fdo_no_implicit_thin_lto(name, **kwargs): |
| """Tests that ThinLTO is not enabled for FDO with LLVM without --features=fdo_implicit_thinlto.""" |
| util.helper_target( |
| cc_binary, |
| name = name + "/bin", |
| srcs = ["binfile.cc"], |
| ) |
| cc_analysis_test( |
| name = name, |
| impl = _make_lto_backend_disabled_test_impl("binfile.o"), |
| target = name + "/bin", |
| with_features = ["thin_lto", "fdo_optimize", "enable_fdo_thinlto", "fdo_implicit_thinlto", "supports_start_end_lib"], |
| test_features = [], |
| config_settings = { |
| "//command_line_option:fdo_optimize": "/pkg/profile.zip", |
| "//command_line_option:compilation_mode": "opt", |
| }, |
| **kwargs |
| ) |
| |
| def _test_fdo_implicit_thin_lto(name, **kwargs): |
| """Tests that --features=fdo_implicit_thinlto enables ThinLTO for FDO with LLVM.""" |
| util.helper_target( |
| cc_binary, |
| name = name + "/bin", |
| srcs = ["binfile.cc"], |
| ) |
| cc_analysis_test( |
| name = name, |
| impl = _test_fdo_implicit_thin_lto_impl, |
| target = name + "/bin", |
| with_features = ["thin_lto", "fdo_optimize", "enable_fdo_thinlto", "fdo_implicit_thinlto", "supports_start_end_lib"], |
| test_features = ["fdo_implicit_thinlto"], |
| config_settings = { |
| "//command_line_option:fdo_optimize": "/pkg/profile.zip", |
| "//command_line_option:compilation_mode": "opt", |
| }, |
| **kwargs |
| ) |
| |
| def _test_fdo_implicit_thin_lto_impl(env, target): |
| binary_obj_path = "{package}/{name}.lto/{bindir}/{package}/_objs/{name}/binfile.o".format( |
| package = target.label.package, |
| name = target.label.name, |
| bindir = target[TestingAspectInfo].bin_path, |
| ) |
| |
| backend_action = env.expect.that_target(target).action_generating(binary_obj_path) |
| backend_action.mnemonic().equals("CcLtoBackendCompile") |
| |
| def _test_fdo_implicit_thin_lto_disabled_option(name, **kwargs): |
| """ Tests that --features=-thin_lto overrides --features=fdo_implicit_thinlto and prevents enabling ThinLTO for FDO with LLVM.""" |
| util.helper_target( |
| cc_binary, |
| name = name + "/bin", |
| srcs = ["binfile.cc"], |
| ) |
| cc_analysis_test( |
| name = name, |
| impl = _make_lto_backend_disabled_test_impl("binfile.o"), |
| target = name + "/bin", |
| with_features = ["thin_lto", "fdo_optimize", "enable_fdo_thinlto", "fdo_implicit_thinlto", "supports_start_end_lib"], |
| test_features = ["fdo_implicit_thinlto", "-thin_lto"], |
| config_settings = { |
| "//command_line_option:fdo_optimize": "/pkg/profile.zip", |
| "//command_line_option:compilation_mode": "opt", |
| }, |
| **kwargs |
| ) |
| |
| def _test_fdo_implicit_thin_lto_disabled_rule(name, **kwargs): |
| """Tests that features=[-thin_lto] in the build rule overrides --features=fdo_implicit_thinlto and prevents enabling ThinLTO for FDO with LLVM.""" |
| util.helper_target( |
| cc_binary, |
| name = name + "/bin", |
| srcs = ["binfile.cc"], |
| features = ["-thin_lto"], |
| ) |
| cc_analysis_test( |
| name = name, |
| impl = _make_lto_backend_disabled_test_impl("binfile.o"), |
| target = name + "/bin", |
| with_features = ["thin_lto", "fdo_optimize", "enable_fdo_thinlto", "fdo_implicit_thinlto", "supports_start_end_lib"], |
| test_features = ["fdo_implicit_thinlto"], |
| config_settings = { |
| "//command_line_option:fdo_optimize": "/pkg/profile.zip", |
| "//command_line_option:compilation_mode": "opt", |
| }, |
| **kwargs |
| ) |
| |
| def _test_fdo_implicit_thin_lto_disabled_package(name, **kwargs): |
| """Tests that features=[-thin_lto] in the package overrides --features=fdo_implicit_thinlto and prevents enabling ThinLTO for FDO with LLVM.""" |
| cc_analysis_test( |
| name = name, |
| impl = _make_lto_backend_disabled_test_impl("empty.o"), |
| target = "//tests/cc/common/disabled_package_fdo:bin", |
| with_features = ["thin_lto", "fdo_optimize", "enable_fdo_thinlto", "fdo_implicit_thinlto", "supports_start_end_lib"], |
| test_features = ["fdo_implicit_thinlto"], |
| config_settings = { |
| "//command_line_option:fdo_optimize": "/pkg/profile.zip", |
| "//command_line_option:compilation_mode": "opt", |
| }, |
| **kwargs |
| ) |
| |
| def _test_xbinary_fdo_no_implicit_thin_lto(name, **kwargs): |
| """Tests that ThinLTO is not enabled for XFDO with LLVM without --features=xbinaryfdo_implicit_thinlto.""" |
| fdo_profile( |
| name = name + "/out.xfdo", |
| profile = "profiles.xfdo", |
| ) |
| util.helper_target( |
| cc_binary, |
| name = name + "/bin", |
| srcs = ["binfile.cc"], |
| ) |
| cc_analysis_test( |
| name = name, |
| impl = _make_lto_backend_disabled_test_impl("binfile.o"), |
| target = name + "/bin", |
| with_features = ["thin_lto", "xbinaryfdo", "enable_xbinaryfdo_thinlto", "xbinaryfdo_implicit_thinlto", "supports_start_end_lib"], |
| test_features = [], |
| config_settings = { |
| "//command_line_option:xbinary_fdo": Label(":" + name + "/out.xfdo"), |
| "//command_line_option:compilation_mode": "opt", |
| }, |
| **kwargs |
| ) |
| |
| def _test_xbinary_fdo_implicit_thin_lto(name, **kwargs): |
| """Tests that --features=xbinaryfdo_implicit_thinlto enables ThinLTO for XFDO with LLVM.""" |
| fdo_profile( |
| name = name + "/out.xfdo", |
| profile = "profiles.xfdo", |
| ) |
| util.helper_target( |
| cc_binary, |
| name = name + "/bin", |
| srcs = ["binfile.cc"], |
| ) |
| cc_analysis_test( |
| name = name, |
| impl = _test_xbinary_fdo_implicit_thin_lto_impl, |
| target = name + "/bin", |
| with_features = ["thin_lto", "xbinaryfdo", "enable_xbinaryfdo_thinlto", "xbinaryfdo_implicit_thinlto", "supports_start_end_lib"], |
| test_features = ["xbinaryfdo_implicit_thinlto"], |
| config_settings = { |
| "//command_line_option:xbinary_fdo": Label(":" + name + "/out.xfdo"), |
| "//command_line_option:compilation_mode": "opt", |
| }, |
| **kwargs |
| ) |
| |
| def _test_xbinary_fdo_implicit_thin_lto_impl(env, target): |
| binary_obj_path = "{package}/{name}.lto/{bindir}/{package}/_objs/{name}/binfile.o".format( |
| package = target.label.package, |
| name = target.label.name, |
| bindir = target[TestingAspectInfo].bin_path, |
| ) |
| |
| backend_action = env.expect.that_target(target).action_generating(binary_obj_path) |
| backend_action.mnemonic().equals("CcLtoBackendCompile") |
| |
| def _test_xbinary_fdo_implicit_thin_lto_disabled_option(name, **kwargs): |
| """Tests that --features=-thin_lto overrides --features=xbinaryfdo_implicit_thinlto and prevents enabling ThinLTO for XFDO with LLVM.""" |
| fdo_profile( |
| name = name + "/out.xfdo", |
| profile = "profiles.xfdo", |
| ) |
| util.helper_target( |
| cc_binary, |
| name = name + "/bin", |
| srcs = ["binfile.cc"], |
| ) |
| cc_analysis_test( |
| name = name, |
| impl = _make_lto_backend_disabled_test_impl("binfile.o"), |
| target = name + "/bin", |
| with_features = ["thin_lto", "xbinaryfdo", "enable_xbinaryfdo_thinlto", "xbinaryfdo_implicit_thinlto", "supports_start_end_lib"], |
| test_features = ["xbinaryfdo_implicit_thinlto", "-thin_lto"], |
| config_settings = { |
| "//command_line_option:xbinary_fdo": Label(":" + name + "/out.xfdo"), |
| "//command_line_option:compilation_mode": "opt", |
| }, |
| **kwargs |
| ) |
| |
| def _test_xbinary_fdo_implicit_thin_lto_disabled_rule(name, **kwargs): |
| """Tests that features=[-thin_lto] in the build rule overrides --features=xbinaryfdo_implicit_thinlto and prevents enabling ThinLTO for XFDO with LLVM.""" |
| fdo_profile( |
| name = name + "/out.xfdo", |
| profile = "profiles.xfdo", |
| ) |
| util.helper_target( |
| cc_binary, |
| name = name + "/bin", |
| srcs = ["binfile.cc"], |
| features = ["-thin_lto"], |
| ) |
| cc_analysis_test( |
| name = name, |
| impl = _make_lto_backend_disabled_test_impl("binfile.o"), |
| target = name + "/bin", |
| with_features = ["thin_lto", "xbinaryfdo", "enable_xbinaryfdo_thinlto", "xbinaryfdo_implicit_thinlto", "supports_start_end_lib"], |
| test_features = ["xbinaryfdo_implicit_thinlto"], |
| config_settings = { |
| "//command_line_option:xbinary_fdo": Label(":" + name + "/out.xfdo"), |
| "//command_line_option:compilation_mode": "opt", |
| }, |
| **kwargs |
| ) |
| |
| def _test_xbinary_fdo_implicit_thin_lto_disabled_package(name, **kwargs): |
| """Tests that features=[-thin_lto] in the package overrides --features=xbinaryfdo_implicit_thinlto and prevents enabling ThinLTO for XFDO with LLVM.""" |
| cc_analysis_test( |
| name = name, |
| impl = _make_lto_backend_disabled_test_impl("empty.o"), |
| target = "//tests/cc/common/disabled_package_xfdo:bin", |
| with_features = ["thin_lto", "xbinaryfdo", "enable_xbinaryfdo_thinlto", "xbinaryfdo_implicit_thinlto", "supports_start_end_lib"], |
| test_features = ["xbinaryfdo_implicit_thinlto"], |
| config_settings = { |
| "//command_line_option:xbinary_fdo": Label("//tests/cc/common/disabled_package_xfdo:out.xfdo"), |
| "//command_line_option:compilation_mode": "opt", |
| }, |
| **kwargs |
| ) |
| |
| def _test_xbinary_fdo(name, **kwargs): |
| """Tests that -fauto-profile is added to the LtoBackendAction when xbinary_fdo is enabled.""" |
| fdo_profile( |
| name = name + "/out.xfdo", |
| profile = "profiles.xfdo", |
| ) |
| util.helper_target( |
| cc_binary, |
| name = name + "/bin", |
| srcs = ["binfile.cc"], |
| features = ["thin_lto"], |
| ) |
| cc_analysis_test( |
| name = name, |
| impl = _test_xbinary_fdo_impl, |
| target = name + "/bin", |
| with_features = ["thin_lto", "xbinaryfdo", "enable_xbinaryfdo_thinlto", "xbinaryfdo_implicit_thinlto", "supports_start_end_lib"], |
| test_features = ["thin_lto"], |
| config_settings = { |
| "//command_line_option:xbinary_fdo": Label(":" + name + "/out.xfdo"), |
| "//command_line_option:compilation_mode": "opt", |
| }, |
| **kwargs |
| ) |
| |
| def _test_xbinary_fdo_impl(env, target): |
| binary_obj_path = "{package}/{name}.lto/{bindir}/{package}/_objs/{name}/binfile.o".format( |
| package = target.label.package, |
| name = target.label.name, |
| bindir = target[TestingAspectInfo].bin_path, |
| ) |
| |
| backend_action = env.expect.that_target(target).action_generating(binary_obj_path) |
| backend_action.mnemonic().equals("CcLtoBackendCompile") |
| backend_action.argv().contains_predicate(matching.str_matches("-fauto-profile=*profiles.xfdo")) |
| backend_action.inputs().contains_predicate(matching.file_basename_equals("profiles.xfdo")) |
| |
| def _test_xbinary_fdo_no_autofdo_or_fdo_implicit_thin_lto(name, **kwargs): |
| """Tests that ThinLTO is not enabled for XBINARYFDO with --features=autofdo_implicit_thinlto and --features=fdo_implicit_thinlto.""" |
| fdo_profile( |
| name = name + "/out.xfdo", |
| profile = "profiles.xfdo", |
| ) |
| util.helper_target( |
| cc_binary, |
| name = name + "/bin", |
| srcs = ["binfile.cc"], |
| ) |
| cc_analysis_test( |
| name = name, |
| impl = _make_lto_backend_disabled_test_impl("binfile.o"), |
| target = name + "/bin", |
| with_features = [ |
| "thin_lto", |
| "fdo_optimize", |
| "enable_fdo_thinlto", |
| "fdo_implicit_thinlto", |
| "autofdo", |
| "enable_afdo_thinlto", |
| "autofdo_implicit_thinlto", |
| "xbinaryfdo", |
| "supports_start_end_lib", |
| ], |
| test_features = ["autofdo_implicit_thinlto", "fdo_implicit_thinlto"], |
| config_settings = { |
| "//command_line_option:xbinary_fdo": Label(":" + name + "/out.xfdo"), |
| "//command_line_option:compilation_mode": "opt", |
| }, |
| **kwargs |
| ) |
| |
| def _test_pic_backend_order(name, **kwargs): |
| _create_thin_lto_basic_targets(name) |
| cc_analysis_test( |
| name = name, |
| impl = _test_pic_backend_order_impl, |
| target = name + "/bin", |
| test_features = ["thin_lto", "supports_pic", "supports_start_end_lib"], |
| config_settings = { |
| "//command_line_option:copt": ["-fno-PIE"], |
| }, |
| **kwargs |
| ) |
| |
| def _test_pic_backend_order_impl(env, target): |
| backend_action = env.expect.that_target(target).action_generating( |
| "{package}/{name}.lto/{bindir}/{package}/_objs/{name}/binfile.pic.o", |
| ) |
| backend_action.mnemonic().equals("CcLtoBackendCompile") |
| backend_action.argv().contains_at_least(["-fno-PIE", "-fPIC"]).in_order() |
| |
| def _test_propeller_optimize_absolute_options(name, **kwargs): |
| _create_thin_lto_basic_targets(name) |
| cc_analysis_test( |
| name = name, |
| impl = _test_propeller_optimize_absolute_options_impl, |
| target = name + "/bin", |
| with_features = ["thin_lto", "autofdo", "supports_start_end_lib", "propeller_optimize"], |
| test_features = ["thin_lto", "supports_start_end_lib", "propeller_optimize"], |
| config_settings = { |
| "//command_line_option:propeller_optimize_absolute_cc_profile": "/tmp/cc_profile.txt", |
| "//command_line_option:propeller_optimize_absolute_ld_profile": "/tmp/ld_profile.txt", |
| "//command_line_option:compilation_mode": "opt", |
| }, |
| **kwargs |
| ) |
| |
| def _test_propeller_optimize_absolute_options_impl(env, target): |
| binary_target = cc_binary_target_subject.from_target(env, target) |
| link_action = binary_target.action_generating("{package}/{name}{binary_extension}") |
| |
| link_action.outputs().has_size(1) |
| |
| link_action.inputs().contains_predicate(matching.file_basename_equals("ld_profile.txt")) |
| link_action.argv().contains_predicate(matching.str_matches("-Wl,--symbol-ordering-file=*/ld_profile.txt")) |
| |
| backend_action = env.expect.that_target(target).action_generating( |
| "{package}/{name}.lto/{bindir}/{package}/_objs/{name}/binfile.o", |
| ) |
| backend_action.mnemonic().equals("CcLtoBackendCompile") |
| |
| backend_action.argv().contains_predicate(matching.str_matches("-fbasic-block-sections=list=*/cc_profile.txt")) |
| backend_action.argv().contains("-DBUILD_PROPELLER_ENABLED=1") |
| backend_action.inputs().contains_predicate(matching.file_basename_equals("cc_profile.txt")) |
| |
| index_action = env.expect.that_target(target).action_generating( |
| "{package}/{name}.lto/{bindir}/{package}/_objs/{name}/binfile.o.thinlto.bc", |
| ) |
| index_action.inputs().not_contains_predicate(matching.file_basename_equals("ld_profile.txt")) |
| |
| def _test_propeller_cc_compile(name, **kwargs): |
| _create_thin_lto_basic_targets(name) |
| cc_analysis_test( |
| name = name, |
| impl = _test_propeller_cc_compile_impl, |
| target = name + "/bin", |
| with_features = ["thin_lto", "autofdo", "supports_start_end_lib", "propeller_optimize"], |
| test_features = ["thin_lto", "supports_start_end_lib", "propeller_optimize"], |
| config_settings = { |
| "//command_line_option:propeller_optimize_absolute_cc_profile": "/tmp/cc_profile.txt", |
| "//command_line_option:propeller_optimize_absolute_ld_profile": "/tmp/ld_profile.txt", |
| "//command_line_option:compilation_mode": "opt", |
| }, |
| **kwargs |
| ) |
| |
| def _test_propeller_cc_compile_impl(env, target): |
| # We need to find bitcodeAction (CppCompile generating binfile.indexing.o) |
| # It is input to indexAction. |
| # indexAction output is obj_path + ".thinlto.bc" |
| index_action = env.expect.that_target(target).action_generating( |
| "{package}/{name}.lto/{bindir}/{package}/_objs/{name}/binfile.o.thinlto.bc", |
| ) |
| |
| index_action.inputs().contains("{package}/_objs/{name}/binfile.indexing.o") |
| |
| bitcode_action = env.expect.that_target(target).action_generating("{package}/_objs/{name}/binfile.indexing.o") |
| bitcode_action.mnemonic().equals("CppCompile") |
| |
| bitcode_action.inputs().not_contains_predicate(matching.file_basename_equals("cc_profile.txt")) |
| bitcode_action.argv().not_contains_predicate(matching.str_startswith("-fbasic-block-sections=")) |
| |
| # Check that the temporary opt-out from disabling Propeller profiles for ThinLTO compile actions |
| # works. |
| # |
| # TODO(b/182804945): Remove after making sure that the rollout of the new Propeller profile |
| # passing logic didn't break anything. |
| def _test_propeller_cc_compile_with_propeller_optimize_thin_lto_compile_actions(name, **kwargs): |
| _create_thin_lto_basic_targets(name) |
| cc_analysis_test( |
| name = name, |
| impl = _test_propeller_cc_compile_with_propeller_optimize_thin_lto_compile_actions_impl, |
| target = name + "/bin", |
| with_features = [ |
| "thin_lto", |
| "autofdo", |
| "supports_start_end_lib", |
| "propeller_optimize", |
| "propeller_optimize_thinlto_compile_actions", |
| ], |
| test_features = [ |
| "thin_lto", |
| "supports_start_end_lib", |
| "propeller_optimize", |
| "propeller_optimize_thinlto_compile_actions", |
| ], |
| config_settings = { |
| "//command_line_option:propeller_optimize_absolute_cc_profile": "/tmp/cc_profile.txt", |
| "//command_line_option:propeller_optimize_absolute_ld_profile": "/tmp/ld_profile.txt", |
| "//command_line_option:compilation_mode": "opt", |
| }, |
| **kwargs |
| ) |
| |
| def _test_propeller_cc_compile_with_propeller_optimize_thin_lto_compile_actions_impl(env, target): |
| lib_name = target.label.name.removesuffix("/bin") + "/lib" |
| |
| index_action = env.expect.that_target(target).action_generating( |
| "{package}/{name}.lto/{bindir}/{package}/_objs/{name}/binfile.o.thinlto.bc", |
| ) |
| |
| index_action.inputs().contains("{package}/_objs/{name}/binfile.indexing.o") |
| index_action.inputs().contains("{package}/_objs/" + lib_name + "/libfile.indexing.o") |
| |
| bitcode_action = env.expect.that_target(target).action_generating("{package}/_objs/{name}/binfile.indexing.o") |
| bitcode_action.mnemonic().equals("CppCompile") |
| |
| bitcode_action.inputs().contains_predicate(matching.file_basename_equals("cc_profile.txt")) |
| bitcode_action.argv().contains_predicate(matching.str_matches("-fbasic-block-sections=list=*/cc_profile.txt")) |
| |
| def _propagating_testing_aspect_impl(target, ctx): |
| return [TestingAspectInfo( |
| attrs = ctx.rule.attr, |
| actions = target.actions, |
| vars = ctx.var, |
| bin_path = ctx.bin_dir.path, |
| required_aspects = ctx.aspect_ids[:-1], |
| )] |
| |
| _propagating_testing_aspect = aspect( |
| implementation = _propagating_testing_aspect_impl, |
| attr_aspects = ["*"], |
| ) |
| |
| def _find_target_in_attr_by_suffix(env, target, attr_name, name_suffix): |
| targets = [ |
| dep |
| for dep in getattr(target[TestingAspectInfo].attrs, attr_name) |
| if dep.label.name.endswith(name_suffix) |
| ] |
| env.expect.that_collection(targets).has_size(1) |
| return targets[0] |
| |
| def _test_propeller_cc_compile_with_thin_lto_disabled(name, **kwargs): |
| util.helper_target( |
| cc_library, |
| name = name + "/lib", |
| srcs = ["libfile.cc"], |
| hdrs = ["libfile.h"], |
| linkstamp = "linkstamp.cc", |
| features = ["-thin_lto"], |
| ) |
| util.helper_target( |
| cc_binary, |
| name = name + "/bin", |
| srcs = ["binfile.cc"], |
| deps = [":" + name + "/lib"], |
| ) |
| cc_analysis_test( |
| name = name, |
| impl = _test_propeller_cc_compile_with_thin_lto_disabled_impl, |
| target = name + "/bin", |
| with_features = ["thin_lto", "autofdo", "supports_start_end_lib", "propeller_optimize"], |
| test_features = ["thin_lto", "supports_start_end_lib", "propeller_optimize"], |
| testing_aspect = _propagating_testing_aspect, |
| config_settings = { |
| "//command_line_option:propeller_optimize_absolute_cc_profile": "/tmp/cc_profile.txt", |
| "//command_line_option:propeller_optimize_absolute_ld_profile": "/tmp/ld_profile.txt", |
| "//command_line_option:compilation_mode": "opt", |
| }, |
| **kwargs |
| ) |
| |
| def _test_propeller_cc_compile_with_thin_lto_disabled_impl(env, target): |
| lib_target = _find_target_in_attr_by_suffix(env, target, attr_name = "deps", name_suffix = "/lib") |
| test_name = target.label.name.split("/")[0] |
| |
| obj_path = "{package}/_objs/{lib_target_name}/libfile.o".format( |
| package = target.label.package, |
| lib_target_name = test_name + "/lib", |
| ) |
| |
| compile_action = env.expect.that_target(lib_target).action_generating(obj_path) |
| compile_action.mnemonic().equals("CppCompile") |
| |
| compile_action.inputs().contains_predicate(matching.file_basename_equals("cc_profile.txt")) |
| compile_action.argv().contains_predicate(matching.str_matches("-fbasic-block-sections=list=*/cc_profile.txt")) |
| |
| def _test_propeller_host_builds(name, **kwargs): |
| util.helper_target( |
| cc_binary, |
| name = name + "/gen_lib", |
| srcs = [name + "/gen_lib.cc"], |
| ) |
| util.helper_target( |
| native.genrule, |
| name = name + "/lib_genrule", |
| srcs = [], |
| outs = [name + "/libfile.cc"], |
| cmd = "$(location :" + name + "/gen_lib) > \"$@\"", |
| tools = [":" + name + "/gen_lib"], |
| ) |
| util.helper_target( |
| cc_library, |
| name = name + "/lib", |
| srcs = [":" + name + "/lib_genrule"], |
| hdrs = [name + "/libfile.h"], |
| ) |
| util.helper_target( |
| cc_binary, |
| name = name + "/bin", |
| srcs = [name + "/binfile.cc"], |
| deps = [":" + name + "/lib"], |
| ) |
| cc_analysis_test( |
| name = name, |
| impl = _test_propeller_host_builds_impl, |
| target = name + "/bin", |
| with_features = ["thin_lto", "autofdo", "supports_start_end_lib", "propeller_optimize"], |
| test_features = ["thin_lto", "supports_start_end_lib", "propeller_optimize"], |
| testing_aspect = _propagating_testing_aspect, |
| config_settings = { |
| "//command_line_option:propeller_optimize_absolute_cc_profile": "/tmp/cc_profile.txt", |
| "//command_line_option:propeller_optimize_absolute_ld_profile": "/tmp/ld_profile.txt", |
| "//command_line_option:compilation_mode": "opt", |
| }, |
| **kwargs |
| ) |
| |
| def _test_propeller_host_builds_impl(env, target): |
| # Sanity check: Verify Propeller IS active on the target binary backend action |
| target_backend_action = env.expect.that_target(target).action_generating( |
| "{package}/{name}.lto/{bindir}/{package}/_objs/{name}/binfile.o".format( |
| package = target.label.package, |
| name = target.label.name, |
| bindir = target[TestingAspectInfo].bin_path, |
| ), |
| ) |
| target_backend_action.mnemonic().equals("CcLtoBackendCompile") |
| target_backend_action.argv().contains_predicate(matching.str_matches("-fbasic-block-sections=list=*/cc_profile.txt")) |
| |
| lib_target = _find_target_in_attr_by_suffix( |
| env, |
| target, |
| attr_name = "deps", |
| name_suffix = "/lib", |
| ) |
| lib_genrule_target = _find_target_in_attr_by_suffix( |
| env, |
| lib_target, |
| attr_name = "srcs", |
| name_suffix = "/lib_genrule", |
| ) |
| gen_lib_target = _find_target_in_attr_by_suffix( |
| env, |
| lib_genrule_target, |
| attr_name = "tools", |
| name_suffix = "/gen_lib", |
| ) |
| |
| gen_lib_executable = gen_lib_target[DefaultInfo].files_to_run.executable |
| host_link_action = env.expect.that_target(gen_lib_target).action_generating(gen_lib_executable.short_path) |
| host_link_action.mnemonic().equals("CppLink") |
| |
| host_link_action.inputs().not_contains_predicate(matching.file_basename_equals("ld_profile.txt")) |
| host_link_action.argv().not_contains_predicate(matching.str_startswith("-Wl,--symbol-ordering-file=")) |
| |
| host_compile_action = env.expect.that_target(gen_lib_target).action_generating("{package}/_objs/{name}/gen_lib.o") |
| host_compile_action.mnemonic().equals("CppCompile") |
| |
| host_compile_action.inputs().not_contains_predicate(matching.file_basename_equals("cc_profile.txt")) |
| host_compile_action.argv().not_contains_predicate(matching.str_startswith("-fbasic-block-sections=")) |
| |
| def _test_propeller_optimize_option_from_label(name, **kwargs): |
| cc_profile = name + "/cc_profile.txt" |
| ld_profile = name + "/ld_profile.txt" |
| |
| util.helper_target( |
| propeller_optimize, |
| name = name + "/test_propeller_optimize", |
| cc_profile = cc_profile, |
| ld_profile = ld_profile, |
| ) |
| |
| _create_thin_lto_basic_targets(name) |
| |
| cc_analysis_test( |
| name = name, |
| impl = _test_propeller_optimize_option_from_label_impl, |
| target = name + "/bin", |
| with_features = ["thin_lto", "autofdo", "supports_start_end_lib", "propeller_optimize"], |
| test_features = ["thin_lto", "supports_start_end_lib", "propeller_optimize"], |
| config_settings = { |
| "//command_line_option:propeller_optimize": Label(":" + name + "/test_propeller_optimize"), |
| "//command_line_option:compilation_mode": "opt", |
| }, |
| **kwargs |
| ) |
| |
| def _test_propeller_optimize_option_from_label_impl(env, target): |
| binary_target = cc_binary_target_subject.from_target(env, target) |
| link_action = binary_target.action_generating("{package}/{name}{binary_extension}") |
| |
| link_action.outputs().has_size(1) |
| |
| link_action.inputs().contains_predicate(matching.file_basename_equals("ld_profile.txt")) |
| link_action.argv().contains_predicate(matching.str_matches("-Wl,--symbol-ordering-file=*/ld_profile.txt")) |
| |
| backend_action = env.expect.that_target(target).action_generating( |
| "{package}/{name}.lto/{bindir}/{package}/_objs/{name}/binfile.o", |
| ) |
| backend_action.mnemonic().equals("CcLtoBackendCompile") |
| |
| backend_action.argv().contains_predicate(matching.str_matches("-fbasic-block-sections=list=*/cc_profile.txt")) |
| backend_action.argv().contains("-DBUILD_PROPELLER_ENABLED=1") |
| |
| backend_action.inputs().contains_predicate(matching.file_basename_equals("cc_profile.txt")) |
| backend_action.inputs().contains_predicate(matching.file_basename_equals("ld_profile.txt")) |
| |
| def _test_no_use_lto_indexing_bitcode_file(name, **kwargs): |
| _create_thin_lto_basic_targets(name) |
| cc_analysis_test( |
| name = name, |
| impl = _test_no_use_lto_indexing_bitcode_file_impl, |
| target = name + "/bin", |
| test_features = [ |
| "thin_lto", |
| "supports_pic", |
| "supports_start_end_lib", |
| "no_use_lto_indexing_bitcode_file", |
| ], |
| **kwargs |
| ) |
| |
| def _test_no_use_lto_indexing_bitcode_file_impl(env, target): |
| test_name = target.label.name.split("/")[0] |
| lib_name = test_name + "/lib" |
| |
| binary_obj_path = "{package}/{name}.lto/{bindir}/{package}/_objs/{name}/binfile.pic.o".format( |
| package = target.label.package, |
| name = target.label.name, |
| bindir = target[TestingAspectInfo].bin_path, |
| ) |
| |
| backend_action = env.expect.that_target(target).action_generating(binary_obj_path) |
| backend_action.mnemonic().equals("CcLtoBackendCompile") |
| |
| index_action = env.expect.that_target(target).action_generating(binary_obj_path + ".thinlto.bc") |
| index_action.mnemonic().equals("CppLTOIndexing") |
| |
| index_action.argv().not_contains("object_suffix_replace") |
| |
| binary_normal_obj = "{package}/_objs/{name}/binfile.pic.o".format( |
| package = target.label.package, |
| name = target.label.name, |
| ) |
| lib_normal_obj = "{package}/_objs/{lib_name}/libfile.pic.o".format( |
| package = target.label.package, |
| lib_name = lib_name, |
| ) |
| index_action.inputs().contains(binary_normal_obj) |
| index_action.inputs().contains(lib_normal_obj) |
| |
| bitcode_action = env.expect.that_target(target).action_generating(binary_normal_obj) |
| bitcode_action.mnemonic().equals("CppCompile") |
| bitcode_action.argv().not_contains("lto_indexing_bitcode=") |
| |
| def _test_fdo_cache_prefetch_llvm_options_to_backend_base(name, extra_config_settings, **kwargs): |
| util.helper_target( |
| fdo_prefetch_hints, |
| name = name + "/test_profile", |
| profile = "prefetch.afdo", |
| ) |
| _create_thin_lto_basic_targets(name) |
| config_settings = { |
| "//command_line_option:fdo_prefetch_hints": Label(":" + name + "/test_profile"), |
| "//command_line_option:compilation_mode": "opt", |
| } |
| config_settings.update(extra_config_settings) |
| cc_analysis_test( |
| name = name, |
| impl = _test_fdo_cache_prefetch_llvm_options_to_backend_impl, |
| target = name + "/bin", |
| with_features = ["thin_lto", "autofdo", "supports_start_end_lib", "fdo_prefetch_hints"], |
| test_features = ["thin_lto", "supports_start_end_lib", "fdo_prefetch_hints"], |
| config_settings = config_settings, |
| **kwargs |
| ) |
| |
| def _test_fdo_cache_prefetch_llvm_options_to_backend_impl(env, target): |
| obj_path = "{package}/{name}.lto/{bindir}/{package}/_objs/{name}/binfile.o".format( |
| package = target.label.package, |
| name = target.label.name, |
| bindir = target[TestingAspectInfo].bin_path, |
| ) |
| |
| backend_action = env.expect.that_target(target).action_generating(obj_path) |
| backend_action.mnemonic().equals("CcLtoBackendCompile") |
| |
| backend_action.argv().contains("-mllvm") |
| backend_action.argv().contains_predicate(matching.str_matches("*-prefetch-hints-file=*/prefetch.afdo")) |
| backend_action.inputs().contains_predicate(matching.file_basename_equals("prefetch.afdo")) |
| |
| def _test_fdo_cache_prefetch_llvm_options_to_backend_from_label(name, **kwargs): |
| _test_fdo_cache_prefetch_llvm_options_to_backend_base(name, [], **kwargs) |
| |
| def _test_fdo_cache_prefetch_and_fdo_llvm_options_to_backend_from_label(name, **kwargs): |
| _test_fdo_cache_prefetch_llvm_options_to_backend_base( |
| name, |
| [("//command_line_option:fdo_optimize", "/profile.zip")], |
| **kwargs |
| ) |
| |
| def _test_thin_lto_without_supports_start_end_lib_error(name, **kwargs): |
| _create_thin_lto_basic_targets(name) |
| cc_analysis_test( |
| name = name, |
| impl = _test_thin_lto_without_supports_start_end_lib_error_impl, |
| target = name + "/bin", |
| with_features = ["thin_lto"], |
| test_features = ["thin_lto"], |
| expect_failure = True, |
| **kwargs |
| ) |
| |
| def _test_thin_lto_without_supports_start_end_lib_error_impl(env, target): |
| env.expect.that_target(target).failures().contains_predicate( |
| matching.contains("The feature supports_start_end_lib must be enabled."), |
| ) |
| |
| def cc_binary_thin_lto_tests(name): |
| """TestSuite for cc_binary with ThinLTO. |
| |
| Args: |
| name: The name of the test suite. |
| """ |
| tests = [] |
| |
| # These tests pass on all Bazel versions. |
| tests.append(_test_thin_lto_action_graph) |
| tests.append(_test_thin_lto_no_linkstatic) |
| tests.append(_test_thin_lto_fission) |
| tests.append(_test_thin_lto_no_linkstatic_fission) |
| tests.append(_test_thin_lto_linkstatic_cc_test_fission) |
| tests.append(_test_assembler_source) |
| tests.append(_test_no_source_files) |
| tests.append(_test_fdo_instrument) |
| tests.append(_test_lto_index_opt) |
| tests.append(_test_copt) |
| tests.append(_test_per_file_copt) |
| tests.append(_test_per_file_lto_backend_opt) |
| tests.append(_test_autofdo) |
| tests.append(_test_autofdo_no_implicit_thin_lto) |
| tests.append(_test_autofdo_implicit_thin_lto) |
| tests.append(_test_autofdo_implicit_thin_lto_disabled_option) |
| tests.append(_test_autofdo_implicit_thin_lto_disabled_rule) |
| tests.append(_test_autofdo_implicit_thin_lto_disabled_package) |
| tests.append(_test_fdo_no_implicit_thin_lto) |
| tests.append(_test_fdo_implicit_thin_lto) |
| tests.append(_test_fdo_implicit_thin_lto_disabled_option) |
| tests.append(_test_fdo_implicit_thin_lto_disabled_rule) |
| tests.append(_test_fdo_implicit_thin_lto_disabled_package) |
| tests.append(_test_xbinary_fdo_no_implicit_thin_lto) |
| tests.append(_test_xbinary_fdo_implicit_thin_lto) |
| tests.append(_test_xbinary_fdo_implicit_thin_lto_disabled_option) |
| tests.append(_test_xbinary_fdo_implicit_thin_lto_disabled_rule) |
| tests.append(_test_xbinary_fdo_implicit_thin_lto_disabled_package) |
| tests.append(_test_xbinary_fdo) |
| tests.append(_test_xbinary_fdo_no_autofdo_or_fdo_implicit_thin_lto) |
| tests.append(_test_pic_backend_order) |
| tests.append(_test_propeller_optimize_absolute_options) |
| tests.append(_test_propeller_cc_compile) |
| tests.append(_test_propeller_cc_compile_with_propeller_optimize_thin_lto_compile_actions) |
| tests.append(_test_propeller_cc_compile_with_thin_lto_disabled) |
| tests.append(_test_propeller_host_builds) |
| tests.append(_test_no_use_lto_indexing_bitcode_file) |
| tests.append(_test_fdo_cache_prefetch_llvm_options_to_backend_from_label) |
| tests.append(_test_fdo_cache_prefetch_and_fdo_llvm_options_to_backend_from_label) |
| tests.append(_test_thin_lto_without_supports_start_end_lib_error) |
| |
| # These tests fail on Bazel 7 and 8, run only for Bazel 9+. |
| if bazel_features.cc.cc_common_is_in_rules_cc: |
| tests.append(_test_thin_lto_linkshared) |
| tests.append(_test_thin_lto_backend_env) |
| tests.append(_test_linkstatic_cc_test) |
| tests.append(_test_test_only_target) |
| tests.append(_test_use_shared_all_linkstatic) |
| tests.append(_test_lto_standalone_command_lines) |
| tests.append(_test_lto_backend_opt) |
| tests.append(_test_link_opt) |
| tests.append(_test_propeller_optimize_option_from_label) |
| tests.append(_test_assembler_source_with_shared_nonlto_backends) |
| tests.append(_test_duplicated_static_libraries_in_lto) |
| |
| test_suite( |
| name = name, |
| tests = tests, |
| ) |