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