1# Copyright (C) 2022 The Android Open Source Project 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14 15load("@bazel_skylib//lib:unittest.bzl", "analysistest", "asserts") 16load("//build/bazel/rules/cc:cc_library_shared.bzl", "cc_library_shared") 17load("//build/bazel/rules/cc:cc_library_static.bzl", "cc_library_static") 18load("//build/bazel/rules/cc:cc_stub_library.bzl", "cc_stub_suite") 19load( 20 "//build/bazel/rules/cc/testing:transitions.bzl", 21 "ActionArgsInfo", 22 "compile_action_argv_aspect_generator", 23) 24load("//build/bazel/rules/fdo:fdo_profile.bzl", "fdo_profile") 25load("//build/bazel/rules/test_common:flags.bzl", "action_flags_present_only_for_mnemonic_test") 26load("//build/bazel/rules/test_common:paths.bzl", "get_output_and_package_dir_based_path", "get_package_dir_based_path") 27load(":cc_binary_test.bzl", "cc_bad_linkopts_test") 28load(":cc_library_common_test.bzl", "target_provides_androidmk_info_test") 29 30def _cc_library_shared_suffix_test_impl(ctx): 31 env = analysistest.begin(ctx) 32 target = analysistest.target_under_test(env) 33 info = target[DefaultInfo] 34 35 # NB: There may be more than 1 output file (if e.g. including a TOC) 36 outputs = [so for so in info.files.to_list() if so.path.endswith(".so")] 37 asserts.true( 38 env, 39 len(outputs) == 1, 40 "Expected only 1 output file; got %s" % outputs, 41 ) 42 out = outputs[0] 43 asserts.equals( 44 env, 45 ctx.attr.expected_output_filename_with_ext, 46 out.basename, 47 "Expected output filename to be `%s`; it was instead %s" % (ctx.attr.expected_output_filename_with_ext, out.basename), 48 ) 49 50 return analysistest.end(env) 51 52cc_library_shared_suffix_test = analysistest.make( 53 _cc_library_shared_suffix_test_impl, 54 attrs = { 55 "expected_output_filename_with_ext": attr.string(), 56 }, 57) 58 59def _cc_library_shared_suffix(): 60 name = "cc_library_shared_suffix" 61 test_name = name + "_test" 62 suffix = "-suf" 63 64 cc_library_shared( 65 name, 66 srcs = ["foo.cc"], 67 tags = ["manual"], 68 suffix = suffix, 69 ) 70 cc_library_shared_suffix_test( 71 name = test_name, 72 target_under_test = name, 73 expected_output_filename_with_ext = name + suffix + ".so", 74 ) 75 return test_name 76 77def _cc_library_shared_empty_suffix(): 78 name = "cc_library_shared_empty_suffix" 79 test_name = name + "_test" 80 81 cc_library_shared( 82 name, 83 srcs = ["foo.cc"], 84 tags = ["manual"], 85 ) 86 cc_library_shared_suffix_test( 87 name = test_name, 88 target_under_test = name, 89 expected_output_filename_with_ext = name + ".so", 90 ) 91 return test_name 92 93def _cc_library_with_stem(): 94 name = "cc_library_with_stem" 95 test_name = name + "_test" 96 97 cc_library_shared( 98 name, 99 srcs = ["foo.cc"], 100 stem = "bar", 101 tags = ["manual"], 102 ) 103 cc_library_shared_suffix_test( 104 name = test_name, 105 target_under_test = name, 106 expected_output_filename_with_ext = "bar.so", 107 ) 108 return test_name 109 110def _cc_library_shared_propagating_compilation_context_test_impl(ctx): 111 env = analysistest.begin(ctx) 112 target = analysistest.target_under_test(env) 113 cc_info = target[CcInfo] 114 compilation_context = cc_info.compilation_context 115 116 header_paths = [f.short_path for f in compilation_context.headers.to_list()] 117 for hdr in ctx.files.expected_hdrs: 118 asserts.true( 119 env, 120 hdr.short_path in header_paths, 121 "Did not find {hdr} in includes: {hdrs}.".format(hdr = hdr, hdrs = compilation_context.headers), 122 ) 123 124 for hdr in ctx.files.expected_absent_hdrs: 125 asserts.true( 126 env, 127 hdr not in header_paths, 128 "Found {hdr} in includes: {hdrs}, should not be present.".format(hdr = hdr, hdrs = compilation_context.headers), 129 ) 130 131 for include in ctx.attr.expected_includes: 132 absolute_include = get_package_dir_based_path(env, include) 133 asserts.true( 134 env, 135 absolute_include in compilation_context.includes.to_list(), 136 "Did not find {include} in includes: {includes}.".format(include = include, includes = compilation_context.includes), 137 ) 138 139 for include in ctx.attr.expected_absent_includes: 140 absolute_include = get_package_dir_based_path(env, include) 141 asserts.true( 142 env, 143 absolute_include not in compilation_context.includes.to_list(), 144 "Found {include} in includes: {includes}, was expected to be absent".format(include = include, includes = compilation_context.includes), 145 ) 146 147 for include in ctx.attr.expected_system_includes: 148 absolute_include = get_package_dir_based_path(env, include) 149 asserts.true( 150 env, 151 absolute_include in compilation_context.system_includes.to_list(), 152 "Did not find {include} in system includes: {includes}.".format(include = include, includes = compilation_context.system_includes), 153 ) 154 155 for include in ctx.attr.expected_absent_system_includes: 156 absolute_include = get_package_dir_based_path(env, include) 157 asserts.true( 158 env, 159 absolute_include not in compilation_context.system_includes.to_list(), 160 "Found {include} in system includes: {includes}, was expected to be absent".format(include = include, includes = compilation_context.system_includes), 161 ) 162 163 return analysistest.end(env) 164 165_cc_library_shared_propagating_compilation_context_test = analysistest.make( 166 _cc_library_shared_propagating_compilation_context_test_impl, 167 attrs = { 168 "expected_hdrs": attr.label_list(), 169 "expected_absent_hdrs": attr.label_list(), 170 "expected_includes": attr.string_list(), 171 "expected_absent_includes": attr.string_list(), 172 "expected_system_includes": attr.string_list(), 173 "expected_absent_system_includes": attr.string_list(), 174 }, 175) 176 177def _cc_library_shared_propagates_deps(): 178 name = "_cc_library_shared_propagates_deps" 179 dep_name = name + "_dep" 180 test_name = name + "_test" 181 182 cc_library_static( 183 name = dep_name, 184 hdrs = [":cc_library_shared_hdr"], 185 export_includes = ["a/b/c"], 186 export_system_includes = ["d/e/f"], 187 tags = ["manual"], 188 ) 189 190 cc_library_shared( 191 name = name, 192 deps = [dep_name], 193 tags = ["manual"], 194 ) 195 196 _cc_library_shared_propagating_compilation_context_test( 197 name = test_name, 198 target_under_test = name, 199 expected_hdrs = [":cc_library_shared_hdr"], 200 expected_includes = ["a/b/c"], 201 expected_system_includes = ["d/e/f"], 202 ) 203 204 return test_name 205 206def _cc_library_shared_propagates_whole_archive_deps(): 207 name = "_cc_library_shared_propagates_whole_archive_deps" 208 dep_name = name + "_dep" 209 test_name = name + "_test" 210 211 cc_library_static( 212 name = dep_name, 213 hdrs = [":cc_library_shared_hdr"], 214 export_includes = ["a/b/c"], 215 export_system_includes = ["d/e/f"], 216 tags = ["manual"], 217 ) 218 219 cc_library_shared( 220 name = name, 221 whole_archive_deps = [dep_name], 222 tags = ["manual"], 223 ) 224 225 _cc_library_shared_propagating_compilation_context_test( 226 name = test_name, 227 target_under_test = name, 228 expected_hdrs = [":cc_library_shared_hdr"], 229 expected_includes = ["a/b/c"], 230 expected_system_includes = ["d/e/f"], 231 ) 232 233 return test_name 234 235def _cc_library_shared_propagates_dynamic_deps(): 236 name = "_cc_library_shared_propagates_dynamic_deps" 237 dep_name = name + "_dep" 238 test_name = name + "_test" 239 240 cc_library_shared( 241 name = dep_name, 242 hdrs = [":cc_library_shared_hdr"], 243 export_includes = ["a/b/c"], 244 export_system_includes = ["d/e/f"], 245 tags = ["manual"], 246 ) 247 248 cc_library_shared( 249 name = name, 250 dynamic_deps = [dep_name], 251 tags = ["manual"], 252 ) 253 254 _cc_library_shared_propagating_compilation_context_test( 255 name = test_name, 256 target_under_test = name, 257 expected_hdrs = [":cc_library_shared_hdr"], 258 expected_includes = ["a/b/c"], 259 expected_system_includes = ["d/e/f"], 260 ) 261 262 return test_name 263 264def _cc_library_shared_does_not_propagate_implementation_deps(): 265 name = "_cc_library_shared_does_not_propagate_implementation_deps" 266 dep_name = name + "_dep" 267 test_name = name + "_test" 268 269 cc_library_static( 270 name = dep_name, 271 hdrs = [":cc_library_shared_hdr"], 272 export_includes = ["a/b/c"], 273 export_system_includes = ["d/e/f"], 274 tags = ["manual"], 275 ) 276 277 cc_library_shared( 278 name = name, 279 implementation_deps = [dep_name], 280 tags = ["manual"], 281 ) 282 283 _cc_library_shared_propagating_compilation_context_test( 284 name = test_name, 285 target_under_test = name, 286 expected_absent_hdrs = [":cc_library_shared_hdr"], 287 expected_absent_includes = ["a/b/c"], 288 expected_absent_system_includes = ["d/e/f"], 289 ) 290 291 return test_name 292 293def _cc_library_shared_does_not_propagate_implementation_whole_archive_deps(): 294 name = "_cc_library_shared_does_not_propagate_implementation_whole_archive_deps" 295 dep_name = name + "_dep" 296 test_name = name + "_test" 297 298 cc_library_static( 299 name = dep_name, 300 hdrs = [":cc_library_shared_hdr"], 301 export_includes = ["a/b/c"], 302 export_system_includes = ["d/e/f"], 303 tags = ["manual"], 304 ) 305 306 cc_library_shared( 307 name = name, 308 implementation_whole_archive_deps = [dep_name], 309 tags = ["manual"], 310 ) 311 312 _cc_library_shared_propagating_compilation_context_test( 313 name = test_name, 314 target_under_test = name, 315 expected_absent_hdrs = [":cc_library_shared_hdr"], 316 expected_absent_includes = ["a/b/c"], 317 expected_absent_system_includes = ["d/e/f"], 318 ) 319 320 return test_name 321 322def _cc_library_shared_does_not_propagate_implementation_dynamic_deps(): 323 name = "_cc_library_shared_does_not_propagate_implementation_dynamic_deps" 324 dep_name = name + "_dep" 325 test_name = name + "_test" 326 327 cc_library_shared( 328 name = dep_name, 329 hdrs = [":cc_library_shared_hdr"], 330 export_includes = ["a/b/c"], 331 export_system_includes = ["d/e/f"], 332 tags = ["manual"], 333 ) 334 335 cc_library_shared( 336 name = name, 337 implementation_dynamic_deps = [dep_name], 338 tags = ["manual"], 339 ) 340 341 _cc_library_shared_propagating_compilation_context_test( 342 name = test_name, 343 target_under_test = name, 344 expected_absent_hdrs = [":cc_library_shared_hdr"], 345 expected_absent_includes = ["a/b/c"], 346 expected_absent_system_includes = ["d/e/f"], 347 ) 348 349 return test_name 350 351def _cc_library_shared_propagating_fdo_profile_test_impl(ctx): 352 env = analysistest.begin(ctx) 353 target_under_test = analysistest.target_under_test(env) 354 argv_map = target_under_test[ActionArgsInfo].argv_map 355 356 for label in ctx.attr.deps_labels_to_check_fdo_profile: 357 asserts.true( 358 env, 359 label in argv_map, 360 "can't find {} in argv map".format(label), 361 ) 362 argv = argv_map[label] 363 asserts.true( 364 env, 365 _has_fdo_profile(argv, ctx.attr.fdo_profile), 366 "can't find {} in compile action of {}".format( 367 ctx.attr.fdo_profile, 368 label, 369 ), 370 ) 371 for label in ctx.attr.deps_labels_to_check_no_fdo_profile: 372 asserts.true( 373 env, 374 label in argv_map, 375 "can't find {} in argv_map".format(label), 376 ) 377 argv = argv_map[label] 378 asserts.true( 379 env, 380 not _has_fdo_profile(argv, ctx.attr.fdo_profile), 381 "{} should not have {} in compile action".format( 382 ctx.attr.fdo_profile, 383 label, 384 ), 385 ) 386 387 return analysistest.end(env) 388 389_compile_action_argv_aspect = compile_action_argv_aspect_generator({ 390 "_cc_library_combiner": ["deps", "roots", "includes"], 391 "_cc_includes": ["deps"], 392 "_cc_library_shared_proxy": ["deps"], 393}) 394 395cc_library_shared_propagating_fdo_profile_test = analysistest.make( 396 _cc_library_shared_propagating_fdo_profile_test_impl, 397 attrs = { 398 # FdoProfileInfo isn't exposed to Starlark so we need to test against 399 # the path basename directly 400 "fdo_profile": attr.string(), 401 # This has to be a string_list() instead of label_list(). If the deps 402 # are given as labels, the deps are analyzed because transition is attached 403 "deps_labels_to_check_fdo_profile": attr.string_list(), 404 "deps_labels_to_check_no_fdo_profile": attr.string_list(), 405 }, 406 # We need to use aspect to examine the dependencies' actions of the apex 407 # target as the result of the transition, checking the dependencies directly 408 # using names will give you the info before the transition takes effect. 409 extra_target_under_test_aspects = [_compile_action_argv_aspect], 410) 411 412# _has_fdo_profile checks whether afdo-specific flag is present in actions.argv 413def _has_fdo_profile(argv, fdo_profile_name): 414 for arg in argv: 415 if "-fprofile-sample-use=" in arg and fdo_profile_name in arg: 416 return True 417 418 return False 419 420def _cc_libary_shared_propagate_fdo_profile_to_whole_archive_deps(): 421 name = "_cc_libary_shared_propagate_fdo_profile_to_whole_archive_deps" 422 fdo_profile_name = name + "_fdo_profile" 423 dep_name = name + "_dep" 424 transitive_dep_name = name + "_transitive_dep" 425 unexported_dep_name = name + "_exported_dep" 426 transitive_unexported_dep_name = name + "_transitive_unexported_dep" 427 test_name = name + "_test" 428 429 native.genrule( 430 name = "{}.afdo".format(fdo_profile_name), 431 outs = ["{}.afdo".format(fdo_profile_name)], 432 cmd = "touch $(OUTS)", 433 ) 434 435 fdo_profile( 436 name = fdo_profile_name, 437 profile = ":" + fdo_profile_name + ".afdo", 438 ) 439 440 cc_library_static( 441 name = transitive_dep_name, 442 srcs = ["foo.cpp"], 443 tags = ["manual"], 444 ) 445 cc_library_static( 446 name = transitive_unexported_dep_name, 447 srcs = ["foo.cpp"], 448 tags = ["manual"], 449 ) 450 cc_library_static( 451 name = dep_name, 452 whole_archive_deps = [transitive_dep_name], 453 implementation_whole_archive_deps = [transitive_unexported_dep_name], 454 srcs = ["foo.cpp", "bar.cpp"], 455 tags = ["manual"], 456 ) 457 cc_library_static( 458 name = unexported_dep_name, 459 srcs = ["foo.cpp"], 460 tags = ["manual"], 461 ) 462 463 cc_library_shared( 464 name = name, 465 whole_archive_deps = [dep_name], 466 implementation_whole_archive_deps = [unexported_dep_name], 467 fdo_profile = ":" + fdo_profile_name, 468 tags = ["manual"], 469 ) 470 471 cc_library_shared_propagating_fdo_profile_test( 472 name = test_name, 473 target_under_test = name, 474 deps_labels_to_check_fdo_profile = [ 475 dep_name + "_cpp", 476 transitive_dep_name + "_cpp", 477 unexported_dep_name + "_cpp", 478 transitive_unexported_dep_name + "_cpp", 479 ], 480 fdo_profile = fdo_profile_name, 481 ) 482 483 return test_name 484 485def _cc_library_shared_does_not_propagate_fdo_profile_to_dynamic_deps(): 486 name = "_cc_library_shared_does_not_propagate_fdo_profile_to_dynamic_deps" 487 fdo_profile_name = name + "_fdo_profile" 488 dep_name = name + "_dep" 489 transitive_shared_dep_name = name + "_transitive_shared_dep" 490 unexported_transitive_shared_dep_name = name + "_unexported_transitive_shared_dep" 491 test_name = name + "_test" 492 493 cc_library_shared( 494 name = transitive_shared_dep_name, 495 srcs = ["foo.cpp"], 496 tags = ["manual"], 497 ) 498 cc_library_shared( 499 name = unexported_transitive_shared_dep_name, 500 srcs = ["foo.cpp"], 501 tags = ["manual"], 502 ) 503 cc_library_static( 504 name = dep_name, 505 srcs = ["foo.cpp"], 506 dynamic_deps = [transitive_shared_dep_name], 507 implementation_dynamic_deps = [unexported_transitive_shared_dep_name], 508 tags = ["manual"], 509 ) 510 native.genrule( 511 name = "{}.afdo".format(fdo_profile_name), 512 outs = ["{}.afdo".format(fdo_profile_name)], 513 cmd = "touch $(OUTS)", 514 ) 515 fdo_profile( 516 name = fdo_profile_name, 517 profile = fdo_profile_name + ".afdo", 518 ) 519 cc_library_shared( 520 name = name, 521 whole_archive_deps = [dep_name], 522 fdo_profile = fdo_profile_name, 523 stl = "", 524 tags = ["manual"], 525 ) 526 527 cc_library_shared_propagating_fdo_profile_test( 528 name = test_name, 529 target_under_test = name, 530 deps_labels_to_check_fdo_profile = [ 531 dep_name + "_cpp", 532 ], 533 # make sure dynamic deps don't build with afdo profiles from rdeps 534 deps_labels_to_check_no_fdo_profile = [ 535 transitive_shared_dep_name + "__internal_root_cpp", 536 unexported_transitive_shared_dep_name + "__internal_root_cpp", 537 ], 538 fdo_profile = fdo_profile_name, 539 ) 540 541 return test_name 542 543def _fdo_profile_transition_correctly_set_and_unset_fdo_profile(): 544 name = "_fdo_profile_transition_set_and_unset_fdo_profile_correctly" 545 fdo_profile_name = name + "_fdo_profile" 546 dep_with_fdo_profile = name + "_dep_with_fdo_profile" 547 transitive_dep_without_fdo_profile = name + "_transitive_dep_without_fdo_profile" 548 test_name = name + "_test" 549 550 native.genrule( 551 name = "{}.afdo".format(fdo_profile_name), 552 outs = ["{}.afdo".format(fdo_profile_name)], 553 cmd = "touch $(OUTS)", 554 ) 555 fdo_profile( 556 name = fdo_profile_name, 557 profile = fdo_profile_name + ".afdo", 558 ) 559 560 cc_library_shared( 561 name = name, 562 srcs = ["foo.cpp"], 563 tags = ["manual"], 564 dynamic_deps = [dep_with_fdo_profile], 565 ) 566 567 cc_library_shared( 568 name = dep_with_fdo_profile, 569 fdo_profile = fdo_profile_name, 570 srcs = ["foo.cpp"], 571 tags = ["manual"], 572 dynamic_deps = [transitive_dep_without_fdo_profile], 573 ) 574 575 cc_library_shared( 576 name = transitive_dep_without_fdo_profile, 577 srcs = ["foo.cpp"], 578 tags = ["manual"], 579 ) 580 581 cc_library_shared_propagating_fdo_profile_test( 582 name = test_name, 583 target_under_test = name, 584 deps_labels_to_check_fdo_profile = [ 585 dep_with_fdo_profile + "__internal_root_cpp", 586 ], 587 # make sure dynamic deps don't build with afdo profiles from rdeps 588 deps_labels_to_check_no_fdo_profile = [ 589 name + "__internal_root_cpp", 590 transitive_dep_without_fdo_profile + "__internal_root_cpp", 591 ], 592 fdo_profile = fdo_profile_name, 593 ) 594 595 return test_name 596 597def _cc_library_link_flags_test_impl(ctx): 598 env = analysistest.begin(ctx) 599 target = analysistest.target_under_test(env) 600 601 for action in target.actions: 602 if action.mnemonic == "CppLink": 603 for flag in ctx.attr.expected_link_flags: 604 if flag not in action.argv: 605 fail("{} is not in list of flags for linking {}".format(flag, action.argv)) 606 607 return analysistest.end(env) 608 609cc_library_link_flags_test = analysistest.make( 610 _cc_library_link_flags_test_impl, 611 attrs = { 612 "expected_link_flags": attr.string_list(), 613 }, 614) 615 616def _cc_library_with_fdo_profile_link_flags(): 617 name = "_cc_library_with_fdo_profile_link_flags" 618 test_name = name + "_test" 619 cc_library_shared( 620 name = name, 621 fdo_profile = name + "_fdo_profile", 622 tags = ["manual"], 623 ) 624 cc_library_link_flags_test( 625 name = test_name, 626 target_under_test = name + "_unstripped", 627 expected_link_flags = [ 628 "-funique-internal-linkage-names", 629 "-fprofile-sample-accurate", 630 "-fprofile-sample-use=build/bazel/rules/cc/_cc_library_with_fdo_profile_link_flags_fdo_profile_file", 631 "-Wl,-mllvm,-no-warn-sample-unused=true", 632 ], 633 ) 634 return test_name 635 636def _cc_library_disable_fdo_optimization_if_coverage_is_enabled_impl(ctx): 637 env = analysistest.begin(ctx) 638 target = analysistest.target_under_test(env) 639 640 for action in target.actions: 641 if action.mnemonic == "CppCompile": 642 for arg in action.argv: 643 if "-fprofile-sample-use" in arg: 644 fail("fdo optimization can not be enabled when coverage is enabled") 645 646 return analysistest.end(env) 647 648cc_library_disable_fdo_optimization_if_coverage_is_enabled_test = analysistest.make( 649 _cc_library_disable_fdo_optimization_if_coverage_is_enabled_impl, 650 config_settings = { 651 "//command_line_option:collect_code_coverage": True, 652 }, 653) 654 655def _cc_library_disable_fdo_optimization_if_coverage_is_enabled_test(): 656 name = "_cc_library_disable_fdo_optimization_if_coverage_is_enabled_test" 657 test_name = name + "_test" 658 cc_library_shared( 659 name = name, 660 fdo_profile = name + "_fdo_profile", 661 srcs = ["foo.cpp"], 662 # Coverage will add an extra lib to all the shared libs, we try to avoid 663 # that by clearing the system_dynamic_deps and stl. 664 system_dynamic_deps = [], 665 stl = "none", 666 tags = ["manual"], 667 ) 668 cc_library_disable_fdo_optimization_if_coverage_is_enabled_test( 669 name = test_name, 670 target_under_test = name + "__internal_root_cpp", 671 ) 672 return test_name 673 674def _cc_library_set_defines_for_stubs(): 675 name = "cc_library_set_defines_for_stubs" 676 test_name = name + "_test" 677 678 cc_library_shared( 679 name = name + "_libfoo", 680 system_dynamic_deps = [], 681 stl = "none", 682 tags = ["manual"], 683 stubs_symbol_file = name + "_libfoo.map.txt", 684 ) 685 686 cc_stub_suite( 687 name = name + "_libfoo_stub_libs", 688 soname = name + "_libfoo.so", 689 source_library_label = ":" + name + "_libfoo", 690 symbol_file = name + "_libfoo.map.txt", 691 versions = ["30", "40"], 692 ) 693 694 cc_library_shared( 695 name = name + "_libbar", 696 system_dynamic_deps = [], 697 stl = "none", 698 tags = ["manual"], 699 stubs_symbol_file = name + "_libbar.map.txt", 700 ) 701 702 cc_stub_suite( 703 name = name + "_libbar_stub_libs", 704 soname = name + "_libbar.so", 705 source_library_label = ":" + name + "_libbar", 706 symbol_file = name + "_libbar.map.txt", 707 versions = ["current"], 708 ) 709 710 cc_library_shared( 711 name = name + "_libbaz", 712 system_dynamic_deps = [], 713 stl = "none", 714 tags = ["manual"], 715 stubs_symbol_file = name + "_libbaz.map.txt", 716 ) 717 718 cc_stub_suite( 719 name = name + "_libbaz_stub_libs", 720 soname = name + "_libbaz.so", 721 source_library_label = ":" + name + "_libbaz", 722 symbol_file = name + "_libbaz.map.txt", 723 versions = ["30"], 724 ) 725 726 cc_library_shared( 727 name = name + "_lib_with_stub_deps", 728 srcs = ["foo.cpp"], 729 implementation_dynamic_deps = [ 730 name + "_libfoo_stub_libs_current", 731 name + "_libbar_stub_libs_current", 732 name + "_libbaz_stub_libs-30", # depend on an old version explicitly 733 ], 734 tags = ["manual"], 735 ) 736 737 action_flags_present_only_for_mnemonic_test( 738 name = test_name, 739 target_under_test = name + "_lib_with_stub_deps__internal_root_cpp", 740 mnemonics = ["CppCompile"], 741 expected_flags = [ 742 "-D__CC_LIBRARY_SET_DEFINES_FOR_STUBS_LIBFOO_API__=10000", 743 "-D__CC_LIBRARY_SET_DEFINES_FOR_STUBS_LIBBAR_API__=10000", 744 "-D__CC_LIBRARY_SET_DEFINES_FOR_STUBS_LIBBAZ_API__=30", 745 ], 746 ) 747 return test_name 748 749def _cc_library_shared_provides_androidmk_info(): 750 name = "cc_library_shared_provides_androidmk_info" 751 dep_name = name + "_static_dep" 752 whole_archive_dep_name = name + "_whole_archive_dep" 753 dynamic_dep_name = name + "_dynamic_dep" 754 test_name = name + "_test" 755 756 cc_library_static( 757 name = dep_name, 758 srcs = ["foo.c"], 759 tags = ["manual"], 760 ) 761 cc_library_static( 762 name = whole_archive_dep_name, 763 srcs = ["foo.c"], 764 tags = ["manual"], 765 ) 766 cc_library_shared( 767 name = dynamic_dep_name, 768 srcs = ["foo.c"], 769 tags = ["manual"], 770 ) 771 cc_library_shared( 772 name = name, 773 srcs = ["foo.cc"], 774 deps = [dep_name], 775 whole_archive_deps = [whole_archive_dep_name], 776 dynamic_deps = [dynamic_dep_name], 777 tags = ["manual"], 778 ) 779 android_test_name = test_name + "_android" 780 linux_test_name = test_name + "_linux" 781 target_provides_androidmk_info_test( 782 name = android_test_name, 783 target_under_test = name, 784 expected_static_libs = [dep_name, "libc++demangle"], 785 expected_whole_static_libs = [whole_archive_dep_name], 786 expected_shared_libs = [dynamic_dep_name, "libc++", "libc_stub_libs-current", "libdl_stub_libs-current", "libm_stub_libs-current"], 787 target_compatible_with = ["//build/bazel_common_rules/platforms/os:android"], 788 ) 789 target_provides_androidmk_info_test( 790 name = linux_test_name, 791 target_under_test = name, 792 expected_static_libs = [dep_name], 793 expected_whole_static_libs = [whole_archive_dep_name], 794 expected_shared_libs = [dynamic_dep_name, "libc++"], 795 target_compatible_with = ["//build/bazel_common_rules/platforms/os:linux"], 796 ) 797 return [ 798 android_test_name, 799 linux_test_name, 800 ] 801 802def _cc_library_minimal_runtime_linked_impl(ctx): 803 env = analysistest.begin(ctx) 804 libraries = [ 805 lib 806 for input in ctx.attr._ubsan_library[CcInfo].linking_context.linker_inputs.to_list() 807 for lib in input.libraries 808 ] 809 ubsan_lib_path = libraries[0].static_library.path 810 811 actions = analysistest.target_actions(env) 812 found_minimal_runtime = False 813 for action in actions: 814 if action.mnemonic != "CppLink": 815 continue 816 for i in range(len(action.argv)): 817 arg = action.argv[i] 818 if ubsan_lib_path in arg: 819 found_minimal_runtime = True 820 if i > 0: 821 prev_arg = action.argv[i - 1] 822 asserts.true( 823 env, 824 "-Wl,--whole-archive" != prev_arg, 825 "expected %s to not be a whole archive but it was" % [prev_arg, arg], 826 ) 827 828 asserts.true( 829 env, 830 found_minimal_runtime, 831 "Expected to find ubsan minimal runtime, but did not.", 832 ) 833 834 return analysistest.end(env) 835 836_cc_library_minimal_runtime_linked_test = analysistest.make( 837 _cc_library_minimal_runtime_linked_impl, 838 attrs = { 839 "_ubsan_library": attr.label( 840 default = "//prebuilts/clang/host/linux-x86:libclang_rt.ubsan_minimal", 841 doc = "The library target corresponding to the undefined " + 842 "behavior sanitizer library to be used", 843 ), 844 }, 845) 846 847def _cc_library_minimal_runtime_linked_from_dep(): 848 name = "cc_library_minimal_runtime_linked_from_dep" 849 dep_name = "dep_" + name 850 test_name = name + "_test" 851 852 cc_library_static( 853 name = dep_name, 854 srcs = ["foo.cc"], 855 tags = ["manual"], 856 features = ["ubsan_undefined"], 857 ) 858 cc_library_shared( 859 name = name, 860 srcs = ["bar.cc"], 861 implementation_deps = [dep_name], 862 tags = ["manual"], 863 ) 864 _cc_library_minimal_runtime_linked_test( 865 name = test_name, 866 target_under_test = name + "_unstripped", 867 ) 868 return test_name 869 870def _cc_library_minimal_runtime_linked(): 871 name = "cc_library_minimal_runtime_linked" 872 test_name = name + "_test" 873 874 cc_library_shared( 875 name = name, 876 srcs = ["bar.cc"], 877 features = ["ubsan_undefined"], 878 tags = ["manual"], 879 ) 880 _cc_library_minimal_runtime_linked_test( 881 name = test_name, 882 target_under_test = name + "_unstripped", 883 ) 884 return test_name 885 886def _cc_library_link_as_whole_archive_test_impl(ctx): 887 env = analysistest.begin(ctx) 888 actions = [a for a in analysistest.target_actions(env) if a.mnemonic == "CppLink"] 889 asserts.true( 890 env, 891 len(actions) == 1, 892 "Cpp link action not found: %s" % actions, 893 ) 894 action = actions[0] 895 whole_arch_libs = [] 896 argv_len = len(action.argv) 897 whole_archive_start = False 898 for i in range(argv_len): 899 if action.argv[i] == "-Wl,--whole-archive": 900 whole_archive_start = True 901 elif action.argv[i] == "-Wl,--no-whole-archive": 902 whole_archive_start = False 903 elif whole_archive_start: 904 whole_arch_libs.append(action.argv[i]) 905 906 for lib in ctx.attr.expected_libs: 907 full_path = get_output_and_package_dir_based_path(env, lib) 908 if full_path not in whole_arch_libs: 909 fail("{} is not in list of libs for linking as whole archive deps {}".format(lib, action.argv)) 910 911 return analysistest.end(env) 912 913cc_library_link_as_whole_archive_test = analysistest.make( 914 _cc_library_link_as_whole_archive_test_impl, 915 attrs = { 916 "expected_libs": attr.string_list(), 917 }, 918) 919 920def _cc_library_shared_links_whole_archive_deps_separately(): 921 name = "cc_library_shared_links_whole_archive_deps_separately" 922 dep_name = name + "_dep" 923 test_name = name + "_test" 924 925 cc_library_static( 926 name = dep_name, 927 tags = ["manual"], 928 ) 929 930 cc_library_shared( 931 name = name, 932 whole_archive_deps = [dep_name], 933 tags = ["manual"], 934 ) 935 936 cc_library_link_as_whole_archive_test( 937 name = test_name, 938 target_under_test = name + "_unstripped", 939 expected_libs = ["libcc_library_shared_links_whole_archive_deps_separately_dep.a"], 940 ) 941 942 return test_name 943 944# Test that an error is raised if a user requests a library that is not available in the toolchain. 945def _cc_library_shared_bad_linkopts_test(): 946 subject_name = "cc_library_shared_bad_linkopts" 947 test_name = subject_name + "_test" 948 949 cc_library_shared( 950 name = subject_name, 951 linkopts = ["-lunknown"], 952 tags = ["manual"], 953 ) 954 cc_bad_linkopts_test( 955 name = test_name, 956 target_under_test = subject_name, 957 ) 958 return test_name 959 960def cc_library_shared_test_suite(name): 961 native.genrule(name = "cc_library_shared_hdr", cmd = "null", outs = ["cc_shared_f.h"], tags = ["manual"]) 962 963 native.test_suite( 964 name = name, 965 tests = [ 966 _cc_library_shared_suffix(), 967 _cc_library_shared_empty_suffix(), 968 _cc_library_with_stem(), 969 _cc_library_shared_propagates_deps(), 970 _cc_library_shared_propagates_whole_archive_deps(), 971 _cc_library_shared_propagates_dynamic_deps(), 972 _cc_library_shared_does_not_propagate_implementation_deps(), 973 _cc_library_shared_does_not_propagate_implementation_whole_archive_deps(), 974 _cc_library_shared_does_not_propagate_implementation_dynamic_deps(), 975 _cc_libary_shared_propagate_fdo_profile_to_whole_archive_deps(), 976 _cc_library_shared_does_not_propagate_fdo_profile_to_dynamic_deps(), 977 _fdo_profile_transition_correctly_set_and_unset_fdo_profile(), 978 _cc_library_with_fdo_profile_link_flags(), 979 _cc_library_disable_fdo_optimization_if_coverage_is_enabled_test(), 980 _cc_library_set_defines_for_stubs(), 981 _cc_library_minimal_runtime_linked_from_dep(), 982 _cc_library_minimal_runtime_linked(), 983 _cc_library_shared_links_whole_archive_deps_separately(), 984 _cc_library_shared_bad_linkopts_test(), 985 ] + _cc_library_shared_provides_androidmk_info(), 986 ) 987