• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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