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