1// Copyright 2015 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 java 16 17import ( 18 "path/filepath" 19 "strconv" 20 "strings" 21 22 "github.com/google/blueprint" 23 "github.com/google/blueprint/pathtools" 24 25 "android/soong/android" 26) 27 28func init() { 29 pctx.SourcePathVariable("logtagsCmd", "build/make/tools/java-event-log-tags.py") 30 pctx.SourcePathVariable("mergeLogtagsCmd", "build/make/tools/merge-event-log-tags.py") 31 pctx.SourcePathVariable("logtagsLib", "build/make/tools/event_log_tags.py") 32} 33 34var ( 35 logtags = pctx.AndroidStaticRule("logtags", 36 blueprint.RuleParams{ 37 Command: "$logtagsCmd -o $out $in", 38 CommandDeps: []string{"$logtagsCmd", "$logtagsLib"}, 39 }) 40 41 mergeLogtags = pctx.AndroidStaticRule("mergeLogtags", 42 blueprint.RuleParams{ 43 Command: "$mergeLogtagsCmd -o $out $in", 44 CommandDeps: []string{"$mergeLogtagsCmd", "$logtagsLib"}, 45 }) 46) 47 48func genAidl(ctx android.ModuleContext, aidlFiles android.Paths, aidlGlobalFlags string, aidlIndividualFlags map[string]string, deps android.Paths) android.Paths { 49 // Shard aidl files into groups of 50 to avoid having to recompile all of them if one changes and to avoid 50 // hitting command line length limits. 51 shards := android.ShardPaths(aidlFiles, 50) 52 53 srcJarFiles := make(android.Paths, 0, len(shards)) 54 55 for i, shard := range shards { 56 srcJarFile := android.PathForModuleGen(ctx, "aidl", "aidl"+strconv.Itoa(i)+".srcjar") 57 srcJarFiles = append(srcJarFiles, srcJarFile) 58 59 outDir := srcJarFile.ReplaceExtension(ctx, "tmp") 60 61 rule := android.NewRuleBuilder(pctx, ctx) 62 63 rule.Command().Text("rm -rf").Flag(outDir.String()) 64 rule.Command().Text("mkdir -p").Flag(outDir.String()) 65 rule.Command().Text("FLAGS=' " + aidlGlobalFlags + "'") 66 67 for _, aidlFile := range shard { 68 localFlag := aidlIndividualFlags[aidlFile.String()] 69 depFile := srcJarFile.InSameDir(ctx, aidlFile.String()+".d") 70 javaFile := outDir.Join(ctx, pathtools.ReplaceExtension(aidlFile.String(), "java")) 71 rule.Command(). 72 Tool(ctx.Config().HostToolPath(ctx, "aidl")). 73 FlagWithDepFile("-d", depFile). 74 Flag("$FLAGS"). 75 Flag(localFlag). 76 Input(aidlFile). 77 Output(javaFile). 78 Implicits(deps) 79 rule.Temporary(javaFile) 80 } 81 82 rule.Command(). 83 Tool(ctx.Config().HostToolPath(ctx, "soong_zip")). 84 Flag("-srcjar"). 85 Flag("-write_if_changed"). 86 FlagWithOutput("-o ", srcJarFile). 87 FlagWithArg("-C ", outDir.String()). 88 FlagWithArg("-D ", outDir.String()) 89 90 rule.Command().Text("rm -rf").Flag(outDir.String()) 91 92 rule.Restat() 93 94 ruleName := "aidl" 95 ruleDesc := "aidl" 96 if len(shards) > 1 { 97 ruleName += "_" + strconv.Itoa(i) 98 ruleDesc += " " + strconv.Itoa(i) 99 } 100 101 rule.Build(ruleName, ruleDesc) 102 } 103 104 return srcJarFiles 105} 106 107func genLogtags(ctx android.ModuleContext, logtagsFile android.Path) android.Path { 108 javaFile := android.GenPathWithExt(ctx, "logtags", logtagsFile, "java") 109 110 ctx.Build(pctx, android.BuildParams{ 111 Rule: logtags, 112 Description: "logtags " + logtagsFile.Rel(), 113 Output: javaFile, 114 Input: logtagsFile, 115 }) 116 117 return javaFile 118} 119 120// genAidlIncludeFlags returns additional include flags based on the relative path 121// of each .aidl file passed in srcFiles. excludeDirs is a list of paths relative to 122// the Android checkout root that should not be included in the returned flags. 123func genAidlIncludeFlags(ctx android.PathContext, srcFiles android.Paths, excludeDirs android.Paths) string { 124 var baseDirs []string 125 excludeDirsStrings := excludeDirs.Strings() 126 for _, srcFile := range srcFiles { 127 if srcFile.Ext() == ".aidl" { 128 baseDir := strings.TrimSuffix(srcFile.String(), srcFile.Rel()) 129 baseDir = filepath.Clean(baseDir) 130 baseDirSeen := android.InList(baseDir, baseDirs) || android.InList(baseDir, excludeDirsStrings) 131 132 // For go/bp2build mixed builds, a file may be listed under a 133 // directory in the Bazel output tree that is symlinked to a 134 // directory under the android source tree. We should only 135 // include one copy of this directory so that the AIDL tool 136 // doesn't find multiple definitions of the same AIDL class. 137 // This code comes into effect when filegroups are used in mixed builds. 138 bazelPathPrefix := android.PathForBazelOut(ctx, "").String() 139 bazelBaseDir, err := filepath.Rel(bazelPathPrefix, baseDir) 140 bazelBaseDirSeen := err == nil && 141 android.InList(bazelBaseDir, baseDirs) || 142 android.InList(bazelBaseDir, excludeDirsStrings) 143 144 if baseDir != "" && !baseDirSeen && !bazelBaseDirSeen { 145 baseDirs = append(baseDirs, baseDir) 146 } 147 } 148 } 149 return android.JoinWithPrefix(baseDirs, " -I") 150} 151 152func (j *Module) genSources(ctx android.ModuleContext, srcFiles android.Paths, 153 flags javaBuilderFlags) android.Paths { 154 155 outSrcFiles := make(android.Paths, 0, len(srcFiles)) 156 var protoSrcs android.Paths 157 var aidlSrcs android.Paths 158 159 for _, srcFile := range srcFiles { 160 switch srcFile.Ext() { 161 case ".aidl": 162 aidlSrcs = append(aidlSrcs, srcFile) 163 case ".logtags": 164 j.logtagsSrcs = append(j.logtagsSrcs, srcFile) 165 javaFile := genLogtags(ctx, srcFile) 166 outSrcFiles = append(outSrcFiles, javaFile) 167 case ".proto": 168 protoSrcs = append(protoSrcs, srcFile) 169 default: 170 outSrcFiles = append(outSrcFiles, srcFile) 171 } 172 } 173 174 // Process all proto files together to support sharding them into one or more rules that produce srcjars. 175 if len(protoSrcs) > 0 { 176 srcJarFiles := genProto(ctx, protoSrcs, flags.proto) 177 outSrcFiles = append(outSrcFiles, srcJarFiles...) 178 } 179 180 // Process all aidl files together to support sharding them into one or more rules that produce srcjars. 181 if len(aidlSrcs) > 0 { 182 individualFlags := make(map[string]string) 183 for _, aidlSrc := range aidlSrcs { 184 flags := j.individualAidlFlags(ctx, aidlSrc) 185 if flags != "" { 186 individualFlags[aidlSrc.String()] = flags 187 } 188 } 189 srcJarFiles := genAidl(ctx, aidlSrcs, flags.aidlFlags, individualFlags, flags.aidlDeps) 190 outSrcFiles = append(outSrcFiles, srcJarFiles...) 191 } 192 193 return outSrcFiles 194} 195 196func LogtagsSingleton() android.Singleton { 197 return &logtagsSingleton{} 198} 199 200type logtagsProducer interface { 201 logtags() android.Paths 202} 203 204func (j *Module) logtags() android.Paths { 205 return j.logtagsSrcs 206} 207 208var _ logtagsProducer = (*Module)(nil) 209 210type logtagsSingleton struct{} 211 212func (l *logtagsSingleton) GenerateBuildActions(ctx android.SingletonContext) { 213 var allLogtags android.Paths 214 ctx.VisitAllModules(func(module android.Module) { 215 if logtags, ok := module.(logtagsProducer); ok { 216 allLogtags = append(allLogtags, logtags.logtags()...) 217 } 218 }) 219 220 ctx.Build(pctx, android.BuildParams{ 221 Rule: mergeLogtags, 222 Description: "merge logtags", 223 Output: android.PathForIntermediates(ctx, "all-event-log-tags.txt"), 224 Inputs: allLogtags, 225 }) 226} 227