// Copyright 2015 Google Inc. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package java import ( "path/filepath" "strconv" "strings" "github.com/google/blueprint" "github.com/google/blueprint/pathtools" "android/soong/android" ) func init() { pctx.SourcePathVariable("logtagsCmd", "build/make/tools/java-event-log-tags.py") pctx.SourcePathVariable("mergeLogtagsCmd", "build/make/tools/merge-event-log-tags.py") pctx.SourcePathVariable("logtagsLib", "build/make/tools/event_log_tags.py") } var ( logtags = pctx.AndroidStaticRule("logtags", blueprint.RuleParams{ Command: "$logtagsCmd -o $out $in", CommandDeps: []string{"$logtagsCmd", "$logtagsLib"}, }) mergeLogtags = pctx.AndroidStaticRule("mergeLogtags", blueprint.RuleParams{ Command: "$mergeLogtagsCmd -o $out $in", CommandDeps: []string{"$mergeLogtagsCmd", "$logtagsLib"}, }) ) func genAidl(ctx android.ModuleContext, aidlFiles android.Paths, aidlGlobalFlags string, aidlIndividualFlags map[string]string, deps android.Paths) android.Paths { // Shard aidl files into groups of 50 to avoid having to recompile all of them if one changes and to avoid // hitting command line length limits. shards := android.ShardPaths(aidlFiles, 50) srcJarFiles := make(android.Paths, 0, len(shards)) for i, shard := range shards { srcJarFile := android.PathForModuleGen(ctx, "aidl", "aidl"+strconv.Itoa(i)+".srcjar") srcJarFiles = append(srcJarFiles, srcJarFile) outDir := srcJarFile.ReplaceExtension(ctx, "tmp") rule := android.NewRuleBuilder(pctx, ctx) rule.Command().Text("rm -rf").Flag(outDir.String()) rule.Command().Text("mkdir -p").Flag(outDir.String()) rule.Command().Text("FLAGS=' " + aidlGlobalFlags + "'") for _, aidlFile := range shard { localFlag := aidlIndividualFlags[aidlFile.String()] depFile := srcJarFile.InSameDir(ctx, aidlFile.String()+".d") javaFile := outDir.Join(ctx, pathtools.ReplaceExtension(aidlFile.String(), "java")) rule.Command(). Tool(ctx.Config().HostToolPath(ctx, "aidl")). FlagWithDepFile("-d", depFile). Flag("$FLAGS"). Flag(localFlag). Input(aidlFile). Output(javaFile). Implicits(deps) rule.Temporary(javaFile) } rule.Command(). Tool(ctx.Config().HostToolPath(ctx, "soong_zip")). Flag("-srcjar"). Flag("-write_if_changed"). FlagWithOutput("-o ", srcJarFile). FlagWithArg("-C ", outDir.String()). FlagWithArg("-D ", outDir.String()) rule.Command().Text("rm -rf").Flag(outDir.String()) rule.Restat() ruleName := "aidl" ruleDesc := "aidl" if len(shards) > 1 { ruleName += "_" + strconv.Itoa(i) ruleDesc += " " + strconv.Itoa(i) } rule.Build(ruleName, ruleDesc) } return srcJarFiles } func genLogtags(ctx android.ModuleContext, logtagsFile android.Path) android.Path { javaFile := android.GenPathWithExt(ctx, "logtags", logtagsFile, "java") ctx.Build(pctx, android.BuildParams{ Rule: logtags, Description: "logtags " + logtagsFile.Rel(), Output: javaFile, Input: logtagsFile, }) return javaFile } // genAidlIncludeFlags returns additional include flags based on the relative path // of each .aidl file passed in srcFiles. excludeDirs is a list of paths relative to // the Android checkout root that should not be included in the returned flags. func genAidlIncludeFlags(ctx android.PathContext, srcFiles android.Paths, excludeDirs android.Paths) string { var baseDirs []string excludeDirsStrings := excludeDirs.Strings() for _, srcFile := range srcFiles { if srcFile.Ext() == ".aidl" { baseDir := strings.TrimSuffix(srcFile.String(), srcFile.Rel()) baseDir = filepath.Clean(baseDir) baseDirSeen := android.InList(baseDir, baseDirs) || android.InList(baseDir, excludeDirsStrings) // For go/bp2build mixed builds, a file may be listed under a // directory in the Bazel output tree that is symlinked to a // directory under the android source tree. We should only // include one copy of this directory so that the AIDL tool // doesn't find multiple definitions of the same AIDL class. // This code comes into effect when filegroups are used in mixed builds. bazelPathPrefix := android.PathForBazelOut(ctx, "").String() bazelBaseDir, err := filepath.Rel(bazelPathPrefix, baseDir) bazelBaseDirSeen := err == nil && android.InList(bazelBaseDir, baseDirs) || android.InList(bazelBaseDir, excludeDirsStrings) if baseDir != "" && !baseDirSeen && !bazelBaseDirSeen { baseDirs = append(baseDirs, baseDir) } } } return android.JoinWithPrefix(baseDirs, " -I") } func (j *Module) genSources(ctx android.ModuleContext, srcFiles android.Paths, flags javaBuilderFlags) android.Paths { outSrcFiles := make(android.Paths, 0, len(srcFiles)) var protoSrcs android.Paths var aidlSrcs android.Paths for _, srcFile := range srcFiles { switch srcFile.Ext() { case ".aidl": aidlSrcs = append(aidlSrcs, srcFile) case ".logtags": j.logtagsSrcs = append(j.logtagsSrcs, srcFile) javaFile := genLogtags(ctx, srcFile) outSrcFiles = append(outSrcFiles, javaFile) case ".proto": protoSrcs = append(protoSrcs, srcFile) default: outSrcFiles = append(outSrcFiles, srcFile) } } // Process all proto files together to support sharding them into one or more rules that produce srcjars. if len(protoSrcs) > 0 { srcJarFiles := genProto(ctx, protoSrcs, flags.proto) outSrcFiles = append(outSrcFiles, srcJarFiles...) } // Process all aidl files together to support sharding them into one or more rules that produce srcjars. if len(aidlSrcs) > 0 { individualFlags := make(map[string]string) for _, aidlSrc := range aidlSrcs { flags := j.individualAidlFlags(ctx, aidlSrc) if flags != "" { individualFlags[aidlSrc.String()] = flags } } srcJarFiles := genAidl(ctx, aidlSrcs, flags.aidlFlags, individualFlags, flags.aidlDeps) outSrcFiles = append(outSrcFiles, srcJarFiles...) } return outSrcFiles } func LogtagsSingleton() android.Singleton { return &logtagsSingleton{} } type logtagsProducer interface { logtags() android.Paths } func (j *Module) logtags() android.Paths { return j.logtagsSrcs } var _ logtagsProducer = (*Module)(nil) type logtagsSingleton struct{} func (l *logtagsSingleton) GenerateBuildActions(ctx android.SingletonContext) { var allLogtags android.Paths ctx.VisitAllModules(func(module android.Module) { if logtags, ok := module.(logtagsProducer); ok { allLogtags = append(allLogtags, logtags.logtags()...) } }) ctx.Build(pctx, android.BuildParams{ Rule: mergeLogtags, Description: "merge logtags", Output: android.PathForIntermediates(ctx, "all-event-log-tags.txt"), Inputs: allLogtags, }) }