cc_toolchain_cpp_features.bzl 11 KB

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