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