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