1// Copyright 2016 Google Inc. All rights reserved. 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 android 16 17import ( 18 "fmt" 19 "testing" 20 21 "github.com/google/blueprint" 22) 23 24func TestPrebuilts(t *testing.T) { 25 buildOS := TestArchConfig(t.TempDir(), nil, "", nil).BuildOS 26 27 var prebuiltsTests = []struct { 28 name string 29 replaceBp bool // modules is added to default bp boilerplate if false. 30 modules string 31 prebuilt []OsType 32 preparer FixturePreparer 33 }{ 34 { 35 name: "no prebuilt", 36 modules: ` 37 source { 38 name: "bar", 39 }`, 40 prebuilt: nil, 41 }, 42 { 43 name: "no source prebuilt not preferred", 44 modules: ` 45 prebuilt { 46 name: "bar", 47 prefer: false, 48 srcs: ["prebuilt_file"], 49 }`, 50 prebuilt: []OsType{Android, buildOS}, 51 }, 52 { 53 name: "no source prebuilt preferred", 54 modules: ` 55 prebuilt { 56 name: "bar", 57 prefer: true, 58 srcs: ["prebuilt_file"], 59 }`, 60 prebuilt: []OsType{Android, buildOS}, 61 }, 62 { 63 name: "prebuilt not preferred", 64 modules: ` 65 source { 66 name: "bar", 67 } 68 69 prebuilt { 70 name: "bar", 71 prefer: false, 72 srcs: ["prebuilt_file"], 73 }`, 74 prebuilt: nil, 75 }, 76 { 77 name: "prebuilt preferred", 78 modules: ` 79 source { 80 name: "bar", 81 } 82 83 prebuilt { 84 name: "bar", 85 prefer: true, 86 srcs: ["prebuilt_file"], 87 }`, 88 prebuilt: []OsType{Android, buildOS}, 89 }, 90 { 91 name: "prebuilt no file not preferred", 92 modules: ` 93 source { 94 name: "bar", 95 } 96 97 prebuilt { 98 name: "bar", 99 prefer: false, 100 }`, 101 prebuilt: nil, 102 }, 103 { 104 name: "prebuilt no file preferred", 105 modules: ` 106 source { 107 name: "bar", 108 } 109 110 prebuilt { 111 name: "bar", 112 prefer: true, 113 }`, 114 prebuilt: nil, 115 }, 116 { 117 name: "prebuilt file from filegroup preferred", 118 modules: ` 119 filegroup { 120 name: "fg", 121 srcs: ["prebuilt_file"], 122 } 123 prebuilt { 124 name: "bar", 125 prefer: true, 126 srcs: [":fg"], 127 }`, 128 prebuilt: []OsType{Android, buildOS}, 129 }, 130 { 131 name: "prebuilt module for device only", 132 modules: ` 133 source { 134 name: "bar", 135 } 136 137 prebuilt { 138 name: "bar", 139 host_supported: false, 140 prefer: true, 141 srcs: ["prebuilt_file"], 142 }`, 143 prebuilt: []OsType{Android}, 144 }, 145 { 146 name: "prebuilt file for host only", 147 modules: ` 148 source { 149 name: "bar", 150 } 151 152 prebuilt { 153 name: "bar", 154 prefer: true, 155 target: { 156 host: { 157 srcs: ["prebuilt_file"], 158 }, 159 }, 160 }`, 161 prebuilt: []OsType{buildOS}, 162 }, 163 { 164 name: "prebuilt override not preferred", 165 modules: ` 166 source { 167 name: "baz", 168 } 169 170 override_source { 171 name: "bar", 172 base: "baz", 173 } 174 175 prebuilt { 176 name: "bar", 177 prefer: false, 178 srcs: ["prebuilt_file"], 179 }`, 180 prebuilt: nil, 181 }, 182 { 183 name: "prebuilt override preferred", 184 modules: ` 185 source { 186 name: "baz", 187 } 188 189 override_source { 190 name: "bar", 191 base: "baz", 192 } 193 194 prebuilt { 195 name: "bar", 196 prefer: true, 197 srcs: ["prebuilt_file"], 198 }`, 199 prebuilt: []OsType{Android, buildOS}, 200 }, 201 { 202 name: "prebuilt including default-disabled OS", 203 replaceBp: true, 204 modules: ` 205 source { 206 name: "foo", 207 deps: [":bar"], 208 target: { 209 windows: { 210 enabled: true, 211 }, 212 }, 213 } 214 215 source { 216 name: "bar", 217 target: { 218 windows: { 219 enabled: true, 220 }, 221 }, 222 } 223 224 prebuilt { 225 name: "bar", 226 prefer: true, 227 srcs: ["prebuilt_file"], 228 target: { 229 windows: { 230 enabled: true, 231 }, 232 }, 233 }`, 234 prebuilt: []OsType{Android, buildOS, Windows}, 235 }, 236 { 237 name: "fall back to source for default-disabled OS", 238 replaceBp: true, 239 modules: ` 240 source { 241 name: "foo", 242 deps: [":bar"], 243 target: { 244 windows: { 245 enabled: true, 246 }, 247 }, 248 } 249 250 source { 251 name: "bar", 252 target: { 253 windows: { 254 enabled: true, 255 }, 256 }, 257 } 258 259 prebuilt { 260 name: "bar", 261 prefer: true, 262 srcs: ["prebuilt_file"], 263 }`, 264 prebuilt: []OsType{Android, buildOS}, 265 }, 266 { 267 name: "prebuilt properties customizable", 268 replaceBp: true, 269 modules: ` 270 source { 271 name: "foo", 272 deps: [":bar"], 273 } 274 275 soong_config_module_type { 276 name: "prebuilt_with_config", 277 module_type: "prebuilt", 278 config_namespace: "any_namespace", 279 bool_variables: ["bool_var"], 280 properties: ["prefer"], 281 } 282 283 prebuilt_with_config { 284 name: "bar", 285 prefer: true, 286 srcs: ["prebuilt_file"], 287 soong_config_variables: { 288 bool_var: { 289 prefer: false, 290 conditions_default: { 291 prefer: true, 292 }, 293 }, 294 }, 295 }`, 296 prebuilt: []OsType{Android, buildOS}, 297 }, 298 { 299 name: "prebuilt use_source_config_var={acme, use_source} - no var specified", 300 modules: ` 301 source { 302 name: "bar", 303 } 304 305 prebuilt { 306 name: "bar", 307 use_source_config_var: {config_namespace: "acme", var_name: "use_source"}, 308 srcs: ["prebuilt_file"], 309 }`, 310 // When use_source_env is specified then it will use the prebuilt by default if the environment 311 // variable is not set. 312 prebuilt: []OsType{Android, buildOS}, 313 }, 314 { 315 name: "prebuilt use_source_config_var={acme, use_source} - acme_use_source=false", 316 modules: ` 317 source { 318 name: "bar", 319 } 320 321 prebuilt { 322 name: "bar", 323 use_source_config_var: {config_namespace: "acme", var_name: "use_source"}, 324 srcs: ["prebuilt_file"], 325 }`, 326 preparer: FixtureModifyProductVariables(func(variables FixtureProductVariables) { 327 variables.VendorVars = map[string]map[string]string{ 328 "acme": { 329 "use_source": "false", 330 }, 331 } 332 }), 333 // Setting the environment variable named in use_source_env to false will cause the prebuilt to 334 // be used. 335 prebuilt: []OsType{Android, buildOS}, 336 }, 337 { 338 name: "prebuilt use_source_config_var={acme, use_source} - acme_use_source=true", 339 modules: ` 340 source { 341 name: "bar", 342 } 343 344 prebuilt { 345 name: "bar", 346 use_source_config_var: {config_namespace: "acme", var_name: "use_source"}, 347 srcs: ["prebuilt_file"], 348 }`, 349 preparer: FixtureModifyProductVariables(func(variables FixtureProductVariables) { 350 variables.VendorVars = map[string]map[string]string{ 351 "acme": { 352 "use_source": "true", 353 }, 354 } 355 }), 356 // Setting the environment variable named in use_source_env to true will cause the source to be 357 // used. 358 prebuilt: nil, 359 }, 360 { 361 name: "prebuilt use_source_config_var={acme, use_source} - acme_use_source=true, no source", 362 modules: ` 363 prebuilt { 364 name: "bar", 365 use_source_config_var: {config_namespace: "acme", var_name: "use_source"}, 366 srcs: ["prebuilt_file"], 367 }`, 368 preparer: FixtureModifyProductVariables(func(variables FixtureProductVariables) { 369 variables.VendorVars = map[string]map[string]string{ 370 "acme": { 371 "use_source": "true", 372 }, 373 } 374 }), 375 // Although the environment variable says to use source there is no source available. 376 prebuilt: []OsType{Android, buildOS}, 377 }, 378 } 379 380 fs := MockFS{ 381 "prebuilt_file": nil, 382 "source_file": nil, 383 } 384 385 for _, test := range prebuiltsTests { 386 t.Run(test.name, func(t *testing.T) { 387 bp := test.modules 388 if !test.replaceBp { 389 bp = bp + ` 390 source { 391 name: "foo", 392 deps: [":bar"], 393 }` 394 } 395 396 // Add windows to the target list to test the logic when a variant is 397 // disabled by default. 398 if !Windows.DefaultDisabled { 399 t.Errorf("windows is assumed to be disabled by default") 400 } 401 402 result := GroupFixturePreparers( 403 PrepareForTestWithArchMutator, 404 PrepareForTestWithPrebuilts, 405 PrepareForTestWithOverrides, 406 PrepareForTestWithFilegroup, 407 // Add a Windows target to the configuration. 408 FixtureModifyConfig(func(config Config) { 409 config.Targets[Windows] = []Target{ 410 {Windows, Arch{ArchType: X86_64}, NativeBridgeDisabled, "", "", true}, 411 } 412 }), 413 fs.AddToFixture(), 414 FixtureRegisterWithContext(registerTestPrebuiltModules), 415 OptionalFixturePreparer(test.preparer), 416 ).RunTestWithBp(t, bp) 417 418 for _, variant := range result.ModuleVariantsForTests("foo") { 419 foo := result.ModuleForTests("foo", variant) 420 t.Run(foo.Module().Target().Os.String(), func(t *testing.T) { 421 var dependsOnSourceModule, dependsOnPrebuiltModule bool 422 result.VisitDirectDeps(foo.Module(), func(m blueprint.Module) { 423 if _, ok := m.(*sourceModule); ok { 424 dependsOnSourceModule = true 425 } 426 if p, ok := m.(*prebuiltModule); ok { 427 dependsOnPrebuiltModule = true 428 if !p.Prebuilt().properties.UsePrebuilt { 429 t.Errorf("dependency on prebuilt module not marked used") 430 } 431 } 432 }) 433 434 moduleIsDisabled := !foo.Module().Enabled() 435 deps := foo.Module().(*sourceModule).deps 436 if moduleIsDisabled { 437 if len(deps) > 0 { 438 t.Errorf("disabled module got deps: %v", deps) 439 } 440 } else { 441 if len(deps) != 1 { 442 t.Errorf("deps does not have single path, but is %v", deps) 443 } 444 } 445 446 var usingSourceFile, usingPrebuiltFile bool 447 if len(deps) > 0 && deps[0].String() == "source_file" { 448 usingSourceFile = true 449 } 450 if len(deps) > 0 && deps[0].String() == "prebuilt_file" { 451 usingPrebuiltFile = true 452 } 453 454 prebuilt := false 455 for _, os := range test.prebuilt { 456 if os == foo.Module().Target().Os { 457 prebuilt = true 458 } 459 } 460 461 if prebuilt { 462 if moduleIsDisabled { 463 t.Errorf("dependent module for prebuilt is disabled") 464 } 465 466 if !dependsOnPrebuiltModule { 467 t.Errorf("doesn't depend on prebuilt module") 468 } 469 if !usingPrebuiltFile { 470 t.Errorf("doesn't use prebuilt_file") 471 } 472 473 if dependsOnSourceModule { 474 t.Errorf("depends on source module") 475 } 476 if usingSourceFile { 477 t.Errorf("using source_file") 478 } 479 } else if !moduleIsDisabled { 480 if dependsOnPrebuiltModule { 481 t.Errorf("depends on prebuilt module") 482 } 483 if usingPrebuiltFile { 484 t.Errorf("using prebuilt_file") 485 } 486 487 if !dependsOnSourceModule { 488 t.Errorf("doesn't depend on source module") 489 } 490 if !usingSourceFile { 491 t.Errorf("doesn't use source_file") 492 } 493 } 494 }) 495 } 496 }) 497 } 498} 499 500func registerTestPrebuiltBuildComponents(ctx RegistrationContext) { 501 registerTestPrebuiltModules(ctx) 502 503 RegisterPrebuiltMutators(ctx) 504 ctx.PostDepsMutators(RegisterOverridePostDepsMutators) 505} 506 507var prepareForTestWithFakePrebuiltModules = FixtureRegisterWithContext(registerTestPrebuiltModules) 508 509func registerTestPrebuiltModules(ctx RegistrationContext) { 510 ctx.RegisterModuleType("prebuilt", newPrebuiltModule) 511 ctx.RegisterModuleType("source", newSourceModule) 512 ctx.RegisterModuleType("override_source", newOverrideSourceModule) 513 ctx.RegisterModuleType("soong_config_module_type", SoongConfigModuleTypeFactory) 514 ctx.RegisterModuleType("soong_config_string_variable", SoongConfigStringVariableDummyFactory) 515 ctx.RegisterModuleType("soong_config_bool_variable", SoongConfigBoolVariableDummyFactory) 516} 517 518type prebuiltModule struct { 519 ModuleBase 520 prebuilt Prebuilt 521 properties struct { 522 Srcs []string `android:"path,arch_variant"` 523 } 524 src Path 525} 526 527func newPrebuiltModule() Module { 528 m := &prebuiltModule{} 529 m.AddProperties(&m.properties) 530 InitPrebuiltModule(m, &m.properties.Srcs) 531 InitAndroidArchModule(m, HostAndDeviceDefault, MultilibCommon) 532 return m 533} 534 535func (p *prebuiltModule) Name() string { 536 return p.prebuilt.Name(p.ModuleBase.Name()) 537} 538 539func (p *prebuiltModule) GenerateAndroidBuildActions(ctx ModuleContext) { 540 if len(p.properties.Srcs) >= 1 { 541 p.src = p.prebuilt.SingleSourcePath(ctx) 542 } 543} 544 545func (p *prebuiltModule) Prebuilt() *Prebuilt { 546 return &p.prebuilt 547} 548 549func (p *prebuiltModule) OutputFiles(tag string) (Paths, error) { 550 switch tag { 551 case "": 552 return Paths{p.src}, nil 553 default: 554 return nil, fmt.Errorf("unsupported module reference tag %q", tag) 555 } 556} 557 558type sourceModuleProperties struct { 559 Deps []string `android:"path,arch_variant"` 560} 561 562type sourceModule struct { 563 ModuleBase 564 OverridableModuleBase 565 566 properties sourceModuleProperties 567 dependsOnSourceModule, dependsOnPrebuiltModule bool 568 deps Paths 569 src Path 570} 571 572func newSourceModule() Module { 573 m := &sourceModule{} 574 m.AddProperties(&m.properties) 575 InitAndroidArchModule(m, HostAndDeviceDefault, MultilibCommon) 576 InitOverridableModule(m, nil) 577 return m 578} 579 580func (s *sourceModule) OverridablePropertiesDepsMutator(ctx BottomUpMutatorContext) { 581 // s.properties.Deps are annotated with android:path, so they are 582 // automatically added to the dependency by pathDeps mutator 583} 584 585func (s *sourceModule) GenerateAndroidBuildActions(ctx ModuleContext) { 586 s.deps = PathsForModuleSrc(ctx, s.properties.Deps) 587 s.src = PathForModuleSrc(ctx, "source_file") 588} 589 590func (s *sourceModule) Srcs() Paths { 591 return Paths{s.src} 592} 593 594type overrideSourceModule struct { 595 ModuleBase 596 OverrideModuleBase 597} 598 599func (o *overrideSourceModule) GenerateAndroidBuildActions(_ ModuleContext) { 600} 601 602func newOverrideSourceModule() Module { 603 m := &overrideSourceModule{} 604 m.AddProperties(&sourceModuleProperties{}) 605 606 InitAndroidArchModule(m, HostAndDeviceDefault, MultilibCommon) 607 InitOverrideModule(m) 608 return m 609} 610