1# Copyright (C) 2021 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//rules:common_settings.bzl", "BuildSettingInfo") 17load("@bazel_tools//tools/build_defs/cc:action_names.bzl", "ACTION_NAMES") 18load("@bazel_tools//tools/cpp:toolchain_utils.bzl", "find_cpp_toolchain") 19load("//build/bazel/rules:common.bzl", "get_dep_targets") 20load( 21 ":cc_library_common.bzl", 22 "CPP_EXTENSIONS", 23 "C_EXTENSIONS", 24 "CcAndroidMkInfo", 25 "check_absolute_include_dirs_disabled", 26 "create_cc_androidmk_provider", 27 "create_ccinfo_for_includes", 28 "get_non_header_srcs", 29 "get_sanitizer_lib_info", 30 "is_external_directory", 31 "parse_sdk_version", 32 "system_dynamic_deps_defaults", 33) 34load(":clang_tidy.bzl", "ClangTidyInfo", "clang_tidy_for_dir", "generate_clang_tidy_actions") 35load(":lto_transitions.bzl", "lto_deps_transition") 36load(":stl.bzl", "stl_info_from_attr") 37 38_ALLOWED_MANUAL_INTERFACE_PATHS = [ 39 "vendor/", 40 "hardware/", 41 # for testing 42 "build/bazel/rules/cc", 43] 44 45CcStaticLibraryInfo = provider(fields = ["root_static_archive", "objects"]) 46 47def cc_library_static( 48 name, 49 deps = [], 50 implementation_deps = [], 51 dynamic_deps = [], 52 implementation_dynamic_deps = [], 53 whole_archive_deps = [], 54 implementation_whole_archive_deps = [], 55 system_dynamic_deps = None, 56 runtime_deps = [], 57 export_absolute_includes = [], 58 export_includes = [], 59 export_system_includes = [], 60 local_includes = [], 61 absolute_includes = [], 62 hdrs = [], 63 native_bridge_supported = False, # TODO: not supported yet. @unused 64 rtti = False, 65 stl = "", 66 cpp_std = "", 67 c_std = "", 68 # Flags for C and C++ 69 copts = [], 70 # C++ attributes 71 srcs = [], 72 cppflags = [], 73 # C attributes 74 srcs_c = [], 75 conlyflags = [], 76 # asm attributes 77 srcs_as = [], 78 asflags = [], 79 features = [], 80 linkopts = [], 81 alwayslink = None, 82 target_compatible_with = [], 83 # TODO(b/202299295): Handle data attribute. 84 data = [], # @unused 85 sdk_version = "", # @unused 86 min_sdk_version = "", 87 tags = [], 88 tidy = None, 89 tidy_checks = None, 90 tidy_checks_as_errors = None, 91 tidy_flags = None, 92 tidy_disabled_srcs = None, 93 tidy_timeout_srcs = None, 94 tidy_gen_header_filter = None, 95 native_coverage = True): 96 "Bazel macro to correspond with the cc_library_static Soong module." 97 98 exports_name = "%s_exports" % name 99 locals_name = "%s_locals" % name 100 cpp_name = "%s_cpp" % name 101 c_name = "%s_c" % name 102 asm_name = "%s_asm" % name 103 104 toolchain_features = [] 105 106 toolchain_features.append("pic") 107 108 if is_external_directory(native.package_name()): 109 toolchain_features += [ 110 "-non_external_compiler_flags", 111 "external_compiler_flags", 112 ] 113 else: 114 toolchain_features += [ 115 "non_external_compiler_flags", 116 "-external_compiler_flags", 117 ] 118 119 if rtti: 120 toolchain_features.append("rtti") 121 if cpp_std: 122 toolchain_features += [cpp_std, "-cpp_std_default"] 123 if c_std: 124 toolchain_features += [c_std, "-c_std_default"] 125 126 for path in _ALLOWED_MANUAL_INTERFACE_PATHS: 127 if native.package_name().startswith(path): 128 toolchain_features += ["do_not_check_manual_binder_interfaces"] 129 break 130 131 if min_sdk_version: 132 toolchain_features += parse_sdk_version(min_sdk_version) + ["-sdk_version_default"] 133 toolchain_features += features 134 135 if not native_coverage: 136 toolchain_features += ["-coverage"] # buildifier: disable=list-append This could be a select, not a list 137 138 if system_dynamic_deps == None: 139 system_dynamic_deps = system_dynamic_deps_defaults 140 141 _cc_includes( 142 name = exports_name, 143 includes = export_includes, 144 absolute_includes = export_absolute_includes, 145 system_includes = export_system_includes, 146 # whole archive deps always re-export their includes, etc 147 deps = deps + whole_archive_deps + dynamic_deps, 148 target_compatible_with = target_compatible_with, 149 tags = ["manual"], 150 ) 151 152 stl_info = stl_info_from_attr(stl, False) 153 linkopts = linkopts + stl_info.linkopts 154 copts = copts + stl_info.cppflags 155 156 _cc_includes( 157 name = locals_name, 158 includes = local_includes, 159 absolute_includes = absolute_includes, 160 deps = ( 161 implementation_deps + 162 implementation_dynamic_deps + 163 system_dynamic_deps + 164 stl_info.static_deps + 165 stl_info.shared_deps + 166 implementation_whole_archive_deps 167 ), 168 target_compatible_with = target_compatible_with, 169 tags = ["manual"], 170 ) 171 172 # Silently drop these attributes for now: 173 # - native_bridge_supported 174 common_attrs = dict( 175 [ 176 # TODO(b/199917423): This may be superfluous. Investigate and possibly remove. 177 ("linkstatic", True), 178 ("hdrs", hdrs), 179 # Add dynamic_deps to implementation_deps, as the include paths from the 180 # dynamic_deps are also needed. 181 ("implementation_deps", [locals_name]), 182 ("deps", [exports_name]), 183 ("features", toolchain_features), 184 ("toolchains", ["//build/bazel/product_config:product_vars"]), 185 ("target_compatible_with", target_compatible_with), 186 ("linkopts", linkopts), 187 ], 188 ) 189 190 # TODO(b/231574899): restructure this to handle other images 191 copts += select({ 192 "//build/bazel/rules/apex:non_apex": [], 193 "//conditions:default": [ 194 "-D__ANDROID_APEX__", 195 ], 196 }) 197 198 native.cc_library( 199 name = cpp_name, 200 srcs = srcs, 201 copts = copts + cppflags, 202 tags = ["manual"], 203 alwayslink = True, 204 **common_attrs 205 ) 206 native.cc_library( 207 name = c_name, 208 srcs = srcs_c, 209 copts = copts + conlyflags, 210 tags = ["manual"], 211 alwayslink = True, 212 **common_attrs 213 ) 214 native.cc_library( 215 name = asm_name, 216 srcs = srcs_as, 217 copts = asflags, 218 tags = ["manual"], 219 alwayslink = True, 220 **common_attrs 221 ) 222 223 # Root target to handle combining of the providers of the language-specific targets. 224 _cc_library_combiner( 225 name = name, 226 roots = [cpp_name, c_name, asm_name], 227 deps = whole_archive_deps + implementation_whole_archive_deps, 228 additional_sanitizer_deps = ( 229 deps + 230 stl_info.static_deps + 231 implementation_deps 232 ), 233 runtime_deps = runtime_deps, 234 target_compatible_with = target_compatible_with, 235 alwayslink = alwayslink, 236 static_deps = deps + implementation_deps + whole_archive_deps + implementation_whole_archive_deps, 237 androidmk_static_deps = deps + implementation_deps + stl_info.static_deps, 238 androidmk_whole_archive_deps = whole_archive_deps + implementation_whole_archive_deps, 239 androidmk_dynamic_deps = dynamic_deps + implementation_dynamic_deps + system_dynamic_deps + stl_info.shared_deps, 240 exports = exports_name, 241 tags = tags, 242 features = toolchain_features, 243 244 # clang-tidy attributes 245 tidy = tidy, 246 srcs_cpp = srcs, 247 srcs_c = srcs_c, 248 copts_cpp = copts + cppflags, 249 copts_c = copts + conlyflags, 250 hdrs = hdrs, 251 includes = [locals_name, exports_name], 252 tidy_flags = tidy_flags, 253 tidy_checks = tidy_checks, 254 tidy_checks_as_errors = tidy_checks_as_errors, 255 tidy_disabled_srcs = tidy_disabled_srcs, 256 tidy_timeout_srcs = tidy_timeout_srcs, 257 tidy_gen_header_filter = tidy_gen_header_filter, 258 ) 259 260def _generate_tidy_files(ctx): 261 disabled_srcs = [] + ctx.files.tidy_disabled_srcs 262 tidy_timeout = ctx.attr._tidy_timeout[BuildSettingInfo].value 263 if tidy_timeout != "": 264 disabled_srcs.extend(ctx.attr.tidy_timeout_srcs) 265 266 if ctx.attr.tidy_gen_header_filter: 267 if ctx.attr.tidy_flags: 268 fail("tidy_flags cannot be set when also using tidy_gen_header_filter") 269 tidy_flags = ["-header-filter=" + paths.join(ctx.genfiles_dir.path, ctx.label.package) + ".*"] 270 else: 271 tidy_flags = ctx.attr.tidy_flags 272 273 cpp_srcs, cpp_hdrs = get_non_header_srcs( 274 ctx.files.srcs_cpp, 275 ctx.files.tidy_disabled_srcs, 276 source_extensions = CPP_EXTENSIONS, 277 ) 278 c_srcs, c_hdrs = get_non_header_srcs( 279 ctx.files.srcs_cpp + ctx.files.srcs_c, 280 ctx.files.tidy_disabled_srcs, 281 source_extensions = C_EXTENSIONS, 282 ) 283 hdrs = ctx.files.hdrs + cpp_hdrs + c_hdrs 284 cpp_tidy_outs = generate_clang_tidy_actions( 285 ctx, 286 ctx.attr.copts_cpp, 287 ctx.attr.deps + ctx.attr.includes, 288 cpp_srcs, 289 hdrs, 290 "c++", 291 tidy_flags, 292 ctx.attr.tidy_checks, 293 ctx.attr.tidy_checks_as_errors, 294 tidy_timeout, 295 ) 296 c_tidy_outs = generate_clang_tidy_actions( 297 ctx, 298 ctx.attr.copts_c, 299 ctx.attr.deps + ctx.attr.includes, 300 c_srcs, 301 hdrs, 302 "c", 303 tidy_flags, 304 ctx.attr.tidy_checks, 305 ctx.attr.tidy_checks_as_errors, 306 tidy_timeout, 307 ) 308 return cpp_tidy_outs + c_tidy_outs 309 310def _generate_tidy_actions(ctx): 311 transitive_tidy_files = [] 312 for ts in get_dep_targets(ctx.attr, predicate = lambda t: ClangTidyInfo in t).values(): 313 for t in ts: 314 transitive_tidy_files.append(t[ClangTidyInfo].transitive_tidy_files) 315 316 with_tidy = ctx.attr._with_tidy[BuildSettingInfo].value 317 allow_local_tidy_true = ctx.attr._allow_local_tidy_true[BuildSettingInfo].value 318 tidy_external_vendor = ctx.attr._tidy_external_vendor[BuildSettingInfo].value 319 tidy_enabled = (with_tidy and ctx.attr.tidy != "never") or (allow_local_tidy_true and ctx.attr.tidy == "local") 320 should_run_for_current_package = clang_tidy_for_dir(tidy_external_vendor, ctx.label.package) 321 if tidy_enabled and should_run_for_current_package: 322 direct_tidy_files = _generate_tidy_files(ctx) 323 else: 324 direct_tidy_files = None 325 326 tidy_files = depset( 327 direct = direct_tidy_files, 328 ) 329 transitive_tidy_files = depset( 330 direct = direct_tidy_files, 331 transitive = transitive_tidy_files, 332 ) 333 return [ 334 OutputGroupInfo( 335 _validation = tidy_files, 336 ), 337 ClangTidyInfo( 338 tidy_files = tidy_files, 339 transitive_tidy_files = transitive_tidy_files, 340 ), 341 ] 342 343def _archive_with_prebuilt_libs(ctx, prebuilt_deps, linking_outputs, cc_toolchain): 344 linking_output = linking_outputs.library_to_link.static_library 345 if not prebuilt_deps: 346 return linking_output 347 348 feature_configuration = cc_common.configure_features( 349 ctx = ctx, 350 cc_toolchain = cc_toolchain, 351 requested_features = ctx.features + ["archive_with_prebuilt_flags"], 352 unsupported_features = ctx.disabled_features + ["linker_flags", "archiver_flags"], 353 ) 354 355 output_file = ctx.actions.declare_file("lib" + ctx.label.name + ".a") 356 357 archiver_path = cc_common.get_tool_for_action( 358 feature_configuration = feature_configuration, 359 action_name = ACTION_NAMES.cpp_link_static_library, 360 ) 361 archiver_variables = cc_common.create_link_variables( 362 feature_configuration = feature_configuration, 363 cc_toolchain = cc_toolchain, 364 output_file = output_file.path, 365 is_using_linker = False, 366 ) 367 command_line = cc_common.get_memory_inefficient_command_line( 368 feature_configuration = feature_configuration, 369 action_name = ACTION_NAMES.cpp_link_static_library, 370 variables = archiver_variables, 371 ) 372 args = ctx.actions.args() 373 args.add_all(command_line) 374 args.add(linking_output) 375 args.add_all(prebuilt_deps) 376 377 ctx.actions.run( 378 executable = archiver_path, 379 arguments = [args], 380 inputs = depset( 381 direct = [linking_output] + prebuilt_deps, 382 transitive = [ 383 cc_toolchain.all_files, 384 ], 385 ), 386 outputs = [output_file], 387 mnemonic = "CppArchive", 388 ) 389 390 return output_file 391 392# Returns a CcInfo object which combines one or more CcInfo objects, except that all 393# linker inputs owned by owners in `old_owner_labels` are relinked and owned by the current target. 394# 395# This is useful in the "macro with proxy rule" pattern, as some rules upstream 396# may expect they are depending directly on a target which generates linker inputs, 397# as opposed to a proxy target which is a level of indirection to such a target. 398def _cc_library_combiner_impl(ctx): 399 old_owner_labels = [] 400 cc_infos = [] 401 for dep in ctx.attr.deps: 402 old_owner_labels.append(dep.label) 403 cc_info = dep[CcInfo] 404 405 # do not propagate includes, hdrs, etc, already handled by roots 406 cc_infos.append(CcInfo(linking_context = cc_info.linking_context)) 407 408 # we handle roots after deps to mimic Soong handling objects from whole archive deps prior to objects from the target itself 409 for dep in ctx.attr.roots: 410 old_owner_labels.append(dep.label) 411 cc_infos.append(dep[CcInfo]) 412 413 combined_info = cc_common.merge_cc_infos(cc_infos = cc_infos) 414 415 objects_to_link = [] 416 417 prebuilt_deps = [] 418 419 # This is not ideal, as it flattens a depset. 420 for old_linker_input in combined_info.linking_context.linker_inputs.to_list(): 421 if old_linker_input.owner in old_owner_labels: 422 for lib in old_linker_input.libraries: 423 # These objects will be recombined into the root archive. 424 objects_to_link.extend(lib.objects) 425 426 # This is a prebuilt library, we have to handle it separately 427 if not lib.objects and lib.static_library: 428 prebuilt_deps.append(lib.static_library) 429 else: 430 # Android macros don't handle transitive linker dependencies because 431 # it's unsupported in legacy. We may want to change this going forward, 432 # but for now it's good to validate that this invariant remains. 433 fail("cc_static_library %s given transitive linker dependency from %s" % (ctx.label, old_linker_input.owner)) 434 435 cc_toolchain = find_cpp_toolchain(ctx) 436 437 feature_configuration = cc_common.configure_features( 438 ctx = ctx, 439 cc_toolchain = cc_toolchain, 440 requested_features = ctx.features + ["archiver_flags"], 441 unsupported_features = ctx.disabled_features + ["linker_flags"], 442 ) 443 444 out_name = ctx.label.name 445 if prebuilt_deps: 446 out_name += "_objs_only" 447 linking_context, linking_outputs = cc_common.create_linking_context_from_compilation_outputs( 448 actions = ctx.actions, 449 name = out_name, 450 feature_configuration = feature_configuration, 451 cc_toolchain = cc_toolchain, 452 alwayslink = ctx.attr.alwayslink, 453 disallow_dynamic_library = True, 454 compilation_outputs = cc_common.create_compilation_outputs(objects = depset(direct = objects_to_link)), 455 ) 456 457 output_file = _archive_with_prebuilt_libs(ctx, prebuilt_deps, linking_outputs, cc_toolchain) 458 linker_input = cc_common.create_linker_input( 459 owner = ctx.label, 460 libraries = depset(direct = [ 461 cc_common.create_library_to_link( 462 actions = ctx.actions, 463 feature_configuration = feature_configuration, 464 cc_toolchain = cc_toolchain, 465 static_library = output_file, 466 objects = objects_to_link, 467 alwayslink = ctx.attr.alwayslink, 468 ), 469 ]), 470 ) 471 linking_context = cc_common.create_linking_context(linker_inputs = depset(direct = [linker_input])) 472 473 providers = [ 474 DefaultInfo(files = depset(direct = [output_file]), data_runfiles = ctx.runfiles(files = [output_file])), 475 CcInfo(compilation_context = combined_info.compilation_context, linking_context = linking_context), 476 CcStaticLibraryInfo(root_static_archive = output_file, objects = objects_to_link), 477 get_sanitizer_lib_info(ctx.attr.features, ctx.attr.deps + ctx.attr.additional_sanitizer_deps), 478 create_cc_androidmk_provider( 479 static_deps = ctx.attr.androidmk_static_deps, 480 whole_archive_deps = ctx.attr.androidmk_whole_archive_deps, 481 dynamic_deps = ctx.attr.androidmk_dynamic_deps, 482 ), 483 ] 484 providers.extend(_generate_tidy_actions(ctx)) 485 486 return providers 487 488# A rule which combines objects of oen or more cc_library targets into a single 489# static linker input. This outputs a single archive file combining the objects 490# of its direct deps, and propagates Cc providers describing that these objects 491# should be linked for linking rules upstream. 492# This rule is useful for maintaining the illusion that the target's deps are 493# comprised by a single consistent rule: 494# - A single archive file is always output by this rule. 495# - A single linker input struct is always output by this rule, and it is 'owned' 496# by this rule. 497_cc_library_combiner = rule( 498 implementation = _cc_library_combiner_impl, 499 attrs = { 500 "roots": attr.label_list( 501 providers = [CcInfo], 502 cfg = lto_deps_transition, 503 ), 504 "deps": attr.label_list( 505 providers = [CcInfo], 506 cfg = lto_deps_transition, 507 ), 508 "additional_sanitizer_deps": attr.label_list( 509 providers = [CcInfo], 510 cfg = lto_deps_transition, 511 doc = "Deps used only to check for sanitizer enablement", 512 ), 513 "runtime_deps": attr.label_list( 514 providers = [CcInfo], 515 doc = "Deps that should be installed along with this target. Read by the apex cc aspect.", 516 ), 517 "static_deps": attr.label_list( 518 providers = [CcInfo], 519 doc = "All the static deps of the lib. This is used by" + 520 " abi_dump_aspect to travel along the static_deps edges" + 521 " to create abi dump files.", 522 ), 523 "androidmk_static_deps": attr.label_list( 524 providers = [CcInfo], 525 doc = "All the whole archive deps of the lib. This is used to propagate" + 526 " information to AndroidMk about LOCAL_STATIC_LIBRARIES.", 527 ), 528 "androidmk_whole_archive_deps": attr.label_list( 529 providers = [CcInfo], 530 doc = "All the whole archive deps of the lib. This is used to propagate" + 531 " information to AndroidMk about LOCAL_WHOLE_STATIC_LIBRARIES.", 532 ), 533 "androidmk_dynamic_deps": attr.label_list( 534 providers = [CcInfo], 535 doc = "All the dynamic deps of the lib. This is used to propagate" + 536 " information to AndroidMk about LOCAL_SHARED_LIBRARIES." + 537 " The attribute name is prefixed with androidmk to avoid" + 538 " collision with the dynamic_deps attribute used in APEX" + 539 " aspects' propagation.", 540 ), 541 "exports": attr.label( 542 providers = [CcInfo], 543 cfg = lto_deps_transition, 544 ), 545 "_cc_toolchain": attr.label( 546 default = Label("@local_config_cc//:toolchain"), 547 providers = [cc_common.CcToolchainInfo], 548 doc = "The exported includes used by abi_dump_aspect to retrieve" + 549 " and use as the inputs of abi dumper binary.", 550 ), 551 "alwayslink": attr.bool( 552 doc = """At link time, whether these libraries should be wrapped in 553 the --whole_archive block. This causes all libraries in the static 554 archive to be unconditionally linked, regardless of whether the 555 symbols in these object files are being searched by the linker.""", 556 default = False, 557 ), 558 559 # Clang-tidy attributes 560 "tidy": attr.string(values = ["", "local", "never"]), 561 "srcs_cpp": attr.label_list(allow_files = True), 562 "srcs_c": attr.label_list(allow_files = True), 563 "copts_cpp": attr.string_list(), 564 "copts_c": attr.string_list(), 565 "hdrs": attr.label_list(allow_files = True), 566 "includes": attr.label_list(cfg = lto_deps_transition), 567 "tidy_checks": attr.string_list(), 568 "tidy_checks_as_errors": attr.string_list(), 569 "tidy_flags": attr.string_list(), 570 "tidy_disabled_srcs": attr.label_list(allow_files = True), 571 "tidy_timeout_srcs": attr.label_list(allow_files = True), 572 "tidy_gen_header_filter": attr.bool(), 573 "_clang_tidy_sh": attr.label( 574 default = Label("@//prebuilts/clang/host/linux-x86:clang-tidy.sh"), 575 allow_single_file = True, 576 executable = True, 577 cfg = "exec", 578 doc = "The clang tidy shell wrapper", 579 ), 580 "_clang_tidy": attr.label( 581 default = Label("@//prebuilts/clang/host/linux-x86:clang-tidy"), 582 allow_single_file = True, 583 executable = True, 584 cfg = "exec", 585 doc = "The clang tidy executable", 586 ), 587 "_clang_tidy_real": attr.label( 588 default = Label("@//prebuilts/clang/host/linux-x86:clang-tidy.real"), 589 allow_single_file = True, 590 executable = True, 591 cfg = "exec", 592 ), 593 "_with_tidy": attr.label( 594 default = "//build/bazel/flags/cc/tidy:with_tidy", 595 ), 596 "_allow_local_tidy_true": attr.label( 597 default = "//build/bazel/flags/cc/tidy:allow_local_tidy_true", 598 ), 599 "_with_tidy_flags": attr.label( 600 default = "//build/bazel/flags/cc/tidy:with_tidy_flags", 601 ), 602 "_default_tidy_header_dirs": attr.label( 603 default = "//build/bazel/flags/cc/tidy:default_tidy_header_dirs", 604 ), 605 "_tidy_timeout": attr.label( 606 default = "//build/bazel/flags/cc/tidy:tidy_timeout", 607 ), 608 "_tidy_external_vendor": attr.label( 609 default = "//build/bazel/flags/cc/tidy:tidy_external_vendor", 610 ), 611 "_allowlist_function_transition": attr.label( 612 default = "@bazel_tools//tools/allowlists/function_transition_allowlist", 613 ), 614 "_product_variables": attr.label( 615 default = "//build/bazel/product_config:product_vars", 616 ), 617 }, 618 toolchains = ["@bazel_tools//tools/cpp:toolchain_type"], 619 provides = [CcInfo, CcAndroidMkInfo], 620 fragments = ["cpp"], 621) 622 623def _cc_includes_impl(ctx): 624 check_absolute_include_dirs_disabled( 625 ctx.label.package, 626 ctx.attr.absolute_includes, 627 ) 628 629 return [create_ccinfo_for_includes( 630 ctx, 631 includes = ctx.attr.includes, 632 absolute_includes = ctx.attr.absolute_includes, 633 system_includes = ctx.attr.system_includes, 634 deps = ctx.attr.deps, 635 )] 636 637# Bazel's native cc_library rule supports specifying include paths two ways: 638# 1. non-exported includes can be specified via copts attribute 639# 2. exported -isystem includes can be specified via includes attribute 640# 641# In order to guarantee a correct inclusion search order, we need to export 642# includes paths for both -I and -isystem; however, there is no native Bazel 643# support to export both of these, this rule provides a CcInfo to propagate the 644# given package-relative include/system include paths as exec root relative 645# include/system include paths. 646_cc_includes = rule( 647 implementation = _cc_includes_impl, 648 attrs = { 649 "absolute_includes": attr.string_list(doc = "List of exec-root relative or absolute search paths for headers, usually passed with -I"), 650 "includes": attr.string_list(doc = "Package-relative list of search paths for headers, usually passed with -I"), 651 "system_includes": attr.string_list(doc = "Package-relative list of search paths for headers, usually passed with -isystem"), 652 "deps": attr.label_list(doc = "Re-propagates the includes obtained from these dependencies.", providers = [CcInfo]), 653 }, 654 toolchains = ["@bazel_tools//tools/cpp:toolchain_type"], 655 fragments = ["cpp"], 656 provides = [CcInfo], 657) 658