1// Copyright 2015 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 config
16
17import (
18	"fmt"
19	"path/filepath"
20
21	"android/soong/android"
22)
23
24type toolchainFactory func(arch android.Arch) Toolchain
25
26var toolchainFactories = make(map[android.OsType]map[android.ArchType]toolchainFactory)
27
28func registerToolchainFactory(os android.OsType, arch android.ArchType, factory toolchainFactory) {
29	if toolchainFactories[os] == nil {
30		toolchainFactories[os] = make(map[android.ArchType]toolchainFactory)
31	}
32	toolchainFactories[os][arch] = factory
33}
34
35func FindToolchain(os android.OsType, arch android.Arch) Toolchain {
36	factory := toolchainFactories[os][arch.ArchType]
37	if factory == nil {
38		panic(fmt.Errorf("Toolchain not found for %s arch %q", os.String(), arch.String()))
39	}
40	return factory(arch)
41}
42
43type Toolchain interface {
44	Name() string
45
46	GccRoot() string
47	GccTriple() string
48	// GccVersion should return a real value, not a ninja reference
49	GccVersion() string
50	ToolPath() string
51
52	IncludeFlags() string
53
54	ClangTriple() string
55	ToolchainClangCflags() string
56	ToolchainClangLdflags() string
57	ClangAsflags() string
58	ClangCflags() string
59	ClangCppflags() string
60	ClangLdflags() string
61	ClangLldflags() string
62	ClangInstructionSetFlags(string) (string, error)
63
64	ndkTriple() string
65
66	YasmFlags() string
67
68	WindresFlags() string
69
70	Is64Bit() bool
71
72	ShlibSuffix() string
73	ExecutableSuffix() string
74
75	LibclangRuntimeLibraryArch() string
76
77	AvailableLibraries() []string
78
79	Bionic() bool
80}
81
82type toolchainBase struct {
83}
84
85func (t *toolchainBase) ndkTriple() string {
86	return ""
87}
88
89func NDKTriple(toolchain Toolchain) string {
90	triple := toolchain.ndkTriple()
91	if triple == "" {
92		// Use the clang triple if there is no explicit NDK triple
93		triple = toolchain.ClangTriple()
94	}
95	return triple
96}
97
98func (toolchainBase) ClangInstructionSetFlags(s string) (string, error) {
99	if s != "" {
100		return "", fmt.Errorf("instruction_set: %s is not a supported instruction set", s)
101	}
102	return "", nil
103}
104
105func (toolchainBase) ToolchainClangCflags() string {
106	return ""
107}
108
109func (toolchainBase) ToolchainClangLdflags() string {
110	return ""
111}
112
113func (toolchainBase) ShlibSuffix() string {
114	return ".so"
115}
116
117func (toolchainBase) ExecutableSuffix() string {
118	return ""
119}
120
121func (toolchainBase) ClangAsflags() string {
122	return ""
123}
124
125func (toolchainBase) YasmFlags() string {
126	return ""
127}
128
129func (toolchainBase) WindresFlags() string {
130	return ""
131}
132
133func (toolchainBase) LibclangRuntimeLibraryArch() string {
134	return ""
135}
136
137func (toolchainBase) AvailableLibraries() []string {
138	return []string{}
139}
140
141func (toolchainBase) Bionic() bool {
142	return true
143}
144
145func (t toolchainBase) ToolPath() string {
146	return ""
147}
148
149type toolchain64Bit struct {
150	toolchainBase
151}
152
153func (toolchain64Bit) Is64Bit() bool {
154	return true
155}
156
157type toolchain32Bit struct {
158	toolchainBase
159}
160
161func (toolchain32Bit) Is64Bit() bool {
162	return false
163}
164
165func variantOrDefault(variants map[string]string, choice string) string {
166	if ret, ok := variants[choice]; ok {
167		return ret
168	}
169	return variants[""]
170}
171
172func addPrefix(list []string, prefix string) []string {
173	for i := range list {
174		list[i] = prefix + list[i]
175	}
176	return list
177}
178
179func LibclangRuntimeLibrary(t Toolchain, library string) string {
180	arch := t.LibclangRuntimeLibraryArch()
181	if arch == "" {
182		return ""
183	}
184	if !t.Bionic() {
185		return "libclang_rt." + library + "-" + arch
186	}
187	return "libclang_rt." + library + "-" + arch + "-android"
188}
189
190func BuiltinsRuntimeLibrary(t Toolchain) string {
191	return LibclangRuntimeLibrary(t, "builtins")
192}
193
194func AddressSanitizerRuntimeLibrary(t Toolchain) string {
195	return LibclangRuntimeLibrary(t, "asan")
196}
197
198func HWAddressSanitizerRuntimeLibrary(t Toolchain) string {
199	return LibclangRuntimeLibrary(t, "hwasan")
200}
201
202func HWAddressSanitizerStaticLibrary(t Toolchain) string {
203	return LibclangRuntimeLibrary(t, "hwasan_static")
204}
205
206func UndefinedBehaviorSanitizerRuntimeLibrary(t Toolchain) string {
207	return LibclangRuntimeLibrary(t, "ubsan_standalone")
208}
209
210func UndefinedBehaviorSanitizerMinimalRuntimeLibrary(t Toolchain) string {
211	return LibclangRuntimeLibrary(t, "ubsan_minimal")
212}
213
214func ThreadSanitizerRuntimeLibrary(t Toolchain) string {
215	return LibclangRuntimeLibrary(t, "tsan")
216}
217
218func ProfileRuntimeLibrary(t Toolchain) string {
219	return LibclangRuntimeLibrary(t, "profile")
220}
221
222func ScudoRuntimeLibrary(t Toolchain) string {
223	return LibclangRuntimeLibrary(t, "scudo")
224}
225
226func ScudoMinimalRuntimeLibrary(t Toolchain) string {
227	return LibclangRuntimeLibrary(t, "scudo_minimal")
228}
229
230func LibFuzzerRuntimeLibrary(t Toolchain) string {
231	return LibclangRuntimeLibrary(t, "fuzzer")
232}
233
234func ToolPath(t Toolchain) string {
235	if p := t.ToolPath(); p != "" {
236		return p
237	}
238	return filepath.Join(t.GccRoot(), t.GccTriple(), "bin")
239}
240
241var inList = android.InList
242