clang_cc_toolchain_config.bzl 45 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142
  1. # Part of the Carbon Language project, under the Apache License v2.0 with LLVM
  2. # Exceptions. See /LICENSE for license information.
  3. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. """A Starlark cc_toolchain configuration rule"""
  5. load("@bazel_tools//tools/build_defs/cc:action_names.bzl", "ACTION_NAMES")
  6. load(
  7. "@bazel_tools//tools/cpp:cc_toolchain_config_lib.bzl",
  8. "action_config",
  9. "feature",
  10. "feature_set",
  11. "flag_group",
  12. "flag_set",
  13. "tool",
  14. "tool_path",
  15. "variable_with_value",
  16. "with_feature_set",
  17. )
  18. load("@rules_cc//cc:defs.bzl", "cc_toolchain")
  19. load(
  20. ":clang_detected_variables.bzl",
  21. "clang_bindir",
  22. "clang_include_dirs_list",
  23. "clang_resource_dir",
  24. "clang_version",
  25. "clang_version_for_cache",
  26. "llvm_bindir",
  27. "sysroot_dir",
  28. )
  29. all_c_compile_actions = [
  30. ACTION_NAMES.c_compile,
  31. ACTION_NAMES.assemble,
  32. ACTION_NAMES.preprocess_assemble,
  33. ]
  34. all_cpp_compile_actions = [
  35. ACTION_NAMES.cpp_compile,
  36. ACTION_NAMES.linkstamp_compile,
  37. ACTION_NAMES.cpp_header_parsing,
  38. ACTION_NAMES.cpp_module_compile,
  39. ACTION_NAMES.cpp_module_codegen,
  40. ]
  41. all_compile_actions = all_c_compile_actions + all_cpp_compile_actions
  42. preprocessor_compile_actions = [
  43. ACTION_NAMES.c_compile,
  44. ACTION_NAMES.cpp_compile,
  45. ACTION_NAMES.linkstamp_compile,
  46. ACTION_NAMES.preprocess_assemble,
  47. ACTION_NAMES.cpp_header_parsing,
  48. ACTION_NAMES.cpp_module_compile,
  49. ]
  50. codegen_compile_actions = [
  51. ACTION_NAMES.c_compile,
  52. ACTION_NAMES.cpp_compile,
  53. ACTION_NAMES.linkstamp_compile,
  54. ACTION_NAMES.assemble,
  55. ACTION_NAMES.preprocess_assemble,
  56. ACTION_NAMES.cpp_module_codegen,
  57. ]
  58. all_link_actions = [
  59. ACTION_NAMES.cpp_link_executable,
  60. ACTION_NAMES.cpp_link_dynamic_library,
  61. ACTION_NAMES.cpp_link_nodeps_dynamic_library,
  62. ]
  63. def _impl(ctx):
  64. tool_paths = [
  65. tool_path(name = "ar", path = llvm_bindir + "/llvm-ar"),
  66. tool_path(name = "ld", path = clang_bindir + "/ld.lld"),
  67. tool_path(name = "cpp", path = clang_bindir + "/clang-cpp"),
  68. tool_path(name = "gcc", path = clang_bindir + "/clang++"),
  69. tool_path(name = "dwp", path = llvm_bindir + "/llvm-dwp"),
  70. tool_path(name = "gcov", path = llvm_bindir + "/llvm-cov"),
  71. tool_path(name = "nm", path = llvm_bindir + "/llvm-nm"),
  72. tool_path(name = "objcopy", path = llvm_bindir + "/llvm-objcopy"),
  73. tool_path(name = "objdump", path = llvm_bindir + "/llvm-objdump"),
  74. tool_path(name = "strip", path = llvm_bindir + "/llvm-strip"),
  75. ]
  76. action_configs = [
  77. action_config(action_name = name, enabled = True, tools = [tool(path = clang_bindir + "/clang")])
  78. for name in all_c_compile_actions
  79. ] + [
  80. action_config(action_name = name, enabled = True, tools = [tool(path = clang_bindir + "/clang++")])
  81. for name in all_cpp_compile_actions
  82. ] + [
  83. action_config(action_name = name, enabled = True, tools = [tool(path = clang_bindir + "/clang++")])
  84. for name in all_link_actions
  85. ] + [
  86. action_config(action_name = name, enabled = True, tools = [tool(path = llvm_bindir + "/llvm-ar")])
  87. for name in [ACTION_NAMES.cpp_link_static_library]
  88. ] + [
  89. action_config(action_name = name, enabled = True, tools = [tool(path = llvm_bindir + "/llvm-strip")])
  90. for name in [ACTION_NAMES.strip]
  91. ]
  92. std_compile_flags = ["-std=c++20"]
  93. # libc++ is only used on non-Windows platforms.
  94. if ctx.attr.target_os != "windows":
  95. std_compile_flags.append("-stdlib=libc++")
  96. # TODO: Regression that warns on anonymous unions; remove depending on fix.
  97. # Sets the flag for unknown clang versions, which are assumed to be at head.
  98. # https://github.com/llvm/llvm-project/issues/70384
  99. if not clang_version or clang_version == 18:
  100. missing_field_init_flags = ["-Wno-missing-field-initializers"]
  101. else:
  102. missing_field_init_flags = []
  103. default_flags_feature = feature(
  104. name = "default_flags",
  105. enabled = True,
  106. flag_sets = [
  107. flag_set(
  108. actions = all_compile_actions + all_link_actions,
  109. flag_groups = ([
  110. flag_group(
  111. flags = [
  112. "-no-canonical-prefixes",
  113. "-fcolor-diagnostics",
  114. ],
  115. ),
  116. ]),
  117. ),
  118. flag_set(
  119. actions = all_compile_actions,
  120. flag_groups = ([
  121. flag_group(
  122. flags = [
  123. "-Werror",
  124. "-Wall",
  125. "-Wextra",
  126. "-Wthread-safety",
  127. "-Wself-assign",
  128. "-Wimplicit-fallthrough",
  129. "-Wctad-maybe-unsupported",
  130. "-Wextra-semi",
  131. "-Wmissing-prototypes",
  132. "-Wzero-as-null-pointer-constant",
  133. # Don't warn on external code as we can't
  134. # necessarily patch it easily. Note that these have
  135. # to be initial directories in the `#include` line.
  136. "--system-header-prefix=absl/",
  137. "--system-header-prefix=benchmark/",
  138. "--system-header-prefix=boost/",
  139. "--system-header-prefix=clang-tools-extra/",
  140. "--system-header-prefix=clang/",
  141. "--system-header-prefix=gmock/",
  142. "--system-header-prefix=google/protobuf/",
  143. "--system-header-prefix=gtest/",
  144. "--system-header-prefix=libfuzzer/",
  145. "--system-header-prefix=llvm/",
  146. "--system-header-prefix=re2/",
  147. "--system-header-prefix=tools/cpp/",
  148. "--system-header-prefix=tree_sitter/",
  149. # Compile actions shouldn't link anything.
  150. "-c",
  151. ] + missing_field_init_flags,
  152. ),
  153. flag_group(
  154. expand_if_available = "output_assembly_file",
  155. flags = ["-S"],
  156. ),
  157. flag_group(
  158. expand_if_available = "output_preprocess_file",
  159. flags = ["-E"],
  160. ),
  161. flag_group(
  162. flags = ["-MD", "-MF", "%{dependency_file}"],
  163. expand_if_available = "dependency_file",
  164. ),
  165. flag_group(
  166. flags = ["-frandom-seed=%{output_file}"],
  167. expand_if_available = "output_file",
  168. ),
  169. ]),
  170. ),
  171. flag_set(
  172. actions = all_cpp_compile_actions + all_link_actions,
  173. flag_groups = ([
  174. flag_group(
  175. flags = std_compile_flags,
  176. ),
  177. ]),
  178. ),
  179. flag_set(
  180. actions = codegen_compile_actions,
  181. flag_groups = ([
  182. flag_group(
  183. flags = [
  184. "-ffunction-sections",
  185. "-fdata-sections",
  186. ],
  187. ),
  188. ]),
  189. ),
  190. flag_set(
  191. actions = codegen_compile_actions,
  192. flag_groups = [
  193. flag_group(flags = ["-fPIC"], expand_if_available = "pic"),
  194. ],
  195. ),
  196. flag_set(
  197. actions = preprocessor_compile_actions,
  198. flag_groups = [
  199. flag_group(
  200. flags = [
  201. # Disable a warning and override builtin macros to
  202. # ensure a hermetic build.
  203. "-Wno-builtin-macro-redefined",
  204. "-D__DATE__=\"redacted\"",
  205. "-D__TIMESTAMP__=\"redacted\"",
  206. "-D__TIME__=\"redacted\"",
  207. # Pass the clang version as a define so that bazel
  208. # caching is more likely to notice version changes.
  209. "-DCLANG_VERSION_FOR_CACHE=\"%s\"" % clang_version_for_cache,
  210. ],
  211. ),
  212. flag_group(
  213. flags = ["-D%{preprocessor_defines}"],
  214. iterate_over = "preprocessor_defines",
  215. ),
  216. flag_group(
  217. flags = ["-include", "%{includes}"],
  218. iterate_over = "includes",
  219. expand_if_available = "includes",
  220. ),
  221. flag_group(
  222. flags = ["-iquote", "%{quote_include_paths}"],
  223. iterate_over = "quote_include_paths",
  224. ),
  225. flag_group(
  226. flags = ["-I%{include_paths}"],
  227. iterate_over = "include_paths",
  228. ),
  229. flag_group(
  230. flags = ["-isystem", "%{system_include_paths}"],
  231. iterate_over = "system_include_paths",
  232. ),
  233. ],
  234. ),
  235. flag_set(
  236. actions = [
  237. ACTION_NAMES.cpp_link_dynamic_library,
  238. ACTION_NAMES.cpp_link_nodeps_dynamic_library,
  239. ],
  240. flag_groups = [flag_group(flags = ["-shared"])],
  241. ),
  242. flag_set(
  243. actions = all_link_actions,
  244. flag_groups = [
  245. flag_group(
  246. flags = ["-Wl,--gdb-index"],
  247. expand_if_available = "is_using_fission",
  248. ),
  249. flag_group(
  250. flags = ["-Wl,-S"],
  251. expand_if_available = "strip_debug_symbols",
  252. ),
  253. flag_group(
  254. flags = ["-L%{library_search_directories}"],
  255. iterate_over = "library_search_directories",
  256. expand_if_available = "library_search_directories",
  257. ),
  258. flag_group(
  259. iterate_over = "runtime_library_search_directories",
  260. flags = [
  261. "-Wl,-rpath,$ORIGIN/%{runtime_library_search_directories}",
  262. ],
  263. expand_if_available =
  264. "runtime_library_search_directories",
  265. ),
  266. ],
  267. ),
  268. ],
  269. )
  270. # Handle different levels of optimization with individual features so that
  271. # they can be ordered and the defaults can override the minimal settings if
  272. # both are enabled.
  273. minimal_optimization_flags = feature(
  274. name = "minimal_optimization_flags",
  275. flag_sets = [
  276. flag_set(
  277. actions = codegen_compile_actions,
  278. flag_groups = [flag_group(flags = [
  279. "-O1",
  280. ])],
  281. ),
  282. ],
  283. )
  284. default_optimization_flags = feature(
  285. name = "default_optimization_flags",
  286. enabled = True,
  287. requires = [feature_set(["opt"])],
  288. flag_sets = [
  289. flag_set(
  290. actions = all_compile_actions,
  291. flag_groups = [flag_group(flags = [
  292. "-DNDEBUG",
  293. ])],
  294. ),
  295. flag_set(
  296. actions = codegen_compile_actions,
  297. flag_groups = [flag_group(flags = [
  298. "-O3",
  299. ])],
  300. ),
  301. ],
  302. )
  303. x86_64_cpu_flags = feature(
  304. name = "x86_64_cpu_flags",
  305. enabled = True,
  306. flag_sets = [
  307. flag_set(
  308. actions = all_compile_actions,
  309. flag_groups = [flag_group(flags = [
  310. "-march=x86-64-v2",
  311. ])],
  312. ),
  313. ],
  314. )
  315. aarch64_cpu_flags = feature(
  316. name = "aarch64_cpu_flags",
  317. enabled = True,
  318. flag_sets = [
  319. flag_set(
  320. actions = all_compile_actions,
  321. flag_groups = [flag_group(flags = [
  322. "-march=armv8.2-a",
  323. ])],
  324. ),
  325. ],
  326. )
  327. # Handle different levels and forms of debug info emission with individual
  328. # features so that they can be ordered and the defaults can override the
  329. # minimal settings if both are enabled.
  330. minimal_debug_info_flags = feature(
  331. name = "minimal_debug_info_flags",
  332. flag_sets = [
  333. flag_set(
  334. actions = codegen_compile_actions,
  335. flag_groups = [
  336. flag_group(
  337. flags = ["-gmlt"],
  338. ),
  339. ],
  340. ),
  341. ],
  342. )
  343. default_debug_info_flags = feature(
  344. name = "default_debug_info_flags",
  345. enabled = True,
  346. flag_sets = [
  347. flag_set(
  348. actions = codegen_compile_actions,
  349. flag_groups = ([
  350. flag_group(
  351. flags = ["-g"],
  352. ),
  353. ]),
  354. with_features = [with_feature_set(features = ["dbg"])],
  355. ),
  356. flag_set(
  357. actions = codegen_compile_actions,
  358. flag_groups = [
  359. flag_group(
  360. flags = ["-gsplit-dwarf", "-g"],
  361. expand_if_available = "per_object_debug_info_file",
  362. ),
  363. ],
  364. ),
  365. ],
  366. )
  367. # This feature can be enabled in conjunction with any optimizations to
  368. # ensure accurate call stacks and backtraces for profilers or errors.
  369. preserve_call_stacks = feature(
  370. name = "preserve_call_stacks",
  371. flag_sets = [flag_set(
  372. actions = codegen_compile_actions,
  373. flag_groups = [flag_group(flags = [
  374. # Ensure good backtraces by preserving frame pointers and
  375. # disabling tail call elimination.
  376. "-fno-omit-frame-pointer",
  377. "-mno-omit-leaf-frame-pointer",
  378. "-fno-optimize-sibling-calls",
  379. ])],
  380. )],
  381. )
  382. sysroot_feature = feature(
  383. name = "sysroot",
  384. enabled = True,
  385. flag_sets = [
  386. flag_set(
  387. actions = all_compile_actions + all_link_actions,
  388. flag_groups = [
  389. flag_group(
  390. flags = ["--sysroot=%{sysroot}"],
  391. expand_if_available = "sysroot",
  392. ),
  393. ],
  394. ),
  395. ],
  396. )
  397. use_module_maps = feature(
  398. name = "use_module_maps",
  399. requires = [feature_set(features = ["module_maps"])],
  400. flag_sets = [
  401. flag_set(
  402. actions = [
  403. ACTION_NAMES.c_compile,
  404. ACTION_NAMES.cpp_compile,
  405. ACTION_NAMES.cpp_header_parsing,
  406. ACTION_NAMES.cpp_module_compile,
  407. ],
  408. flag_groups = [
  409. # These flag groups are separate so they do not expand to
  410. # the cross product of the variables.
  411. flag_group(flags = ["-fmodule-name=%{module_name}"]),
  412. flag_group(
  413. flags = ["-fmodule-map-file=%{module_map_file}"],
  414. ),
  415. ],
  416. ),
  417. ],
  418. )
  419. # Tell bazel we support module maps in general, so they will be generated
  420. # for all c/c++ rules.
  421. # Note: not all C++ rules support module maps; thus, do not imply this
  422. # feature from other features - instead, require it.
  423. module_maps = feature(
  424. name = "module_maps",
  425. enabled = True,
  426. implies = [
  427. # "module_map_home_cwd",
  428. # "module_map_without_extern_module",
  429. # "generate_submodules",
  430. ],
  431. )
  432. layering_check = feature(
  433. name = "layering_check",
  434. implies = ["use_module_maps"],
  435. flag_sets = [
  436. flag_set(
  437. actions = [
  438. ACTION_NAMES.c_compile,
  439. ACTION_NAMES.cpp_compile,
  440. ACTION_NAMES.cpp_header_parsing,
  441. ACTION_NAMES.cpp_module_compile,
  442. ],
  443. flag_groups = [
  444. flag_group(flags = [
  445. "-fmodules-strict-decluse",
  446. "-Wprivate-header",
  447. ]),
  448. flag_group(
  449. iterate_over = "dependent_module_map_files",
  450. flags = [
  451. "-fmodule-map-file=%{dependent_module_map_files}",
  452. ],
  453. ),
  454. ],
  455. ),
  456. ],
  457. )
  458. sanitizer_common_flags = feature(
  459. name = "sanitizer_common_flags",
  460. requires = [feature_set(["nonhost"])],
  461. implies = ["minimal_optimization_flags", "minimal_debug_info_flags", "preserve_call_stacks"],
  462. )
  463. # Separated from the feature above so it can only be included on platforms
  464. # where it is supported. There is no negative flag in Clang so we can't just
  465. # override it later.
  466. sanitizer_static_lib_flags = feature(
  467. name = "sanitizer_static_lib_flags",
  468. enabled = True,
  469. requires = [feature_set(["sanitizer_common_flags"])],
  470. flag_sets = [flag_set(
  471. actions = all_link_actions,
  472. flag_groups = [flag_group(flags = [
  473. "-static-libsan",
  474. ])],
  475. )],
  476. )
  477. asan = feature(
  478. name = "asan",
  479. requires = [feature_set(["nonhost"])],
  480. implies = ["sanitizer_common_flags"],
  481. flag_sets = [flag_set(
  482. actions = all_compile_actions + all_link_actions,
  483. flag_groups = [flag_group(flags = [
  484. "-fsanitize=address,undefined,nullability",
  485. "-fsanitize-address-use-after-scope",
  486. # We don't need the recovery behavior of UBSan as we expect
  487. # builds to be clean. Not recovering is a bit cheaper.
  488. "-fno-sanitize-recover=undefined",
  489. # Don't embed the full path name for files. This limits the size
  490. # and combined with line numbers is unlikely to result in many
  491. # ambiguities.
  492. "-fsanitize-undefined-strip-path-components=-1",
  493. # Needed due to clang AST issues, such as in
  494. # clang/AST/Redeclarable.h line 199.
  495. "-fno-sanitize=vptr",
  496. ])],
  497. )],
  498. )
  499. # Likely due to being unable to use the static-linked and up-to-date
  500. # sanitizer runtimes, we have to disable a number of sanitizers on macOS.
  501. macos_asan_workarounds = feature(
  502. name = "macos_sanitizer_workarounds",
  503. enabled = True,
  504. requires = [feature_set(["asan"])],
  505. flag_sets = [flag_set(
  506. actions = all_compile_actions + all_link_actions,
  507. flag_groups = [flag_group(flags = [
  508. "-fno-sanitize=function",
  509. ])],
  510. )],
  511. )
  512. enable_asan_in_fastbuild = feature(
  513. name = "enable_asan_in_fastbuild",
  514. enabled = True,
  515. requires = [feature_set(["nonhost", "fastbuild"])],
  516. implies = ["asan"],
  517. )
  518. fuzzer = feature(
  519. name = "fuzzer",
  520. requires = [feature_set(["nonhost"])],
  521. implies = ["asan"],
  522. flag_sets = [flag_set(
  523. actions = all_compile_actions + all_link_actions,
  524. flag_groups = [flag_group(flags = [
  525. "-fsanitize=fuzzer-no-link",
  526. ])],
  527. )],
  528. )
  529. if clang_version and clang_version <= 16:
  530. libcpp_debug_flags = ["-D_LIBCPP_ENABLE_ASSERTIONS=1"]
  531. else:
  532. # Clang 17 deprecates LIBCPP_ENABLE_ASSERTIONS in favor of
  533. # HARDENED_MODE.
  534. libcpp_debug_flags = ["-D_LIBCPP_ENABLE_HARDENED_MODE=1"]
  535. linux_flags_feature = feature(
  536. name = "linux_flags",
  537. enabled = True,
  538. flag_sets = [
  539. flag_set(
  540. actions = all_link_actions,
  541. flag_groups = ([
  542. flag_group(
  543. flags = [
  544. "-fuse-ld=lld",
  545. "-stdlib=libc++",
  546. "-unwindlib=libunwind",
  547. # Force the C++ standard library and runtime
  548. # libraries to be statically linked. This works even
  549. # with libc++ and libunwind despite the names,
  550. # provided libc++ is built with the CMake option:
  551. # - `-DCMAKE_POSITION_INDEPENDENT_CODE=ON`
  552. "-static-libstdc++",
  553. "-static-libgcc",
  554. # Link with Clang's runtime library. This is always
  555. # linked statically.
  556. "-rtlib=compiler-rt",
  557. # Explicitly add LLVM libs to the search path to
  558. # preempt the detected GCC installation's library
  559. # paths. Those might have a system installed libc++
  560. # and we want to find the one next to our Clang.
  561. "-L" + llvm_bindir + "/../lib",
  562. # Link with pthread.
  563. "-lpthread",
  564. # Force linking the static libc++abi archive here.
  565. # This *should* be linked automatically, but not
  566. # every release of LLVM correctly sets the CMake
  567. # flags to do so.
  568. "-l:libc++abi.a",
  569. ],
  570. ),
  571. ]),
  572. ),
  573. flag_set(
  574. actions = all_compile_actions,
  575. flag_groups = [flag_group(flags = libcpp_debug_flags)],
  576. with_features = [
  577. with_feature_set(not_features = ["opt"]),
  578. ],
  579. ),
  580. flag_set(
  581. actions = [
  582. ACTION_NAMES.cpp_link_executable,
  583. ],
  584. flag_groups = [
  585. flag_group(
  586. flags = ["-pie"],
  587. expand_if_available = "force_pic",
  588. ),
  589. ],
  590. ),
  591. ],
  592. )
  593. macos_flags_feature = feature(
  594. name = "macos_flags",
  595. enabled = True,
  596. flag_sets = [
  597. flag_set(
  598. actions = [
  599. ACTION_NAMES.cpp_link_executable,
  600. ],
  601. flag_groups = [
  602. flag_group(
  603. flags = ["-fpie"],
  604. expand_if_available = "force_pic",
  605. ),
  606. ],
  607. ),
  608. ],
  609. )
  610. freebsd_flags_feature = feature(
  611. name = "freebsd_flags",
  612. enabled = True,
  613. flag_sets = [
  614. flag_set(
  615. actions = [
  616. ACTION_NAMES.c_compile,
  617. ACTION_NAMES.cpp_compile,
  618. ACTION_NAMES.cpp_header_parsing,
  619. ACTION_NAMES.cpp_module_compile,
  620. ],
  621. flag_groups = [
  622. flag_group(
  623. flags = [
  624. "-DHAVE_MALLCTL",
  625. ],
  626. ),
  627. ],
  628. ),
  629. flag_set(
  630. actions = [
  631. ACTION_NAMES.cpp_link_executable,
  632. ],
  633. flag_groups = [
  634. flag_group(
  635. flags = ["-fpie"],
  636. expand_if_available = "force_pic",
  637. ),
  638. ],
  639. ),
  640. ],
  641. )
  642. default_link_libraries_feature = feature(
  643. name = "default_link_libraries",
  644. enabled = True,
  645. flag_sets = [
  646. flag_set(
  647. actions = all_link_actions,
  648. flag_groups = [
  649. flag_group(
  650. flags = ["%{linkstamp_paths}"],
  651. iterate_over = "linkstamp_paths",
  652. expand_if_available = "linkstamp_paths",
  653. ),
  654. flag_group(
  655. iterate_over = "libraries_to_link",
  656. flag_groups = [
  657. flag_group(
  658. flags = ["-Wl,--start-lib"],
  659. expand_if_equal = variable_with_value(
  660. name = "libraries_to_link.type",
  661. value = "object_file_group",
  662. ),
  663. ),
  664. flag_group(
  665. flags = ["-Wl,-whole-archive"],
  666. expand_if_true = "libraries_to_link.is_whole_archive",
  667. ),
  668. flag_group(
  669. flags = ["%{libraries_to_link.object_files}"],
  670. iterate_over = "libraries_to_link.object_files",
  671. expand_if_equal = variable_with_value(
  672. name = "libraries_to_link.type",
  673. value = "object_file_group",
  674. ),
  675. ),
  676. flag_group(
  677. flags = ["%{libraries_to_link.name}"],
  678. expand_if_equal = variable_with_value(
  679. name = "libraries_to_link.type",
  680. value = "object_file",
  681. ),
  682. ),
  683. flag_group(
  684. flags = ["%{libraries_to_link.name}"],
  685. expand_if_equal = variable_with_value(
  686. name = "libraries_to_link.type",
  687. value = "interface_library",
  688. ),
  689. ),
  690. flag_group(
  691. flags = ["%{libraries_to_link.name}"],
  692. expand_if_equal = variable_with_value(
  693. name = "libraries_to_link.type",
  694. value = "static_library",
  695. ),
  696. ),
  697. flag_group(
  698. flags = ["-l%{libraries_to_link.name}"],
  699. expand_if_equal = variable_with_value(
  700. name = "libraries_to_link.type",
  701. value = "dynamic_library",
  702. ),
  703. ),
  704. flag_group(
  705. flags = ["-l:%{libraries_to_link.name}"],
  706. expand_if_equal = variable_with_value(
  707. name = "libraries_to_link.type",
  708. value = "versioned_dynamic_library",
  709. ),
  710. ),
  711. flag_group(
  712. flags = ["-Wl,-no-whole-archive"],
  713. expand_if_true = "libraries_to_link.is_whole_archive",
  714. ),
  715. flag_group(
  716. flags = ["-Wl,--end-lib"],
  717. expand_if_equal = variable_with_value(
  718. name = "libraries_to_link.type",
  719. value = "object_file_group",
  720. ),
  721. ),
  722. ],
  723. expand_if_available = "libraries_to_link",
  724. ),
  725. # Note that the params file comes at the end, after the
  726. # libraries to link above.
  727. flag_group(
  728. expand_if_available = "linker_param_file",
  729. flags = ["@%{linker_param_file}"],
  730. ),
  731. ],
  732. ),
  733. ],
  734. )
  735. macos_link_libraries_feature = feature(
  736. name = "macos_link_libraries",
  737. enabled = True,
  738. flag_sets = [
  739. flag_set(
  740. actions = all_link_actions,
  741. flag_groups = [
  742. flag_group(
  743. flags = ["%{linkstamp_paths}"],
  744. iterate_over = "linkstamp_paths",
  745. expand_if_available = "linkstamp_paths",
  746. ),
  747. flag_group(
  748. iterate_over = "libraries_to_link",
  749. flag_groups = [
  750. flag_group(
  751. flags = ["-Wl,--start-lib"],
  752. expand_if_equal = variable_with_value(
  753. name = "libraries_to_link.type",
  754. value = "object_file_group",
  755. ),
  756. ),
  757. flag_group(
  758. iterate_over = "libraries_to_link.object_files",
  759. expand_if_equal = variable_with_value(
  760. name = "libraries_to_link.type",
  761. value = "object_file_group",
  762. ),
  763. flag_groups = [
  764. flag_group(
  765. flags = ["%{libraries_to_link.object_files}"],
  766. expand_if_false = "libraries_to_link.is_whole_archive",
  767. ),
  768. flag_group(
  769. flags = ["-Wl,-force_load,%{libraries_to_link.object_files}"],
  770. expand_if_true = "libraries_to_link.is_whole_archive",
  771. ),
  772. ],
  773. ),
  774. flag_group(
  775. expand_if_equal = variable_with_value(
  776. name = "libraries_to_link.type",
  777. value = "object_file",
  778. ),
  779. flag_groups = [
  780. flag_group(
  781. flags = ["%{libraries_to_link.name}"],
  782. expand_if_false = "libraries_to_link.is_whole_archive",
  783. ),
  784. flag_group(
  785. flags = ["-Wl,-force_load,%{libraries_to_link.name}"],
  786. expand_if_true = "libraries_to_link.is_whole_archive",
  787. ),
  788. ],
  789. ),
  790. flag_group(
  791. expand_if_equal = variable_with_value(
  792. name = "libraries_to_link.type",
  793. value = "interface_library",
  794. ),
  795. flag_groups = [
  796. flag_group(
  797. flags = ["%{libraries_to_link.name}"],
  798. expand_if_false = "libraries_to_link.is_whole_archive",
  799. ),
  800. flag_group(
  801. flags = ["-Wl,-force_load,%{libraries_to_link.name}"],
  802. expand_if_true = "libraries_to_link.is_whole_archive",
  803. ),
  804. ],
  805. ),
  806. flag_group(
  807. expand_if_equal = variable_with_value(
  808. name = "libraries_to_link.type",
  809. value = "static_library",
  810. ),
  811. flag_groups = [
  812. flag_group(
  813. flags = ["%{libraries_to_link.name}"],
  814. expand_if_false = "libraries_to_link.is_whole_archive",
  815. ),
  816. flag_group(
  817. flags = ["-Wl,-force_load,%{libraries_to_link.name}"],
  818. expand_if_true = "libraries_to_link.is_whole_archive",
  819. ),
  820. ],
  821. ),
  822. flag_group(
  823. flags = ["-l%{libraries_to_link.name}"],
  824. expand_if_equal = variable_with_value(
  825. name = "libraries_to_link.type",
  826. value = "dynamic_library",
  827. ),
  828. ),
  829. flag_group(
  830. flags = ["-l:%{libraries_to_link.name}"],
  831. expand_if_equal = variable_with_value(
  832. name = "libraries_to_link.type",
  833. value = "versioned_dynamic_library",
  834. ),
  835. ),
  836. flag_group(
  837. expand_if_true = "libraries_to_link.is_whole_archive",
  838. flag_groups = [
  839. flag_group(
  840. expand_if_false = "macos_flags",
  841. flags = ["-Wl,-no-whole-archive"],
  842. ),
  843. ],
  844. ),
  845. flag_group(
  846. flags = ["-Wl,--end-lib"],
  847. expand_if_equal = variable_with_value(
  848. name = "libraries_to_link.type",
  849. value = "object_file_group",
  850. ),
  851. ),
  852. ],
  853. expand_if_available = "libraries_to_link",
  854. ),
  855. # Note that the params file comes at the end, after the
  856. # libraries to link above.
  857. flag_group(
  858. expand_if_available = "linker_param_file",
  859. flags = ["@%{linker_param_file}"],
  860. ),
  861. ],
  862. ),
  863. ],
  864. )
  865. # Place user provided compile flags after all the features so that these
  866. # flags can override or customize behavior. The only thing user flags
  867. # cannot override is the output file as Bazel depends on that.
  868. #
  869. # Finally, place the source file (if present) and output file last to make
  870. # reading the compile command lines easier for humans.
  871. final_flags_feature = feature(
  872. name = "final_flags",
  873. enabled = True,
  874. flag_sets = [
  875. flag_set(
  876. actions = all_compile_actions,
  877. flag_groups = [
  878. flag_group(
  879. flags = ["%{user_compile_flags}"],
  880. iterate_over = "user_compile_flags",
  881. expand_if_available = "user_compile_flags",
  882. ),
  883. flag_group(
  884. flags = ["%{source_file}"],
  885. expand_if_available = "source_file",
  886. ),
  887. flag_group(
  888. expand_if_available = "output_file",
  889. flags = ["-o", "%{output_file}"],
  890. ),
  891. ],
  892. ),
  893. flag_set(
  894. actions = all_link_actions,
  895. flag_groups = [
  896. flag_group(
  897. flags = ["%{user_link_flags}"],
  898. iterate_over = "user_link_flags",
  899. expand_if_available = "user_link_flags",
  900. ),
  901. flag_group(
  902. flags = ["-o", "%{output_execpath}"],
  903. expand_if_available = "output_execpath",
  904. ),
  905. ],
  906. ),
  907. ],
  908. )
  909. # Archive actions have an entirely independent set of flags and don't
  910. # interact with either compiler or link actions.
  911. default_archiver_flags_feature = feature(
  912. name = "default_archiver_flags",
  913. enabled = True,
  914. flag_sets = [
  915. flag_set(
  916. actions = [ACTION_NAMES.cpp_link_static_library],
  917. flag_groups = [
  918. flag_group(flags = ["rcsD"]),
  919. flag_group(
  920. flags = ["%{output_execpath}"],
  921. expand_if_available = "output_execpath",
  922. ),
  923. flag_group(
  924. iterate_over = "libraries_to_link",
  925. flag_groups = [
  926. flag_group(
  927. flags = ["%{libraries_to_link.name}"],
  928. expand_if_equal = variable_with_value(
  929. name = "libraries_to_link.type",
  930. value = "object_file",
  931. ),
  932. ),
  933. flag_group(
  934. flags = ["%{libraries_to_link.object_files}"],
  935. iterate_over = "libraries_to_link.object_files",
  936. expand_if_equal = variable_with_value(
  937. name = "libraries_to_link.type",
  938. value = "object_file_group",
  939. ),
  940. ),
  941. ],
  942. expand_if_available = "libraries_to_link",
  943. ),
  944. flag_group(
  945. expand_if_available = "linker_param_file",
  946. flags = ["@%{linker_param_file}"],
  947. ),
  948. ],
  949. ),
  950. ],
  951. )
  952. # Now that we have built up the constituent feature definitions, compose
  953. # them, including configuration based on the target platform.
  954. # First, define features that are simply used to configure others.
  955. features = [
  956. feature(name = "dbg"),
  957. feature(name = "fastbuild"),
  958. feature(name = "host"),
  959. feature(name = "no_legacy_features"),
  960. feature(name = "nonhost"),
  961. feature(name = "opt"),
  962. feature(name = "supports_dynamic_linker", enabled = ctx.attr.target_os == "linux"),
  963. feature(name = "supports_pic", enabled = True),
  964. feature(name = "supports_start_end_lib", enabled = ctx.attr.target_os == "linux"),
  965. ]
  966. # The order of the features determines the relative order of flags used.
  967. # Start off adding the baseline features.
  968. features += [
  969. default_flags_feature,
  970. minimal_optimization_flags,
  971. default_optimization_flags,
  972. minimal_debug_info_flags,
  973. default_debug_info_flags,
  974. preserve_call_stacks,
  975. sysroot_feature,
  976. sanitizer_common_flags,
  977. asan,
  978. enable_asan_in_fastbuild,
  979. fuzzer,
  980. layering_check,
  981. module_maps,
  982. use_module_maps,
  983. default_archiver_flags_feature,
  984. ]
  985. # Next, add the features based on the target platform. Here too the
  986. # features are order sensitive. We also setup the sysroot here.
  987. if ctx.attr.target_os == "linux":
  988. features.append(sanitizer_static_lib_flags)
  989. features.append(linux_flags_feature)
  990. sysroot = None
  991. elif ctx.attr.target_os == "windows":
  992. # TODO: Need to figure out if we need to add windows specific features
  993. # I think the .pdb debug files will need to be handled differently,
  994. # so that might be an example where a feature must be added.
  995. sysroot = None
  996. elif ctx.attr.target_os == "macos":
  997. features.append(macos_asan_workarounds)
  998. features.append(macos_flags_feature)
  999. sysroot = sysroot_dir
  1000. elif ctx.attr.target_os == "freebsd":
  1001. features.append(sanitizer_static_lib_flags)
  1002. features.append(freebsd_flags_feature)
  1003. sysroot = sysroot_dir
  1004. else:
  1005. fail("Unsupported target OS!")
  1006. if ctx.attr.target_cpu in ["aarch64", "arm64"]:
  1007. features.append(aarch64_cpu_flags)
  1008. else:
  1009. features.append(x86_64_cpu_flags)
  1010. # Finally append the libraries to link and any final flags.
  1011. if ctx.attr.target_os == "macos":
  1012. features.append(macos_link_libraries_feature)
  1013. else:
  1014. features.append(default_link_libraries_feature)
  1015. features.append(final_flags_feature)
  1016. identifier = "local-{0}-{1}".format(ctx.attr.target_cpu, ctx.attr.target_os)
  1017. return cc_common.create_cc_toolchain_config_info(
  1018. ctx = ctx,
  1019. features = features,
  1020. action_configs = action_configs,
  1021. cxx_builtin_include_directories = clang_include_dirs_list + [
  1022. # Add Clang's resource directory to the end of the builtin include
  1023. # directories to cover the use of sanitizer resource files by the driver.
  1024. clang_resource_dir + "/share",
  1025. ],
  1026. builtin_sysroot = sysroot,
  1027. # This configuration only supports local non-cross builds so derive
  1028. # everything from the target CPU selected.
  1029. toolchain_identifier = identifier,
  1030. host_system_name = identifier,
  1031. target_system_name = identifier,
  1032. target_cpu = ctx.attr.target_cpu,
  1033. # These attributes aren't meaningful at all so just use placeholder
  1034. # values.
  1035. target_libc = "local",
  1036. compiler = "local",
  1037. abi_version = "local",
  1038. abi_libc_version = "local",
  1039. # We do have to pass in our tool paths.
  1040. tool_paths = tool_paths,
  1041. )
  1042. cc_toolchain_config = rule(
  1043. implementation = _impl,
  1044. attrs = {
  1045. "target_cpu": attr.string(mandatory = True),
  1046. "target_os": attr.string(mandatory = True),
  1047. },
  1048. provides = [CcToolchainConfigInfo],
  1049. )
  1050. def cc_local_toolchain_suite(name, configs):
  1051. """Create a toolchain suite that uses the local Clang/LLVM install.
  1052. Args:
  1053. name: The name of the toolchain suite to produce.
  1054. configs: An array of (os, cpu) pairs to support in the toolchain.
  1055. """
  1056. # An empty filegroup to use when stubbing out the toolchains.
  1057. native.filegroup(
  1058. name = name + "_empty",
  1059. srcs = [],
  1060. )
  1061. # Create the individual local toolchains for each CPU.
  1062. for (os, cpu) in configs:
  1063. config_name = "{0}_{1}_{2}".format(name, os, cpu)
  1064. cc_toolchain_config(
  1065. name = config_name + "_config",
  1066. target_os = os,
  1067. target_cpu = cpu,
  1068. )
  1069. cc_toolchain(
  1070. name = config_name + "_tools",
  1071. all_files = ":" + name + "_empty",
  1072. ar_files = ":" + name + "_empty",
  1073. as_files = ":" + name + "_empty",
  1074. compiler_files = ":" + name + "_empty",
  1075. dwp_files = ":" + name + "_empty",
  1076. linker_files = ":" + name + "_empty",
  1077. objcopy_files = ":" + name + "_empty",
  1078. strip_files = ":" + name + "_empty",
  1079. supports_param_files = 1,
  1080. toolchain_config = ":" + config_name + "_config",
  1081. toolchain_identifier = config_name,
  1082. )
  1083. compatible_with = ["@platforms//cpu:" + cpu, "@platforms//os:" + os]
  1084. native.toolchain(
  1085. name = config_name,
  1086. exec_compatible_with = compatible_with,
  1087. target_compatible_with = compatible_with,
  1088. toolchain = config_name + "_tools",
  1089. toolchain_type = "@bazel_tools//tools/cpp:toolchain_type",
  1090. )