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