clang_cc_toolchain_config.bzl 31 KB

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