clang_cc_toolchain_config.bzl 31 KB

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