clang_cc_toolchain_config.bzl 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997
  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", "cc_toolchain_suite")
  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++17"]
  93. # libc++ is only used on non-Windows platforms.
  94. if ctx.attr.target_cpu != "x64_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. # With clang 14 and lower, we expect it to be built with libc++ debug
  515. # support. In later LLVM versions, we expect the assertions define to work.
  516. # clang 17 deprecates LIBCPP_ENABLE_ASSERTIONS in favor of HARDENED_MODE.
  517. if clang_version and clang_version <= 14:
  518. libcpp_debug_flags = ["-D_LIBCPP_DEBUG=1"]
  519. elif clang_version and clang_version <= 16:
  520. libcpp_debug_flags = ["-D_LIBCPP_ENABLE_ASSERTIONS=1"]
  521. else:
  522. libcpp_debug_flags = ["-D_LIBCPP_ENABLE_HARDENED_MODE=1"]
  523. linux_flags_feature = feature(
  524. name = "linux_flags",
  525. enabled = True,
  526. flag_sets = [
  527. flag_set(
  528. actions = all_link_actions,
  529. flag_groups = ([
  530. flag_group(
  531. flags = [
  532. "-fuse-ld=lld",
  533. "-stdlib=libc++",
  534. "-unwindlib=libunwind",
  535. # Force the C++ standard library and runtime
  536. # libraries to be statically linked. This works even
  537. # with libc++ and libunwind despite the names,
  538. # provided libc++ is built with two CMake options:
  539. # - `-DCMAKE_POSITION_INDEPENDENT_CODE=ON`
  540. # - `-DLIBCXX_STATICALLY_LINK_ABI_IN_STATIC_LIBRARY`
  541. # These are both required because of PR43604
  542. # (impacting at least Debian packages of libc++) and
  543. # PR46321 (impacting most other packages).
  544. # We recommend using Homebrew's LLVM install on
  545. # Linux.
  546. "-static-libstdc++",
  547. "-static-libgcc",
  548. # Link with Clang's runtime library. This is always
  549. # linked statically.
  550. "-rtlib=compiler-rt",
  551. # Explicitly add LLVM libs to the search path to
  552. # preempt the detected GCC installation's library
  553. # paths. Those might have a system installed libc++
  554. # and we want to find the one next to our Clang.
  555. "-L" + llvm_bindir + "/../lib",
  556. # Link with pthread.
  557. "-lpthread",
  558. ],
  559. ),
  560. ]),
  561. ),
  562. flag_set(
  563. actions = all_compile_actions,
  564. flag_groups = [flag_group(flags = libcpp_debug_flags)],
  565. with_features = [
  566. with_feature_set(not_features = ["opt"]),
  567. ],
  568. ),
  569. flag_set(
  570. actions = [
  571. ACTION_NAMES.cpp_link_executable,
  572. ],
  573. flag_groups = [
  574. flag_group(
  575. flags = ["-pie"],
  576. expand_if_available = "force_pic",
  577. ),
  578. ],
  579. ),
  580. ],
  581. )
  582. macos_flags_feature = feature(
  583. name = "macos_flags",
  584. enabled = True,
  585. flag_sets = [
  586. flag_set(
  587. actions = [
  588. ACTION_NAMES.cpp_link_executable,
  589. ],
  590. flag_groups = [
  591. flag_group(
  592. flags = ["-fpie"],
  593. expand_if_available = "force_pic",
  594. ),
  595. ],
  596. ),
  597. ],
  598. )
  599. freebsd_flags_feature = feature(
  600. name = "freebsd_flags",
  601. enabled = True,
  602. flag_sets = [
  603. flag_set(
  604. actions = [
  605. ACTION_NAMES.c_compile,
  606. ACTION_NAMES.cpp_compile,
  607. ACTION_NAMES.cpp_header_parsing,
  608. ACTION_NAMES.cpp_module_compile,
  609. ],
  610. flag_groups = [
  611. flag_group(
  612. flags = [
  613. "-DHAVE_MALLCTL",
  614. ],
  615. ),
  616. ],
  617. ),
  618. flag_set(
  619. actions = [
  620. ACTION_NAMES.cpp_link_executable,
  621. ],
  622. flag_groups = [
  623. flag_group(
  624. flags = ["-fpie"],
  625. expand_if_available = "force_pic",
  626. ),
  627. ],
  628. ),
  629. ],
  630. )
  631. default_link_libraries_feature = feature(
  632. name = "default_link_libraries",
  633. enabled = True,
  634. flag_sets = [
  635. flag_set(
  636. actions = all_link_actions,
  637. flag_groups = [
  638. flag_group(
  639. flags = ["%{linkstamp_paths}"],
  640. iterate_over = "linkstamp_paths",
  641. expand_if_available = "linkstamp_paths",
  642. ),
  643. flag_group(
  644. iterate_over = "libraries_to_link",
  645. flag_groups = [
  646. flag_group(
  647. flags = ["-Wl,--start-lib"],
  648. expand_if_equal = variable_with_value(
  649. name = "libraries_to_link.type",
  650. value = "object_file_group",
  651. ),
  652. ),
  653. flag_group(
  654. flags = ["-Wl,-whole-archive"],
  655. expand_if_true =
  656. "libraries_to_link.is_whole_archive",
  657. ),
  658. flag_group(
  659. flags = ["%{libraries_to_link.object_files}"],
  660. iterate_over = "libraries_to_link.object_files",
  661. expand_if_equal = variable_with_value(
  662. name = "libraries_to_link.type",
  663. value = "object_file_group",
  664. ),
  665. ),
  666. flag_group(
  667. flags = ["%{libraries_to_link.name}"],
  668. expand_if_equal = variable_with_value(
  669. name = "libraries_to_link.type",
  670. value = "object_file",
  671. ),
  672. ),
  673. flag_group(
  674. flags = ["%{libraries_to_link.name}"],
  675. expand_if_equal = variable_with_value(
  676. name = "libraries_to_link.type",
  677. value = "interface_library",
  678. ),
  679. ),
  680. flag_group(
  681. flags = ["%{libraries_to_link.name}"],
  682. expand_if_equal = variable_with_value(
  683. name = "libraries_to_link.type",
  684. value = "static_library",
  685. ),
  686. ),
  687. flag_group(
  688. flags = ["-l%{libraries_to_link.name}"],
  689. expand_if_equal = variable_with_value(
  690. name = "libraries_to_link.type",
  691. value = "dynamic_library",
  692. ),
  693. ),
  694. flag_group(
  695. flags = ["-l:%{libraries_to_link.name}"],
  696. expand_if_equal = variable_with_value(
  697. name = "libraries_to_link.type",
  698. value = "versioned_dynamic_library",
  699. ),
  700. ),
  701. flag_group(
  702. flags = ["-Wl,-no-whole-archive"],
  703. expand_if_true = "libraries_to_link.is_whole_archive",
  704. ),
  705. flag_group(
  706. flags = ["-Wl,--end-lib"],
  707. expand_if_equal = variable_with_value(
  708. name = "libraries_to_link.type",
  709. value = "object_file_group",
  710. ),
  711. ),
  712. ],
  713. expand_if_available = "libraries_to_link",
  714. ),
  715. # Note that the params file comes at the end, after the
  716. # libraries to link above.
  717. flag_group(
  718. expand_if_available = "linker_param_file",
  719. flags = ["@%{linker_param_file}"],
  720. ),
  721. ],
  722. ),
  723. ],
  724. )
  725. # Place user provided compile flags after all the features so that these
  726. # flags can override or customize behavior. The only thing user flags
  727. # cannot override is the output file as Bazel depends on that.
  728. #
  729. # Finally, place the source file (if present) and output file last to make
  730. # reading the compile command lines easier for humans.
  731. final_flags_feature = feature(
  732. name = "final_flags",
  733. enabled = True,
  734. flag_sets = [
  735. flag_set(
  736. actions = all_compile_actions,
  737. flag_groups = [
  738. flag_group(
  739. flags = ["%{user_compile_flags}"],
  740. iterate_over = "user_compile_flags",
  741. expand_if_available = "user_compile_flags",
  742. ),
  743. flag_group(
  744. flags = ["%{source_file}"],
  745. expand_if_available = "source_file",
  746. ),
  747. flag_group(
  748. expand_if_available = "output_file",
  749. flags = ["-o", "%{output_file}"],
  750. ),
  751. ],
  752. ),
  753. flag_set(
  754. actions = all_link_actions,
  755. flag_groups = [
  756. flag_group(
  757. flags = ["%{user_link_flags}"],
  758. iterate_over = "user_link_flags",
  759. expand_if_available = "user_link_flags",
  760. ),
  761. flag_group(
  762. flags = ["-o", "%{output_execpath}"],
  763. expand_if_available = "output_execpath",
  764. ),
  765. ],
  766. ),
  767. ],
  768. )
  769. # Archive actions have an entirely independent set of flags and don't
  770. # interact with either compiler or link actions.
  771. default_archiver_flags_feature = feature(
  772. name = "default_archiver_flags",
  773. enabled = True,
  774. flag_sets = [
  775. flag_set(
  776. actions = [ACTION_NAMES.cpp_link_static_library],
  777. flag_groups = [
  778. flag_group(flags = ["rcsD"]),
  779. flag_group(
  780. flags = ["%{output_execpath}"],
  781. expand_if_available = "output_execpath",
  782. ),
  783. flag_group(
  784. iterate_over = "libraries_to_link",
  785. flag_groups = [
  786. flag_group(
  787. flags = ["%{libraries_to_link.name}"],
  788. expand_if_equal = variable_with_value(
  789. name = "libraries_to_link.type",
  790. value = "object_file",
  791. ),
  792. ),
  793. flag_group(
  794. flags = ["%{libraries_to_link.object_files}"],
  795. iterate_over = "libraries_to_link.object_files",
  796. expand_if_equal = variable_with_value(
  797. name = "libraries_to_link.type",
  798. value = "object_file_group",
  799. ),
  800. ),
  801. ],
  802. expand_if_available = "libraries_to_link",
  803. ),
  804. flag_group(
  805. expand_if_available = "linker_param_file",
  806. flags = ["@%{linker_param_file}"],
  807. ),
  808. ],
  809. ),
  810. ],
  811. )
  812. # Now that we have built up the constituent feature definitions, compose
  813. # them, including configuration based on the target platform. Currently,
  814. # the target platform is configured with the "cpu" attribute for legacy
  815. # reasons. Further, for legacy reasons the default is a Linux OS target and
  816. # the x88-64 CPU name is "k8".
  817. # First, define features that are simply used to configure others.
  818. features = [
  819. feature(name = "dbg"),
  820. feature(name = "fastbuild"),
  821. feature(name = "host"),
  822. feature(name = "no_legacy_features"),
  823. feature(name = "nonhost"),
  824. feature(name = "opt"),
  825. feature(name = "supports_dynamic_linker", enabled = ctx.attr.target_cpu == "k8"),
  826. feature(name = "supports_pic", enabled = True),
  827. feature(name = "supports_start_end_lib", enabled = ctx.attr.target_cpu == "k8"),
  828. ]
  829. # The order of the features determines the relative order of flags used.
  830. # Start off adding the baseline features.
  831. features += [
  832. default_flags_feature,
  833. minimal_optimization_flags,
  834. default_optimization_flags,
  835. minimal_debug_info_flags,
  836. default_debug_info_flags,
  837. preserve_call_stacks,
  838. sysroot_feature,
  839. sanitizer_common_flags,
  840. asan,
  841. enable_asan_in_fastbuild,
  842. fuzzer,
  843. layering_check,
  844. module_maps,
  845. use_module_maps,
  846. default_archiver_flags_feature,
  847. ]
  848. # Next, add the features based on the target platform. Here too the
  849. # features are order sensitive. We also setup the sysroot here.
  850. if ctx.attr.target_cpu in ["aarch64", "k8"]:
  851. features.append(sanitizer_static_lib_flags)
  852. features.append(linux_flags_feature)
  853. sysroot = None
  854. elif ctx.attr.target_cpu == "x64_windows":
  855. # TODO: Need to figure out if we need to add windows specific features
  856. # I think the .pdb debug files will need to be handled differently,
  857. # so that might be an example where a feature must be added.
  858. sysroot = None
  859. elif ctx.attr.target_cpu in ["darwin", "darwin_arm64"]:
  860. features.append(macos_asan_workarounds)
  861. features.append(macos_flags_feature)
  862. sysroot = sysroot_dir
  863. elif ctx.attr.target_cpu == "freebsd":
  864. features.append(sanitizer_static_lib_flags)
  865. features.append(freebsd_flags_feature)
  866. sysroot = sysroot_dir
  867. else:
  868. fail("Unsupported target platform!")
  869. if ctx.attr.target_cpu in ["aarch64", "darwin_arm64"]:
  870. features.append(aarch64_cpu_flags)
  871. else:
  872. features.append(x86_64_cpu_flags)
  873. # Finally append the libraries to link and any final flags.
  874. features += [
  875. default_link_libraries_feature,
  876. final_flags_feature,
  877. ]
  878. return cc_common.create_cc_toolchain_config_info(
  879. ctx = ctx,
  880. features = features,
  881. action_configs = action_configs,
  882. cxx_builtin_include_directories = clang_include_dirs_list + [
  883. # Add Clang's resource directory to the end of the builtin include
  884. # directories to cover the use of sanitizer resource files by the driver.
  885. clang_resource_dir + "/share",
  886. ],
  887. builtin_sysroot = sysroot,
  888. # This configuration only supports local non-cross builds so derive
  889. # everything from the target CPU selected.
  890. toolchain_identifier = "local-" + ctx.attr.target_cpu,
  891. host_system_name = "local-" + ctx.attr.target_cpu,
  892. target_system_name = "local-" + ctx.attr.target_cpu,
  893. target_cpu = ctx.attr.target_cpu,
  894. # These attributes aren't meaningful at all so just use placeholder
  895. # values.
  896. target_libc = "local",
  897. compiler = "local",
  898. abi_version = "local",
  899. abi_libc_version = "local",
  900. # We do have to pass in our tool paths.
  901. tool_paths = tool_paths,
  902. )
  903. cc_toolchain_config = rule(
  904. implementation = _impl,
  905. attrs = {
  906. "target_cpu": attr.string(mandatory = True),
  907. },
  908. provides = [CcToolchainConfigInfo],
  909. )
  910. def cc_local_toolchain_suite(name, cpus):
  911. """Create a toolchain suite that uses the local Clang/LLVM install.
  912. Args:
  913. name: The name of the toolchain suite to produce.
  914. cpus: An array of CPU strings to support in the toolchain.
  915. """
  916. # An empty filegroup to use when stubbing out the toolchains.
  917. native.filegroup(
  918. name = name + "_empty",
  919. srcs = [],
  920. )
  921. # Create the individual local toolchains for each CPU.
  922. for cpu in cpus:
  923. cc_toolchain_config(
  924. name = name + "_local_config_" + cpu,
  925. target_cpu = cpu,
  926. )
  927. cc_toolchain(
  928. name = name + "_local_" + cpu,
  929. all_files = ":" + name + "_empty",
  930. ar_files = ":" + name + "_empty",
  931. as_files = ":" + name + "_empty",
  932. compiler_files = ":" + name + "_empty",
  933. dwp_files = ":" + name + "_empty",
  934. linker_files = ":" + name + "_empty",
  935. objcopy_files = ":" + name + "_empty",
  936. strip_files = ":" + name + "_empty",
  937. supports_param_files = 1,
  938. toolchain_config = ":" + name + "_local_config_" + cpu,
  939. toolchain_identifier = name + "_local_" + cpu,
  940. )
  941. # Now build the suite, associating each CPU with its toolchain.
  942. cc_toolchain_suite(
  943. name = name,
  944. toolchains = {cpu: ":" + name + "_local_" + cpu for cpu in cpus},
  945. )