• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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	"fmt"
19	"path/filepath"
20	"strings"
21	"sync"
22
23	"github.com/google/blueprint/proptools"
24
25	"android/soong/android"
26	"android/soong/cc"
27	"android/soong/cc/config"
28)
29
30var supportedArches = []string{"arm", "arm64", "riscv64", "x86", "x86_64"}
31
32func globalFlags(ctx android.LoadHookContext) ([]string, []string) {
33	var cflags []string
34	var asflags []string
35
36	opt := ctx.Config().GetenvWithDefault("ART_NDEBUG_OPT_FLAG", "-O3")
37	cflags = append(cflags, opt)
38
39	tlab := false
40	gcType := ctx.Config().GetenvWithDefault("ART_DEFAULT_GC_TYPE", "CMC")
41
42	if ctx.Config().IsEnvTrue("ART_TEST_DEBUG_GC") {
43		gcType = "SS"
44		tlab = true
45	}
46
47	if ctx.Config().IsEnvTrue("ART_USE_RESTRICTED_MODE") {
48		cflags = append(cflags, "-DART_USE_RESTRICTED_MODE=1")
49		asflags = append(asflags, "-DART_USE_RESTRICTED_MODE=1")
50
51		// TODO(Simulator): Support other GC types.
52		gcType = "MS"
53	}
54
55	if ctx.Config().IsEnvTrue("ART_USE_SIMULATOR") {
56		cflags = append(cflags, "-DART_USE_SIMULATOR=1")
57		asflags = append(asflags, "-DART_USE_SIMULATOR=1")
58	}
59
60	cflags = append(cflags, "-DART_DEFAULT_GC_TYPE_IS_"+gcType)
61
62	if ctx.Config().IsEnvTrue("ART_HEAP_POISONING") {
63		cflags = append(cflags, "-DART_HEAP_POISONING=1")
64		asflags = append(asflags, "-DART_HEAP_POISONING=1")
65	}
66	if ctx.Config().IsEnvTrue("ART_USE_CXX_INTERPRETER") {
67		cflags = append(cflags, "-DART_USE_CXX_INTERPRETER=1")
68	}
69
70	// TODO: deprecate and then eventually remove ART_USE_GENERATIONAL_CC in favor of
71	// ART_USE_GENERATIONAL_GC
72	if !ctx.Config().IsEnvFalse("ART_USE_READ_BARRIER") && ctx.Config().ArtUseReadBarrier() &&
73	   !ctx.Config().IsEnvTrue("ART_USE_RESTRICTED_MODE") {
74		// Used to change the read barrier type. Valid values are BAKER, TABLELOOKUP.
75		// The default is BAKER.
76		barrierType := ctx.Config().GetenvWithDefault("ART_READ_BARRIER_TYPE", "BAKER")
77		cflags = append(cflags,
78			"-DART_USE_READ_BARRIER=1",
79			"-DART_READ_BARRIER_TYPE_IS_"+barrierType+"=1")
80		asflags = append(asflags,
81			"-DART_USE_READ_BARRIER=1",
82			"-DART_READ_BARRIER_TYPE_IS_"+barrierType+"=1")
83
84		if !(ctx.Config().IsEnvFalse("ART_USE_GENERATIONAL_CC") ||
85		     ctx.Config().IsEnvFalse("ART_USE_GENERATIONAL_GC")) {
86			cflags = append(cflags, "-DART_USE_GENERATIONAL_GC=1")
87		}
88		// Force CC only if ART_USE_READ_BARRIER was set to true explicitly during
89		// build time.
90		if ctx.Config().IsEnvTrue("ART_USE_READ_BARRIER") {
91			cflags = append(cflags, "-DART_FORCE_USE_READ_BARRIER=1")
92		}
93		tlab = true
94	} else if gcType == "CMC" {
95		tlab = true
96		if !(ctx.Config().IsEnvFalse("ART_USE_GENERATIONAL_CC") ||
97		     ctx.Config().IsEnvFalse("ART_USE_GENERATIONAL_GC")) {
98			cflags = append(cflags, "-DART_USE_GENERATIONAL_GC=1")
99		}
100	}
101
102	if tlab {
103		cflags = append(cflags, "-DART_USE_TLAB=1")
104	}
105
106	if ctx.Config().IsEnvTrue("ART_FORCE_TRY_PREDICATED_SIMD") {
107		cflags = append(cflags, "-DART_FORCE_TRY_PREDICATED_SIMD=1")
108	}
109
110	// We need larger stack overflow guards for ASAN, as the compiled code will have
111	// larger frame sizes. For simplicity, just use global not-target-specific cflags.
112	// Note: We increase this for both debug and non-debug, as the overflow gap will
113	//       be compiled into managed code. We always preopt (and build core images) with
114	//       the debug version. So make the gap consistent (and adjust for the worst).
115	if len(ctx.Config().SanitizeDevice()) > 0 || len(ctx.Config().SanitizeHost()) > 0 {
116		cflags = append(cflags,
117			"-DART_STACK_OVERFLOW_GAP_arm=16384",
118			"-DART_STACK_OVERFLOW_GAP_arm64=16384",
119			"-DART_STACK_OVERFLOW_GAP_riscv64=16384",
120			"-DART_STACK_OVERFLOW_GAP_x86=16384",
121			"-DART_STACK_OVERFLOW_GAP_x86_64=20480")
122	} else {
123		cflags = append(cflags,
124			"-DART_STACK_OVERFLOW_GAP_arm=8192",
125			"-DART_STACK_OVERFLOW_GAP_arm64=8192",
126			"-DART_STACK_OVERFLOW_GAP_riscv64=8192",
127			"-DART_STACK_OVERFLOW_GAP_x86=8192",
128			"-DART_STACK_OVERFLOW_GAP_x86_64=8192")
129	}
130
131	// This was originally coupled to targets, with the no bionic page size
132	// macro. However, we want all devices to have the same layout for Art
133	// targets. This is important to share optimizations across devices as
134	// well as to make sure all test configurations are consistent (Android
135	// shares tests between targets, and tests built with this option will
136	// only work on devices with this option.
137	// Previously contingent on  ctx.Config().NoBionicPageSizeMacro()
138	cflags = append(cflags, "-DART_PAGE_SIZE_AGNOSTIC=1")
139
140	if ctx.Config().IsEnvTrue("ART_ENABLE_ADDRESS_SANITIZER") {
141		// Used to enable full sanitization, i.e., user poisoning, under ASAN.
142		cflags = append(cflags, "-DART_ENABLE_ADDRESS_SANITIZER=1")
143		asflags = append(asflags, "-DART_ENABLE_ADDRESS_SANITIZER=1")
144	}
145
146	if !ctx.Config().IsEnvFalse("USE_D8_DESUGAR") {
147		cflags = append(cflags, "-DUSE_D8_DESUGAR=1")
148	}
149
150	return cflags, asflags
151}
152
153func deviceFlags(ctx android.LoadHookContext) []string {
154	var cflags []string
155	deviceFrameSizeLimit := 1744
156	if len(ctx.Config().SanitizeDevice()) > 0 {
157		deviceFrameSizeLimit = 7400
158	}
159	cflags = append(cflags,
160		fmt.Sprintf("-Wframe-larger-than=%d", deviceFrameSizeLimit),
161		fmt.Sprintf("-DART_FRAME_SIZE_LIMIT=%d", deviceFrameSizeLimit),
162	)
163
164	cflags = append(cflags, "-DART_BASE_ADDRESS="+ctx.Config().LibartImgDeviceBaseAddress())
165	minDelta := ctx.Config().GetenvWithDefault("LIBART_IMG_TARGET_MIN_BASE_ADDRESS_DELTA", "(-0x1000000)")
166	maxDelta := ctx.Config().GetenvWithDefault("LIBART_IMG_TARGET_MAX_BASE_ADDRESS_DELTA", "0x1000000")
167	cflags = append(cflags, "-DART_BASE_ADDRESS_MIN_DELTA="+minDelta)
168	cflags = append(cflags, "-DART_BASE_ADDRESS_MAX_DELTA="+maxDelta)
169
170	return cflags
171}
172
173func hostFlags(ctx android.LoadHookContext) []string {
174	var cflags []string
175	hostFrameSizeLimit := 1744
176	if len(ctx.Config().SanitizeHost()) > 0 {
177		// art/test/137-cfi/cfi.cc
178		// error: stack frame size of 1944 bytes in function 'Java_Main_unwindInProcess'
179		// b/249586057, need larger stack frame for newer clang compilers
180		hostFrameSizeLimit = 10000
181		// cannot add "-fsanitize-address-use-after-return=never" everywhere,
182		// or some file like compiler_driver.o can have stack frame of 30072 bytes.
183		// cflags = append(cflags, "-fsanitize-address-use-after-return=never")
184	}
185	cflags = append(cflags,
186		fmt.Sprintf("-Wframe-larger-than=%d", hostFrameSizeLimit),
187		fmt.Sprintf("-DART_FRAME_SIZE_LIMIT=%d", hostFrameSizeLimit),
188	)
189
190	cflags = append(cflags, "-DART_BASE_ADDRESS="+ctx.Config().LibartImgHostBaseAddress())
191	minDelta := ctx.Config().GetenvWithDefault("LIBART_IMG_HOST_MIN_BASE_ADDRESS_DELTA", "(-0x1000000)")
192	maxDelta := ctx.Config().GetenvWithDefault("LIBART_IMG_HOST_MAX_BASE_ADDRESS_DELTA", "0x1000000")
193	cflags = append(cflags, "-DART_BASE_ADDRESS_MIN_DELTA="+minDelta)
194	cflags = append(cflags, "-DART_BASE_ADDRESS_MAX_DELTA="+maxDelta)
195
196	if len(ctx.Config().SanitizeHost()) > 0 && !ctx.Config().IsEnvFalse("ART_ENABLE_ADDRESS_SANITIZER") {
197		// We enable full sanitization on the host by default.
198		cflags = append(cflags, "-DART_ENABLE_ADDRESS_SANITIZER=1")
199	}
200
201	clang_path := filepath.Join(config.ClangDefaultBase, ctx.Config().PrebuiltOS(), config.ClangDefaultVersion)
202	cflags = append(cflags, fmt.Sprintf("-DART_CLANG_PATH=\"%s\"", clang_path))
203
204	return cflags
205}
206
207func globalDefaults(ctx android.LoadHookContext) {
208	type props struct {
209		Target struct {
210			Android struct {
211				Cflags []string
212			}
213			Host struct {
214				Cflags []string
215			}
216		}
217		Cflags   []string
218		Asflags  []string
219		Sanitize struct {
220			Recover []string
221		}
222	}
223
224	p := &props{}
225	p.Cflags, p.Asflags = globalFlags(ctx)
226	p.Target.Android.Cflags = deviceFlags(ctx)
227	p.Target.Host.Cflags = hostFlags(ctx)
228
229	if ctx.Config().IsEnvTrue("ART_DEX_FILE_ACCESS_TRACKING") {
230		p.Cflags = append(p.Cflags, "-DART_DEX_FILE_ACCESS_TRACKING")
231		p.Sanitize.Recover = []string{
232			"address",
233		}
234	}
235
236	ctx.AppendProperties(p)
237}
238
239// Hook that adds flags that are implicit for all cc_art_* modules.
240func addImplicitFlags(ctx android.LoadHookContext) {
241	type props struct {
242		Target struct {
243			Android struct {
244				Cflags []string
245			}
246		}
247	}
248
249	p := &props{}
250	if ctx.Config().IsEnvTrue("ART_TARGET_LINUX") {
251		p.Target.Android.Cflags = []string{"-DART_TARGET", "-DART_TARGET_LINUX"}
252	} else {
253		p.Target.Android.Cflags = []string{"-DART_TARGET", "-DART_TARGET_ANDROID"}
254	}
255
256	ctx.AppendProperties(p)
257}
258
259func customLinker(ctx android.LoadHookContext) {
260	linker := ctx.Config().Getenv("CUSTOM_TARGET_LINKER")
261	type props struct {
262		DynamicLinker string
263	}
264
265	p := &props{}
266	if linker != "" {
267		p.DynamicLinker = linker
268	}
269
270	ctx.AppendProperties(p)
271}
272
273func prefer32Bit(ctx android.LoadHookContext) {
274	type props struct {
275		Target struct {
276			Host struct {
277				Compile_multilib *string
278			}
279		}
280	}
281
282	p := &props{}
283	if ctx.Config().IsEnvTrue("HOST_PREFER_32_BIT") {
284		p.Target.Host.Compile_multilib = proptools.StringPtr("prefer32")
285	}
286
287	// Prepend to make it overridable in the blueprints. Note that it doesn't work
288	// to override the property in a cc_defaults module.
289	ctx.PrependProperties(p)
290}
291
292var testMapKey = android.NewOnceKey("artTests")
293
294func testMap(config android.Config) map[string][]string {
295	return config.Once(testMapKey, func() interface{} {
296		return make(map[string][]string)
297	}).(map[string][]string)
298}
299
300func testInstall(ctx android.InstallHookContext) {
301	testMap := testMap(ctx.Config())
302
303	var name string
304	if ctx.Host() {
305		name = "host_"
306	} else {
307		name = "device_"
308	}
309	name += ctx.Arch().ArchType.String() + "_" + ctx.ModuleName()
310
311	artTestMutex.Lock()
312	defer artTestMutex.Unlock()
313
314	tests := testMap[name]
315	tests = append(tests, ctx.Path().String())
316	testMap[name] = tests
317}
318
319var testcasesContentKey = android.NewOnceKey("artTestcasesContent")
320
321func testcasesContent(config android.Config) map[string]string {
322	return config.Once(testcasesContentKey, func() interface{} {
323		return make(map[string]string)
324	}).(map[string]string)
325}
326
327// Binaries and libraries also need to be copied in the testcases directory for
328// running tests on host.  This method adds module to the list of needed files.
329// The 'key' is the file in testcases and 'value' is the path to copy it from.
330// The actual copy will be done in make since soong does not do installations.
331func addTestcasesFile(ctx android.InstallHookContext) {
332	if ctx.Os() != ctx.Config().BuildOS || ctx.Target().HostCross || ctx.Module().IsSkipInstall() {
333		return
334	}
335
336	testcasesContent := testcasesContent(ctx.Config())
337
338	artTestMutex.Lock()
339	defer artTestMutex.Unlock()
340
341	src := ctx.SrcPath().String()
342	path := strings.Split(ctx.Path().String(), "/")
343	// Keep last two parts of the install path (e.g. bin/dex2oat).
344	dst := strings.Join(path[len(path)-2:], "/")
345	if oldSrc, ok := testcasesContent[dst]; ok {
346		ctx.ModuleErrorf("Conflicting sources for %s: %s and %s", dst, oldSrc, src)
347	}
348	testcasesContent[dst] = src
349}
350
351var artTestMutex sync.Mutex
352
353func init() {
354	artModuleTypes := []string{
355		"art_cc_library",
356		"art_cc_library_static",
357		"art_cc_binary",
358		"art_cc_test",
359		"art_cc_test_library",
360		"art_cc_defaults",
361		"art_global_defaults",
362	}
363	android.AddNeverAllowRules(
364		android.NeverAllow().
365			NotIn("art", "external/vixl").
366			ModuleType(artModuleTypes...))
367
368	android.RegisterModuleType("art_cc_library", artLibrary)
369	android.RegisterModuleType("art_cc_library_static", artStaticLibrary)
370	android.RegisterModuleType("art_cc_binary", artBinary)
371	android.RegisterModuleType("art_cc_test", artTest)
372	android.RegisterModuleType("art_cc_test_library", artTestLibrary)
373	android.RegisterModuleType("art_cc_defaults", artDefaultsFactory)
374	android.RegisterModuleType("art_global_defaults", artGlobalDefaultsFactory)
375}
376
377func artGlobalDefaultsFactory() android.Module {
378	module := artDefaultsFactory()
379	android.AddLoadHook(module, addImplicitFlags)
380	android.AddLoadHook(module, globalDefaults)
381
382	return module
383}
384
385func artDefaultsFactory() android.Module {
386	c := &codegenProperties{}
387	module := cc.DefaultsFactory(c)
388	android.AddLoadHook(module, func(ctx android.LoadHookContext) { codegen(ctx, c, staticAndSharedLibrary) })
389
390	return module
391}
392
393func artLibrary() android.Module {
394	module := cc.LibraryFactory()
395
396	installCodegenCustomizer(module, staticAndSharedLibrary)
397
398	android.AddLoadHook(module, addImplicitFlags)
399	android.AddInstallHook(module, addTestcasesFile)
400	return module
401}
402
403func artStaticLibrary() android.Module {
404	module := cc.LibraryStaticFactory()
405
406	installCodegenCustomizer(module, staticLibrary)
407
408	android.AddLoadHook(module, addImplicitFlags)
409	return module
410}
411
412func artBinary() android.Module {
413	module := cc.BinaryFactory()
414
415	android.AddLoadHook(module, addImplicitFlags)
416	android.AddLoadHook(module, customLinker)
417	android.AddLoadHook(module, prefer32Bit)
418	android.AddInstallHook(module, addTestcasesFile)
419	return module
420}
421
422func artTest() android.Module {
423	module := cc.NewTest(android.HostAndDeviceSupported).Init()
424
425	installCodegenCustomizer(module, binary)
426
427	android.AddLoadHook(module, addImplicitFlags)
428	android.AddLoadHook(module, customLinker)
429	android.AddLoadHook(module, prefer32Bit)
430	android.AddInstallHook(module, testInstall)
431	return module
432}
433
434func artTestLibrary() android.Module {
435	module := cc.TestLibraryFactory()
436
437	installCodegenCustomizer(module, staticAndSharedLibrary)
438
439	android.AddLoadHook(module, addImplicitFlags)
440	android.AddLoadHook(module, prefer32Bit)
441	android.AddInstallHook(module, testInstall)
442	return module
443}
444