• 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/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}
199