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 15 package cc 16 17 import ( 18 "android/soong/android" 19 "fmt" 20 ) 21 22 type StlProperties struct { 23 // select the STL library to use. Possible values are "libc++", "libc++_static", 24 // "stlport", "stlport_static", "ndk", "libstdc++", or "none". Leave blank to select the 25 // default 26 Stl *string 27 28 SelectedStl string `blueprint:"mutated"` 29 } 30 31 type stl struct { 32 Properties StlProperties 33 } 34 35 func (stl *stl) props() []interface{} { 36 return []interface{}{&stl.Properties} 37 } 38 39 func (stl *stl) begin(ctx BaseModuleContext) { 40 stl.Properties.SelectedStl = func() string { 41 s := "" 42 if stl.Properties.Stl != nil { 43 s = *stl.Properties.Stl 44 } 45 if ctx.sdk() && ctx.Device() { 46 switch s { 47 case "": 48 return "ndk_system" 49 case "c++_shared", "c++_static", 50 "stlport_shared", "stlport_static", 51 "gnustl_static": 52 return "ndk_lib" + s 53 case "libc++": 54 return "ndk_libc++_shared" 55 case "libc++_static": 56 return "ndk_libc++_static" 57 case "none": 58 return "" 59 default: 60 ctx.ModuleErrorf("stl: %q is not a supported STL with sdk_version set", s) 61 return "" 62 } 63 } else if ctx.Os() == android.Windows { 64 switch s { 65 case "libc++", "libc++_static", "libstdc++", "": 66 // libc++ is not supported on mingw 67 return "libstdc++" 68 case "none": 69 return "" 70 default: 71 ctx.ModuleErrorf("stl: %q is not a supported STL for windows", s) 72 return "" 73 } 74 } else { 75 switch s { 76 case "libc++", "libc++_static": 77 return s 78 case "none": 79 return "" 80 case "": 81 if ctx.static() { 82 return "libc++_static" 83 } else { 84 return "libc++" 85 } 86 default: 87 ctx.ModuleErrorf("stl: %q is not a supported STL", s) 88 return "" 89 } 90 } 91 }() 92 } 93 94 func (stl *stl) deps(ctx BaseModuleContext, deps Deps) Deps { 95 switch stl.Properties.SelectedStl { 96 case "libstdc++": 97 // Nothing 98 case "libc++", "libc++_static": 99 if stl.Properties.SelectedStl == "libc++" { 100 deps.SharedLibs = append(deps.SharedLibs, stl.Properties.SelectedStl) 101 } else { 102 deps.StaticLibs = append(deps.StaticLibs, stl.Properties.SelectedStl) 103 } 104 if ctx.toolchain().Bionic() { 105 if ctx.Arch().ArchType == android.Arm { 106 deps.StaticLibs = append(deps.StaticLibs, "libunwind_llvm") 107 } 108 if ctx.staticBinary() { 109 deps.StaticLibs = append(deps.StaticLibs, "libm", "libc", "libdl") 110 } else { 111 deps.SharedLibs = append(deps.SharedLibs, "libdl") 112 } 113 } 114 case "": 115 // None or error. 116 case "ndk_system": 117 // TODO: Make a system STL prebuilt for the NDK. 118 // The system STL doesn't have a prebuilt (it uses the system's libstdc++), but it does have 119 // its own includes. The includes are handled in CCBase.Flags(). 120 deps.SharedLibs = append([]string{"libstdc++"}, deps.SharedLibs...) 121 case "ndk_libc++_shared": 122 deps.SharedLibs = append(deps.SharedLibs, stl.Properties.SelectedStl, 123 "libdl") 124 case "ndk_libc++_static": 125 deps.StaticLibs = append(deps.StaticLibs, stl.Properties.SelectedStl) 126 deps.SharedLibs = append(deps.SharedLibs, "libdl") 127 case "ndk_libstlport_shared": 128 deps.SharedLibs = append(deps.SharedLibs, stl.Properties.SelectedStl) 129 case "ndk_libstlport_static", "ndk_libgnustl_static": 130 deps.StaticLibs = append(deps.StaticLibs, stl.Properties.SelectedStl) 131 default: 132 panic(fmt.Errorf("Unknown stl: %q", stl.Properties.SelectedStl)) 133 } 134 135 return deps 136 } 137 138 func (stl *stl) flags(ctx ModuleContext, flags Flags) Flags { 139 switch stl.Properties.SelectedStl { 140 case "libc++", "libc++_static": 141 flags.CFlags = append(flags.CFlags, "-D_USING_LIBCXX") 142 if !ctx.toolchain().Bionic() { 143 flags.CppFlags = append(flags.CppFlags, "-nostdinc++") 144 flags.LdFlags = append(flags.LdFlags, "-nodefaultlibs") 145 flags.LdFlags = append(flags.LdFlags, "-lpthread", "-lm") 146 if ctx.staticBinary() { 147 flags.LdFlags = append(flags.LdFlags, hostStaticGccLibs[ctx.Os()]...) 148 } else { 149 flags.LdFlags = append(flags.LdFlags, hostDynamicGccLibs[ctx.Os()]...) 150 } 151 } else { 152 if ctx.Arch().ArchType == android.Arm { 153 flags.LdFlags = append(flags.LdFlags, "-Wl,--exclude-libs,libunwind_llvm.a") 154 } 155 } 156 case "libstdc++": 157 // Nothing 158 case "ndk_system": 159 ndkSrcRoot := android.PathForSource(ctx, "prebuilts/ndk/current/sources/cxx-stl/system/include") 160 flags.CFlags = append(flags.CFlags, "-isystem "+ndkSrcRoot.String()) 161 case "ndk_libc++_shared", "ndk_libc++_static": 162 // TODO(danalbert): This really shouldn't be here... 163 flags.CppFlags = append(flags.CppFlags, "-std=c++11") 164 case "ndk_libstlport_shared", "ndk_libstlport_static", "ndk_libgnustl_static": 165 // Nothing 166 case "": 167 // None or error. 168 if !ctx.toolchain().Bionic() { 169 flags.CppFlags = append(flags.CppFlags, "-nostdinc++") 170 flags.LdFlags = append(flags.LdFlags, "-nodefaultlibs") 171 if ctx.staticBinary() { 172 flags.LdFlags = append(flags.LdFlags, hostStaticGccLibs[ctx.Os()]...) 173 } else { 174 flags.LdFlags = append(flags.LdFlags, hostDynamicGccLibs[ctx.Os()]...) 175 } 176 } 177 default: 178 panic(fmt.Errorf("Unknown stl: %q", stl.Properties.SelectedStl)) 179 } 180 181 return flags 182 } 183 184 var hostDynamicGccLibs, hostStaticGccLibs map[android.OsType][]string 185 186 func init() { 187 hostDynamicGccLibs = map[android.OsType][]string{ 188 android.Linux: []string{"-lgcc_s", "-lgcc", "-lc", "-lgcc_s", "-lgcc"}, 189 android.Darwin: []string{"-lc", "-lSystem"}, 190 android.Windows: []string{"-lmsvcr110", "-lmingw32", "-lgcc", "-lmoldname", 191 "-lmingwex", "-lmsvcrt", "-ladvapi32", "-lshell32", "-luser32", 192 "-lkernel32", "-lmingw32", "-lgcc", "-lmoldname", "-lmingwex", 193 "-lmsvcrt"}, 194 } 195 hostStaticGccLibs = map[android.OsType][]string{ 196 android.Linux: []string{"-Wl,--start-group", "-lgcc", "-lgcc_eh", "-lc", "-Wl,--end-group"}, 197 android.Darwin: []string{"NO_STATIC_HOST_BINARIES_ON_DARWIN"}, 198 android.Windows: []string{"NO_STATIC_HOST_BINARIES_ON_WINDOWS"}, 199 } 200 } 201