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