clang_cc_toolchain_config.bzl 34 KB

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