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