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/apex" 20 "android/soong/cc" 21 "fmt" 22 "log" 23 "sync" 24 25 "github.com/google/blueprint/proptools" 26) 27 28var supportedArches = []string{"arm", "arm64", "mips", "mips64", "x86", "x86_64"} 29 30func globalFlags(ctx android.BaseContext) ([]string, []string) { 31 var cflags []string 32 var asflags []string 33 34 opt := envDefault(ctx, "ART_NDEBUG_OPT_FLAG", "-O3") 35 cflags = append(cflags, opt) 36 37 tlab := false 38 39 gcType := envDefault(ctx, "ART_DEFAULT_GC_TYPE", "CMS") 40 41 if envTrue(ctx, "ART_TEST_DEBUG_GC") { 42 gcType = "SS" 43 tlab = true 44 } 45 46 cflags = append(cflags, "-DART_DEFAULT_GC_TYPE_IS_"+gcType) 47 if tlab { 48 cflags = append(cflags, "-DART_USE_TLAB=1") 49 } 50 51 imtSize := envDefault(ctx, "ART_IMT_SIZE", "43") 52 cflags = append(cflags, "-DIMT_SIZE="+imtSize) 53 54 if envTrue(ctx, "ART_HEAP_POISONING") { 55 cflags = append(cflags, "-DART_HEAP_POISONING=1") 56 asflags = append(asflags, "-DART_HEAP_POISONING=1") 57 } 58 if envTrue(ctx, "ART_USE_CXX_INTERPRETER") { 59 cflags = append(cflags, "-DART_USE_CXX_INTERPRETER=1") 60 } 61 62 if !envFalse(ctx, "ART_USE_READ_BARRIER") && ctx.AConfig().ArtUseReadBarrier() { 63 // Used to change the read barrier type. Valid values are BAKER, BROOKS, 64 // TABLELOOKUP. The default is BAKER. 65 barrierType := envDefault(ctx, "ART_READ_BARRIER_TYPE", "BAKER") 66 cflags = append(cflags, 67 "-DART_USE_READ_BARRIER=1", 68 "-DART_READ_BARRIER_TYPE_IS_"+barrierType+"=1") 69 asflags = append(asflags, 70 "-DART_USE_READ_BARRIER=1", 71 "-DART_READ_BARRIER_TYPE_IS_"+barrierType+"=1") 72 } 73 74 if !envFalse(ctx, "ART_USE_GENERATIONAL_CC") { 75 cflags = append(cflags, "-DART_USE_GENERATIONAL_CC=1") 76 } 77 78 cdexLevel := envDefault(ctx, "ART_DEFAULT_COMPACT_DEX_LEVEL", "fast") 79 cflags = append(cflags, "-DART_DEFAULT_COMPACT_DEX_LEVEL="+cdexLevel) 80 81 // We need larger stack overflow guards for ASAN, as the compiled code will have 82 // larger frame sizes. For simplicity, just use global not-target-specific cflags. 83 // Note: We increase this for both debug and non-debug, as the overflow gap will 84 // be compiled into managed code. We always preopt (and build core images) with 85 // the debug version. So make the gap consistent (and adjust for the worst). 86 if len(ctx.AConfig().SanitizeDevice()) > 0 || len(ctx.AConfig().SanitizeHost()) > 0 { 87 cflags = append(cflags, 88 "-DART_STACK_OVERFLOW_GAP_arm=8192", 89 "-DART_STACK_OVERFLOW_GAP_arm64=8192", 90 "-DART_STACK_OVERFLOW_GAP_mips=16384", 91 "-DART_STACK_OVERFLOW_GAP_mips64=16384", 92 "-DART_STACK_OVERFLOW_GAP_x86=16384", 93 "-DART_STACK_OVERFLOW_GAP_x86_64=20480") 94 } else { 95 cflags = append(cflags, 96 "-DART_STACK_OVERFLOW_GAP_arm=8192", 97 "-DART_STACK_OVERFLOW_GAP_arm64=8192", 98 "-DART_STACK_OVERFLOW_GAP_mips=16384", 99 "-DART_STACK_OVERFLOW_GAP_mips64=16384", 100 "-DART_STACK_OVERFLOW_GAP_x86=8192", 101 "-DART_STACK_OVERFLOW_GAP_x86_64=8192") 102 } 103 104 if envTrue(ctx, "ART_ENABLE_ADDRESS_SANITIZER") { 105 // Used to enable full sanitization, i.e., user poisoning, under ASAN. 106 cflags = append(cflags, "-DART_ENABLE_ADDRESS_SANITIZER=1") 107 asflags = append(asflags, "-DART_ENABLE_ADDRESS_SANITIZER=1") 108 } 109 110 if envTrue(ctx, "ART_MIPS32_CHECK_ALIGNMENT") { 111 // Enable the use of MIPS32 CHECK_ALIGNMENT macro for debugging purposes 112 asflags = append(asflags, "-DART_MIPS32_CHECK_ALIGNMENT") 113 } 114 115 if envTrueOrDefault(ctx, "USE_D8_DESUGAR") { 116 cflags = append(cflags, "-DUSE_D8_DESUGAR=1") 117 } 118 119 return cflags, asflags 120} 121 122func debugFlags(ctx android.BaseContext) []string { 123 var cflags []string 124 125 opt := envDefault(ctx, "ART_DEBUG_OPT_FLAG", "-O2") 126 cflags = append(cflags, opt) 127 128 return cflags 129} 130 131func deviceFlags(ctx android.BaseContext) []string { 132 var cflags []string 133 deviceFrameSizeLimit := 1736 134 if len(ctx.AConfig().SanitizeDevice()) > 0 { 135 deviceFrameSizeLimit = 7400 136 } 137 cflags = append(cflags, 138 fmt.Sprintf("-Wframe-larger-than=%d", deviceFrameSizeLimit), 139 fmt.Sprintf("-DART_FRAME_SIZE_LIMIT=%d", deviceFrameSizeLimit), 140 ) 141 142 cflags = append(cflags, "-DART_BASE_ADDRESS="+ctx.AConfig().LibartImgDeviceBaseAddress()) 143 if envTrue(ctx, "ART_TARGET_LINUX") { 144 cflags = append(cflags, "-DART_TARGET_LINUX") 145 } else { 146 cflags = append(cflags, "-DART_TARGET_ANDROID") 147 } 148 minDelta := envDefault(ctx, "LIBART_IMG_TARGET_MIN_BASE_ADDRESS_DELTA", "-0x1000000") 149 maxDelta := envDefault(ctx, "LIBART_IMG_TARGET_MAX_BASE_ADDRESS_DELTA", "0x1000000") 150 cflags = append(cflags, "-DART_BASE_ADDRESS_MIN_DELTA="+minDelta) 151 cflags = append(cflags, "-DART_BASE_ADDRESS_MAX_DELTA="+maxDelta) 152 153 return cflags 154} 155 156func hostFlags(ctx android.BaseContext) []string { 157 var cflags []string 158 hostFrameSizeLimit := 1736 159 if len(ctx.AConfig().SanitizeHost()) > 0 { 160 // art/test/137-cfi/cfi.cc 161 // error: stack frame size of 1944 bytes in function 'Java_Main_unwindInProcess' 162 hostFrameSizeLimit = 6400 163 } 164 cflags = append(cflags, 165 fmt.Sprintf("-Wframe-larger-than=%d", hostFrameSizeLimit), 166 fmt.Sprintf("-DART_FRAME_SIZE_LIMIT=%d", hostFrameSizeLimit), 167 ) 168 169 cflags = append(cflags, "-DART_BASE_ADDRESS="+ctx.AConfig().LibartImgHostBaseAddress()) 170 minDelta := envDefault(ctx, "LIBART_IMG_HOST_MIN_BASE_ADDRESS_DELTA", "-0x1000000") 171 maxDelta := envDefault(ctx, "LIBART_IMG_HOST_MAX_BASE_ADDRESS_DELTA", "0x1000000") 172 cflags = append(cflags, "-DART_BASE_ADDRESS_MIN_DELTA="+minDelta) 173 cflags = append(cflags, "-DART_BASE_ADDRESS_MAX_DELTA="+maxDelta) 174 175 if len(ctx.AConfig().SanitizeHost()) > 0 && !envFalse(ctx, "ART_ENABLE_ADDRESS_SANITIZER") { 176 // We enable full sanitization on the host by default. 177 cflags = append(cflags, "-DART_ENABLE_ADDRESS_SANITIZER=1") 178 } 179 180 return cflags 181} 182 183func globalDefaults(ctx android.LoadHookContext) { 184 type props struct { 185 Target struct { 186 Android struct { 187 Cflags []string 188 } 189 Host struct { 190 Cflags []string 191 } 192 } 193 Cflags []string 194 Asflags []string 195 Sanitize struct { 196 Recover []string 197 } 198 } 199 200 p := &props{} 201 p.Cflags, p.Asflags = globalFlags(ctx) 202 p.Target.Android.Cflags = deviceFlags(ctx) 203 p.Target.Host.Cflags = hostFlags(ctx) 204 205 if envTrue(ctx, "ART_DEX_FILE_ACCESS_TRACKING") { 206 p.Cflags = append(p.Cflags, "-DART_DEX_FILE_ACCESS_TRACKING") 207 p.Sanitize.Recover = []string{ 208 "address", 209 } 210 } 211 212 ctx.AppendProperties(p) 213} 214 215func debugDefaults(ctx android.LoadHookContext) { 216 type props struct { 217 Cflags []string 218 } 219 220 p := &props{} 221 p.Cflags = debugFlags(ctx) 222 ctx.AppendProperties(p) 223} 224 225func customLinker(ctx android.LoadHookContext) { 226 linker := envDefault(ctx, "CUSTOM_TARGET_LINKER", "") 227 type props struct { 228 DynamicLinker string 229 } 230 231 p := &props{} 232 if linker != "" { 233 p.DynamicLinker = linker 234 } 235 236 ctx.AppendProperties(p) 237} 238 239func prefer32Bit(ctx android.LoadHookContext) { 240 type props struct { 241 Target struct { 242 Host struct { 243 Compile_multilib *string 244 } 245 } 246 } 247 248 p := &props{} 249 if envTrue(ctx, "HOST_PREFER_32_BIT") { 250 p.Target.Host.Compile_multilib = proptools.StringPtr("prefer32") 251 } 252 253 ctx.AppendProperties(p) 254} 255 256var testMapKey = android.NewOnceKey("artTests") 257 258func testMap(config android.Config) map[string][]string { 259 return config.Once(testMapKey, func() interface{} { 260 return make(map[string][]string) 261 }).(map[string][]string) 262} 263 264func testInstall(ctx android.InstallHookContext) { 265 testMap := testMap(ctx.AConfig()) 266 267 var name string 268 if ctx.Host() { 269 name = "host_" 270 } else { 271 name = "device_" 272 } 273 name += ctx.Arch().ArchType.String() + "_" + ctx.ModuleName() 274 275 artTestMutex.Lock() 276 defer artTestMutex.Unlock() 277 278 tests := testMap[name] 279 tests = append(tests, ctx.Path().RelPathString()) 280 testMap[name] = tests 281} 282 283var artTestMutex sync.Mutex 284 285func init() { 286 android.RegisterModuleType("art_cc_library", artLibrary) 287 android.RegisterModuleType("art_cc_library_static", artStaticLibrary) 288 android.RegisterModuleType("art_cc_binary", artBinary) 289 android.RegisterModuleType("art_cc_test", artTest) 290 android.RegisterModuleType("art_cc_test_library", artTestLibrary) 291 android.RegisterModuleType("art_cc_defaults", artDefaultsFactory) 292 android.RegisterModuleType("libart_cc_defaults", libartDefaultsFactory) 293 android.RegisterModuleType("libart_static_cc_defaults", libartStaticDefaultsFactory) 294 android.RegisterModuleType("art_global_defaults", artGlobalDefaultsFactory) 295 android.RegisterModuleType("art_debug_defaults", artDebugDefaultsFactory) 296 297 // TODO: This makes the module disable itself for host if HOST_PREFER_32_BIT is 298 // set. We need this because the multilib types of binaries listed in the apex 299 // rule must match the declared type. This is normally not difficult but HOST_PREFER_32_BIT 300 // changes this to 'prefer32' on all host binaries. Since HOST_PREFER_32_BIT is 301 // only used for testing we can just disable the module. 302 // See b/120617876 for more information. 303 android.RegisterModuleType("art_apex_test", artTestApexBundleFactory) 304} 305 306func artTestApexBundleFactory() android.Module { 307 module := apex.ApexBundleFactory( /*testApex*/ true) 308 android.AddLoadHook(module, func(ctx android.LoadHookContext) { 309 if envTrue(ctx, "HOST_PREFER_32_BIT") { 310 type props struct { 311 Target struct { 312 Host struct { 313 Enabled *bool 314 } 315 } 316 } 317 318 p := &props{} 319 p.Target.Host.Enabled = proptools.BoolPtr(false) 320 ctx.AppendProperties(p) 321 log.Print("Disabling host build of " + ctx.ModuleName() + " for HOST_PREFER_32_BIT=true") 322 } 323 }) 324 325 return module 326} 327 328func artGlobalDefaultsFactory() android.Module { 329 module := artDefaultsFactory() 330 android.AddLoadHook(module, globalDefaults) 331 332 return module 333} 334 335func artDebugDefaultsFactory() android.Module { 336 module := artDefaultsFactory() 337 android.AddLoadHook(module, debugDefaults) 338 339 return module 340} 341 342func artDefaultsFactory() android.Module { 343 c := &codegenProperties{} 344 module := cc.DefaultsFactory(c) 345 android.AddLoadHook(module, func(ctx android.LoadHookContext) { codegen(ctx, c, true) }) 346 347 return module 348} 349 350func libartDefaultsFactory() android.Module { 351 c := &codegenProperties{} 352 module := cc.DefaultsFactory(c) 353 android.AddLoadHook(module, func(ctx android.LoadHookContext) { codegen(ctx, c, true) }) 354 355 return module 356} 357 358func libartStaticDefaultsFactory() android.Module { 359 c := &codegenProperties{} 360 module := cc.DefaultsFactory(c) 361 android.AddLoadHook(module, func(ctx android.LoadHookContext) { codegen(ctx, c, true) }) 362 363 return module 364} 365 366func artLibrary() android.Module { 367 m, _ := cc.NewLibrary(android.HostAndDeviceSupported) 368 module := m.Init() 369 370 installCodegenCustomizer(module, true) 371 372 return module 373} 374 375func artStaticLibrary() android.Module { 376 m, library := cc.NewLibrary(android.HostAndDeviceSupported) 377 library.BuildOnlyStatic() 378 module := m.Init() 379 380 installCodegenCustomizer(module, true) 381 382 return module 383} 384 385func artBinary() android.Module { 386 binary, _ := cc.NewBinary(android.HostAndDeviceSupported) 387 module := binary.Init() 388 389 android.AddLoadHook(module, customLinker) 390 android.AddLoadHook(module, prefer32Bit) 391 return module 392} 393 394func artTest() android.Module { 395 test := cc.NewTest(android.HostAndDeviceSupported) 396 module := test.Init() 397 398 installCodegenCustomizer(module, false) 399 400 android.AddLoadHook(module, customLinker) 401 android.AddLoadHook(module, prefer32Bit) 402 android.AddInstallHook(module, testInstall) 403 return module 404} 405 406func artTestLibrary() android.Module { 407 test := cc.NewTestLibrary(android.HostAndDeviceSupported) 408 module := test.Init() 409 410 installCodegenCustomizer(module, false) 411 412 android.AddLoadHook(module, prefer32Bit) 413 android.AddInstallHook(module, testInstall) 414 return module 415} 416 417func envDefault(ctx android.BaseContext, key string, defaultValue string) string { 418 ret := ctx.AConfig().Getenv(key) 419 if ret == "" { 420 return defaultValue 421 } 422 return ret 423} 424 425func envTrue(ctx android.BaseContext, key string) bool { 426 return ctx.AConfig().Getenv(key) == "true" 427} 428 429func envFalse(ctx android.BaseContext, key string) bool { 430 return ctx.AConfig().Getenv(key) == "false" 431} 432 433func envTrueOrDefault(ctx android.BaseContext, key string) bool { 434 return ctx.AConfig().Getenv(key) != "false" 435} 436