cc_toolchain_cpp_features.bzl 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  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. """Definitions of general C++ `cc_toolchain_config` features."""
  5. load("@rules_cc//cc:action_names.bzl", "ACTION_NAMES")
  6. load(
  7. "@rules_cc//cc:cc_toolchain_config_lib.bzl",
  8. "feature",
  9. "flag_group",
  10. "flag_set",
  11. "with_feature_set",
  12. )
  13. load(
  14. ":cc_toolchain_actions.bzl",
  15. "all_compile_actions",
  16. "all_cpp_compile_actions",
  17. "all_link_actions",
  18. "codegen_compile_actions",
  19. "preprocessor_compile_actions",
  20. )
  21. clang_feature = feature(
  22. name = "clang",
  23. enabled = True,
  24. flag_sets = [
  25. flag_set(
  26. actions = all_compile_actions + all_link_actions,
  27. flag_groups = [
  28. flag_group(flags = [
  29. "-no-canonical-prefixes",
  30. "-fcolor-diagnostics",
  31. ]),
  32. flag_group(
  33. expand_if_available = "sysroot",
  34. flags = ["--sysroot=%{sysroot}"],
  35. ),
  36. ],
  37. ),
  38. flag_set(
  39. actions = all_compile_actions,
  40. flag_groups = [
  41. flag_group(flags = [
  42. # Compile actions shouldn't link anything.
  43. "-c",
  44. ]),
  45. # Flags controlling the production of specific outputs from
  46. # compile actions.
  47. flag_group(
  48. expand_if_available = "output_assembly_file",
  49. flags = ["-S"],
  50. ),
  51. flag_group(
  52. expand_if_available = "output_preprocess_file",
  53. flags = ["-E"],
  54. ),
  55. flag_group(
  56. expand_if_available = "dependency_file",
  57. flags = ["-MD", "-MF", "%{dependency_file}"],
  58. ),
  59. flag_group(
  60. expand_if_available = "output_file",
  61. flags = ["-frandom-seed=%{output_file}"],
  62. ),
  63. ],
  64. ),
  65. flag_set(
  66. # Flags specific to compiling C++ sources.
  67. actions = all_cpp_compile_actions,
  68. flag_groups = [flag_group(flags = [
  69. "-std=c++20",
  70. ])],
  71. ),
  72. flag_set(
  73. actions = codegen_compile_actions,
  74. flag_groups = [flag_group(flags = [
  75. "-ffunction-sections",
  76. "-fdata-sections",
  77. ])],
  78. ),
  79. flag_set(
  80. actions = codegen_compile_actions,
  81. flag_groups = [flag_group(
  82. expand_if_available = "pic",
  83. flags = ["-fPIC"],
  84. )],
  85. ),
  86. flag_set(
  87. actions = preprocessor_compile_actions,
  88. flag_groups = [
  89. flag_group(flags = [
  90. # Disable a warning and override builtin macros to
  91. # ensure a hermetic build.
  92. "-Wno-builtin-macro-redefined",
  93. "-D__DATE__=\"redacted\"",
  94. "-D__TIMESTAMP__=\"redacted\"",
  95. "-D__TIME__=\"redacted\"",
  96. ]),
  97. flag_group(
  98. flags = ["-D%{preprocessor_defines}"],
  99. iterate_over = "preprocessor_defines",
  100. ),
  101. flag_group(
  102. expand_if_available = "includes",
  103. flags = ["-include", "%{includes}"],
  104. iterate_over = "includes",
  105. ),
  106. flag_group(
  107. flags = ["-iquote", "%{quote_include_paths}"],
  108. iterate_over = "quote_include_paths",
  109. ),
  110. flag_group(
  111. flags = ["-I%{include_paths}"],
  112. iterate_over = "include_paths",
  113. ),
  114. flag_group(
  115. flags = ["-isystem", "%{system_include_paths}"],
  116. iterate_over = "system_include_paths",
  117. ),
  118. ],
  119. ),
  120. flag_set(
  121. actions = [
  122. ACTION_NAMES.cpp_link_dynamic_library,
  123. ACTION_NAMES.cpp_link_nodeps_dynamic_library,
  124. ],
  125. flag_groups = [flag_group(flags = ["-shared"])],
  126. ),
  127. flag_set(
  128. actions = all_link_actions,
  129. flag_groups = [
  130. flag_group(
  131. expand_if_available = "strip_debug_symbols",
  132. flags = ["-Wl,-S"],
  133. ),
  134. flag_group(
  135. expand_if_available = "library_search_directories",
  136. flags = ["-L%{library_search_directories}"],
  137. iterate_over = "library_search_directories",
  138. ),
  139. flag_group(
  140. expand_if_available =
  141. "runtime_library_search_directories",
  142. iterate_over = "runtime_library_search_directories",
  143. flags = [
  144. "-Wl,-rpath,$ORIGIN/%{runtime_library_search_directories}",
  145. ],
  146. ),
  147. ],
  148. ),
  149. flag_set(
  150. actions = all_link_actions,
  151. flag_groups = [
  152. flag_group(
  153. flags = [
  154. "-fuse-ld=lld",
  155. # Force the C++ standard library and runtime libraries
  156. # to be statically linked. This works even with libc++
  157. # and libunwind despite the names, provided libc++ is
  158. # built with the CMake option:
  159. # - `-DCMAKE_POSITION_INDEPENDENT_CODE=ON`
  160. "-static-libstdc++",
  161. "-static-libgcc",
  162. # Link with Clang's runtime library. This is always
  163. # linked statically.
  164. "-rtlib=compiler-rt",
  165. # Link with pthread.
  166. "-lpthread",
  167. ],
  168. ),
  169. ],
  170. with_features = [with_feature_set(["linux_target"])],
  171. ),
  172. flag_set(
  173. actions = [ACTION_NAMES.cpp_link_executable],
  174. flag_groups = [flag_group(
  175. expand_if_available = "force_pic",
  176. flags = ["-pie"],
  177. )],
  178. with_features = [with_feature_set([
  179. "linux_target",
  180. "freebsd_target",
  181. ])],
  182. ),
  183. flag_set(
  184. actions = [ACTION_NAMES.cpp_link_executable],
  185. flag_groups = [flag_group(
  186. expand_if_available = "force_pic",
  187. flags = ["-fpie"],
  188. )],
  189. with_features = [with_feature_set(["macos_target"])],
  190. ),
  191. ],
  192. )
  193. clang_warnings_feature = feature(
  194. name = "clang_warnings",
  195. enabled = True,
  196. flag_sets = [flag_set(
  197. actions = all_compile_actions,
  198. flag_groups = [flag_group(flags = [
  199. "-Werror",
  200. "-Wall",
  201. "-Wextra",
  202. "-Wthread-safety",
  203. "-Wself-assign",
  204. "-Wimplicit-fallthrough",
  205. "-Wctad-maybe-unsupported",
  206. "-Wextra-semi",
  207. "-Wmissing-prototypes",
  208. "-Wzero-as-null-pointer-constant",
  209. "-Wdelete-non-virtual-dtor",
  210. # TODO: Regression that warns on anonymous unions; remove depending
  211. # on fix.
  212. "-Wno-missing-designated-field-initializers",
  213. ])],
  214. )],
  215. )
  216. # Libc++ HARDENING_MODE has 4 possible values:
  217. # https://libcxx.llvm.org/Hardening.html#notes-for-users
  218. #
  219. # Do not enable DEBUG hardening mode, even for -c dbg, because its performance
  220. # impact on llvm-symbolizer is too severe -- this flag results in symbolization
  221. # becoming quadratic in the number of debug symbols, in practice meaning it
  222. # never completes.
  223. _libcpp_debug_flags = [
  224. "-D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_EXTENSIVE",
  225. ]
  226. _libcpp_release_flags = [
  227. "-D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_FAST",
  228. ]
  229. def libcxx_feature(llvm_bindir = None, clang_bindir = None):
  230. """Builds a libc++ feature.
  231. Returns:
  232. The feature for use with `cc_toolchain_config`.
  233. Args:
  234. llvm_bindir: Optional LLVM installation `bin` directory, causes the
  235. feature to look for adjacent installed libraries.
  236. clang_bindir: Optional Clang installation `bin` directory, causes the
  237. feature to look for adjacent installed libraries if different from
  238. `llvm_bindir`.
  239. """
  240. # Explicitly add LLVM libs to the search path to preempt the
  241. # detected GCC installation's library paths. Those might have a
  242. # system installed libc++ and we want to find the one next to
  243. # our Clang.
  244. extra_link_flags = []
  245. if llvm_bindir:
  246. extra_link_flags.append("-L" + llvm_bindir + "/../lib")
  247. if clang_bindir and clang_bindir != llvm_bindir:
  248. extra_link_flags.append("-L" + clang_bindir + "/../lib")
  249. return feature(
  250. name = "libcxx",
  251. enabled = True,
  252. flag_sets = [
  253. flag_set(
  254. actions = all_cpp_compile_actions + all_link_actions,
  255. flag_groups = [flag_group(flags = [
  256. "-stdlib=libc++",
  257. ])],
  258. with_features = [
  259. # libc++ is only used on non-Windows platforms.
  260. with_feature_set(not_features = ["windows_target"]),
  261. ],
  262. ),
  263. flag_set(
  264. actions = all_cpp_compile_actions,
  265. flag_groups = [flag_group(flags = _libcpp_debug_flags)],
  266. with_features = [with_feature_set(not_features = ["opt"])],
  267. ),
  268. flag_set(
  269. actions = all_cpp_compile_actions,
  270. flag_groups = [flag_group(flags = _libcpp_release_flags)],
  271. with_features = [with_feature_set(features = ["opt"])],
  272. ),
  273. flag_set(
  274. actions = all_link_actions,
  275. flag_groups = [flag_group(flags = [
  276. "-unwindlib=libunwind",
  277. ])],
  278. with_features = [
  279. # libc++ is only used on non-Windows platforms.
  280. with_feature_set(not_features = ["windows_target"]),
  281. ],
  282. ),
  283. flag_set(
  284. actions = all_link_actions,
  285. flag_groups = [flag_group(flags = extra_link_flags + [
  286. # Force linking the static libc++abi archive here. This
  287. # *should* be linked automatically, but not every release of
  288. # LLVM correctly sets the CMake flags to do so.
  289. "-l:libc++abi.a",
  290. ])],
  291. with_features = [with_feature_set(["linux_target"])],
  292. ),
  293. ],
  294. )