• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
22func getNdkStlFamily(m LinkableInterface) string {
23	family, _ := getNdkStlFamilyAndLinkType(m)
24	return family
25}
26
27func getNdkStlFamilyAndLinkType(m LinkableInterface) (string, string) {
28	stl := m.SelectedStl()
29	switch stl {
30	case "ndk_libc++_shared":
31		return "libc++", "shared"
32	case "ndk_libc++_static":
33		return "libc++", "static"
34	case "ndk_system":
35		return "system", "shared"
36	case "":
37		return "none", "none"
38	default:
39		panic(fmt.Errorf("stl: %q is not a valid STL", stl))
40	}
41}
42
43type StlProperties struct {
44	// Select the STL library to use.  Possible values are "libc++",
45	// "libc++_static", "libstdc++", or "none". Leave blank to select the
46	// default.
47	Stl *string `android:"arch_variant"`
48
49	SelectedStl string `blueprint:"mutated"`
50}
51
52type stl struct {
53	Properties StlProperties
54}
55
56func (stl *stl) props() []interface{} {
57	return []interface{}{&stl.Properties}
58}
59
60func (stl *stl) begin(ctx BaseModuleContext) {
61	stl.Properties.SelectedStl = func() string {
62		s := ""
63		if stl.Properties.Stl != nil {
64			s = *stl.Properties.Stl
65		} else if ctx.header() {
66			s = "none"
67		}
68		if ctx.useSdk() && ctx.Device() {
69			switch s {
70			case "", "system":
71				return "ndk_system"
72			case "c++_shared", "c++_static":
73				return "ndk_lib" + s
74			case "libc++":
75				return "ndk_libc++_shared"
76			case "libc++_static":
77				return "ndk_libc++_static"
78			case "none":
79				return ""
80			default:
81				ctx.ModuleErrorf("stl: %q is not a supported STL with sdk_version set", s)
82				return ""
83			}
84		} else if ctx.Windows() {
85			switch s {
86			case "libc++", "libc++_static", "":
87				// Only use static libc++ for Windows.
88				return "libc++_static"
89			case "none":
90				return ""
91			default:
92				ctx.ModuleErrorf("stl: %q is not a supported STL for windows", s)
93				return ""
94			}
95		} else if ctx.Fuchsia() {
96			switch s {
97			case "c++_static":
98				return "libc++_static"
99			case "c++_shared":
100				return "libc++"
101			case "libc++", "libc++_static":
102				return s
103			case "none":
104				return ""
105			case "":
106				if ctx.static() {
107					return "libc++_static"
108				} else {
109					return "libc++"
110				}
111			default:
112				ctx.ModuleErrorf("stl: %q is not a supported STL on Fuchsia", s)
113				return ""
114			}
115		} else {
116			switch s {
117			case "libc++", "libc++_static":
118				return s
119			case "c++_shared":
120				return "libc++"
121			case "c++_static":
122				return "libc++_static"
123			case "none":
124				return ""
125			case "", "system":
126				if ctx.static() {
127					return "libc++_static"
128				} else {
129					return "libc++"
130				}
131			default:
132				ctx.ModuleErrorf("stl: %q is not a supported STL", s)
133				return ""
134			}
135		}
136	}()
137}
138
139func needsLibAndroidSupport(ctx BaseModuleContext) bool {
140	version := nativeApiLevelOrPanic(ctx, ctx.sdkVersion())
141	return version.LessThan(android.FirstNonLibAndroidSupportVersion)
142}
143
144func staticUnwinder(ctx android.BaseModuleContext) string {
145	vndkVersion := ctx.Module().(*Module).VndkVersion()
146
147	// Modules using R vndk use different unwinder
148	if vndkVersion == "30" {
149		if ctx.Arch().ArchType == android.Arm {
150			return "libunwind_llvm"
151		} else {
152			return "libgcc_stripped"
153		}
154	}
155
156	return "libunwind"
157}
158
159func (stl *stl) deps(ctx BaseModuleContext, deps Deps) Deps {
160	switch stl.Properties.SelectedStl {
161	case "libstdc++":
162		// Nothing
163	case "libc++", "libc++_static":
164		if stl.Properties.SelectedStl == "libc++" {
165			deps.SharedLibs = append(deps.SharedLibs, stl.Properties.SelectedStl)
166		} else {
167			deps.StaticLibs = append(deps.StaticLibs, stl.Properties.SelectedStl)
168		}
169		if ctx.Device() && !ctx.useSdk() {
170			// __cxa_demangle is not a part of libc++.so on the device since
171			// it's large and most processes don't need it. Statically link
172			// libc++demangle into every process so that users still have it if
173			// needed, but the linker won't include this unless it is actually
174			// called.
175			// http://b/138245375
176			deps.StaticLibs = append(deps.StaticLibs, "libc++demangle")
177		}
178		if ctx.toolchain().Bionic() {
179			if ctx.staticBinary() {
180				deps.StaticLibs = append(deps.StaticLibs, "libm", "libc", staticUnwinder(ctx))
181			} else {
182				deps.StaticUnwinderIfLegacy = true
183			}
184		}
185	case "":
186		// None or error.
187		if ctx.toolchain().Bionic() && ctx.Module().Name() == "libc++" {
188			deps.StaticUnwinderIfLegacy = true
189		}
190	case "ndk_system":
191		// TODO: Make a system STL prebuilt for the NDK.
192		// The system STL doesn't have a prebuilt (it uses the system's libstdc++), but it does have
193		// its own includes. The includes are handled in CCBase.Flags().
194		deps.SharedLibs = append([]string{"libstdc++"}, deps.SharedLibs...)
195	case "ndk_libc++_shared", "ndk_libc++_static":
196		if stl.Properties.SelectedStl == "ndk_libc++_shared" {
197			deps.SharedLibs = append(deps.SharedLibs, stl.Properties.SelectedStl)
198		} else {
199			deps.StaticLibs = append(deps.StaticLibs, stl.Properties.SelectedStl, "ndk_libc++abi")
200		}
201		if needsLibAndroidSupport(ctx) {
202			deps.StaticLibs = append(deps.StaticLibs, "ndk_libandroid_support")
203		}
204		deps.StaticLibs = append(deps.StaticLibs, "ndk_libunwind")
205	default:
206		panic(fmt.Errorf("Unknown stl: %q", stl.Properties.SelectedStl))
207	}
208
209	return deps
210}
211
212func (stl *stl) flags(ctx ModuleContext, flags Flags) Flags {
213	switch stl.Properties.SelectedStl {
214	case "libc++", "libc++_static":
215		if ctx.Darwin() {
216			// libc++'s headers are annotated with availability macros that
217			// indicate which version of Mac OS was the first to ship with a
218			// libc++ feature available in its *system's* libc++.dylib. We do
219			// not use the system's library, but rather ship our own. As such,
220			// these availability attributes are meaningless for us but cause
221			// build breaks when we try to use code that would not be available
222			// in the system's dylib.
223			flags.Local.CppFlags = append(flags.Local.CppFlags,
224				"-D_LIBCPP_DISABLE_AVAILABILITY")
225		}
226
227		if !ctx.toolchain().Bionic() {
228			flags.Local.CppFlags = append(flags.Local.CppFlags, "-nostdinc++")
229			flags.extraLibFlags = append(flags.extraLibFlags, "-nostdlib++")
230			if ctx.Windows() {
231				flags.Local.CppFlags = append(flags.Local.CppFlags,
232					// Disable visiblity annotations since we're using static
233					// libc++.
234					"-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS",
235					"-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS",
236					// Use Win32 threads in libc++.
237					"-D_LIBCPP_HAS_THREAD_API_WIN32")
238			}
239		}
240	case "libstdc++":
241		// Nothing
242	case "ndk_system":
243		ndkSrcRoot := android.PathForSource(ctx, "prebuilts/ndk/current/sources/cxx-stl/system/include")
244		flags.Local.CFlags = append(flags.Local.CFlags, "-isystem "+ndkSrcRoot.String())
245	case "ndk_libc++_shared", "ndk_libc++_static":
246		if ctx.Arch().ArchType == android.Arm {
247			// Make sure the _Unwind_XXX symbols are not re-exported.
248			flags.Local.LdFlags = append(flags.Local.LdFlags, "-Wl,--exclude-libs,libunwind.a")
249		}
250	case "":
251		// None or error.
252		if !ctx.toolchain().Bionic() {
253			flags.Local.CppFlags = append(flags.Local.CppFlags, "-nostdinc++")
254			flags.extraLibFlags = append(flags.extraLibFlags, "-nostdlib++")
255		}
256	default:
257		panic(fmt.Errorf("Unknown stl: %q", stl.Properties.SelectedStl))
258	}
259
260	return flags
261}
262