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 "android/soong/android" 19 "fmt" 20) 21 22type 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 31type stl struct { 32 Properties StlProperties 33} 34 35func (stl *stl) props() []interface{} { 36 return []interface{}{&stl.Properties} 37} 38 39func (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.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 94func (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 } 111 } 112 case "": 113 // None or error. 114 case "ndk_system": 115 // TODO: Make a system STL prebuilt for the NDK. 116 // The system STL doesn't have a prebuilt (it uses the system's libstdc++), but it does have 117 // its own includes. The includes are handled in CCBase.Flags(). 118 deps.SharedLibs = append([]string{"libstdc++"}, deps.SharedLibs...) 119 case "ndk_libc++_shared", "ndk_libstlport_shared": 120 deps.SharedLibs = append(deps.SharedLibs, stl.Properties.SelectedStl) 121 case "ndk_libc++_static", "ndk_libstlport_static", "ndk_libgnustl_static": 122 deps.StaticLibs = append(deps.StaticLibs, stl.Properties.SelectedStl) 123 default: 124 panic(fmt.Errorf("Unknown stl: %q", stl.Properties.SelectedStl)) 125 } 126 127 return deps 128} 129 130func (stl *stl) flags(ctx ModuleContext, flags Flags) Flags { 131 switch stl.Properties.SelectedStl { 132 case "libc++", "libc++_static": 133 flags.CFlags = append(flags.CFlags, "-D_USING_LIBCXX") 134 if !ctx.toolchain().Bionic() { 135 flags.CppFlags = append(flags.CppFlags, "-nostdinc++") 136 flags.LdFlags = append(flags.LdFlags, "-nodefaultlibs") 137 flags.LdFlags = append(flags.LdFlags, "-lpthread", "-lm") 138 if ctx.staticBinary() { 139 flags.LdFlags = append(flags.LdFlags, hostStaticGccLibs[ctx.Os()]...) 140 } else { 141 flags.LdFlags = append(flags.LdFlags, hostDynamicGccLibs[ctx.Os()]...) 142 } 143 } else { 144 if ctx.Arch().ArchType == android.Arm { 145 flags.LdFlags = append(flags.LdFlags, "-Wl,--exclude-libs,libunwind_llvm.a") 146 } 147 } 148 case "libstdc++": 149 // Nothing 150 case "ndk_system": 151 ndkSrcRoot := android.PathForSource(ctx, "prebuilts/ndk/current/sources/cxx-stl/system/include") 152 flags.CFlags = append(flags.CFlags, "-isystem "+ndkSrcRoot.String()) 153 case "ndk_libc++_shared", "ndk_libc++_static": 154 // TODO(danalbert): This really shouldn't be here... 155 flags.CppFlags = append(flags.CppFlags, "-std=c++11") 156 case "ndk_libstlport_shared", "ndk_libstlport_static", "ndk_libgnustl_static": 157 // Nothing 158 case "": 159 // None or error. 160 if !ctx.toolchain().Bionic() { 161 flags.CppFlags = append(flags.CppFlags, "-nostdinc++") 162 flags.LdFlags = append(flags.LdFlags, "-nodefaultlibs") 163 if ctx.staticBinary() { 164 flags.LdFlags = append(flags.LdFlags, hostStaticGccLibs[ctx.Os()]...) 165 } else { 166 flags.LdFlags = append(flags.LdFlags, hostDynamicGccLibs[ctx.Os()]...) 167 } 168 } 169 default: 170 panic(fmt.Errorf("Unknown stl: %q", stl.Properties.SelectedStl)) 171 } 172 173 return flags 174} 175 176var hostDynamicGccLibs, hostStaticGccLibs map[android.OsType][]string 177 178func init() { 179 hostDynamicGccLibs = map[android.OsType][]string{ 180 android.Linux: []string{"-lgcc_s", "-lgcc", "-lc", "-lgcc_s", "-lgcc"}, 181 android.Darwin: []string{"-lc", "-lSystem"}, 182 android.Windows: []string{"-lmsvcr110", "-lmingw32", "-lgcc", "-lmoldname", 183 "-lmingwex", "-lmsvcrt", "-ladvapi32", "-lshell32", "-luser32", 184 "-lkernel32", "-lmingw32", "-lgcc", "-lmoldname", "-lmingwex", 185 "-lmsvcrt"}, 186 } 187 hostStaticGccLibs = map[android.OsType][]string{ 188 android.Linux: []string{"-Wl,--start-group", "-lgcc", "-lgcc_eh", "-lc", "-Wl,--end-group"}, 189 android.Darwin: []string{"NO_STATIC_HOST_BINARIES_ON_DARWIN"}, 190 android.Windows: []string{"NO_STATIC_HOST_BINARIES_ON_WINDOWS"}, 191 } 192} 193