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 if ctx.useSdk() && ctx.Device() { 84 switch s { 85 case "", "system": 86 return "ndk_system" 87 case "libc++": 88 return "ndk_libc++_shared" 89 case "libc++_static": 90 return "ndk_libc++_static" 91 default: 92 ctx.ModuleErrorf("stl: %q is not a supported STL with sdk_version set", s) 93 return "" 94 } 95 } else if ctx.Windows() { 96 switch s { 97 case "libc++", "libc++_static", "": 98 // Only use static libc++ for Windows. 99 return "libc++_static" 100 default: 101 ctx.ModuleErrorf("stl: %q is not a supported STL for windows", s) 102 return "" 103 } 104 } else { 105 switch s { 106 case "libc++", "libc++_static": 107 return s 108 case "", "system": 109 if ctx.static() { 110 return "libc++_static" 111 } else { 112 return "libc++" 113 } 114 default: 115 ctx.ModuleErrorf("stl: %q is not a supported STL", s) 116 return "" 117 } 118 } 119 }() 120} 121 122func staticUnwinder(ctx android.BaseModuleContext) string { 123 vndkVersion := ctx.Module().(*Module).VndkVersion() 124 125 // Modules using R vndk use different unwinder 126 if vndkVersion == "30" { 127 if ctx.Arch().ArchType == android.Arm { 128 return "libunwind_llvm" 129 } else { 130 return "libgcc_stripped" 131 } 132 } 133 134 return "libunwind" 135} 136 137func (stl *stl) deps(ctx BaseModuleContext, deps Deps) Deps { 138 switch stl.Properties.SelectedStl { 139 case "libstdc++": 140 // Nothing 141 case "libc++", "libc++_static": 142 if stl.Properties.SelectedStl == "libc++" { 143 deps.SharedLibs = append(deps.SharedLibs, stl.Properties.SelectedStl) 144 } else { 145 deps.StaticLibs = append(deps.StaticLibs, stl.Properties.SelectedStl) 146 } 147 if ctx.Device() && !ctx.useSdk() { 148 // __cxa_demangle is not a part of libc++.so on the device since 149 // it's large and most processes don't need it. Statically link 150 // libc++demangle into every process so that users still have it if 151 // needed, but the linker won't include this unless it is actually 152 // called. 153 // http://b/138245375 154 deps.StaticLibs = append(deps.StaticLibs, "libc++demangle") 155 } 156 if ctx.toolchain().Bionic() { 157 if ctx.staticBinary() { 158 deps.StaticLibs = append(deps.StaticLibs, "libm", "libc", staticUnwinder(ctx)) 159 } else { 160 deps.StaticUnwinderIfLegacy = true 161 } 162 } 163 case "": 164 // None or error. 165 if ctx.toolchain().Bionic() && ctx.Module().Name() == "libc++" { 166 deps.StaticUnwinderIfLegacy = true 167 } 168 case "ndk_system": 169 // TODO: Make a system STL prebuilt for the NDK. 170 // The system STL doesn't have a prebuilt (it uses the system's libstdc++), but it does have 171 // its own includes. The includes are handled in CCBase.Flags(). 172 deps.SharedLibs = append([]string{"libstdc++"}, deps.SharedLibs...) 173 deps.HeaderLibs = append([]string{"ndk_system"}, deps.HeaderLibs...) 174 case "ndk_libc++_shared", "ndk_libc++_static": 175 if stl.Properties.SelectedStl == "ndk_libc++_shared" { 176 deps.SharedLibs = append(deps.SharedLibs, stl.Properties.SelectedStl) 177 } else { 178 deps.StaticLibs = append(deps.StaticLibs, stl.Properties.SelectedStl, "ndk_libc++abi") 179 } 180 deps.StaticLibs = append(deps.StaticLibs, "libunwind") 181 default: 182 panic(fmt.Errorf("Unknown stl: %q", stl.Properties.SelectedStl)) 183 } 184 185 return deps 186} 187 188func (stl *stl) flags(ctx ModuleContext, flags Flags) Flags { 189 switch stl.Properties.SelectedStl { 190 case "libc++", "libc++_static": 191 if ctx.Darwin() { 192 // libc++'s headers are annotated with availability macros that 193 // indicate which version of Mac OS was the first to ship with a 194 // libc++ feature available in its *system's* libc++.dylib. We do 195 // not use the system's library, but rather ship our own. As such, 196 // these availability attributes are meaningless for us but cause 197 // build breaks when we try to use code that would not be available 198 // in the system's dylib. 199 flags.Local.CppFlags = append(flags.Local.CppFlags, 200 "-D_LIBCPP_DISABLE_AVAILABILITY") 201 } 202 203 if !ctx.toolchain().Bionic() { 204 flags.Local.CppFlags = append(flags.Local.CppFlags, "-nostdinc++") 205 flags.extraLibFlags = append(flags.extraLibFlags, "-nostdlib++") 206 if ctx.Windows() { 207 flags.Local.CppFlags = append(flags.Local.CppFlags, 208 // These macros can also be defined by libc++'s __config 209 // or __config_site headers so define them the same way 210 // (i.e. to nothing). Disable visibility annotations since 211 // we're using static libc++. 212 "-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS=", 213 "-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS=", 214 // Use Win32 threads in libc++. 215 "-D_LIBCPP_HAS_THREAD_API_WIN32=") 216 } 217 } 218 case "libstdc++": 219 // Nothing 220 case "ndk_system": 221 // Nothing: The exports of ndk_system will be added automatically to the local cflags 222 case "ndk_libc++_shared", "ndk_libc++_static": 223 if ctx.Arch().ArchType == android.Arm { 224 // Make sure the _Unwind_XXX symbols are not re-exported. 225 flags.Local.LdFlags = append(flags.Local.LdFlags, "-Wl,--exclude-libs,libunwind.a") 226 } 227 case "": 228 // None or error. 229 if !ctx.toolchain().Bionic() { 230 flags.Local.CppFlags = append(flags.Local.CppFlags, "-nostdinc++") 231 flags.extraLibFlags = append(flags.extraLibFlags, "-nostdlib++") 232 } 233 default: 234 panic(fmt.Errorf("Unknown stl: %q", stl.Properties.SelectedStl)) 235 } 236 237 return flags 238} 239