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