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