1// Copyright (C) 2016 The Android Open Source Project
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 art
16
17import (
18	"android/soong/android"
19	"android/soong/cc"
20	"fmt"
21	"sync"
22
23	"github.com/google/blueprint"
24)
25
26var supportedArches = []string{"arm", "arm64", "mips", "mips64", "x86", "x86_64"}
27
28func globalFlags(ctx android.BaseContext) ([]string, []string) {
29	var cflags []string
30	var asflags []string
31
32	opt := envDefault(ctx, "ART_NDEBUG_OPT_FLAG", "-O3")
33	cflags = append(cflags, opt)
34
35	tlab := false
36
37	gcType := envDefault(ctx, "ART_DEFAULT_GC_TYPE", "CMS")
38
39	if envTrue(ctx, "ART_TEST_DEBUG_GC") {
40		gcType = "SS"
41		tlab = true
42	}
43
44	cflags = append(cflags, "-DART_DEFAULT_GC_TYPE_IS_"+gcType)
45	if tlab {
46		cflags = append(cflags, "-DART_USE_TLAB=1")
47	}
48
49	if !envFalse(ctx, "ART_ENABLE_VDEX") {
50		cflags = append(cflags, "-DART_ENABLE_VDEX")
51	}
52
53	imtSize := envDefault(ctx, "ART_IMT_SIZE", "43")
54	cflags = append(cflags, "-DIMT_SIZE="+imtSize)
55
56	if envTrue(ctx, "ART_HEAP_POISONING") {
57		cflags = append(cflags, "-DART_HEAP_POISONING=1")
58		asflags = append(asflags, "-DART_HEAP_POISONING=1")
59	}
60
61	if !envFalse(ctx, "ART_USE_READ_BARRIER") && ctx.AConfig().ArtUseReadBarrier() {
62		// Used to change the read barrier type. Valid values are BAKER, BROOKS,
63		// TABLELOOKUP. The default is BAKER.
64		barrierType := envDefault(ctx, "ART_READ_BARRIER_TYPE", "BAKER")
65		cflags = append(cflags,
66			"-DART_USE_READ_BARRIER=1",
67			"-DART_READ_BARRIER_TYPE_IS_"+barrierType+"=1")
68		asflags = append(asflags,
69			"-DART_USE_READ_BARRIER=1",
70			"-DART_READ_BARRIER_TYPE_IS_"+barrierType+"=1")
71	}
72
73	if envTrue(ctx, "ART_USE_OLD_ARM_BACKEND") {
74		// Used to enable the old, pre-VIXL ARM code generator.
75		cflags = append(cflags, "-DART_USE_OLD_ARM_BACKEND=1")
76		asflags = append(asflags, "-DART_USE_OLD_ARM_BACKEND=1")
77	}
78
79	return cflags, asflags
80}
81
82func debugFlags(ctx android.BaseContext) []string {
83	var cflags []string
84
85	opt := envDefault(ctx, "ART_DEBUG_OPT_FLAG", "-O2")
86	cflags = append(cflags, opt)
87
88	return cflags
89}
90
91func deviceFlags(ctx android.BaseContext) []string {
92	var cflags []string
93	deviceFrameSizeLimit := 1736
94	if len(ctx.AConfig().SanitizeDevice()) > 0 {
95		deviceFrameSizeLimit = 7400
96	}
97	cflags = append(cflags,
98		fmt.Sprintf("-Wframe-larger-than=%d", deviceFrameSizeLimit),
99		fmt.Sprintf("-DART_FRAME_SIZE_LIMIT=%d", deviceFrameSizeLimit),
100	)
101
102	cflags = append(cflags, "-DART_BASE_ADDRESS="+ctx.AConfig().LibartImgDeviceBaseAddress())
103	if envTrue(ctx, "ART_TARGET_LINUX") {
104		cflags = append(cflags, "-DART_TARGET_LINUX")
105	} else {
106		cflags = append(cflags, "-DART_TARGET_ANDROID")
107	}
108	minDelta := envDefault(ctx, "LIBART_IMG_TARGET_MIN_BASE_ADDRESS_DELTA", "-0x1000000")
109	maxDelta := envDefault(ctx, "LIBART_IMG_TARGET_MAX_BASE_ADDRESS_DELTA", "0x1000000")
110	cflags = append(cflags, "-DART_BASE_ADDRESS_MIN_DELTA="+minDelta)
111	cflags = append(cflags, "-DART_BASE_ADDRESS_MAX_DELTA="+maxDelta)
112
113	return cflags
114}
115
116func hostFlags(ctx android.BaseContext) []string {
117	var cflags []string
118	hostFrameSizeLimit := 1736
119	if len(ctx.AConfig().SanitizeHost()) > 0 {
120		// art/test/137-cfi/cfi.cc
121		// error: stack frame size of 1944 bytes in function 'Java_Main_unwindInProcess'
122		hostFrameSizeLimit = 6400
123	}
124	cflags = append(cflags,
125		fmt.Sprintf("-Wframe-larger-than=%d", hostFrameSizeLimit),
126		fmt.Sprintf("-DART_FRAME_SIZE_LIMIT=%d", hostFrameSizeLimit),
127	)
128
129	cflags = append(cflags, "-DART_BASE_ADDRESS="+ctx.AConfig().LibartImgHostBaseAddress())
130	minDelta := envDefault(ctx, "LIBART_IMG_HOST_MIN_BASE_ADDRESS_DELTA", "-0x1000000")
131	maxDelta := envDefault(ctx, "LIBART_IMG_HOST_MAX_BASE_ADDRESS_DELTA", "0x1000000")
132	cflags = append(cflags, "-DART_BASE_ADDRESS_MIN_DELTA="+minDelta)
133	cflags = append(cflags, "-DART_BASE_ADDRESS_MAX_DELTA="+maxDelta)
134
135	return cflags
136}
137
138func globalDefaults(ctx android.LoadHookContext) {
139	type props struct {
140		Target struct {
141			Android struct {
142				Cflags []string
143			}
144			Host struct {
145				Cflags []string
146			}
147		}
148		Cflags  []string
149		Asflags []string
150	}
151
152	p := &props{}
153	p.Cflags, p.Asflags = globalFlags(ctx)
154	p.Target.Android.Cflags = deviceFlags(ctx)
155	p.Target.Host.Cflags = hostFlags(ctx)
156	ctx.AppendProperties(p)
157}
158
159func debugDefaults(ctx android.LoadHookContext) {
160	type props struct {
161		Cflags []string
162	}
163
164	p := &props{}
165	p.Cflags = debugFlags(ctx)
166	ctx.AppendProperties(p)
167}
168
169func customLinker(ctx android.LoadHookContext) {
170	linker := envDefault(ctx, "CUSTOM_TARGET_LINKER", "")
171	if linker != "" {
172		type props struct {
173			DynamicLinker string
174		}
175
176		p := &props{}
177		p.DynamicLinker = linker
178		ctx.AppendProperties(p)
179	}
180}
181
182func prefer32Bit(ctx android.LoadHookContext) {
183	if envTrue(ctx, "HOST_PREFER_32_BIT") {
184		type props struct {
185			Target struct {
186				Host struct {
187					Compile_multilib string
188				}
189			}
190		}
191
192		p := &props{}
193		p.Target.Host.Compile_multilib = "prefer32"
194		ctx.AppendProperties(p)
195	}
196}
197
198func testMap(config android.Config) map[string][]string {
199	return config.Once("artTests", func() interface{} {
200		return make(map[string][]string)
201	}).(map[string][]string)
202}
203
204func testInstall(ctx android.InstallHookContext) {
205	testMap := testMap(ctx.AConfig())
206
207	var name string
208	if ctx.Host() {
209		name = "host_"
210	} else {
211		name = "device_"
212	}
213	name += ctx.Arch().ArchType.String() + "_" + ctx.ModuleName()
214
215	artTestMutex.Lock()
216	defer artTestMutex.Unlock()
217
218	tests := testMap[name]
219	tests = append(tests, ctx.Path().RelPathString())
220	testMap[name] = tests
221}
222
223var artTestMutex sync.Mutex
224
225func init() {
226	android.RegisterModuleType("art_cc_library", artLibrary)
227	android.RegisterModuleType("art_cc_binary", artBinary)
228	android.RegisterModuleType("art_cc_test", artTest)
229	android.RegisterModuleType("art_cc_test_library", artTestLibrary)
230	android.RegisterModuleType("art_cc_defaults", artDefaultsFactory)
231	android.RegisterModuleType("art_global_defaults", artGlobalDefaultsFactory)
232	android.RegisterModuleType("art_debug_defaults", artDebugDefaultsFactory)
233}
234
235func artGlobalDefaultsFactory() (blueprint.Module, []interface{}) {
236	module, props := artDefaultsFactory()
237	android.AddLoadHook(module, globalDefaults)
238
239	return module, props
240}
241
242func artDebugDefaultsFactory() (blueprint.Module, []interface{}) {
243	module, props := artDefaultsFactory()
244	android.AddLoadHook(module, debugDefaults)
245
246	return module, props
247}
248
249func artDefaultsFactory() (blueprint.Module, []interface{}) {
250	c := &codegenProperties{}
251	module, props := cc.DefaultsFactory(c)
252	android.AddLoadHook(module, func(ctx android.LoadHookContext) { codegen(ctx, c, true) })
253
254	return module, props
255}
256
257func artLibrary() (blueprint.Module, []interface{}) {
258	library, _ := cc.NewLibrary(android.HostAndDeviceSupported)
259	module, props := library.Init()
260
261	props = installCodegenCustomizer(module, props, true)
262
263	return module, props
264}
265
266func artBinary() (blueprint.Module, []interface{}) {
267	binary, _ := cc.NewBinary(android.HostAndDeviceSupported)
268	module, props := binary.Init()
269
270	android.AddLoadHook(module, customLinker)
271	android.AddLoadHook(module, prefer32Bit)
272	return module, props
273}
274
275func artTest() (blueprint.Module, []interface{}) {
276	test := cc.NewTest(android.HostAndDeviceSupported)
277	module, props := test.Init()
278
279	props = installCodegenCustomizer(module, props, false)
280
281	android.AddLoadHook(module, customLinker)
282	android.AddLoadHook(module, prefer32Bit)
283	android.AddInstallHook(module, testInstall)
284	return module, props
285}
286
287func artTestLibrary() (blueprint.Module, []interface{}) {
288	test := cc.NewTestLibrary(android.HostAndDeviceSupported)
289	module, props := test.Init()
290
291	props = installCodegenCustomizer(module, props, false)
292
293	android.AddLoadHook(module, prefer32Bit)
294	android.AddInstallHook(module, testInstall)
295	return module, props
296}
297
298func envDefault(ctx android.BaseContext, key string, defaultValue string) string {
299	ret := ctx.AConfig().Getenv(key)
300	if ret == "" {
301		return defaultValue
302	}
303	return ret
304}
305
306func envTrue(ctx android.BaseContext, key string) bool {
307	return ctx.AConfig().Getenv(key) == "true"
308}
309
310func envFalse(ctx android.BaseContext, key string) bool {
311	return ctx.AConfig().Getenv(key) == "false"
312}
313