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