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