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