clang_cc_toolchain_config.bzl 44 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131
  1. # Part of the Carbon Language project, under the Apache License v2.0 with LLVM
  2. # Exceptions. See /LICENSE for license information.
  3. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. """A Starlark cc_toolchain configuration rule"""
  5. load("@bazel_tools//tools/build_defs/cc:action_names.bzl", "ACTION_NAMES")
  6. load(
  7. "@bazel_tools//tools/cpp:cc_toolchain_config_lib.bzl",
  8. "action_config",
  9. "feature",
  10. "feature_set",
  11. "flag_group",
  12. "flag_set",
  13. "tool",
  14. "tool_path",
  15. "variable_with_value",
  16. "with_feature_set",
  17. )
  18. load("@rules_cc//cc:defs.bzl", "cc_toolchain")
  19. load(
  20. ":clang_detected_variables.bzl",
  21. "clang_bindir",
  22. "clang_include_dirs_list",
  23. "clang_resource_dir",
  24. "clang_version",
  25. "clang_version_for_cache",
  26. "llvm_bindir",
  27. "sysroot_dir",
  28. )
  29. all_c_compile_actions = [
  30. ACTION_NAMES.c_compile,
  31. ACTION_NAMES.assemble,
  32. ACTION_NAMES.preprocess_assemble,
  33. ]
  34. all_cpp_compile_actions = [
  35. ACTION_NAMES.cpp_compile,
  36. ACTION_NAMES.linkstamp_compile,
  37. ACTION_NAMES.cpp_header_parsing,
  38. ACTION_NAMES.cpp_module_compile,
  39. ACTION_NAMES.cpp_module_codegen,
  40. ]
  41. all_compile_actions = all_c_compile_actions + all_cpp_compile_actions
  42. preprocessor_compile_actions = [
  43. ACTION_NAMES.c_compile,
  44. ACTION_NAMES.cpp_compile,
  45. ACTION_NAMES.linkstamp_compile,
  46. ACTION_NAMES.preprocess_assemble,
  47. ACTION_NAMES.cpp_header_parsing,
  48. ACTION_NAMES.cpp_module_compile,
  49. ]
  50. codegen_compile_actions = [
  51. ACTION_NAMES.c_compile,
  52. ACTION_NAMES.cpp_compile,
  53. ACTION_NAMES.linkstamp_compile,
  54. ACTION_NAMES.assemble,
  55. ACTION_NAMES.preprocess_assemble,
  56. ACTION_NAMES.cpp_module_codegen,
  57. ]
  58. all_link_actions = [
  59. ACTION_NAMES.cpp_link_executable,
  60. ACTION_NAMES.cpp_link_dynamic_library,
  61. ACTION_NAMES.cpp_link_nodeps_dynamic_library,
  62. ]
  63. def _impl(ctx):
  64. tool_paths = [
  65. tool_path(name = "ar", path = llvm_bindir + "/llvm-ar"),
  66. tool_path(name = "ld", path = clang_bindir + "/ld.lld"),
  67. tool_path(name = "cpp", path = clang_bindir + "/clang-cpp"),
  68. tool_path(name = "gcc", path = clang_bindir + "/clang++"),
  69. tool_path(name = "dwp", path = llvm_bindir + "/llvm-dwp"),
  70. tool_path(name = "gcov", path = llvm_bindir + "/llvm-cov"),
  71. tool_path(name = "nm", path = llvm_bindir + "/llvm-nm"),
  72. tool_path(name = "objcopy", path = llvm_bindir + "/llvm-objcopy"),
  73. tool_path(name = "objdump", path = llvm_bindir + "/llvm-objdump"),
  74. tool_path(name = "strip", path = llvm_bindir + "/llvm-strip"),
  75. ]
  76. action_configs = [
  77. action_config(action_name = name, enabled = True, tools = [tool(path = clang_bindir + "/clang")])
  78. for name in all_c_compile_actions
  79. ] + [
  80. action_config(action_name = name, enabled = True, tools = [tool(path = clang_bindir + "/clang++")])
  81. for name in all_cpp_compile_actions
  82. ] + [
  83. action_config(action_name = name, enabled = True, tools = [tool(path = clang_bindir + "/clang++")])
  84. for name in all_link_actions
  85. ] + [
  86. action_config(action_name = name, enabled = True, tools = [tool(path = llvm_bindir + "/llvm-ar")])
  87. for name in [ACTION_NAMES.cpp_link_static_library]
  88. ] + [
  89. action_config(action_name = name, enabled = True, tools = [tool(path = llvm_bindir + "/llvm-strip")])
  90. for name in [ACTION_NAMES.strip]
  91. ]
  92. std_compile_flags = ["-std=c++17"]
  93. # libc++ is only used on non-Windows platforms.
  94. if ctx.attr.target_os != "windows":
  95. std_compile_flags.append("-stdlib=libc++")
  96. # TODO: Regression that warns on anonymous unions; remove depending on fix.
  97. # Sets the flag for unknown clang versions, which are assumed to be at head.
  98. # https://github.com/llvm/llvm-project/issues/70384
  99. if not clang_version or clang_version == 18:
  100. missing_field_init_flags = ["-Wno-missing-field-initializers"]
  101. else:
  102. missing_field_init_flags = []
  103. default_flags_feature = feature(
  104. name = "default_flags",
  105. enabled = True,
  106. flag_sets = [
  107. flag_set(
  108. actions = all_compile_actions + all_link_actions,
  109. flag_groups = ([
  110. flag_group(
  111. flags = [
  112. "-no-canonical-prefixes",
  113. "-fcolor-diagnostics",
  114. ],
  115. ),
  116. ]),
  117. ),
  118. flag_set(
  119. actions = all_compile_actions,
  120. flag_groups = ([
  121. flag_group(
  122. flags = [
  123. "-Werror",
  124. "-Wall",
  125. "-Wextra",
  126. "-Wthread-safety",
  127. "-Wself-assign",
  128. "-Wimplicit-fallthrough",
  129. "-Wctad-maybe-unsupported",
  130. "-Wdelete-non-virtual-dtor",
  131. # Don't warn on external code as we can't
  132. # necessarily patch it easily.
  133. "--system-header-prefix=external/",
  134. # Compile actions shouldn't link anything.
  135. "-c",
  136. ] + missing_field_init_flags,
  137. ),
  138. flag_group(
  139. expand_if_available = "output_assembly_file",
  140. flags = ["-S"],
  141. ),
  142. flag_group(
  143. expand_if_available = "output_preprocess_file",
  144. flags = ["-E"],
  145. ),
  146. flag_group(
  147. flags = ["-MD", "-MF", "%{dependency_file}"],
  148. expand_if_available = "dependency_file",
  149. ),
  150. flag_group(
  151. flags = ["-frandom-seed=%{output_file}"],
  152. expand_if_available = "output_file",
  153. ),
  154. ]),
  155. ),
  156. flag_set(
  157. actions = all_cpp_compile_actions + all_link_actions,
  158. flag_groups = ([
  159. flag_group(
  160. flags = std_compile_flags,
  161. ),
  162. ]),
  163. ),
  164. flag_set(
  165. actions = codegen_compile_actions,
  166. flag_groups = ([
  167. flag_group(
  168. flags = [
  169. "-ffunction-sections",
  170. "-fdata-sections",
  171. ],
  172. ),
  173. ]),
  174. ),
  175. flag_set(
  176. actions = codegen_compile_actions,
  177. flag_groups = [
  178. flag_group(flags = ["-fPIC"], expand_if_available = "pic"),
  179. ],
  180. ),
  181. flag_set(
  182. actions = preprocessor_compile_actions,
  183. flag_groups = [
  184. flag_group(
  185. flags = [
  186. # Disable a warning and override builtin macros to
  187. # ensure a hermetic build.
  188. "-Wno-builtin-macro-redefined",
  189. "-D__DATE__=\"redacted\"",
  190. "-D__TIMESTAMP__=\"redacted\"",
  191. "-D__TIME__=\"redacted\"",
  192. # Pass the clang version as a define so that bazel
  193. # caching is more likely to notice version changes.
  194. "-DCLANG_VERSION_FOR_CACHE=\"%s\"" % clang_version_for_cache,
  195. ],
  196. ),
  197. flag_group(
  198. flags = ["-D%{preprocessor_defines}"],
  199. iterate_over = "preprocessor_defines",
  200. ),
  201. flag_group(
  202. flags = ["-include", "%{includes}"],
  203. iterate_over = "includes",
  204. expand_if_available = "includes",
  205. ),
  206. flag_group(
  207. flags = ["-iquote", "%{quote_include_paths}"],
  208. iterate_over = "quote_include_paths",
  209. ),
  210. flag_group(
  211. flags = ["-I%{include_paths}"],
  212. iterate_over = "include_paths",
  213. ),
  214. flag_group(
  215. flags = ["-isystem", "%{system_include_paths}"],
  216. iterate_over = "system_include_paths",
  217. ),
  218. ],
  219. ),
  220. flag_set(
  221. actions = [
  222. ACTION_NAMES.cpp_link_dynamic_library,
  223. ACTION_NAMES.cpp_link_nodeps_dynamic_library,
  224. ],
  225. flag_groups = [flag_group(flags = ["-shared"])],
  226. ),
  227. flag_set(
  228. actions = all_link_actions,
  229. flag_groups = [
  230. flag_group(
  231. flags = ["-Wl,--gdb-index"],
  232. expand_if_available = "is_using_fission",
  233. ),
  234. flag_group(
  235. flags = ["-Wl,-S"],
  236. expand_if_available = "strip_debug_symbols",
  237. ),
  238. flag_group(
  239. flags = ["-L%{library_search_directories}"],
  240. iterate_over = "library_search_directories",
  241. expand_if_available = "library_search_directories",
  242. ),
  243. flag_group(
  244. iterate_over = "runtime_library_search_directories",
  245. flags = [
  246. "-Wl,-rpath,$ORIGIN/%{runtime_library_search_directories}",
  247. ],
  248. expand_if_available =
  249. "runtime_library_search_directories",
  250. ),
  251. ],
  252. ),
  253. ],
  254. )
  255. # Handle different levels of optimization with individual features so that
  256. # they can be ordered and the defaults can override the minimal settings if
  257. # both are enabled.
  258. minimal_optimization_flags = feature(
  259. name = "minimal_optimization_flags",
  260. flag_sets = [
  261. flag_set(
  262. actions = codegen_compile_actions,
  263. flag_groups = [flag_group(flags = [
  264. "-O1",
  265. ])],
  266. ),
  267. ],
  268. )
  269. default_optimization_flags = feature(
  270. name = "default_optimization_flags",
  271. enabled = True,
  272. requires = [feature_set(["opt"])],
  273. flag_sets = [
  274. flag_set(
  275. actions = all_compile_actions,
  276. flag_groups = [flag_group(flags = [
  277. "-DNDEBUG",
  278. ])],
  279. ),
  280. flag_set(
  281. actions = codegen_compile_actions,
  282. flag_groups = [flag_group(flags = [
  283. "-O3",
  284. ])],
  285. ),
  286. ],
  287. )
  288. x86_64_cpu_flags = feature(
  289. name = "x86_64_cpu_flags",
  290. enabled = True,
  291. flag_sets = [
  292. flag_set(
  293. actions = all_compile_actions,
  294. flag_groups = [flag_group(flags = [
  295. "-march=x86-64-v2",
  296. ])],
  297. ),
  298. ],
  299. )
  300. aarch64_cpu_flags = feature(
  301. name = "aarch64_cpu_flags",
  302. enabled = True,
  303. flag_sets = [
  304. flag_set(
  305. actions = all_compile_actions,
  306. flag_groups = [flag_group(flags = [
  307. "-march=armv8.2-a",
  308. ])],
  309. ),
  310. ],
  311. )
  312. # Handle different levels and forms of debug info emission with individual
  313. # features so that they can be ordered and the defaults can override the
  314. # minimal settings if both are enabled.
  315. minimal_debug_info_flags = feature(
  316. name = "minimal_debug_info_flags",
  317. flag_sets = [
  318. flag_set(
  319. actions = codegen_compile_actions,
  320. flag_groups = [
  321. flag_group(
  322. flags = ["-gmlt"],
  323. ),
  324. ],
  325. ),
  326. ],
  327. )
  328. default_debug_info_flags = feature(
  329. name = "default_debug_info_flags",
  330. enabled = True,
  331. flag_sets = [
  332. flag_set(
  333. actions = codegen_compile_actions,
  334. flag_groups = ([
  335. flag_group(
  336. flags = ["-g"],
  337. ),
  338. ]),
  339. with_features = [with_feature_set(features = ["dbg"])],
  340. ),
  341. flag_set(
  342. actions = codegen_compile_actions,
  343. flag_groups = [
  344. flag_group(
  345. flags = ["-gsplit-dwarf", "-g"],
  346. expand_if_available = "per_object_debug_info_file",
  347. ),
  348. ],
  349. ),
  350. ],
  351. )
  352. # This feature can be enabled in conjunction with any optimizations to
  353. # ensure accurate call stacks and backtraces for profilers or errors.
  354. preserve_call_stacks = feature(
  355. name = "preserve_call_stacks",
  356. flag_sets = [flag_set(
  357. actions = codegen_compile_actions,
  358. flag_groups = [flag_group(flags = [
  359. # Ensure good backtraces by preserving frame pointers and
  360. # disabling tail call elimination.
  361. "-fno-omit-frame-pointer",
  362. "-mno-omit-leaf-frame-pointer",
  363. "-fno-optimize-sibling-calls",
  364. ])],
  365. )],
  366. )
  367. sysroot_feature = feature(
  368. name = "sysroot",
  369. enabled = True,
  370. flag_sets = [
  371. flag_set(
  372. actions = all_compile_actions + all_link_actions,
  373. flag_groups = [
  374. flag_group(
  375. flags = ["--sysroot=%{sysroot}"],
  376. expand_if_available = "sysroot",
  377. ),
  378. ],
  379. ),
  380. ],
  381. )
  382. use_module_maps = feature(
  383. name = "use_module_maps",
  384. requires = [feature_set(features = ["module_maps"])],
  385. flag_sets = [
  386. flag_set(
  387. actions = [
  388. ACTION_NAMES.c_compile,
  389. ACTION_NAMES.cpp_compile,
  390. ACTION_NAMES.cpp_header_parsing,
  391. ACTION_NAMES.cpp_module_compile,
  392. ],
  393. flag_groups = [
  394. # These flag groups are separate so they do not expand to
  395. # the cross product of the variables.
  396. flag_group(flags = ["-fmodule-name=%{module_name}"]),
  397. flag_group(
  398. flags = ["-fmodule-map-file=%{module_map_file}"],
  399. ),
  400. ],
  401. ),
  402. ],
  403. )
  404. # Tell bazel we support module maps in general, so they will be generated
  405. # for all c/c++ rules.
  406. # Note: not all C++ rules support module maps; thus, do not imply this
  407. # feature from other features - instead, require it.
  408. module_maps = feature(
  409. name = "module_maps",
  410. enabled = True,
  411. implies = [
  412. # "module_map_home_cwd",
  413. # "module_map_without_extern_module",
  414. # "generate_submodules",
  415. ],
  416. )
  417. layering_check = feature(
  418. name = "layering_check",
  419. implies = ["use_module_maps"],
  420. flag_sets = [
  421. flag_set(
  422. actions = [
  423. ACTION_NAMES.c_compile,
  424. ACTION_NAMES.cpp_compile,
  425. ACTION_NAMES.cpp_header_parsing,
  426. ACTION_NAMES.cpp_module_compile,
  427. ],
  428. flag_groups = [
  429. flag_group(flags = [
  430. "-fmodules-strict-decluse",
  431. "-Wprivate-header",
  432. ]),
  433. flag_group(
  434. iterate_over = "dependent_module_map_files",
  435. flags = [
  436. "-fmodule-map-file=%{dependent_module_map_files}",
  437. ],
  438. ),
  439. ],
  440. ),
  441. ],
  442. )
  443. sanitizer_common_flags = feature(
  444. name = "sanitizer_common_flags",
  445. requires = [feature_set(["nonhost"])],
  446. implies = ["minimal_optimization_flags", "minimal_debug_info_flags", "preserve_call_stacks"],
  447. )
  448. # Separated from the feature above so it can only be included on platforms
  449. # where it is supported. There is no negative flag in Clang so we can't just
  450. # override it later.
  451. sanitizer_static_lib_flags = feature(
  452. name = "sanitizer_static_lib_flags",
  453. enabled = True,
  454. requires = [feature_set(["sanitizer_common_flags"])],
  455. flag_sets = [flag_set(
  456. actions = all_link_actions,
  457. flag_groups = [flag_group(flags = [
  458. "-static-libsan",
  459. ])],
  460. )],
  461. )
  462. asan = feature(
  463. name = "asan",
  464. requires = [feature_set(["nonhost"])],
  465. implies = ["sanitizer_common_flags"],
  466. flag_sets = [flag_set(
  467. actions = all_compile_actions + all_link_actions,
  468. flag_groups = [flag_group(flags = [
  469. "-fsanitize=address,undefined,nullability",
  470. "-fsanitize-address-use-after-scope",
  471. # We don't need the recovery behavior of UBSan as we expect
  472. # builds to be clean. Not recovering is a bit cheaper.
  473. "-fno-sanitize-recover=undefined",
  474. # Don't embed the full path name for files. This limits the size
  475. # and combined with line numbers is unlikely to result in many
  476. # ambiguities.
  477. "-fsanitize-undefined-strip-path-components=-1",
  478. # Needed due to clang AST issues, such as in
  479. # clang/AST/Redeclarable.h line 199.
  480. "-fno-sanitize=vptr",
  481. ])],
  482. )],
  483. )
  484. # Likely due to being unable to use the static-linked and up-to-date
  485. # sanitizer runtimes, we have to disable a number of sanitizers on macOS.
  486. macos_asan_workarounds = feature(
  487. name = "macos_sanitizer_workarounds",
  488. enabled = True,
  489. requires = [feature_set(["asan"])],
  490. flag_sets = [flag_set(
  491. actions = all_compile_actions + all_link_actions,
  492. flag_groups = [flag_group(flags = [
  493. "-fno-sanitize=function",
  494. ])],
  495. )],
  496. )
  497. enable_asan_in_fastbuild = feature(
  498. name = "enable_asan_in_fastbuild",
  499. enabled = True,
  500. requires = [feature_set(["nonhost", "fastbuild"])],
  501. implies = ["asan"],
  502. )
  503. fuzzer = feature(
  504. name = "fuzzer",
  505. requires = [feature_set(["nonhost"])],
  506. implies = ["asan"],
  507. flag_sets = [flag_set(
  508. actions = all_compile_actions + all_link_actions,
  509. flag_groups = [flag_group(flags = [
  510. "-fsanitize=fuzzer-no-link",
  511. ])],
  512. )],
  513. )
  514. # With clang 14 and lower, we expect it to be built with libc++ debug
  515. # support. In later LLVM versions, we expect the assertions define to work.
  516. # clang 17 deprecates LIBCPP_ENABLE_ASSERTIONS in favor of HARDENED_MODE.
  517. if clang_version and clang_version <= 14:
  518. libcpp_debug_flags = ["-D_LIBCPP_DEBUG=1"]
  519. elif clang_version and clang_version <= 16:
  520. libcpp_debug_flags = ["-D_LIBCPP_ENABLE_ASSERTIONS=1"]
  521. else:
  522. libcpp_debug_flags = ["-D_LIBCPP_ENABLE_HARDENED_MODE=1"]
  523. linux_flags_feature = feature(
  524. name = "linux_flags",
  525. enabled = True,
  526. flag_sets = [
  527. flag_set(
  528. actions = all_link_actions,
  529. flag_groups = ([
  530. flag_group(
  531. flags = [
  532. "-fuse-ld=lld",
  533. "-stdlib=libc++",
  534. "-unwindlib=libunwind",
  535. # Force the C++ standard library and runtime
  536. # libraries to be statically linked. This works even
  537. # with libc++ and libunwind despite the names,
  538. # provided libc++ is built with two CMake options:
  539. # - `-DCMAKE_POSITION_INDEPENDENT_CODE=ON`
  540. # - `-DLIBCXX_STATICALLY_LINK_ABI_IN_STATIC_LIBRARY`
  541. # These are both required because of PR43604
  542. # (impacting at least Debian packages of libc++) and
  543. # PR46321 (impacting most other packages).
  544. # We recommend using Homebrew's LLVM install on
  545. # Linux.
  546. "-static-libstdc++",
  547. "-static-libgcc",
  548. # Link with Clang's runtime library. This is always
  549. # linked statically.
  550. "-rtlib=compiler-rt",
  551. # Explicitly add LLVM libs to the search path to
  552. # preempt the detected GCC installation's library
  553. # paths. Those might have a system installed libc++
  554. # and we want to find the one next to our Clang.
  555. "-L" + llvm_bindir + "/../lib",
  556. # Link with pthread.
  557. "-lpthread",
  558. ],
  559. ),
  560. ]),
  561. ),
  562. flag_set(
  563. actions = all_compile_actions,
  564. flag_groups = [flag_group(flags = libcpp_debug_flags)],
  565. with_features = [
  566. with_feature_set(not_features = ["opt"]),
  567. ],
  568. ),
  569. flag_set(
  570. actions = [
  571. ACTION_NAMES.cpp_link_executable,
  572. ],
  573. flag_groups = [
  574. flag_group(
  575. flags = ["-pie"],
  576. expand_if_available = "force_pic",
  577. ),
  578. ],
  579. ),
  580. ],
  581. )
  582. macos_flags_feature = feature(
  583. name = "macos_flags",
  584. enabled = True,
  585. flag_sets = [
  586. flag_set(
  587. actions = [
  588. ACTION_NAMES.cpp_link_executable,
  589. ],
  590. flag_groups = [
  591. flag_group(
  592. flags = ["-fpie"],
  593. expand_if_available = "force_pic",
  594. ),
  595. ],
  596. ),
  597. ],
  598. )
  599. freebsd_flags_feature = feature(
  600. name = "freebsd_flags",
  601. enabled = True,
  602. flag_sets = [
  603. flag_set(
  604. actions = [
  605. ACTION_NAMES.c_compile,
  606. ACTION_NAMES.cpp_compile,
  607. ACTION_NAMES.cpp_header_parsing,
  608. ACTION_NAMES.cpp_module_compile,
  609. ],
  610. flag_groups = [
  611. flag_group(
  612. flags = [
  613. "-DHAVE_MALLCTL",
  614. ],
  615. ),
  616. ],
  617. ),
  618. flag_set(
  619. actions = [
  620. ACTION_NAMES.cpp_link_executable,
  621. ],
  622. flag_groups = [
  623. flag_group(
  624. flags = ["-fpie"],
  625. expand_if_available = "force_pic",
  626. ),
  627. ],
  628. ),
  629. ],
  630. )
  631. default_link_libraries_feature = feature(
  632. name = "default_link_libraries",
  633. enabled = True,
  634. flag_sets = [
  635. flag_set(
  636. actions = all_link_actions,
  637. flag_groups = [
  638. flag_group(
  639. flags = ["%{linkstamp_paths}"],
  640. iterate_over = "linkstamp_paths",
  641. expand_if_available = "linkstamp_paths",
  642. ),
  643. flag_group(
  644. iterate_over = "libraries_to_link",
  645. flag_groups = [
  646. flag_group(
  647. flags = ["-Wl,--start-lib"],
  648. expand_if_equal = variable_with_value(
  649. name = "libraries_to_link.type",
  650. value = "object_file_group",
  651. ),
  652. ),
  653. flag_group(
  654. flags = ["-Wl,-whole-archive"],
  655. expand_if_true = "libraries_to_link.is_whole_archive",
  656. ),
  657. flag_group(
  658. flags = ["%{libraries_to_link.object_files}"],
  659. iterate_over = "libraries_to_link.object_files",
  660. expand_if_equal = variable_with_value(
  661. name = "libraries_to_link.type",
  662. value = "object_file_group",
  663. ),
  664. ),
  665. flag_group(
  666. flags = ["%{libraries_to_link.name}"],
  667. expand_if_equal = variable_with_value(
  668. name = "libraries_to_link.type",
  669. value = "object_file",
  670. ),
  671. ),
  672. flag_group(
  673. flags = ["%{libraries_to_link.name}"],
  674. expand_if_equal = variable_with_value(
  675. name = "libraries_to_link.type",
  676. value = "interface_library",
  677. ),
  678. ),
  679. flag_group(
  680. flags = ["%{libraries_to_link.name}"],
  681. expand_if_equal = variable_with_value(
  682. name = "libraries_to_link.type",
  683. value = "static_library",
  684. ),
  685. ),
  686. flag_group(
  687. flags = ["-l%{libraries_to_link.name}"],
  688. expand_if_equal = variable_with_value(
  689. name = "libraries_to_link.type",
  690. value = "dynamic_library",
  691. ),
  692. ),
  693. flag_group(
  694. flags = ["-l:%{libraries_to_link.name}"],
  695. expand_if_equal = variable_with_value(
  696. name = "libraries_to_link.type",
  697. value = "versioned_dynamic_library",
  698. ),
  699. ),
  700. flag_group(
  701. flags = ["-Wl,-no-whole-archive"],
  702. expand_if_true = "libraries_to_link.is_whole_archive",
  703. ),
  704. flag_group(
  705. flags = ["-Wl,--end-lib"],
  706. expand_if_equal = variable_with_value(
  707. name = "libraries_to_link.type",
  708. value = "object_file_group",
  709. ),
  710. ),
  711. ],
  712. expand_if_available = "libraries_to_link",
  713. ),
  714. # Note that the params file comes at the end, after the
  715. # libraries to link above.
  716. flag_group(
  717. expand_if_available = "linker_param_file",
  718. flags = ["@%{linker_param_file}"],
  719. ),
  720. ],
  721. ),
  722. ],
  723. )
  724. macos_link_libraries_feature = feature(
  725. name = "macos_link_libraries",
  726. enabled = True,
  727. flag_sets = [
  728. flag_set(
  729. actions = all_link_actions,
  730. flag_groups = [
  731. flag_group(
  732. flags = ["%{linkstamp_paths}"],
  733. iterate_over = "linkstamp_paths",
  734. expand_if_available = "linkstamp_paths",
  735. ),
  736. flag_group(
  737. iterate_over = "libraries_to_link",
  738. flag_groups = [
  739. flag_group(
  740. flags = ["-Wl,--start-lib"],
  741. expand_if_equal = variable_with_value(
  742. name = "libraries_to_link.type",
  743. value = "object_file_group",
  744. ),
  745. ),
  746. flag_group(
  747. iterate_over = "libraries_to_link.object_files",
  748. expand_if_equal = variable_with_value(
  749. name = "libraries_to_link.type",
  750. value = "object_file_group",
  751. ),
  752. flag_groups = [
  753. flag_group(
  754. flags = ["%{libraries_to_link.object_files}"],
  755. expand_if_false = "libraries_to_link.is_whole_archive",
  756. ),
  757. flag_group(
  758. flags = ["-Wl,-force_load,%{libraries_to_link.object_files}"],
  759. expand_if_true = "libraries_to_link.is_whole_archive",
  760. ),
  761. ],
  762. ),
  763. flag_group(
  764. expand_if_equal = variable_with_value(
  765. name = "libraries_to_link.type",
  766. value = "object_file",
  767. ),
  768. flag_groups = [
  769. flag_group(
  770. flags = ["%{libraries_to_link.name}"],
  771. expand_if_false = "libraries_to_link.is_whole_archive",
  772. ),
  773. flag_group(
  774. flags = ["-Wl,-force_load,%{libraries_to_link.name}"],
  775. expand_if_true = "libraries_to_link.is_whole_archive",
  776. ),
  777. ],
  778. ),
  779. flag_group(
  780. expand_if_equal = variable_with_value(
  781. name = "libraries_to_link.type",
  782. value = "interface_library",
  783. ),
  784. flag_groups = [
  785. flag_group(
  786. flags = ["%{libraries_to_link.name}"],
  787. expand_if_false = "libraries_to_link.is_whole_archive",
  788. ),
  789. flag_group(
  790. flags = ["-Wl,-force_load,%{libraries_to_link.name}"],
  791. expand_if_true = "libraries_to_link.is_whole_archive",
  792. ),
  793. ],
  794. ),
  795. flag_group(
  796. expand_if_equal = variable_with_value(
  797. name = "libraries_to_link.type",
  798. value = "static_library",
  799. ),
  800. flag_groups = [
  801. flag_group(
  802. flags = ["%{libraries_to_link.name}"],
  803. expand_if_false = "libraries_to_link.is_whole_archive",
  804. ),
  805. flag_group(
  806. flags = ["-Wl,-force_load,%{libraries_to_link.name}"],
  807. expand_if_true = "libraries_to_link.is_whole_archive",
  808. ),
  809. ],
  810. ),
  811. flag_group(
  812. flags = ["-l%{libraries_to_link.name}"],
  813. expand_if_equal = variable_with_value(
  814. name = "libraries_to_link.type",
  815. value = "dynamic_library",
  816. ),
  817. ),
  818. flag_group(
  819. flags = ["-l:%{libraries_to_link.name}"],
  820. expand_if_equal = variable_with_value(
  821. name = "libraries_to_link.type",
  822. value = "versioned_dynamic_library",
  823. ),
  824. ),
  825. flag_group(
  826. expand_if_true = "libraries_to_link.is_whole_archive",
  827. flag_groups = [
  828. flag_group(
  829. expand_if_false = "macos_flags",
  830. flags = ["-Wl,-no-whole-archive"],
  831. ),
  832. ],
  833. ),
  834. flag_group(
  835. flags = ["-Wl,--end-lib"],
  836. expand_if_equal = variable_with_value(
  837. name = "libraries_to_link.type",
  838. value = "object_file_group",
  839. ),
  840. ),
  841. ],
  842. expand_if_available = "libraries_to_link",
  843. ),
  844. # Note that the params file comes at the end, after the
  845. # libraries to link above.
  846. flag_group(
  847. expand_if_available = "linker_param_file",
  848. flags = ["@%{linker_param_file}"],
  849. ),
  850. ],
  851. ),
  852. ],
  853. )
  854. # Place user provided compile flags after all the features so that these
  855. # flags can override or customize behavior. The only thing user flags
  856. # cannot override is the output file as Bazel depends on that.
  857. #
  858. # Finally, place the source file (if present) and output file last to make
  859. # reading the compile command lines easier for humans.
  860. final_flags_feature = feature(
  861. name = "final_flags",
  862. enabled = True,
  863. flag_sets = [
  864. flag_set(
  865. actions = all_compile_actions,
  866. flag_groups = [
  867. flag_group(
  868. flags = ["%{user_compile_flags}"],
  869. iterate_over = "user_compile_flags",
  870. expand_if_available = "user_compile_flags",
  871. ),
  872. flag_group(
  873. flags = ["%{source_file}"],
  874. expand_if_available = "source_file",
  875. ),
  876. flag_group(
  877. expand_if_available = "output_file",
  878. flags = ["-o", "%{output_file}"],
  879. ),
  880. ],
  881. ),
  882. flag_set(
  883. actions = all_link_actions,
  884. flag_groups = [
  885. flag_group(
  886. flags = ["%{user_link_flags}"],
  887. iterate_over = "user_link_flags",
  888. expand_if_available = "user_link_flags",
  889. ),
  890. flag_group(
  891. flags = ["-o", "%{output_execpath}"],
  892. expand_if_available = "output_execpath",
  893. ),
  894. ],
  895. ),
  896. ],
  897. )
  898. # Archive actions have an entirely independent set of flags and don't
  899. # interact with either compiler or link actions.
  900. default_archiver_flags_feature = feature(
  901. name = "default_archiver_flags",
  902. enabled = True,
  903. flag_sets = [
  904. flag_set(
  905. actions = [ACTION_NAMES.cpp_link_static_library],
  906. flag_groups = [
  907. flag_group(flags = ["rcsD"]),
  908. flag_group(
  909. flags = ["%{output_execpath}"],
  910. expand_if_available = "output_execpath",
  911. ),
  912. flag_group(
  913. iterate_over = "libraries_to_link",
  914. flag_groups = [
  915. flag_group(
  916. flags = ["%{libraries_to_link.name}"],
  917. expand_if_equal = variable_with_value(
  918. name = "libraries_to_link.type",
  919. value = "object_file",
  920. ),
  921. ),
  922. flag_group(
  923. flags = ["%{libraries_to_link.object_files}"],
  924. iterate_over = "libraries_to_link.object_files",
  925. expand_if_equal = variable_with_value(
  926. name = "libraries_to_link.type",
  927. value = "object_file_group",
  928. ),
  929. ),
  930. ],
  931. expand_if_available = "libraries_to_link",
  932. ),
  933. flag_group(
  934. expand_if_available = "linker_param_file",
  935. flags = ["@%{linker_param_file}"],
  936. ),
  937. ],
  938. ),
  939. ],
  940. )
  941. # Now that we have built up the constituent feature definitions, compose
  942. # them, including configuration based on the target platform.
  943. # First, define features that are simply used to configure others.
  944. features = [
  945. feature(name = "dbg"),
  946. feature(name = "fastbuild"),
  947. feature(name = "host"),
  948. feature(name = "no_legacy_features"),
  949. feature(name = "nonhost"),
  950. feature(name = "opt"),
  951. feature(name = "supports_dynamic_linker", enabled = ctx.attr.target_os == "linux"),
  952. feature(name = "supports_pic", enabled = True),
  953. feature(name = "supports_start_end_lib", enabled = ctx.attr.target_os == "linux"),
  954. ]
  955. # The order of the features determines the relative order of flags used.
  956. # Start off adding the baseline features.
  957. features += [
  958. default_flags_feature,
  959. minimal_optimization_flags,
  960. default_optimization_flags,
  961. minimal_debug_info_flags,
  962. default_debug_info_flags,
  963. preserve_call_stacks,
  964. sysroot_feature,
  965. sanitizer_common_flags,
  966. asan,
  967. enable_asan_in_fastbuild,
  968. fuzzer,
  969. layering_check,
  970. module_maps,
  971. use_module_maps,
  972. default_archiver_flags_feature,
  973. ]
  974. # Next, add the features based on the target platform. Here too the
  975. # features are order sensitive. We also setup the sysroot here.
  976. if ctx.attr.target_os == "linux":
  977. features.append(sanitizer_static_lib_flags)
  978. features.append(linux_flags_feature)
  979. sysroot = None
  980. elif ctx.attr.target_os == "windows":
  981. # TODO: Need to figure out if we need to add windows specific features
  982. # I think the .pdb debug files will need to be handled differently,
  983. # so that might be an example where a feature must be added.
  984. sysroot = None
  985. elif ctx.attr.target_os == "macos":
  986. features.append(macos_asan_workarounds)
  987. features.append(macos_flags_feature)
  988. sysroot = sysroot_dir
  989. elif ctx.attr.target_os == "freebsd":
  990. features.append(sanitizer_static_lib_flags)
  991. features.append(freebsd_flags_feature)
  992. sysroot = sysroot_dir
  993. else:
  994. fail("Unsupported target OS!")
  995. if ctx.attr.target_cpu in ["aarch64", "arm64"]:
  996. features.append(aarch64_cpu_flags)
  997. else:
  998. features.append(x86_64_cpu_flags)
  999. # Finally append the libraries to link and any final flags.
  1000. if ctx.attr.target_os == "macos":
  1001. features.append(macos_link_libraries_feature)
  1002. else:
  1003. features.append(default_link_libraries_feature)
  1004. features.append(final_flags_feature)
  1005. identifier = "local-{0}-{1}".format(ctx.attr.target_cpu, ctx.attr.target_os)
  1006. return cc_common.create_cc_toolchain_config_info(
  1007. ctx = ctx,
  1008. features = features,
  1009. action_configs = action_configs,
  1010. cxx_builtin_include_directories = clang_include_dirs_list + [
  1011. # Add Clang's resource directory to the end of the builtin include
  1012. # directories to cover the use of sanitizer resource files by the driver.
  1013. clang_resource_dir + "/share",
  1014. ],
  1015. builtin_sysroot = sysroot,
  1016. # This configuration only supports local non-cross builds so derive
  1017. # everything from the target CPU selected.
  1018. toolchain_identifier = identifier,
  1019. host_system_name = identifier,
  1020. target_system_name = identifier,
  1021. target_cpu = ctx.attr.target_cpu,
  1022. # These attributes aren't meaningful at all so just use placeholder
  1023. # values.
  1024. target_libc = "local",
  1025. compiler = "local",
  1026. abi_version = "local",
  1027. abi_libc_version = "local",
  1028. # We do have to pass in our tool paths.
  1029. tool_paths = tool_paths,
  1030. )
  1031. cc_toolchain_config = rule(
  1032. implementation = _impl,
  1033. attrs = {
  1034. "target_cpu": attr.string(mandatory = True),
  1035. "target_os": attr.string(mandatory = True),
  1036. },
  1037. provides = [CcToolchainConfigInfo],
  1038. )
  1039. def cc_local_toolchain_suite(name, configs):
  1040. """Create a toolchain suite that uses the local Clang/LLVM install.
  1041. Args:
  1042. name: The name of the toolchain suite to produce.
  1043. configs: An array of (os, cpu) pairs to support in the toolchain.
  1044. """
  1045. # An empty filegroup to use when stubbing out the toolchains.
  1046. native.filegroup(
  1047. name = name + "_empty",
  1048. srcs = [],
  1049. )
  1050. # Create the individual local toolchains for each CPU.
  1051. for (os, cpu) in configs:
  1052. config_name = "{0}_{1}_{2}".format(name, os, cpu)
  1053. cc_toolchain_config(
  1054. name = config_name + "_config",
  1055. target_os = os,
  1056. target_cpu = cpu,
  1057. )
  1058. cc_toolchain(
  1059. name = config_name + "_tools",
  1060. all_files = ":" + name + "_empty",
  1061. ar_files = ":" + name + "_empty",
  1062. as_files = ":" + name + "_empty",
  1063. compiler_files = ":" + name + "_empty",
  1064. dwp_files = ":" + name + "_empty",
  1065. linker_files = ":" + name + "_empty",
  1066. objcopy_files = ":" + name + "_empty",
  1067. strip_files = ":" + name + "_empty",
  1068. supports_param_files = 1,
  1069. toolchain_config = ":" + config_name + "_config",
  1070. toolchain_identifier = config_name,
  1071. )
  1072. compatible_with = ["@platforms//cpu:" + cpu, "@platforms//os:" + os]
  1073. native.toolchain(
  1074. name = config_name,
  1075. exec_compatible_with = compatible_with,
  1076. target_compatible_with = compatible_with,
  1077. toolchain = config_name + "_tools",
  1078. toolchain_type = "@bazel_tools//tools/cpp:toolchain_type",
  1079. )