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:paths.bzl", "paths") 16load("@bazel_skylib//lib:unittest.bzl", "analysistest", "asserts") 17load("//build/bazel/rules/cc:cc_binary.bzl", "cc_binary") 18load("//build/bazel/rules/cc:cc_library_headers.bzl", "cc_library_headers") 19load("//build/bazel/rules/cc:cc_library_shared.bzl", "cc_library_shared") 20load("//build/bazel/rules/cc:cc_library_static.bzl", "cc_library_static") 21load("//build/bazel/rules/cc:cc_prebuilt_library_static.bzl", "cc_prebuilt_library_static") 22load( 23 "//build/bazel/rules/test_common:flags.bzl", 24 "action_flags_absent_for_mnemonic_test", 25 "action_flags_present_only_for_mnemonic_test", 26) 27load("//build/bazel/rules/test_common:paths.bzl", "get_output_and_package_dir_based_path", "get_package_dir_based_path") 28load("//build/bazel/rules/test_common:rules.bzl", "expect_failure_test") 29load(":cc_library_common_test.bzl", "target_provides_androidmk_info_test", "target_sdk_variant_provides_androidmk_info_test") 30 31def _cc_library_static_propagating_compilation_context_test_impl(ctx): 32 env = analysistest.begin(ctx) 33 target = analysistest.target_under_test(env) 34 cc_info = target[CcInfo] 35 compilation_context = cc_info.compilation_context 36 37 header_paths = [f.short_path for f in compilation_context.headers.to_list()] 38 for hdr in ctx.files.expected_hdrs: 39 asserts.true( 40 env, 41 hdr.short_path in header_paths, 42 "Did not find {hdr} in includes: {hdrs}.".format(hdr = hdr, hdrs = compilation_context.headers), 43 ) 44 45 for hdr in ctx.files.expected_absent_hdrs: 46 asserts.true( 47 env, 48 hdr not in header_paths, 49 "Found {hdr} in includes: {hdrs}, should not be present.".format(hdr = hdr, hdrs = compilation_context.headers), 50 ) 51 52 for include in ctx.attr.expected_includes: 53 absolute_include = get_package_dir_based_path(env, include) 54 asserts.true( 55 env, 56 absolute_include in compilation_context.includes.to_list(), 57 "Did not find {include} in includes: {includes}.".format(include = include, includes = compilation_context.includes), 58 ) 59 60 for include in ctx.attr.expected_absent_includes: 61 absolute_include = get_package_dir_based_path(env, include) 62 asserts.true( 63 env, 64 absolute_include not in compilation_context.includes.to_list(), 65 "Found {include} in includes: {includes}, was expected to be absent".format(include = include, includes = compilation_context.includes), 66 ) 67 68 for include in ctx.attr.expected_system_includes: 69 absolute_include = get_package_dir_based_path(env, include) 70 asserts.true( 71 env, 72 absolute_include in compilation_context.system_includes.to_list(), 73 "Did not find {include} in system includes: {includes}.".format(include = include, includes = compilation_context.system_includes), 74 ) 75 76 for include in ctx.attr.expected_absent_system_includes: 77 absolute_include = get_package_dir_based_path(env, include) 78 asserts.true( 79 env, 80 absolute_include not in compilation_context.system_includes.to_list(), 81 "Found {include} in system includes: {includes}, was expected to be absent".format(include = include, includes = compilation_context.system_includes), 82 ) 83 84 return analysistest.end(env) 85 86_cc_library_static_propagating_compilation_context_test = analysistest.make( 87 _cc_library_static_propagating_compilation_context_test_impl, 88 attrs = { 89 "expected_hdrs": attr.label_list(), 90 "expected_absent_hdrs": attr.label_list(), 91 "expected_includes": attr.string_list(), 92 "expected_absent_includes": attr.string_list(), 93 "expected_system_includes": attr.string_list(), 94 "expected_absent_system_includes": attr.string_list(), 95 }, 96) 97 98def _cc_library_static_propagates_deps(): 99 name = "_cc_library_static_propagates_deps" 100 dep_name = name + "_dep" 101 test_name = name + "_test" 102 103 cc_library_static( 104 name = dep_name, 105 hdrs = [":hdr"], 106 export_includes = ["a/b/c"], 107 export_system_includes = ["d/e/f"], 108 tags = ["manual"], 109 ) 110 111 cc_library_static( 112 name = name, 113 deps = [dep_name], 114 tags = ["manual"], 115 ) 116 117 _cc_library_static_propagating_compilation_context_test( 118 name = test_name, 119 target_under_test = name, 120 expected_hdrs = [":hdr"], 121 expected_includes = ["a/b/c"], 122 expected_system_includes = ["d/e/f"], 123 ) 124 125 return test_name 126 127def _cc_library_static_propagates_whole_archive_deps(): 128 name = "_cc_library_static_propagates_whole_archive_deps" 129 dep_name = name + "_dep" 130 test_name = name + "_test" 131 132 cc_library_static( 133 name = dep_name, 134 hdrs = [":hdr"], 135 export_includes = ["a/b/c"], 136 export_system_includes = ["d/e/f"], 137 tags = ["manual"], 138 ) 139 140 cc_library_static( 141 name = name, 142 whole_archive_deps = [dep_name], 143 tags = ["manual"], 144 ) 145 146 _cc_library_static_propagating_compilation_context_test( 147 name = test_name, 148 target_under_test = name, 149 expected_hdrs = [":hdr"], 150 expected_includes = ["a/b/c"], 151 expected_system_includes = ["d/e/f"], 152 ) 153 154 return test_name 155 156def _cc_library_static_propagates_dynamic_deps(): 157 name = "_cc_library_static_propagates_dynamic_deps" 158 dep_name = name + "_dep" 159 test_name = name + "_test" 160 161 cc_library_shared( 162 name = dep_name, 163 hdrs = [":hdr"], 164 export_includes = ["a/b/c"], 165 export_system_includes = ["d/e/f"], 166 tags = ["manual"], 167 ) 168 169 cc_library_static( 170 name = name, 171 dynamic_deps = [dep_name], 172 tags = ["manual"], 173 ) 174 175 _cc_library_static_propagating_compilation_context_test( 176 name = test_name, 177 target_under_test = name, 178 expected_hdrs = [":hdr"], 179 expected_includes = ["a/b/c"], 180 expected_system_includes = ["d/e/f"], 181 ) 182 183 return test_name 184 185def _cc_library_static_does_not_propagate_implementation_deps(): 186 name = "_cc_library_static_does_not_propagate_implementation_deps" 187 dep_name = name + "_dep" 188 test_name = name + "_test" 189 190 cc_library_static( 191 name = dep_name, 192 hdrs = [":hdr"], 193 export_includes = ["a/b/c"], 194 export_system_includes = ["d/e/f"], 195 tags = ["manual"], 196 ) 197 198 cc_library_static( 199 name = name, 200 implementation_deps = [dep_name], 201 tags = ["manual"], 202 ) 203 204 _cc_library_static_propagating_compilation_context_test( 205 name = test_name, 206 target_under_test = name, 207 expected_absent_hdrs = [":hdr"], 208 expected_absent_includes = ["a/b/c"], 209 expected_absent_system_includes = ["d/e/f"], 210 ) 211 212 return test_name 213 214def _cc_library_static_does_not_propagate_implementation_whole_archive_deps(): 215 name = "_cc_library_static_does_not_propagate_implementation_whole_archive_deps" 216 dep_name = name + "_dep" 217 test_name = name + "_test" 218 219 cc_library_static( 220 name = dep_name, 221 hdrs = [":hdr"], 222 export_includes = ["a/b/c"], 223 export_system_includes = ["d/e/f"], 224 tags = ["manual"], 225 ) 226 227 cc_library_static( 228 name = name, 229 implementation_whole_archive_deps = [dep_name], 230 tags = ["manual"], 231 ) 232 233 _cc_library_static_propagating_compilation_context_test( 234 name = test_name, 235 target_under_test = name, 236 expected_absent_hdrs = [":hdr"], 237 expected_absent_includes = ["a/b/c"], 238 expected_absent_system_includes = ["d/e/f"], 239 ) 240 241 return test_name 242 243def _cc_library_static_does_not_propagate_implementation_dynamic_deps(): 244 name = "_cc_library_static_does_not_propagate_implementation_dynamic_deps" 245 dep_name = name + "_dep" 246 test_name = name + "_test" 247 248 cc_library_shared( 249 name = dep_name, 250 hdrs = [":hdr"], 251 export_includes = ["a/b/c"], 252 export_system_includes = ["d/e/f"], 253 tags = ["manual"], 254 ) 255 256 cc_library_static( 257 name = name, 258 implementation_dynamic_deps = [dep_name], 259 tags = ["manual"], 260 ) 261 262 _cc_library_static_propagating_compilation_context_test( 263 name = test_name, 264 target_under_test = name, 265 expected_absent_hdrs = [":hdr"], 266 expected_absent_includes = ["a/b/c"], 267 expected_absent_system_includes = ["d/e/f"], 268 ) 269 270 return test_name 271 272def _cc_rules_do_not_allow_absolute_includes(): 273 name = "cc_rules_do_not_allow_absolute_includes" 274 test_names = [] 275 276 DISALLOWED_INCLUDE_DIRS = [ 277 "art", 278 "art/libnativebridge", 279 "art/libnativeloader", 280 "libcore", 281 "libnativehelper", 282 "external/apache-harmony", 283 "external/apache-xml", 284 "external/boringssl", 285 "external/bouncycastle", 286 "external/conscrypt", 287 "external/icu", 288 "external/okhttp", 289 "external/vixl", 290 "external/wycheproof", 291 ] 292 293 for include_dir in DISALLOWED_INCLUDE_DIRS: 294 binary_name = name + "_binary" + "_" + include_dir 295 library_headers_name = name + "_library_headers" + "_" + include_dir 296 library_shared_name = name + "_library_shared" + "_" + include_dir 297 library_static_name = name + "_library_static" + "_" + include_dir 298 299 cc_binary( 300 name = binary_name, 301 absolute_includes = [include_dir], 302 tags = ["manual"], 303 ) 304 cc_library_headers( 305 name = library_headers_name, 306 export_absolute_includes = [include_dir], 307 tags = ["manual"], 308 ) 309 cc_library_shared( 310 name = library_shared_name, 311 absolute_includes = [include_dir], 312 tags = ["manual"], 313 ) 314 cc_library_static( 315 name = library_static_name, 316 absolute_includes = [include_dir], 317 tags = ["manual"], 318 ) 319 320 for target in [ 321 binary_name, 322 library_headers_name, 323 library_static_name, 324 library_shared_name, 325 ]: 326 test_name = target + "_" + include_dir + "_test" 327 test_names.append(test_name) 328 expect_failure_test( 329 name = test_name, 330 target_under_test = target, 331 ) 332 333 return test_names 334 335def _cc_library_static_links_against_prebuilt_library_test_impl(ctx): 336 env = analysistest.begin(ctx) 337 actions = analysistest.target_actions(env) 338 339 asserts.equals(env, 2, len(actions), "Expected actions, got %s" % actions) 340 341 argv = actions[0].argv 342 expected_output_action1 = get_output_and_package_dir_based_path(env, "libcc_library_static_links_against_prebuilt_library_objs_only.a") 343 asserts.equals(env, 5, len(argv)) 344 asserts.equals(env, "crsPD", argv[1]) 345 asserts.equals(env, expected_output_action1, argv[2]) 346 asserts.equals(env, get_output_and_package_dir_based_path(env, paths.join("_objs", "cc_library_static_links_against_prebuilt_library_cpp", "bar.o")), argv[3]) 347 asserts.equals(env, "--format=gnu", argv[4]) 348 349 argv = actions[1].argv 350 asserts.equals(env, 6, len(argv)) 351 asserts.equals(env, "cqsL", argv[1]) 352 asserts.equals(env, get_output_and_package_dir_based_path(env, "libcc_library_static_links_against_prebuilt_library.a"), argv[2]) 353 asserts.equals(env, "--format=gnu", argv[3]) 354 asserts.equals(env, expected_output_action1, argv[4]) 355 asserts.equals(env, get_package_dir_based_path(env, "foo.a"), argv[5]) 356 357 return analysistest.end(env) 358 359_cc_library_static_links_against_prebuilt_library_test = analysistest.make(_cc_library_static_links_against_prebuilt_library_test_impl) 360 361def _cc_library_static_links_against_prebuilt_library(): 362 name = "cc_library_static_links_against_prebuilt_library" 363 test_name = name + "_test" 364 dep_name = name + "_dep" 365 366 cc_prebuilt_library_static( 367 name = dep_name, 368 static_library = "foo.a", 369 tags = ["manual"], 370 ) 371 372 cc_library_static( 373 name = name, 374 srcs = ["bar.c"], 375 whole_archive_deps = [dep_name], 376 tags = ["manual"], 377 ) 378 379 _cc_library_static_links_against_prebuilt_library_test( 380 name = test_name, 381 target_under_test = name, 382 ) 383 384 return test_name 385 386def _cc_library_static_linking_object_ordering_test_impl(ctx): 387 env = analysistest.begin(ctx) 388 actions = analysistest.target_actions(env) 389 390 asserts.equals(env, 1, len(actions), "Expected actions, got %s" % actions) 391 392 outputs = actions[0].outputs.to_list() 393 argv = actions[0].argv 394 asserts.equals(env, 4 + len(ctx.attr.expected_objects_in_order), len(argv)) 395 asserts.equals(env, "crsPD", argv[1]) 396 asserts.equals(env, outputs[0].path, argv[2]) 397 398 for i in range(len(ctx.attr.expected_objects_in_order)): 399 obj = ctx.attr.expected_objects_in_order[i] 400 asserts.equals(env, obj, paths.basename(argv[3 + i])) 401 402 asserts.equals(env, "--format=gnu", argv[-1]) 403 404 return analysistest.end(env) 405 406_cc_library_static_linking_object_ordering_test = analysistest.make( 407 _cc_library_static_linking_object_ordering_test_impl, 408 attrs = { 409 "expected_objects_in_order": attr.string_list(), 410 }, 411) 412 413def _cc_library_static_whole_archive_deps_objects_precede_target_objects(): 414 name = "_cc_library_static_whole_archive_deps_objects_precede_target_objects" 415 dep_name = name + "_dep" 416 test_name = name + "_test" 417 418 cc_library_static( 419 name = dep_name, 420 srcs = ["first.c"], 421 tags = ["manual"], 422 ) 423 424 cc_library_static( 425 name = name, 426 srcs = ["second.c"], 427 whole_archive_deps = [dep_name], 428 tags = ["manual"], 429 ) 430 431 _cc_library_static_linking_object_ordering_test( 432 name = test_name, 433 target_under_test = name, 434 expected_objects_in_order = [ 435 "first.o", 436 "second.o", 437 ], 438 ) 439 440 return test_name 441 442def _cc_library_static_whole_archive_deps_objects_excluded_when_shared_linking(): 443 name = "cc_library_static_whole_archive_deps_objects_excluded_when_shared_linking" 444 dep_name = name + "_dep" 445 test_name = name + "_test" 446 447 cc_library_static( 448 name = dep_name, 449 srcs = ["first.c"], 450 tags = ["manual"], 451 ) 452 453 cc_library_static( 454 name = name, 455 shared_linking = True, 456 srcs = ["second.c"], 457 whole_archive_deps = [dep_name], 458 tags = ["manual"], 459 ) 460 461 _cc_library_static_linking_object_ordering_test( 462 name = test_name, 463 target_under_test = name, 464 expected_objects_in_order = [ 465 "second.o", 466 ], 467 ) 468 469 return test_name 470 471def _cc_library_static_provides_androidmk_info(): 472 name = "cc_library_static_provides_androidmk_info" 473 dep_name = name + "_static_dep" 474 whole_archive_dep_name = name + "_whole_archive_dep" 475 dynamic_dep_name = name + "_dynamic_dep" 476 test_name = name + "_test" 477 478 cc_library_static( 479 name = dep_name, 480 srcs = ["foo.c"], 481 tags = ["manual"], 482 ) 483 cc_library_static( 484 name = whole_archive_dep_name, 485 srcs = ["foo.c"], 486 tags = ["manual"], 487 ) 488 cc_library_shared( 489 name = dynamic_dep_name, 490 srcs = ["foo.c"], 491 tags = ["manual"], 492 ) 493 cc_library_static( 494 name = name, 495 srcs = ["foo.cc"], 496 deps = [dep_name], 497 whole_archive_deps = [whole_archive_dep_name], 498 dynamic_deps = [dynamic_dep_name], 499 tags = ["manual"], 500 ) 501 android_test_name = test_name + "_android" 502 android_sdk_variant_test_name = test_name + "_android_sdk_variant" 503 linux_test_name = test_name + "_linux" 504 target_provides_androidmk_info_test( 505 name = android_test_name, 506 target_under_test = name, 507 expected_static_libs = [dep_name, "libc++_static", "libc++demangle"], 508 expected_whole_static_libs = [whole_archive_dep_name], 509 expected_shared_libs = [dynamic_dep_name, "libc_stub_libs-current", "libdl_stub_libs-current", "libm_stub_libs-current"], 510 target_compatible_with = ["//build/bazel_common_rules/platforms/os:android"], 511 ) 512 target_sdk_variant_provides_androidmk_info_test( 513 name = android_sdk_variant_test_name, 514 target_under_test = name, 515 expected_static_libs = [dep_name], 516 expected_whole_static_libs = [whole_archive_dep_name], 517 expected_shared_libs = [ 518 dynamic_dep_name, 519 # bionic NDK stubs from system_dynamic_dep_defaults 520 "libc.ndk_stub_libs-current", 521 "libdl.ndk_stub_libs-current", 522 "libm.ndk_stub_libs-current", 523 # from STL: "ndk_system". 524 # sdk variants default to system STL. 525 "libstdc++", 526 ], 527 target_compatible_with = ["//build/bazel_common_rules/platforms/os:android"], 528 ) 529 target_provides_androidmk_info_test( 530 name = linux_test_name, 531 target_under_test = name, 532 expected_static_libs = [dep_name, "libc++_static"], 533 expected_whole_static_libs = [whole_archive_dep_name], 534 expected_shared_libs = [dynamic_dep_name], 535 target_compatible_with = ["//build/bazel_common_rules/platforms/os:linux"], 536 ) 537 return [ 538 android_test_name, 539 android_sdk_variant_test_name, 540 linux_test_name, 541 ] 542 543def _cc_library_static_link_action_should_not_have_arch_cflags(): 544 name = "cc_library_static_link_action_should_not_have_cflags" 545 cpp_compile_test_name = name + "_CppCompile_test" 546 cpp_link_test_name = name + "_CppLink_test" 547 548 # https://cs.android.com/android/platform/build/soong/+/master:cc/config/arm_device.go;l=57-59;drc=de7c7847e7e028d46fdff8268689f30163c4c231 549 arm_armv7_a_cflags = ["-march=armv7-a", "-mfloat-abi=softfp"] 550 551 cc_library_static( 552 name = name, 553 srcs = ["foo.cpp"], 554 tags = ["manual"], 555 ) 556 557 action_flags_present_only_for_mnemonic_test( 558 name = cpp_compile_test_name, 559 target_under_test = name + "_cpp", 560 mnemonics = ["CppCompile"], 561 expected_flags = arm_armv7_a_cflags, 562 target_compatible_with = [ 563 "//build/bazel_common_rules/platforms/os:android", 564 "//build/bazel/platforms/arch/variants:armv7-a-neon", 565 ], 566 ) 567 568 action_flags_absent_for_mnemonic_test( 569 name = cpp_link_test_name, 570 target_under_test = name, 571 mnemonics = ["CppLink"], 572 expected_absent_flags = arm_armv7_a_cflags, 573 target_compatible_with = [ 574 "//build/bazel_common_rules/platforms/os:android", 575 "//build/bazel/platforms/arch/variants:armv7-a-neon", 576 ], 577 ) 578 579 return [ 580 cpp_compile_test_name, 581 cpp_link_test_name, 582 ] 583 584def _cc_library_static_defines_do_not_check_manual_binder_interfaces(): 585 name = "_cc_library_static_defines_do_not_check_manual_binder_interfaces" 586 cpp_lib_name = name + "_cpp" 587 cpp_test_name = cpp_lib_name + "_test" 588 c_lib_name = name + "_c" 589 c_test_name = c_lib_name + "_test" 590 591 cc_library_static( 592 name = name, 593 srcs = ["a.cpp"], 594 srcs_c = ["b.c"], 595 tags = ["manual"], 596 ) 597 action_flags_present_only_for_mnemonic_test( 598 name = cpp_test_name, 599 target_under_test = cpp_lib_name, 600 mnemonics = ["CppCompile"], 601 expected_flags = [ 602 "-DDO_NOT_CHECK_MANUAL_BINDER_INTERFACES", 603 ], 604 ) 605 action_flags_present_only_for_mnemonic_test( 606 name = c_test_name, 607 target_under_test = c_lib_name, 608 mnemonics = ["CppCompile"], 609 expected_flags = [ 610 "-DDO_NOT_CHECK_MANUAL_BINDER_INTERFACES", 611 ], 612 ) 613 614 non_allowlisted_package_cpp_name = name + "_non_allowlisted_package_cpp" 615 action_flags_absent_for_mnemonic_test( 616 name = non_allowlisted_package_cpp_name, 617 target_under_test = "//build/bazel/examples/cc:foo_static_cpp", 618 mnemonics = ["CppCompile"], 619 expected_absent_flags = [ 620 "-DDO_NOT_CHECK_MANUAL_BINDER_INTERFACES", 621 ], 622 ) 623 624 return [ 625 cpp_test_name, 626 c_test_name, 627 non_allowlisted_package_cpp_name, 628 ] 629 630def cc_library_static_test_suite(name): 631 native.genrule(name = "hdr", cmd = "null", outs = ["f.h"], tags = ["manual"]) 632 633 native.test_suite( 634 name = name, 635 tests = [ 636 _cc_library_static_propagates_deps(), 637 _cc_library_static_propagates_whole_archive_deps(), 638 _cc_library_static_propagates_dynamic_deps(), 639 _cc_library_static_does_not_propagate_implementation_deps(), 640 _cc_library_static_does_not_propagate_implementation_whole_archive_deps(), 641 _cc_library_static_does_not_propagate_implementation_dynamic_deps(), 642 _cc_library_static_links_against_prebuilt_library(), 643 _cc_library_static_whole_archive_deps_objects_precede_target_objects(), 644 _cc_library_static_whole_archive_deps_objects_excluded_when_shared_linking(), 645 ] + ( 646 _cc_rules_do_not_allow_absolute_includes() + 647 _cc_library_static_provides_androidmk_info() + 648 _cc_library_static_link_action_should_not_have_arch_cflags() + 649 _cc_library_static_defines_do_not_check_manual_binder_interfaces() 650 ), 651 ) 652