clang_cc_toolchain_config.bzl 44 KB

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