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 264func TestPrebuilts(t *testing.T) { 265 fs := map[string][]byte{ 266 "prebuilt_file": nil, 267 "source_file": nil, 268 } 269 270 for _, test := range prebuiltsTests { 271 t.Run(test.name, func(t *testing.T) { 272 bp := test.modules 273 if !test.replaceBp { 274 bp = bp + ` 275 source { 276 name: "foo", 277 deps: [":bar"], 278 }` 279 } 280 config := TestArchConfig(buildDir, nil, bp, fs) 281 282 // Add windows to the target list to test the logic when a variant is 283 // disabled by default. 284 if !Windows.DefaultDisabled { 285 t.Errorf("windows is assumed to be disabled by default") 286 } 287 config.config.Targets[Windows] = []Target{ 288 {Windows, Arch{ArchType: X86_64}, NativeBridgeDisabled, "", ""}, 289 } 290 291 ctx := NewTestArchContext() 292 registerTestPrebuiltBuildComponents(ctx) 293 ctx.RegisterModuleType("filegroup", FileGroupFactory) 294 ctx.Register(config) 295 296 _, errs := ctx.ParseBlueprintsFiles("Android.bp") 297 FailIfErrored(t, errs) 298 _, errs = ctx.PrepareBuildActions(config) 299 FailIfErrored(t, errs) 300 301 for _, variant := range ctx.ModuleVariantsForTests("foo") { 302 foo := ctx.ModuleForTests("foo", variant) 303 t.Run(foo.Module().Target().Os.String(), func(t *testing.T) { 304 var dependsOnSourceModule, dependsOnPrebuiltModule bool 305 ctx.VisitDirectDeps(foo.Module(), func(m blueprint.Module) { 306 if _, ok := m.(*sourceModule); ok { 307 dependsOnSourceModule = true 308 } 309 if p, ok := m.(*prebuiltModule); ok { 310 dependsOnPrebuiltModule = true 311 if !p.Prebuilt().properties.UsePrebuilt { 312 t.Errorf("dependency on prebuilt module not marked used") 313 } 314 } 315 }) 316 317 moduleIsDisabled := !foo.Module().Enabled() 318 deps := foo.Module().(*sourceModule).deps 319 if moduleIsDisabled { 320 if len(deps) > 0 { 321 t.Errorf("disabled module got deps: %v", deps) 322 } 323 } else { 324 if len(deps) != 1 { 325 t.Errorf("deps does not have single path, but is %v", deps) 326 } 327 } 328 329 var usingSourceFile, usingPrebuiltFile bool 330 if len(deps) > 0 && deps[0].String() == "source_file" { 331 usingSourceFile = true 332 } 333 if len(deps) > 0 && deps[0].String() == "prebuilt_file" { 334 usingPrebuiltFile = true 335 } 336 337 prebuilt := false 338 for _, os := range test.prebuilt { 339 if os == foo.Module().Target().Os { 340 prebuilt = true 341 } 342 } 343 344 if prebuilt { 345 if moduleIsDisabled { 346 t.Errorf("dependent module for prebuilt is disabled") 347 } 348 349 if !dependsOnPrebuiltModule { 350 t.Errorf("doesn't depend on prebuilt module") 351 } 352 if !usingPrebuiltFile { 353 t.Errorf("doesn't use prebuilt_file") 354 } 355 356 if dependsOnSourceModule { 357 t.Errorf("depends on source module") 358 } 359 if usingSourceFile { 360 t.Errorf("using source_file") 361 } 362 } else if !moduleIsDisabled { 363 if dependsOnPrebuiltModule { 364 t.Errorf("depends on prebuilt module") 365 } 366 if usingPrebuiltFile { 367 t.Errorf("using prebuilt_file") 368 } 369 370 if !dependsOnSourceModule { 371 t.Errorf("doesn't depend on source module") 372 } 373 if !usingSourceFile { 374 t.Errorf("doesn't use source_file") 375 } 376 } 377 }) 378 } 379 }) 380 } 381} 382 383func registerTestPrebuiltBuildComponents(ctx RegistrationContext) { 384 ctx.RegisterModuleType("prebuilt", newPrebuiltModule) 385 ctx.RegisterModuleType("source", newSourceModule) 386 ctx.RegisterModuleType("override_source", newOverrideSourceModule) 387 388 RegisterPrebuiltMutators(ctx) 389 ctx.PostDepsMutators(RegisterOverridePostDepsMutators) 390} 391 392type prebuiltModule struct { 393 ModuleBase 394 prebuilt Prebuilt 395 properties struct { 396 Srcs []string `android:"path,arch_variant"` 397 } 398 src Path 399} 400 401func newPrebuiltModule() Module { 402 m := &prebuiltModule{} 403 m.AddProperties(&m.properties) 404 InitPrebuiltModule(m, &m.properties.Srcs) 405 InitAndroidArchModule(m, HostAndDeviceDefault, MultilibCommon) 406 return m 407} 408 409func (p *prebuiltModule) Name() string { 410 return p.prebuilt.Name(p.ModuleBase.Name()) 411} 412 413func (p *prebuiltModule) GenerateAndroidBuildActions(ctx ModuleContext) { 414 if len(p.properties.Srcs) >= 1 { 415 p.src = p.prebuilt.SingleSourcePath(ctx) 416 } 417} 418 419func (p *prebuiltModule) Prebuilt() *Prebuilt { 420 return &p.prebuilt 421} 422 423func (p *prebuiltModule) OutputFiles(tag string) (Paths, error) { 424 switch tag { 425 case "": 426 return Paths{p.src}, nil 427 default: 428 return nil, fmt.Errorf("unsupported module reference tag %q", tag) 429 } 430} 431 432type sourceModuleProperties struct { 433 Deps []string `android:"path,arch_variant"` 434} 435 436type sourceModule struct { 437 ModuleBase 438 OverridableModuleBase 439 440 properties sourceModuleProperties 441 dependsOnSourceModule, dependsOnPrebuiltModule bool 442 deps Paths 443 src Path 444} 445 446func newSourceModule() Module { 447 m := &sourceModule{} 448 m.AddProperties(&m.properties) 449 InitAndroidArchModule(m, HostAndDeviceDefault, MultilibCommon) 450 InitOverridableModule(m, nil) 451 return m 452} 453 454func (s *sourceModule) OverridablePropertiesDepsMutator(ctx BottomUpMutatorContext) { 455 // s.properties.Deps are annotated with android:path, so they are 456 // automatically added to the dependency by pathDeps mutator 457} 458 459func (s *sourceModule) GenerateAndroidBuildActions(ctx ModuleContext) { 460 s.deps = PathsForModuleSrc(ctx, s.properties.Deps) 461 s.src = PathForModuleSrc(ctx, "source_file") 462} 463 464func (s *sourceModule) Srcs() Paths { 465 return Paths{s.src} 466} 467 468type overrideSourceModule struct { 469 ModuleBase 470 OverrideModuleBase 471} 472 473func (o *overrideSourceModule) GenerateAndroidBuildActions(_ ModuleContext) { 474} 475 476func newOverrideSourceModule() Module { 477 m := &overrideSourceModule{} 478 m.AddProperties(&sourceModuleProperties{}) 479 480 InitAndroidArchModule(m, HostAndDeviceDefault, MultilibCommon) 481 InitOverrideModule(m) 482 return m 483} 484