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