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