blob: 580570d76cc5cebcfe59cdfb96bcb442ea676a05 [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
31type stlFeature struct {
32 Properties StlProperties
33}
34
35var _ feature = (*stlFeature)(nil)
36
37func (stl *stlFeature) props() []interface{} {
38 return []interface{}{&stl.Properties}
39}
40
41func (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
87func (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
127func (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
182var hostDynamicGccLibs, hostStaticGccLibs map[common.HostType][]string
183
184func 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}