| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274 |
- # Part of the Carbon Language project, under the Apache License v2.0 with LLVM
- # Exceptions. See /LICENSE for license information.
- # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- """A Starlark cc_toolchain configuration rule"""
- load("@bazel_tools//tools/build_defs/cc:action_names.bzl", "ACTION_NAMES")
- load(
- "@bazel_tools//tools/cpp:cc_toolchain_config_lib.bzl",
- "action_config",
- "feature",
- "feature_set",
- "flag_group",
- "flag_set",
- "tool",
- "tool_path",
- "variable_with_value",
- "with_feature_set",
- )
- load("@rules_cc//cc:defs.bzl", "cc_toolchain")
- load(
- ":clang_detected_variables.bzl",
- "clang_bindir",
- "clang_include_dirs_list",
- "clang_resource_dir",
- "clang_version",
- "clang_version_for_cache",
- "llvm_bindir",
- "sysroot_dir",
- )
- all_c_compile_actions = [
- ACTION_NAMES.c_compile,
- ACTION_NAMES.assemble,
- ACTION_NAMES.preprocess_assemble,
- ]
- all_cpp_compile_actions = [
- ACTION_NAMES.cpp_compile,
- ACTION_NAMES.linkstamp_compile,
- ACTION_NAMES.cpp_header_parsing,
- ACTION_NAMES.cpp_module_compile,
- ACTION_NAMES.cpp_module_codegen,
- ]
- all_compile_actions = all_c_compile_actions + all_cpp_compile_actions
- preprocessor_compile_actions = [
- ACTION_NAMES.c_compile,
- ACTION_NAMES.cpp_compile,
- ACTION_NAMES.linkstamp_compile,
- ACTION_NAMES.preprocess_assemble,
- ACTION_NAMES.cpp_header_parsing,
- ACTION_NAMES.cpp_module_compile,
- ]
- codegen_compile_actions = [
- ACTION_NAMES.c_compile,
- ACTION_NAMES.cpp_compile,
- ACTION_NAMES.linkstamp_compile,
- ACTION_NAMES.assemble,
- ACTION_NAMES.preprocess_assemble,
- ACTION_NAMES.cpp_module_codegen,
- ]
- all_link_actions = [
- ACTION_NAMES.cpp_link_executable,
- ACTION_NAMES.cpp_link_dynamic_library,
- ACTION_NAMES.cpp_link_nodeps_dynamic_library,
- ]
- def _impl(ctx):
- tool_paths = [
- tool_path(name = "ar", path = llvm_bindir + "/llvm-ar"),
- tool_path(name = "ld", path = clang_bindir + "/ld.lld"),
- tool_path(name = "cpp", path = clang_bindir + "/clang-cpp"),
- tool_path(name = "gcc", path = clang_bindir + "/clang++"),
- tool_path(name = "dwp", path = llvm_bindir + "/llvm-dwp"),
- tool_path(name = "gcov", path = llvm_bindir + "/llvm-cov"),
- tool_path(name = "nm", path = llvm_bindir + "/llvm-nm"),
- tool_path(name = "objcopy", path = llvm_bindir + "/llvm-objcopy"),
- tool_path(name = "objdump", path = llvm_bindir + "/llvm-objdump"),
- tool_path(name = "strip", path = llvm_bindir + "/llvm-strip"),
- ]
- action_configs = [
- action_config(action_name = name, enabled = True, tools = [tool(path = clang_bindir + "/clang")])
- for name in all_c_compile_actions
- ] + [
- action_config(action_name = name, enabled = True, tools = [tool(path = clang_bindir + "/clang++")])
- for name in all_cpp_compile_actions
- ] + [
- action_config(action_name = name, enabled = True, tools = [tool(path = clang_bindir + "/clang++")])
- for name in all_link_actions
- ] + [
- action_config(action_name = name, enabled = True, tools = [tool(path = llvm_bindir + "/llvm-ar")])
- for name in [ACTION_NAMES.cpp_link_static_library]
- ] + [
- action_config(action_name = name, enabled = True, tools = [tool(path = llvm_bindir + "/llvm-strip")])
- for name in [ACTION_NAMES.strip]
- ]
- std_compile_flags = ["-std=c++20"]
- # libc++ is only used on non-Windows platforms.
- if ctx.attr.target_os != "windows":
- std_compile_flags.append("-stdlib=libc++")
- # TODO: Regression that warns on anonymous unions; remove depending on fix.
- # Sets the flag for unknown clang versions, which are assumed to be at head.
- # https://github.com/llvm/llvm-project/issues/70384
- if not clang_version or clang_version == 18:
- missing_field_init_flags = ["-Wno-missing-field-initializers"]
- elif clang_version > 18:
- missing_field_init_flags = ["-Wno-missing-designated-field-initializers"]
- else:
- missing_field_init_flags = []
- default_flags_feature = feature(
- name = "default_flags",
- enabled = True,
- flag_sets = [
- flag_set(
- actions = all_compile_actions + all_link_actions,
- flag_groups = ([
- flag_group(
- flags = [
- "-no-canonical-prefixes",
- "-fcolor-diagnostics",
- ],
- ),
- ]),
- ),
- flag_set(
- actions = all_compile_actions,
- flag_groups = ([
- flag_group(
- flags = [
- "-Werror",
- "-Wall",
- "-Wextra",
- "-Wthread-safety",
- "-Wself-assign",
- "-Wimplicit-fallthrough",
- "-Wctad-maybe-unsupported",
- "-Wextra-semi",
- "-Wmissing-prototypes",
- "-Wzero-as-null-pointer-constant",
- "-Wdelete-non-virtual-dtor",
- # Don't warn on external code as we can't
- # necessarily patch it easily. Note that these have
- # to be initial directories in the `#include` line.
- "--system-header-prefix=absl/",
- "--system-header-prefix=benchmark/",
- "--system-header-prefix=boost/",
- "--system-header-prefix=clang-tools-extra/",
- "--system-header-prefix=clang/",
- "--system-header-prefix=gmock/",
- "--system-header-prefix=gtest/",
- "--system-header-prefix=libfuzzer/",
- "--system-header-prefix=llvm/",
- "--system-header-prefix=re2/",
- "--system-header-prefix=tools/cpp/",
- "--system-header-prefix=tree_sitter/",
- # Compile actions shouldn't link anything.
- "-c",
- ] + missing_field_init_flags,
- ),
- flag_group(
- expand_if_available = "output_assembly_file",
- flags = ["-S"],
- ),
- flag_group(
- expand_if_available = "output_preprocess_file",
- flags = ["-E"],
- ),
- flag_group(
- flags = ["-MD", "-MF", "%{dependency_file}"],
- expand_if_available = "dependency_file",
- ),
- flag_group(
- flags = ["-frandom-seed=%{output_file}"],
- expand_if_available = "output_file",
- ),
- ]),
- ),
- flag_set(
- actions = all_cpp_compile_actions + all_link_actions,
- flag_groups = ([
- flag_group(
- flags = std_compile_flags,
- ),
- ]),
- ),
- flag_set(
- actions = codegen_compile_actions,
- flag_groups = ([
- flag_group(
- flags = [
- "-ffunction-sections",
- "-fdata-sections",
- ],
- ),
- ]),
- ),
- flag_set(
- actions = codegen_compile_actions,
- flag_groups = [
- flag_group(flags = ["-fPIC"], expand_if_available = "pic"),
- ],
- ),
- flag_set(
- actions = preprocessor_compile_actions,
- flag_groups = [
- flag_group(
- flags = [
- # Disable a warning and override builtin macros to
- # ensure a hermetic build.
- "-Wno-builtin-macro-redefined",
- "-D__DATE__=\"redacted\"",
- "-D__TIMESTAMP__=\"redacted\"",
- "-D__TIME__=\"redacted\"",
- # Pass the clang version as a define so that bazel
- # caching is more likely to notice version changes.
- "-DCLANG_VERSION_FOR_CACHE=\"%s\"" % clang_version_for_cache,
- ],
- ),
- flag_group(
- flags = ["-D%{preprocessor_defines}"],
- iterate_over = "preprocessor_defines",
- ),
- flag_group(
- flags = ["-include", "%{includes}"],
- iterate_over = "includes",
- expand_if_available = "includes",
- ),
- flag_group(
- flags = ["-iquote", "%{quote_include_paths}"],
- iterate_over = "quote_include_paths",
- ),
- flag_group(
- flags = ["-I%{include_paths}"],
- iterate_over = "include_paths",
- ),
- flag_group(
- flags = ["-isystem", "%{system_include_paths}"],
- iterate_over = "system_include_paths",
- ),
- ],
- ),
- flag_set(
- actions = [
- ACTION_NAMES.cpp_link_dynamic_library,
- ACTION_NAMES.cpp_link_nodeps_dynamic_library,
- ],
- flag_groups = [flag_group(flags = ["-shared"])],
- ),
- flag_set(
- actions = all_link_actions,
- flag_groups = [
- flag_group(
- flags = ["-Wl,-S"],
- expand_if_available = "strip_debug_symbols",
- ),
- flag_group(
- flags = ["-L%{library_search_directories}"],
- iterate_over = "library_search_directories",
- expand_if_available = "library_search_directories",
- ),
- flag_group(
- iterate_over = "runtime_library_search_directories",
- flags = [
- "-Wl,-rpath,$ORIGIN/%{runtime_library_search_directories}",
- ],
- expand_if_available =
- "runtime_library_search_directories",
- ),
- ],
- ),
- ],
- )
- # Handle different levels of optimization with individual features so that
- # they can be ordered and the defaults can override the minimal settings if
- # both are enabled.
- minimal_optimization_flags = feature(
- name = "minimal_optimization_flags",
- flag_sets = [
- flag_set(
- actions = codegen_compile_actions,
- flag_groups = [flag_group(flags = [
- "-O1",
- ])],
- ),
- ],
- )
- default_optimization_flags = feature(
- name = "default_optimization_flags",
- enabled = True,
- requires = [feature_set(["opt"])],
- flag_sets = [
- flag_set(
- actions = all_compile_actions,
- flag_groups = [flag_group(flags = [
- "-DNDEBUG",
- ])],
- ),
- flag_set(
- actions = codegen_compile_actions,
- flag_groups = [flag_group(flags = [
- "-O3",
- ])],
- ),
- ],
- )
- x86_64_cpu_flags = feature(
- name = "x86_64_cpu_flags",
- enabled = True,
- flag_sets = [
- flag_set(
- actions = all_compile_actions,
- flag_groups = [flag_group(flags = [
- "-march=x86-64-v2",
- ])],
- ),
- ],
- )
- aarch64_cpu_flags = feature(
- name = "aarch64_cpu_flags",
- enabled = True,
- flag_sets = [
- flag_set(
- actions = all_compile_actions,
- flag_groups = [flag_group(flags = [
- "-march=armv8.2-a",
- ])],
- ),
- ],
- )
- # Handle different levels and forms of debug info emission with individual
- # features so that they can be ordered and the defaults can override the
- # minimal settings if both are enabled.
- minimal_debug_info_flags = feature(
- name = "minimal_debug_info_flags",
- implies = ["debug_info_compression_flags"],
- flag_sets = [
- flag_set(
- actions = codegen_compile_actions,
- flag_groups = [
- flag_group(
- flags = ["-gmlt"],
- ),
- ],
- ),
- ],
- )
- debug_info_flags = feature(
- name = "debug_info_flags",
- implies = ["debug_info_compression_flags"],
- flag_sets = [
- flag_set(
- actions = codegen_compile_actions,
- flag_groups = ([
- flag_group(
- flags = ["-g"],
- ),
- flag_group(
- flags = ["-gsplit-dwarf"],
- expand_if_available = "per_object_debug_info_file",
- ),
- ]),
- ),
- ],
- )
- debug_info_compression_flags = feature(
- name = "debug_info_compression_flags",
- flag_sets = [
- flag_set(
- actions = codegen_compile_actions + all_link_actions,
- flag_groups = ([
- flag_group(
- flags = ["-gz"],
- ),
- ]),
- ),
- ],
- )
- # Define a set of mutually exclusive debugger flags.
- debugger_flags = feature(name = "debugger_flags")
- lldb_flags = feature(
- # Use a convenient name for users to select if needed.
- name = "lldb_flags",
- # Default enable LLDB-optimized flags whenever debugging.
- enabled = True,
- requires = [feature_set(features = ["debug_info_flags"])],
- provides = ["debugger_flags"],
- flag_sets = [
- flag_set(
- actions = codegen_compile_actions,
- flag_groups = ([
- flag_group(
- flags = [
- "-glldb",
- "-gpubnames",
- "-gsimple-template-names",
- ],
- ),
- ]),
- ),
- ],
- )
- gdb_flags = feature(
- # Use a convenient name for users to select if needed.
- name = "gdb_flags",
- requires = [feature_set(features = ["debug_info_flags"])],
- provides = ["debugger_flags"],
- flag_sets = [
- flag_set(
- actions = codegen_compile_actions,
- flag_groups = ([
- flag_group(
- flags = ["-ggdb"],
- ),
- flag_group(
- flags = ["-ggnu-pubnames"],
- ),
- ]),
- ),
- flag_set(
- actions = all_link_actions,
- flag_groups = [
- flag_group(
- flags = ["-Wl,--gdb-index"],
- ),
- ],
- ),
- ],
- )
- # An enabled feature that requires the `dbg` compilation mode. This is used
- # to toggle on more general features to use by default, while allowing those
- # general features to be explicitly enabled where needed.
- enable_in_dbg = feature(
- name = "enable_in_dbg",
- enabled = True,
- requires = [feature_set(["dbg"])],
- implies = [
- "debug_info_flags",
- ],
- )
- # This feature can be enabled in conjunction with any optimizations to
- # ensure accurate call stacks and backtraces for profilers or errors.
- preserve_call_stacks = feature(
- name = "preserve_call_stacks",
- flag_sets = [flag_set(
- actions = codegen_compile_actions,
- flag_groups = [flag_group(flags = [
- # Ensure good backtraces by preserving frame pointers and
- # disabling tail call elimination.
- "-fno-omit-frame-pointer",
- "-mno-omit-leaf-frame-pointer",
- "-fno-optimize-sibling-calls",
- ])],
- )],
- )
- sysroot_feature = feature(
- name = "sysroot",
- enabled = True,
- flag_sets = [
- flag_set(
- actions = all_compile_actions + all_link_actions,
- flag_groups = [
- flag_group(
- flags = ["--sysroot=%{sysroot}"],
- expand_if_available = "sysroot",
- ),
- ],
- ),
- ],
- )
- use_module_maps = feature(
- name = "use_module_maps",
- requires = [feature_set(features = ["module_maps"])],
- flag_sets = [
- flag_set(
- actions = [
- ACTION_NAMES.c_compile,
- ACTION_NAMES.cpp_compile,
- ACTION_NAMES.cpp_header_parsing,
- ACTION_NAMES.cpp_module_compile,
- ],
- flag_groups = [
- # These flag groups are separate so they do not expand to
- # the cross product of the variables.
- flag_group(flags = ["-fmodule-name=%{module_name}"]),
- flag_group(
- flags = ["-fmodule-map-file=%{module_map_file}"],
- ),
- ],
- ),
- ],
- )
- # Tell bazel we support module maps in general, so they will be generated
- # for all c/c++ rules.
- # Note: not all C++ rules support module maps; thus, do not imply this
- # feature from other features - instead, require it.
- module_maps = feature(
- name = "module_maps",
- enabled = True,
- implies = [
- # "module_map_home_cwd",
- # "module_map_without_extern_module",
- # "generate_submodules",
- ],
- )
- layering_check = feature(
- name = "layering_check",
- implies = ["use_module_maps"],
- flag_sets = [
- flag_set(
- actions = [
- ACTION_NAMES.c_compile,
- ACTION_NAMES.cpp_compile,
- ACTION_NAMES.cpp_header_parsing,
- ACTION_NAMES.cpp_module_compile,
- ],
- flag_groups = [
- flag_group(flags = [
- "-fmodules-strict-decluse",
- "-Wprivate-header",
- ]),
- flag_group(
- iterate_over = "dependent_module_map_files",
- flags = [
- "-fmodule-map-file=%{dependent_module_map_files}",
- ],
- ),
- ],
- ),
- ],
- )
- sanitizer_common_flags = feature(
- name = "sanitizer_common_flags",
- implies = ["minimal_debug_info_flags", "preserve_call_stacks"],
- )
- # Separated from the feature above so it can only be included on platforms
- # where it is supported. There is no negative flag in Clang so we can't just
- # override it later.
- sanitizer_static_lib_flags = feature(
- name = "sanitizer_static_lib_flags",
- enabled = True,
- requires = [feature_set(["sanitizer_common_flags"])],
- flag_sets = [flag_set(
- actions = all_link_actions,
- flag_groups = [flag_group(flags = [
- "-static-libsan",
- ])],
- )],
- )
- asan = feature(
- name = "asan",
- implies = ["sanitizer_common_flags"],
- flag_sets = [flag_set(
- actions = all_compile_actions + all_link_actions,
- flag_groups = [flag_group(flags = [
- "-fsanitize=address,undefined,nullability",
- "-fsanitize-address-use-after-scope",
- # Outlining is almost always the right tradeoff for our
- # sanitizer usage where we're more pressured on generated code
- # size than runtime performance.
- "-fsanitize-address-outline-instrumentation",
- # We don't need the recovery behavior of UBSan as we expect
- # builds to be clean. Not recovering is a bit cheaper.
- "-fno-sanitize-recover=undefined,nullability",
- # Don't embed the full path name for files. This limits the size
- # and combined with line numbers is unlikely to result in many
- # ambiguities.
- "-fsanitize-undefined-strip-path-components=-1",
- # Needed due to clang AST issues, such as in
- # clang/AST/Redeclarable.h line 199.
- "-fno-sanitize=vptr",
- ])],
- )],
- )
- # A feature that further reduces the generated code size of our the ASan
- # feature, but at the cost of lower quality diagnostics. This is enabled
- # along with ASan in our fastbuild configuration, but can be disabled
- # explicitly to get better error messages.
- asan_min_size = feature(
- name = "asan_min_size",
- requires = [feature_set(["asan"])],
- flag_sets = [flag_set(
- actions = all_compile_actions + all_link_actions,
- flag_groups = [flag_group(flags = [
- # Force two UBSan checks that have especially large code size
- # cost to use the minimal branch to a trapping instruction model
- # instead of the full diagnostic.
- "-fsanitize-trap=alignment,null",
- ])],
- )],
- )
- # Likely due to being unable to use the static-linked and up-to-date
- # sanitizer runtimes, we have to disable a number of sanitizers on macOS.
- macos_asan_workarounds = feature(
- name = "macos_sanitizer_workarounds",
- enabled = True,
- requires = [feature_set(["asan"])],
- flag_sets = [flag_set(
- actions = all_compile_actions + all_link_actions,
- flag_groups = [flag_group(flags = [
- "-fno-sanitize=function",
- ])],
- )],
- )
- # An enabled feature that requires the `fastbuild` compilation. This is used
- # to toggle general features on by default, while allowing them to be
- # directly enabled and disabled more generally as desired.
- enable_in_fastbuild = feature(
- name = "enable_in_fastbuild",
- enabled = True,
- requires = [feature_set(["fastbuild"])],
- implies = [
- "asan",
- "asan_min_size",
- "minimal_optimization_flags",
- "minimal_debug_info_flags",
- ],
- )
- fuzzer = feature(
- name = "fuzzer",
- flag_sets = [flag_set(
- actions = all_compile_actions + all_link_actions,
- flag_groups = [flag_group(flags = [
- "-fsanitize=fuzzer-no-link",
- ])],
- )],
- )
- if clang_version and clang_version <= 16:
- libcpp_debug_flags = ["-D_LIBCPP_ENABLE_ASSERTIONS=1"]
- libcpp_release_flags = ["-D_LIBCPP_ENABLE_ASSERTIONS=0"]
- elif clang_version and clang_version <= 17:
- # Clang 17 deprecates LIBCPP_ENABLE_ASSERTIONS in favor of
- # HARDENED_MODE and DEBUG_MODE.
- libcpp_debug_flags = ["-D_LIBCPP_ENABLE_HARDENED_MODE=1"]
- libcpp_release_flags = ["-D_LIBCPP_ENABLE_HARDENED_MODE=1"]
- else:
- # Clang 18 changes HARDENED_MODE to use 4 values:
- # https://releases.llvm.org/18.1.0/projects/libcxx/docs/Hardening.html#hardening-modes
- libcpp_debug_flags = [
- "-D_LIBCPP_ENABLE_HARDENED_MODE=_LIBCPP_HARDENING_MODE_EXTENSIVE",
- ]
- libcpp_release_flags = [
- "-D_LIBCPP_ENABLE_HARDENED_MODE=_LIBCPP_HARDENING_MODE_FAST",
- ]
- linux_flags_feature = feature(
- name = "linux_flags",
- enabled = True,
- flag_sets = [
- flag_set(
- actions = all_link_actions,
- flag_groups = ([
- flag_group(
- flags = [
- "-fuse-ld=lld",
- "-stdlib=libc++",
- "-unwindlib=libunwind",
- # Force the C++ standard library and runtime
- # libraries to be statically linked. This works even
- # with libc++ and libunwind despite the names,
- # provided libc++ is built with the CMake option:
- # - `-DCMAKE_POSITION_INDEPENDENT_CODE=ON`
- "-static-libstdc++",
- "-static-libgcc",
- # Link with Clang's runtime library. This is always
- # linked statically.
- "-rtlib=compiler-rt",
- # Explicitly add LLVM libs to the search path to
- # preempt the detected GCC installation's library
- # paths. Those might have a system installed libc++
- # and we want to find the one next to our Clang.
- "-L" + llvm_bindir + "/../lib",
- # Link with pthread.
- "-lpthread",
- # Force linking the static libc++abi archive here.
- # This *should* be linked automatically, but not
- # every release of LLVM correctly sets the CMake
- # flags to do so.
- "-l:libc++abi.a",
- ],
- ),
- ]),
- ),
- flag_set(
- actions = all_compile_actions,
- flag_groups = [flag_group(flags = libcpp_debug_flags)],
- with_features = [
- with_feature_set(not_features = ["opt"]),
- ],
- ),
- flag_set(
- actions = all_compile_actions,
- flag_groups = [flag_group(flags = libcpp_release_flags)],
- with_features = [
- with_feature_set(features = ["opt"]),
- ],
- ),
- flag_set(
- actions = [
- ACTION_NAMES.cpp_link_executable,
- ],
- flag_groups = [
- flag_group(
- flags = ["-pie"],
- expand_if_available = "force_pic",
- ),
- ],
- ),
- ],
- )
- macos_flags_feature = feature(
- name = "macos_flags",
- enabled = True,
- flag_sets = [
- flag_set(
- actions = [
- ACTION_NAMES.cpp_link_executable,
- ],
- flag_groups = [
- flag_group(
- flags = ["-fpie"],
- expand_if_available = "force_pic",
- ),
- ],
- ),
- ],
- )
- freebsd_flags_feature = feature(
- name = "freebsd_flags",
- enabled = True,
- flag_sets = [
- flag_set(
- actions = [
- ACTION_NAMES.c_compile,
- ACTION_NAMES.cpp_compile,
- ACTION_NAMES.cpp_header_parsing,
- ACTION_NAMES.cpp_module_compile,
- ],
- flag_groups = [
- flag_group(
- flags = [
- "-DHAVE_MALLCTL",
- ],
- ),
- ],
- ),
- flag_set(
- actions = [
- ACTION_NAMES.cpp_link_executable,
- ],
- flag_groups = [
- flag_group(
- flags = ["-fpie"],
- expand_if_available = "force_pic",
- ),
- ],
- ),
- ],
- )
- default_link_libraries_feature = feature(
- name = "default_link_libraries",
- enabled = True,
- flag_sets = [
- flag_set(
- actions = all_link_actions,
- flag_groups = [
- flag_group(
- flags = ["%{linkstamp_paths}"],
- iterate_over = "linkstamp_paths",
- expand_if_available = "linkstamp_paths",
- ),
- flag_group(
- iterate_over = "libraries_to_link",
- flag_groups = [
- flag_group(
- flags = ["-Wl,--start-lib"],
- expand_if_equal = variable_with_value(
- name = "libraries_to_link.type",
- value = "object_file_group",
- ),
- ),
- flag_group(
- flags = ["-Wl,-whole-archive"],
- expand_if_true = "libraries_to_link.is_whole_archive",
- ),
- flag_group(
- flags = ["%{libraries_to_link.object_files}"],
- iterate_over = "libraries_to_link.object_files",
- expand_if_equal = variable_with_value(
- name = "libraries_to_link.type",
- value = "object_file_group",
- ),
- ),
- flag_group(
- flags = ["%{libraries_to_link.name}"],
- expand_if_equal = variable_with_value(
- name = "libraries_to_link.type",
- value = "object_file",
- ),
- ),
- flag_group(
- flags = ["%{libraries_to_link.name}"],
- expand_if_equal = variable_with_value(
- name = "libraries_to_link.type",
- value = "interface_library",
- ),
- ),
- flag_group(
- flags = ["%{libraries_to_link.name}"],
- expand_if_equal = variable_with_value(
- name = "libraries_to_link.type",
- value = "static_library",
- ),
- ),
- flag_group(
- flags = ["-l%{libraries_to_link.name}"],
- expand_if_equal = variable_with_value(
- name = "libraries_to_link.type",
- value = "dynamic_library",
- ),
- ),
- flag_group(
- flags = ["-l:%{libraries_to_link.name}"],
- expand_if_equal = variable_with_value(
- name = "libraries_to_link.type",
- value = "versioned_dynamic_library",
- ),
- ),
- flag_group(
- flags = ["-Wl,-no-whole-archive"],
- expand_if_true = "libraries_to_link.is_whole_archive",
- ),
- flag_group(
- flags = ["-Wl,--end-lib"],
- expand_if_equal = variable_with_value(
- name = "libraries_to_link.type",
- value = "object_file_group",
- ),
- ),
- ],
- expand_if_available = "libraries_to_link",
- ),
- # Note that the params file comes at the end, after the
- # libraries to link above.
- flag_group(
- expand_if_available = "linker_param_file",
- flags = ["@%{linker_param_file}"],
- ),
- ],
- ),
- ],
- )
- macos_link_libraries_feature = feature(
- name = "macos_link_libraries",
- enabled = True,
- flag_sets = [
- flag_set(
- actions = all_link_actions,
- flag_groups = [
- flag_group(
- flags = ["%{linkstamp_paths}"],
- iterate_over = "linkstamp_paths",
- expand_if_available = "linkstamp_paths",
- ),
- flag_group(
- iterate_over = "libraries_to_link",
- flag_groups = [
- flag_group(
- flags = ["-Wl,--start-lib"],
- expand_if_equal = variable_with_value(
- name = "libraries_to_link.type",
- value = "object_file_group",
- ),
- ),
- flag_group(
- iterate_over = "libraries_to_link.object_files",
- expand_if_equal = variable_with_value(
- name = "libraries_to_link.type",
- value = "object_file_group",
- ),
- flag_groups = [
- flag_group(
- flags = ["%{libraries_to_link.object_files}"],
- expand_if_false = "libraries_to_link.is_whole_archive",
- ),
- flag_group(
- flags = ["-Wl,-force_load,%{libraries_to_link.object_files}"],
- expand_if_true = "libraries_to_link.is_whole_archive",
- ),
- ],
- ),
- flag_group(
- expand_if_equal = variable_with_value(
- name = "libraries_to_link.type",
- value = "object_file",
- ),
- flag_groups = [
- flag_group(
- flags = ["%{libraries_to_link.name}"],
- expand_if_false = "libraries_to_link.is_whole_archive",
- ),
- flag_group(
- flags = ["-Wl,-force_load,%{libraries_to_link.name}"],
- expand_if_true = "libraries_to_link.is_whole_archive",
- ),
- ],
- ),
- flag_group(
- expand_if_equal = variable_with_value(
- name = "libraries_to_link.type",
- value = "interface_library",
- ),
- flag_groups = [
- flag_group(
- flags = ["%{libraries_to_link.name}"],
- expand_if_false = "libraries_to_link.is_whole_archive",
- ),
- flag_group(
- flags = ["-Wl,-force_load,%{libraries_to_link.name}"],
- expand_if_true = "libraries_to_link.is_whole_archive",
- ),
- ],
- ),
- flag_group(
- expand_if_equal = variable_with_value(
- name = "libraries_to_link.type",
- value = "static_library",
- ),
- flag_groups = [
- flag_group(
- flags = ["%{libraries_to_link.name}"],
- expand_if_false = "libraries_to_link.is_whole_archive",
- ),
- flag_group(
- flags = ["-Wl,-force_load,%{libraries_to_link.name}"],
- expand_if_true = "libraries_to_link.is_whole_archive",
- ),
- ],
- ),
- flag_group(
- flags = ["-l%{libraries_to_link.name}"],
- expand_if_equal = variable_with_value(
- name = "libraries_to_link.type",
- value = "dynamic_library",
- ),
- ),
- flag_group(
- flags = ["-l:%{libraries_to_link.name}"],
- expand_if_equal = variable_with_value(
- name = "libraries_to_link.type",
- value = "versioned_dynamic_library",
- ),
- ),
- flag_group(
- expand_if_true = "libraries_to_link.is_whole_archive",
- flag_groups = [
- flag_group(
- expand_if_false = "macos_flags",
- flags = ["-Wl,-no-whole-archive"],
- ),
- ],
- ),
- flag_group(
- flags = ["-Wl,--end-lib"],
- expand_if_equal = variable_with_value(
- name = "libraries_to_link.type",
- value = "object_file_group",
- ),
- ),
- ],
- expand_if_available = "libraries_to_link",
- ),
- # Note that the params file comes at the end, after the
- # libraries to link above.
- flag_group(
- expand_if_available = "linker_param_file",
- flags = ["@%{linker_param_file}"],
- ),
- ],
- ),
- ],
- )
- # Place user provided compile flags after all the features so that these
- # flags can override or customize behavior. The only thing user flags
- # cannot override is the output file as Bazel depends on that.
- #
- # Finally, place the source file (if present) and output file last to make
- # reading the compile command lines easier for humans.
- final_flags_feature = feature(
- name = "final_flags",
- enabled = True,
- flag_sets = [
- flag_set(
- actions = all_compile_actions,
- flag_groups = [
- flag_group(
- flags = ["%{user_compile_flags}"],
- iterate_over = "user_compile_flags",
- expand_if_available = "user_compile_flags",
- ),
- flag_group(
- flags = ["%{source_file}"],
- expand_if_available = "source_file",
- ),
- flag_group(
- expand_if_available = "output_file",
- flags = ["-o", "%{output_file}"],
- ),
- ],
- ),
- flag_set(
- actions = all_link_actions,
- flag_groups = [
- flag_group(
- flags = ["%{user_link_flags}"],
- iterate_over = "user_link_flags",
- expand_if_available = "user_link_flags",
- ),
- flag_group(
- flags = ["-o", "%{output_execpath}"],
- expand_if_available = "output_execpath",
- ),
- ],
- ),
- ],
- )
- # Archive actions have an entirely independent set of flags and don't
- # interact with either compiler or link actions.
- default_archiver_flags_feature = feature(
- name = "default_archiver_flags",
- enabled = True,
- flag_sets = [
- flag_set(
- actions = [ACTION_NAMES.cpp_link_static_library],
- flag_groups = [
- flag_group(flags = ["rcsD"]),
- flag_group(
- flags = ["%{output_execpath}"],
- expand_if_available = "output_execpath",
- ),
- flag_group(
- iterate_over = "libraries_to_link",
- flag_groups = [
- flag_group(
- flags = ["%{libraries_to_link.name}"],
- expand_if_equal = variable_with_value(
- name = "libraries_to_link.type",
- value = "object_file",
- ),
- ),
- flag_group(
- flags = ["%{libraries_to_link.object_files}"],
- iterate_over = "libraries_to_link.object_files",
- expand_if_equal = variable_with_value(
- name = "libraries_to_link.type",
- value = "object_file_group",
- ),
- ),
- ],
- expand_if_available = "libraries_to_link",
- ),
- flag_group(
- expand_if_available = "linker_param_file",
- flags = ["@%{linker_param_file}"],
- ),
- ],
- ),
- ],
- )
- # Now that we have built up the constituent feature definitions, compose
- # them, including configuration based on the target platform.
- # First, define features that are simply used to configure others.
- features = [
- feature(name = "dbg"),
- feature(name = "fastbuild"),
- feature(name = "host"),
- feature(name = "no_legacy_features"),
- feature(name = "opt"),
- feature(name = "supports_dynamic_linker", enabled = ctx.attr.target_os == "linux"),
- feature(name = "supports_pic", enabled = True),
- feature(name = "supports_start_end_lib", enabled = ctx.attr.target_os == "linux"),
- # Enable split debug info whenever debug info is requested.
- feature(
- name = "per_object_debug_info",
- enabled = True,
- # This has to be directly conditioned on requesting debug info at
- # all, otherwise Bazel will look for an extra output file and not
- # find one.
- requires = [feature_set(features = ["debug_info_flags"])],
- ),
- ]
- # The order of the features determines the relative order of flags used.
- # Start off adding the baseline features.
- features += [
- default_flags_feature,
- minimal_optimization_flags,
- default_optimization_flags,
- minimal_debug_info_flags,
- debug_info_flags,
- debug_info_compression_flags,
- debugger_flags,
- lldb_flags,
- gdb_flags,
- enable_in_dbg,
- preserve_call_stacks,
- sysroot_feature,
- sanitizer_common_flags,
- asan,
- asan_min_size,
- enable_in_fastbuild,
- fuzzer,
- layering_check,
- module_maps,
- use_module_maps,
- default_archiver_flags_feature,
- ]
- # Next, add the features based on the target platform. Here too the
- # features are order sensitive. We also setup the sysroot here.
- if ctx.attr.target_os == "linux":
- features.append(sanitizer_static_lib_flags)
- features.append(linux_flags_feature)
- sysroot = None
- elif ctx.attr.target_os == "windows":
- # TODO: Need to figure out if we need to add windows specific features
- # I think the .pdb debug files will need to be handled differently,
- # so that might be an example where a feature must be added.
- sysroot = None
- elif ctx.attr.target_os == "macos":
- features.append(macos_asan_workarounds)
- features.append(macos_flags_feature)
- sysroot = sysroot_dir
- elif ctx.attr.target_os == "freebsd":
- features.append(sanitizer_static_lib_flags)
- features.append(freebsd_flags_feature)
- sysroot = sysroot_dir
- else:
- fail("Unsupported target OS!")
- if ctx.attr.target_cpu in ["aarch64", "arm64"]:
- features.append(aarch64_cpu_flags)
- else:
- features.append(x86_64_cpu_flags)
- # Finally append the libraries to link and any final flags.
- if ctx.attr.target_os == "macos":
- features.append(macos_link_libraries_feature)
- else:
- features.append(default_link_libraries_feature)
- features.append(final_flags_feature)
- identifier = "local-{0}-{1}".format(ctx.attr.target_cpu, ctx.attr.target_os)
- return cc_common.create_cc_toolchain_config_info(
- ctx = ctx,
- features = features,
- action_configs = action_configs,
- cxx_builtin_include_directories = clang_include_dirs_list + [
- # Add Clang's resource directory to the end of the builtin include
- # directories to cover the use of sanitizer resource files by the driver.
- clang_resource_dir + "/share",
- ],
- builtin_sysroot = sysroot,
- # This configuration only supports local non-cross builds so derive
- # everything from the target CPU selected.
- toolchain_identifier = identifier,
- host_system_name = identifier,
- target_system_name = identifier,
- target_cpu = ctx.attr.target_cpu,
- # This is used to expose a "flag" that `config_setting` rules can use to
- # determine if the compiler is Clang.
- compiler = "clang",
- # These attributes aren't meaningful at all so just use placeholder
- # values.
- target_libc = "local",
- abi_version = "local",
- abi_libc_version = "local",
- # We do have to pass in our tool paths.
- tool_paths = tool_paths,
- )
- cc_toolchain_config = rule(
- implementation = _impl,
- attrs = {
- "target_cpu": attr.string(mandatory = True),
- "target_os": attr.string(mandatory = True),
- },
- provides = [CcToolchainConfigInfo],
- )
- def cc_local_toolchain_suite(name, configs):
- """Create a toolchain suite that uses the local Clang/LLVM install.
- Args:
- name: The name of the toolchain suite to produce.
- configs: An array of (os, cpu) pairs to support in the toolchain.
- """
- # An empty filegroup to use when stubbing out the toolchains.
- native.filegroup(
- name = name + "_empty",
- srcs = [],
- )
- # Create the individual local toolchains for each CPU.
- for (os, cpu) in configs:
- config_name = "{0}_{1}_{2}".format(name, os, cpu)
- cc_toolchain_config(
- name = config_name + "_config",
- target_os = os,
- target_cpu = cpu,
- )
- cc_toolchain(
- name = config_name + "_tools",
- all_files = ":" + name + "_empty",
- ar_files = ":" + name + "_empty",
- as_files = ":" + name + "_empty",
- compiler_files = ":" + name + "_empty",
- dwp_files = ":" + name + "_empty",
- linker_files = ":" + name + "_empty",
- objcopy_files = ":" + name + "_empty",
- strip_files = ":" + name + "_empty",
- supports_param_files = 1,
- toolchain_config = ":" + config_name + "_config",
- toolchain_identifier = config_name,
- )
- compatible_with = ["@platforms//cpu:" + cpu, "@platforms//os:" + os]
- native.toolchain(
- name = config_name,
- exec_compatible_with = compatible_with,
- target_compatible_with = compatible_with,
- toolchain = config_name + "_tools",
- toolchain_type = "@bazel_tools//tools/cpp:toolchain_type",
- )
|