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