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