stl.go 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. // Copyright 2016 Google Inc. All rights reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package cc
  15. import (
  16. "fmt"
  17. "android/soong/android"
  18. )
  19. func getNdkStlFamily(m LinkableInterface) string {
  20. family, _ := getNdkStlFamilyAndLinkType(m)
  21. return family
  22. }
  23. func deduplicateStlInput(stl string) string {
  24. switch stl {
  25. case "c++_shared":
  26. return "libc++"
  27. case "c++_static":
  28. return "libc++_static"
  29. }
  30. return stl
  31. }
  32. func getNdkStlFamilyAndLinkType(m LinkableInterface) (string, string) {
  33. stl := m.SelectedStl()
  34. switch stl {
  35. case "ndk_libc++_shared", "libc++":
  36. return "libc++", "shared"
  37. case "ndk_libc++_static", "libc++_static":
  38. return "libc++", "static"
  39. case "ndk_system":
  40. return "system", "shared"
  41. case "":
  42. return "none", "none"
  43. default:
  44. panic(fmt.Errorf("stl: %q is not a valid STL", stl))
  45. }
  46. }
  47. type StlProperties struct {
  48. // Select the STL library to use. Possible values are "libc++",
  49. // "libc++_static", "libstdc++", or "none". Leave blank to select the
  50. // default.
  51. Stl *string `android:"arch_variant"`
  52. SelectedStl string `blueprint:"mutated"`
  53. }
  54. type stl struct {
  55. Properties StlProperties
  56. }
  57. func (stl *stl) props() []interface{} {
  58. return []interface{}{&stl.Properties}
  59. }
  60. func (stl *stl) begin(ctx BaseModuleContext) {
  61. stl.Properties.SelectedStl = func() string {
  62. s := ""
  63. if stl.Properties.Stl != nil {
  64. s = *stl.Properties.Stl
  65. } else if ctx.header() {
  66. s = "none"
  67. }
  68. if s == "none" {
  69. return ""
  70. }
  71. s = deduplicateStlInput(s)
  72. archHasNDKStl := ctx.Arch().ArchType != android.Riscv64
  73. if ctx.useSdk() && ctx.Device() && archHasNDKStl {
  74. switch s {
  75. case "", "system":
  76. return "ndk_system"
  77. case "libc++":
  78. return "ndk_libc++_shared"
  79. case "libc++_static":
  80. return "ndk_libc++_static"
  81. default:
  82. ctx.ModuleErrorf("stl: %q is not a supported STL with sdk_version set", s)
  83. return ""
  84. }
  85. } else if ctx.Windows() {
  86. switch s {
  87. case "libc++", "libc++_static", "":
  88. // Only use static libc++ for Windows.
  89. return "libc++_static"
  90. default:
  91. ctx.ModuleErrorf("stl: %q is not a supported STL for windows", s)
  92. return ""
  93. }
  94. } else {
  95. switch s {
  96. case "libc++", "libc++_static":
  97. return s
  98. case "", "system":
  99. if ctx.static() {
  100. return "libc++_static"
  101. } else {
  102. return "libc++"
  103. }
  104. default:
  105. ctx.ModuleErrorf("stl: %q is not a supported STL", s)
  106. return ""
  107. }
  108. }
  109. }()
  110. }
  111. func needsLibAndroidSupport(ctx BaseModuleContext) bool {
  112. version := nativeApiLevelOrPanic(ctx, ctx.sdkVersion())
  113. return version.LessThan(android.FirstNonLibAndroidSupportVersion)
  114. }
  115. func staticUnwinder(ctx android.BaseModuleContext) string {
  116. vndkVersion := ctx.Module().(*Module).VndkVersion()
  117. // Modules using R vndk use different unwinder
  118. if vndkVersion == "30" {
  119. if ctx.Arch().ArchType == android.Arm {
  120. return "libunwind_llvm"
  121. } else {
  122. return "libgcc_stripped"
  123. }
  124. }
  125. return "libunwind"
  126. }
  127. // Should be kept up to date with
  128. // https://cs.android.com/android/platform/superproject/+/master:build/bazel/rules/cc/stl.bzl;l=46;drc=21771b671ae08565033768a6d3d151c54f887fa2
  129. func (stl *stl) deps(ctx BaseModuleContext, deps Deps) Deps {
  130. switch stl.Properties.SelectedStl {
  131. case "libstdc++":
  132. // Nothing
  133. case "libc++", "libc++_static":
  134. if stl.Properties.SelectedStl == "libc++" {
  135. deps.SharedLibs = append(deps.SharedLibs, stl.Properties.SelectedStl)
  136. } else {
  137. deps.StaticLibs = append(deps.StaticLibs, stl.Properties.SelectedStl)
  138. }
  139. if ctx.Device() && !ctx.useSdk() {
  140. // __cxa_demangle is not a part of libc++.so on the device since
  141. // it's large and most processes don't need it. Statically link
  142. // libc++demangle into every process so that users still have it if
  143. // needed, but the linker won't include this unless it is actually
  144. // called.
  145. // http://b/138245375
  146. deps.StaticLibs = append(deps.StaticLibs, "libc++demangle")
  147. }
  148. if ctx.toolchain().Bionic() {
  149. if ctx.staticBinary() {
  150. deps.StaticLibs = append(deps.StaticLibs, "libm", "libc", staticUnwinder(ctx))
  151. } else {
  152. deps.StaticUnwinderIfLegacy = true
  153. }
  154. }
  155. case "":
  156. // None or error.
  157. if ctx.toolchain().Bionic() && ctx.Module().Name() == "libc++" {
  158. deps.StaticUnwinderIfLegacy = true
  159. }
  160. case "ndk_system":
  161. // TODO: Make a system STL prebuilt for the NDK.
  162. // The system STL doesn't have a prebuilt (it uses the system's libstdc++), but it does have
  163. // its own includes. The includes are handled in CCBase.Flags().
  164. deps.SharedLibs = append([]string{"libstdc++"}, deps.SharedLibs...)
  165. case "ndk_libc++_shared", "ndk_libc++_static":
  166. if stl.Properties.SelectedStl == "ndk_libc++_shared" {
  167. deps.SharedLibs = append(deps.SharedLibs, stl.Properties.SelectedStl)
  168. } else {
  169. deps.StaticLibs = append(deps.StaticLibs, stl.Properties.SelectedStl, "ndk_libc++abi")
  170. }
  171. if needsLibAndroidSupport(ctx) {
  172. // Use LateStaticLibs for ndk_libandroid_support so that its include directories
  173. // come after ndk_libc++_static or ndk_libc++_shared.
  174. deps.LateStaticLibs = append(deps.LateStaticLibs, "ndk_libandroid_support")
  175. }
  176. deps.StaticLibs = append(deps.StaticLibs, "ndk_libunwind")
  177. default:
  178. panic(fmt.Errorf("Unknown stl: %q", stl.Properties.SelectedStl))
  179. }
  180. return deps
  181. }
  182. // Should be kept up to date with
  183. // https://cs.android.com/android/platform/superproject/+/master:build/bazel/rules/cc/stl.bzl;l=94;drc=5bc8e39d2637927dc57dd0850210d43d348a1341
  184. func (stl *stl) flags(ctx ModuleContext, flags Flags) Flags {
  185. switch stl.Properties.SelectedStl {
  186. case "libc++", "libc++_static":
  187. if ctx.Darwin() {
  188. // libc++'s headers are annotated with availability macros that
  189. // indicate which version of Mac OS was the first to ship with a
  190. // libc++ feature available in its *system's* libc++.dylib. We do
  191. // not use the system's library, but rather ship our own. As such,
  192. // these availability attributes are meaningless for us but cause
  193. // build breaks when we try to use code that would not be available
  194. // in the system's dylib.
  195. flags.Local.CppFlags = append(flags.Local.CppFlags,
  196. "-D_LIBCPP_DISABLE_AVAILABILITY")
  197. }
  198. if !ctx.toolchain().Bionic() {
  199. flags.Local.CppFlags = append(flags.Local.CppFlags, "-nostdinc++")
  200. flags.extraLibFlags = append(flags.extraLibFlags, "-nostdlib++")
  201. if ctx.Windows() {
  202. flags.Local.CppFlags = append(flags.Local.CppFlags,
  203. // Disable visiblity annotations since we're using static
  204. // libc++.
  205. "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
  206. "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
  207. // Use Win32 threads in libc++.
  208. "-D_LIBCPP_HAS_THREAD_API_WIN32")
  209. }
  210. }
  211. case "libstdc++":
  212. // Nothing
  213. case "ndk_system":
  214. ndkSrcRoot := android.PathForSource(ctx, "prebuilts/ndk/current/sources/cxx-stl/system/include")
  215. flags.Local.CFlags = append(flags.Local.CFlags, "-isystem "+ndkSrcRoot.String())
  216. case "ndk_libc++_shared", "ndk_libc++_static":
  217. if ctx.Arch().ArchType == android.Arm {
  218. // Make sure the _Unwind_XXX symbols are not re-exported.
  219. flags.Local.LdFlags = append(flags.Local.LdFlags, "-Wl,--exclude-libs,libunwind.a")
  220. }
  221. case "":
  222. // None or error.
  223. if !ctx.toolchain().Bionic() {
  224. flags.Local.CppFlags = append(flags.Local.CppFlags, "-nostdinc++")
  225. flags.extraLibFlags = append(flags.extraLibFlags, "-nostdlib++")
  226. }
  227. default:
  228. panic(fmt.Errorf("Unknown stl: %q", stl.Properties.SelectedStl))
  229. }
  230. return flags
  231. }