1// Copyright 2021 Google Inc. All rights reserved. 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 15package bp2build 16 17import ( 18 "fmt" 19 "strings" 20 "testing" 21 22 "android/soong/android" 23 "android/soong/cc" 24 "android/soong/genrule" 25) 26 27const ( 28 ccBinaryTypePlaceHolder = "{rule_name}" 29) 30 31type testBazelTarget struct { 32 typ string 33 name string 34 attrs AttrNameToString 35} 36 37func generateBazelTargetsForTest(targets []testBazelTarget, hod android.HostOrDeviceSupported) []string { 38 ret := make([]string, 0, len(targets)) 39 for _, t := range targets { 40 attrs := t.attrs.clone() 41 ret = append(ret, makeBazelTargetHostOrDevice(t.typ, t.name, attrs, hod)) 42 } 43 return ret 44} 45 46type ccBinaryBp2buildTestCase struct { 47 description string 48 filesystem map[string]string 49 blueprint string 50 targets []testBazelTarget 51} 52 53func registerCcBinaryModuleTypes(ctx android.RegistrationContext) { 54 cc.RegisterCCBuildComponents(ctx) 55 ctx.RegisterModuleType("filegroup", android.FileGroupFactory) 56 ctx.RegisterModuleType("cc_library_static", cc.LibraryStaticFactory) 57 ctx.RegisterModuleType("cc_library", cc.LibraryFactory) 58 ctx.RegisterModuleType("genrule", genrule.GenRuleFactory) 59} 60 61var binaryReplacer = strings.NewReplacer(ccBinaryTypePlaceHolder, "cc_binary") 62var hostBinaryReplacer = strings.NewReplacer(ccBinaryTypePlaceHolder, "cc_binary_host") 63 64func runCcBinaryTests(t *testing.T, tc ccBinaryBp2buildTestCase) { 65 t.Helper() 66 runCcBinaryTestCase(t, tc) 67 runCcHostBinaryTestCase(t, tc) 68} 69 70func runCcBinaryTestCase(t *testing.T, testCase ccBinaryBp2buildTestCase) { 71 t.Helper() 72 moduleTypeUnderTest := "cc_binary" 73 74 description := fmt.Sprintf("%s %s", moduleTypeUnderTest, testCase.description) 75 t.Run(description, func(t *testing.T) { 76 t.Helper() 77 RunBp2BuildTestCase(t, registerCcBinaryModuleTypes, Bp2buildTestCase{ 78 ExpectedBazelTargets: generateBazelTargetsForTest(testCase.targets, android.DeviceSupported), 79 ModuleTypeUnderTest: moduleTypeUnderTest, 80 ModuleTypeUnderTestFactory: cc.BinaryFactory, 81 Description: description, 82 Blueprint: binaryReplacer.Replace(testCase.blueprint), 83 Filesystem: testCase.filesystem, 84 }) 85 }) 86} 87 88func runCcHostBinaryTestCase(t *testing.T, testCase ccBinaryBp2buildTestCase) { 89 t.Helper() 90 moduleTypeUnderTest := "cc_binary_host" 91 description := fmt.Sprintf("%s %s", moduleTypeUnderTest, testCase.description) 92 t.Run(description, func(t *testing.T) { 93 RunBp2BuildTestCase(t, registerCcBinaryModuleTypes, Bp2buildTestCase{ 94 ExpectedBazelTargets: generateBazelTargetsForTest(testCase.targets, android.HostSupported), 95 ModuleTypeUnderTest: moduleTypeUnderTest, 96 ModuleTypeUnderTestFactory: cc.BinaryHostFactory, 97 Description: description, 98 Blueprint: hostBinaryReplacer.Replace(testCase.blueprint), 99 Filesystem: testCase.filesystem, 100 }) 101 }) 102} 103 104func TestBasicCcBinary(t *testing.T) { 105 runCcBinaryTests(t, ccBinaryBp2buildTestCase{ 106 description: "basic -- properties -> attrs with little/no transformation", 107 filesystem: map[string]string{ 108 soongCcVersionLibBpPath: soongCcVersionLibBp, 109 }, 110 blueprint: ` 111{rule_name} { 112 name: "foo", 113 srcs: ["a.cc"], 114 local_include_dirs: ["dir"], 115 include_dirs: ["absolute_dir"], 116 cflags: ["-Dcopt"], 117 cppflags: ["-Dcppflag"], 118 conlyflags: ["-Dconlyflag"], 119 asflags: ["-Dasflag"], 120 ldflags: ["ld-flag"], 121 rtti: true, 122 strip: { 123 all: true, 124 keep_symbols: true, 125 keep_symbols_and_debug_frame: true, 126 keep_symbols_list: ["symbol"], 127 none: true, 128 }, 129 sdk_version: "current", 130 min_sdk_version: "29", 131 use_version_lib: true, 132} 133`, 134 targets: []testBazelTarget{ 135 {"cc_binary", "foo", AttrNameToString{ 136 "absolute_includes": `["absolute_dir"]`, 137 "asflags": `["-Dasflag"]`, 138 "conlyflags": `["-Dconlyflag"]`, 139 "copts": `["-Dcopt"]`, 140 "cppflags": `["-Dcppflag"]`, 141 "linkopts": `["ld-flag"]`, 142 "local_includes": `[ 143 "dir", 144 ".", 145 ]`, 146 "rtti": `True`, 147 "srcs": `["a.cc"]`, 148 "strip": `{ 149 "all": True, 150 "keep_symbols": True, 151 "keep_symbols_and_debug_frame": True, 152 "keep_symbols_list": ["symbol"], 153 "none": True, 154 }`, 155 "sdk_version": `"current"`, 156 "min_sdk_version": `"29"`, 157 "use_version_lib": `True`, 158 "whole_archive_deps": `["//build/soong/cc/libbuildversion:libbuildversion"]`, 159 }, 160 }, 161 }, 162 }) 163} 164 165func TestCcBinaryWithSharedLdflagDisableFeature(t *testing.T) { 166 runCcBinaryTests(t, ccBinaryBp2buildTestCase{ 167 description: `ldflag "-shared" disables static_flag feature`, 168 blueprint: ` 169{rule_name} { 170 name: "foo", 171 ldflags: ["-shared"], 172 include_build_directory: false, 173} 174`, 175 targets: []testBazelTarget{ 176 {"cc_binary", "foo", AttrNameToString{ 177 "features": `["-static_flag"]`, 178 "linkopts": `["-shared"]`, 179 }, 180 }, 181 }, 182 }) 183} 184 185func TestCcBinaryWithLinkStatic(t *testing.T) { 186 runCcBinaryTests(t, ccBinaryBp2buildTestCase{ 187 description: "link static", 188 blueprint: ` 189{rule_name} { 190 name: "foo", 191 static_executable: true, 192 include_build_directory: false, 193} 194`, 195 targets: []testBazelTarget{ 196 {"cc_binary", "foo", AttrNameToString{ 197 "linkshared": `False`, 198 }, 199 }, 200 }, 201 }) 202} 203 204func TestCcBinaryVersionScriptAndDynamicList(t *testing.T) { 205 runCcBinaryTests(t, ccBinaryBp2buildTestCase{ 206 description: `version script and dynamic list`, 207 blueprint: ` 208{rule_name} { 209 name: "foo", 210 include_build_directory: false, 211 version_script: "vs", 212 dynamic_list: "dynamic.list", 213} 214`, 215 targets: []testBazelTarget{ 216 {"cc_binary", "foo", AttrNameToString{ 217 "additional_linker_inputs": `[ 218 "vs", 219 "dynamic.list", 220 ]`, 221 "linkopts": `[ 222 "-Wl,--version-script,$(location vs)", 223 "-Wl,--dynamic-list,$(location dynamic.list)", 224 ]`, 225 }, 226 }, 227 }, 228 }) 229} 230 231func TestCcBinaryLdflagsSplitBySpaceExceptSoongAdded(t *testing.T) { 232 runCcBinaryTests(t, ccBinaryBp2buildTestCase{ 233 description: "ldflags are split by spaces except for the ones added by soong (version script and dynamic list)", 234 blueprint: ` 235{rule_name} { 236 name: "foo", 237 ldflags: [ 238 "--nospace_flag", 239 "-z spaceflag", 240 ], 241 version_script: "version_script", 242 dynamic_list: "dynamic.list", 243 include_build_directory: false, 244} 245`, 246 targets: []testBazelTarget{ 247 {"cc_binary", "foo", AttrNameToString{ 248 "additional_linker_inputs": `[ 249 "version_script", 250 "dynamic.list", 251 ]`, 252 "linkopts": `[ 253 "--nospace_flag", 254 "-z", 255 "spaceflag", 256 "-Wl,--version-script,$(location version_script)", 257 "-Wl,--dynamic-list,$(location dynamic.list)", 258 ]`, 259 }}}, 260 }) 261} 262 263func TestCcBinarySplitSrcsByLang(t *testing.T) { 264 runCcHostBinaryTestCase(t, ccBinaryBp2buildTestCase{ 265 description: "split srcs by lang", 266 blueprint: ` 267{rule_name} { 268 name: "foo", 269 srcs: [ 270 "asonly.S", 271 "conly.c", 272 "cpponly.cpp", 273 ":fg_foo", 274 ], 275 include_build_directory: false, 276} 277` + simpleModuleDoNotConvertBp2build("filegroup", "fg_foo"), 278 targets: []testBazelTarget{ 279 {"cc_binary", "foo", AttrNameToString{ 280 "srcs": `[ 281 "cpponly.cpp", 282 ":fg_foo_cpp_srcs", 283 ]`, 284 "srcs_as": `[ 285 "asonly.S", 286 ":fg_foo_as_srcs", 287 ]`, 288 "srcs_c": `[ 289 "conly.c", 290 ":fg_foo_c_srcs", 291 ]`, 292 }, 293 }, 294 }, 295 }) 296} 297 298func TestCcBinaryDoNotDistinguishBetweenDepsAndImplementationDeps(t *testing.T) { 299 runCcBinaryTestCase(t, ccBinaryBp2buildTestCase{ 300 description: "no implementation deps", 301 blueprint: ` 302genrule { 303 name: "generated_hdr", 304 cmd: "nothing to see here", 305 bazel_module: { bp2build_available: false }, 306} 307 308genrule { 309 name: "export_generated_hdr", 310 cmd: "nothing to see here", 311 bazel_module: { bp2build_available: false }, 312} 313 314{rule_name} { 315 name: "foo", 316 srcs: ["foo.cpp"], 317 shared_libs: ["implementation_shared_dep", "shared_dep"], 318 export_shared_lib_headers: ["shared_dep"], 319 static_libs: ["implementation_static_dep", "static_dep"], 320 export_static_lib_headers: ["static_dep", "whole_static_dep"], 321 whole_static_libs: ["not_explicitly_exported_whole_static_dep", "whole_static_dep"], 322 include_build_directory: false, 323 generated_headers: ["generated_hdr", "export_generated_hdr"], 324 export_generated_headers: ["export_generated_hdr"], 325} 326` + 327 simpleModuleDoNotConvertBp2build("cc_library_static", "static_dep") + 328 simpleModuleDoNotConvertBp2build("cc_library_static", "implementation_static_dep") + 329 simpleModuleDoNotConvertBp2build("cc_library_static", "whole_static_dep") + 330 simpleModuleDoNotConvertBp2build("cc_library_static", "not_explicitly_exported_whole_static_dep") + 331 simpleModuleDoNotConvertBp2build("cc_library", "shared_dep") + 332 simpleModuleDoNotConvertBp2build("cc_library", "implementation_shared_dep"), 333 targets: []testBazelTarget{ 334 {"cc_binary", "foo", AttrNameToString{ 335 "deps": `[ 336 ":implementation_static_dep", 337 ":static_dep", 338 ]`, 339 "dynamic_deps": `[ 340 ":implementation_shared_dep", 341 ":shared_dep", 342 ]`, 343 "srcs": `[ 344 "foo.cpp", 345 ":generated_hdr", 346 ":export_generated_hdr", 347 ]`, 348 "whole_archive_deps": `[ 349 ":not_explicitly_exported_whole_static_dep", 350 ":whole_static_dep", 351 ]`, 352 "local_includes": `["."]`, 353 }, 354 }, 355 }, 356 }) 357} 358 359func TestCcBinaryNocrtTests(t *testing.T) { 360 baseTestCases := []struct { 361 description string 362 soongProperty string 363 bazelAttr AttrNameToString 364 }{ 365 { 366 description: "nocrt: true", 367 soongProperty: `nocrt: true,`, 368 bazelAttr: AttrNameToString{"features": `["-link_crt"]`}, 369 }, 370 { 371 description: "nocrt: false", 372 soongProperty: `nocrt: false,`, 373 bazelAttr: AttrNameToString{}, 374 }, 375 { 376 description: "nocrt: not set", 377 bazelAttr: AttrNameToString{}, 378 }, 379 } 380 381 baseBlueprint := `{rule_name} { 382 name: "foo",%s 383 include_build_directory: false, 384} 385` 386 387 for _, btc := range baseTestCases { 388 prop := btc.soongProperty 389 if len(prop) > 0 { 390 prop = "\n" + prop 391 } 392 runCcBinaryTests(t, ccBinaryBp2buildTestCase{ 393 description: btc.description, 394 blueprint: fmt.Sprintf(baseBlueprint, prop), 395 targets: []testBazelTarget{ 396 {"cc_binary", "foo", btc.bazelAttr}, 397 }, 398 }) 399 } 400} 401 402func TestCcBinaryNo_libcrtTests(t *testing.T) { 403 baseTestCases := []struct { 404 description string 405 soongProperty string 406 bazelAttr AttrNameToString 407 }{ 408 { 409 description: "no_libcrt: true", 410 soongProperty: `no_libcrt: true,`, 411 bazelAttr: AttrNameToString{"features": `["-use_libcrt"]`}, 412 }, 413 { 414 description: "no_libcrt: false", 415 soongProperty: `no_libcrt: false,`, 416 bazelAttr: AttrNameToString{}, 417 }, 418 { 419 description: "no_libcrt: not set", 420 bazelAttr: AttrNameToString{}, 421 }, 422 } 423 424 baseBlueprint := `{rule_name} { 425 name: "foo",%s 426 include_build_directory: false, 427} 428` 429 430 for _, btc := range baseTestCases { 431 prop := btc.soongProperty 432 if len(prop) > 0 { 433 prop = "\n" + prop 434 } 435 runCcBinaryTests(t, ccBinaryBp2buildTestCase{ 436 description: btc.description, 437 blueprint: fmt.Sprintf(baseBlueprint, prop), 438 targets: []testBazelTarget{ 439 {"cc_binary", "foo", btc.bazelAttr}, 440 }, 441 }) 442 } 443} 444 445func TestCcBinaryPropertiesToFeatures(t *testing.T) { 446 baseTestCases := []struct { 447 description string 448 soongProperty string 449 bazelAttr AttrNameToString 450 }{ 451 { 452 description: "pack_relocation: true", 453 soongProperty: `pack_relocations: true,`, 454 bazelAttr: AttrNameToString{}, 455 }, 456 { 457 description: "pack_relocations: false", 458 soongProperty: `pack_relocations: false,`, 459 bazelAttr: AttrNameToString{"features": `["disable_pack_relocations"]`}, 460 }, 461 { 462 description: "pack_relocations: not set", 463 bazelAttr: AttrNameToString{}, 464 }, 465 { 466 description: "pack_relocation: true", 467 soongProperty: `allow_undefined_symbols: true,`, 468 bazelAttr: AttrNameToString{"features": `["-no_undefined_symbols"]`}, 469 }, 470 { 471 description: "allow_undefined_symbols: false", 472 soongProperty: `allow_undefined_symbols: false,`, 473 bazelAttr: AttrNameToString{}, 474 }, 475 { 476 description: "allow_undefined_symbols: not set", 477 bazelAttr: AttrNameToString{}, 478 }, 479 } 480 481 baseBlueprint := `{rule_name} { 482 name: "foo",%s 483 include_build_directory: false, 484} 485` 486 for _, btc := range baseTestCases { 487 prop := btc.soongProperty 488 if len(prop) > 0 { 489 prop = "\n" + prop 490 } 491 runCcBinaryTests(t, ccBinaryBp2buildTestCase{ 492 description: btc.description, 493 blueprint: fmt.Sprintf(baseBlueprint, prop), 494 targets: []testBazelTarget{ 495 {"cc_binary", "foo", btc.bazelAttr}, 496 }, 497 }) 498 } 499} 500 501func TestCcBinarySharedProto(t *testing.T) { 502 runCcBinaryTests(t, ccBinaryBp2buildTestCase{ 503 blueprint: soongCcProtoLibraries + `{rule_name} { 504 name: "foo", 505 srcs: ["foo.proto"], 506 proto: { 507 }, 508 include_build_directory: false, 509}`, 510 targets: []testBazelTarget{ 511 {"proto_library", "foo_proto", AttrNameToString{ 512 "srcs": `["foo.proto"]`, 513 }}, {"cc_lite_proto_library", "foo_cc_proto_lite", AttrNameToString{ 514 "deps": `[":foo_proto"]`, 515 }}, {"cc_binary", "foo", AttrNameToString{ 516 "dynamic_deps": `[":libprotobuf-cpp-lite"]`, 517 "whole_archive_deps": `[":foo_cc_proto_lite"]`, 518 }}, 519 }, 520 }) 521} 522 523func TestCcBinaryStaticProto(t *testing.T) { 524 runCcBinaryTests(t, ccBinaryBp2buildTestCase{ 525 blueprint: soongCcProtoLibraries + `{rule_name} { 526 name: "foo", 527 srcs: ["foo.proto"], 528 static_executable: true, 529 proto: { 530 }, 531 include_build_directory: false, 532}`, 533 targets: []testBazelTarget{ 534 {"proto_library", "foo_proto", AttrNameToString{ 535 "srcs": `["foo.proto"]`, 536 }}, {"cc_lite_proto_library", "foo_cc_proto_lite", AttrNameToString{ 537 "deps": `[":foo_proto"]`, 538 }}, {"cc_binary", "foo", AttrNameToString{ 539 "deps": `[":libprotobuf-cpp-lite"]`, 540 "whole_archive_deps": `[":foo_cc_proto_lite"]`, 541 "linkshared": `False`, 542 }}, 543 }, 544 }) 545} 546 547func TestCcBinaryConvertLex(t *testing.T) { 548 runCcBinaryTests(t, ccBinaryBp2buildTestCase{ 549 description: `.l and .ll sources converted to .c and .cc`, 550 blueprint: ` 551{rule_name} { 552 name: "foo", 553 srcs: ["foo.c", "bar.cc", "foo1.l", "foo2.l", "bar1.ll", "bar2.ll"], 554 lex: { flags: ["--foo_opt", "--bar_opt"] }, 555 include_build_directory: false, 556} 557`, 558 targets: []testBazelTarget{ 559 {"genlex", "foo_genlex_l", AttrNameToString{ 560 "srcs": `[ 561 "foo1.l", 562 "foo2.l", 563 ]`, 564 "lexopts": `[ 565 "--foo_opt", 566 "--bar_opt", 567 ]`, 568 }}, 569 {"genlex", "foo_genlex_ll", AttrNameToString{ 570 "srcs": `[ 571 "bar1.ll", 572 "bar2.ll", 573 ]`, 574 "lexopts": `[ 575 "--foo_opt", 576 "--bar_opt", 577 ]`, 578 }}, 579 {"cc_binary", "foo", AttrNameToString{ 580 "srcs": `[ 581 "bar.cc", 582 ":foo_genlex_ll", 583 ]`, 584 "srcs_c": `[ 585 "foo.c", 586 ":foo_genlex_l", 587 ]`, 588 }}, 589 }, 590 }) 591} 592 593func TestCcBinaryRuntimeLibs(t *testing.T) { 594 runCcBinaryTests(t, ccBinaryBp2buildTestCase{ 595 description: "cc_binary with runtime libs", 596 blueprint: ` 597cc_library { 598 name: "bar", 599 srcs: ["b.cc"], 600} 601 602{rule_name} { 603 name: "foo", 604 srcs: ["a.cc"], 605 runtime_libs: ["bar"], 606} 607`, 608 targets: []testBazelTarget{ 609 {"cc_library_static", "bar_bp2build_cc_library_static", AttrNameToString{ 610 "local_includes": `["."]`, 611 "srcs": `["b.cc"]`, 612 "target_compatible_with": `["//build/bazel/platforms/os:android"]`, 613 }, 614 }, 615 {"cc_library_shared", "bar", AttrNameToString{ 616 "local_includes": `["."]`, 617 "srcs": `["b.cc"]`, 618 "target_compatible_with": `["//build/bazel/platforms/os:android"]`, 619 }, 620 }, 621 {"cc_binary", "foo", AttrNameToString{ 622 "local_includes": `["."]`, 623 "srcs": `["a.cc"]`, 624 "runtime_deps": `[":bar"]`, 625 }, 626 }, 627 }, 628 }) 629} 630 631func TestCcBinaryWithInstructionSet(t *testing.T) { 632 runCcBinaryTests(t, ccBinaryBp2buildTestCase{ 633 description: "instruction set", 634 blueprint: ` 635{rule_name} { 636 name: "foo", 637 arch: { 638 arm: { 639 instruction_set: "arm", 640 } 641 } 642} 643`, 644 targets: []testBazelTarget{ 645 {"cc_binary", "foo", AttrNameToString{ 646 "features": `select({ 647 "//build/bazel/platforms/arch:arm": [ 648 "arm_isa_arm", 649 "-arm_isa_thumb", 650 ], 651 "//conditions:default": [], 652 })`, 653 "local_includes": `["."]`, 654 }}, 655 }, 656 }) 657} 658 659func TestCcBinaryEmptySuffix(t *testing.T) { 660 runCcBinaryTests(t, ccBinaryBp2buildTestCase{ 661 description: "binary with empty suffix", 662 blueprint: ` 663{rule_name} { 664 name: "foo", 665 suffix: "", 666}`, 667 targets: []testBazelTarget{ 668 {"cc_binary", "foo", AttrNameToString{ 669 "local_includes": `["."]`, 670 "suffix": `""`, 671 }}, 672 }, 673 }) 674} 675 676func TestCcBinarySuffix(t *testing.T) { 677 runCcBinaryTests(t, ccBinaryBp2buildTestCase{ 678 description: "binary with suffix", 679 blueprint: ` 680{rule_name} { 681 name: "foo", 682 suffix: "-suf", 683} 684`, 685 targets: []testBazelTarget{ 686 {"cc_binary", "foo", AttrNameToString{ 687 "local_includes": `["."]`, 688 "suffix": `"-suf"`, 689 }}, 690 }, 691 }) 692} 693 694func TestCcArchVariantBinarySuffix(t *testing.T) { 695 runCcBinaryTests(t, ccBinaryBp2buildTestCase{ 696 description: "binary with suffix", 697 blueprint: ` 698{rule_name} { 699 name: "foo", 700 arch: { 701 arm64: { suffix: "-64" }, 702 arm: { suffix: "-32" }, 703 }, 704} 705`, 706 targets: []testBazelTarget{ 707 {"cc_binary", "foo", AttrNameToString{ 708 "local_includes": `["."]`, 709 "suffix": `select({ 710 "//build/bazel/platforms/arch:arm": "-32", 711 "//build/bazel/platforms/arch:arm64": "-64", 712 "//conditions:default": None, 713 })`, 714 }}, 715 }, 716 }) 717} 718 719func TestCcBinaryWithSyspropSrcs(t *testing.T) { 720 runCcBinaryTestCase(t, ccBinaryBp2buildTestCase{ 721 description: "cc_binary with sysprop sources", 722 blueprint: ` 723{rule_name} { 724 name: "foo", 725 srcs: [ 726 "bar.sysprop", 727 "baz.sysprop", 728 "blah.cpp", 729 ], 730 min_sdk_version: "5", 731}`, 732 targets: []testBazelTarget{ 733 {"sysprop_library", "foo_sysprop_library", AttrNameToString{ 734 "srcs": `[ 735 "bar.sysprop", 736 "baz.sysprop", 737 ]`, 738 }}, 739 {"cc_sysprop_library_static", "foo_cc_sysprop_library_static", AttrNameToString{ 740 "dep": `":foo_sysprop_library"`, 741 "min_sdk_version": `"5"`, 742 }}, 743 {"cc_binary", "foo", AttrNameToString{ 744 "srcs": `["blah.cpp"]`, 745 "local_includes": `["."]`, 746 "min_sdk_version": `"5"`, 747 "whole_archive_deps": `[":foo_cc_sysprop_library_static"]`, 748 }}, 749 }, 750 }) 751} 752 753func TestCcBinaryWithSyspropSrcsSomeConfigs(t *testing.T) { 754 runCcBinaryTestCase(t, ccBinaryBp2buildTestCase{ 755 description: "cc_binary with sysprop sources in some configs but not others", 756 blueprint: ` 757{rule_name} { 758 name: "foo", 759 srcs: [ 760 "blah.cpp", 761 ], 762 target: { 763 android: { 764 srcs: ["bar.sysprop"], 765 }, 766 }, 767 min_sdk_version: "5", 768}`, 769 targets: []testBazelTarget{ 770 {"sysprop_library", "foo_sysprop_library", AttrNameToString{ 771 "srcs": `select({ 772 "//build/bazel/platforms/os:android": ["bar.sysprop"], 773 "//conditions:default": [], 774 })`, 775 }}, 776 {"cc_sysprop_library_static", "foo_cc_sysprop_library_static", AttrNameToString{ 777 "dep": `":foo_sysprop_library"`, 778 "min_sdk_version": `"5"`, 779 }}, 780 {"cc_binary", "foo", AttrNameToString{ 781 "srcs": `["blah.cpp"]`, 782 "local_includes": `["."]`, 783 "min_sdk_version": `"5"`, 784 "whole_archive_deps": `select({ 785 "//build/bazel/platforms/os:android": [":foo_cc_sysprop_library_static"], 786 "//conditions:default": [], 787 })`, 788 }}, 789 }, 790 }) 791} 792 793func TestCcBinaryWithIntegerOverflowProperty(t *testing.T) { 794 runCcBinaryTestCase(t, ccBinaryBp2buildTestCase{ 795 description: "cc_binary with integer overflow property specified", 796 blueprint: ` 797{rule_name} { 798 name: "foo", 799 sanitize: { 800 integer_overflow: true, 801 }, 802}`, 803 targets: []testBazelTarget{ 804 {"cc_binary", "foo", AttrNameToString{ 805 "local_includes": `["."]`, 806 "features": `["ubsan_integer_overflow"]`, 807 }}, 808 }, 809 }) 810} 811 812func TestCcBinaryWithMiscUndefinedProperty(t *testing.T) { 813 runCcBinaryTestCase(t, ccBinaryBp2buildTestCase{ 814 description: "cc_binary with miscellaneous properties specified", 815 blueprint: ` 816{rule_name} { 817 name: "foo", 818 sanitize: { 819 misc_undefined: ["undefined", "nullability"], 820 }, 821}`, 822 targets: []testBazelTarget{ 823 {"cc_binary", "foo", AttrNameToString{ 824 "local_includes": `["."]`, 825 "features": `[ 826 "ubsan_undefined", 827 "ubsan_nullability", 828 ]`, 829 }}, 830 }, 831 }) 832} 833 834func TestCcBinaryWithUBSanPropertiesArchSpecific(t *testing.T) { 835 runCcBinaryTestCase(t, ccBinaryBp2buildTestCase{ 836 description: "cc_binary has correct feature select when UBSan props are specified in arch specific blocks", 837 blueprint: ` 838{rule_name} { 839 name: "foo", 840 sanitize: { 841 misc_undefined: ["undefined", "nullability"], 842 }, 843 target: { 844 android: { 845 sanitize: { 846 misc_undefined: ["alignment"], 847 }, 848 }, 849 linux_glibc: { 850 sanitize: { 851 integer_overflow: true, 852 }, 853 }, 854 }, 855}`, 856 targets: []testBazelTarget{ 857 {"cc_binary", "foo", AttrNameToString{ 858 "local_includes": `["."]`, 859 "features": `[ 860 "ubsan_undefined", 861 "ubsan_nullability", 862 ] + select({ 863 "//build/bazel/platforms/os:android": ["ubsan_alignment"], 864 "//build/bazel/platforms/os:linux_glibc": ["ubsan_integer_overflow"], 865 "//conditions:default": [], 866 })`, 867 }}, 868 }, 869 }) 870} 871 872func TestCcBinaryWithThinLto(t *testing.T) { 873 runCcBinaryTestCase(t, ccBinaryBp2buildTestCase{ 874 description: "cc_binary has correct features when thin LTO is enabled", 875 blueprint: ` 876{rule_name} { 877 name: "foo", 878 lto: { 879 thin: true, 880 }, 881}`, 882 targets: []testBazelTarget{ 883 {"cc_binary", "foo", AttrNameToString{ 884 "local_includes": `["."]`, 885 "features": `["android_thin_lto"]`, 886 }}, 887 }, 888 }) 889} 890 891func TestCcBinaryWithLtoNever(t *testing.T) { 892 runCcBinaryTestCase(t, ccBinaryBp2buildTestCase{ 893 description: "cc_binary has correct features when LTO is explicitly disabled", 894 blueprint: ` 895{rule_name} { 896 name: "foo", 897 lto: { 898 never: true, 899 }, 900}`, 901 targets: []testBazelTarget{ 902 {"cc_binary", "foo", AttrNameToString{ 903 "local_includes": `["."]`, 904 "features": `["-android_thin_lto"]`, 905 }}, 906 }, 907 }) 908} 909 910func TestCcBinaryWithThinLtoArchSpecific(t *testing.T) { 911 runCcBinaryTestCase(t, ccBinaryBp2buildTestCase{ 912 description: "cc_binary has correct features when LTO differs across arch and os variants", 913 blueprint: ` 914{rule_name} { 915 name: "foo", 916 target: { 917 android: { 918 lto: { 919 thin: true, 920 }, 921 }, 922 }, 923 arch: { 924 riscv64: { 925 lto: { 926 thin: false, 927 }, 928 }, 929 }, 930}`, 931 targets: []testBazelTarget{ 932 {"cc_binary", "foo", AttrNameToString{ 933 "local_includes": `["."]`, 934 "features": `select({ 935 "//build/bazel/platforms/os_arch:android_arm": ["android_thin_lto"], 936 "//build/bazel/platforms/os_arch:android_arm64": ["android_thin_lto"], 937 "//build/bazel/platforms/os_arch:android_riscv64": ["-android_thin_lto"], 938 "//build/bazel/platforms/os_arch:android_x86": ["android_thin_lto"], 939 "//build/bazel/platforms/os_arch:android_x86_64": ["android_thin_lto"], 940 "//conditions:default": [], 941 })`, 942 }}, 943 }, 944 }) 945} 946 947func TestCcBinaryWithThinLtoDisabledDefaultEnabledVariant(t *testing.T) { 948 runCcBinaryTestCase(t, ccBinaryBp2buildTestCase{ 949 description: "cc_binary has correct features when LTO disabled by default but enabled on a particular variant", 950 blueprint: ` 951{rule_name} { 952 name: "foo", 953 lto: { 954 never: true, 955 }, 956 target: { 957 android: { 958 lto: { 959 thin: true, 960 never: false, 961 }, 962 }, 963 }, 964}`, 965 targets: []testBazelTarget{ 966 {"cc_binary", "foo", AttrNameToString{ 967 "local_includes": `["."]`, 968 "features": `select({ 969 "//build/bazel/platforms/os:android": ["android_thin_lto"], 970 "//conditions:default": ["-android_thin_lto"], 971 })`, 972 }}, 973 }, 974 }) 975} 976 977func TestCcBinaryWithThinLtoAndWholeProgramVtables(t *testing.T) { 978 runCcBinaryTestCase(t, ccBinaryBp2buildTestCase{ 979 description: "cc_binary has correct features when thin LTO is enabled with whole_program_vtables", 980 blueprint: ` 981{rule_name} { 982 name: "foo", 983 lto: { 984 thin: true, 985 }, 986 whole_program_vtables: true, 987}`, 988 targets: []testBazelTarget{ 989 {"cc_binary", "foo", AttrNameToString{ 990 "local_includes": `["."]`, 991 "features": `[ 992 "android_thin_lto", 993 "android_thin_lto_whole_program_vtables", 994 ]`, 995 }}, 996 }, 997 }) 998} 999