clang_cc_toolchain_config.bzl 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870
  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(
  6. "@bazel_tools//tools/cpp:cc_toolchain_config_lib.bzl",
  7. "action_config",
  8. "feature",
  9. "feature_set",
  10. "flag_group",
  11. "flag_set",
  12. "tool",
  13. "tool_path",
  14. "variable_with_value",
  15. "with_feature_set",
  16. )
  17. load("@bazel_tools//tools/build_defs/cc:action_names.bzl", "ACTION_NAMES")
  18. load(
  19. ":clang_detected_variables.bzl",
  20. "clang_bindir",
  21. "clang_version",
  22. "clang_version_for_cache",
  23. "clang_include_dirs_list",
  24. "clang_resource_dir",
  25. "llvm_bindir",
  26. "sysroot_dir",
  27. )
  28. all_c_compile_actions = [
  29. ACTION_NAMES.c_compile,
  30. ACTION_NAMES.assemble,
  31. ACTION_NAMES.preprocess_assemble,
  32. ]
  33. all_cpp_compile_actions = [
  34. ACTION_NAMES.cpp_compile,
  35. ACTION_NAMES.linkstamp_compile,
  36. ACTION_NAMES.cpp_header_parsing,
  37. ACTION_NAMES.cpp_module_compile,
  38. ACTION_NAMES.cpp_module_codegen,
  39. ]
  40. all_compile_actions = all_c_compile_actions + all_cpp_compile_actions
  41. preprocessor_compile_actions = [
  42. ACTION_NAMES.c_compile,
  43. ACTION_NAMES.cpp_compile,
  44. ACTION_NAMES.linkstamp_compile,
  45. ACTION_NAMES.preprocess_assemble,
  46. ACTION_NAMES.cpp_header_parsing,
  47. ACTION_NAMES.cpp_module_compile,
  48. ]
  49. codegen_compile_actions = [
  50. ACTION_NAMES.c_compile,
  51. ACTION_NAMES.cpp_compile,
  52. ACTION_NAMES.linkstamp_compile,
  53. ACTION_NAMES.assemble,
  54. ACTION_NAMES.preprocess_assemble,
  55. ACTION_NAMES.cpp_module_codegen,
  56. ]
  57. all_link_actions = [
  58. ACTION_NAMES.cpp_link_executable,
  59. ACTION_NAMES.cpp_link_dynamic_library,
  60. ACTION_NAMES.cpp_link_nodeps_dynamic_library,
  61. ]
  62. def _impl(ctx):
  63. tool_paths = [
  64. tool_path(name = "ar", path = llvm_bindir + "/llvm-ar"),
  65. tool_path(name = "ld", path = clang_bindir + "/ld.lld"),
  66. tool_path(name = "cpp", path = clang_bindir + "/clang-cpp"),
  67. tool_path(name = "gcc", path = clang_bindir + "/clang++"),
  68. tool_path(name = "dwp", path = llvm_bindir + "/llvm-dwp"),
  69. tool_path(name = "gcov", path = llvm_bindir + "/llvm-cov"),
  70. tool_path(name = "nm", path = llvm_bindir + "/llvm-nm"),
  71. tool_path(name = "objcopy", path = llvm_bindir + "/llvm-objcopy"),
  72. tool_path(name = "objdump", path = llvm_bindir + "/llvm-objdump"),
  73. tool_path(name = "strip", path = llvm_bindir + "/llvm-strip"),
  74. ]
  75. action_configs = [
  76. action_config(action_name = name, enabled = True, tools = [tool(path = clang_bindir + "/clang")])
  77. for name in all_c_compile_actions
  78. ] + [
  79. action_config(action_name = name, enabled = True, tools = [tool(path = clang_bindir + "/clang++")])
  80. for name in all_cpp_compile_actions
  81. ] + [
  82. action_config(action_name = name, enabled = True, tools = [tool(path = clang_bindir + "/clang++")])
  83. for name in all_link_actions
  84. ] + [
  85. action_config(action_name = name, enabled = True, tools = [tool(path = llvm_bindir + "/llvm-ar")])
  86. for name in [ACTION_NAMES.cpp_link_static_library]
  87. ] + [
  88. action_config(action_name = name, enabled = True, tools = [tool(path = llvm_bindir + "/llvm-strip")])
  89. for name in [ACTION_NAMES.strip]
  90. ]
  91. std_compile_flags = ["-std=c++17"]
  92. # libc++ is only used on non-Windows platforms.
  93. if ctx.attr.target_cpu != "x64_windows":
  94. std_compile_flags.append("-stdlib=libc++")
  95. default_flags_feature = feature(
  96. name = "default_flags",
  97. enabled = True,
  98. flag_sets = [
  99. flag_set(
  100. actions = all_compile_actions + all_link_actions,
  101. flag_groups = ([
  102. flag_group(
  103. flags = [
  104. "-no-canonical-prefixes",
  105. "-fcolor-diagnostics",
  106. ],
  107. ),
  108. ]),
  109. ),
  110. flag_set(
  111. actions = all_compile_actions,
  112. flag_groups = ([
  113. flag_group(
  114. flags = [
  115. "-Werror",
  116. "-Wall",
  117. "-Wextra",
  118. "-Wthread-safety",
  119. "-Wself-assign",
  120. "-Wimplicit-fallthrough",
  121. "-Wctad-maybe-unsupported",
  122. "-Wnon-virtual-dtor",
  123. # Unfortunately, LLVM isn't clean for this warning.
  124. "-Wno-unused-parameter",
  125. # Compile actions shouldn't link anything.
  126. "-c",
  127. ],
  128. ),
  129. flag_group(
  130. expand_if_available = "output_assembly_file",
  131. flags = ["-S"],
  132. ),
  133. flag_group(
  134. expand_if_available = "output_preprocess_file",
  135. flags = ["-E"],
  136. ),
  137. flag_group(
  138. flags = ["-MD", "-MF", "%{dependency_file}"],
  139. expand_if_available = "dependency_file",
  140. ),
  141. flag_group(
  142. flags = ["-frandom-seed=%{output_file}"],
  143. expand_if_available = "output_file",
  144. ),
  145. ]),
  146. ),
  147. flag_set(
  148. actions = all_cpp_compile_actions + all_link_actions,
  149. flag_groups = ([
  150. flag_group(
  151. flags = std_compile_flags,
  152. ),
  153. ]),
  154. ),
  155. flag_set(
  156. actions = codegen_compile_actions,
  157. flag_groups = ([
  158. flag_group(
  159. flags = [
  160. "-ffunction-sections",
  161. "-fdata-sections",
  162. ],
  163. ),
  164. ]),
  165. ),
  166. flag_set(
  167. actions = codegen_compile_actions,
  168. flag_groups = [
  169. flag_group(flags = ["-fPIC"], expand_if_available = "pic"),
  170. ],
  171. ),
  172. flag_set(
  173. actions = preprocessor_compile_actions,
  174. flag_groups = [
  175. flag_group(
  176. flags = [
  177. # Disable a warning and override builtin macros to
  178. # ensure a hermetic build.
  179. "-Wno-builtin-macro-redefined",
  180. "-D__DATE__=\"redacted\"",
  181. "-D__TIMESTAMP__=\"redacted\"",
  182. "-D__TIME__=\"redacted\"",
  183. # Pass the clang version as a define so that bazel
  184. # caching is more likely to notice version changes.
  185. "-DCLANG_VERSION_FOR_CACHE=\"%s\"" % clang_version_for_cache,
  186. ],
  187. ),
  188. flag_group(
  189. flags = ["-D%{preprocessor_defines}"],
  190. iterate_over = "preprocessor_defines",
  191. ),
  192. flag_group(
  193. flags = ["-include", "%{includes}"],
  194. iterate_over = "includes",
  195. expand_if_available = "includes",
  196. ),
  197. flag_group(
  198. flags = ["-iquote", "%{quote_include_paths}"],
  199. iterate_over = "quote_include_paths",
  200. ),
  201. flag_group(
  202. flags = ["-I%{include_paths}"],
  203. iterate_over = "include_paths",
  204. ),
  205. flag_group(
  206. flags = ["-isystem", "%{system_include_paths}"],
  207. iterate_over = "system_include_paths",
  208. ),
  209. ],
  210. ),
  211. flag_set(
  212. actions = [
  213. ACTION_NAMES.cpp_link_dynamic_library,
  214. ACTION_NAMES.cpp_link_nodeps_dynamic_library,
  215. ],
  216. flag_groups = [flag_group(flags = ["-shared"])],
  217. ),
  218. flag_set(
  219. actions = all_link_actions,
  220. flag_groups = [
  221. flag_group(
  222. flags = ["-Wl,--gdb-index"],
  223. expand_if_available = "is_using_fission",
  224. ),
  225. flag_group(
  226. flags = ["-Wl,-S"],
  227. expand_if_available = "strip_debug_symbols",
  228. ),
  229. flag_group(
  230. flags = ["-L%{library_search_directories}"],
  231. iterate_over = "library_search_directories",
  232. expand_if_available = "library_search_directories",
  233. ),
  234. flag_group(
  235. iterate_over = "runtime_library_search_directories",
  236. flags = [
  237. "-Wl,-rpath,$ORIGIN/%{runtime_library_search_directories}",
  238. ],
  239. expand_if_available =
  240. "runtime_library_search_directories",
  241. ),
  242. ],
  243. ),
  244. ],
  245. )
  246. # Handle different levels of optimization with individual features so that
  247. # they can be ordered and the defaults can override the minimal settings if
  248. # both are enabled.
  249. minimal_optimization_flags = feature(
  250. name = "minimal_optimization_flags",
  251. flag_sets = [
  252. flag_set(
  253. actions = codegen_compile_actions,
  254. flag_groups = [flag_group(flags = [
  255. "-O1",
  256. ])],
  257. ),
  258. # Use a conditional flag set for enabling the fast instruction
  259. # selector to work around an LLVM bug:
  260. # https://github.com/llvm/llvm-project/issues/56133
  261. flag_set(
  262. actions = codegen_compile_actions,
  263. flag_groups = [flag_group(flags = [
  264. "-mllvm",
  265. "-fast-isel",
  266. ])],
  267. with_features = [
  268. with_feature_set(not_features = ["fuzzer"]),
  269. ],
  270. ),
  271. ],
  272. )
  273. default_optimization_flags = feature(
  274. name = "default_optimization_flags",
  275. enabled = True,
  276. requires = [feature_set(["opt"])],
  277. flag_sets = [
  278. flag_set(
  279. actions = all_compile_actions,
  280. flag_groups = [flag_group(flags = [
  281. "-DNDEBUG",
  282. ])],
  283. ),
  284. flag_set(
  285. actions = codegen_compile_actions,
  286. flag_groups = [flag_group(flags = [
  287. "-O3",
  288. ])],
  289. ),
  290. ],
  291. )
  292. # Handle different levels and forms of debug info emission with individual
  293. # features so that they can be ordered and the defaults can override the
  294. # minimal settings if both are enabled.
  295. minimal_debug_info_flags = feature(
  296. name = "minimal_debug_info_flags",
  297. flag_sets = [
  298. flag_set(
  299. actions = codegen_compile_actions,
  300. flag_groups = [
  301. flag_group(
  302. flags = ["-gmlt"],
  303. ),
  304. ],
  305. ),
  306. ],
  307. )
  308. default_debug_info_flags = feature(
  309. name = "default_debug_info_flags",
  310. enabled = True,
  311. flag_sets = [
  312. flag_set(
  313. actions = codegen_compile_actions,
  314. flag_groups = ([
  315. flag_group(
  316. flags = ["-g"],
  317. ),
  318. ]),
  319. with_features = [with_feature_set(features = ["dbg"])],
  320. ),
  321. flag_set(
  322. actions = codegen_compile_actions,
  323. flag_groups = [
  324. flag_group(
  325. flags = ["-gsplit-dwarf", "-g"],
  326. expand_if_available = "per_object_debug_info_file",
  327. ),
  328. ],
  329. ),
  330. ],
  331. )
  332. # This feature can be enabled in conjunction with any optimizations to
  333. # ensure accurate call stacks and backtraces for profilers or errors.
  334. preserve_call_stacks = feature(
  335. name = "preserve_call_stacks",
  336. flag_sets = [flag_set(
  337. actions = codegen_compile_actions,
  338. flag_groups = [flag_group(flags = [
  339. # Ensure good backtraces by preserving frame pointers and
  340. # disabling tail call elimination.
  341. "-fno-omit-frame-pointer",
  342. "-mno-omit-leaf-frame-pointer",
  343. "-fno-optimize-sibling-calls",
  344. ])],
  345. )],
  346. )
  347. sysroot_feature = feature(
  348. name = "sysroot",
  349. enabled = True,
  350. flag_sets = [
  351. flag_set(
  352. actions = all_compile_actions + all_link_actions,
  353. flag_groups = [
  354. flag_group(
  355. flags = ["--sysroot=%{sysroot}"],
  356. expand_if_available = "sysroot",
  357. ),
  358. ],
  359. ),
  360. ],
  361. )
  362. use_module_maps = feature(
  363. name = "use_module_maps",
  364. requires = [feature_set(features = ["module_maps"])],
  365. flag_sets = [
  366. flag_set(
  367. actions = [
  368. ACTION_NAMES.c_compile,
  369. ACTION_NAMES.cpp_compile,
  370. ACTION_NAMES.cpp_header_parsing,
  371. ACTION_NAMES.cpp_module_compile,
  372. ],
  373. flag_groups = [
  374. # These flag groups are separate so they do not expand to
  375. # the cross product of the variables.
  376. flag_group(flags = ["-fmodule-name=%{module_name}"]),
  377. flag_group(
  378. flags = ["-fmodule-map-file=%{module_map_file}"],
  379. ),
  380. ],
  381. ),
  382. ],
  383. )
  384. # Tell bazel we support module maps in general, so they will be generated
  385. # for all c/c++ rules.
  386. # Note: not all C++ rules support module maps; thus, do not imply this
  387. # feature from other features - instead, require it.
  388. module_maps = feature(
  389. name = "module_maps",
  390. enabled = True,
  391. implies = [
  392. # "module_map_home_cwd",
  393. # "module_map_without_extern_module",
  394. # "generate_submodules",
  395. ],
  396. )
  397. layering_check = feature(
  398. name = "layering_check",
  399. implies = ["use_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. flag_group(flags = [
  410. "-fmodules-strict-decluse",
  411. "-Wprivate-header",
  412. ]),
  413. flag_group(
  414. iterate_over = "dependent_module_map_files",
  415. flags = [
  416. "-fmodule-map-file=%{dependent_module_map_files}",
  417. ],
  418. ),
  419. ],
  420. ),
  421. ],
  422. )
  423. sanitizer_common_flags = feature(
  424. name = "sanitizer_common_flags",
  425. requires = [feature_set(["nonhost"])],
  426. implies = ["minimal_optimization_flags", "minimal_debug_info_flags", "preserve_call_stacks"],
  427. flag_sets = [flag_set(
  428. actions = all_link_actions,
  429. flag_groups = [flag_group(flags = [
  430. "-static-libsan",
  431. ])],
  432. )],
  433. )
  434. asan = feature(
  435. name = "asan",
  436. requires = [feature_set(["nonhost"])],
  437. implies = ["sanitizer_common_flags"],
  438. flag_sets = [flag_set(
  439. actions = all_compile_actions + all_link_actions,
  440. flag_groups = [flag_group(flags = [
  441. "-fsanitize=address,undefined,nullability",
  442. "-fsanitize-address-use-after-scope",
  443. # We don't need the recovery behavior of UBSan as we expect
  444. # builds to be clean. Not recovering is a bit cheaper.
  445. "-fno-sanitize-recover=undefined",
  446. # Don't embed the full path name for files. This limits the size
  447. # and combined with line numbers is unlikely to result in many
  448. # ambiguities.
  449. "-fsanitize-undefined-strip-path-components=-1",
  450. # Needed due to clang AST issues, such as in
  451. # clang/AST/Redeclarable.h line 199.
  452. "-fno-sanitize=vptr",
  453. ])],
  454. )],
  455. )
  456. enable_asan_in_fastbuild = feature(
  457. name = "enable_asan_in_fastbuild",
  458. enabled = True,
  459. requires = [feature_set(["nonhost", "fastbuild"])],
  460. implies = ["asan"],
  461. )
  462. fuzzer = feature(
  463. name = "fuzzer",
  464. requires = [feature_set(["nonhost"])],
  465. implies = ["asan"],
  466. flag_sets = [flag_set(
  467. actions = all_compile_actions + all_link_actions,
  468. flag_groups = [flag_group(flags = [
  469. "-fsanitize=fuzzer-no-link",
  470. ])],
  471. )],
  472. )
  473. proto_fuzzer = feature(
  474. name = "proto-fuzzer",
  475. enabled = False,
  476. requires = [feature_set(["nonhost"])],
  477. implies = ["fuzzer"],
  478. )
  479. # With clang 14 and lower, we expect it to be built with libc++ debug
  480. # support. In later LLVM versions, we expect the assertions define to work.
  481. if clang_version and clang_version <= 14:
  482. libcpp_debug_flags = ["-D_LIBCPP_DEBUG=1"]
  483. else:
  484. libcpp_debug_flags = ["-D_LIBCPP_ENABLE_ASSERTIONS=1"]
  485. linux_flags_feature = feature(
  486. name = "linux_flags",
  487. enabled = True,
  488. flag_sets = [
  489. flag_set(
  490. actions = all_link_actions,
  491. flag_groups = ([
  492. flag_group(
  493. flags = [
  494. "-fuse-ld=lld",
  495. "-stdlib=libc++",
  496. "-unwindlib=libunwind",
  497. # Force the C++ standard library and runtime
  498. # libraries to be statically linked. This works even
  499. # with libc++ and libunwind despite the names,
  500. # provided libc++ is built with two CMake options:
  501. # - `-DCMAKE_POSITION_INDEPENDENT_CODE=ON`
  502. # - `-DLIBCXX_STATICALLY_LINK_ABI_IN_STATIC_LIBRARY`
  503. # These are both required because of PR43604
  504. # (impacting at least Debian packages of libc++) and
  505. # PR46321 (impacting most other packages).
  506. # We recommend using Homebrew's LLVM install on
  507. # Linux.
  508. "-static-libstdc++",
  509. "-static-libgcc",
  510. # Link with Clang's runtime library. This is always
  511. # linked statically.
  512. "-rtlib=compiler-rt",
  513. # Explicitly add LLVM libs to the search path to
  514. # preempt the detected GCC installation's library
  515. # paths. Those might have a system installed libc++
  516. # and we want to find the one next to our Clang.
  517. "-L" + llvm_bindir + "/../lib",
  518. # Link with pthread.
  519. "-lpthread",
  520. ],
  521. ),
  522. ]),
  523. ),
  524. flag_set(
  525. actions = all_compile_actions,
  526. flag_groups = [flag_group(flags = libcpp_debug_flags)],
  527. with_features = [
  528. with_feature_set(not_features = ["opt"]),
  529. ],
  530. ),
  531. flag_set(
  532. actions = [
  533. ACTION_NAMES.cpp_link_executable,
  534. ],
  535. flag_groups = [
  536. flag_group(
  537. flags = ["-pie"],
  538. expand_if_available = "force_pic",
  539. ),
  540. ],
  541. ),
  542. ],
  543. )
  544. macos_flags_feature = feature(
  545. name = "macos_flags",
  546. enabled = True,
  547. flag_sets = [
  548. flag_set(
  549. actions = [
  550. ACTION_NAMES.cpp_link_executable,
  551. ],
  552. flag_groups = [
  553. flag_group(
  554. flags = ["-fpie"],
  555. expand_if_available = "force_pic",
  556. ),
  557. ],
  558. ),
  559. ],
  560. )
  561. default_link_libraries_feature = feature(
  562. name = "default_link_libraries",
  563. enabled = True,
  564. flag_sets = [
  565. flag_set(
  566. actions = all_link_actions,
  567. flag_groups = [
  568. flag_group(
  569. flags = ["%{linkstamp_paths}"],
  570. iterate_over = "linkstamp_paths",
  571. expand_if_available = "linkstamp_paths",
  572. ),
  573. flag_group(
  574. iterate_over = "libraries_to_link",
  575. flag_groups = [
  576. flag_group(
  577. flags = ["-Wl,--start-lib"],
  578. expand_if_equal = variable_with_value(
  579. name = "libraries_to_link.type",
  580. value = "object_file_group",
  581. ),
  582. ),
  583. flag_group(
  584. flags = ["-Wl,-whole-archive"],
  585. expand_if_true =
  586. "libraries_to_link.is_whole_archive",
  587. ),
  588. flag_group(
  589. flags = ["%{libraries_to_link.object_files}"],
  590. iterate_over = "libraries_to_link.object_files",
  591. expand_if_equal = variable_with_value(
  592. name = "libraries_to_link.type",
  593. value = "object_file_group",
  594. ),
  595. ),
  596. flag_group(
  597. flags = ["%{libraries_to_link.name}"],
  598. expand_if_equal = variable_with_value(
  599. name = "libraries_to_link.type",
  600. value = "object_file",
  601. ),
  602. ),
  603. flag_group(
  604. flags = ["%{libraries_to_link.name}"],
  605. expand_if_equal = variable_with_value(
  606. name = "libraries_to_link.type",
  607. value = "interface_library",
  608. ),
  609. ),
  610. flag_group(
  611. flags = ["%{libraries_to_link.name}"],
  612. expand_if_equal = variable_with_value(
  613. name = "libraries_to_link.type",
  614. value = "static_library",
  615. ),
  616. ),
  617. flag_group(
  618. flags = ["-l%{libraries_to_link.name}"],
  619. expand_if_equal = variable_with_value(
  620. name = "libraries_to_link.type",
  621. value = "dynamic_library",
  622. ),
  623. ),
  624. flag_group(
  625. flags = ["-l:%{libraries_to_link.name}"],
  626. expand_if_equal = variable_with_value(
  627. name = "libraries_to_link.type",
  628. value = "versioned_dynamic_library",
  629. ),
  630. ),
  631. flag_group(
  632. flags = ["-Wl,-no-whole-archive"],
  633. expand_if_true = "libraries_to_link.is_whole_archive",
  634. ),
  635. flag_group(
  636. flags = ["-Wl,--end-lib"],
  637. expand_if_equal = variable_with_value(
  638. name = "libraries_to_link.type",
  639. value = "object_file_group",
  640. ),
  641. ),
  642. ],
  643. expand_if_available = "libraries_to_link",
  644. ),
  645. # Note that the params file comes at the end, after the
  646. # libraries to link above.
  647. flag_group(
  648. expand_if_available = "linker_param_file",
  649. flags = ["@%{linker_param_file}"],
  650. ),
  651. ],
  652. ),
  653. ],
  654. )
  655. # Place user provided compile flags after all the features so that these
  656. # flags can override or customize behavior. The only thing user flags
  657. # cannot override is the output file as Bazel depends on that.
  658. #
  659. # Finally, place the source file (if present) and output file last to make
  660. # reading the compile command lines easier for humans.
  661. final_flags_feature = feature(
  662. name = "final_flags",
  663. enabled = True,
  664. flag_sets = [
  665. flag_set(
  666. actions = all_compile_actions,
  667. flag_groups = [
  668. flag_group(
  669. flags = ["%{user_compile_flags}"],
  670. iterate_over = "user_compile_flags",
  671. expand_if_available = "user_compile_flags",
  672. ),
  673. flag_group(
  674. flags = ["%{source_file}"],
  675. expand_if_available = "source_file",
  676. ),
  677. flag_group(
  678. expand_if_available = "output_file",
  679. flags = ["-o", "%{output_file}"],
  680. ),
  681. ],
  682. ),
  683. flag_set(
  684. actions = all_link_actions,
  685. flag_groups = [
  686. flag_group(
  687. flags = ["%{user_link_flags}"],
  688. iterate_over = "user_link_flags",
  689. expand_if_available = "user_link_flags",
  690. ),
  691. flag_group(
  692. flags = ["-o", "%{output_execpath}"],
  693. expand_if_available = "output_execpath",
  694. ),
  695. ],
  696. ),
  697. ],
  698. )
  699. # Archive actions have an entirely independent set of flags and don't
  700. # interact with either compiler or link actions.
  701. default_archiver_flags_feature = feature(
  702. name = "default_archiver_flags",
  703. enabled = True,
  704. flag_sets = [
  705. flag_set(
  706. actions = [ACTION_NAMES.cpp_link_static_library],
  707. flag_groups = [
  708. flag_group(flags = ["rcsD"]),
  709. flag_group(
  710. flags = ["%{output_execpath}"],
  711. expand_if_available = "output_execpath",
  712. ),
  713. flag_group(
  714. iterate_over = "libraries_to_link",
  715. flag_groups = [
  716. flag_group(
  717. flags = ["%{libraries_to_link.name}"],
  718. expand_if_equal = variable_with_value(
  719. name = "libraries_to_link.type",
  720. value = "object_file",
  721. ),
  722. ),
  723. flag_group(
  724. flags = ["%{libraries_to_link.object_files}"],
  725. iterate_over = "libraries_to_link.object_files",
  726. expand_if_equal = variable_with_value(
  727. name = "libraries_to_link.type",
  728. value = "object_file_group",
  729. ),
  730. ),
  731. ],
  732. expand_if_available = "libraries_to_link",
  733. ),
  734. flag_group(
  735. expand_if_available = "linker_param_file",
  736. flags = ["@%{linker_param_file}"],
  737. ),
  738. ],
  739. ),
  740. ],
  741. )
  742. # Now that we have built up the constituent feature definitions, compose
  743. # them, including configuration based on the target platform. Currently,
  744. # the target platform is configured with the "cpu" attribute for legacy
  745. # reasons. Further, for legacy reasons the default is a Linux OS target and
  746. # the x88-64 CPU name is "k8".
  747. # First, define features that are simply used to configure others.
  748. features = [
  749. feature(name = "dbg"),
  750. feature(name = "fastbuild"),
  751. feature(name = "host"),
  752. feature(name = "no_legacy_features"),
  753. feature(name = "nonhost"),
  754. feature(name = "opt"),
  755. feature(name = "supports_dynamic_linker", enabled = ctx.attr.target_cpu == "k8"),
  756. feature(name = "supports_pic", enabled = True),
  757. feature(name = "supports_start_end_lib", enabled = ctx.attr.target_cpu == "k8"),
  758. ]
  759. # The order of the features determines the relative order of flags used.
  760. # Start off adding the baseline features.
  761. features += [
  762. default_flags_feature,
  763. minimal_optimization_flags,
  764. default_optimization_flags,
  765. minimal_debug_info_flags,
  766. default_debug_info_flags,
  767. preserve_call_stacks,
  768. sysroot_feature,
  769. sanitizer_common_flags,
  770. asan,
  771. enable_asan_in_fastbuild,
  772. fuzzer,
  773. proto_fuzzer,
  774. layering_check,
  775. module_maps,
  776. use_module_maps,
  777. default_archiver_flags_feature,
  778. ]
  779. # Next, add the features based on the target platform. Here too the
  780. # features are order sensitive. We also setup the sysroot here.
  781. if ctx.attr.target_cpu == "k8":
  782. features += [linux_flags_feature]
  783. sysroot = None
  784. elif ctx.attr.target_cpu == "x64_windows":
  785. # TODO: Need to figure out if we need to add windows specific features
  786. # I think the .pdb debug files will need to be handled differently,
  787. # so that might be an example where a feature must be added.
  788. sysroot = None
  789. elif ctx.attr.target_cpu in ["darwin", "darwin_arm64"]:
  790. features += [macos_flags_feature]
  791. sysroot = sysroot_dir
  792. else:
  793. fail("Unsupported target platform!")
  794. # Finally append the libraries to link and any final flags.
  795. features += [
  796. default_link_libraries_feature,
  797. final_flags_feature,
  798. ]
  799. return cc_common.create_cc_toolchain_config_info(
  800. ctx = ctx,
  801. features = features,
  802. action_configs = action_configs,
  803. cxx_builtin_include_directories = clang_include_dirs_list + [
  804. # Add Clang's resource directory to the end of the builtin include
  805. # directories to cover the use of sanitizer resource files by the driver.
  806. clang_resource_dir + "/share",
  807. ],
  808. builtin_sysroot = sysroot,
  809. # This configuration only supports local non-cross builds so derive
  810. # everything from the target CPU selected.
  811. toolchain_identifier = "local-" + ctx.attr.target_cpu,
  812. host_system_name = "local-" + ctx.attr.target_cpu,
  813. target_system_name = "local-" + ctx.attr.target_cpu,
  814. target_cpu = ctx.attr.target_cpu,
  815. # These attributes aren't meaningful at all so just use placeholder
  816. # values.
  817. target_libc = "local",
  818. compiler = "local",
  819. abi_version = "local",
  820. abi_libc_version = "local",
  821. # We do have to pass in our tool paths.
  822. tool_paths = tool_paths,
  823. )
  824. cc_toolchain_config = rule(
  825. implementation = _impl,
  826. attrs = {
  827. "target_cpu": attr.string(mandatory = True),
  828. },
  829. provides = [CcToolchainConfigInfo],
  830. )