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