1# Copyright (C) 2023 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 15"""Feature definitions for Android's C/C++ toolchain. 16 17This top level list of features are available through the get_features function. 18""" 19 20load("@bazel_skylib//rules:common_settings.bzl", "BuildSettingInfo") 21load( 22 "@bazel_tools//tools/cpp:cc_toolchain_config_lib.bzl", 23 "feature", 24 "feature_set", 25 "flag_group", 26 "flag_set", 27 "variable_with_value", 28 "with_feature_set", 29) 30load("@soong_injection//api_levels:platform_versions.bzl", "platform_versions") 31load("//build/bazel/rules/common:api.bzl", "api") 32load( 33 ":cc_toolchain_constants.bzl", 34 _actions = "actions", 35 _arches = "arches", 36 _c_std_versions = "c_std_versions", 37 _cpp_std_versions = "cpp_std_versions", 38 _default_c_std_version = "default_c_std_version", 39 _default_cpp_std_version = "default_cpp_std_version", 40 _default_cpp_std_version_no_gnu = "default_cpp_std_version_no_gnu", 41 _experimental_cpp_std_version = "experimental_cpp_std_version", 42 _experimental_cpp_std_version_no_gnu = "experimental_cpp_std_version_no_gnu", 43 _flags = "flags", 44 _generated_config_constants = "generated_config_constants", 45 _generated_sanitizer_constants = "generated_sanitizer_constants", 46 _oses = "oses", 47) 48 49def is_os_device(os): 50 return os == _oses.Android 51 52def is_os_bionic(os): 53 return os == _oses.Android or os == _oses.LinuxBionic 54 55def _sdk_version_features_between(start, end): 56 return ["sdk_version_" + str(i) for i in range(start, end + 1)] 57 58def _sdk_version_features_before(version): 59 return _sdk_version_features_between(1, version - 1) 60 61def _get_sdk_version_features(os_is_device, target_arch): 62 if not os_is_device: 63 return [] 64 65 default_sdk_version = "10000" 66 sdk_feature_prefix = "sdk_version_" 67 all_sdk_versions = [default_sdk_version] 68 for level in api.api_levels.values(): 69 all_sdk_versions.append(str(level)) 70 71 # Explicitly support internal branch state where the platform sdk version has 72 # finalized, but the sdk is still active, so it's represented by a 9000-ish 73 # value in api_levels. 74 platform_sdk_version = str(platform_versions.platform_sdk_version) 75 if platform_sdk_version not in all_sdk_versions: 76 all_sdk_versions.append(platform_sdk_version) 77 78 flag_prefix = "--target=" 79 if target_arch == _arches.X86: 80 flag_prefix += "i686-linux-android" 81 elif target_arch == _arches.X86_64: 82 flag_prefix += "x86_64-linux-android" 83 elif target_arch == _arches.Arm: 84 flag_prefix += _generated_config_constants.ArmClangTriple 85 elif target_arch == _arches.Arm64: 86 flag_prefix += "aarch64-linux-android" 87 else: 88 fail("Unknown target arch %s" % (target_arch)) 89 90 features = [feature( 91 name = "sdk_version_default", 92 enabled = True, 93 implies = [sdk_feature_prefix + default_sdk_version], 94 )] 95 features.extend([ 96 feature(name = sdk_feature_prefix + sdk_version, provides = ["sdk_version"]) 97 for sdk_version in all_sdk_versions 98 ]) 99 features.append(feature( 100 name = "sdk_version_flag", 101 enabled = True, 102 flag_sets = [ 103 flag_set( 104 actions = _actions.compile + _actions.link, 105 flag_groups = [ 106 flag_group( 107 flags = [flag_prefix + sdk_version], 108 ), 109 ], 110 with_features = [ 111 with_feature_set( 112 features = [sdk_feature_prefix + sdk_version], 113 ), 114 ], 115 ) 116 for sdk_version in all_sdk_versions 117 ], 118 )) 119 return features 120 121def _get_c_std_features(): 122 features = [] 123 features.append(feature( 124 # The default cpp_std feature. Remember to disable 125 # this feature if enabling another cpp_std feature. 126 name = "cpp_std_default", 127 enabled = True, 128 implies = [_default_cpp_std_version], 129 )) 130 features.append(feature( 131 # The default c_std feature. Remember to disable 132 # this feature if enabling another cpp_std feature. 133 name = "c_std_default", 134 enabled = True, 135 implies = [_default_c_std_version], 136 )) 137 138 features.append(feature( 139 name = "cpp_std_default_no_gnu", 140 implies = [_default_cpp_std_version_no_gnu], 141 )) 142 features.append(feature( 143 name = "c_std_default_no_gnu", 144 implies = [_default_cpp_std_version_no_gnu], 145 )) 146 features.append(feature( 147 name = "cpp_std_experimental", 148 implies = [_experimental_cpp_std_version], 149 )) 150 features.append(feature( 151 name = "c_std_experimental", 152 implies = [_experimental_cpp_std_version], 153 )) 154 features.append(feature( 155 name = "cpp_std_experimental_no_gnu", 156 implies = [_experimental_cpp_std_version_no_gnu], 157 )) 158 features.append(feature( 159 name = "c_std_experimental_no_gnu", 160 implies = [_experimental_cpp_std_version_no_gnu], 161 )) 162 features.extend([ 163 feature(name = std_version, provides = ["cpp_std"]) 164 for std_version in _cpp_std_versions 165 ]) 166 features.extend([ 167 feature(name = std_version, provides = ["c_std"]) 168 for std_version in _c_std_versions 169 ]) 170 features.append(feature( 171 name = "cpp_std_flag", 172 enabled = True, 173 # Create the -std flag group for each of the std versions, 174 # enabled with with_feature_set. 175 flag_sets = [ 176 flag_set( 177 actions = [_actions.cpp_compile], 178 flag_groups = [ 179 flag_group( 180 flags = ["-std=" + std_version], 181 ), 182 ], 183 with_features = [ 184 with_feature_set( 185 features = [std_version], 186 ), 187 ], 188 ) 189 for std_version in _cpp_std_versions 190 ], 191 )) 192 features.append(feature( 193 name = "c_std_flag", 194 enabled = True, 195 # Create the -std flag group for each of the std versions, 196 # enabled with with_feature_set. 197 flag_sets = [ 198 flag_set( 199 actions = [_actions.c_compile], 200 flag_groups = [ 201 flag_group( 202 flags = ["-std=" + std_version], 203 ), 204 ], 205 with_features = [ 206 with_feature_set( 207 features = [std_version], 208 ), 209 ], 210 ) 211 for std_version in _c_std_versions 212 ], 213 )) 214 return features 215 216def _env_based_common_global_cflags(ctx): 217 flags = [] 218 219 # The logic comes from https://cs.android.com/android/platform/superproject/+/master:build/soong/cc/config/global.go;l=332;drc=af32e1ba3ffca6b552ac1ff6d14e5c3a5148cb80 220 auto_pattern_initialize = ctx.attr._auto_pattern_initialize[BuildSettingInfo].value 221 auto_uninitialize = ctx.attr._auto_uninitialize[BuildSettingInfo].value 222 if ctx.attr._auto_zero_initialize[BuildSettingInfo].value: 223 flags.extend(["-ftrivial-auto-var-init=zero"]) 224 elif auto_pattern_initialize: 225 flags.extend(["-ftrivial-auto-var-init=pattern"]) 226 elif auto_uninitialize: 227 flags.extend(["-ftrivial-auto-var-init=uninitialized"]) 228 else: 229 # Default to zero initialization. 230 flags.extend(["-ftrivial-auto-var-init=zero"]) 231 232 if ctx.attr._use_ccache[BuildSettingInfo].value or (not auto_pattern_initialize and not auto_uninitialize): 233 flags.extend(["-Wno-unused-command-line-argument"]) 234 235 if ctx.attr._llvm_next[BuildSettingInfo].value: 236 flags.extend(["-Wno-error=single-bit-bitfield-constant-conversion"]) 237 238 if ctx.attr._allow_unknown_warning_option[BuildSettingInfo].value: 239 flags.extend(["-Wno-error=unknown-warning-option"]) 240 241 if ctx.attr._device_no_bionic_page_size_macro[BuildSettingInfo].value: 242 flags.extend(["-D__BIONIC_NO_PAGE_SIZE_MACRO"]) 243 244 clang_debug_env_value = ctx.attr._clang_default_debug_level[BuildSettingInfo].value 245 if clang_debug_env_value == "": 246 flags.extend(["-g"]) 247 elif clang_debug_env_value == "debug_level_g": 248 flags.extend(["-g"]) 249 elif clang_debug_env_value == "debug_level_0": 250 flags.extend(["-g0"]) 251 elif clang_debug_env_value == "debug_level_1": 252 flags.extend(["-g1"]) 253 elif clang_debug_env_value == "debug_level_2": 254 flags.extend(["-g2"]) 255 elif clang_debug_env_value == "debug_level_3": 256 flags.extend(["-g3"]) 257 258 return flags 259 260def _compiler_flag_features(ctx, target_arch, target_os, flags = []): 261 os_is_device = is_os_device(target_os) 262 compiler_flags = [] 263 264 # Combine the toolchain's provided flags with the default ones. 265 compiler_flags.extend(flags) 266 compiler_flags.extend(_flags.compiler_flags) 267 compiler_flags.extend(_generated_config_constants.CommonGlobalCflags) 268 compiler_flags.extend(_env_based_common_global_cflags(ctx)) 269 270 if os_is_device: 271 compiler_flags.extend(_generated_config_constants.DeviceGlobalCflags) 272 else: 273 compiler_flags.extend(_generated_config_constants.HostGlobalCflags) 274 275 # Default compiler flags for assembly sources. 276 asm_only_flags = _generated_config_constants.CommonGlobalAsflags 277 278 # Default C++ compile action only flags (No C) 279 cpp_only_flags = [] 280 cpp_only_flags.extend(_generated_config_constants.CommonGlobalCppflags) 281 if os_is_device: 282 cpp_only_flags.extend(_generated_config_constants.DeviceGlobalCppflags) 283 else: 284 cpp_only_flags.extend(_generated_config_constants.HostGlobalCppflags) 285 286 # Default C compile action only flags (No C++) 287 c_only_flags = [] 288 c_only_flags.extend(_generated_config_constants.CommonGlobalConlyflags) 289 290 # Flags that only apply in the external/ directory. 291 non_external_flags = _flags.non_external_defines 292 293 features = [] 294 295 # TODO: disabled on windows 296 features.append(feature( 297 name = "pic", 298 enabled = False, 299 flag_sets = [ 300 flag_set( 301 actions = _actions.compile, 302 flag_groups = [ 303 flag_group( 304 flags = ["-fPIC"], 305 ), 306 ], 307 with_features = [ 308 with_feature_set( 309 features = ["linker_flags"], 310 not_features = ["pie"], 311 ), 312 ], 313 ), 314 ], 315 )) 316 317 features.append(feature( 318 name = "pie", 319 enabled = False, 320 flag_sets = [ 321 flag_set( 322 actions = _actions.compile, 323 flag_groups = [ 324 flag_group( 325 flags = ["-fPIE"], 326 ), 327 ], 328 with_features = [ 329 with_feature_set( 330 features = ["linker_flags"], 331 not_features = ["pic"], 332 ), 333 ], 334 ), 335 ], 336 )) 337 338 features.append(feature( 339 name = "non_external_compiler_flags", 340 enabled = True, 341 flag_sets = [ 342 flag_set( 343 actions = _actions.compile, 344 flag_groups = [ 345 flag_group( 346 flags = non_external_flags, 347 ), 348 ], 349 with_features = [ 350 with_feature_set( 351 not_features = ["external_compiler_flags"], 352 ), 353 ], 354 ), 355 ], 356 )) 357 358 # bpf only needs the flag below instead of all the flags in 359 # common_compiler_flags 360 features.append(feature( 361 name = "bpf_compiler_flags", 362 enabled = False, 363 flag_sets = [ 364 flag_set( 365 actions = _actions.compile, 366 flag_groups = [ 367 flag_group( 368 flags = ["-fdebug-prefix-map=/proc/self/cwd="], 369 ), 370 ], 371 ), 372 ], 373 )) 374 375 if target_arch == _arches.Arm: 376 features.append(feature( 377 name = "arm_isa_arm", 378 enabled = False, 379 flag_sets = [ 380 flag_set( 381 actions = _actions.compile, 382 flag_groups = [ 383 flag_group( 384 flags = ["-fstrict-aliasing"], 385 ), 386 ], 387 ), 388 ], 389 )) 390 391 features.append(feature( 392 name = "arm_isa_thumb", 393 enabled = True, 394 flag_sets = [ 395 flag_set( 396 actions = _actions.compile, 397 flag_groups = [ 398 flag_group( 399 flags = _generated_config_constants.ArmThumbCflags, 400 ), 401 ], 402 with_features = [ 403 with_feature_set( 404 not_features = ["arm_isa_arm"], 405 ), 406 ], 407 ), 408 ], 409 )) 410 411 # Must follow arm_isa_thumb for flag ordering 412 features.append(feature( 413 name = "common_compiler_flags", 414 enabled = True, 415 flag_sets = [ 416 flag_set( 417 actions = _actions.compile, 418 flag_groups = [ 419 flag_group( 420 flags = compiler_flags, 421 ), 422 ], 423 ), 424 ], 425 )) 426 427 features.append(feature( 428 name = "asm_compiler_flags", 429 enabled = True, 430 flag_sets = [ 431 flag_set( 432 actions = _actions.assemble, 433 flag_groups = [ 434 flag_group( 435 flags = asm_only_flags, 436 ), 437 ], 438 ), 439 ], 440 )) 441 442 features.append(feature( 443 name = "cpp_compiler_flags", 444 enabled = True, 445 flag_sets = [ 446 flag_set( 447 actions = [_actions.cpp_compile], 448 flag_groups = [ 449 flag_group( 450 flags = cpp_only_flags, 451 ), 452 ], 453 ), 454 ], 455 )) 456 457 if c_only_flags: 458 features.append(feature( 459 name = "c_compiler_flags", 460 enabled = True, 461 flag_sets = [ 462 flag_set( 463 actions = [_actions.c_compile], 464 flag_groups = [ 465 flag_group( 466 flags = c_only_flags, 467 ), 468 ], 469 ), 470 ], 471 )) 472 473 features.append(feature( 474 name = "external_compiler_flags", 475 enabled = True, 476 flag_sets = [ 477 flag_set( 478 actions = _actions.compile, 479 flag_groups = [ 480 flag_group( 481 flags = _generated_config_constants.ExternalCflags, 482 ), 483 ], 484 with_features = [ 485 with_feature_set( 486 not_features = ["non_external_compiler_flags"], 487 ), 488 ], 489 ), 490 ], 491 )) 492 493 features.append(feature( 494 name = "warnings_as_errors", 495 enabled = True, 496 flag_sets = [ 497 flag_set( 498 actions = _actions.compile, 499 flag_groups = [ 500 flag_group( 501 flags = ["-Werror"], 502 ), 503 ], 504 ), 505 ], 506 )) 507 508 # The user_compile_flags feature is used by Bazel to add --copt, --conlyopt, 509 # and --cxxopt values. Any features added above this call will thus appear 510 # earlier in the commandline than the user opts (so users could override 511 # flags set by earlier features). Anything after the user options are 512 # effectively non-overridable by users. 513 features.append(feature( 514 name = "user_compile_flags", 515 enabled = True, 516 flag_sets = [ 517 flag_set( 518 actions = _actions.compile, 519 flag_groups = [ 520 flag_group( 521 expand_if_available = "user_compile_flags", 522 flags = ["%{user_compile_flags}"], 523 iterate_over = "user_compile_flags", 524 ), 525 ], 526 ), 527 ], 528 )) 529 530 return features 531 532def _get_no_override_compile_flags(target_os): 533 features = [] 534 535 # These cannot be overriden by the user. 536 features.append(feature( 537 name = "no_override_clang_global_copts", 538 enabled = True, 539 flag_sets = [ 540 flag_set( 541 # We want this to apply to all actions except assembly 542 # primarily to match Soong's semantics 543 actions = [a for a in _actions.compile if a not in _actions.assemble], 544 flag_groups = [ 545 flag_group( 546 flags = _generated_config_constants.NoOverrideGlobalCflags, 547 ), 548 ], 549 ), 550 ], 551 )) 552 553 if target_os != _oses.Darwin: 554 # These cannot be overriden by the user. 555 features.append(feature( 556 name = "no_override_clang_external_global_copts", 557 enabled = True, 558 flag_sets = [ 559 flag_set( 560 # We want this to apply to all actions except assembly 561 # primarily to match Soong's semantics 562 actions = [a for a in _actions.compile if a not in _actions.assemble], 563 flag_groups = [ 564 flag_group( 565 flags = _generated_config_constants.NoOverrideExternalGlobalCflags, 566 ), 567 ], 568 ), 569 ], 570 requires = [ 571 feature_set(features = [ 572 "external_compiler_flags", 573 ]), 574 ], 575 )) 576 577 return features 578 579def _rtti_features(rtti_toggle): 580 if not rtti_toggle: 581 return [] 582 583 rtti_flag_feature = feature( 584 name = "rtti_flag", 585 flag_sets = [ 586 flag_set( 587 actions = [_actions.cpp_compile], 588 flag_groups = [ 589 flag_group( 590 flags = ["-frtti"], 591 ), 592 ], 593 with_features = [ 594 with_feature_set(features = ["rtti"]), 595 ], 596 ), 597 flag_set( 598 actions = [_actions.cpp_compile], 599 flag_groups = [ 600 flag_group( 601 flags = ["-fno-rtti"], 602 ), 603 ], 604 with_features = [ 605 with_feature_set(not_features = ["rtti"]), 606 ], 607 ), 608 ], 609 enabled = True, 610 ) 611 rtti_feature = feature( 612 name = "rtti", 613 enabled = False, 614 ) 615 return [rtti_flag_feature, rtti_feature] 616 617# TODO(b/202167934): Darwin does not support pack dynamic relocations 618def _pack_dynamic_relocations_features(target_os): 619 sht_relr_flags = flag_set( 620 actions = _actions.link, 621 flag_groups = [ 622 flag_group( 623 flags = ["-Wl,--pack-dyn-relocs=android+relr"], 624 ), 625 ], 626 with_features = [ 627 with_feature_set( 628 features = ["linker_flags"], 629 not_features = ["disable_pack_relocations"] + _sdk_version_features_before(30), 630 ), 631 ], 632 ) 633 android_relr_flags = flag_set( 634 actions = _actions.link, 635 flag_groups = [ 636 flag_group( 637 flags = ["-Wl,--pack-dyn-relocs=android+relr", "-Wl,--use-android-relr-tags"], 638 ), 639 ], 640 with_features = [ 641 with_feature_set( 642 features = ["linker_flags", version], 643 not_features = ["disable_pack_relocations"], 644 ) 645 for version in _sdk_version_features_between(28, 29) 646 ], 647 ) 648 relocation_packer_flags = flag_set( 649 actions = _actions.link, 650 flag_groups = [ 651 flag_group( 652 flags = ["-Wl,--pack-dyn-relocs=android"], 653 ), 654 ], 655 with_features = [ 656 with_feature_set( 657 features = ["linker_flags", version], 658 not_features = ["disable_pack_relocations"], 659 ) 660 for version in _sdk_version_features_between(23, 27) 661 ], 662 ) 663 664 if is_os_bionic(target_os): 665 pack_dyn_relr_flag_sets = [ 666 sht_relr_flags, 667 android_relr_flags, 668 relocation_packer_flags, 669 ] 670 else: 671 pack_dyn_relr_flag_sets = [] 672 673 pack_dynamic_relocations_feature = feature( 674 name = "pack_dynamic_relocations", 675 enabled = True, 676 flag_sets = pack_dyn_relr_flag_sets, 677 ) 678 disable_pack_relocations_feature = feature( 679 # this will take precedence over the pack_dynamic_relocations feature 680 # because each flag_set in that feature explicitly disallows the 681 # disable_dynamic_relocations feature 682 name = "disable_pack_relocations", 683 flag_sets = [ 684 flag_set( 685 actions = _actions.link, 686 flag_groups = [ 687 flag_group( 688 flags = ["-Wl,--pack-dyn-relocs=none"], 689 ), 690 ], 691 with_features = [ 692 with_feature_set( 693 features = ["linker_flags"], 694 ), 695 ], 696 ), 697 ], 698 enabled = False, 699 ) 700 return [ 701 pack_dynamic_relocations_feature, 702 disable_pack_relocations_feature, 703 ] 704 705# TODO(b/202167934): Darwin by default disallows undefined symbols, to allow, -Wl,undefined,dynamic_lookup 706def _undefined_symbols_feature(target_os): 707 return _linker_flag_feature( 708 "no_undefined_symbols", 709 flags = ["-Wl,--no-undefined"], 710 enabled = is_os_bionic(target_os) or target_os == _oses.LinuxMusl, 711 ) 712 713def _dynamic_linker_flag_feature(target_os, arch_is_64_bit): 714 flags = [] 715 if is_os_device(target_os): 716 # TODO: handle bootstrap partition, asan 717 dynamic_linker_path = "/system/bin/linker" 718 if arch_is_64_bit: 719 dynamic_linker_path += "64" 720 flags.append("-Wl,-dynamic-linker," + dynamic_linker_path) 721 elif is_os_bionic(target_os) or target_os == _oses.LinuxMusl: 722 flags.append("-Wl,--no-dynamic-linker") 723 return _binary_linker_flag_feature(name = "dynamic_linker", flags = flags) if len(flags) else [] 724 725# TODO(b/202167934): Darwin uses @loader_path in place of $ORIGIN 726def _rpath_features(target_os, arch_is_64_bit): 727 runtime_library_search_directories_flag_sets = [ 728 flag_set( 729 actions = _actions.link, 730 flag_groups = [ 731 flag_group( 732 iterate_over = "runtime_library_search_directories", 733 flag_groups = [ 734 flag_group( 735 flags = [ 736 "-Wl,-rpath,$EXEC_ORIGIN/%{runtime_library_search_directories}", 737 ], 738 expand_if_true = "is_cc_test", 739 ), 740 flag_group( 741 flags = [ 742 "-Wl,-rpath,$ORIGIN/%{runtime_library_search_directories}", 743 ], 744 expand_if_false = "is_cc_test", 745 ), 746 ], 747 expand_if_available = 748 "runtime_library_search_directories", 749 ), 750 ], 751 with_features = [ 752 with_feature_set(features = ["static_link_cpp_runtimes"]), 753 ], 754 ), 755 flag_set( 756 actions = _actions.link, 757 flag_groups = [ 758 flag_group( 759 iterate_over = "runtime_library_search_directories", 760 flag_groups = [ 761 flag_group( 762 flags = [ 763 "-Wl,-rpath,$ORIGIN/%{runtime_library_search_directories}", 764 ], 765 ), 766 ], 767 expand_if_available = 768 "runtime_library_search_directories", 769 ), 770 ], 771 with_features = [ 772 with_feature_set( 773 not_features = ["static_link_cpp_runtimes", "disable_rpath"], 774 ), 775 ], 776 ), 777 ] 778 779 if (not is_os_device(target_os)) and arch_is_64_bit: 780 runtime_library_search_directories_flag_sets.append(flag_set( 781 actions = _actions.link, 782 flag_groups = [ 783 flag_group( 784 flag_groups = [ 785 flag_group( 786 flags = [ 787 "-Wl,-rpath,$ORIGIN/../lib64", 788 "-Wl,-rpath,$ORIGIN/lib64", 789 ], 790 ), 791 ], 792 ), 793 ], 794 with_features = [ 795 with_feature_set(not_features = ["static_link_cpp_runtimes"]), 796 ], 797 )) 798 799 runtime_library_search_directories_feature = feature( 800 name = "runtime_library_search_directories", 801 flag_sets = runtime_library_search_directories_flag_sets, 802 ) 803 804 disable_rpath_feature = feature( 805 name = "disable_rpath", 806 enabled = False, 807 ) 808 return [runtime_library_search_directories_feature, disable_rpath_feature] 809 810def _use_libcrt_feature(path): 811 if not path: 812 return None 813 return _flag_feature("use_libcrt", actions = _actions.link, flags = [ 814 path.path, 815 "-Wl,--exclude-libs=" + path.basename, 816 ]) 817 818def _flag_feature(name, actions = None, flags = None, enabled = True): 819 if not flags or not actions: 820 return None 821 return feature( 822 name = name, 823 enabled = enabled, 824 flag_sets = [ 825 flag_set( 826 actions = actions, 827 flag_groups = [ 828 flag_group(flags = flags), 829 ], 830 ), 831 ], 832 ) 833 834def _linker_flag_feature(name, flags = [], enabled = True): 835 return _flag_feature(name, actions = _actions.link, flags = flags, enabled = enabled) 836 837def _archiver_flag_feature(name, flags = [], enabled = True): 838 return _flag_feature(name, actions = _actions.archive, flags = flags, enabled = enabled) 839 840def _binary_linker_flag_feature(name, flags = [], enabled = True): 841 return _flag_feature(name, actions = [_actions.cpp_link_executable], flags = flags, enabled = enabled) 842 843def _toolchain_include_feature(system_includes = []): 844 flags = [] 845 for include in system_includes: 846 flags.append("-isystem") 847 flags.append(include) 848 if not flags: 849 return None 850 return feature( 851 name = "toolchain_include_directories", 852 enabled = True, 853 flag_sets = [ 854 flag_set( 855 actions = _actions.compile, 856 flag_groups = [ 857 flag_group( 858 flags = flags, 859 ), 860 ], 861 ), 862 ], 863 ) 864 865def _stub_library_feature(): 866 return feature( 867 name = "stub_library", 868 enabled = False, 869 flag_sets = [ 870 flag_set( 871 actions = [_actions.c_compile], 872 flag_groups = [ 873 flag_group( 874 # Ensures that the stub libraries are always compiled with default visibility 875 flags = _generated_config_constants.StubLibraryCompilerFlags + ["-fvisibility=default"], 876 ), 877 ], 878 ), 879 ], 880 ) 881 882def _flatten(xs): 883 ret = [] 884 for x in xs: 885 if type(x) == "list": 886 ret.extend(x) 887 else: 888 ret.append(x) 889 return ret 890 891def _additional_archiver_flags(target_os): 892 archiver_flags = [] 893 if target_os != _oses.Darwin: 894 archiver_flags.extend(_flags.non_darwin_archiver_flags) 895 return archiver_flags 896 897# Additional linker flags that are dependent on a host or device target. 898def _additional_linker_flags(os_is_device): 899 linker_flags = [] 900 if os_is_device: 901 linker_flags.extend(_generated_config_constants.DeviceGlobalLldflags) 902 linker_flags.extend(_flags.bionic_linker_flags) 903 else: 904 linker_flags.extend(_generated_config_constants.HostGlobalLldflags) 905 return linker_flags 906 907def _static_binary_linker_flags(os_is_device): 908 linker_flags = [] 909 if os_is_device: 910 linker_flags.extend(_flags.bionic_static_executable_linker_flags) 911 return linker_flags 912 913def _shared_binary_linker_flags(target_os): 914 linker_flags = [] 915 if is_os_device(target_os): 916 linker_flags.extend(_flags.bionic_dynamic_executable_linker_flags) 917 elif target_os != _oses.Windows: 918 linker_flags.extend(_flags.host_non_windows_dynamic_executable_linker_flags) 919 return linker_flags 920 921# Legacy features moved from their hardcoded Bazel's Java implementation 922# to Starlark. 923# 924# These legacy features must come before all other features. 925def _get_legacy_features_begin(): 926 features = [ 927 # Legacy features omitted from this list, since they're not used in 928 # Android builds currently, or is alternatively supported through rules 929 # directly (e.g. stripped_shared_library for debug symbol stripping). 930 # 931 # thin_lto: Do not add, as it may break some features. replaced by _get_thinlto_features() 932 # 933 # runtime_library_search_directories: replaced by custom _rpath_feature(). 934 # 935 # Compile related features: 936 # 937 # random_seed 938 # legacy_compile_flags 939 # per_object_debug_info 940 # pic 941 # force_pic_flags 942 # 943 # Optimization related features: 944 # 945 # fdo_instrument 946 # fdo_optimize 947 # cs_fdo_instrument 948 # cs_fdo_optimize 949 # fdo_prefetch_hints 950 # propeller_optimize 951 # 952 # Interface libraries related features: 953 # 954 # supports_interface_shared_libraries 955 # build_interface_libraries 956 # dynamic_library_linker_tool 957 # 958 # Coverage: 959 # 960 # coverage 961 # llvm_coverage_map_format 962 # gcc_coverage_map_format 963 # 964 # Others: 965 # 966 # symbol_counts 967 # static_libgcc 968 # fission_support 969 # static_link_cpp_runtimes 970 # 971 # ------------------------ 972 # 973 feature( 974 name = "autofdo", 975 flag_sets = [ 976 flag_set( 977 actions = _actions.compile, 978 flag_groups = [ 979 flag_group( 980 # https://cs.android.com/android/platform/superproject/+/master:build/soong/cc/afdo.go;l=35;drc=7a8362c252b152f806fc303c414ff1418672b067 981 flags = [ 982 "-funique-internal-linkage-names", 983 "-fprofile-sample-accurate", 984 "-fprofile-sample-use=%{fdo_profile_path}", 985 ], 986 expand_if_available = "fdo_profile_path", 987 ), 988 ], 989 ), 990 ], 991 provides = ["profile"], 992 ), 993 # https://cs.opensource.google/bazel/bazel/+/master:src/main/java/com/google/devtools/build/lib/rules/cpp/CppActionConfigs.java;l=98;drc=6d03a2ecf25ad596446c296ef1e881b60c379812 994 feature( 995 name = "dependency_file", 996 enabled = True, 997 flag_sets = [ 998 flag_set( 999 actions = _actions.compile, 1000 flag_groups = [ 1001 flag_group( 1002 expand_if_available = "dependency_file", 1003 flags = [ 1004 "-MD", 1005 "-MF", 1006 "%{dependency_file}", 1007 ], 1008 ), 1009 ], 1010 ), 1011 ], 1012 ), 1013 # https://cs.opensource.google/bazel/bazel/+/master:src/main/java/com/google/devtools/build/lib/rules/cpp/CppActionConfigs.java;l=186;drc=6d03a2ecf25ad596446c296ef1e881b60c379812 1014 feature( 1015 name = "preprocessor_defines", 1016 enabled = True, 1017 flag_sets = [ 1018 flag_set( 1019 actions = _actions.compile, 1020 flag_groups = [ 1021 flag_group( 1022 iterate_over = "preprocessor_defines", 1023 flags = ["-D%{preprocessor_defines}"], 1024 ), 1025 ], 1026 ), 1027 ], 1028 ), 1029 # https://cs.opensource.google/bazel/bazel/+/master:src/main/java/com/google/devtools/build/lib/rules/cpp/CppActionConfigs.java;l=207;drc=6d03a2ecf25ad596446c296ef1e881b60c379812 1030 feature( 1031 name = "includes", 1032 enabled = True, 1033 flag_sets = [ 1034 flag_set( 1035 actions = _actions.compile, 1036 flag_groups = [ 1037 flag_group( 1038 expand_if_available = "includes", 1039 iterate_over = "includes", 1040 flags = ["-include", "%{includes}"], 1041 ), 1042 ], 1043 ), 1044 ], 1045 ), 1046 # https://cs.opensource.google/bazel/bazel/+/master:src/main/java/com/google/devtools/build/lib/rules/cpp/CppActionConfigs.java;l=232;drc=6d03a2ecf25ad596446c296ef1e881b60c379812 1047 feature( 1048 name = "include_paths", 1049 enabled = True, 1050 flag_sets = [ 1051 flag_set( 1052 actions = _actions.compile, 1053 flag_groups = [ 1054 flag_group( 1055 iterate_over = "quote_include_paths", 1056 flags = ["-iquote", "%{quote_include_paths}"], 1057 ), 1058 flag_group( 1059 iterate_over = "include_paths", 1060 flags = ["-I", "%{include_paths}"], 1061 ), 1062 flag_group( 1063 iterate_over = "system_include_paths", 1064 flags = ["-isystem", "%{system_include_paths}"], 1065 ), 1066 flag_group( 1067 flags = ["-F%{framework_include_paths}"], 1068 iterate_over = "framework_include_paths", 1069 ), 1070 ], 1071 ), 1072 ], 1073 ), 1074 # https://cs.opensource.google/bazel/bazel/+/master:src/main/java/com/google/devtools/build/lib/rules/cpp/CppActionConfigs.java;l=476;drc=6d03a2ecf25ad596446c296ef1e881b60c379812 1075 feature( 1076 name = "shared_flag", 1077 flag_sets = [ 1078 flag_set( 1079 actions = [ 1080 _actions.cpp_link_dynamic_library, 1081 _actions.cpp_link_nodeps_dynamic_library, 1082 ], 1083 flag_groups = [ 1084 flag_group( 1085 flags = [ 1086 "-shared", 1087 ], 1088 ), 1089 ], 1090 ), 1091 ], 1092 ), 1093 1094 # https://cs.opensource.google/bazel/bazel/+/master:src/main/java/com/google/devtools/build/lib/rules/cpp/CppActionConfigs.java;l=492;drc=6d03a2ecf25ad596446c296ef1e881b60c379812 1095 feature( 1096 name = "linkstamps", 1097 flag_sets = [ 1098 flag_set( 1099 actions = _actions.link, 1100 flag_groups = [ 1101 flag_group( 1102 expand_if_available = "linkstamp_paths", 1103 iterate_over = "linkstamp_paths", 1104 flags = ["%{linkstamp_paths}"], 1105 ), 1106 ], 1107 ), 1108 ], 1109 ), 1110 # https://cs.opensource.google/bazel/bazel/+/master:src/main/java/com/google/devtools/build/lib/rules/cpp/CppActionConfigs.java;l=512;drc=6d03a2ecf25ad596446c296ef1e881b60c379812 1111 feature( 1112 name = "output_execpath_flags", 1113 flag_sets = [ 1114 flag_set( 1115 actions = _actions.link, 1116 flag_groups = [ 1117 flag_group( 1118 expand_if_available = "output_execpath", 1119 flags = [ 1120 "-o", 1121 "%{output_execpath}", 1122 ], 1123 ), 1124 ], 1125 ), 1126 ], 1127 ), 1128 # https://cs.opensource.google/bazel/bazel/+/master:src/main/java/com/google/devtools/build/lib/rules/cpp/CppActionConfigs.java;l=592;drc=6d03a2ecf25ad596446c296ef1e881b60c379812 1129 feature( 1130 name = "library_search_directories", 1131 flag_sets = [ 1132 flag_set( 1133 actions = _actions.link, 1134 flag_groups = [ 1135 flag_group( 1136 expand_if_available = "library_search_directories", 1137 iterate_over = "library_search_directories", 1138 flags = ["-L%{library_search_directories}"], 1139 ), 1140 ], 1141 ), 1142 ], 1143 ), 1144 # https://cs.opensource.google/bazel/bazel/+/master:src/main/java/com/google/devtools/build/lib/rules/cpp/CppActionConfigs.java;l=612;drc=6d03a2ecf25ad596446c296ef1e881b60c379812 1145 feature( 1146 name = "archiver_flags", 1147 flag_sets = [ 1148 flag_set( 1149 actions = ["c++-link-static-library"], 1150 flag_groups = [ 1151 flag_group( 1152 flags = ["crsPD"], 1153 ), 1154 flag_group( 1155 expand_if_available = "output_execpath", 1156 flags = ["%{output_execpath}"], 1157 ), 1158 ], 1159 ), 1160 flag_set( 1161 actions = ["c++-link-static-library"], 1162 flag_groups = [ 1163 flag_group( 1164 expand_if_available = "libraries_to_link", 1165 iterate_over = "libraries_to_link", 1166 flag_groups = [ 1167 flag_group( 1168 expand_if_equal = variable_with_value( 1169 name = "libraries_to_link.type", 1170 value = "object_file", 1171 ), 1172 flags = ["%{libraries_to_link.name}"], 1173 ), 1174 ], 1175 ), 1176 flag_group( 1177 expand_if_equal = variable_with_value( 1178 name = "libraries_to_link.type", 1179 value = "object_file_group", 1180 ), 1181 iterate_over = "libraries_to_link.object_files", 1182 flags = ["%{libraries_to_link.object_files}"], 1183 ), 1184 ], 1185 ), 1186 ], 1187 ), 1188 feature( 1189 name = "archive_with_prebuilt_flags", 1190 flag_sets = [ 1191 flag_set( 1192 actions = ["c++-link-static-library"], 1193 flag_groups = [ 1194 flag_group( 1195 flags = ["cqsL"], 1196 ), 1197 flag_group( 1198 expand_if_available = "output_execpath", 1199 flags = ["%{output_execpath}"], 1200 ), 1201 ], 1202 ), 1203 ], 1204 ), 1205 # https://cs.opensource.google/bazel/bazel/+/master:src/main/java/com/google/devtools/build/lib/rules/cpp/CppActionConfigs.java;l=653;drc=6d03a2ecf25ad596446c296ef1e881b60c379812 1206 feature( 1207 name = "libraries_to_link", 1208 flag_sets = [ 1209 flag_set( 1210 actions = _actions.link, 1211 flag_groups = ([ 1212 flag_group( 1213 expand_if_true = "thinlto_param_file", 1214 flags = ["-Wl,@%{thinlto_param_file}"], 1215 ), 1216 flag_group( 1217 expand_if_available = "libraries_to_link", 1218 iterate_over = "libraries_to_link", 1219 flag_groups = ( 1220 [ 1221 flag_group( 1222 expand_if_equal = variable_with_value( 1223 name = "libraries_to_link.type", 1224 value = "object_file_group", 1225 ), 1226 expand_if_false = "libraries_to_link.is_whole_archive", 1227 flags = ["-Wl,--start-lib"], 1228 ), 1229 flag_group( 1230 expand_if_equal = variable_with_value( 1231 name = "libraries_to_link.type", 1232 value = "static_library", 1233 ), 1234 expand_if_true = "libraries_to_link.is_whole_archive", 1235 flags = ["-Wl,--whole-archive"], 1236 ), 1237 flag_group( 1238 expand_if_equal = variable_with_value( 1239 name = "libraries_to_link.type", 1240 value = "object_file_group", 1241 ), 1242 iterate_over = "libraries_to_link.object_files", 1243 flags = ["%{libraries_to_link.object_files}"], 1244 ), 1245 flag_group( 1246 expand_if_equal = variable_with_value( 1247 name = "libraries_to_link.type", 1248 value = "object_file", 1249 ), 1250 flags = ["%{libraries_to_link.name}"], 1251 ), 1252 flag_group( 1253 expand_if_equal = variable_with_value( 1254 name = "libraries_to_link.type", 1255 value = "interface_library", 1256 ), 1257 flags = ["%{libraries_to_link.name}"], 1258 ), 1259 flag_group( 1260 expand_if_equal = variable_with_value( 1261 name = "libraries_to_link.type", 1262 value = "static_library", 1263 ), 1264 flags = ["%{libraries_to_link.name}"], 1265 ), 1266 flag_group( 1267 expand_if_equal = variable_with_value( 1268 name = "libraries_to_link.type", 1269 value = "dynamic_library", 1270 ), 1271 flags = ["-l%{libraries_to_link.name}"], 1272 ), 1273 flag_group( 1274 expand_if_equal = variable_with_value( 1275 name = "libraries_to_link.type", 1276 value = "versioned_dynamic_library", 1277 ), 1278 flags = ["-l:%{libraries_to_link.name}"], 1279 ), 1280 flag_group( 1281 expand_if_equal = variable_with_value( 1282 name = "libraries_to_link.type", 1283 value = "static_library", 1284 ), 1285 expand_if_true = "libraries_to_link.is_whole_archive", 1286 flags = ["-Wl,--no-whole-archive"], 1287 ), 1288 flag_group( 1289 expand_if_equal = variable_with_value( 1290 name = "libraries_to_link.type", 1291 value = "object_file_group", 1292 ), 1293 expand_if_false = "libraries_to_link.is_whole_archive", 1294 flags = ["-Wl,--end-lib"], 1295 ), 1296 ] 1297 ), 1298 ), 1299 ]), 1300 ), 1301 ], 1302 ), 1303 # https://cs.opensource.google/bazel/bazel/+/master:src/main/java/com/google/devtools/build/lib/rules/cpp/CppActionConfigs.java;l=842;drc=6d03a2ecf25ad596446c296ef1e881b60c379812 1304 feature( 1305 name = "user_link_flags", 1306 flag_sets = [ 1307 flag_set( 1308 actions = _actions.link, 1309 flag_groups = [ 1310 flag_group( 1311 expand_if_available = "user_link_flags", 1312 iterate_over = "user_link_flags", 1313 flags = ["%{user_link_flags}"], 1314 ), 1315 ], 1316 ), 1317 ], 1318 ), 1319 feature( 1320 name = "strip_debug_symbols", 1321 flag_sets = [ 1322 flag_set( 1323 actions = _actions.link, 1324 flag_groups = [ 1325 flag_group( 1326 expand_if_available = "strip_debug_symbols", 1327 flags = ["-Wl,-S"], 1328 ), 1329 ], 1330 ), 1331 ], 1332 enabled = False, 1333 ), 1334 feature( 1335 name = "llvm_coverage_map_format", 1336 flag_sets = [ 1337 flag_set( 1338 actions = _actions.compile, 1339 flag_groups = [ 1340 flag_group( 1341 flags = [ 1342 "-fprofile-instr-generate=/data/misc/trace/clang-%%p-%%m.profraw", 1343 "-fcoverage-mapping", 1344 "-Wno-pass-failed", 1345 "-D__ANDROID_CLANG_COVERAGE__", 1346 ], 1347 ), 1348 ], 1349 ), 1350 flag_set( 1351 actions = [_actions.c_compile, _actions.cpp_compile], 1352 flag_groups = [flag_group(flags = ["-Wno-frame-larger-than="])], 1353 ), 1354 # TODO(b/233660582): support "-Wl,--wrap,open" and libprofile-clang-extras 1355 flag_set( 1356 actions = _actions.link, 1357 flag_groups = [flag_group(flags = ["-fprofile-instr-generate"])], 1358 ), 1359 flag_set( 1360 actions = _actions.link, 1361 flag_groups = [flag_group(flags = ["-Wl,--wrap,open"])], 1362 with_features = [ 1363 with_feature_set( 1364 features = ["android_coverage_lib"], 1365 ), 1366 ], 1367 ), 1368 ], 1369 requires = [feature_set(features = ["coverage"])], 1370 ), 1371 feature(name = "coverage"), 1372 feature(name = "android_coverage_lib"), 1373 ] 1374 1375 return features 1376 1377# Legacy features moved from their hardcoded Bazel's Java implementation 1378# to Starlark. 1379# 1380# These legacy features must come after all other features. 1381def _get_legacy_features_end(): 1382 # Omitted legacy (unused or re-implemented) features: 1383 # 1384 # fully_static_link 1385 # user_compile_flags 1386 # sysroot 1387 features = [ 1388 feature( 1389 name = "linker_param_file", 1390 enabled = True, 1391 flag_sets = [ 1392 flag_set( 1393 actions = _actions.link + _actions.archive, 1394 flag_groups = [ 1395 flag_group( 1396 expand_if_available = "linker_param_file", 1397 flags = ["@%{linker_param_file}"], 1398 ), 1399 ], 1400 ), 1401 ], 1402 ), 1403 # https://cs.opensource.google/bazel/bazel/+/master:src/main/java/com/google/devtools/build/lib/rules/cpp/CppActionConfigs.java;l=1511;drc=6d03a2ecf25ad596446c296ef1e881b60c379812 1404 feature( 1405 name = "compiler_input_flags", 1406 enabled = True, 1407 flag_sets = [ 1408 flag_set( 1409 actions = _actions.compile, 1410 flag_groups = [ 1411 flag_group( 1412 expand_if_available = "source_file", 1413 flags = ["-c", "%{source_file}"], 1414 ), 1415 ], 1416 ), 1417 ], 1418 ), 1419 # https://cs.opensource.google/bazel/bazel/+/master:src/main/java/com/google/devtools/build/lib/rules/cpp/CppActionConfigs.java;l=1538;drc=6d03a2ecf25ad596446c296ef1e881b60c379812 1420 feature( 1421 name = "compiler_output_flags", 1422 enabled = True, 1423 flag_sets = [ 1424 flag_set( 1425 actions = _actions.compile, 1426 flag_groups = [ 1427 flag_group( 1428 expand_if_available = "output_assembly_file", 1429 flags = ["-S"], 1430 ), 1431 flag_group( 1432 expand_if_available = "output_preprocess_file", 1433 flags = ["-E"], 1434 ), 1435 flag_group( 1436 expand_if_available = "output_file", 1437 flags = ["-o", "%{output_file}"], 1438 ), 1439 ], 1440 ), 1441 ], 1442 ), 1443 ] 1444 1445 return features 1446 1447def _link_crtbegin(crt_files): 1448 # in practice, either all of these are supported for a toolchain or none of them do 1449 if crt_files.shared_library_crtbegin == None or crt_files.shared_binary_crtbegin == None or crt_files.static_binary_crtbegin == None: 1450 return [] 1451 1452 features = [ 1453 feature( 1454 # User facing feature 1455 name = "link_crt", 1456 enabled = True, 1457 implies = ["link_crtbegin", "link_crtend"], 1458 ), 1459 feature( 1460 name = "link_crtbegin", 1461 enabled = True, 1462 ), 1463 feature( 1464 name = "link_crtbegin_so", 1465 enabled = True, 1466 flag_sets = [ 1467 flag_set( 1468 actions = [_actions.cpp_link_dynamic_library], 1469 flag_groups = [ 1470 flag_group( 1471 flags = [crt_files.shared_library_crtbegin.path], 1472 ), 1473 ], 1474 with_features = [ 1475 with_feature_set( 1476 features = ["link_crt", "link_crtbegin"], 1477 ), 1478 ], 1479 ), 1480 ], 1481 ), 1482 feature( 1483 name = "link_crtbegin_dynamic", 1484 enabled = True, 1485 flag_sets = [ 1486 flag_set( 1487 actions = [_actions.cpp_link_executable], 1488 flag_groups = [ 1489 flag_group( 1490 flags = [crt_files.shared_binary_crtbegin.path], 1491 ), 1492 ], 1493 with_features = [ 1494 with_feature_set( 1495 features = [ 1496 "dynamic_executable", 1497 "link_crt", 1498 "link_crtbegin", 1499 ], 1500 ), 1501 ], 1502 ), 1503 ], 1504 ), 1505 feature( 1506 name = "link_crtbegin_static", 1507 enabled = True, 1508 flag_sets = [ 1509 flag_set( 1510 actions = [_actions.cpp_link_executable], 1511 flag_groups = [ 1512 flag_group( 1513 flags = [crt_files.static_binary_crtbegin.path], 1514 ), 1515 ], 1516 with_features = [ 1517 with_feature_set( 1518 features = [ 1519 "link_crt", 1520 "link_crtbegin", 1521 "static_executable", 1522 ], 1523 ), 1524 ], 1525 ), 1526 ], 1527 ), 1528 ] 1529 1530 return features 1531 1532def _link_crtend(crt_files): 1533 # in practice, either all of these are supported for a toolchain or none of them do 1534 if crt_files.shared_library_crtend == None or crt_files.binary_crtend == None: 1535 return None 1536 1537 return [ 1538 feature( 1539 name = "link_crtend", 1540 enabled = True, 1541 ), 1542 feature( 1543 name = "link_crtend_so", 1544 enabled = True, 1545 flag_sets = [ 1546 flag_set( 1547 actions = [_actions.cpp_link_dynamic_library], 1548 flag_groups = [ 1549 flag_group( 1550 flags = [crt_files.shared_library_crtend.path], 1551 ), 1552 ], 1553 with_features = [ 1554 with_feature_set( 1555 features = ["link_crt", "link_crtend"], 1556 ), 1557 ], 1558 ), 1559 ], 1560 ), 1561 feature( 1562 name = "link_crtend_binary", 1563 enabled = True, 1564 flag_sets = [ 1565 flag_set( 1566 actions = [_actions.cpp_link_executable], 1567 flag_groups = [ 1568 flag_group( 1569 flags = [crt_files.binary_crtend.path], 1570 ), 1571 ], 1572 with_features = [ 1573 with_feature_set( 1574 features = ["link_crt", "link_crtend"], 1575 ), 1576 ], 1577 ), 1578 ], 1579 ), 1580 ] 1581 1582# TODO(b/276932249): Restrict for Fuzzer when we have Fuzzer in Bazel 1583def _get_thinlto_features(): 1584 features = [ 1585 feature( 1586 name = "android_thin_lto", 1587 enabled = False, 1588 flag_sets = [ 1589 flag_set( 1590 actions = _actions.compile + _actions.link + _actions.assemble, 1591 flag_groups = [ 1592 flag_group( 1593 flags = [ 1594 "-flto=thin", 1595 "-fsplit-lto-unit", 1596 ], 1597 ), 1598 ], 1599 ), 1600 ], 1601 ), 1602 feature( 1603 name = "android_thin_lto_whole_program_vtables", 1604 enabled = False, 1605 requires = [feature_set(features = ["android_thin_lto"])], 1606 flag_sets = [ 1607 flag_set( 1608 actions = _actions.link, 1609 flag_groups = [ 1610 flag_group( 1611 flags = ["-fwhole-program-vtables"], 1612 ), 1613 ], 1614 ), 1615 ], 1616 ), 1617 # See Soong code: 1618 # https://cs.android.com/android/platform/superproject/+/master:build/soong/cc/lto.go;l=133;drc=2c435a00ff73dc485855824ee49d2dec1a01e592 1619 feature( 1620 name = "android_thin_lto_limit_cross_tu_inline", 1621 enabled = True, 1622 requires = [feature_set(features = ["android_thin_lto"])], 1623 flag_sets = [ 1624 flag_set( 1625 actions = _actions.link, 1626 flag_groups = [ 1627 flag_group( 1628 flags = ["-Wl,-plugin-opt,-import-instr-limit=5"], 1629 ), 1630 ], 1631 with_features = [ 1632 with_feature_set( 1633 not_features = [ 1634 # TODO(b/267220812): Update for PGO 1635 "autofdo", 1636 ], 1637 ), 1638 ], 1639 ), 1640 ], 1641 ), 1642 # Used for CFI 1643 # TODO(b/283951987): Remove after full LTO support is removed in Soong 1644 feature( 1645 name = "android_full_lto", 1646 enabled = False, 1647 flag_sets = [ 1648 flag_set( 1649 actions = _actions.compile + _actions.link + _actions.assemble, 1650 flag_groups = [ 1651 flag_group( 1652 flags = ["-flto"], 1653 ), 1654 ], 1655 ), 1656 ], 1657 ), 1658 ] 1659 return features 1660 1661def _make_flag_set(actions, flags, with_features = [], with_not_features = []): 1662 return flag_set( 1663 actions = actions, 1664 flag_groups = [ 1665 flag_group( 1666 flags = flags, 1667 ), 1668 ], 1669 with_features = [ 1670 with_feature_set( 1671 features = with_features, 1672 not_features = with_not_features, 1673 ), 1674 ], 1675 ) 1676 1677def _get_misc_sanitizer_features(): 1678 return [ 1679 # New sanitizers must imply this feature 1680 feature( 1681 name = "sanitizers_enabled", 1682 enabled = False, 1683 ), 1684 ] 1685 1686# TODO(b/276756817): Restrict for VNDK when we have VNDK in Bazel 1687# TODO(b/276756319): Restrict for riscv64 when we have riscv64 in Bazel 1688# TODO(b/276932249): Restrict for Fuzzer when we have Fuzzer in Bazel 1689# TODO(b/276931992): Restrict for Asan when we have Asan in Bazel 1690# TODO(b/283951987): Switch to thin LTO when possible 1691def _get_cfi_features(target_arch, target_os): 1692 if target_os in [_oses.Windows, _oses.Darwin, _oses.LinuxMusl]: 1693 return [] 1694 features = [ 1695 feature( 1696 name = "android_cfi_cross_dso", 1697 enabled = True, 1698 requires = [feature_set(features = ["android_cfi"])], 1699 flag_sets = [ 1700 _make_flag_set( 1701 actions = _actions.c_and_cpp_compile + _actions.link, 1702 flags = [_generated_sanitizer_constants.CfiCrossDsoFlag], 1703 with_features = ["dynamic_executable"], 1704 with_not_features = ["static_executable"], 1705 ), 1706 ], 1707 ), 1708 ] 1709 1710 features.append( 1711 feature( 1712 name = "android_cfi", 1713 enabled = False, 1714 flag_sets = [ 1715 _make_flag_set( 1716 _actions.c_and_cpp_compile, 1717 _generated_sanitizer_constants.CfiCFlags, 1718 ), 1719 _make_flag_set( 1720 _actions.link, 1721 _generated_sanitizer_constants.CfiLdFlags, 1722 ), 1723 _make_flag_set( 1724 _actions.assemble, 1725 _generated_sanitizer_constants.CfiAsFlags, 1726 ), 1727 ], 1728 implies = ["android_full_lto", "sanitizers_enabled"] + ( 1729 ["arm_isa_thumb"] if target_arch == _arches.Arm else [] 1730 ), 1731 ), 1732 ) 1733 1734 features.append( 1735 feature( 1736 name = "android_cfi_assembly_support", 1737 enabled = False, 1738 requires = [feature_set(features = ["android_cfi"])], 1739 flag_sets = [ 1740 _make_flag_set( 1741 _actions.c_and_cpp_compile, 1742 [_generated_sanitizer_constants.CfiAssemblySupportFlag], 1743 ), 1744 ], 1745 ), 1746 ) 1747 1748 features.append( 1749 feature( 1750 name = "android_cfi_exports_map", 1751 enabled = False, 1752 requires = [feature_set(features = ["android_cfi"])], 1753 flag_sets = [ 1754 _make_flag_set( 1755 _actions.link, 1756 [ 1757 _generated_config_constants.VersionScriptFlagPrefix + 1758 _generated_sanitizer_constants.CfiExportsMapPath + 1759 "/" + 1760 _generated_sanitizer_constants.CfiExportsMapFilename, 1761 ], 1762 ), 1763 ], 1764 ), 1765 ) 1766 1767 features.append( 1768 feature( 1769 name = "android_cfi_visibility_default", 1770 enabled = True, 1771 requires = [feature_set(features = ["android_cfi"])], 1772 flag_sets = [ 1773 flag_set( 1774 actions = _actions.c_and_cpp_compile, 1775 flag_groups = [ 1776 flag_group( 1777 flags = [ 1778 _generated_config_constants.VisibilityDefaultFlag, 1779 ], 1780 ), 1781 ], 1782 with_features = [ 1783 with_feature_set( 1784 not_features = ["visibility_hidden"], 1785 ), 1786 ], 1787 ), 1788 ], 1789 ), 1790 ) 1791 1792 return features 1793 1794def _get_memtag_features(target_arch, target_os): 1795 features = [] 1796 if target_os != _oses.Android or target_arch != _arches.Arm64: 1797 return features 1798 1799 features.append( 1800 feature( 1801 name = "memtag_heap", 1802 enabled = False, 1803 requires = [feature_set(features = ["cc_binary"])], 1804 flag_sets = [ 1805 _make_flag_set( 1806 actions = _actions.compile + _actions.link, 1807 flags = ["-fsanitize=memtag-heap"], 1808 ), 1809 _make_flag_set( 1810 actions = _actions.link, 1811 flags = ["-fsanitize-memtag-mode=sync"], 1812 with_features = ["diag_memtag_heap"], 1813 ), 1814 _make_flag_set( 1815 actions = _actions.link, 1816 flags = ["-fsanitize-memtag-mode=async"], 1817 with_not_features = ["diag_memtag_heap"], 1818 ), 1819 ], 1820 implies = ["sanitizers_enabled"], 1821 ), 1822 ) 1823 1824 features.append(feature(name = "cc_binary")) 1825 features.append(feature(name = "diag_memtag_heap")) 1826 1827 return features 1828 1829def _get_visibiility_hidden_feature(): 1830 return [ 1831 feature( 1832 name = "visibility_hidden", 1833 enabled = False, 1834 flag_sets = [ 1835 _make_flag_set( 1836 _actions.c_and_cpp_compile, 1837 [_generated_config_constants.VisibilityHiddenFlag], 1838 ), 1839 ], 1840 ), 1841 ] 1842 1843def _sanitizer_flag_feature(name, actions, flags): 1844 return feature( 1845 name = name, 1846 enabled = True, 1847 flag_sets = [ 1848 flag_set( 1849 actions = actions, 1850 flag_groups = [ 1851 flag_group( 1852 flags = flags, 1853 ), 1854 ], 1855 # Any new sanitizers that are enabled need to have a 1856 # with_feature_set added here. 1857 with_features = [ 1858 with_feature_set( 1859 features = ["sanitizers_enabled"], 1860 ), 1861 ], 1862 ), 1863 ], 1864 ) 1865 1866def _host_or_device_specific_sanitizer_feature(target_os): 1867 if is_os_device(target_os): 1868 return _sanitizer_flag_feature( 1869 "sanitizer_device_only_flags", 1870 _actions.compile, 1871 _generated_sanitizer_constants.DeviceOnlySanitizeFlags, 1872 ) 1873 return _sanitizer_flag_feature( 1874 "sanitizer_host_only_flags", 1875 _actions.compile, 1876 _generated_sanitizer_constants.HostOnlySanitizeFlags, 1877 ) 1878 1879def _exclude_ubsan_rt_feature(path): 1880 if not path: 1881 return None 1882 return feature( 1883 name = "ubsan_exclude_rt", 1884 enabled = True, 1885 flag_sets = [ 1886 flag_set( 1887 actions = _actions.link, 1888 flag_groups = [ 1889 flag_group( 1890 flags = ["-Wl,--exclude-libs=" + path.basename], 1891 ), 1892 ], 1893 ), 1894 ], 1895 ) 1896 1897int_overflow_ignorelist_path = "build/soong/cc/config" 1898int_overflow_ignorelist_filename = "integer_overflow_blocklist.txt" 1899 1900def _get_unsupported_integer_check_with_feature_sets(feature_check): 1901 integer_sanitizers = [ 1902 "implicit-unsigned-integer-truncation", 1903 "implicit-signed-integer-truncation", 1904 "implicit-integer-sign-change", 1905 "integer-divide-by-zero", 1906 "signed-integer-overflow", 1907 "unsigned-integer-overflow", 1908 "implicit-integer-truncation", 1909 "implicit-integer-arithmetic-value-change", 1910 "integer", 1911 "integer_overflow", 1912 ] 1913 if feature_check in integer_sanitizers: 1914 integer_sanitizers.remove(feature_check) 1915 1916 return [ 1917 with_feature_set( 1918 features = ["ubsan_" + integer_sanitizer], 1919 not_features = ["ubsan_" + feature_check], 1920 ) 1921 for integer_sanitizer in integer_sanitizers 1922 ] 1923 1924def _get_ubsan_features(target_os, libclang_rt_ubsan_minimal): 1925 if target_os in [_oses.Windows, _oses.Darwin]: 1926 return [] 1927 1928 ALL_UBSAN_ACTIONS = _actions.compile + _actions.link + _actions.assemble 1929 1930 ubsan_features = [ 1931 feature( 1932 name = "ubsan_enabled", 1933 enabled = False, 1934 implies = ["sanitizers_enabled"], 1935 ), 1936 ] 1937 1938 ubsan_features.append( 1939 feature( 1940 name = "ubsan_integer_overflow", 1941 enabled = False, 1942 flag_sets = [ 1943 flag_set( 1944 actions = ALL_UBSAN_ACTIONS, 1945 flag_groups = [ 1946 flag_group( 1947 flags = [ 1948 "-fsanitize=unsigned-integer-overflow", 1949 "-fsanitize=signed-integer-overflow", 1950 ], 1951 ), 1952 ], 1953 ), 1954 flag_set( 1955 actions = _actions.c_and_cpp_compile, 1956 flag_groups = [ 1957 flag_group( 1958 flags = [ 1959 "-fsanitize-ignorelist=%s/%s" % ( 1960 int_overflow_ignorelist_path, 1961 int_overflow_ignorelist_filename, 1962 ), 1963 ], 1964 ), 1965 ], 1966 ), 1967 ], 1968 implies = ["ubsan_minimal_runtime", "ubsan_enabled"], 1969 ), 1970 ) 1971 1972 ubsan_checks = [ 1973 "alignment", 1974 "bool", 1975 "builtin", 1976 "bounds", 1977 "array-bounds", 1978 "local-bounds", 1979 "enum", 1980 "float-cast-overflow", 1981 "float-divide-by-zero", 1982 "function", 1983 "implicit-unsigned-integer-truncation", 1984 "implicit-signed-integer-truncation", 1985 "implicit-integer-sign-change", 1986 "integer-divide-by-zero", 1987 "nonnull-attribute", 1988 "null", 1989 "nullability-arg", 1990 "nullability-assign", 1991 "nullability-return", 1992 "objc-cast", 1993 "object-size", 1994 "pointer-overflow", 1995 "return", 1996 "returns-nonnull-attribute", 1997 "shift", 1998 "shift-base", 1999 "shift-exponent", 2000 "unsigned-shift-base", 2001 "signed-integer-overflow", 2002 "unreachable", 2003 "unsigned-integer-overflow", 2004 "vla-bound", 2005 "vptr", 2006 2007 # check groups 2008 "undefined", 2009 "implicit-integer-truncation", 2010 "implicit-integer-arithmetic-value-change", 2011 "implicit-conversion", 2012 "integer", 2013 "nullability", 2014 ] 2015 ubsan_features += [ 2016 feature( 2017 name = "ubsan_" + check_name, 2018 enabled = False, 2019 flag_sets = [ 2020 flag_set( 2021 actions = ALL_UBSAN_ACTIONS, 2022 flag_groups = [ 2023 flag_group( 2024 flags = ["-fsanitize=%s" % check_name], 2025 ), 2026 ], 2027 ), 2028 ], 2029 implies = ["ubsan_minimal_runtime", "ubsan_enabled"], 2030 ) 2031 for check_name in ubsan_checks 2032 ] 2033 2034 ubsan_features.append( 2035 feature( 2036 name = "ubsan_no_sanitize_link_runtime", 2037 enabled = target_os in [ 2038 _oses.Android, 2039 _oses.LinuxBionic, 2040 _oses.LinuxMusl, 2041 ], 2042 flag_sets = [ 2043 flag_set( 2044 actions = _actions.link, 2045 flag_groups = [ 2046 flag_group( 2047 flags = [ 2048 _generated_sanitizer_constants.NoSanitizeLinkRuntimeFlag, 2049 ], 2050 ), 2051 ], 2052 with_features = [ 2053 with_feature_set( 2054 features = ["sanitizers_enabled"], 2055 ), 2056 ], 2057 ), 2058 ], 2059 ), 2060 ) 2061 2062 # non-Bionic toolchain prebuilts are missing UBSan's vptr and function san. 2063 # Musl toolchain prebuilts have vptr and function sanitizers, but enabling 2064 # them implicitly enables RTTI which causes RTTI mismatch issues with 2065 # dependencies. 2066 ubsan_features.append( 2067 feature( 2068 name = "ubsan_disable_unsupported_non_bionic_checks", 2069 enabled = target_os not in [_oses.LinuxBionic, _oses.Android], 2070 flag_sets = [ 2071 flag_set( 2072 actions = _actions.c_and_cpp_compile, 2073 flag_groups = [ 2074 flag_group( 2075 flags = [ 2076 "-fno-sanitize=function,vptr", 2077 ], 2078 ), 2079 ], 2080 with_features = [ 2081 with_feature_set( 2082 features = ["ubsan_integer_overflow"], 2083 ), 2084 ] + [ 2085 with_feature_set(features = ["ubsan_" + check_name]) 2086 for check_name in ubsan_checks 2087 ], 2088 ), 2089 ], 2090 ), 2091 ) 2092 2093 ubsan_features += [ 2094 _host_or_device_specific_sanitizer_feature(target_os), 2095 _exclude_ubsan_rt_feature(libclang_rt_ubsan_minimal), 2096 ] 2097 2098 ubsan_features.append( 2099 feature( 2100 name = "ubsan_minimal_runtime", 2101 enabled = False, 2102 flag_sets = [ 2103 flag_set( 2104 actions = _actions.c_and_cpp_compile, 2105 flag_groups = [ 2106 flag_group( 2107 flags = _generated_sanitizer_constants.MinimalRuntimeFlags, 2108 ), 2109 ], 2110 ), 2111 ], 2112 ), 2113 ) 2114 2115 ubsan_features.append( 2116 feature( 2117 name = "ubsan_disable_unsupported_integer_checks", 2118 enabled = True, 2119 flag_sets = [ 2120 # TODO(b/119329758): If this bug is fixed, this shouldn't be 2121 # needed anymore 2122 flag_set( 2123 actions = _actions.c_and_cpp_compile, 2124 flag_groups = [ 2125 flag_group( 2126 flags = [ 2127 "-fno-sanitize=implicit-integer-sign-change", 2128 ], 2129 ), 2130 ], 2131 with_features = _get_unsupported_integer_check_with_feature_sets( 2132 "implicit-integer-sign-change", 2133 ), 2134 ), 2135 # TODO(b/171275751): If this bug is fixed, this shouldn't be 2136 # needed anymore 2137 flag_set( 2138 actions = _actions.c_and_cpp_compile, 2139 flag_groups = [ 2140 flag_group( 2141 flags = [ 2142 "-fno-sanitize=unsigned-shift-base", 2143 ], 2144 ), 2145 ], 2146 with_features = _get_unsupported_integer_check_with_feature_sets( 2147 "unsigned-shift-base", 2148 ), 2149 ), 2150 ], 2151 ), 2152 ) 2153 2154 return ubsan_features 2155 2156def _manual_binder_interface_feature(): 2157 return feature( 2158 name = "do_not_check_manual_binder_interfaces", 2159 enabled = False, 2160 flag_sets = [ 2161 flag_set( 2162 actions = _actions.compile, 2163 flag_groups = [ 2164 flag_group( 2165 flags = [ 2166 "-DDO_NOT_CHECK_MANUAL_BINDER_INTERFACES", 2167 ], 2168 ), 2169 ], 2170 ), 2171 ], 2172 ) 2173 2174# Create the full list of features. 2175# buildifier: disable=function-docstring 2176def get_features( 2177 ctx, 2178 builtin_include_dirs, 2179 crt_files): 2180 target_os = ctx.attr.target_os 2181 target_arch = ctx.attr.target_arch 2182 target_flags = ctx.attr.target_flags 2183 compile_only_flags = ctx.attr.compiler_flags 2184 linker_only_flags = ctx.attr.linker_flags 2185 device_max_page_size = ctx.attr._device_max_page_size_supported[BuildSettingInfo].value 2186 if device_max_page_size and (target_arch == "arm64" or target_arch == "x86_64"): 2187 linker_only_flags = ctx.attr.linker_flags + \ 2188 ["-Wl,-z,max-page-size=" + device_max_page_size] 2189 2190 libclang_rt_builtin = ctx.file.libclang_rt_builtin 2191 libclang_rt_ubsan_minimal = ctx.file.libclang_rt_ubsan_minimal 2192 rtti_toggle = ctx.attr.rtti_toggle 2193 2194 os_is_device = is_os_device(target_os) 2195 arch_is_64_bit = target_arch.endswith("64") 2196 2197 # Aggregate all features in order. 2198 # Note that the feature-list helper methods called below may return empty 2199 # lists, depending on whether these features should be enabled. These are still 2200 # listed in the below stanza as-is to preserve ordering. 2201 features = [ 2202 # Do not depend on Bazel's built-in legacy features and action configs: 2203 feature(name = "no_legacy_features"), 2204 2205 # This must always come first, after no_legacy_features. 2206 _link_crtbegin(crt_files), 2207 2208 # Explicitly depend on a subset of legacy configs: 2209 _get_legacy_features_begin(), 2210 2211 # get_c_std_features must come before _compiler_flag_features and user 2212 # compile flags, as build targets may use copts/cflags to explicitly 2213 # change the -std version to overwrite the defaults or c{,pp}_std attribute 2214 # value. 2215 _get_c_std_features(), 2216 # Features tied to sdk version 2217 _get_sdk_version_features(os_is_device, target_arch), 2218 _compiler_flag_features(ctx, target_arch, target_os, target_flags + compile_only_flags), 2219 _rpath_features(target_os, arch_is_64_bit), 2220 # Optimization 2221 _get_thinlto_features(), 2222 # Sanitizers 2223 _get_cfi_features(target_arch, target_os), 2224 _get_memtag_features(target_arch, target_os), 2225 _get_ubsan_features(target_os, libclang_rt_ubsan_minimal), 2226 _get_misc_sanitizer_features(), 2227 # Misc features 2228 _get_visibiility_hidden_feature(), 2229 # RTTI 2230 _rtti_features(rtti_toggle), 2231 _use_libcrt_feature(libclang_rt_builtin), 2232 # Shared compile/link flags that should also be part of the link actions. 2233 _linker_flag_feature("linker_target_flags", flags = target_flags), 2234 # Link-only flags. 2235 _linker_flag_feature("linker_flags", flags = linker_only_flags + _additional_linker_flags(os_is_device)), 2236 _archiver_flag_feature("additional_archiver_flags", flags = _additional_archiver_flags(target_os)), 2237 _undefined_symbols_feature(target_os), 2238 _dynamic_linker_flag_feature(target_os, arch_is_64_bit), 2239 _binary_linker_flag_feature("dynamic_executable", flags = _shared_binary_linker_flags(target_os)), 2240 # distinct from other static flags as it can be disabled separately 2241 _binary_linker_flag_feature("static_flag", flags = ["-static"], enabled = False), 2242 # default for executables is dynamic linking 2243 _binary_linker_flag_feature("static_executable", flags = _static_binary_linker_flags(os_is_device), enabled = False), 2244 _manual_binder_interface_feature(), 2245 _pack_dynamic_relocations_features(target_os), 2246 # System include directories features 2247 _toolchain_include_feature(system_includes = builtin_include_dirs), 2248 # Compiling stub.c sources to stub libraries 2249 _stub_library_feature(), 2250 _get_legacy_features_end(), 2251 # Flags that cannot be overridden must be at the end 2252 _get_no_override_compile_flags(target_os), 2253 # This must always come last. 2254 _link_crtend(crt_files), 2255 ] 2256 2257 return _flatten([f for f in features if f != None]) 2258