• 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 phony
16
17import (
18	"fmt"
19	"io"
20	"strings"
21
22	"android/soong/android"
23
24	"github.com/google/blueprint/proptools"
25)
26
27func init() {
28	registerPhonyModuleTypes(android.InitRegistrationContext)
29}
30
31func registerPhonyModuleTypes(ctx android.RegistrationContext) {
32	ctx.RegisterModuleType("phony", PhonyFactory)
33	ctx.RegisterModuleType("phony_rule", PhonyRuleFactory)
34	ctx.RegisterModuleType("phony_rule_defaults", PhonyRuleDefaultsFactory)
35}
36
37var PrepareForTestWithPhony = android.FixtureRegisterWithContext(registerPhonyModuleTypes)
38
39type phony struct {
40	android.ModuleBase
41
42	requiredModuleNames       []string
43	hostRequiredModuleNames   []string
44	targetRequiredModuleNames []string
45	outputDeps                android.Paths
46}
47
48func PhonyFactory() android.Module {
49	module := &phony{}
50
51	android.InitAndroidArchModule(module, android.HostAndDeviceSupported, android.MultilibCommon)
52	return module
53}
54
55func (p *phony) GenerateAndroidBuildActions(ctx android.ModuleContext) {
56	p.requiredModuleNames = ctx.RequiredModuleNames(ctx)
57	p.hostRequiredModuleNames = ctx.HostRequiredModuleNames()
58	p.targetRequiredModuleNames = ctx.TargetRequiredModuleNames()
59
60	ctx.VisitDirectDepsWithTag(android.RequiredDepTag, func(dep android.Module) {
61		if o, ok := android.OtherModuleProvider(ctx, dep, android.OutputFilesProvider); ok {
62			p.outputDeps = append(p.outputDeps, o.DefaultOutputFiles...)
63		}
64	})
65
66	ctx.Phony(p.Name(), p.outputDeps...)
67}
68
69func (p *phony) AndroidMk() android.AndroidMkData {
70	return android.AndroidMkData{
71		Custom: func(w io.Writer, name, prefix, moduleDir string, data android.AndroidMkData) {
72			fmt.Fprintln(w, "\ninclude $(CLEAR_VARS)", " # phony.phony")
73			fmt.Fprintln(w, "LOCAL_PATH :=", moduleDir)
74			fmt.Fprintln(w, "LOCAL_MODULE :=", name)
75			if p.Host() {
76				fmt.Fprintln(w, "LOCAL_IS_HOST_MODULE := true")
77			}
78			if len(p.requiredModuleNames) > 0 {
79				fmt.Fprintln(w, "LOCAL_REQUIRED_MODULES :=",
80					strings.Join(p.requiredModuleNames, " "))
81			}
82			if len(p.hostRequiredModuleNames) > 0 {
83				fmt.Fprintln(w, "LOCAL_HOST_REQUIRED_MODULES :=",
84					strings.Join(p.hostRequiredModuleNames, " "))
85			}
86			if len(p.targetRequiredModuleNames) > 0 {
87				fmt.Fprintln(w, "LOCAL_TARGET_REQUIRED_MODULES :=",
88					strings.Join(p.targetRequiredModuleNames, " "))
89			}
90			if len(p.outputDeps) > 0 {
91				fmt.Fprintln(w, "LOCAL_ADDITIONAL_DEPENDENCIES :=",
92					strings.Join(p.outputDeps.Strings(), " "))
93			}
94			// AconfigUpdateAndroidMkData may have added elements to Extra.  Process them here.
95			for _, extra := range data.Extra {
96				extra(w, nil)
97			}
98			fmt.Fprintln(w, "include $(BUILD_PHONY_PACKAGE)")
99		},
100	}
101}
102
103type PhonyRule struct {
104	android.ModuleBase
105	android.DefaultableModuleBase
106
107	properties PhonyProperties
108}
109
110type PhonyProperties struct {
111	// The Phony_deps is the set of all dependencies for this target,
112	// and it can function similarly to .PHONY in a makefile.
113	// Additionally, dependencies within it can even include genrule.
114	Phony_deps proptools.Configurable[[]string]
115}
116
117// The phony_rule provides functionality similar to the .PHONY in a makefile.
118// It can create a phony target and include relevant dependencies associated with it.
119func PhonyRuleFactory() android.Module {
120	module := &PhonyRule{}
121	android.InitAndroidModule(module)
122	module.AddProperties(&module.properties)
123	android.InitDefaultableModule(module)
124	return module
125}
126
127func (p *PhonyRule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
128	for _, dep := range p.properties.Phony_deps.GetOrDefault(ctx, nil) {
129		ctx.Phony(ctx.ModuleName(), android.PathForPhony(ctx, dep))
130	}
131}
132
133// PhonyRuleDefaults
134type PhonyRuleDefaults struct {
135	android.ModuleBase
136	android.DefaultsModuleBase
137}
138
139// phony_rule_defaults provides a set of properties that can be inherited by other phony_rules.
140//
141// A module can use the properties from a phony_rule_defaults module using `defaults: ["defaults_module_name"]`.  Each
142// property in the defaults module that exists in the depending module will be prepended to the depending module's
143// value for that property.
144//
145// Example:
146//
147//	phony_rule_defaults {
148//	    name: "add_module1_defaults",
149//	    phony_deps: [
150//	        "module1",
151//	    ],
152//	}
153//
154//	phony_rule {
155//	    name: "example",
156//	    defaults: ["add_module1_defaults"],
157//	}
158//
159// is functionally identical to:
160//
161//	phony_rule {
162//	    name: "example",
163//	    phony_deps: [
164//	        "module1",
165//	    ],
166//	}
167func PhonyRuleDefaultsFactory() android.Module {
168	module := &PhonyRuleDefaults{}
169	module.AddProperties(&PhonyProperties{})
170	android.InitDefaultsModule(module)
171
172	return module
173}
174